static int avmcs_event(event_t event, int priority, event_callback_args_t *args) { dev_link_t *link = args->client_data; switch (event) { case CS_EVENT_CARD_REMOVAL: link->state &= ~DEV_PRESENT; if (link->state & DEV_CONFIG) avmcs_release(link); break; case CS_EVENT_CARD_INSERTION: link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; avmcs_config(link); break; case CS_EVENT_PM_SUSPEND: link->state |= DEV_SUSPEND; /* Fall through... */ case CS_EVENT_RESET_PHYSICAL: if (link->state & DEV_CONFIG) pcmcia_release_configuration(link->handle); break; case CS_EVENT_PM_RESUME: link->state &= ~DEV_SUSPEND; /* Fall through... */ case CS_EVENT_CARD_RESET: if (link->state & DEV_CONFIG) pcmcia_request_configuration(link->handle, &link->conf); break; } return 0; } /* avmcs_event */
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); } }
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); } }
static void avmcs_config(dev_link_t *link) { client_handle_t handle; tuple_t tuple; cisparse_t parse; cistpl_cftable_entry_t *cf = &parse.cftable_entry; local_info_t *dev; int i; u_char buf[64]; char devname[128]; int cardtype; int (*addcard)(unsigned int port, unsigned irq); handle = link->handle; dev = link->priv; /* This reads the card's CONFIG tuple to find its configuration registers. */ do { tuple.DesiredTuple = CISTPL_CONFIG; i = pcmcia_get_first_tuple(handle, &tuple); if (i != CS_SUCCESS) break; tuple.TupleData = buf; tuple.TupleDataMax = 64; tuple.TupleOffset = 0; i = pcmcia_get_tuple_data(handle, &tuple); if (i != CS_SUCCESS) break; i = pcmcia_parse_tuple(handle, &tuple, &parse); if (i != CS_SUCCESS) break; link->conf.ConfigBase = parse.config.base; } while (0); if (i != CS_SUCCESS) { cs_error(link->handle, ParseTuple, i); link->state &= ~DEV_CONFIG_PENDING; return; } /* Configure card */ link->state |= DEV_CONFIG; do { tuple.Attributes = 0; tuple.TupleData = buf; tuple.TupleDataMax = 254; tuple.TupleOffset = 0; tuple.DesiredTuple = CISTPL_VERS_1; devname[0] = 0; if( !first_tuple(handle, &tuple, &parse) && parse.version_1.ns > 1 ) { strlcpy(devname,parse.version_1.str + parse.version_1.ofs[1], sizeof(devname)); } /* * find IO port */ tuple.TupleData = (cisdata_t *)buf; tuple.TupleOffset = 0; tuple.TupleDataMax = 255; tuple.Attributes = 0; tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; i = first_tuple(handle, &tuple, &parse); while (i == CS_SUCCESS) { if (cf->io.nwin > 0) { link->conf.ConfigIndex = cf->index; link->io.BasePort1 = cf->io.win[0].base; link->io.NumPorts1 = cf->io.win[0].len; link->io.NumPorts2 = 0; printk(KERN_INFO "avm_cs: testing i/o %#x-%#x\n", link->io.BasePort1, link->io.BasePort1+link->io.NumPorts1-1); i = pcmcia_request_io(link->handle, &link->io); if (i == CS_SUCCESS) goto found_port; } i = next_tuple(handle, &tuple, &parse); } found_port: if (i != CS_SUCCESS) { cs_error(link->handle, RequestIO, i); break; } /* * allocate an interrupt line */ i = pcmcia_request_irq(link->handle, &link->irq); if (i != CS_SUCCESS) { cs_error(link->handle, RequestIRQ, i); pcmcia_release_io(link->handle, &link->io); break; } /* * configure the PCMCIA socket */ i = pcmcia_request_configuration(link->handle, &link->conf); if (i != CS_SUCCESS) { cs_error(link->handle, RequestConfiguration, i); pcmcia_release_io(link->handle, &link->io); pcmcia_release_irq(link->handle, &link->irq); break; } } while (0); /* At this point, the dev_node_t structure(s) should be initialized and arranged in a linked list at link->dev. */ if (devname[0]) { char *s = strrchr(devname, ' '); if (!s) s = devname; else s++; strcpy(dev->node.dev_name, s); if (strcmp("M1", s) == 0) { cardtype = AVM_CARDTYPE_M1; } else if (strcmp("M2", s) == 0) { cardtype = AVM_CARDTYPE_M2; } else { cardtype = AVM_CARDTYPE_B1; } } else { strcpy(dev->node.dev_name, "b1"); cardtype = AVM_CARDTYPE_B1; } dev->node.major = 64; dev->node.minor = 0; link->dev = &dev->node; link->state &= ~DEV_CONFIG_PENDING; /* If any step failed, release any partially configured state */ if (i != 0) { avmcs_release(link); return; } switch (cardtype) { case AVM_CARDTYPE_M1: addcard = b1pcmcia_addcard_m1; break; case AVM_CARDTYPE_M2: addcard = b1pcmcia_addcard_m2; break; default: case AVM_CARDTYPE_B1: addcard = b1pcmcia_addcard_b1; break; } if ((i = (*addcard)(link->io.BasePort1, link->irq.AssignedIRQ)) < 0) { printk(KERN_ERR "avm_cs: failed to add AVM-%s-Controller at i/o %#x, irq %d\n", dev->node.dev_name, link->io.BasePort1, link->irq.AssignedIRQ); avmcs_release(link); return; } dev->node.minor = i; } /* avmcs_config */
static int avmcs_config(struct pcmcia_device *link) { local_info_t *dev; int i; char devname[128]; int cardtype; int (*addcard)(unsigned int port, unsigned irq); dev = link->priv; devname[0] = 0; if (link->prod_id[1]) strlcpy(devname, link->prod_id[1], sizeof(devname)); /* * find IO port */ if (pcmcia_loop_config(link, avmcs_configcheck, NULL)) return -ENODEV; do { /* * allocate an interrupt line */ i = pcmcia_request_irq(link, &link->irq); if (i != 0) { /* undo */ pcmcia_disable_device(link); break; } /* * configure the PCMCIA socket */ i = pcmcia_request_configuration(link, &link->conf); if (i != 0) { pcmcia_disable_device(link); break; } } while (0); /* At this point, the dev_node_t structure(s) should be initialized and arranged in a linked list at link->dev. */ if (devname[0]) { char *s = strrchr(devname, ' '); if (!s) s = devname; else s++; strcpy(dev->node.dev_name, s); if (strcmp("M1", s) == 0) { cardtype = AVM_CARDTYPE_M1; } else if (strcmp("M2", s) == 0) { cardtype = AVM_CARDTYPE_M2; } else { cardtype = AVM_CARDTYPE_B1; } } else { strcpy(dev->node.dev_name, "b1"); cardtype = AVM_CARDTYPE_B1; } dev->node.major = 64; dev->node.minor = 0; link->dev_node = &dev->node; /* If any step failed, release any partially configured state */ if (i != 0) { avmcs_release(link); return -ENODEV; } switch (cardtype) { case AVM_CARDTYPE_M1: addcard = b1pcmcia_addcard_m1; break; case AVM_CARDTYPE_M2: addcard = b1pcmcia_addcard_m2; break; default: case AVM_CARDTYPE_B1: addcard = b1pcmcia_addcard_b1; break; } if ((i = (*addcard)(link->io.BasePort1, link->irq.AssignedIRQ)) < 0) { printk(KERN_ERR "avm_cs: failed to add AVM-%s-Controller at i/o %#x, irq %d\n", dev->node.dev_name, link->io.BasePort1, link->irq.AssignedIRQ); avmcs_release(link); return -ENODEV; } dev->node.minor = i; return 0; } /* avmcs_config */
static void avmcs_detach(struct pcmcia_device *link) { avmcs_release(link); kfree(link->priv); } /* avmcs_detach */
static int avmcs_config(struct pcmcia_device *link) { tuple_t tuple; cisparse_t parse; cistpl_cftable_entry_t *cf = &parse.cftable_entry; local_info_t *dev; int i; u_char buf[64]; char devname[128]; int cardtype; int (*addcard)(unsigned int port, unsigned irq); dev = link->priv; do { devname[0] = 0; if (link->prod_id[1]) strlcpy(devname, link->prod_id[1], sizeof(devname)); /* * find IO port */ tuple.TupleData = (cisdata_t *)buf; tuple.TupleOffset = 0; tuple.TupleDataMax = 255; tuple.Attributes = 0; tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; i = first_tuple(link, &tuple, &parse); while (i == CS_SUCCESS) { if (cf->io.nwin > 0) { link->conf.ConfigIndex = cf->index; link->io.BasePort1 = cf->io.win[0].base; link->io.NumPorts1 = cf->io.win[0].len; link->io.NumPorts2 = 0; printk(KERN_INFO "avm_cs: testing i/o %#x-%#x\n", link->io.BasePort1, link->io.BasePort1+link->io.NumPorts1-1); i = pcmcia_request_io(link, &link->io); if (i == CS_SUCCESS) goto found_port; } i = next_tuple(link, &tuple, &parse); } found_port: if (i != CS_SUCCESS) { cs_error(link, RequestIO, i); break; } /* * allocate an interrupt line */ i = pcmcia_request_irq(link, &link->irq); if (i != CS_SUCCESS) { cs_error(link, RequestIRQ, i); /* undo */ pcmcia_disable_device(link); break; } /* * configure the PCMCIA socket */ i = pcmcia_request_configuration(link, &link->conf); if (i != CS_SUCCESS) { cs_error(link, RequestConfiguration, i); pcmcia_disable_device(link); break; } } while (0); /* At this point, the dev_node_t structure(s) should be initialized and arranged in a linked list at link->dev. */ if (devname[0]) { char *s = strrchr(devname, ' '); if (!s) s = devname; else s++; strcpy(dev->node.dev_name, s); if (strcmp("M1", s) == 0) { cardtype = AVM_CARDTYPE_M1; } else if (strcmp("M2", s) == 0) { cardtype = AVM_CARDTYPE_M2; } else { cardtype = AVM_CARDTYPE_B1; } } else { strcpy(dev->node.dev_name, "b1"); cardtype = AVM_CARDTYPE_B1; } dev->node.major = 64; dev->node.minor = 0; link->dev_node = &dev->node; /* If any step failed, release any partially configured state */ if (i != 0) { avmcs_release(link); return -ENODEV; } switch (cardtype) { case AVM_CARDTYPE_M1: addcard = b1pcmcia_addcard_m1; break; case AVM_CARDTYPE_M2: addcard = b1pcmcia_addcard_m2; break; default: case AVM_CARDTYPE_B1: addcard = b1pcmcia_addcard_b1; break; } if ((i = (*addcard)(link->io.BasePort1, link->irq.AssignedIRQ)) < 0) { printk(KERN_ERR "avm_cs: failed to add AVM-%s-Controller at i/o %#x, irq %d\n", dev->node.dev_name, link->io.BasePort1, link->irq.AssignedIRQ); avmcs_release(link); return -ENODEV; } dev->node.minor = i; return 0; } /* avmcs_config */
static int avmcs_config(struct pcmcia_device *link) { int i = -1; char devname[128]; int cardtype; int (*addcard)(unsigned int port, unsigned irq); devname[0] = 0; if (link->prod_id[1]) strlcpy(devname, link->prod_id[1], sizeof(devname)); /* * find IO port */ if (pcmcia_loop_config(link, avmcs_configcheck, NULL)) return -ENODEV; do { if (!link->irq) { /* undo */ pcmcia_disable_device(link); break; } /* * configure the PCMCIA socket */ i = pcmcia_request_configuration(link, &link->conf); if (i != 0) { pcmcia_disable_device(link); break; } } while (0); if (devname[0]) { char *s = strrchr(devname, ' '); if (!s) s = devname; else s++; if (strcmp("M1", s) == 0) { cardtype = AVM_CARDTYPE_M1; } else if (strcmp("M2", s) == 0) { cardtype = AVM_CARDTYPE_M2; } else { cardtype = AVM_CARDTYPE_B1; } } else cardtype = AVM_CARDTYPE_B1; /* If any step failed, release any partially configured state */ if (i != 0) { avmcs_release(link); return -ENODEV; } switch (cardtype) { case AVM_CARDTYPE_M1: addcard = b1pcmcia_addcard_m1; break; case AVM_CARDTYPE_M2: addcard = b1pcmcia_addcard_m2; break; default: case AVM_CARDTYPE_B1: addcard = b1pcmcia_addcard_b1; break; } if ((i = (*addcard)(link->io.BasePort1, link->irq)) < 0) { dev_err(&link->dev, "avm_cs: failed to add AVM-Controller at i/o %#x, irq %d\n", link->io.BasePort1, link->irq); avmcs_release(link); return -ENODEV; } return 0; } /* avmcs_config */