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 63MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>"); 64MODULE_DESCRIPTION("PCMCIA Driver Services " CS_RELEASE); 65MODULE_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 70INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG); 71#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) 72static 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 80typedef 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 88typedef 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)) 100typedef 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 */ 108typedef 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 */ 125static dev_info_t dev_info = "Driver Services"; 126 127/* Linked list of all registered device drivers */ 128static driver_info_t *root_driver = NULL; 129 130static int sockets = 0, major_dev = -1; 131static socket_info_t *socket_table = NULL; 132 133extern struct proc_dir_entry *proc_pccard; 134 135/* We use this to distinguish in-kernel from modular drivers */ 136static int init_status = 1; 137 138/*====================================================================*/ 139 140static 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 154int 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 196int 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 227static 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 245static int queue_empty(user_info_t *user) 246{ 247 return (user->event_head == user->event_tail); 248} 249 250static 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 256static 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 264static 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 272static 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 289static 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 302static 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 347static 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 376static 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 448static 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 518static 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 559static 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 591static 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); 617out: 618 unlock_kernel(); 619 return 0; 620} /* ds_release */ 621 622/*====================================================================*/ 623 624static 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 653static 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 */ 687static 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 709static 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 870static 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 880EXPORT_SYMBOL(register_pccard_driver); 881EXPORT_SYMBOL(unregister_pccard_driver); 882 883/*====================================================================*/ 884 885int __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 973int __init init_module(void) 974{ 975 return init_pcmcia_ds(); 976} 977 978void __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