0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/device.h>
0012 #include <linux/module.h>
0013 #include <linux/delay.h>
0014 #include <linux/cdev.h>
0015 #include <linux/slab.h>
0016 #include <linux/fs.h>
0017 #include <linux/io.h>
0018 #include <linux/uaccess.h>
0019
0020 #include <pcmcia/cistpl.h>
0021 #include <pcmcia/ds.h>
0022
0023 #define CCID_HEADER_SIZE 10
0024 #define CCID_LENGTH_OFFSET 1
0025 #define CCID_MAX_LEN 271
0026
0027 #define SCR24X_DATA(n) (1 + n)
0028 #define SCR24X_CMD_STATUS 7
0029 #define CMD_START 0x40
0030 #define CMD_WRITE_BYTE 0x41
0031 #define CMD_READ_BYTE 0x42
0032 #define STATUS_BUSY 0x80
0033
0034 struct scr24x_dev {
0035 struct device *dev;
0036 struct cdev c_dev;
0037 unsigned char buf[CCID_MAX_LEN];
0038 int devno;
0039 struct mutex lock;
0040 struct kref refcnt;
0041 u8 __iomem *regs;
0042 };
0043
0044 #define SCR24X_DEVS 8
0045 static DECLARE_BITMAP(scr24x_minors, SCR24X_DEVS);
0046
0047 static struct class *scr24x_class;
0048 static dev_t scr24x_devt;
0049
0050 static void scr24x_delete(struct kref *kref)
0051 {
0052 struct scr24x_dev *dev = container_of(kref, struct scr24x_dev,
0053 refcnt);
0054
0055 kfree(dev);
0056 }
0057
0058 static int scr24x_wait_ready(struct scr24x_dev *dev)
0059 {
0060 u_char status;
0061 int timeout = 100;
0062
0063 do {
0064 status = ioread8(dev->regs + SCR24X_CMD_STATUS);
0065 if (!(status & STATUS_BUSY))
0066 return 0;
0067
0068 msleep(20);
0069 } while (--timeout);
0070
0071 return -EIO;
0072 }
0073
0074 static int scr24x_open(struct inode *inode, struct file *filp)
0075 {
0076 struct scr24x_dev *dev = container_of(inode->i_cdev,
0077 struct scr24x_dev, c_dev);
0078
0079 kref_get(&dev->refcnt);
0080 filp->private_data = dev;
0081
0082 return stream_open(inode, filp);
0083 }
0084
0085 static int scr24x_release(struct inode *inode, struct file *filp)
0086 {
0087 struct scr24x_dev *dev = filp->private_data;
0088
0089
0090
0091
0092
0093
0094
0095 kref_put(&dev->refcnt, scr24x_delete);
0096 return 0;
0097 }
0098
0099 static int read_chunk(struct scr24x_dev *dev, size_t offset, size_t limit)
0100 {
0101 size_t i, y;
0102 int ret;
0103
0104 for (i = offset; i < limit; i += 5) {
0105 iowrite8(CMD_READ_BYTE, dev->regs + SCR24X_CMD_STATUS);
0106 ret = scr24x_wait_ready(dev);
0107 if (ret < 0)
0108 return ret;
0109
0110 for (y = 0; y < 5 && i + y < limit; y++)
0111 dev->buf[i + y] = ioread8(dev->regs + SCR24X_DATA(y));
0112 }
0113
0114 return 0;
0115 }
0116
0117 static ssize_t scr24x_read(struct file *filp, char __user *buf, size_t count,
0118 loff_t *ppos)
0119 {
0120 struct scr24x_dev *dev = filp->private_data;
0121 int ret;
0122 int len;
0123
0124 if (count < CCID_HEADER_SIZE)
0125 return -EINVAL;
0126
0127 if (mutex_lock_interruptible(&dev->lock))
0128 return -ERESTARTSYS;
0129
0130 if (!dev->dev) {
0131 ret = -ENODEV;
0132 goto out;
0133 }
0134
0135 ret = scr24x_wait_ready(dev);
0136 if (ret < 0)
0137 goto out;
0138 len = CCID_HEADER_SIZE;
0139 ret = read_chunk(dev, 0, len);
0140 if (ret < 0)
0141 goto out;
0142
0143 len += le32_to_cpu(*(__le32 *)(&dev->buf[CCID_LENGTH_OFFSET]));
0144 if (len > sizeof(dev->buf)) {
0145 ret = -EIO;
0146 goto out;
0147 }
0148 ret = read_chunk(dev, CCID_HEADER_SIZE, len);
0149 if (ret < 0)
0150 goto out;
0151
0152 if (len < count)
0153 count = len;
0154
0155 if (copy_to_user(buf, dev->buf, count)) {
0156 ret = -EFAULT;
0157 goto out;
0158 }
0159
0160 ret = count;
0161 out:
0162 mutex_unlock(&dev->lock);
0163 return ret;
0164 }
0165
0166 static ssize_t scr24x_write(struct file *filp, const char __user *buf,
0167 size_t count, loff_t *ppos)
0168 {
0169 struct scr24x_dev *dev = filp->private_data;
0170 size_t i, y;
0171 int ret;
0172
0173 if (mutex_lock_interruptible(&dev->lock))
0174 return -ERESTARTSYS;
0175
0176 if (!dev->dev) {
0177 ret = -ENODEV;
0178 goto out;
0179 }
0180
0181 if (count > sizeof(dev->buf)) {
0182 ret = -EINVAL;
0183 goto out;
0184 }
0185
0186 if (copy_from_user(dev->buf, buf, count)) {
0187 ret = -EFAULT;
0188 goto out;
0189 }
0190
0191 ret = scr24x_wait_ready(dev);
0192 if (ret < 0)
0193 goto out;
0194
0195 iowrite8(CMD_START, dev->regs + SCR24X_CMD_STATUS);
0196 ret = scr24x_wait_ready(dev);
0197 if (ret < 0)
0198 goto out;
0199
0200 for (i = 0; i < count; i += 5) {
0201 for (y = 0; y < 5 && i + y < count; y++)
0202 iowrite8(dev->buf[i + y], dev->regs + SCR24X_DATA(y));
0203
0204 iowrite8(CMD_WRITE_BYTE, dev->regs + SCR24X_CMD_STATUS);
0205 ret = scr24x_wait_ready(dev);
0206 if (ret < 0)
0207 goto out;
0208 }
0209
0210 ret = count;
0211 out:
0212 mutex_unlock(&dev->lock);
0213 return ret;
0214 }
0215
0216 static const struct file_operations scr24x_fops = {
0217 .owner = THIS_MODULE,
0218 .read = scr24x_read,
0219 .write = scr24x_write,
0220 .open = scr24x_open,
0221 .release = scr24x_release,
0222 .llseek = no_llseek,
0223 };
0224
0225 static int scr24x_config_check(struct pcmcia_device *link, void *priv_data)
0226 {
0227 if (resource_size(link->resource[PCMCIA_IOPORT_0]) != 0x11)
0228 return -ENODEV;
0229 return pcmcia_request_io(link);
0230 }
0231
0232 static int scr24x_probe(struct pcmcia_device *link)
0233 {
0234 struct scr24x_dev *dev;
0235 int ret;
0236
0237 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
0238 if (!dev)
0239 return -ENOMEM;
0240
0241 dev->devno = find_first_zero_bit(scr24x_minors, SCR24X_DEVS);
0242 if (dev->devno >= SCR24X_DEVS) {
0243 ret = -EBUSY;
0244 goto err;
0245 }
0246
0247 mutex_init(&dev->lock);
0248 kref_init(&dev->refcnt);
0249
0250 link->priv = dev;
0251 link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
0252
0253 ret = pcmcia_loop_config(link, scr24x_config_check, NULL);
0254 if (ret < 0)
0255 goto err;
0256
0257 dev->dev = &link->dev;
0258 dev->regs = devm_ioport_map(&link->dev,
0259 link->resource[PCMCIA_IOPORT_0]->start,
0260 resource_size(link->resource[PCMCIA_IOPORT_0]));
0261 if (!dev->regs) {
0262 ret = -EIO;
0263 goto err;
0264 }
0265
0266 cdev_init(&dev->c_dev, &scr24x_fops);
0267 dev->c_dev.owner = THIS_MODULE;
0268 ret = cdev_add(&dev->c_dev, MKDEV(MAJOR(scr24x_devt), dev->devno), 1);
0269 if (ret < 0)
0270 goto err;
0271
0272 ret = pcmcia_enable_device(link);
0273 if (ret < 0) {
0274 pcmcia_disable_device(link);
0275 goto err;
0276 }
0277
0278 device_create(scr24x_class, NULL, MKDEV(MAJOR(scr24x_devt), dev->devno),
0279 NULL, "scr24x%d", dev->devno);
0280
0281 dev_info(&link->dev, "SCR24x Chip Card Interface\n");
0282 return 0;
0283
0284 err:
0285 if (dev->devno < SCR24X_DEVS)
0286 clear_bit(dev->devno, scr24x_minors);
0287 kfree (dev);
0288 return ret;
0289 }
0290
0291 static void scr24x_remove(struct pcmcia_device *link)
0292 {
0293 struct scr24x_dev *dev = (struct scr24x_dev *)link->priv;
0294
0295 device_destroy(scr24x_class, MKDEV(MAJOR(scr24x_devt), dev->devno));
0296 mutex_lock(&dev->lock);
0297 pcmcia_disable_device(link);
0298 cdev_del(&dev->c_dev);
0299 clear_bit(dev->devno, scr24x_minors);
0300 dev->dev = NULL;
0301 mutex_unlock(&dev->lock);
0302
0303 kref_put(&dev->refcnt, scr24x_delete);
0304 }
0305
0306 static const struct pcmcia_device_id scr24x_ids[] = {
0307 PCMCIA_DEVICE_PROD_ID12("HP", "PC Card Smart Card Reader",
0308 0x53cb94f9, 0xbfdf89a5),
0309 PCMCIA_DEVICE_PROD_ID1("SCR241 PCMCIA", 0x6271efa3),
0310 PCMCIA_DEVICE_PROD_ID1("SCR243 PCMCIA", 0x2054e8de),
0311 PCMCIA_DEVICE_PROD_ID1("SCR24x PCMCIA", 0x54a33665),
0312 PCMCIA_DEVICE_NULL
0313 };
0314 MODULE_DEVICE_TABLE(pcmcia, scr24x_ids);
0315
0316 static struct pcmcia_driver scr24x_driver = {
0317 .owner = THIS_MODULE,
0318 .name = "scr24x_cs",
0319 .probe = scr24x_probe,
0320 .remove = scr24x_remove,
0321 .id_table = scr24x_ids,
0322 };
0323
0324 static int __init scr24x_init(void)
0325 {
0326 int ret;
0327
0328 scr24x_class = class_create(THIS_MODULE, "scr24x");
0329 if (IS_ERR(scr24x_class))
0330 return PTR_ERR(scr24x_class);
0331
0332 ret = alloc_chrdev_region(&scr24x_devt, 0, SCR24X_DEVS, "scr24x");
0333 if (ret < 0) {
0334 class_destroy(scr24x_class);
0335 return ret;
0336 }
0337
0338 ret = pcmcia_register_driver(&scr24x_driver);
0339 if (ret < 0) {
0340 unregister_chrdev_region(scr24x_devt, SCR24X_DEVS);
0341 class_destroy(scr24x_class);
0342 }
0343
0344 return ret;
0345 }
0346
0347 static void __exit scr24x_exit(void)
0348 {
0349 pcmcia_unregister_driver(&scr24x_driver);
0350 unregister_chrdev_region(scr24x_devt, SCR24X_DEVS);
0351 class_destroy(scr24x_class);
0352 }
0353
0354 module_init(scr24x_init);
0355 module_exit(scr24x_exit);
0356
0357 MODULE_AUTHOR("Lubomir Rintel");
0358 MODULE_DESCRIPTION("SCR24x PCMCIA Smart Card Reader Driver");
0359 MODULE_LICENSE("GPL");