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