static void avmcs_release(u_long arg)
{
    dev_link_t *link = (dev_link_t *)arg;

    /*
       If the device is currently in use, we won't release until it
       is actually closed.
    */
    if (link->open) {
	link->state |= DEV_STALE_CONFIG;
	return;
    }

    b1pcmcia_delcard(link->io.BasePort1, link->irq.AssignedIRQ);

    /* Unlink the device chain */
    link->dev = NULL;
    
    /* Don't bother checking to see if these succeed or not */
    CardServices(ReleaseConfiguration, link->handle);
    CardServices(ReleaseIO, link->handle, &link->io);
    CardServices(ReleaseIRQ, link->handle, &link->irq);
    link->state &= ~DEV_CONFIG;
    
    if (link->state & DEV_STALE_LINK)
	avmcs_detach(link);
    
} /* avmcs_release */
static void __exit avmcs_exit(void)
{
    unregister_pccard_driver(&dev_info);
    while (dev_list != NULL) {
	if (dev_list->state & DEV_CONFIG)
	    avmcs_release((u_long)dev_list);
	avmcs_detach(dev_list);
    }
}
Esempio n. 3
0
static void __exit avmcs_exit(void)
{
	pcmcia_unregister_driver(&avmcs_driver);

	/* XXX: this really needs to move into generic code.. */
	while (dev_list != NULL) {
		if (dev_list->state & DEV_CONFIG)
			avmcs_release(dev_list);
		avmcs_detach(dev_list);
	}
}
Esempio n. 4
0
static void avmcs_release(dev_link_t *link)
{
    b1pcmcia_delcard(link->io.BasePort1, link->irq.AssignedIRQ);

    /* Unlink the device chain */
    link->dev = NULL;
    
    /* Don't bother checking to see if these succeed or not */
    pcmcia_release_configuration(link->handle);
    pcmcia_release_io(link->handle, &link->io);
    pcmcia_release_irq(link->handle, &link->irq);
    link->state &= ~DEV_CONFIG;
    
    if (link->state & DEV_STALE_LINK)
	avmcs_detach(link);
    
} /* avmcs_release */
Esempio n. 5
0
static dev_link_t *avmcs_attach(void)
{
    client_reg_t client_reg;
    dev_link_t *link;
    local_info_t *local;
    int ret;
    
    /* Initialize the dev_link_t structure */
    link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
    if (!link)
        goto err;
    memset(link, 0, sizeof(struct dev_link_t));

    /* The io structure describes IO port mapping */
    link->io.NumPorts1 = 16;
    link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
    link->io.NumPorts2 = 0;

    /* Interrupt setup */
    link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
    link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED;

    link->irq.IRQInfo1 = IRQ_LEVEL_ID;
    
    /* General socket configuration */
    link->conf.Attributes = CONF_ENABLE_IRQ;
    link->conf.Vcc = 50;
    link->conf.IntType = INT_MEMORY_AND_IO;
    link->conf.ConfigIndex = 1;
    link->conf.Present = PRESENT_OPTION;

    /* Allocate space for private device-specific data */
    local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
    if (!local)
        goto err_kfree;
    memset(local, 0, sizeof(local_info_t));
    link->priv = local;
    
    /* Register with Card Services */
    link->next = dev_list;
    dev_list = link;
    client_reg.dev_info = &dev_info;
    client_reg.EventMask =
	CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
	CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
	CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
    client_reg.event_handler = &avmcs_event;
    client_reg.Version = 0x0210;
    client_reg.event_callback_args.client_data = link;
    ret = pcmcia_register_client(&link->handle, &client_reg);
    if (ret != 0) {
	cs_error(link->handle, RegisterClient, ret);
	avmcs_detach(link);
	goto err;
    }
    return link;

 err_kfree:
    kfree(link);
 err:
    return NULL;
} /* avmcs_attach */
static dev_link_t *avmcs_attach(void)
{
    client_reg_t client_reg;
    dev_link_t *link;
    local_info_t *local;
    int ret, i;
    
    /* Initialize the dev_link_t structure */
    link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
    if (!link)
	return NULL;
    memset(link, 0, sizeof(struct dev_link_t));
    link->release.function = &avmcs_release;
    link->release.data = (u_long)link;

    /* The io structure describes IO port mapping */
    link->io.NumPorts1 = 16;
    link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
    link->io.NumPorts2 = 0;

    /* Interrupt setup */
    link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
    link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED;

    link->irq.IRQInfo1 = IRQ_INFO2_VALID|IRQ_LEVEL_ID;
    if (irq_list[0] != -1) {
	    for (i = 0; i < 10 && irq_list[i] > 0; i++)
	       link->irq.IRQInfo2 |= 1 << irq_list[i];
    } else {
	    for (i = 0; i < 10 && default_irq_list[i] > 0; i++)
	       link->irq.IRQInfo2 |= 1 << default_irq_list[i];
    }
    
    /* General socket configuration */
    link->conf.Attributes = CONF_ENABLE_IRQ;
    link->conf.Vcc = 50;
    link->conf.IntType = INT_MEMORY_AND_IO;
    link->conf.ConfigIndex = 1;
    link->conf.Present = PRESENT_OPTION;

    /* Allocate space for private device-specific data */
    local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
    if (!local)
	return NULL;
    memset(local, 0, sizeof(local_info_t));
    link->priv = local;
    
    /* Register with Card Services */
    link->next = dev_list;
    dev_list = link;
    client_reg.dev_info = &dev_info;
    client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
    client_reg.EventMask =
	CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
	CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
	CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
    client_reg.event_handler = &avmcs_event;
    client_reg.Version = 0x0210;
    client_reg.event_callback_args.client_data = link;
    ret = CardServices(RegisterClient, &link->handle, &client_reg);
    if (ret != 0) {
	cs_error(link->handle, RegisterClient, ret);
	avmcs_detach(link);
	return NULL;
    }

    return link;
} /* avmcs_attach */