[PATCH] pcmcia: remove unneeded includes in ds.c
[safe/jmp/linux-2.6] / drivers / pcmcia / pcmcia_ioctl.c
1 /*
2  * pcmcia_ioctl.c -- ioctl interface for cardmgr and cardctl
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  *
8  * The initial developer of the original code is David A. Hinds
9  * <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
10  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
11  *
12  * (C) 1999             David A. Hinds
13  * (C) 2003 - 2004      Dominik Brodowski
14  */
15
16 /*
17  * This file will go away soon.
18  */
19
20
21 #include <linux/config.h>
22 #include <linux/kernel.h>
23 #include <linux/module.h>
24 #include <linux/init.h>
25 #include <linux/major.h>
26 #include <linux/errno.h>
27 #include <linux/ioctl.h>
28 #include <linux/proc_fs.h>
29 #include <linux/poll.h>
30 #include <linux/pci.h>
31 #include <linux/workqueue.h>
32
33 #define IN_CARD_SERVICES
34 #include <pcmcia/version.h>
35 #include <pcmcia/cs_types.h>
36 #include <pcmcia/cs.h>
37 #include <pcmcia/cistpl.h>
38 #include <pcmcia/ds.h>
39 #include <pcmcia/ss.h>
40
41 #include "cs_internal.h"
42 #include "ds_internal.h"
43
44 static int major_dev = -1;
45
46
47 /* Device user information */
48 #define MAX_EVENTS      32
49 #define USER_MAGIC      0x7ea4
50 #define CHECK_USER(u) \
51     (((u) == NULL) || ((u)->user_magic != USER_MAGIC))
52
53 typedef struct user_info_t {
54         u_int                   user_magic;
55         int                     event_head, event_tail;
56         event_t                 event[MAX_EVENTS];
57         struct user_info_t      *next;
58         struct pcmcia_socket    *socket;
59 } user_info_t;
60
61
62 #ifdef DEBUG
63 extern int ds_pc_debug;
64 #define cs_socket_name(skt)    ((skt)->dev.class_id)
65
66 #define ds_dbg(lvl, fmt, arg...) do {           \
67         if (ds_pc_debug >= lvl)                         \
68                 printk(KERN_DEBUG "ds: " fmt , ## arg);         \
69 } while (0)
70 #else
71 #define ds_dbg(lvl, fmt, arg...) do { } while (0)
72 #endif
73
74
75 /* backwards-compatible accessing of driver --- by name! */
76
77 static struct pcmcia_driver * get_pcmcia_driver (dev_info_t *dev_info)
78 {
79         struct device_driver *drv;
80         struct pcmcia_driver *p_drv;
81
82         drv = driver_find((char *) dev_info, &pcmcia_bus_type);
83         if (!drv)
84                 return NULL;
85
86         p_drv = container_of(drv, struct pcmcia_driver, drv);
87
88         return (p_drv);
89 }
90
91
92 #ifdef CONFIG_PROC_FS
93 static struct proc_dir_entry *proc_pccard = NULL;
94
95 static int proc_read_drivers_callback(struct device_driver *driver, void *d)
96 {
97         char **p = d;
98         struct pcmcia_driver *p_drv = container_of(driver,
99                                                    struct pcmcia_driver, drv);
100
101         *p += sprintf(*p, "%-24.24s 1 %d\n", p_drv->drv.name,
102 #ifdef CONFIG_MODULE_UNLOAD
103                       (p_drv->owner) ? module_refcount(p_drv->owner) : 1
104 #else
105                       1
106 #endif
107         );
108         d = (void *) p;
109
110         return 0;
111 }
112
113 static int proc_read_drivers(char *buf, char **start, off_t pos,
114                              int count, int *eof, void *data)
115 {
116         char *p = buf;
117
118         bus_for_each_drv(&pcmcia_bus_type, NULL,
119                          (void *) &p, proc_read_drivers_callback);
120
121         return (p - buf);
122 }
123 #endif
124
125 /*======================================================================
126
127     These manage a ring buffer of events pending for one user process
128
129 ======================================================================*/
130
131
132 static int queue_empty(user_info_t *user)
133 {
134     return (user->event_head == user->event_tail);
135 }
136
137 static event_t get_queued_event(user_info_t *user)
138 {
139     user->event_tail = (user->event_tail+1) % MAX_EVENTS;
140     return user->event[user->event_tail];
141 }
142
143 static void queue_event(user_info_t *user, event_t event)
144 {
145     user->event_head = (user->event_head+1) % MAX_EVENTS;
146     if (user->event_head == user->event_tail)
147         user->event_tail = (user->event_tail+1) % MAX_EVENTS;
148     user->event[user->event_head] = event;
149 }
150
151 void handle_event(struct pcmcia_socket *s, event_t event)
152 {
153     user_info_t *user;
154     for (user = s->user; user; user = user->next)
155         queue_event(user, event);
156     wake_up_interruptible(&s->queue);
157 }
158
159
160 /*======================================================================
161
162     bind_request() and bind_device() are merged by now. Register_client()
163     is called right at the end of bind_request(), during the driver's
164     ->attach() call. Individual descriptions:
165
166     bind_request() connects a socket to a particular client driver.
167     It looks up the specified device ID in the list of registered
168     drivers, binds it to the socket, and tries to create an instance
169     of the device.  unbind_request() deletes a driver instance.
170
171     Bind_device() associates a device driver with a particular socket.
172     It is normally called by Driver Services after it has identified
173     a newly inserted card.  An instance of that driver will then be
174     eligible to register as a client of this socket.
175
176     Register_client() uses the dev_info_t handle to match the
177     caller with a socket.  The driver must have already been bound
178     to a socket with bind_device() -- in fact, bind_device()
179     allocates the client structure that will be used.
180
181 ======================================================================*/
182
183 static int bind_request(struct pcmcia_socket *s, bind_info_t *bind_info)
184 {
185         struct pcmcia_driver *p_drv;
186         struct pcmcia_device *p_dev;
187         int ret = 0;
188         unsigned long flags;
189
190         s = pcmcia_get_socket(s);
191         if (!s)
192                 return -EINVAL;
193
194         ds_dbg(2, "bind_request(%d, '%s')\n", s->sock,
195                (char *)bind_info->dev_info);
196
197         p_drv = get_pcmcia_driver(&bind_info->dev_info);
198         if (!p_drv) {
199                 ret = -EINVAL;
200                 goto err_put;
201         }
202
203         if (!try_module_get(p_drv->owner)) {
204                 ret = -EINVAL;
205                 goto err_put_driver;
206         }
207
208         spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
209         list_for_each_entry(p_dev, &s->devices_list, socket_device_list) {
210                 if (p_dev->func == bind_info->function) {
211                         if ((p_dev->dev.driver == &p_drv->drv)) {
212                                 if (p_dev->cardmgr) {
213                                         /* if there's already a device
214                                          * registered, and it was registered
215                                          * by userspace before, we need to
216                                          * return the "instance". */
217                                         spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
218                                         bind_info->instance = p_dev->instance;
219                                         ret = -EBUSY;
220                                         goto err_put_module;
221                                 } else {
222                                         /* the correct driver managed to bind
223                                          * itself magically to the correct
224                                          * device. */
225                                         spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
226                                         p_dev->cardmgr = p_drv;
227                                         ret = 0;
228                                         goto err_put_module;
229                                 }
230                         } else if (!p_dev->dev.driver) {
231                                 /* there's already a device available where
232                                  * no device has been bound to yet. So we don't
233                                  * need to register a device! */
234                                 spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
235                                 goto rescan;
236                         }
237                 }
238         }
239         spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
240
241         p_dev = pcmcia_device_add(s, bind_info->function);
242         if (!p_dev) {
243                 ret = -EIO;
244                 goto err_put_module;
245         }
246
247 rescan:
248         p_dev->cardmgr = p_drv;
249
250         /* if a driver is already running, we can abort */
251         if (p_dev->dev.driver)
252                 goto err_put_module;
253
254         /*
255          * Prevent this racing with a card insertion.
256          */
257         down(&s->skt_sem);
258         bus_rescan_devices(&pcmcia_bus_type);
259         up(&s->skt_sem);
260
261         /* check whether the driver indeed matched. I don't care if this
262          * is racy or not, because it can only happen on cardmgr access
263          * paths...
264          */
265         if (!(p_dev->dev.driver == &p_drv->drv))
266                 p_dev->cardmgr = NULL;
267
268  err_put_module:
269         module_put(p_drv->owner);
270  err_put_driver:
271         put_driver(&p_drv->drv);
272  err_put:
273         pcmcia_put_socket(s);
274
275         return (ret);
276 } /* bind_request */
277
278
279 extern struct pci_bus *pcmcia_lookup_bus(struct pcmcia_socket *s);
280
281 static int get_device_info(struct pcmcia_socket *s, bind_info_t *bind_info, int first)
282 {
283         dev_node_t *node;
284         struct pcmcia_device *p_dev;
285         unsigned long flags;
286         int ret = 0;
287
288 #ifdef CONFIG_CARDBUS
289         /*
290          * Some unbelievably ugly code to associate the PCI cardbus
291          * device and its driver with the PCMCIA "bind" information.
292          */
293         {
294                 struct pci_bus *bus;
295
296                 bus = pcmcia_lookup_bus(s);
297                 if (bus) {
298                         struct list_head *list;
299                         struct pci_dev *dev = NULL;
300
301                         list = bus->devices.next;
302                         while (list != &bus->devices) {
303                                 struct pci_dev *pdev = pci_dev_b(list);
304                                 list = list->next;
305
306                                 if (first) {
307                                         dev = pdev;
308                                         break;
309                                 }
310
311                                 /* Try to handle "next" here some way? */
312                         }
313                         if (dev && dev->driver) {
314                                 strlcpy(bind_info->name, dev->driver->name, DEV_NAME_LEN);
315                                 bind_info->major = 0;
316                                 bind_info->minor = 0;
317                                 bind_info->next = NULL;
318                                 return 0;
319                         }
320                 }
321         }
322 #endif
323
324         spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
325         list_for_each_entry(p_dev, &s->devices_list, socket_device_list) {
326                 if (p_dev->func == bind_info->function) {
327                         p_dev = pcmcia_get_dev(p_dev);
328                         if (!p_dev)
329                                 continue;
330                         goto found;
331                 }
332         }
333         spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
334         return -ENODEV;
335
336  found:
337         spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
338
339         if ((!p_dev->instance) ||
340             (p_dev->instance->state & DEV_CONFIG_PENDING)) {
341                 ret = -EAGAIN;
342                 goto err_put;
343         }
344
345         if (first)
346                 node = p_dev->instance->dev;
347         else
348                 for (node = p_dev->instance->dev; node; node = node->next)
349                         if (node == bind_info->next)
350                                 break;
351         if (!node) {
352                 ret = -ENODEV;
353                 goto err_put;
354         }
355
356         strlcpy(bind_info->name, node->dev_name, DEV_NAME_LEN);
357         bind_info->major = node->major;
358         bind_info->minor = node->minor;
359         bind_info->next = node->next;
360
361  err_put:
362         pcmcia_put_dev(p_dev);
363         return (ret);
364 } /* get_device_info */
365
366
367 static int ds_open(struct inode *inode, struct file *file)
368 {
369     socket_t i = iminor(inode);
370     struct pcmcia_socket *s;
371     user_info_t *user;
372
373     ds_dbg(0, "ds_open(socket %d)\n", i);
374
375     s = pcmcia_get_socket_by_nr(i);
376     if (!s)
377             return -ENODEV;
378     s = pcmcia_get_socket(s);
379     if (!s)
380             return -ENODEV;
381
382     if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
383             if (s->pcmcia_state.busy) {
384                     pcmcia_put_socket(s);
385                     return -EBUSY;
386             }
387         else
388             s->pcmcia_state.busy = 1;
389     }
390
391     user = kmalloc(sizeof(user_info_t), GFP_KERNEL);
392     if (!user) {
393             pcmcia_put_socket(s);
394             return -ENOMEM;
395     }
396     user->event_tail = user->event_head = 0;
397     user->next = s->user;
398     user->user_magic = USER_MAGIC;
399     user->socket = s;
400     s->user = user;
401     file->private_data = user;
402
403     if (s->pcmcia_state.present)
404         queue_event(user, CS_EVENT_CARD_INSERTION);
405     return 0;
406 } /* ds_open */
407
408 /*====================================================================*/
409
410 static int ds_release(struct inode *inode, struct file *file)
411 {
412     struct pcmcia_socket *s;
413     user_info_t *user, **link;
414
415     ds_dbg(0, "ds_release(socket %d)\n", iminor(inode));
416
417     user = file->private_data;
418     if (CHECK_USER(user))
419         goto out;
420
421     s = user->socket;
422
423     /* Unlink user data structure */
424     if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
425         s->pcmcia_state.busy = 0;
426     }
427     file->private_data = NULL;
428     for (link = &s->user; *link; link = &(*link)->next)
429         if (*link == user) break;
430     if (link == NULL)
431         goto out;
432     *link = user->next;
433     user->user_magic = 0;
434     kfree(user);
435     pcmcia_put_socket(s);
436 out:
437     return 0;
438 } /* ds_release */
439
440 /*====================================================================*/
441
442 static ssize_t ds_read(struct file *file, char __user *buf,
443                        size_t count, loff_t *ppos)
444 {
445     struct pcmcia_socket *s;
446     user_info_t *user;
447     int ret;
448
449     ds_dbg(2, "ds_read(socket %d)\n", iminor(file->f_dentry->d_inode));
450
451     if (count < 4)
452         return -EINVAL;
453
454     user = file->private_data;
455     if (CHECK_USER(user))
456         return -EIO;
457
458     s = user->socket;
459     if (s->pcmcia_state.dead)
460         return -EIO;
461
462     ret = wait_event_interruptible(s->queue, !queue_empty(user));
463     if (ret == 0)
464         ret = put_user(get_queued_event(user), (int __user *)buf) ? -EFAULT : 4;
465
466     return ret;
467 } /* ds_read */
468
469 /*====================================================================*/
470
471 static ssize_t ds_write(struct file *file, const char __user *buf,
472                         size_t count, loff_t *ppos)
473 {
474     ds_dbg(2, "ds_write(socket %d)\n", iminor(file->f_dentry->d_inode));
475
476     if (count != 4)
477         return -EINVAL;
478     if ((file->f_flags & O_ACCMODE) == O_RDONLY)
479         return -EBADF;
480
481     return -EIO;
482 } /* ds_write */
483
484 /*====================================================================*/
485
486 /* No kernel lock - fine */
487 static u_int ds_poll(struct file *file, poll_table *wait)
488 {
489     struct pcmcia_socket *s;
490     user_info_t *user;
491
492     ds_dbg(2, "ds_poll(socket %d)\n", iminor(file->f_dentry->d_inode));
493
494     user = file->private_data;
495     if (CHECK_USER(user))
496         return POLLERR;
497     s = user->socket;
498     /*
499      * We don't check for a dead socket here since that
500      * will send cardmgr into an endless spin.
501      */
502     poll_wait(file, &s->queue, wait);
503     if (!queue_empty(user))
504         return POLLIN | POLLRDNORM;
505     return 0;
506 } /* ds_poll */
507
508 /*====================================================================*/
509
510 extern int pcmcia_adjust_resource_info(adjust_t *adj);
511
512 static int ds_ioctl(struct inode * inode, struct file * file,
513                     u_int cmd, u_long arg)
514 {
515     struct pcmcia_socket *s;
516     void __user *uarg = (char __user *)arg;
517     u_int size;
518     int ret, err;
519     ds_ioctl_arg_t *buf;
520     user_info_t *user;
521
522     ds_dbg(2, "ds_ioctl(socket %d, %#x, %#lx)\n", iminor(inode), cmd, arg);
523
524     user = file->private_data;
525     if (CHECK_USER(user))
526         return -EIO;
527
528     s = user->socket;
529     if (s->pcmcia_state.dead)
530         return -EIO;
531
532     size = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT;
533     if (size > sizeof(ds_ioctl_arg_t)) return -EINVAL;
534
535     /* Permission check */
536     if (!(cmd & IOC_OUT) && !capable(CAP_SYS_ADMIN))
537         return -EPERM;
538
539     if (cmd & IOC_IN) {
540         if (!access_ok(VERIFY_READ, uarg, size)) {
541             ds_dbg(3, "ds_ioctl(): verify_read = %d\n", -EFAULT);
542             return -EFAULT;
543         }
544     }
545     if (cmd & IOC_OUT) {
546         if (!access_ok(VERIFY_WRITE, uarg, size)) {
547             ds_dbg(3, "ds_ioctl(): verify_write = %d\n", -EFAULT);
548             return -EFAULT;
549         }
550     }
551     buf = kmalloc(sizeof(ds_ioctl_arg_t), GFP_KERNEL);
552     if (!buf)
553         return -ENOMEM;
554
555     err = ret = 0;
556
557     if (cmd & IOC_IN) __copy_from_user((char *)buf, uarg, size);
558
559     switch (cmd) {
560     case DS_ADJUST_RESOURCE_INFO:
561         ret = pcmcia_adjust_resource_info(&buf->adjust);
562         break;
563     case DS_GET_CARD_SERVICES_INFO:
564         ret = pcmcia_get_card_services_info(&buf->servinfo);
565         break;
566     case DS_GET_CONFIGURATION_INFO:
567         if (buf->config.Function &&
568            (buf->config.Function >= s->functions))
569             ret = CS_BAD_ARGS;
570         else
571             ret = pccard_get_configuration_info(s,
572                         buf->config.Function, &buf->config);
573         break;
574     case DS_GET_FIRST_TUPLE:
575         down(&s->skt_sem);
576         pcmcia_validate_mem(s);
577         up(&s->skt_sem);
578         ret = pccard_get_first_tuple(s, BIND_FN_ALL, &buf->tuple);
579         break;
580     case DS_GET_NEXT_TUPLE:
581         ret = pccard_get_next_tuple(s, BIND_FN_ALL, &buf->tuple);
582         break;
583     case DS_GET_TUPLE_DATA:
584         buf->tuple.TupleData = buf->tuple_parse.data;
585         buf->tuple.TupleDataMax = sizeof(buf->tuple_parse.data);
586         ret = pccard_get_tuple_data(s, &buf->tuple);
587         break;
588     case DS_PARSE_TUPLE:
589         buf->tuple.TupleData = buf->tuple_parse.data;
590         ret = pccard_parse_tuple(&buf->tuple, &buf->tuple_parse.parse);
591         break;
592     case DS_RESET_CARD:
593         ret = pccard_reset_card(s);
594         break;
595     case DS_GET_STATUS:
596         if (buf->status.Function &&
597            (buf->status.Function >= s->functions))
598             ret = CS_BAD_ARGS;
599         else
600         ret = pccard_get_status(s, buf->status.Function, &buf->status);
601         break;
602     case DS_VALIDATE_CIS:
603         down(&s->skt_sem);
604         pcmcia_validate_mem(s);
605         up(&s->skt_sem);
606         ret = pccard_validate_cis(s, BIND_FN_ALL, &buf->cisinfo);
607         break;
608     case DS_SUSPEND_CARD:
609         ret = pcmcia_suspend_card(s);
610         break;
611     case DS_RESUME_CARD:
612         ret = pcmcia_resume_card(s);
613         break;
614     case DS_EJECT_CARD:
615         err = pcmcia_eject_card(s);
616         break;
617     case DS_INSERT_CARD:
618         err = pcmcia_insert_card(s);
619         break;
620     case DS_ACCESS_CONFIGURATION_REGISTER:
621         if ((buf->conf_reg.Action == CS_WRITE) && !capable(CAP_SYS_ADMIN)) {
622             err = -EPERM;
623             goto free_out;
624         }
625         if (buf->conf_reg.Function &&
626            (buf->conf_reg.Function >= s->functions))
627             ret = CS_BAD_ARGS;
628         else
629             ret = pccard_access_configuration_register(s,
630                         buf->conf_reg.Function, &buf->conf_reg);
631         break;
632     case DS_GET_FIRST_REGION:
633     case DS_GET_NEXT_REGION:
634     case DS_BIND_MTD:
635         if (!capable(CAP_SYS_ADMIN)) {
636                 err = -EPERM;
637                 goto free_out;
638         } else {
639                 static int printed = 0;
640                 if (!printed) {
641                         printk(KERN_WARNING "2.6. kernels use pcmciamtd instead of memory_cs.c and do not require special\n");
642                         printk(KERN_WARNING "MTD handling any more.\n");
643                         printed++;
644                 }
645         }
646         err = -EINVAL;
647         goto free_out;
648         break;
649     case DS_GET_FIRST_WINDOW:
650         ret = pcmcia_get_window(s, &buf->win_info.handle, 0,
651                         &buf->win_info.window);
652         break;
653     case DS_GET_NEXT_WINDOW:
654         ret = pcmcia_get_window(s, &buf->win_info.handle,
655                         buf->win_info.handle->index + 1, &buf->win_info.window);
656         break;
657     case DS_GET_MEM_PAGE:
658         ret = pcmcia_get_mem_page(buf->win_info.handle,
659                            &buf->win_info.map);
660         break;
661     case DS_REPLACE_CIS:
662         ret = pcmcia_replace_cis(s, &buf->cisdump);
663         break;
664     case DS_BIND_REQUEST:
665         if (!capable(CAP_SYS_ADMIN)) {
666                 err = -EPERM;
667                 goto free_out;
668         }
669         err = bind_request(s, &buf->bind_info);
670         break;
671     case DS_GET_DEVICE_INFO:
672         err = get_device_info(s, &buf->bind_info, 1);
673         break;
674     case DS_GET_NEXT_DEVICE:
675         err = get_device_info(s, &buf->bind_info, 0);
676         break;
677     case DS_UNBIND_REQUEST:
678         err = 0;
679         break;
680     default:
681         err = -EINVAL;
682     }
683
684     if ((err == 0) && (ret != CS_SUCCESS)) {
685         ds_dbg(2, "ds_ioctl: ret = %d\n", ret);
686         switch (ret) {
687         case CS_BAD_SOCKET: case CS_NO_CARD:
688             err = -ENODEV; break;
689         case CS_BAD_ARGS: case CS_BAD_ATTRIBUTE: case CS_BAD_IRQ:
690         case CS_BAD_TUPLE:
691             err = -EINVAL; break;
692         case CS_IN_USE:
693             err = -EBUSY; break;
694         case CS_OUT_OF_RESOURCE:
695             err = -ENOSPC; break;
696         case CS_NO_MORE_ITEMS:
697             err = -ENODATA; break;
698         case CS_UNSUPPORTED_FUNCTION:
699             err = -ENOSYS; break;
700         default:
701             err = -EIO; break;
702         }
703     }
704
705     if (cmd & IOC_OUT) {
706         if (__copy_to_user(uarg, (char *)buf, size))
707             err = -EFAULT;
708     }
709
710 free_out:
711     kfree(buf);
712     return err;
713 } /* ds_ioctl */
714
715 /*====================================================================*/
716
717 static struct file_operations ds_fops = {
718         .owner          = THIS_MODULE,
719         .open           = ds_open,
720         .release        = ds_release,
721         .ioctl          = ds_ioctl,
722         .read           = ds_read,
723         .write          = ds_write,
724         .poll           = ds_poll,
725 };
726
727 void __init pcmcia_setup_ioctl(void) {
728         int i;
729
730         /* Set up character device for user mode clients */
731         i = register_chrdev(0, "pcmcia", &ds_fops);
732         if (i == -EBUSY)
733                 printk(KERN_NOTICE "unable to find a free device # for "
734                        "Driver Services\n");
735         else
736                 major_dev = i;
737
738 #ifdef CONFIG_PROC_FS
739         proc_pccard = proc_mkdir("pccard", proc_bus);
740         if (proc_pccard)
741                 create_proc_read_entry("drivers",0,proc_pccard,proc_read_drivers,NULL);
742 #endif
743 }
744
745
746 void __exit pcmcia_cleanup_ioctl(void) {
747 #ifdef CONFIG_PROC_FS
748         if (proc_pccard) {
749                 remove_proc_entry("drivers", proc_pccard);
750                 remove_proc_entry("pccard", proc_bus);
751         }
752 #endif
753         if (major_dev != -1)
754                 unregister_chrdev(major_dev, "pcmcia");
755 }