static void das08_pcmcia_detach(struct pcmcia_device *link) { dev_dbg(&link->dev, "das08_pcmcia_detach\n"); ((struct local_info_t *)link->priv)->stop = 1; das08_pcmcia_release(link); /* This points to the parent struct local_info_t struct */ kfree(link->priv); } /* das08_pcmcia_detach */
static void das08_pcmcia_detach(struct pcmcia_device *link) { DEBUG(0, "das08_pcmcia_detach(0x%p)\n", link); if (link->dev_node) { ((struct local_info_t *)link->priv)->stop = 1; das08_pcmcia_release(link); } /* This points to the parent struct local_info_t struct */ if (link->priv) kfree(link->priv); } /* das08_pcmcia_detach */
static void das08_pcmcia_config(struct pcmcia_device *link) { int ret; dev_dbg(&link->dev, "das08_pcmcia_config\n"); ret = pcmcia_loop_config(link, das08_pcmcia_config_loop, NULL); if (ret) { dev_warn(&link->dev, "no configuration found\n"); goto failed; } if (!link->irq) goto failed; /* This actually configures the PCMCIA socket -- setting up the I/O windows and the interrupt mapping, and putting the card and host interface into "Memory and IO" mode. */ ret = pcmcia_request_configuration(link, &link->conf); if (ret) goto failed; /* Finally, report what we've done */ dev_info(&link->dev, "index 0x%02x", link->conf.ConfigIndex); if (link->conf.Attributes & CONF_ENABLE_IRQ) printk(", irq %u", link->irq); if (link->io.NumPorts1) printk(", io 0x%04x-0x%04x", link->io.BasePort1, link->io.BasePort1 + link->io.NumPorts1 - 1); if (link->io.NumPorts2) printk(" & 0x%04x-0x%04x", link->io.BasePort2, link->io.BasePort2 + link->io.NumPorts2 - 1); printk("\n"); return; failed: das08_pcmcia_release(link); } /* das08_pcmcia_config */
static void das08_pcmcia_config(struct pcmcia_device *link) { struct local_info_t *dev = link->priv; tuple_t tuple; cisparse_t parse; int last_fn, last_ret; u_char buf[64]; cistpl_cftable_entry_t dflt = { 0 }; DEBUG(0, "das08_pcmcia_config(0x%p)\n", link); /* This reads the card's CONFIG tuple to find its configuration registers. */ tuple.DesiredTuple = CISTPL_CONFIG; tuple.Attributes = 0; tuple.TupleData = buf; tuple.TupleDataMax = sizeof(buf); tuple.TupleOffset = 0; last_fn = GetFirstTuple; last_ret = pcmcia_get_first_tuple(link, &tuple); if (last_ret) goto cs_failed; last_fn = GetTupleData; last_ret = pcmcia_get_tuple_data(link, &tuple); if (last_ret) goto cs_failed; last_fn = ParseTuple; last_ret = pcmcia_parse_tuple(&tuple, &parse); if (last_ret) goto cs_failed; link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; /* In this loop, we scan the CIS for configuration table entries, each of which describes a valid card configuration, including voltage, IO window, memory window, and interrupt settings. We make no assumptions about the card to be configured: we use just the information available in the CIS. In an ideal world, this would work for any PCMCIA card, but it requires a complete and accurate CIS. In practice, a driver usually "knows" most of these things without consulting the CIS, and most client drivers will only use the CIS to fill in implementation-defined details. */ tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; last_fn = GetFirstTuple; last_ret = pcmcia_get_first_tuple(link, &tuple); if (last_ret) goto cs_failed; while (1) { cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); last_ret = pcmcia_get_tuple_data(link, &tuple); if (last_ret) goto next_entry; last_ret = pcmcia_parse_tuple(&tuple, &parse); if (last_ret) goto next_entry; if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg; if (cfg->index == 0) goto next_entry; link->conf.ConfigIndex = cfg->index; /* Does this card need audio output? */ /* if (cfg->flags & CISTPL_CFTABLE_AUDIO) { link->conf.Attributes |= CONF_ENABLE_SPKR; link->conf.Status = CCSR_AUDIO_ENA; } */ /* Do we need to allocate an interrupt? */ if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1) link->conf.Attributes |= CONF_ENABLE_IRQ; /* IO window settings */ link->io.NumPorts1 = link->io.NumPorts2 = 0; if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; if (!(io->flags & CISTPL_IO_8BIT)) link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; if (!(io->flags & CISTPL_IO_16BIT)) link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; link->io.BasePort1 = io->win[0].base; link->io.NumPorts1 = io->win[0].len; if (io->nwin > 1) { link->io.Attributes2 = link->io.Attributes1; link->io.BasePort2 = io->win[1].base; link->io.NumPorts2 = io->win[1].len; } /* This reserves IO space but doesn't actually enable it */ if (pcmcia_request_io(link, &link->io) != 0) goto next_entry; } /* If we got this far, we're cool! */ break; next_entry: last_fn = GetNextTuple; last_ret = pcmcia_get_next_tuple(link, &tuple); if (last_ret) goto cs_failed; } if (link->conf.Attributes & CONF_ENABLE_IRQ) { last_fn = RequestIRQ; last_ret = pcmcia_request_irq(link, &link->irq); if (last_ret) goto cs_failed; } /* This actually configures the PCMCIA socket -- setting up the I/O windows and the interrupt mapping, and putting the card and host interface into "Memory and IO" mode. */ last_fn = RequestConfiguration; last_ret = pcmcia_request_configuration(link, &link->conf); if (last_ret) goto cs_failed; /* At this point, the dev_node_t structure(s) need to be initialized and arranged in a linked list at link->dev. */ sprintf(dev->node.dev_name, "pcm-das08"); dev->node.major = dev->node.minor = 0; link->dev_node = &dev->node; /* Finally, report what we've done */ printk(KERN_INFO "%s: index 0x%02x", dev->node.dev_name, link->conf.ConfigIndex); if (link->conf.Attributes & CONF_ENABLE_IRQ) printk(", irq %u", link->irq.AssignedIRQ); if (link->io.NumPorts1) printk(", io 0x%04x-0x%04x", link->io.BasePort1, link->io.BasePort1 + link->io.NumPorts1 - 1); if (link->io.NumPorts2) printk(" & 0x%04x-0x%04x", link->io.BasePort2, link->io.BasePort2 + link->io.NumPorts2 - 1); printk("\n"); return; cs_failed: cs_error(link, last_fn, last_ret); das08_pcmcia_release(link); } /* das08_pcmcia_config */
static void das08_pcmcia_config(struct pcmcia_device *link) { struct local_info_t *dev = link->priv; tuple_t tuple; cisparse_t parse; int last_fn, last_ret; u_char buf[64]; cistpl_cftable_entry_t dflt = { 0 }; DEBUG(0, "das08_pcmcia_config(0x%p)\n", link); tuple.DesiredTuple = CISTPL_CONFIG; tuple.Attributes = 0; tuple.TupleData = buf; tuple.TupleDataMax = sizeof(buf); tuple.TupleOffset = 0; last_fn = GetFirstTuple; last_ret = pcmcia_get_first_tuple(link, &tuple); if (last_ret) goto cs_failed; last_fn = GetTupleData; last_ret = pcmcia_get_tuple_data(link, &tuple); if (last_ret) goto cs_failed; last_fn = ParseTuple; last_ret = pcmcia_parse_tuple(&tuple, &parse); if (last_ret) goto cs_failed; link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; last_fn = GetFirstTuple; last_ret = pcmcia_get_first_tuple(link, &tuple); if (last_ret) goto cs_failed; while (1) { cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); last_ret = pcmcia_get_tuple_data(link, &tuple); if (last_ret) goto next_entry; last_ret = pcmcia_parse_tuple(&tuple, &parse); if (last_ret) goto next_entry; if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg; if (cfg->index == 0) goto next_entry; link->conf.ConfigIndex = cfg->index; if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1) link->conf.Attributes |= CONF_ENABLE_IRQ; link->io.NumPorts1 = link->io.NumPorts2 = 0; if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; if (!(io->flags & CISTPL_IO_8BIT)) link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; if (!(io->flags & CISTPL_IO_16BIT)) link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; link->io.BasePort1 = io->win[0].base; link->io.NumPorts1 = io->win[0].len; if (io->nwin > 1) { link->io.Attributes2 = link->io.Attributes1; link->io.BasePort2 = io->win[1].base; link->io.NumPorts2 = io->win[1].len; } if (pcmcia_request_io(link, &link->io) != 0) goto next_entry; } break; next_entry: last_fn = GetNextTuple; last_ret = pcmcia_get_next_tuple(link, &tuple); if (last_ret) goto cs_failed; } if (link->conf.Attributes & CONF_ENABLE_IRQ) { last_fn = RequestIRQ; last_ret = pcmcia_request_irq(link, &link->irq); if (last_ret) goto cs_failed; } last_fn = RequestConfiguration; last_ret = pcmcia_request_configuration(link, &link->conf); if (last_ret) goto cs_failed; sprintf(dev->node.dev_name, "pcm-das08"); dev->node.major = dev->node.minor = 0; link->dev_node = &dev->node; printk(KERN_INFO "%s: index 0x%02x", dev->node.dev_name, link->conf.ConfigIndex); if (link->conf.Attributes & CONF_ENABLE_IRQ) printk(", irq %u", link->irq.AssignedIRQ); if (link->io.NumPorts1) printk(", io 0x%04x-0x%04x", link->io.BasePort1, link->io.BasePort1 + link->io.NumPorts1 - 1); if (link->io.NumPorts2) printk(" & 0x%04x-0x%04x", link->io.BasePort2, link->io.BasePort2 + link->io.NumPorts2 - 1); printk("\n"); return; cs_failed: cs_error(link, last_fn, last_ret); das08_pcmcia_release(link); }