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