Esempio n. 1
0
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;
}
Esempio n. 2
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;
}
Esempio n. 3
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 */
Esempio n. 4
0
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 */