1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21#include <linux/kernel.h>
22#include <linux/module.h>
23#include <linux/init.h>
24#include <linux/major.h>
25#include <linux/errno.h>
26#include <linux/ioctl.h>
27#include <linux/proc_fs.h>
28#include <linux/poll.h>
29#include <linux/pci.h>
30#include <linux/smp_lock.h>
31#include <linux/workqueue.h>
32
33#include <pcmcia/cs_types.h>
34#include <pcmcia/cs.h>
35#include <pcmcia/cistpl.h>
36#include <pcmcia/cisreg.h>
37#include <pcmcia/ds.h>
38#include <pcmcia/ss.h>
39
40#include "cs_internal.h"
41#include "ds_internal.h"
42
43static int major_dev = -1;
44
45
46
47#define MAX_EVENTS 32
48#define USER_MAGIC 0x7ea4
49#define CHECK_USER(u) \
50 (((u) == NULL) || ((u)->user_magic != USER_MAGIC))
51
52typedef 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
62extern int ds_pc_debug;
63
64#define ds_dbg(lvl, fmt, arg...) do { \
65 if (ds_pc_debug >= lvl) \
66 printk(KERN_DEBUG "ds: " fmt , ## arg); \
67} while (0)
68#else
69#define ds_dbg(lvl, fmt, arg...) do { } while (0)
70#endif
71
72static struct pcmcia_device *get_pcmcia_device(struct pcmcia_socket *s,
73 unsigned int function)
74{
75 struct pcmcia_device *p_dev = NULL;
76 unsigned long flags;
77
78 spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
79 list_for_each_entry(p_dev, &s->devices_list, socket_device_list) {
80 if (p_dev->func == function) {
81 spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
82 return pcmcia_get_dev(p_dev);
83 }
84 }
85 spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
86 return NULL;
87}
88
89
90
91static struct pcmcia_driver *get_pcmcia_driver(dev_info_t *dev_info)
92{
93 struct device_driver *drv;
94 struct pcmcia_driver *p_drv;
95
96 drv = driver_find((char *) dev_info, &pcmcia_bus_type);
97 if (!drv)
98 return NULL;
99
100 p_drv = container_of(drv, struct pcmcia_driver, drv);
101
102 return (p_drv);
103}
104
105
106#ifdef CONFIG_PROC_FS
107static struct proc_dir_entry *proc_pccard = NULL;
108
109static int proc_read_drivers_callback(struct device_driver *driver, void *d)
110{
111 char **p = d;
112 struct pcmcia_driver *p_drv = container_of(driver,
113 struct pcmcia_driver, drv);
114
115 *p += sprintf(*p, "%-24.24s 1 %d\n", p_drv->drv.name,
116#ifdef CONFIG_MODULE_UNLOAD
117 (p_drv->owner) ? module_refcount(p_drv->owner) : 1
118#else
119 1
120#endif
121 );
122 d = (void *) p;
123
124 return 0;
125}
126
127static int proc_read_drivers(char *buf, char **start, off_t pos,
128 int count, int *eof, void *data)
129{
130 char *p = buf;
131 int rc;
132
133 rc = bus_for_each_drv(&pcmcia_bus_type, NULL,
134 (void *) &p, proc_read_drivers_callback);
135 if (rc < 0)
136 return rc;
137
138 return (p - buf);
139}
140#endif
141
142
143#ifdef CONFIG_PCMCIA_PROBE
144
145static int adjust_irq(struct pcmcia_socket *s, adjust_t *adj)
146{
147 int irq;
148 u32 mask;
149
150 irq = adj->resource.irq.IRQ;
151 if ((irq < 0) || (irq > 15))
152 return CS_BAD_IRQ;
153
154 if (adj->Action != REMOVE_MANAGED_RESOURCE)
155 return 0;
156
157 mask = 1 << irq;
158
159 if (!(s->irq_mask & mask))
160 return 0;
161
162 s->irq_mask &= ~mask;
163
164 return 0;
165}
166
167#else
168
169static inline int adjust_irq(struct pcmcia_socket *s, adjust_t *adj) {
170 return CS_SUCCESS;
171}
172
173#endif
174
175static int pcmcia_adjust_resource_info(adjust_t *adj)
176{
177 struct pcmcia_socket *s;
178 int ret = CS_UNSUPPORTED_FUNCTION;
179 unsigned long flags;
180
181 down_read(&pcmcia_socket_list_rwsem);
182 list_for_each_entry(s, &pcmcia_socket_list, socket_list) {
183
184 if (adj->Resource == RES_IRQ)
185 ret = adjust_irq(s, adj);
186
187 else if (s->resource_ops->add_io) {
188 unsigned long begin, end;
189
190
191
192 spin_lock_irqsave(&s->lock, flags);
193 if ((s->resource_setup_new) &&
194 !(s->resource_setup_old)) {
195 spin_unlock_irqrestore(&s->lock, flags);
196 continue;
197 } else if (!(s->resource_setup_old))
198 s->resource_setup_old = 1;
199 spin_unlock_irqrestore(&s->lock, flags);
200
201 switch (adj->Resource) {
202 case RES_MEMORY_RANGE:
203 begin = adj->resource.memory.Base;
204 end = adj->resource.memory.Base + adj->resource.memory.Size - 1;
205 if (s->resource_ops->add_mem)
206 ret =s->resource_ops->add_mem(s, adj->Action, begin, end);
207 case RES_IO_RANGE:
208 begin = adj->resource.io.BasePort;
209 end = adj->resource.io.BasePort + adj->resource.io.NumPorts - 1;
210 if (s->resource_ops->add_io)
211 ret = s->resource_ops->add_io(s, adj->Action, begin, end);
212 }
213 if (!ret) {
214
215
216
217
218 spin_lock_irqsave(&s->lock, flags);
219 s->resource_setup_done = 1;
220 spin_unlock_irqrestore(&s->lock, flags);
221 }
222 }
223 }
224 up_read(&pcmcia_socket_list_rwsem);
225
226 return (ret);
227}
228
229
230
231
232
233
234
235static int pccard_get_status(struct pcmcia_socket *s,
236 struct pcmcia_device *p_dev,
237 cs_status_t *status)
238{
239 config_t *c;
240 int val;
241
242 s->ops->get_status(s, &val);
243 status->CardState = status->SocketState = 0;
244 status->CardState |= (val & SS_DETECT) ? CS_EVENT_CARD_DETECT : 0;
245 status->CardState |= (val & SS_CARDBUS) ? CS_EVENT_CB_DETECT : 0;
246 status->CardState |= (val & SS_3VCARD) ? CS_EVENT_3VCARD : 0;
247 status->CardState |= (val & SS_XVCARD) ? CS_EVENT_XVCARD : 0;
248 if (s->state & SOCKET_SUSPEND)
249 status->CardState |= CS_EVENT_PM_SUSPEND;
250 if (!(s->state & SOCKET_PRESENT))
251 return CS_NO_CARD;
252
253 c = (p_dev) ? p_dev->function_config : NULL;
254
255 if ((c != NULL) && (c->state & CONFIG_LOCKED) &&
256 (c->IntType & (INT_MEMORY_AND_IO | INT_ZOOMED_VIDEO))) {
257 u_char reg;
258 if (c->CardValues & PRESENT_PIN_REPLACE) {
259 pcmcia_read_cis_mem(s, 1, (c->ConfigBase+CISREG_PRR)>>1, 1, ®);
260 status->CardState |=
261 (reg & PRR_WP_STATUS) ? CS_EVENT_WRITE_PROTECT : 0;
262 status->CardState |=
263 (reg & PRR_READY_STATUS) ? CS_EVENT_READY_CHANGE : 0;
264 status->CardState |=
265 (reg & PRR_BVD2_STATUS) ? CS_EVENT_BATTERY_LOW : 0;
266 status->CardState |=
267 (reg & PRR_BVD1_STATUS) ? CS_EVENT_BATTERY_DEAD : 0;
268 } else {
269
270 status->CardState |= CS_EVENT_READY_CHANGE;
271 }
272 if (c->CardValues & PRESENT_EXT_STATUS) {
273 pcmcia_read_cis_mem(s, 1, (c->ConfigBase+CISREG_ESR)>>1, 1, ®);
274 status->CardState |=
275 (reg & ESR_REQ_ATTN) ? CS_EVENT_REQUEST_ATTENTION : 0;
276 }
277 return CS_SUCCESS;
278 }
279 status->CardState |=
280 (val & SS_WRPROT) ? CS_EVENT_WRITE_PROTECT : 0;
281 status->CardState |=
282 (val & SS_BATDEAD) ? CS_EVENT_BATTERY_DEAD : 0;
283 status->CardState |=
284 (val & SS_BATWARN) ? CS_EVENT_BATTERY_LOW : 0;
285 status->CardState |=
286 (val & SS_READY) ? CS_EVENT_READY_CHANGE : 0;
287 return CS_SUCCESS;
288}
289
290
291
292
293
294
295
296
297static int queue_empty(user_info_t *user)
298{
299 return (user->event_head == user->event_tail);
300}
301
302static event_t get_queued_event(user_info_t *user)
303{
304 user->event_tail = (user->event_tail+1) % MAX_EVENTS;
305 return user->event[user->event_tail];
306}
307
308static void queue_event(user_info_t *user, event_t event)
309{
310 user->event_head = (user->event_head+1) % MAX_EVENTS;
311 if (user->event_head == user->event_tail)
312 user->event_tail = (user->event_tail+1) % MAX_EVENTS;
313 user->event[user->event_head] = event;
314}
315
316void handle_event(struct pcmcia_socket *s, event_t event)
317{
318 user_info_t *user;
319 for (user = s->user; user; user = user->next)
320 queue_event(user, event);
321 wake_up_interruptible(&s->queue);
322}
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348static int bind_request(struct pcmcia_socket *s, bind_info_t *bind_info)
349{
350 struct pcmcia_driver *p_drv;
351 struct pcmcia_device *p_dev;
352 int ret = 0;
353 unsigned long flags;
354
355 s = pcmcia_get_socket(s);
356 if (!s)
357 return -EINVAL;
358
359 ds_dbg(2, "bind_request(%d, '%s')\n", s->sock,
360 (char *)bind_info->dev_info);
361
362 p_drv = get_pcmcia_driver(&bind_info->dev_info);
363 if (!p_drv) {
364 ret = -EINVAL;
365 goto err_put;
366 }
367
368 if (!try_module_get(p_drv->owner)) {
369 ret = -EINVAL;
370 goto err_put_driver;
371 }
372
373 spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
374 list_for_each_entry(p_dev, &s->devices_list, socket_device_list) {
375 if (p_dev->func == bind_info->function) {
376 if ((p_dev->dev.driver == &p_drv->drv)) {
377 if (p_dev->cardmgr) {
378
379
380
381
382 spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
383 bind_info->instance = p_dev;
384 ret = -EBUSY;
385 goto err_put_module;
386 } else {
387
388
389
390 spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
391 p_dev->cardmgr = p_drv;
392 ret = 0;
393 goto err_put_module;
394 }
395 } else if (!p_dev->dev.driver) {
396
397
398
399 spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
400 goto rescan;
401 }
402 }
403 }
404 spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
405
406 p_dev = pcmcia_device_add(s, bind_info->function);
407 if (!p_dev) {
408 ret = -EIO;
409 goto err_put_module;
410 }
411
412rescan:
413 p_dev->cardmgr = p_drv;
414
415
416 if (p_dev->dev.driver)
417 goto err_put_module;
418
419
420
421
422 mutex_lock(&s->skt_mutex);
423 ret = bus_rescan_devices(&pcmcia_bus_type);
424 mutex_unlock(&s->skt_mutex);
425 if (ret)
426 goto err_put_module;
427
428
429
430
431
432 if (!(p_dev->dev.driver == &p_drv->drv))
433 p_dev->cardmgr = NULL;
434
435 err_put_module:
436 module_put(p_drv->owner);
437 err_put_driver:
438 put_driver(&p_drv->drv);
439 err_put:
440 pcmcia_put_socket(s);
441
442 return (ret);
443}
444
445#ifdef CONFIG_CARDBUS
446
447static struct pci_bus *pcmcia_lookup_bus(struct pcmcia_socket *s)
448{
449 if (!s || !(s->state & SOCKET_CARDBUS))
450 return NULL;
451
452 return s->cb_dev->subordinate;
453}
454#endif
455
456static int get_device_info(struct pcmcia_socket *s, bind_info_t *bind_info, int first)
457{
458 dev_node_t *node;
459 struct pcmcia_device *p_dev;
460 struct pcmcia_driver *p_drv;
461 unsigned long flags;
462 int ret = 0;
463
464#ifdef CONFIG_CARDBUS
465
466
467
468
469 {
470 struct pci_bus *bus;
471
472 bus = pcmcia_lookup_bus(s);
473 if (bus) {
474 struct list_head *list;
475 struct pci_dev *dev = NULL;
476
477 list = bus->devices.next;
478 while (list != &bus->devices) {
479 struct pci_dev *pdev = pci_dev_b(list);
480 list = list->next;
481
482 if (first) {
483 dev = pdev;
484 break;
485 }
486
487
488 }
489 if (dev && dev->driver) {
490 strlcpy(bind_info->name, dev->driver->name, DEV_NAME_LEN);
491 bind_info->major = 0;
492 bind_info->minor = 0;
493 bind_info->next = NULL;
494 return 0;
495 }
496 }
497 }
498#endif
499
500 spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
501 list_for_each_entry(p_dev, &s->devices_list, socket_device_list) {
502 if (p_dev->func == bind_info->function) {
503 p_dev = pcmcia_get_dev(p_dev);
504 if (!p_dev)
505 continue;
506 goto found;
507 }
508 }
509 spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
510 return -ENODEV;
511
512 found:
513 spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
514
515 p_drv = to_pcmcia_drv(p_dev->dev.driver);
516 if (p_drv && !p_dev->_locked) {
517 ret = -EAGAIN;
518 goto err_put;
519 }
520
521 if (first)
522 node = p_dev->dev_node;
523 else
524 for (node = p_dev->dev_node; node; node = node->next)
525 if (node == bind_info->next)
526 break;
527 if (!node) {
528 ret = -ENODEV;
529 goto err_put;
530 }
531
532 strlcpy(bind_info->name, node->dev_name, DEV_NAME_LEN);
533 bind_info->major = node->major;
534 bind_info->minor = node->minor;
535 bind_info->next = node->next;
536
537 err_put:
538 pcmcia_put_dev(p_dev);
539 return (ret);
540}
541
542
543static int ds_open(struct inode *inode, struct file *file)
544{
545 socket_t i = iminor(inode);
546 struct pcmcia_socket *s;
547 user_info_t *user;
548 static int warning_printed = 0;
549 int ret = 0;
550
551 ds_dbg(0, "ds_open(socket %d)\n", i);
552
553 lock_kernel();
554 s = pcmcia_get_socket_by_nr(i);
555 if (!s) {
556 ret = -ENODEV;
557 goto out;
558 }
559 s = pcmcia_get_socket(s);
560 if (!s) {
561 ret = -ENODEV;
562 goto out;
563 }
564
565 if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
566 if (s->pcmcia_state.busy) {
567 pcmcia_put_socket(s);
568 ret = -EBUSY;
569 goto out;
570 }
571 else
572 s->pcmcia_state.busy = 1;
573 }
574
575 user = kmalloc(sizeof(user_info_t), GFP_KERNEL);
576 if (!user) {
577 pcmcia_put_socket(s);
578 ret = -ENOMEM;
579 goto out;
580 }
581 user->event_tail = user->event_head = 0;
582 user->next = s->user;
583 user->user_magic = USER_MAGIC;
584 user->socket = s;
585 s->user = user;
586 file->private_data = user;
587
588 if (!warning_printed) {
589 printk(KERN_INFO "pcmcia: Detected deprecated PCMCIA ioctl "
590 "usage from process: %s.\n", current->comm);
591 printk(KERN_INFO "pcmcia: This interface will soon be removed from "
592 "the kernel; please expect breakage unless you upgrade "
593 "to new tools.\n");
594 printk(KERN_INFO "pcmcia: see http://www.kernel.org/pub/linux/"
595 "utils/kernel/pcmcia/pcmcia.html for details.\n");
596 warning_printed = 1;
597 }
598
599 if (s->pcmcia_state.present)
600 queue_event(user, CS_EVENT_CARD_INSERTION);
601out:
602 unlock_kernel();
603 return ret;
604}
605
606
607
608static int ds_release(struct inode *inode, struct file *file)
609{
610 struct pcmcia_socket *s;
611 user_info_t *user, **link;
612
613 ds_dbg(0, "ds_release(socket %d)\n", iminor(inode));
614
615 user = file->private_data;
616 if (CHECK_USER(user))
617 goto out;
618
619 s = user->socket;
620
621
622 if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
623 s->pcmcia_state.busy = 0;
624 }
625 file->private_data = NULL;
626 for (link = &s->user; *link; link = &(*link)->next)
627 if (*link == user) break;
628 if (link == NULL)
629 goto out;
630 *link = user->next;
631 user->user_magic = 0;
632 kfree(user);
633 pcmcia_put_socket(s);
634out:
635 return 0;
636}
637
638
639
640static ssize_t ds_read(struct file *file, char __user *buf,
641 size_t count, loff_t *ppos)
642{
643 struct pcmcia_socket *s;
644 user_info_t *user;
645 int ret;
646
647 ds_dbg(2, "ds_read(socket %d)\n", iminor(file->f_path.dentry->d_inode));
648
649 if (count < 4)
650 return -EINVAL;
651
652 user = file->private_data;
653 if (CHECK_USER(user))
654 return -EIO;
655
656 s = user->socket;
657 if (s->pcmcia_state.dead)
658 return -EIO;
659
660 ret = wait_event_interruptible(s->queue, !queue_empty(user));
661 if (ret == 0)
662 ret = put_user(get_queued_event(user), (int __user *)buf) ? -EFAULT : 4;
663
664 return ret;
665}
666
667
668
669static ssize_t ds_write(struct file *file, const char __user *buf,
670 size_t count, loff_t *ppos)
671{
672 ds_dbg(2, "ds_write(socket %d)\n", iminor(file->f_path.dentry->d_inode));
673
674 if (count != 4)
675 return -EINVAL;
676 if ((file->f_flags & O_ACCMODE) == O_RDONLY)
677 return -EBADF;
678
679 return -EIO;
680}
681
682
683
684
685static u_int ds_poll(struct file *file, poll_table *wait)
686{
687 struct pcmcia_socket *s;
688 user_info_t *user;
689
690 ds_dbg(2, "ds_poll(socket %d)\n", iminor(file->f_path.dentry->d_inode));
691
692 user = file->private_data;
693 if (CHECK_USER(user))
694 return POLLERR;
695 s = user->socket;
696
697
698
699
700 poll_wait(file, &s->queue, wait);
701 if (!queue_empty(user))
702 return POLLIN | POLLRDNORM;
703 return 0;
704}
705
706
707
708static int ds_ioctl(struct inode * inode, struct file * file,
709 u_int cmd, u_long arg)
710{
711 struct pcmcia_socket *s;
712 void __user *uarg = (char __user *)arg;
713 u_int size;
714 int ret, err;
715 ds_ioctl_arg_t *buf;
716 user_info_t *user;
717
718 ds_dbg(2, "ds_ioctl(socket %d, %#x, %#lx)\n", iminor(inode), cmd, arg);
719
720 user = file->private_data;
721 if (CHECK_USER(user))
722 return -EIO;
723
724 s = user->socket;
725 if (s->pcmcia_state.dead)
726 return -EIO;
727
728 size = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT;
729 if (size > sizeof(ds_ioctl_arg_t)) return -EINVAL;
730
731
732 if (!(cmd & IOC_OUT) && !capable(CAP_SYS_ADMIN))
733 return -EPERM;
734
735 if (cmd & IOC_IN) {
736 if (!access_ok(VERIFY_READ, uarg, size)) {
737 ds_dbg(3, "ds_ioctl(): verify_read = %d\n", -EFAULT);
738 return -EFAULT;
739 }
740 }
741 if (cmd & IOC_OUT) {
742 if (!access_ok(VERIFY_WRITE, uarg, size)) {
743 ds_dbg(3, "ds_ioctl(): verify_write = %d\n", -EFAULT);
744 return -EFAULT;
745 }
746 }
747 buf = kmalloc(sizeof(ds_ioctl_arg_t), GFP_KERNEL);
748 if (!buf)
749 return -ENOMEM;
750
751 err = ret = 0;
752
753 if (cmd & IOC_IN) {
754 if (__copy_from_user((char *)buf, uarg, size)) {
755 err = -EFAULT;
756 goto free_out;
757 }
758 }
759
760 switch (cmd) {
761 case DS_ADJUST_RESOURCE_INFO:
762 ret = pcmcia_adjust_resource_info(&buf->adjust);
763 break;
764 case DS_GET_CONFIGURATION_INFO:
765 if (buf->config.Function &&
766 (buf->config.Function >= s->functions))
767 ret = CS_BAD_ARGS;
768 else {
769 struct pcmcia_device *p_dev = get_pcmcia_device(s, buf->config.Function);
770 ret = pccard_get_configuration_info(s, p_dev, &buf->config);
771 pcmcia_put_dev(p_dev);
772 }
773 break;
774 case DS_GET_FIRST_TUPLE:
775 mutex_lock(&s->skt_mutex);
776 pcmcia_validate_mem(s);
777 mutex_unlock(&s->skt_mutex);
778 ret = pccard_get_first_tuple(s, BIND_FN_ALL, &buf->tuple);
779 break;
780 case DS_GET_NEXT_TUPLE:
781 ret = pccard_get_next_tuple(s, BIND_FN_ALL, &buf->tuple);
782 break;
783 case DS_GET_TUPLE_DATA:
784 buf->tuple.TupleData = buf->tuple_parse.data;
785 buf->tuple.TupleDataMax = sizeof(buf->tuple_parse.data);
786 ret = pccard_get_tuple_data(s, &buf->tuple);
787 break;
788 case DS_PARSE_TUPLE:
789 buf->tuple.TupleData = buf->tuple_parse.data;
790 ret = pccard_parse_tuple(&buf->tuple, &buf->tuple_parse.parse);
791 break;
792 case DS_RESET_CARD:
793 ret = pccard_reset_card(s);
794 break;
795 case DS_GET_STATUS:
796 if (buf->status.Function &&
797 (buf->status.Function >= s->functions))
798 ret = CS_BAD_ARGS;
799 else {
800 struct pcmcia_device *p_dev = get_pcmcia_device(s, buf->status.Function);
801 ret = pccard_get_status(s, p_dev, &buf->status);
802 pcmcia_put_dev(p_dev);
803 }
804 break;
805 case DS_VALIDATE_CIS:
806 mutex_lock(&s->skt_mutex);
807 pcmcia_validate_mem(s);
808 mutex_unlock(&s->skt_mutex);
809 ret = pccard_validate_cis(s, BIND_FN_ALL, &buf->cisinfo.Chains);
810 break;
811 case DS_SUSPEND_CARD:
812 ret = pcmcia_suspend_card(s);
813 break;
814 case DS_RESUME_CARD:
815 ret = pcmcia_resume_card(s);
816 break;
817 case DS_EJECT_CARD:
818 err = pcmcia_eject_card(s);
819 break;
820 case DS_INSERT_CARD:
821 err = pcmcia_insert_card(s);
822 break;
823 case DS_ACCESS_CONFIGURATION_REGISTER:
824 if ((buf->conf_reg.Action == CS_WRITE) && !capable(CAP_SYS_ADMIN)) {
825 err = -EPERM;
826 goto free_out;
827 }
828
829 ret = CS_BAD_ARGS;
830
831 if (!(buf->conf_reg.Function &&
832 (buf->conf_reg.Function >= s->functions))) {
833 struct pcmcia_device *p_dev = get_pcmcia_device(s, buf->conf_reg.Function);
834 if (p_dev) {
835 ret = pcmcia_access_configuration_register(p_dev, &buf->conf_reg);
836 pcmcia_put_dev(p_dev);
837 }
838 }
839 break;
840 case DS_GET_FIRST_REGION:
841 case DS_GET_NEXT_REGION:
842 case DS_BIND_MTD:
843 if (!capable(CAP_SYS_ADMIN)) {
844 err = -EPERM;
845 goto free_out;
846 } else {
847 static int printed = 0;
848 if (!printed) {
849 printk(KERN_WARNING "2.6. kernels use pcmciamtd instead of memory_cs.c and do not require special\n");
850 printk(KERN_WARNING "MTD handling any more.\n");
851 printed++;
852 }
853 }
854 err = -EINVAL;
855 goto free_out;
856 break;
857 case DS_GET_FIRST_WINDOW:
858 ret = pcmcia_get_window(s, &buf->win_info.handle, 0,
859 &buf->win_info.window);
860 break;
861 case DS_GET_NEXT_WINDOW:
862 ret = pcmcia_get_window(s, &buf->win_info.handle,
863 buf->win_info.handle->index + 1, &buf->win_info.window);
864 break;
865 case DS_GET_MEM_PAGE:
866 ret = pcmcia_get_mem_page(buf->win_info.handle,
867 &buf->win_info.map);
868 break;
869 case DS_REPLACE_CIS:
870 ret = pcmcia_replace_cis(s, &buf->cisdump);
871 break;
872 case DS_BIND_REQUEST:
873 if (!capable(CAP_SYS_ADMIN)) {
874 err = -EPERM;
875 goto free_out;
876 }
877 err = bind_request(s, &buf->bind_info);
878 break;
879 case DS_GET_DEVICE_INFO:
880 err = get_device_info(s, &buf->bind_info, 1);
881 break;
882 case DS_GET_NEXT_DEVICE:
883 err = get_device_info(s, &buf->bind_info, 0);
884 break;
885 case DS_UNBIND_REQUEST:
886 err = 0;
887 break;
888 default:
889 err = -EINVAL;
890 }
891
892 if ((err == 0) && (ret != CS_SUCCESS)) {
893 ds_dbg(2, "ds_ioctl: ret = %d\n", ret);
894 switch (ret) {
895 case CS_BAD_SOCKET: case CS_NO_CARD:
896 err = -ENODEV; break;
897 case CS_BAD_ARGS: case CS_BAD_ATTRIBUTE: case CS_BAD_IRQ:
898 case CS_BAD_TUPLE:
899 err = -EINVAL; break;
900 case CS_IN_USE:
901 err = -EBUSY; break;
902 case CS_OUT_OF_RESOURCE:
903 err = -ENOSPC; break;
904 case CS_NO_MORE_ITEMS:
905 err = -ENODATA; break;
906 case CS_UNSUPPORTED_FUNCTION:
907 err = -ENOSYS; break;
908 default:
909 err = -EIO; break;
910 }
911 }
912
913 if (cmd & IOC_OUT) {
914 if (__copy_to_user(uarg, (char *)buf, size))
915 err = -EFAULT;
916 }
917
918free_out:
919 kfree(buf);
920 return err;
921}
922
923
924
925static const struct file_operations ds_fops = {
926 .owner = THIS_MODULE,
927 .open = ds_open,
928 .release = ds_release,
929 .ioctl = ds_ioctl,
930 .read = ds_read,
931 .write = ds_write,
932 .poll = ds_poll,
933};
934
935void __init pcmcia_setup_ioctl(void) {
936 int i;
937
938
939 i = register_chrdev(0, "pcmcia", &ds_fops);
940 if (i < 0)
941 printk(KERN_NOTICE "unable to find a free device # for "
942 "Driver Services (error=%d)\n", i);
943 else
944 major_dev = i;
945
946#ifdef CONFIG_PROC_FS
947 proc_pccard = proc_mkdir("bus/pccard", NULL);
948 if (proc_pccard)
949 create_proc_read_entry("drivers",0,proc_pccard,proc_read_drivers,NULL);
950#endif
951}
952
953
954void __exit pcmcia_cleanup_ioctl(void) {
955#ifdef CONFIG_PROC_FS
956 if (proc_pccard) {
957 remove_proc_entry("drivers", proc_pccard);
958 remove_proc_entry("bus/pccard", NULL);
959 }
960#endif
961 if (major_dev != -1)
962 unregister_chrdev(major_dev, "pcmcia");
963}
964