diff options
Diffstat (limited to 'drivers/char/pcmcia/cm4000_cs.c')
-rw-r--r-- | drivers/char/pcmcia/cm4000_cs.c | 175 |
1 files changed, 58 insertions, 117 deletions
diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c index ef011ef5dc46..649677b5dc36 100644 --- a/drivers/char/pcmcia/cm4000_cs.c +++ b/drivers/char/pcmcia/cm4000_cs.c | |||
@@ -66,7 +66,6 @@ static char *version = "cm4000_cs.c v2.4.0gm5 - All bugs added by Harald Welte"; | |||
66 | #define T_100MSEC msecs_to_jiffies(100) | 66 | #define T_100MSEC msecs_to_jiffies(100) |
67 | #define T_500MSEC msecs_to_jiffies(500) | 67 | #define T_500MSEC msecs_to_jiffies(500) |
68 | 68 | ||
69 | static void cm4000_detach(dev_link_t *link); | ||
70 | static void cm4000_release(dev_link_t *link); | 69 | static void cm4000_release(dev_link_t *link); |
71 | 70 | ||
72 | static int major; /* major number we get from the kernel */ | 71 | static int major; /* major number we get from the kernel */ |
@@ -156,7 +155,6 @@ struct cm4000_dev { | |||
156 | /*sbuf*/ 512*sizeof(char) - \ | 155 | /*sbuf*/ 512*sizeof(char) - \ |
157 | /*queue*/ 4*sizeof(wait_queue_head_t)) | 156 | /*queue*/ 4*sizeof(wait_queue_head_t)) |
158 | 157 | ||
159 | static dev_info_t dev_info = MODULE_NAME; | ||
160 | static dev_link_t *dev_table[CM4000_MAX_DEV]; | 158 | static dev_link_t *dev_table[CM4000_MAX_DEV]; |
161 | 159 | ||
162 | /* This table doesn't use spaces after the comma between fields and thus | 160 | /* This table doesn't use spaces after the comma between fields and thus |
@@ -1444,6 +1442,7 @@ static int cmm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, | |||
1444 | dev_link_t *link; | 1442 | dev_link_t *link; |
1445 | int size; | 1443 | int size; |
1446 | int rc; | 1444 | int rc; |
1445 | void __user *argp = (void __user *)arg; | ||
1447 | #ifdef PCMCIA_DEBUG | 1446 | #ifdef PCMCIA_DEBUG |
1448 | char *ioctl_names[CM_IOC_MAXNR + 1] = { | 1447 | char *ioctl_names[CM_IOC_MAXNR + 1] = { |
1449 | [_IOC_NR(CM_IOCGSTATUS)] "CM_IOCGSTATUS", | 1448 | [_IOC_NR(CM_IOCGSTATUS)] "CM_IOCGSTATUS", |
@@ -1481,11 +1480,11 @@ static int cmm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, | |||
1481 | _IOC_DIR(cmd), _IOC_READ, _IOC_WRITE, size, cmd); | 1480 | _IOC_DIR(cmd), _IOC_READ, _IOC_WRITE, size, cmd); |
1482 | 1481 | ||
1483 | if (_IOC_DIR(cmd) & _IOC_READ) { | 1482 | if (_IOC_DIR(cmd) & _IOC_READ) { |
1484 | if (!access_ok(VERIFY_WRITE, (void *)arg, size)) | 1483 | if (!access_ok(VERIFY_WRITE, argp, size)) |
1485 | return -EFAULT; | 1484 | return -EFAULT; |
1486 | } | 1485 | } |
1487 | if (_IOC_DIR(cmd) & _IOC_WRITE) { | 1486 | if (_IOC_DIR(cmd) & _IOC_WRITE) { |
1488 | if (!access_ok(VERIFY_READ, (void *)arg, size)) | 1487 | if (!access_ok(VERIFY_READ, argp, size)) |
1489 | return -EFAULT; | 1488 | return -EFAULT; |
1490 | } | 1489 | } |
1491 | 1490 | ||
@@ -1506,14 +1505,14 @@ static int cmm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, | |||
1506 | status |= CM_NO_READER; | 1505 | status |= CM_NO_READER; |
1507 | if (test_bit(IS_BAD_CARD, &dev->flags)) | 1506 | if (test_bit(IS_BAD_CARD, &dev->flags)) |
1508 | status |= CM_BAD_CARD; | 1507 | status |= CM_BAD_CARD; |
1509 | if (copy_to_user((int *)arg, &status, sizeof(int))) | 1508 | if (copy_to_user(argp, &status, sizeof(int))) |
1510 | return -EFAULT; | 1509 | return -EFAULT; |
1511 | } | 1510 | } |
1512 | return 0; | 1511 | return 0; |
1513 | case CM_IOCGATR: | 1512 | case CM_IOCGATR: |
1514 | DEBUGP(4, dev, "... in CM_IOCGATR\n"); | 1513 | DEBUGP(4, dev, "... in CM_IOCGATR\n"); |
1515 | { | 1514 | { |
1516 | struct atreq *atreq = (struct atreq *) arg; | 1515 | struct atreq __user *atreq = argp; |
1517 | int tmp; | 1516 | int tmp; |
1518 | /* allow nonblocking io and being interrupted */ | 1517 | /* allow nonblocking io and being interrupted */ |
1519 | if (wait_event_interruptible | 1518 | if (wait_event_interruptible |
@@ -1597,7 +1596,7 @@ static int cmm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, | |||
1597 | { | 1596 | { |
1598 | struct ptsreq krnptsreq; | 1597 | struct ptsreq krnptsreq; |
1599 | 1598 | ||
1600 | if (copy_from_user(&krnptsreq, (struct ptsreq *) arg, | 1599 | if (copy_from_user(&krnptsreq, argp, |
1601 | sizeof(struct ptsreq))) | 1600 | sizeof(struct ptsreq))) |
1602 | return -EFAULT; | 1601 | return -EFAULT; |
1603 | 1602 | ||
@@ -1641,7 +1640,7 @@ static int cmm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, | |||
1641 | int old_pc_debug = 0; | 1640 | int old_pc_debug = 0; |
1642 | 1641 | ||
1643 | old_pc_debug = pc_debug; | 1642 | old_pc_debug = pc_debug; |
1644 | if (copy_from_user(&pc_debug, (int *)arg, sizeof(int))) | 1643 | if (copy_from_user(&pc_debug, argp, sizeof(int))) |
1645 | return -EFAULT; | 1644 | return -EFAULT; |
1646 | 1645 | ||
1647 | if (old_pc_debug != pc_debug) | 1646 | if (old_pc_debug != pc_debug) |
@@ -1863,68 +1862,36 @@ cs_release: | |||
1863 | link->state &= ~DEV_CONFIG_PENDING; | 1862 | link->state &= ~DEV_CONFIG_PENDING; |
1864 | } | 1863 | } |
1865 | 1864 | ||
1866 | static int cm4000_event(event_t event, int priority, | 1865 | static int cm4000_suspend(struct pcmcia_device *p_dev) |
1867 | event_callback_args_t *args) | ||
1868 | { | 1866 | { |
1869 | dev_link_t *link; | 1867 | dev_link_t *link = dev_to_instance(p_dev); |
1870 | struct cm4000_dev *dev; | 1868 | struct cm4000_dev *dev; |
1871 | int devno; | ||
1872 | 1869 | ||
1873 | link = args->client_data; | ||
1874 | dev = link->priv; | 1870 | dev = link->priv; |
1875 | 1871 | ||
1876 | DEBUGP(3, dev, "-> cm4000_event\n"); | 1872 | link->state |= DEV_SUSPEND; |
1877 | for (devno = 0; devno < CM4000_MAX_DEV; devno++) | 1873 | if (link->state & DEV_CONFIG) |
1878 | if (dev_table[devno] == link) | 1874 | pcmcia_release_configuration(link->handle); |
1879 | break; | 1875 | stop_monitor(dev); |
1880 | 1876 | ||
1881 | if (devno == CM4000_MAX_DEV) | 1877 | return 0; |
1882 | return CS_BAD_ADAPTER; | 1878 | } |
1883 | 1879 | ||
1884 | switch (event) { | 1880 | static int cm4000_resume(struct pcmcia_device *p_dev) |
1885 | case CS_EVENT_CARD_INSERTION: | 1881 | { |
1886 | DEBUGP(5, dev, "CS_EVENT_CARD_INSERTION\n"); | 1882 | dev_link_t *link = dev_to_instance(p_dev); |
1887 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | 1883 | struct cm4000_dev *dev; |
1888 | cm4000_config(link, devno); | 1884 | |
1889 | break; | 1885 | dev = link->priv; |
1890 | case CS_EVENT_CARD_REMOVAL: | 1886 | |
1891 | DEBUGP(5, dev, "CS_EVENT_CARD_REMOVAL\n"); | 1887 | link->state &= ~DEV_SUSPEND; |
1892 | link->state &= ~DEV_PRESENT; | 1888 | if (link->state & DEV_CONFIG) |
1893 | stop_monitor(dev); | 1889 | pcmcia_request_configuration(link->handle, &link->conf); |
1894 | break; | 1890 | |
1895 | case CS_EVENT_PM_SUSPEND: | 1891 | if (link->open) |
1896 | DEBUGP(5, dev, "CS_EVENT_PM_SUSPEND " | 1892 | start_monitor(dev); |
1897 | "(fall-through to CS_EVENT_RESET_PHYSICAL)\n"); | 1893 | |
1898 | link->state |= DEV_SUSPEND; | 1894 | return 0; |
1899 | /* fall-through */ | ||
1900 | case CS_EVENT_RESET_PHYSICAL: | ||
1901 | DEBUGP(5, dev, "CS_EVENT_RESET_PHYSICAL\n"); | ||
1902 | if (link->state & DEV_CONFIG) { | ||
1903 | DEBUGP(5, dev, "ReleaseConfiguration\n"); | ||
1904 | pcmcia_release_configuration(link->handle); | ||
1905 | } | ||
1906 | stop_monitor(dev); | ||
1907 | break; | ||
1908 | case CS_EVENT_PM_RESUME: | ||
1909 | DEBUGP(5, dev, "CS_EVENT_PM_RESUME " | ||
1910 | "(fall-through to CS_EVENT_CARD_RESET)\n"); | ||
1911 | link->state &= ~DEV_SUSPEND; | ||
1912 | /* fall-through */ | ||
1913 | case CS_EVENT_CARD_RESET: | ||
1914 | DEBUGP(5, dev, "CS_EVENT_CARD_RESET\n"); | ||
1915 | if ((link->state & DEV_CONFIG)) { | ||
1916 | DEBUGP(5, dev, "RequestConfiguration\n"); | ||
1917 | pcmcia_request_configuration(link->handle, &link->conf); | ||
1918 | } | ||
1919 | if (link->open) | ||
1920 | start_monitor(dev); | ||
1921 | break; | ||
1922 | default: | ||
1923 | DEBUGP(5, dev, "unknown event %.2x\n", event); | ||
1924 | break; | ||
1925 | } | ||
1926 | DEBUGP(3, dev, "<- cm4000_event\n"); | ||
1927 | return CS_SUCCESS; | ||
1928 | } | 1895 | } |
1929 | 1896 | ||
1930 | static void cm4000_release(dev_link_t *link) | 1897 | static void cm4000_release(dev_link_t *link) |
@@ -1934,11 +1901,10 @@ static void cm4000_release(dev_link_t *link) | |||
1934 | pcmcia_release_io(link->handle, &link->io); | 1901 | pcmcia_release_io(link->handle, &link->io); |
1935 | } | 1902 | } |
1936 | 1903 | ||
1937 | static dev_link_t *cm4000_attach(void) | 1904 | static int cm4000_attach(struct pcmcia_device *p_dev) |
1938 | { | 1905 | { |
1939 | struct cm4000_dev *dev; | 1906 | struct cm4000_dev *dev; |
1940 | dev_link_t *link; | 1907 | dev_link_t *link; |
1941 | client_reg_t client_reg; | ||
1942 | int i; | 1908 | int i; |
1943 | 1909 | ||
1944 | for (i = 0; i < CM4000_MAX_DEV; i++) | 1910 | for (i = 0; i < CM4000_MAX_DEV; i++) |
@@ -1947,76 +1913,55 @@ static dev_link_t *cm4000_attach(void) | |||
1947 | 1913 | ||
1948 | if (i == CM4000_MAX_DEV) { | 1914 | if (i == CM4000_MAX_DEV) { |
1949 | printk(KERN_NOTICE MODULE_NAME ": all devices in use\n"); | 1915 | printk(KERN_NOTICE MODULE_NAME ": all devices in use\n"); |
1950 | return NULL; | 1916 | return -ENODEV; |
1951 | } | 1917 | } |
1952 | 1918 | ||
1953 | /* create a new cm4000_cs device */ | 1919 | /* create a new cm4000_cs device */ |
1954 | dev = kzalloc(sizeof(struct cm4000_dev), GFP_KERNEL); | 1920 | dev = kzalloc(sizeof(struct cm4000_dev), GFP_KERNEL); |
1955 | if (dev == NULL) | 1921 | if (dev == NULL) |
1956 | return NULL; | 1922 | return -ENOMEM; |
1957 | 1923 | ||
1958 | link = &dev->link; | 1924 | link = &dev->link; |
1959 | link->priv = dev; | 1925 | link->priv = dev; |
1960 | link->conf.IntType = INT_MEMORY_AND_IO; | 1926 | link->conf.IntType = INT_MEMORY_AND_IO; |
1961 | dev_table[i] = link; | 1927 | dev_table[i] = link; |
1962 | 1928 | ||
1963 | /* register with card services */ | ||
1964 | client_reg.dev_info = &dev_info; | ||
1965 | client_reg.EventMask = | ||
1966 | CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | | ||
1967 | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | | ||
1968 | CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; | ||
1969 | client_reg.Version = 0x0210; | ||
1970 | client_reg.event_callback_args.client_data = link; | ||
1971 | |||
1972 | i = pcmcia_register_client(&link->handle, &client_reg); | ||
1973 | if (i) { | ||
1974 | cs_error(link->handle, RegisterClient, i); | ||
1975 | cm4000_detach(link); | ||
1976 | return NULL; | ||
1977 | } | ||
1978 | |||
1979 | init_waitqueue_head(&dev->devq); | 1929 | init_waitqueue_head(&dev->devq); |
1980 | init_waitqueue_head(&dev->ioq); | 1930 | init_waitqueue_head(&dev->ioq); |
1981 | init_waitqueue_head(&dev->atrq); | 1931 | init_waitqueue_head(&dev->atrq); |
1982 | init_waitqueue_head(&dev->readq); | 1932 | init_waitqueue_head(&dev->readq); |
1983 | 1933 | ||
1984 | return link; | 1934 | link->handle = p_dev; |
1985 | } | 1935 | p_dev->instance = link; |
1986 | |||
1987 | static void cm4000_detach_by_devno(int devno, dev_link_t * link) | ||
1988 | { | ||
1989 | struct cm4000_dev *dev = link->priv; | ||
1990 | |||
1991 | DEBUGP(3, dev, "-> detach_by_devno(devno=%d)\n", devno); | ||
1992 | |||
1993 | if (link->state & DEV_CONFIG) { | ||
1994 | DEBUGP(5, dev, "device still configured (try to release it)\n"); | ||
1995 | cm4000_release(link); | ||
1996 | } | ||
1997 | 1936 | ||
1998 | if (link->handle) { | 1937 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; |
1999 | pcmcia_deregister_client(link->handle); | 1938 | cm4000_config(link, i); |
2000 | } | ||
2001 | 1939 | ||
2002 | dev_table[devno] = NULL; | 1940 | return 0; |
2003 | kfree(dev); | ||
2004 | return; | ||
2005 | } | 1941 | } |
2006 | 1942 | ||
2007 | static void cm4000_detach(dev_link_t * link) | 1943 | static void cm4000_detach(struct pcmcia_device *p_dev) |
2008 | { | 1944 | { |
2009 | int i; | 1945 | dev_link_t *link = dev_to_instance(p_dev); |
1946 | struct cm4000_dev *dev = link->priv; | ||
1947 | int devno; | ||
2010 | 1948 | ||
2011 | /* find device */ | 1949 | /* find device */ |
2012 | for (i = 0; i < CM4000_MAX_DEV; i++) | 1950 | for (devno = 0; devno < CM4000_MAX_DEV; devno++) |
2013 | if (dev_table[i] == link) | 1951 | if (dev_table[devno] == link) |
2014 | break; | 1952 | break; |
2015 | 1953 | if (devno == CM4000_MAX_DEV) | |
2016 | if (i == CM4000_MAX_DEV) | ||
2017 | return; | 1954 | return; |
2018 | 1955 | ||
2019 | cm4000_detach_by_devno(i, link); | 1956 | link->state &= ~DEV_PRESENT; |
1957 | stop_monitor(dev); | ||
1958 | |||
1959 | if (link->state & DEV_CONFIG) | ||
1960 | cm4000_release(link); | ||
1961 | |||
1962 | dev_table[devno] = NULL; | ||
1963 | kfree(dev); | ||
1964 | |||
2020 | return; | 1965 | return; |
2021 | } | 1966 | } |
2022 | 1967 | ||
@@ -2041,9 +1986,10 @@ static struct pcmcia_driver cm4000_driver = { | |||
2041 | .drv = { | 1986 | .drv = { |
2042 | .name = "cm4000_cs", | 1987 | .name = "cm4000_cs", |
2043 | }, | 1988 | }, |
2044 | .attach = cm4000_attach, | 1989 | .probe = cm4000_attach, |
2045 | .detach = cm4000_detach, | 1990 | .remove = cm4000_detach, |
2046 | .event = cm4000_event, | 1991 | .suspend = cm4000_suspend, |
1992 | .resume = cm4000_resume, | ||
2047 | .id_table = cm4000_ids, | 1993 | .id_table = cm4000_ids, |
2048 | }; | 1994 | }; |
2049 | 1995 | ||
@@ -2063,13 +2009,8 @@ static int __init cmm_init(void) | |||
2063 | 2009 | ||
2064 | static void __exit cmm_exit(void) | 2010 | static void __exit cmm_exit(void) |
2065 | { | 2011 | { |
2066 | int i; | ||
2067 | |||
2068 | printk(KERN_INFO MODULE_NAME ": unloading\n"); | 2012 | printk(KERN_INFO MODULE_NAME ": unloading\n"); |
2069 | pcmcia_unregister_driver(&cm4000_driver); | 2013 | pcmcia_unregister_driver(&cm4000_driver); |
2070 | for (i = 0; i < CM4000_MAX_DEV; i++) | ||
2071 | if (dev_table[i]) | ||
2072 | cm4000_detach_by_devno(i, dev_table[i]); | ||
2073 | unregister_chrdev(major, DEVICE_NAME); | 2014 | unregister_chrdev(major, DEVICE_NAME); |
2074 | }; | 2015 | }; |
2075 | 2016 | ||