static int __devinit pcmcia_bus_add_socket(struct class_device *class_dev) { struct pcmcia_socket *socket = class_dev->class_data; client_reg_t client_reg; bind_req_t bind; struct pcmcia_bus_socket *s; int ret; s = kmalloc(sizeof(struct pcmcia_bus_socket), GFP_KERNEL); if(!s) return -ENOMEM; memset(s, 0, sizeof(struct pcmcia_bus_socket)); atomic_set(&s->refcount, 1); /* * Ugly. But we want to wait for the socket threads to have started up. * We really should let the drivers themselves drive some of this.. */ current->state = TASK_INTERRUPTIBLE; schedule_timeout(HZ/4); init_waitqueue_head(&s->queue); init_waitqueue_head(&s->request); /* initialize data */ INIT_WORK(&s->removal, handle_removal, s); s->parent = socket; /* Set up hotline to Card Services */ client_reg.dev_info = bind.dev_info = &dev_info; bind.Socket = socket; bind.Function = BIND_FN_ALL; ret = pcmcia_bind_device(&bind); if (ret != CS_SUCCESS) { cs_error(NULL, BindDevice, ret); kfree(s); return -EINVAL; } client_reg.Attributes = INFO_MASTER_CLIENT; client_reg.EventMask = CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | CS_EVENT_EJECTION_REQUEST | CS_EVENT_INSERTION_REQUEST | CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; client_reg.event_handler = &ds_event; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = s; ret = pcmcia_register_client(&s->handle, &client_reg); if (ret != CS_SUCCESS) { cs_error(NULL, RegisterClient, ret); kfree(s); return -EINVAL; } socket->pcmcia = s; return 0; }
int __init init_pcmcia_ds(void) { client_reg_t client_reg; servinfo_t serv; bind_req_t bind; socket_info_t *s; int i, ret; DEBUG(0, "%s\n", version); /* * Ugly. But we want to wait for the socket threads to have started up. * We really should let the drivers themselves drive some of this.. */ current->state = TASK_INTERRUPTIBLE; schedule_timeout(HZ/10); pcmcia_get_card_services_info(&serv); if (serv.Revision != CS_RELEASE_CODE) { printk(KERN_NOTICE "ds: Card Services release does not match!\n"); return -1; } if (serv.Count == 0) { printk(KERN_NOTICE "ds: no socket drivers loaded!\n"); return -1; } sockets = serv.Count; socket_table = kmalloc(sockets*sizeof(socket_info_t), GFP_KERNEL); if (!socket_table) return -1; for (i = 0, s = socket_table; i < sockets; i++, s++) { s->state = 0; s->user = NULL; s->req_pending = 0; init_waitqueue_head(&s->queue); init_waitqueue_head(&s->request); s->handle = NULL; init_timer(&s->removal); s->removal.data = i; s->removal.function = &handle_removal; s->bind = NULL; } /* Set up hotline to Card Services */ client_reg.dev_info = bind.dev_info = &dev_info; client_reg.Attributes = INFO_MASTER_CLIENT; client_reg.EventMask = CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | CS_EVENT_EJECTION_REQUEST | CS_EVENT_INSERTION_REQUEST | CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; client_reg.event_handler = &ds_event; client_reg.Version = 0x0210; for (i = 0; i < sockets; i++) { bind.Socket = i; bind.Function = BIND_FN_ALL; ret = pcmcia_bind_device(&bind); if (ret != CS_SUCCESS) { cs_error(NULL, BindDevice, ret); break; } client_reg.event_callback_args.client_data = &socket_table[i]; ret = pcmcia_register_client(&socket_table[i].handle, &client_reg); if (ret != CS_SUCCESS) { cs_error(NULL, RegisterClient, ret); break; } } /* Set up character device for user mode clients */ i = register_chrdev(0, "pcmcia", &ds_fops); if (i == -EBUSY) printk(KERN_NOTICE "unable to find a free device # for " "Driver Services\n"); else major_dev = i; #ifdef CONFIG_PROC_FS if (proc_pccard) create_proc_read_entry("drivers",0,proc_pccard,proc_read_drivers,NULL); init_status = 0; #endif return 0; }
static int bind_request(int i, bind_info_t *bind_info) { struct driver_info_t *driver; socket_bind_t *b; bind_req_t bind_req; socket_info_t *s = &socket_table[i]; int ret; DEBUG(2, "bind_request(%d, '%s')\n", i, (char *)bind_info->dev_info); for (driver = root_driver; driver; driver = driver->next) if (strcmp((char *)driver->dev_info, (char *)bind_info->dev_info) == 0) break; if (driver == NULL) { driver = kmalloc(sizeof(driver_info_t), GFP_KERNEL); if (!driver) return -ENOMEM; strncpy(driver->dev_info, bind_info->dev_info, DEV_NAME_LEN); driver->use_count = 0; driver->next = root_driver; driver->attach = NULL; driver->detach = NULL; root_driver = driver; } for (b = s->bind; b; b = b->next) if ((driver == b->driver) && (bind_info->function == b->function)) break; if (b != NULL) { bind_info->instance = b->instance; return -EBUSY; } bind_req.Socket = i; bind_req.Function = bind_info->function; bind_req.dev_info = &driver->dev_info; ret = pcmcia_bind_device(&bind_req); if (ret != CS_SUCCESS) { cs_error(NULL, BindDevice, ret); printk(KERN_NOTICE "ds: unable to bind '%s' to socket %d\n", (char *)dev_info, i); return -ENODEV; } /* Add binding to list for this socket */ driver->use_count++; b = kmalloc(sizeof(socket_bind_t), GFP_KERNEL); if (!b) { driver->use_count--; return -ENOMEM; } b->driver = driver; b->function = bind_info->function; b->instance = NULL; b->next = s->bind; s->bind = b; if (driver->attach) { b->instance = driver->attach(); if (b->instance == NULL) { printk(KERN_NOTICE "ds: unable to create instance " "of '%s'!\n", (char *)bind_info->dev_info); return -ENODEV; } } return 0; } /* bind_request */
static int bind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info) { struct pcmcia_driver *driver; socket_bind_t *b; bind_req_t bind_req; int ret; if (!s) return -EINVAL; ds_dbg(2, "bind_request(%d, '%s')\n", s->parent->sock, (char *)bind_info->dev_info); driver = get_pcmcia_driver(&bind_info->dev_info); if (!driver) return -EINVAL; for (b = s->bind; b; b = b->next) if ((driver == b->driver) && (bind_info->function == b->function)) break; if (b != NULL) { bind_info->instance = b->instance; return -EBUSY; } if (!try_module_get(driver->owner)) return -EINVAL; bind_req.Socket = s->parent; bind_req.Function = bind_info->function; bind_req.dev_info = (dev_info_t *) driver->drv.name; ret = pcmcia_bind_device(&bind_req); if (ret != CS_SUCCESS) { cs_error(NULL, BindDevice, ret); printk(KERN_NOTICE "ds: unable to bind '%s' to socket %d\n", (char *)dev_info, s->parent->sock); module_put(driver->owner); return -ENODEV; } /* Add binding to list for this socket */ driver->use_count++; b = kmalloc(sizeof(socket_bind_t), GFP_KERNEL); if (!b) { driver->use_count--; module_put(driver->owner); return -ENOMEM; } b->driver = driver; b->function = bind_info->function; b->instance = NULL; b->next = s->bind; s->bind = b; if (driver->attach) { b->instance = driver->attach(); if (b->instance == NULL) { printk(KERN_NOTICE "ds: unable to create instance " "of '%s'!\n", (char *)bind_info->dev_info); module_put(driver->owner); return -ENODEV; } } return 0; } /* bind_request */