diff options
Diffstat (limited to 'drivers/char/pcmcia/cm4000_cs.c')
| -rw-r--r-- | drivers/char/pcmcia/cm4000_cs.c | 208 |
1 files changed, 69 insertions, 139 deletions
diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c index f070ae7bd91..c115217c79a 100644 --- a/drivers/char/pcmcia/cm4000_cs.c +++ b/drivers/char/pcmcia/cm4000_cs.c @@ -23,8 +23,6 @@ * All rights reserved. Licensed under dual BSD/GPL license. */ -/* #define PCMCIA_DEBUG 6 */ - #include <linux/kernel.h> #include <linux/module.h> #include <linux/slab.h> @@ -32,12 +30,10 @@ #include <linux/fs.h> #include <linux/delay.h> #include <linux/bitrev.h> -#include <linux/smp_lock.h> +#include <linux/mutex.h> #include <linux/uaccess.h> #include <linux/io.h> -#include <pcmcia/cs_types.h> -#include <pcmcia/cs.h> #include <pcmcia/cistpl.h> #include <pcmcia/cisreg.h> #include <pcmcia/ciscode.h> @@ -47,19 +43,18 @@ /* #define ATR_CSUM */ -#ifdef PCMCIA_DEBUG -#define reader_to_dev(x) (&handle_to_dev(x->p_dev)) -static int pc_debug = PCMCIA_DEBUG; -module_param(pc_debug, int, 0600); -#define DEBUGP(n, rdr, x, args...) do { \ - if (pc_debug >= (n)) \ - dev_printk(KERN_DEBUG, reader_to_dev(rdr), "%s:" x, \ - __func__ , ## args); \ +#define reader_to_dev(x) (&x->p_dev->dev) + +/* n (debug level) is ignored */ +/* additional debug output may be enabled by re-compiling with + * CM4000_DEBUG set */ +/* #define CM4000_DEBUG */ +#define DEBUGP(n, rdr, x, args...) do { \ + dev_dbg(reader_to_dev(rdr), "%s:" x, \ + __func__ , ## args); \ } while (0) -#else -#define DEBUGP(n, rdr, x, args...) -#endif -static char *version = "cm4000_cs.c v2.4.0gm6 - All bugs added by Harald Welte"; + +static DEFINE_MUTEX(cmm_mutex); #define T_1SEC (HZ) #define T_10MSEC msecs_to_jiffies(10) @@ -109,7 +104,6 @@ static int major; /* major number we get from the kernel */ struct cm4000_dev { struct pcmcia_device *p_dev; - dev_node_t node; /* OS node (major,minor) */ unsigned char atr[MAX_ATR]; unsigned char rbuf[512]; @@ -174,14 +168,13 @@ static unsigned char fi_di_table[10][14] = { /* 9 */ {0x09,0x19,0x29,0x39,0x49,0x59,0x69,0x11,0x11,0x99,0xA9,0xB9,0xC9,0xD9} }; -#ifndef PCMCIA_DEBUG +#ifndef CM4000_DEBUG #define xoutb outb #define xinb inb #else static inline void xoutb(unsigned char val, unsigned short port) { - if (pc_debug >= 7) - printk(KERN_DEBUG "outb(val=%.2x,port=%.4x)\n", val, port); + pr_debug("outb(val=%.2x,port=%.4x)\n", val, port); outb(val, port); } static inline unsigned char xinb(unsigned short port) @@ -189,8 +182,7 @@ static inline unsigned char xinb(unsigned short port) unsigned char val; val = inb(port); - if (pc_debug >= 7) - printk(KERN_DEBUG "%.2x=inb(%.4x)\n", val, port); + pr_debug("%.2x=inb(%.4x)\n", val, port); return val; } @@ -428,7 +420,7 @@ static struct card_fixup card_fixups[] = { static void set_cardparameter(struct cm4000_dev *dev) { int i; - unsigned int iobase = dev->p_dev->io.BasePort1; + unsigned int iobase = dev->p_dev->resource[0]->start; u_int8_t stopbits = 0x02; /* ISO default */ DEBUGP(3, dev, "-> set_cardparameter\n"); @@ -461,7 +453,7 @@ static int set_protocol(struct cm4000_dev *dev, struct ptsreq *ptsreq) unsigned short num_bytes_read; unsigned char pts_reply[4]; ssize_t rc; - unsigned int iobase = dev->p_dev->io.BasePort1; + unsigned int iobase = dev->p_dev->resource[0]->start; rc = 0; @@ -514,12 +506,10 @@ static int set_protocol(struct cm4000_dev *dev, struct ptsreq *ptsreq) for (i = 0; i < 4; i++) { xoutb(i, REG_BUF_ADDR(iobase)); xoutb(dev->pts[i], REG_BUF_DATA(iobase)); /* buf data */ -#ifdef PCMCIA_DEBUG - if (pc_debug >= 5) - printk("0x%.2x ", dev->pts[i]); +#ifdef CM4000_DEBUG + pr_debug("0x%.2x ", dev->pts[i]); } - if (pc_debug >= 5) - printk("\n"); + pr_debug("\n"); #else } #endif @@ -579,14 +569,13 @@ static int set_protocol(struct cm4000_dev *dev, struct ptsreq *ptsreq) pts_reply[i] = inb(REG_BUF_DATA(iobase)); } -#ifdef PCMCIA_DEBUG +#ifdef CM4000_DEBUG DEBUGP(2, dev, "PTSreply: "); for (i = 0; i < num_bytes_read; i++) { - if (pc_debug >= 5) - printk("0x%.2x ", pts_reply[i]); + pr_debug("0x%.2x ", pts_reply[i]); } - printk("\n"); -#endif /* PCMCIA_DEBUG */ + pr_debug("\n"); +#endif /* CM4000_DEBUG */ DEBUGP(5, dev, "Clear Tactive in Flags1\n"); xoutb(0x20, REG_FLAGS1(iobase)); @@ -655,7 +644,7 @@ static void terminate_monitor(struct cm4000_dev *dev) DEBUGP(5, dev, "Delete timer\n"); del_timer_sync(&dev->timer); -#ifdef PCMCIA_DEBUG +#ifdef CM4000_DEBUG dev->monitor_running = 0; #endif @@ -673,7 +662,7 @@ static void terminate_monitor(struct cm4000_dev *dev) static void monitor_card(unsigned long p) { struct cm4000_dev *dev = (struct cm4000_dev *) p; - unsigned int iobase = dev->p_dev->io.BasePort1; + unsigned int iobase = dev->p_dev->resource[0]->start; unsigned short s; struct ptsreq ptsreq; int i, atrc; @@ -817,7 +806,7 @@ static void monitor_card(unsigned long p) dev->flags1 = 0x01; xoutb(dev->flags1, REG_FLAGS1(iobase)); - /* atr is present (which doesnt mean it's valid) */ + /* atr is present (which doesn't mean it's valid) */ set_bit(IS_ATR_PRESENT, &dev->flags); if (dev->atr[0] == 0x03) str_invert_revert(dev->atr, dev->atr_len); @@ -841,8 +830,7 @@ static void monitor_card(unsigned long p) test_bit(IS_ANY_T1, &dev->flags))) { DEBUGP(4, dev, "Perform AUTOPPS\n"); set_bit(IS_AUTOPPS_ACT, &dev->flags); - ptsreq.protocol = ptsreq.protocol = - (0x01 << dev->proto); + ptsreq.protocol = (0x01 << dev->proto); ptsreq.flags = 0x01; ptsreq.pts1 = 0x00; ptsreq.pts2 = 0x00; @@ -892,13 +880,12 @@ static void monitor_card(unsigned long p) /* slow down warning, but prompt immediately after insertion */ if (dev->cwarn == 0 || dev->cwarn == 10) { set_bit(IS_BAD_CARD, &dev->flags); - printk(KERN_WARNING MODULE_NAME ": device %s: ", - dev->node.dev_name); + dev_warn(&dev->p_dev->dev, MODULE_NAME ": "); if (test_bit(IS_BAD_CSUM, &dev->flags)) { DEBUGP(4, dev, "ATR checksum (0x%.2x, should " "be zero) failed\n", dev->atr_csum); } -#ifdef PCMCIA_DEBUG +#ifdef CM4000_DEBUG else if (test_bit(IS_BAD_LENGTH, &dev->flags)) { DEBUGP(4, dev, "ATR length error\n"); } else { @@ -935,7 +922,7 @@ static ssize_t cmm_read(struct file *filp, __user char *buf, size_t count, loff_t *ppos) { struct cm4000_dev *dev = filp->private_data; - unsigned int iobase = dev->p_dev->io.BasePort1; + unsigned int iobase = dev->p_dev->resource[0]->start; ssize_t rc; int i, j, k; @@ -991,8 +978,9 @@ static ssize_t cmm_read(struct file *filp, __user char *buf, size_t count, if (dev->flags0 & 1) { set_bit(IS_CMM_ABSENT, &dev->flags); rc = -ENODEV; + } else { + rc = -EIO; } - rc = -EIO; goto release_io; } @@ -1017,7 +1005,7 @@ static ssize_t cmm_read(struct file *filp, __user char *buf, size_t count, } } - if (dev->proto == 0 && count > dev->rlen - dev->rpos) { + if (dev->proto == 0 && count > dev->rlen - dev->rpos && i) { DEBUGP(4, dev, "T=0 and count > buffer\n"); dev->rbuf[i] = dev->rbuf[i - 1]; dev->rbuf[i - 1] = dev->procbyte; @@ -1034,14 +1022,16 @@ static ssize_t cmm_read(struct file *filp, __user char *buf, size_t count, xoutb(0, REG_FLAGS1(iobase)); /* clear detectCMM */ /* last check before exit */ - if (!io_detect_cm4000(iobase, dev)) - count = -ENODEV; + if (!io_detect_cm4000(iobase, dev)) { + rc = -ENODEV; + goto release_io; + } if (test_bit(IS_INVREV, &dev->flags) && count > 0) str_invert_revert(dev->rbuf, count); if (copy_to_user(buf, dev->rbuf, count)) - return -EFAULT; + rc = -EFAULT; release_io: clear_bit(LOCK_IO, &dev->flags); @@ -1055,8 +1045,8 @@ release_io: static ssize_t cmm_write(struct file *filp, const char __user *buf, size_t count, loff_t *ppos) { - struct cm4000_dev *dev = (struct cm4000_dev *) filp->private_data; - unsigned int iobase = dev->p_dev->io.BasePort1; + struct cm4000_dev *dev = filp->private_data; + unsigned int iobase = dev->p_dev->resource[0]->start; unsigned short s; unsigned char tmp; unsigned char infolen; @@ -1409,13 +1399,13 @@ static void stop_monitor(struct cm4000_dev *dev) static long cmm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { struct cm4000_dev *dev = filp->private_data; - unsigned int iobase = dev->p_dev->io.BasePort1; - struct inode *inode = filp->f_path.dentry->d_inode; + unsigned int iobase = dev->p_dev->resource[0]->start; + struct inode *inode = file_inode(filp); struct pcmcia_device *link; int size; int rc; void __user *argp = (void __user *)arg; -#ifdef PCMCIA_DEBUG +#ifdef CM4000_DEBUG char *ioctl_names[CM_IOC_MAXNR + 1] = { [_IOC_NR(CM_IOCGSTATUS)] "CM_IOCGSTATUS", [_IOC_NR(CM_IOCGATR)] "CM_IOCGATR", @@ -1423,11 +1413,11 @@ static long cmm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) [_IOC_NR(CM_IOCSPTS)] "CM_IOCSPTS", [_IOC_NR(CM_IOSDBGLVL)] "CM4000_DBGLVL", }; -#endif DEBUGP(3, dev, "cmm_ioctl(device=%d.%d) %s\n", imajor(inode), iminor(inode), ioctl_names[_IOC_NR(cmd)]); +#endif - lock_kernel(); + mutex_lock(&cmm_mutex); rc = -ENODEV; link = dev_table[iminor(inode)]; if (!pcmcia_dev_present(link)) { @@ -1523,7 +1513,7 @@ static long cmm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) } case CM_IOCARDOFF: -#ifdef PCMCIA_DEBUG +#ifdef CM4000_DEBUG DEBUGP(4, dev, "... in CM_IOCARDOFF\n"); if (dev->flags0 & 0x01) { DEBUGP(4, dev, " Card inserted\n"); @@ -1575,7 +1565,8 @@ static long cmm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) clear_bit(LOCK_IO, &dev->flags); wake_up_interruptible(&dev->ioq); - return 0; + rc = 0; + break; case CM_IOCSPTS: { struct ptsreq krnptsreq; @@ -1624,18 +1615,9 @@ static long cmm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) } break; -#ifdef PCMCIA_DEBUG - case CM_IOSDBGLVL: /* set debug log level */ - { - int old_pc_debug = 0; - - old_pc_debug = pc_debug; - if (copy_from_user(&pc_debug, argp, sizeof(int))) - rc = -EFAULT; - else if (old_pc_debug != pc_debug) - DEBUGP(0, dev, "Changed debug log level " - "to %i\n", pc_debug); - } +#ifdef CM4000_DEBUG + case CM_IOSDBGLVL: + rc = -ENOTTY; break; #endif default: @@ -1643,7 +1625,7 @@ static long cmm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) rc = -ENOTTY; } out: - unlock_kernel(); + mutex_unlock(&cmm_mutex); return rc; } @@ -1657,7 +1639,7 @@ static int cmm_open(struct inode *inode, struct file *filp) if (minor >= CM4000_MAX_DEV) return -ENODEV; - lock_kernel(); + mutex_lock(&cmm_mutex); link = dev_table[minor]; if (link == NULL || !pcmcia_dev_present(link)) { ret = -ENODEV; @@ -1684,7 +1666,7 @@ static int cmm_open(struct inode *inode, struct file *filp) /* opening will always block since the * monitor will be started by open, which * means we have to wait for ATR becoming - * vaild = block until valid (or card + * valid = block until valid (or card * inserted) */ if (filp->f_flags & O_NONBLOCK) { @@ -1702,7 +1684,7 @@ static int cmm_open(struct inode *inode, struct file *filp) DEBUGP(2, dev, "<- cmm_open\n"); ret = nonseekable_open(inode, filp); out: - unlock_kernel(); + mutex_unlock(&cmm_mutex); return ret; } @@ -1759,72 +1741,25 @@ static void cmm_cm4000_release(struct pcmcia_device * link) /*==== Interface to PCMCIA Layer =======================================*/ +static int cm4000_config_check(struct pcmcia_device *p_dev, void *priv_data) +{ + return pcmcia_request_io(p_dev); +} + static int cm4000_config(struct pcmcia_device * link, int devno) { struct cm4000_dev *dev; - tuple_t tuple; - cisparse_t parse; - u_char buf[64]; - int fail_fn, fail_rc; - int rc; + + link->config_flags |= CONF_AUTO_SET_IO; /* read the config-tuples */ - tuple.Attributes = 0; - tuple.TupleData = buf; - tuple.TupleDataMax = sizeof(buf); - tuple.TupleOffset = 0; - - link->io.BasePort2 = 0; - link->io.NumPorts2 = 0; - link->io.Attributes2 = 0; - tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - for (rc = pcmcia_get_first_tuple(link, &tuple); - rc == CS_SUCCESS; rc = pcmcia_get_next_tuple(link, &tuple)) { - - rc = pcmcia_get_tuple_data(link, &tuple); - if (rc != CS_SUCCESS) - continue; - rc = pcmcia_parse_tuple(link, &tuple, &parse); - if (rc != CS_SUCCESS) - continue; - - link->conf.ConfigIndex = parse.cftable_entry.index; - - if (!parse.cftable_entry.io.nwin) - continue; - - /* Get the IOaddr */ - link->io.BasePort1 = parse.cftable_entry.io.win[0].base; - link->io.NumPorts1 = parse.cftable_entry.io.win[0].len; - link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - if (!(parse.cftable_entry.io.flags & CISTPL_IO_8BIT)) - link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; - if (!(parse.cftable_entry.io.flags & CISTPL_IO_16BIT)) - link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - link->io.IOAddrLines = parse.cftable_entry.io.flags - & CISTPL_IO_LINES_MASK; - - rc = pcmcia_request_io(link, &link->io); - if (rc == CS_SUCCESS) - break; /* we are done */ - } - if (rc != CS_SUCCESS) + if (pcmcia_loop_config(link, cm4000_config_check, NULL)) goto cs_release; - link->conf.IntType = 00000002; - - if ((fail_rc = - pcmcia_request_configuration(link, &link->conf)) != CS_SUCCESS) { - fail_fn = RequestConfiguration; + if (pcmcia_enable_device(link)) goto cs_release; - } dev = link->priv; - sprintf(dev->node.dev_name, DEVICE_NAME "%d", devno); - dev->node.major = major; - dev->node.minor = devno; - dev->node.next = NULL; - link->dev_node = &dev->node; return 0; @@ -1881,7 +1816,6 @@ static int cm4000_probe(struct pcmcia_device *link) dev->p_dev = link; link->priv = dev; - link->conf.IntType = INT_MEMORY_AND_IO; dev_table[i] = link; init_waitqueue_head(&dev->devq); @@ -1896,7 +1830,7 @@ static int cm4000_probe(struct pcmcia_device *link) return ret; } - device_create_drvdata(cmm_class, NULL, MKDEV(major, i), NULL, "cmm%d", i); + device_create(cmm_class, NULL, MKDEV(major, i), NULL, "cmm%d", i); return 0; } @@ -1932,9 +1866,10 @@ static const struct file_operations cm4000_fops = { .unlocked_ioctl = cmm_ioctl, .open = cmm_open, .release= cmm_close, + .llseek = no_llseek, }; -static struct pcmcia_device_id cm4000_ids[] = { +static const struct pcmcia_device_id cm4000_ids[] = { PCMCIA_DEVICE_MANF_CARD(0x0223, 0x0002), PCMCIA_DEVICE_PROD_ID12("CardMan", "4000", 0x2FB368CA, 0xA2BD8C39), PCMCIA_DEVICE_NULL, @@ -1943,9 +1878,7 @@ MODULE_DEVICE_TABLE(pcmcia, cm4000_ids); static struct pcmcia_driver cm4000_driver = { .owner = THIS_MODULE, - .drv = { - .name = "cm4000_cs", - }, + .name = "cm4000_cs", .probe = cm4000_probe, .remove = cm4000_detach, .suspend = cm4000_suspend, @@ -1957,8 +1890,6 @@ static int __init cmm_init(void) { int rc; - printk(KERN_INFO "%s\n", version); - cmm_class = class_create(THIS_MODULE, "cardman_4000"); if (IS_ERR(cmm_class)) return PTR_ERR(cmm_class); @@ -1983,7 +1914,6 @@ static int __init cmm_init(void) static void __exit cmm_exit(void) { - printk(KERN_INFO MODULE_NAME ": unloading\n"); pcmcia_unregister_driver(&cm4000_driver); unregister_chrdev(major, DEVICE_NAME); class_destroy(cmm_class); |
