- Kai Germaschewski: ymfpci cleanups and resource leak fixes
[davej-history.git] / drivers / pcmcia / ds.c
blob02c689855511ca7c4f71f2dd1f3f62d97a3df561
1 /*======================================================================
3 PC Card Driver Services
5 ds.c 1.108 2000/08/07 19:06:15
7 The contents of this file are subject to the Mozilla Public
8 License Version 1.1 (the "License"); you may not use this file
9 except in compliance with the License. You may obtain a copy of
10 the License at http://www.mozilla.org/MPL/
12 Software distributed under the License is distributed on an "AS
13 IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
14 implied. See the License for the specific language governing
15 rights and limitations under the License.
17 The initial developer of the original code is David A. Hinds
18 <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
19 are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
21 Alternatively, the contents of this file may be used under the
22 terms of the GNU Public License version 2 (the "GPL"), in which
23 case the provisions of the GPL are applicable instead of the
24 above. If you wish to allow the use of your version of this file
25 only under the terms of the GPL and not to allow others to use
26 your version of this file under the MPL, indicate your decision
27 by deleting the provisions above and replace them with the notice
28 and other provisions required by the GPL. If you do not delete
29 the provisions above, a recipient may use your version of this
30 file under either the MPL or the GPL.
32 ======================================================================*/
34 #include <linux/config.h>
35 #include <linux/module.h>
36 #include <linux/init.h>
37 #include <linux/kernel.h>
38 #include <linux/major.h>
39 #include <linux/string.h>
40 #include <linux/errno.h>
41 #include <linux/malloc.h>
42 #include <linux/mm.h>
43 #include <linux/fcntl.h>
44 #include <linux/sched.h>
45 #include <linux/smp_lock.h>
46 #include <linux/timer.h>
47 #include <linux/ioctl.h>
48 #include <linux/proc_fs.h>
49 #include <linux/poll.h>
50 #include <linux/pci.h>
52 #include <pcmcia/version.h>
53 #include <pcmcia/cs_types.h>
54 #include <pcmcia/cs.h>
55 #include <pcmcia/bulkmem.h>
56 #include <pcmcia/cistpl.h>
57 #include <pcmcia/ds.h>
59 #ifdef PCMCIA_DEBUG
60 int pc_debug = PCMCIA_DEBUG;
61 MODULE_PARM(pc_debug, "i");
62 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
63 static const char *version =
64 "ds.c 1.108 2000/08/07 19:06:15 (David Hinds)";
65 #else
66 #define DEBUG(n, args...)
67 #endif
69 MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
70 MODULE_DESCRIPTION("PCMCIA Driver Services " CS_RELEASE);
72 /*====================================================================*/
74 typedef struct driver_info_t {
75 dev_info_t dev_info;
76 int use_count, status;
77 dev_link_t *(*attach)(void);
78 void (*detach)(dev_link_t *);
79 struct driver_info_t *next;
80 } driver_info_t;
82 typedef struct socket_bind_t {
83 driver_info_t *driver;
84 u_char function;
85 dev_link_t *instance;
86 struct socket_bind_t *next;
87 } socket_bind_t;
89 /* Device user information */
90 #define MAX_EVENTS 32
91 #define USER_MAGIC 0x7ea4
92 #define CHECK_USER(u) \
93 (((u) == NULL) || ((u)->user_magic != USER_MAGIC))
94 typedef struct user_info_t {
95 u_int user_magic;
96 int event_head, event_tail;
97 event_t event[MAX_EVENTS];
98 struct user_info_t *next;
99 } user_info_t;
101 /* Socket state information */
102 typedef struct socket_info_t {
103 client_handle_t handle;
104 int state;
105 user_info_t *user;
106 int req_pending, req_result;
107 wait_queue_head_t queue, request;
108 struct timer_list removal;
109 socket_bind_t *bind;
110 } socket_info_t;
112 #define SOCKET_PRESENT 0x01
113 #define SOCKET_BUSY 0x02
114 #define SOCKET_REMOVAL_PENDING 0x10
116 /*====================================================================*/
118 /* Device driver ID passed to Card Services */
119 static dev_info_t dev_info = "Driver Services";
121 /* Linked list of all registered device drivers */
122 static driver_info_t *root_driver = NULL;
124 static int sockets = 0, major_dev = -1;
125 static socket_info_t *socket_table = NULL;
127 extern struct proc_dir_entry *proc_pccard;
129 /* We use this to distinguish in-kernel from modular drivers */
130 static int init_status = 1;
132 /*====================================================================*/
134 static void cs_error(client_handle_t handle, int func, int ret)
136 error_info_t err = { func, ret };
137 pcmcia_report_error(handle, &err);
140 /*======================================================================
142 Register_pccard_driver() and unregister_pccard_driver() are used
143 tell Driver Services that a PC Card client driver is available to
144 be bound to sockets.
146 ======================================================================*/
148 int register_pccard_driver(dev_info_t *dev_info,
149 dev_link_t *(*attach)(void),
150 void (*detach)(dev_link_t *))
152 driver_info_t *driver;
153 socket_bind_t *b;
154 int i;
156 DEBUG(0, "ds: register_pccard_driver('%s')\n", (char *)dev_info);
157 for (driver = root_driver; driver; driver = driver->next)
158 if (strncmp((char *)dev_info, (char *)driver->dev_info,
159 DEV_NAME_LEN) == 0)
160 break;
161 if (!driver) {
162 driver = kmalloc(sizeof(driver_info_t), GFP_KERNEL);
163 if (!driver) return -ENOMEM;
164 strncpy(driver->dev_info, (char *)dev_info, DEV_NAME_LEN);
165 driver->use_count = 0;
166 driver->status = init_status;
167 driver->next = root_driver;
168 root_driver = driver;
171 driver->attach = attach;
172 driver->detach = detach;
173 if (driver->use_count == 0) return 0;
175 /* Instantiate any already-bound devices */
176 for (i = 0; i < sockets; i++)
177 for (b = socket_table[i].bind; b; b = b->next) {
178 if (b->driver != driver) continue;
179 b->instance = driver->attach();
180 if (b->instance == NULL)
181 printk(KERN_NOTICE "ds: unable to create instance "
182 "of '%s'!\n", driver->dev_info);
185 return 0;
186 } /* register_pccard_driver */
188 /*====================================================================*/
190 int unregister_pccard_driver(dev_info_t *dev_info)
192 driver_info_t *target, **d = &root_driver;
193 socket_bind_t *b;
194 int i;
196 DEBUG(0, "ds: unregister_pccard_driver('%s')\n",
197 (char *)dev_info);
198 while ((*d) && (strncmp((*d)->dev_info, (char *)dev_info,
199 DEV_NAME_LEN) != 0))
200 d = &(*d)->next;
201 if (*d == NULL)
202 return -ENODEV;
204 target = *d;
205 if (target->use_count == 0) {
206 *d = target->next;
207 kfree(target);
208 } else {
209 /* Blank out any left-over device instances */
210 target->attach = NULL; target->detach = NULL;
211 for (i = 0; i < sockets; i++)
212 for (b = socket_table[i].bind; b; b = b->next)
213 if (b->driver == target) b->instance = NULL;
215 return 0;
216 } /* unregister_pccard_driver */
218 /*====================================================================*/
220 #ifdef CONFIG_PROC_FS
221 static int proc_read_drivers(char *buf, char **start, off_t pos,
222 int count, int *eof, void *data)
224 driver_info_t *d;
225 char *p = buf;
226 for (d = root_driver; d; d = d->next)
227 p += sprintf(p, "%-24.24s %d %d\n", d->dev_info,
228 d->status, d->use_count);
229 return (p - buf);
231 #endif
233 /*======================================================================
235 These manage a ring buffer of events pending for one user process
237 ======================================================================*/
239 static int queue_empty(user_info_t *user)
241 return (user->event_head == user->event_tail);
244 static event_t get_queued_event(user_info_t *user)
246 user->event_tail = (user->event_tail+1) % MAX_EVENTS;
247 return user->event[user->event_tail];
250 static void queue_event(user_info_t *user, event_t event)
252 user->event_head = (user->event_head+1) % MAX_EVENTS;
253 if (user->event_head == user->event_tail)
254 user->event_tail = (user->event_tail+1) % MAX_EVENTS;
255 user->event[user->event_head] = event;
258 static void handle_event(socket_info_t *s, event_t event)
260 user_info_t *user;
261 for (user = s->user; user; user = user->next)
262 queue_event(user, event);
263 wake_up_interruptible(&s->queue);
266 static int handle_request(socket_info_t *s, event_t event)
268 if (s->req_pending != 0)
269 return CS_IN_USE;
270 if (s->state & SOCKET_BUSY)
271 s->req_pending = 1;
272 handle_event(s, event);
273 if (s->req_pending > 0) {
274 interruptible_sleep_on(&s->request);
275 if (signal_pending(current))
276 return CS_IN_USE;
277 else
278 return s->req_result;
280 return CS_SUCCESS;
283 static void handle_removal(u_long sn)
285 socket_info_t *s = &socket_table[sn];
286 handle_event(s, CS_EVENT_CARD_REMOVAL);
287 s->state &= ~SOCKET_REMOVAL_PENDING;
290 /*======================================================================
292 The card status event handler.
294 ======================================================================*/
296 static int ds_event(event_t event, int priority,
297 event_callback_args_t *args)
299 socket_info_t *s;
300 int i;
302 DEBUG(1, "ds: ds_event(0x%06x, %d, 0x%p)\n",
303 event, priority, args->client_handle);
304 s = args->client_data;
305 i = s - socket_table;
307 switch (event) {
309 case CS_EVENT_CARD_REMOVAL:
310 s->state &= ~SOCKET_PRESENT;
311 if (!(s->state & SOCKET_REMOVAL_PENDING)) {
312 s->state |= SOCKET_REMOVAL_PENDING;
313 s->removal.expires = jiffies + HZ/10;
314 add_timer(&s->removal);
316 break;
318 case CS_EVENT_CARD_INSERTION:
319 s->state |= SOCKET_PRESENT;
320 handle_event(s, event);
321 break;
323 case CS_EVENT_EJECTION_REQUEST:
324 return handle_request(s, event);
325 break;
327 default:
328 handle_event(s, event);
329 break;
332 return 0;
333 } /* ds_event */
335 /*======================================================================
337 bind_mtd() connects a memory region with an MTD client.
339 ======================================================================*/
341 static int bind_mtd(int i, mtd_info_t *mtd_info)
343 mtd_bind_t bind_req;
344 int ret;
346 bind_req.dev_info = &mtd_info->dev_info;
347 bind_req.Attributes = mtd_info->Attributes;
348 bind_req.Socket = i;
349 bind_req.CardOffset = mtd_info->CardOffset;
350 ret = pcmcia_bind_mtd(&bind_req);
351 if (ret != CS_SUCCESS) {
352 cs_error(NULL, BindMTD, ret);
353 printk(KERN_NOTICE "ds: unable to bind MTD '%s' to socket %d"
354 " offset 0x%x\n",
355 (char *)bind_req.dev_info, i, bind_req.CardOffset);
356 return -ENODEV;
358 return 0;
359 } /* bind_mtd */
361 /*======================================================================
363 bind_request() connects a socket to a particular client driver.
364 It looks up the specified device ID in the list of registered
365 drivers, binds it to the socket, and tries to create an instance
366 of the device. unbind_request() deletes a driver instance.
368 ======================================================================*/
370 static int bind_request(int i, bind_info_t *bind_info)
372 struct driver_info_t *driver;
373 socket_bind_t *b;
374 bind_req_t bind_req;
375 socket_info_t *s = &socket_table[i];
376 int ret;
378 DEBUG(2, "bind_request(%d, '%s')\n", i,
379 (char *)bind_info->dev_info);
380 for (driver = root_driver; driver; driver = driver->next)
381 if (strcmp((char *)driver->dev_info,
382 (char *)bind_info->dev_info) == 0)
383 break;
384 if (driver == NULL) {
385 driver = kmalloc(sizeof(driver_info_t), GFP_KERNEL);
386 if (!driver) return -ENOMEM;
387 strncpy(driver->dev_info, bind_info->dev_info, DEV_NAME_LEN);
388 driver->use_count = 0;
389 driver->next = root_driver;
390 driver->attach = NULL; driver->detach = NULL;
391 root_driver = driver;
394 for (b = s->bind; b; b = b->next)
395 if ((driver == b->driver) &&
396 (bind_info->function == b->function))
397 break;
398 if (b != NULL) {
399 bind_info->instance = b->instance;
400 return -EBUSY;
403 bind_req.Socket = i;
404 bind_req.Function = bind_info->function;
405 bind_req.dev_info = &driver->dev_info;
406 ret = pcmcia_bind_device(&bind_req);
407 if (ret != CS_SUCCESS) {
408 cs_error(NULL, BindDevice, ret);
409 printk(KERN_NOTICE "ds: unable to bind '%s' to socket %d\n",
410 (char *)dev_info, i);
411 return -ENODEV;
414 /* Add binding to list for this socket */
415 driver->use_count++;
416 b = kmalloc(sizeof(socket_bind_t), GFP_KERNEL);
417 b->driver = driver;
418 b->function = bind_info->function;
419 b->instance = NULL;
420 b->next = s->bind;
421 s->bind = b;
423 if (driver->attach) {
424 b->instance = driver->attach();
425 if (b->instance == NULL) {
426 printk(KERN_NOTICE "ds: unable to create instance "
427 "of '%s'!\n", (char *)bind_info->dev_info);
428 return -ENODEV;
432 return 0;
433 } /* bind_request */
435 /*====================================================================*/
437 static int get_device_info(int i, bind_info_t *bind_info, int first)
439 socket_info_t *s = &socket_table[i];
440 socket_bind_t *b;
441 dev_node_t *node;
443 #ifdef CONFIG_CARDBUS
445 * Some unbelievably ugly code to associate the PCI cardbus
446 * device and its driver with the PCMCIA "bind" information.
449 struct pci_bus *bus;
451 bus = pcmcia_lookup_bus(s->handle);
452 if (bus) {
453 struct list_head *list;
454 struct pci_dev *dev = NULL;
456 list = bus->devices.next;
457 while (list != &bus->devices) {
458 struct pci_dev *pdev = pci_dev_b(list);
459 list = list->next;
461 if (first) {
462 dev = pdev;
463 break;
466 /* Try to handle "next" here some way? */
468 if (dev && dev->driver) {
469 strncpy(bind_info->name, dev->driver->name, DEV_NAME_LEN);
470 bind_info->name[DEV_NAME_LEN-1] = '\0';
471 bind_info->major = 0;
472 bind_info->minor = 0;
473 bind_info->next = NULL;
474 return 0;
478 #endif
480 for (b = s->bind; b; b = b->next)
481 if ((strcmp((char *)b->driver->dev_info,
482 (char *)bind_info->dev_info) == 0) &&
483 (b->function == bind_info->function))
484 break;
485 if (b == NULL) return -ENODEV;
486 if ((b->instance == NULL) ||
487 (b->instance->state & DEV_CONFIG_PENDING))
488 return -EAGAIN;
489 if (first)
490 node = b->instance->dev;
491 else
492 for (node = b->instance->dev; node; node = node->next)
493 if (node == bind_info->next) break;
494 if (node == NULL) return -ENODEV;
496 strncpy(bind_info->name, node->dev_name, DEV_NAME_LEN);
497 bind_info->name[DEV_NAME_LEN-1] = '\0';
498 bind_info->major = node->major;
499 bind_info->minor = node->minor;
500 bind_info->next = node->next;
502 return 0;
503 } /* get_device_info */
505 /*====================================================================*/
507 static int unbind_request(int i, bind_info_t *bind_info)
509 socket_info_t *s = &socket_table[i];
510 socket_bind_t **b, *c;
512 DEBUG(2, "unbind_request(%d, '%s')\n", i,
513 (char *)bind_info->dev_info);
514 for (b = &s->bind; *b; b = &(*b)->next)
515 if ((strcmp((char *)(*b)->driver->dev_info,
516 (char *)bind_info->dev_info) == 0) &&
517 ((*b)->function == bind_info->function))
518 break;
519 if (*b == NULL)
520 return -ENODEV;
522 c = *b;
523 c->driver->use_count--;
524 if (c->driver->detach) {
525 if (c->instance)
526 c->driver->detach(c->instance);
527 } else {
528 if (c->driver->use_count == 0) {
529 driver_info_t **d;
530 for (d = &root_driver; *d; d = &((*d)->next))
531 if (c->driver == *d) break;
532 *d = (*d)->next;
533 kfree(c->driver);
536 *b = c->next;
537 kfree(c);
539 return 0;
540 } /* unbind_request */
542 /*======================================================================
544 The user-mode PC Card device interface
546 ======================================================================*/
548 static int ds_open(struct inode *inode, struct file *file)
550 socket_t i = MINOR(inode->i_rdev);
551 socket_info_t *s;
552 user_info_t *user;
554 DEBUG(0, "ds_open(socket %d)\n", i);
555 if ((i >= sockets) || (sockets == 0))
556 return -ENODEV;
557 s = &socket_table[i];
558 if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
559 if (s->state & SOCKET_BUSY)
560 return -EBUSY;
561 else
562 s->state |= SOCKET_BUSY;
565 user = kmalloc(sizeof(user_info_t), GFP_KERNEL);
566 if (!user) return -ENOMEM;
567 user->event_tail = user->event_head = 0;
568 user->next = s->user;
569 user->user_magic = USER_MAGIC;
570 s->user = user;
571 file->private_data = user;
573 if (s->state & SOCKET_PRESENT)
574 queue_event(user, CS_EVENT_CARD_INSERTION);
575 return 0;
576 } /* ds_open */
578 /*====================================================================*/
580 static int ds_release(struct inode *inode, struct file *file)
582 socket_t i = MINOR(inode->i_rdev);
583 socket_info_t *s;
584 user_info_t *user, **link;
586 DEBUG(0, "ds_release(socket %d)\n", i);
587 if ((i >= sockets) || (sockets == 0))
588 return 0;
589 lock_kernel();
590 s = &socket_table[i];
591 user = file->private_data;
592 if (CHECK_USER(user))
593 goto out;
595 /* Unlink user data structure */
596 if ((file->f_flags & O_ACCMODE) != O_RDONLY)
597 s->state &= ~SOCKET_BUSY;
598 file->private_data = NULL;
599 for (link = &s->user; *link; link = &(*link)->next)
600 if (*link == user) break;
601 if (link == NULL)
602 goto out;
603 *link = user->next;
604 user->user_magic = 0;
605 kfree(user);
606 out:
607 unlock_kernel();
608 return 0;
609 } /* ds_release */
611 /*====================================================================*/
613 static ssize_t ds_read(struct file *file, char *buf,
614 size_t count, loff_t *ppos)
616 socket_t i = MINOR(file->f_dentry->d_inode->i_rdev);
617 socket_info_t *s;
618 user_info_t *user;
620 DEBUG(2, "ds_read(socket %d)\n", i);
622 if ((i >= sockets) || (sockets == 0))
623 return -ENODEV;
624 if (count < 4)
625 return -EINVAL;
626 s = &socket_table[i];
627 user = file->private_data;
628 if (CHECK_USER(user))
629 return -EIO;
631 if (queue_empty(user)) {
632 interruptible_sleep_on(&s->queue);
633 if (signal_pending(current))
634 return -EINTR;
636 put_user(get_queued_event(user), (int *)buf);
637 return 4;
638 } /* ds_read */
640 /*====================================================================*/
642 static ssize_t ds_write(struct file *file, const char *buf,
643 size_t count, loff_t *ppos)
645 socket_t i = MINOR(file->f_dentry->d_inode->i_rdev);
646 socket_info_t *s;
647 user_info_t *user;
649 DEBUG(2, "ds_write(socket %d)\n", i);
651 if ((i >= sockets) || (sockets == 0))
652 return -ENODEV;
653 if (count != 4)
654 return -EINVAL;
655 if ((file->f_flags & O_ACCMODE) == O_RDONLY)
656 return -EBADF;
657 s = &socket_table[i];
658 user = file->private_data;
659 if (CHECK_USER(user))
660 return -EIO;
662 if (s->req_pending) {
663 s->req_pending--;
664 get_user(s->req_result, (int *)buf);
665 if ((s->req_result != 0) || (s->req_pending == 0))
666 wake_up_interruptible(&s->request);
667 } else
668 return -EIO;
670 return 4;
671 } /* ds_write */
673 /*====================================================================*/
675 /* No kernel lock - fine */
676 static u_int ds_poll(struct file *file, poll_table *wait)
678 socket_t i = MINOR(file->f_dentry->d_inode->i_rdev);
679 socket_info_t *s;
680 user_info_t *user;
682 DEBUG(2, "ds_poll(socket %d)\n", i);
684 if ((i >= sockets) || (sockets == 0))
685 return POLLERR;
686 s = &socket_table[i];
687 user = file->private_data;
688 if (CHECK_USER(user))
689 return POLLERR;
690 poll_wait(file, &s->queue, wait);
691 if (!queue_empty(user))
692 return POLLIN | POLLRDNORM;
693 return 0;
694 } /* ds_poll */
696 /*====================================================================*/
698 static int ds_ioctl(struct inode * inode, struct file * file,
699 u_int cmd, u_long arg)
701 socket_t i = MINOR(inode->i_rdev);
702 socket_info_t *s;
703 u_int size;
704 int ret, err;
705 ds_ioctl_arg_t buf;
707 DEBUG(2, "ds_ioctl(socket %d, %#x, %#lx)\n", i, cmd, arg);
709 if ((i >= sockets) || (sockets == 0))
710 return -ENODEV;
711 s = &socket_table[i];
713 size = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT;
714 if (size > sizeof(ds_ioctl_arg_t)) return -EINVAL;
716 /* Permission check */
717 if (!(cmd & IOC_OUT) && !capable(CAP_SYS_ADMIN))
718 return -EPERM;
720 if (cmd & IOC_IN) {
721 err = verify_area(VERIFY_READ, (char *)arg, size);
722 if (err) {
723 DEBUG(3, "ds_ioctl(): verify_read = %d\n", err);
724 return err;
727 if (cmd & IOC_OUT) {
728 err = verify_area(VERIFY_WRITE, (char *)arg, size);
729 if (err) {
730 DEBUG(3, "ds_ioctl(): verify_write = %d\n", err);
731 return err;
735 err = ret = 0;
737 if (cmd & IOC_IN) copy_from_user((char *)&buf, (char *)arg, size);
739 switch (cmd) {
740 case DS_ADJUST_RESOURCE_INFO:
741 ret = pcmcia_adjust_resource_info(s->handle, &buf.adjust);
742 break;
743 case DS_GET_CARD_SERVICES_INFO:
744 ret = pcmcia_get_card_services_info(&buf.servinfo);
745 break;
746 case DS_GET_CONFIGURATION_INFO:
747 ret = pcmcia_get_configuration_info(s->handle, &buf.config);
748 break;
749 case DS_GET_FIRST_TUPLE:
750 ret = pcmcia_get_first_tuple(s->handle, &buf.tuple);
751 break;
752 case DS_GET_NEXT_TUPLE:
753 ret = pcmcia_get_next_tuple(s->handle, &buf.tuple);
754 break;
755 case DS_GET_TUPLE_DATA:
756 buf.tuple.TupleData = buf.tuple_parse.data;
757 buf.tuple.TupleDataMax = sizeof(buf.tuple_parse.data);
758 ret = pcmcia_get_tuple_data(s->handle, &buf.tuple);
759 break;
760 case DS_PARSE_TUPLE:
761 buf.tuple.TupleData = buf.tuple_parse.data;
762 ret = pcmcia_parse_tuple(s->handle, &buf.tuple, &buf.tuple_parse.parse);
763 break;
764 case DS_RESET_CARD:
765 ret = pcmcia_reset_card(s->handle, NULL);
766 break;
767 case DS_GET_STATUS:
768 ret = pcmcia_get_status(s->handle, &buf.status);
769 break;
770 case DS_VALIDATE_CIS:
771 ret = pcmcia_validate_cis(s->handle, &buf.cisinfo);
772 break;
773 case DS_SUSPEND_CARD:
774 ret = pcmcia_suspend_card(s->handle, NULL);
775 break;
776 case DS_RESUME_CARD:
777 ret = pcmcia_resume_card(s->handle, NULL);
778 break;
779 case DS_EJECT_CARD:
780 ret = pcmcia_eject_card(s->handle, NULL);
781 break;
782 case DS_INSERT_CARD:
783 ret = pcmcia_insert_card(s->handle, NULL);
784 break;
785 case DS_ACCESS_CONFIGURATION_REGISTER:
786 if ((buf.conf_reg.Action == CS_WRITE) && !capable(CAP_SYS_ADMIN))
787 return -EPERM;
788 ret = pcmcia_access_configuration_register(s->handle, &buf.conf_reg);
789 break;
790 case DS_GET_FIRST_REGION:
791 ret = pcmcia_get_first_region(s->handle, &buf.region);
792 break;
793 case DS_GET_NEXT_REGION:
794 ret = pcmcia_get_next_region(s->handle, &buf.region);
795 break;
796 case DS_GET_FIRST_WINDOW:
797 buf.win_info.handle = (window_handle_t)s->handle;
798 ret = pcmcia_get_first_window(&buf.win_info.handle, &buf.win_info.window);
799 break;
800 case DS_GET_NEXT_WINDOW:
801 ret = pcmcia_get_next_window(&buf.win_info.handle, &buf.win_info.window);
802 break;
803 case DS_GET_MEM_PAGE:
804 ret = pcmcia_get_mem_page(buf.win_info.handle,
805 &buf.win_info.map);
806 break;
807 case DS_REPLACE_CIS:
808 ret = pcmcia_replace_cis(s->handle, &buf.cisdump);
809 break;
810 case DS_BIND_REQUEST:
811 if (!capable(CAP_SYS_ADMIN)) return -EPERM;
812 err = bind_request(i, &buf.bind_info);
813 break;
814 case DS_GET_DEVICE_INFO:
815 err = get_device_info(i, &buf.bind_info, 1);
816 break;
817 case DS_GET_NEXT_DEVICE:
818 err = get_device_info(i, &buf.bind_info, 0);
819 break;
820 case DS_UNBIND_REQUEST:
821 err = unbind_request(i, &buf.bind_info);
822 break;
823 case DS_BIND_MTD:
824 if (!suser()) return -EPERM;
825 err = bind_mtd(i, &buf.mtd_info);
826 break;
827 default:
828 err = -EINVAL;
831 if ((err == 0) && (ret != CS_SUCCESS)) {
832 DEBUG(2, "ds_ioctl: ret = %d\n", ret);
833 switch (ret) {
834 case CS_BAD_SOCKET: case CS_NO_CARD:
835 err = -ENODEV; break;
836 case CS_BAD_ARGS: case CS_BAD_ATTRIBUTE: case CS_BAD_IRQ:
837 case CS_BAD_TUPLE:
838 err = -EINVAL; break;
839 case CS_IN_USE:
840 err = -EBUSY; break;
841 case CS_OUT_OF_RESOURCE:
842 err = -ENOSPC; break;
843 case CS_NO_MORE_ITEMS:
844 err = -ENODATA; break;
845 case CS_UNSUPPORTED_FUNCTION:
846 err = -ENOSYS; break;
847 default:
848 err = -EIO; break;
852 if (cmd & IOC_OUT) copy_to_user((char *)arg, (char *)&buf, size);
854 return err;
855 } /* ds_ioctl */
857 /*====================================================================*/
859 static struct file_operations ds_fops = {
860 owner: THIS_MODULE,
861 open: ds_open,
862 release: ds_release,
863 ioctl: ds_ioctl,
864 read: ds_read,
865 write: ds_write,
866 poll: ds_poll,
869 EXPORT_SYMBOL(register_pccard_driver);
870 EXPORT_SYMBOL(unregister_pccard_driver);
872 /*====================================================================*/
874 int __init init_pcmcia_ds(void)
876 client_reg_t client_reg;
877 servinfo_t serv;
878 bind_req_t bind;
879 socket_info_t *s;
880 int i, ret;
882 DEBUG(0, "%s\n", version);
885 * Ugly. But we want to wait for the socket threads to have started up.
886 * We really should let the drivers themselves drive some of this..
888 current->state = TASK_INTERRUPTIBLE;
889 schedule_timeout(HZ/10);
891 pcmcia_get_card_services_info(&serv);
892 if (serv.Revision != CS_RELEASE_CODE) {
893 printk(KERN_NOTICE "ds: Card Services release does not match!\n");
894 return -1;
896 if (serv.Count == 0) {
897 printk(KERN_NOTICE "ds: no socket drivers loaded!\n");
898 return -1;
901 sockets = serv.Count;
902 socket_table = kmalloc(sockets*sizeof(socket_info_t), GFP_KERNEL);
903 if (!socket_table) return -1;
904 for (i = 0, s = socket_table; i < sockets; i++, s++) {
905 s->state = 0;
906 s->user = NULL;
907 s->req_pending = 0;
908 init_waitqueue_head(&s->queue);
909 init_waitqueue_head(&s->request);
910 s->handle = NULL;
911 init_timer(&s->removal);
912 s->removal.data = i;
913 s->removal.function = &handle_removal;
914 s->bind = NULL;
917 /* Set up hotline to Card Services */
918 client_reg.dev_info = bind.dev_info = &dev_info;
919 client_reg.Attributes = INFO_MASTER_CLIENT;
920 client_reg.EventMask =
921 CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
922 CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
923 CS_EVENT_EJECTION_REQUEST | CS_EVENT_INSERTION_REQUEST |
924 CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
925 client_reg.event_handler = &ds_event;
926 client_reg.Version = 0x0210;
927 for (i = 0; i < sockets; i++) {
928 bind.Socket = i;
929 bind.Function = BIND_FN_ALL;
930 ret = pcmcia_bind_device(&bind);
931 if (ret != CS_SUCCESS) {
932 cs_error(NULL, BindDevice, ret);
933 break;
935 client_reg.event_callback_args.client_data = &socket_table[i];
936 ret = pcmcia_register_client(&socket_table[i].handle,
937 &client_reg);
938 if (ret != CS_SUCCESS) {
939 cs_error(NULL, RegisterClient, ret);
940 break;
944 /* Set up character device for user mode clients */
945 i = register_chrdev(0, "pcmcia", &ds_fops);
946 if (i == -EBUSY)
947 printk(KERN_NOTICE "unable to find a free device # for "
948 "Driver Services\n");
949 else
950 major_dev = i;
952 #ifdef CONFIG_PROC_FS
953 if (proc_pccard)
954 create_proc_read_entry("drivers",0,proc_pccard,proc_read_drivers,NULL);
955 init_status = 0;
956 #endif
957 return 0;
960 #ifdef MODULE
962 int __init init_module(void)
964 return init_pcmcia_ds();
967 void __exit cleanup_module(void)
969 int i;
970 #ifdef CONFIG_PROC_FS
971 if (proc_pccard)
972 remove_proc_entry("drivers", proc_pccard);
973 #endif
974 if (major_dev != -1)
975 unregister_chrdev(major_dev, "pcmcia");
976 for (i = 0; i < sockets; i++)
977 pcmcia_deregister_client(socket_table[i].handle);
978 sockets = 0;
979 kfree(socket_table);
982 #endif