1 /*======================================================================
2
3 PC Card Driver Services
4
5 ds.c 1.112 2001/10/13 00:08:28
6
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/
11
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.
16
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.
20
21 Alternatively, the contents of this file may be used under the
22 terms of the GNU General Public License version 2 (the "GPL"), in
23 which 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.
31
32 ======================================================================*/
33
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/slab.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>
51
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>
58
59 /*====================================================================*/
60
61 /* Module parameters */
62
63 MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
64 MODULE_DESCRIPTION("PCMCIA Driver Services " CS_RELEASE);
65 MODULE_LICENSE("Dual MPL/GPL");
66
67 #define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")
68
69 #ifdef PCMCIA_DEBUG
70 INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG);
71 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
72 static const char *version =
73 "ds.c 1.112 2001/10/13 00:08:28 (David Hinds)";
74 #else
75 #define DEBUG(n, args...)
76 #endif
77
78 /*====================================================================*/
79
80 typedef struct driver_info_t {
81 dev_info_t dev_info;
82 int use_count, status;
83 dev_link_t *(*attach)(void);
84 void (*detach)(dev_link_t *);
85 struct driver_info_t *next;
86 } driver_info_t;
87
88 typedef struct socket_bind_t {
89 driver_info_t *driver;
90 u_char function;
91 dev_link_t *instance;
92 struct socket_bind_t *next;
93 } socket_bind_t;
94
95 /* Device user information */
96 #define MAX_EVENTS 32
97 #define USER_MAGIC 0x7ea4
98 #define CHECK_USER(u) \
99 (((u) == NULL) || ((u)->user_magic != USER_MAGIC))
100 typedef struct user_info_t {
101 u_int user_magic;
102 int event_head, event_tail;
103 event_t event[MAX_EVENTS];
104 struct user_info_t *next;
105 } user_info_t;
106
107 /* Socket state information */
108 typedef struct socket_info_t {
109 client_handle_t handle;
110 int state;
111 user_info_t *user;
112 int req_pending, req_result;
113 wait_queue_head_t queue, request;
114 struct timer_list removal;
115 socket_bind_t *bind;
116 } socket_info_t;
117
118 #define SOCKET_PRESENT 0x01
119 #define SOCKET_BUSY 0x02
120 #define SOCKET_REMOVAL_PENDING 0x10
121
122 /*====================================================================*/
123
124 /* Device driver ID passed to Card Services */
125 static dev_info_t dev_info = "Driver Services";
126
127 /* Linked list of all registered device drivers */
128 static driver_info_t *root_driver = NULL;
129
130 static int sockets = 0, major_dev = -1;
131 static socket_info_t *socket_table = NULL;
132
133 extern struct proc_dir_entry *proc_pccard;
134
135 /* We use this to distinguish in-kernel from modular drivers */
136 static int init_status = 1;
137
138 /*====================================================================*/
139
cs_error(client_handle_t handle,int func,int ret)140 static void cs_error(client_handle_t handle, int func, int ret)
141 {
142 error_info_t err = { func, ret };
143 pcmcia_report_error(handle, &err);
144 }
145
146 /*======================================================================
147
148 Register_pccard_driver() and unregister_pccard_driver() are used
149 tell Driver Services that a PC Card client driver is available to
150 be bound to sockets.
151
152 ======================================================================*/
153
register_pccard_driver(dev_info_t * dev_info,dev_link_t * (* attach)(void),void (* detach)(dev_link_t *))154 int register_pccard_driver(dev_info_t *dev_info,
155 dev_link_t *(*attach)(void),
156 void (*detach)(dev_link_t *))
157 {
158 driver_info_t *driver;
159 socket_bind_t *b;
160 int i;
161
162 DEBUG(0, "ds: register_pccard_driver('%s')\n", (char *)dev_info);
163 for (driver = root_driver; driver; driver = driver->next)
164 if (strncmp((char *)dev_info, (char *)driver->dev_info,
165 DEV_NAME_LEN) == 0)
166 break;
167 if (!driver) {
168 driver = kmalloc(sizeof(driver_info_t), GFP_KERNEL);
169 if (!driver) return -ENOMEM;
170 strncpy(driver->dev_info, (char *)dev_info, DEV_NAME_LEN);
171 driver->use_count = 0;
172 driver->status = init_status;
173 driver->next = root_driver;
174 root_driver = driver;
175 }
176
177 driver->attach = attach;
178 driver->detach = detach;
179 if (driver->use_count == 0) return 0;
180
181 /* Instantiate any already-bound devices */
182 for (i = 0; i < sockets; i++)
183 for (b = socket_table[i].bind; b; b = b->next) {
184 if (b->driver != driver) continue;
185 b->instance = driver->attach();
186 if (b->instance == NULL)
187 printk(KERN_NOTICE "ds: unable to create instance "
188 "of '%s'!\n", driver->dev_info);
189 }
190
191 return 0;
192 } /* register_pccard_driver */
193
194 /*====================================================================*/
195
unregister_pccard_driver(dev_info_t * dev_info)196 int unregister_pccard_driver(dev_info_t *dev_info)
197 {
198 driver_info_t *target, **d = &root_driver;
199 socket_bind_t *b;
200 int i;
201
202 DEBUG(0, "ds: unregister_pccard_driver('%s')\n",
203 (char *)dev_info);
204 while ((*d) && (strncmp((*d)->dev_info, (char *)dev_info,
205 DEV_NAME_LEN) != 0))
206 d = &(*d)->next;
207 if (*d == NULL)
208 return -ENODEV;
209
210 target = *d;
211 if (target->use_count == 0) {
212 *d = target->next;
213 kfree(target);
214 } else {
215 /* Blank out any left-over device instances */
216 target->attach = NULL; target->detach = NULL;
217 for (i = 0; i < sockets; i++)
218 for (b = socket_table[i].bind; b; b = b->next)
219 if (b->driver == target) b->instance = NULL;
220 }
221 return 0;
222 } /* unregister_pccard_driver */
223
224 /*====================================================================*/
225
226 #ifdef CONFIG_PROC_FS
proc_read_drivers(char * buf,char ** start,off_t pos,int count,int * eof,void * data)227 static int proc_read_drivers(char *buf, char **start, off_t pos,
228 int count, int *eof, void *data)
229 {
230 driver_info_t *d;
231 char *p = buf;
232 for (d = root_driver; d; d = d->next)
233 p += sprintf(p, "%-24.24s %d %d\n", d->dev_info,
234 d->status, d->use_count);
235 return (p - buf);
236 }
237 #endif
238
239 /*======================================================================
240
241 These manage a ring buffer of events pending for one user process
242
243 ======================================================================*/
244
queue_empty(user_info_t * user)245 static int queue_empty(user_info_t *user)
246 {
247 return (user->event_head == user->event_tail);
248 }
249
get_queued_event(user_info_t * user)250 static event_t get_queued_event(user_info_t *user)
251 {
252 user->event_tail = (user->event_tail+1) % MAX_EVENTS;
253 return user->event[user->event_tail];
254 }
255
queue_event(user_info_t * user,event_t event)256 static void queue_event(user_info_t *user, event_t event)
257 {
258 user->event_head = (user->event_head+1) % MAX_EVENTS;
259 if (user->event_head == user->event_tail)
260 user->event_tail = (user->event_tail+1) % MAX_EVENTS;
261 user->event[user->event_head] = event;
262 }
263
handle_event(socket_info_t * s,event_t event)264 static void handle_event(socket_info_t *s, event_t event)
265 {
266 user_info_t *user;
267 for (user = s->user; user; user = user->next)
268 queue_event(user, event);
269 wake_up_interruptible(&s->queue);
270 }
271
handle_request(socket_info_t * s,event_t event)272 static int handle_request(socket_info_t *s, event_t event)
273 {
274 if (s->req_pending != 0)
275 return CS_IN_USE;
276 if (s->state & SOCKET_BUSY)
277 s->req_pending = 1;
278 handle_event(s, event);
279 if (s->req_pending > 0) {
280 interruptible_sleep_on(&s->request);
281 if (signal_pending(current))
282 return CS_IN_USE;
283 else
284 return s->req_result;
285 }
286 return CS_SUCCESS;
287 }
288
handle_removal(u_long sn)289 static void handle_removal(u_long sn)
290 {
291 socket_info_t *s = &socket_table[sn];
292 handle_event(s, CS_EVENT_CARD_REMOVAL);
293 s->state &= ~SOCKET_REMOVAL_PENDING;
294 }
295
296 /*======================================================================
297
298 The card status event handler.
299
300 ======================================================================*/
301
ds_event(event_t event,int priority,event_callback_args_t * args)302 static int ds_event(event_t event, int priority,
303 event_callback_args_t *args)
304 {
305 socket_info_t *s;
306 int i;
307
308 DEBUG(1, "ds: ds_event(0x%06x, %d, 0x%p)\n",
309 event, priority, args->client_handle);
310 s = args->client_data;
311 i = s - socket_table;
312
313 switch (event) {
314
315 case CS_EVENT_CARD_REMOVAL:
316 s->state &= ~SOCKET_PRESENT;
317 if (!(s->state & SOCKET_REMOVAL_PENDING)) {
318 s->state |= SOCKET_REMOVAL_PENDING;
319 s->removal.expires = jiffies + HZ/10;
320 add_timer(&s->removal);
321 }
322 break;
323
324 case CS_EVENT_CARD_INSERTION:
325 s->state |= SOCKET_PRESENT;
326 handle_event(s, event);
327 break;
328
329 case CS_EVENT_EJECTION_REQUEST:
330 return handle_request(s, event);
331 break;
332
333 default:
334 handle_event(s, event);
335 break;
336 }
337
338 return 0;
339 } /* ds_event */
340
341 /*======================================================================
342
343 bind_mtd() connects a memory region with an MTD client.
344
345 ======================================================================*/
346
bind_mtd(int i,mtd_info_t * mtd_info)347 static int bind_mtd(int i, mtd_info_t *mtd_info)
348 {
349 mtd_bind_t bind_req;
350 int ret;
351
352 bind_req.dev_info = &mtd_info->dev_info;
353 bind_req.Attributes = mtd_info->Attributes;
354 bind_req.Socket = i;
355 bind_req.CardOffset = mtd_info->CardOffset;
356 ret = pcmcia_bind_mtd(&bind_req);
357 if (ret != CS_SUCCESS) {
358 cs_error(NULL, BindMTD, ret);
359 printk(KERN_NOTICE "ds: unable to bind MTD '%s' to socket %d"
360 " offset 0x%x\n",
361 (char *)bind_req.dev_info, i, bind_req.CardOffset);
362 return -ENODEV;
363 }
364 return 0;
365 } /* bind_mtd */
366
367 /*======================================================================
368
369 bind_request() connects a socket to a particular client driver.
370 It looks up the specified device ID in the list of registered
371 drivers, binds it to the socket, and tries to create an instance
372 of the device. unbind_request() deletes a driver instance.
373
374 ======================================================================*/
375
bind_request(int i,bind_info_t * bind_info)376 static int bind_request(int i, bind_info_t *bind_info)
377 {
378 struct driver_info_t *driver;
379 socket_bind_t *b;
380 bind_req_t bind_req;
381 socket_info_t *s = &socket_table[i];
382 int ret;
383
384 DEBUG(2, "bind_request(%d, '%s')\n", i,
385 (char *)bind_info->dev_info);
386 for (driver = root_driver; driver; driver = driver->next)
387 if (strcmp((char *)driver->dev_info,
388 (char *)bind_info->dev_info) == 0)
389 break;
390 if (driver == NULL) {
391 driver = kmalloc(sizeof(driver_info_t), GFP_KERNEL);
392 if (!driver) return -ENOMEM;
393 strncpy(driver->dev_info, bind_info->dev_info, DEV_NAME_LEN);
394 driver->use_count = 0;
395 driver->next = root_driver;
396 driver->attach = NULL; driver->detach = NULL;
397 root_driver = driver;
398 }
399
400 for (b = s->bind; b; b = b->next)
401 if ((driver == b->driver) &&
402 (bind_info->function == b->function))
403 break;
404 if (b != NULL) {
405 bind_info->instance = b->instance;
406 return -EBUSY;
407 }
408
409 bind_req.Socket = i;
410 bind_req.Function = bind_info->function;
411 bind_req.dev_info = &driver->dev_info;
412 ret = pcmcia_bind_device(&bind_req);
413 if (ret != CS_SUCCESS) {
414 cs_error(NULL, BindDevice, ret);
415 printk(KERN_NOTICE "ds: unable to bind '%s' to socket %d\n",
416 (char *)dev_info, i);
417 return -ENODEV;
418 }
419
420 /* Add binding to list for this socket */
421 driver->use_count++;
422 b = kmalloc(sizeof(socket_bind_t), GFP_KERNEL);
423 if (!b)
424 {
425 driver->use_count--;
426 return -ENOMEM;
427 }
428 b->driver = driver;
429 b->function = bind_info->function;
430 b->instance = NULL;
431 b->next = s->bind;
432 s->bind = b;
433
434 if (driver->attach) {
435 b->instance = driver->attach();
436 if (b->instance == NULL) {
437 printk(KERN_NOTICE "ds: unable to create instance "
438 "of '%s'!\n", (char *)bind_info->dev_info);
439 return -ENODEV;
440 }
441 }
442
443 return 0;
444 } /* bind_request */
445
446 /*====================================================================*/
447
get_device_info(int i,bind_info_t * bind_info,int first)448 static int get_device_info(int i, bind_info_t *bind_info, int first)
449 {
450 socket_info_t *s = &socket_table[i];
451 socket_bind_t *b;
452 dev_node_t *node;
453
454 #ifdef CONFIG_CARDBUS
455 /*
456 * Some unbelievably ugly code to associate the PCI cardbus
457 * device and its driver with the PCMCIA "bind" information.
458 */
459 {
460 struct pci_bus *bus;
461
462 bus = pcmcia_lookup_bus(s->handle);
463 if (bus) {
464 struct list_head *list;
465 struct pci_dev *dev = NULL;
466
467 list = bus->devices.next;
468 while (list != &bus->devices) {
469 struct pci_dev *pdev = pci_dev_b(list);
470 list = list->next;
471
472 if (first) {
473 dev = pdev;
474 break;
475 }
476
477 /* Try to handle "next" here some way? */
478 }
479 if (dev && dev->driver) {
480 strncpy(bind_info->name, dev->driver->name, DEV_NAME_LEN);
481 bind_info->name[DEV_NAME_LEN-1] = '\0';
482 bind_info->major = 0;
483 bind_info->minor = 0;
484 bind_info->next = NULL;
485 return 0;
486 }
487 }
488 }
489 #endif
490
491 for (b = s->bind; b; b = b->next)
492 if ((strcmp((char *)b->driver->dev_info,
493 (char *)bind_info->dev_info) == 0) &&
494 (b->function == bind_info->function))
495 break;
496 if (b == NULL) return -ENODEV;
497 if ((b->instance == NULL) ||
498 (b->instance->state & DEV_CONFIG_PENDING))
499 return -EAGAIN;
500 if (first)
501 node = b->instance->dev;
502 else
503 for (node = b->instance->dev; node; node = node->next)
504 if (node == bind_info->next) break;
505 if (node == NULL) return -ENODEV;
506
507 strncpy(bind_info->name, node->dev_name, DEV_NAME_LEN);
508 bind_info->name[DEV_NAME_LEN-1] = '\0';
509 bind_info->major = node->major;
510 bind_info->minor = node->minor;
511 bind_info->next = node->next;
512
513 return 0;
514 } /* get_device_info */
515
516 /*====================================================================*/
517
unbind_request(int i,bind_info_t * bind_info)518 static int unbind_request(int i, bind_info_t *bind_info)
519 {
520 socket_info_t *s = &socket_table[i];
521 socket_bind_t **b, *c;
522
523 DEBUG(2, "unbind_request(%d, '%s')\n", i,
524 (char *)bind_info->dev_info);
525 for (b = &s->bind; *b; b = &(*b)->next)
526 if ((strcmp((char *)(*b)->driver->dev_info,
527 (char *)bind_info->dev_info) == 0) &&
528 ((*b)->function == bind_info->function))
529 break;
530 if (*b == NULL)
531 return -ENODEV;
532
533 c = *b;
534 c->driver->use_count--;
535 if (c->driver->detach) {
536 if (c->instance)
537 c->driver->detach(c->instance);
538 } else {
539 if (c->driver->use_count == 0) {
540 driver_info_t **d;
541 for (d = &root_driver; *d; d = &((*d)->next))
542 if (c->driver == *d) break;
543 *d = (*d)->next;
544 kfree(c->driver);
545 }
546 }
547 *b = c->next;
548 kfree(c);
549
550 return 0;
551 } /* unbind_request */
552
553 /*======================================================================
554
555 The user-mode PC Card device interface
556
557 ======================================================================*/
558
ds_open(struct inode * inode,struct file * file)559 static int ds_open(struct inode *inode, struct file *file)
560 {
561 socket_t i = MINOR(inode->i_rdev);
562 socket_info_t *s;
563 user_info_t *user;
564
565 DEBUG(0, "ds_open(socket %d)\n", i);
566 if ((i >= sockets) || (sockets == 0))
567 return -ENODEV;
568 s = &socket_table[i];
569 if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
570 if (s->state & SOCKET_BUSY)
571 return -EBUSY;
572 else
573 s->state |= SOCKET_BUSY;
574 }
575
576 user = kmalloc(sizeof(user_info_t), GFP_KERNEL);
577 if (!user) return -ENOMEM;
578 user->event_tail = user->event_head = 0;
579 user->next = s->user;
580 user->user_magic = USER_MAGIC;
581 s->user = user;
582 file->private_data = user;
583
584 if (s->state & SOCKET_PRESENT)
585 queue_event(user, CS_EVENT_CARD_INSERTION);
586 return 0;
587 } /* ds_open */
588
589 /*====================================================================*/
590
ds_release(struct inode * inode,struct file * file)591 static int ds_release(struct inode *inode, struct file *file)
592 {
593 socket_t i = MINOR(inode->i_rdev);
594 socket_info_t *s;
595 user_info_t *user, **link;
596
597 DEBUG(0, "ds_release(socket %d)\n", i);
598 if ((i >= sockets) || (sockets == 0))
599 return 0;
600 lock_kernel();
601 s = &socket_table[i];
602 user = file->private_data;
603 if (CHECK_USER(user))
604 goto out;
605
606 /* Unlink user data structure */
607 if ((file->f_flags & O_ACCMODE) != O_RDONLY)
608 s->state &= ~SOCKET_BUSY;
609 file->private_data = NULL;
610 for (link = &s->user; *link; link = &(*link)->next)
611 if (*link == user) break;
612 if (link == NULL)
613 goto out;
614 *link = user->next;
615 user->user_magic = 0;
616 kfree(user);
617 out:
618 unlock_kernel();
619 return 0;
620 } /* ds_release */
621
622 /*====================================================================*/
623
ds_read(struct file * file,char * buf,size_t count,loff_t * ppos)624 static ssize_t ds_read(struct file *file, char *buf,
625 size_t count, loff_t *ppos)
626 {
627 socket_t i = MINOR(file->f_dentry->d_inode->i_rdev);
628 socket_info_t *s;
629 user_info_t *user;
630
631 DEBUG(2, "ds_read(socket %d)\n", i);
632
633 if ((i >= sockets) || (sockets == 0))
634 return -ENODEV;
635 if (count < 4)
636 return -EINVAL;
637 s = &socket_table[i];
638 user = file->private_data;
639 if (CHECK_USER(user))
640 return -EIO;
641
642 if (queue_empty(user)) {
643 interruptible_sleep_on(&s->queue);
644 if (signal_pending(current))
645 return -EINTR;
646 }
647
648 return put_user(get_queued_event(user), (int *)buf) ? -EFAULT : 4;
649 } /* ds_read */
650
651 /*====================================================================*/
652
ds_write(struct file * file,const char * buf,size_t count,loff_t * ppos)653 static ssize_t ds_write(struct file *file, const char *buf,
654 size_t count, loff_t *ppos)
655 {
656 socket_t i = MINOR(file->f_dentry->d_inode->i_rdev);
657 socket_info_t *s;
658 user_info_t *user;
659
660 DEBUG(2, "ds_write(socket %d)\n", i);
661
662 if ((i >= sockets) || (sockets == 0))
663 return -ENODEV;
664 if (count != 4)
665 return -EINVAL;
666 if ((file->f_flags & O_ACCMODE) == O_RDONLY)
667 return -EBADF;
668 s = &socket_table[i];
669 user = file->private_data;
670 if (CHECK_USER(user))
671 return -EIO;
672
673 if (s->req_pending) {
674 s->req_pending--;
675 get_user(s->req_result, (int *)buf);
676 if ((s->req_result != 0) || (s->req_pending == 0))
677 wake_up_interruptible(&s->request);
678 } else
679 return -EIO;
680
681 return 4;
682 } /* ds_write */
683
684 /*====================================================================*/
685
686 /* No kernel lock - fine */
ds_poll(struct file * file,poll_table * wait)687 static u_int ds_poll(struct file *file, poll_table *wait)
688 {
689 socket_t i = MINOR(file->f_dentry->d_inode->i_rdev);
690 socket_info_t *s;
691 user_info_t *user;
692
693 DEBUG(2, "ds_poll(socket %d)\n", i);
694
695 if ((i >= sockets) || (sockets == 0))
696 return POLLERR;
697 s = &socket_table[i];
698 user = file->private_data;
699 if (CHECK_USER(user))
700 return POLLERR;
701 poll_wait(file, &s->queue, wait);
702 if (!queue_empty(user))
703 return POLLIN | POLLRDNORM;
704 return 0;
705 } /* ds_poll */
706
707 /*====================================================================*/
708
ds_ioctl(struct inode * inode,struct file * file,u_int cmd,u_long arg)709 static int ds_ioctl(struct inode * inode, struct file * file,
710 u_int cmd, u_long arg)
711 {
712 socket_t i = MINOR(inode->i_rdev);
713 socket_info_t *s;
714 u_int size;
715 int ret, err;
716 ds_ioctl_arg_t buf;
717
718 DEBUG(2, "ds_ioctl(socket %d, %#x, %#lx)\n", i, cmd, arg);
719
720 if ((i >= sockets) || (sockets == 0))
721 return -ENODEV;
722 s = &socket_table[i];
723
724 size = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT;
725 if (size > sizeof(ds_ioctl_arg_t)) return -EINVAL;
726
727 /* Permission check */
728 if (!(cmd & IOC_OUT) && !capable(CAP_SYS_ADMIN))
729 return -EPERM;
730
731 if (cmd & IOC_IN) {
732 err = verify_area(VERIFY_READ, (char *)arg, size);
733 if (err) {
734 DEBUG(3, "ds_ioctl(): verify_read = %d\n", err);
735 return err;
736 }
737 }
738 if (cmd & IOC_OUT) {
739 err = verify_area(VERIFY_WRITE, (char *)arg, size);
740 if (err) {
741 DEBUG(3, "ds_ioctl(): verify_write = %d\n", err);
742 return err;
743 }
744 }
745
746 err = ret = 0;
747
748 if (cmd & IOC_IN) copy_from_user((char *)&buf, (char *)arg, size);
749
750 switch (cmd) {
751 case DS_ADJUST_RESOURCE_INFO:
752 ret = pcmcia_adjust_resource_info(s->handle, &buf.adjust);
753 break;
754 case DS_GET_CARD_SERVICES_INFO:
755 ret = pcmcia_get_card_services_info(&buf.servinfo);
756 break;
757 case DS_GET_CONFIGURATION_INFO:
758 ret = pcmcia_get_configuration_info(s->handle, &buf.config);
759 break;
760 case DS_GET_FIRST_TUPLE:
761 ret = pcmcia_get_first_tuple(s->handle, &buf.tuple);
762 break;
763 case DS_GET_NEXT_TUPLE:
764 ret = pcmcia_get_next_tuple(s->handle, &buf.tuple);
765 break;
766 case DS_GET_TUPLE_DATA:
767 buf.tuple.TupleData = buf.tuple_parse.data;
768 buf.tuple.TupleDataMax = sizeof(buf.tuple_parse.data);
769 ret = pcmcia_get_tuple_data(s->handle, &buf.tuple);
770 break;
771 case DS_PARSE_TUPLE:
772 buf.tuple.TupleData = buf.tuple_parse.data;
773 ret = pcmcia_parse_tuple(s->handle, &buf.tuple, &buf.tuple_parse.parse);
774 break;
775 case DS_RESET_CARD:
776 ret = pcmcia_reset_card(s->handle, NULL);
777 break;
778 case DS_GET_STATUS:
779 ret = pcmcia_get_status(s->handle, &buf.status);
780 break;
781 case DS_VALIDATE_CIS:
782 ret = pcmcia_validate_cis(s->handle, &buf.cisinfo);
783 break;
784 case DS_SUSPEND_CARD:
785 ret = pcmcia_suspend_card(s->handle, NULL);
786 break;
787 case DS_RESUME_CARD:
788 ret = pcmcia_resume_card(s->handle, NULL);
789 break;
790 case DS_EJECT_CARD:
791 ret = pcmcia_eject_card(s->handle, NULL);
792 break;
793 case DS_INSERT_CARD:
794 ret = pcmcia_insert_card(s->handle, NULL);
795 break;
796 case DS_ACCESS_CONFIGURATION_REGISTER:
797 if ((buf.conf_reg.Action == CS_WRITE) && !capable(CAP_SYS_ADMIN))
798 return -EPERM;
799 ret = pcmcia_access_configuration_register(s->handle, &buf.conf_reg);
800 break;
801 case DS_GET_FIRST_REGION:
802 ret = pcmcia_get_first_region(s->handle, &buf.region);
803 break;
804 case DS_GET_NEXT_REGION:
805 ret = pcmcia_get_next_region(s->handle, &buf.region);
806 break;
807 case DS_GET_FIRST_WINDOW:
808 buf.win_info.handle = (window_handle_t)s->handle;
809 ret = pcmcia_get_first_window(&buf.win_info.handle, &buf.win_info.window);
810 break;
811 case DS_GET_NEXT_WINDOW:
812 ret = pcmcia_get_next_window(&buf.win_info.handle, &buf.win_info.window);
813 break;
814 case DS_GET_MEM_PAGE:
815 ret = pcmcia_get_mem_page(buf.win_info.handle,
816 &buf.win_info.map);
817 break;
818 case DS_REPLACE_CIS:
819 ret = pcmcia_replace_cis(s->handle, &buf.cisdump);
820 break;
821 case DS_BIND_REQUEST:
822 if (!capable(CAP_SYS_ADMIN)) return -EPERM;
823 err = bind_request(i, &buf.bind_info);
824 break;
825 case DS_GET_DEVICE_INFO:
826 err = get_device_info(i, &buf.bind_info, 1);
827 break;
828 case DS_GET_NEXT_DEVICE:
829 err = get_device_info(i, &buf.bind_info, 0);
830 break;
831 case DS_UNBIND_REQUEST:
832 err = unbind_request(i, &buf.bind_info);
833 break;
834 case DS_BIND_MTD:
835 if (!suser()) return -EPERM;
836 err = bind_mtd(i, &buf.mtd_info);
837 break;
838 default:
839 err = -EINVAL;
840 }
841
842 if ((err == 0) && (ret != CS_SUCCESS)) {
843 DEBUG(2, "ds_ioctl: ret = %d\n", ret);
844 switch (ret) {
845 case CS_BAD_SOCKET: case CS_NO_CARD:
846 err = -ENODEV; break;
847 case CS_BAD_ARGS: case CS_BAD_ATTRIBUTE: case CS_BAD_IRQ:
848 case CS_BAD_TUPLE:
849 err = -EINVAL; break;
850 case CS_IN_USE:
851 err = -EBUSY; break;
852 case CS_OUT_OF_RESOURCE:
853 err = -ENOSPC; break;
854 case CS_NO_MORE_ITEMS:
855 err = -ENODATA; break;
856 case CS_UNSUPPORTED_FUNCTION:
857 err = -ENOSYS; break;
858 default:
859 err = -EIO; break;
860 }
861 }
862
863 if (cmd & IOC_OUT) copy_to_user((char *)arg, (char *)&buf, size);
864
865 return err;
866 } /* ds_ioctl */
867
868 /*====================================================================*/
869
870 static struct file_operations ds_fops = {
871 owner: THIS_MODULE,
872 open: ds_open,
873 release: ds_release,
874 ioctl: ds_ioctl,
875 read: ds_read,
876 write: ds_write,
877 poll: ds_poll,
878 };
879
880 EXPORT_SYMBOL(register_pccard_driver);
881 EXPORT_SYMBOL(unregister_pccard_driver);
882
883 /*====================================================================*/
884
init_pcmcia_ds(void)885 int __init init_pcmcia_ds(void)
886 {
887 client_reg_t client_reg;
888 servinfo_t serv;
889 bind_req_t bind;
890 socket_info_t *s;
891 int i, ret;
892
893 DEBUG(0, "%s\n", version);
894
895 /*
896 * Ugly. But we want to wait for the socket threads to have started up.
897 * We really should let the drivers themselves drive some of this..
898 */
899 current->state = TASK_INTERRUPTIBLE;
900 schedule_timeout(HZ/10);
901
902 pcmcia_get_card_services_info(&serv);
903 if (serv.Revision != CS_RELEASE_CODE) {
904 printk(KERN_NOTICE "ds: Card Services release does not match!\n");
905 return -1;
906 }
907 if (serv.Count == 0) {
908 printk(KERN_NOTICE "ds: no socket drivers loaded!\n");
909 return -1;
910 }
911
912 sockets = serv.Count;
913 socket_table = kmalloc(sockets*sizeof(socket_info_t), GFP_KERNEL);
914 if (!socket_table) return -1;
915 for (i = 0, s = socket_table; i < sockets; i++, s++) {
916 s->state = 0;
917 s->user = NULL;
918 s->req_pending = 0;
919 init_waitqueue_head(&s->queue);
920 init_waitqueue_head(&s->request);
921 s->handle = NULL;
922 init_timer(&s->removal);
923 s->removal.data = i;
924 s->removal.function = &handle_removal;
925 s->bind = NULL;
926 }
927
928 /* Set up hotline to Card Services */
929 client_reg.dev_info = bind.dev_info = &dev_info;
930 client_reg.Attributes = INFO_MASTER_CLIENT;
931 client_reg.EventMask =
932 CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
933 CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
934 CS_EVENT_EJECTION_REQUEST | CS_EVENT_INSERTION_REQUEST |
935 CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
936 client_reg.event_handler = &ds_event;
937 client_reg.Version = 0x0210;
938 for (i = 0; i < sockets; i++) {
939 bind.Socket = i;
940 bind.Function = BIND_FN_ALL;
941 ret = pcmcia_bind_device(&bind);
942 if (ret != CS_SUCCESS) {
943 cs_error(NULL, BindDevice, ret);
944 break;
945 }
946 client_reg.event_callback_args.client_data = &socket_table[i];
947 ret = pcmcia_register_client(&socket_table[i].handle,
948 &client_reg);
949 if (ret != CS_SUCCESS) {
950 cs_error(NULL, RegisterClient, ret);
951 break;
952 }
953 }
954
955 /* Set up character device for user mode clients */
956 i = register_chrdev(0, "pcmcia", &ds_fops);
957 if (i == -EBUSY)
958 printk(KERN_NOTICE "unable to find a free device # for "
959 "Driver Services\n");
960 else
961 major_dev = i;
962
963 #ifdef CONFIG_PROC_FS
964 if (proc_pccard)
965 create_proc_read_entry("drivers",0,proc_pccard,proc_read_drivers,NULL);
966 init_status = 0;
967 #endif
968 return 0;
969 }
970
971 #ifdef MODULE
972
init_module(void)973 int __init init_module(void)
974 {
975 return init_pcmcia_ds();
976 }
977
cleanup_module(void)978 void __exit cleanup_module(void)
979 {
980 int i;
981 #ifdef CONFIG_PROC_FS
982 if (proc_pccard)
983 remove_proc_entry("drivers", proc_pccard);
984 #endif
985 if (major_dev != -1)
986 unregister_chrdev(major_dev, "pcmcia");
987 for (i = 0; i < sockets; i++)
988 pcmcia_deregister_client(socket_table[i].handle);
989 sockets = 0;
990 kfree(socket_table);
991 }
992
993 #endif
994