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