/* read/write{8,16} copy_{from,to} routines with window remapping to access whole card */ static caddr_t remap_window(struct map_info *map, unsigned long to) { struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1; window_handle_t win = (window_handle_t)map->map_priv_2; memreq_t mrq; int ret; if(!(dev->link.state & DEV_PRESENT)) { DEBUG(1, "device removed state = 0x%4.4X", dev->link.state); return 0; } mrq.CardOffset = to & ~(dev->win_size-1); if(mrq.CardOffset != dev->offset) { DEBUG(2, "Remapping window from 0x%8.8x to 0x%8.8x", dev->offset, mrq.CardOffset); mrq.Page = 0; if( (ret = pcmcia_map_mem_page(win, &mrq)) != CS_SUCCESS) { cs_error(dev->link.handle, MapMemPage, ret); return NULL; } dev->offset = mrq.CardOffset; } return dev->win_base + (to & (dev->win_size-1)); }
static hw_info_t *get_hwinfo(struct pcmcia_device *link) { struct net_device *dev = link->priv; u_char __iomem *base, *virt; int i, j; /* Allocate a small memory window */ link->resource[2]->flags |= WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE; link->resource[2]->start = 0; link->resource[2]->end = 0; i = pcmcia_request_window(link, link->resource[2], 0); if (i != 0) return NULL; virt = ioremap(link->resource[2]->start, resource_size(link->resource[2])); for (i = 0; i < NR_INFO; i++) { pcmcia_map_mem_page(link, link->resource[2], hw_info[i].offset & ~(resource_size(link->resource[2])-1)); base = &virt[hw_info[i].offset & (resource_size(link->resource[2])-1)]; if ((readb(base+0) == hw_info[i].a0) && (readb(base+2) == hw_info[i].a1) && (readb(base+4) == hw_info[i].a2)) { for (j = 0; j < 6; j++) dev->dev_addr[j] = readb(base + (j<<1)); break; } } iounmap(virt); j = pcmcia_release_window(link, link->resource[2]); return (i < NR_INFO) ? hw_info+i : NULL; } /* get_hwinfo */
static void osl_pcmcia_attr(osl_t *osh, uint offset, char *buf, int size, bool write) { #if (defined(CONFIG_PCMCIA) || defined(CONFIG_PCMCIA_MODULE)) && defined(BCMPCMCIA) struct pcmcia_dev *dev = osh->pdev; dev_link_t *link = (dev_link_t *) &dev->link; modwin_t mod; memreq_t mem; int ret; ASSERT(link->win); ASSERT(dev->base && dev->size); mod.Attributes = WIN_ENABLE | WIN_MEMORY_TYPE_AM; mod.AccessSpeed = 0; ret = pcmcia_modify_window(link->win, &mod); if (ret != CS_SUCCESS) { cs_error(link->handle, ModifyWindow, ret); return; } offset *= 2; mem.CardOffset = offset & ~(dev->size - 1); mem.Page = 0; while (size > 0) { ret = pcmcia_map_mem_page(link->win, &mem); if (ret != CS_SUCCESS) { cs_error(link->handle, MapMemPage, ret); break; } for (offset &= (dev->size - 1); offset < dev->size && size > 0; offset += 2, buf++, size--) { if (write) writeb(*buf, (char *) dev->base + offset); else *buf = readb((char *) dev->base + offset); } mem.CardOffset += dev->size; } mod.Attributes = WIN_ENABLE | WIN_MEMORY_TYPE_CM; mod.AccessSpeed = 0; ret = pcmcia_modify_window(link->win, &mod); if (ret != CS_SUCCESS) { cs_error(link->handle, ModifyWindow, ret); return; } #endif }
static int b43_pcmcia_probe(struct pcmcia_device *dev) { struct ssb_bus *ssb; int err = -ENOMEM; int res = 0; ssb = kzalloc(sizeof(*ssb), GFP_KERNEL); if (!ssb) goto out_error; err = -ENODEV; dev->config_flags |= CONF_ENABLE_IRQ; dev->resource[2]->flags |= WIN_ENABLE | WIN_DATA_WIDTH_16 | WIN_USE_WAIT; dev->resource[2]->start = 0; dev->resource[2]->end = SSB_CORE_SIZE; res = pcmcia_request_window(dev, dev->resource[2], 250); if (res != 0) goto err_kfree_ssb; res = pcmcia_map_mem_page(dev, dev->resource[2], 0); if (res != 0) goto err_disable; if (!dev->irq) goto err_disable; res = pcmcia_enable_device(dev); if (res != 0) goto err_disable; err = ssb_bus_pcmciabus_register(ssb, dev, dev->resource[2]->start); if (err) goto err_disable; dev->priv = ssb; return 0; err_disable: pcmcia_disable_device(dev); err_kfree_ssb: kfree(ssb); out_error: printk(KERN_ERR "b43-pcmcia: Initialization failed (%d, %d)\n", res, err); return err; }
static int __devinit ems_pcmcia_probe(struct pcmcia_device *dev) { int csval; /* */ dev->config_flags |= CONF_ENABLE_IRQ; dev->config_index = 1; dev->config_regs = PRESENT_OPTION; /* */ dev->resource[0]->end = 16; dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; dev->resource[1]->end = 16; dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_16; dev->io_lines = 5; /* */ dev->resource[2]->flags = (WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_CM | WIN_ENABLE); dev->resource[2]->start = dev->resource[2]->end = 0; csval = pcmcia_request_window(dev, dev->resource[2], 0); if (csval) { dev_err(&dev->dev, "pcmcia_request_window failed (err=%d)\n", csval); return 0; } csval = pcmcia_map_mem_page(dev, dev->resource[2], dev->config_base); if (csval) { dev_err(&dev->dev, "pcmcia_map_mem_page failed (err=%d)\n", csval); return 0; } csval = pcmcia_enable_device(dev); if (csval) { dev_err(&dev->dev, "pcmcia_enable_device failed (err=%d)\n", csval); return 0; } ems_pcmcia_add_card(dev, dev->resource[2]->start); return 0; }
/* gpib_config() is scheduled to run after a CARD_INSERTION event is received, to configure the PCMCIA socket, and to make the ethernet device available to the system. */ static void ines_gpib_config( struct pcmcia_device *link ) { tuple_t tuple; cisparse_t parse; local_info_t *dev; int i; u_char buf[64]; win_req_t req; memreq_t mem; void *virt; dev = link->priv; DEBUG(0, "ines_gpib_config(0x%p)\n", link); /* This reads the card's CONFIG tuple to find its configuration registers. */ do { tuple.DesiredTuple = CISTPL_CONFIG; i = pcmcia_get_first_tuple(link, &tuple); if (i != 0) break; tuple.TupleData = buf; tuple.TupleDataMax = 64; tuple.TupleOffset = 0; i = pcmcia_get_tuple_data(link, &tuple); if (i != 0) break; i = PCMCIA_PARSE_TUPLE(&tuple, &parse); if (i != 0) break; link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; } while (0); if (i != 0) { cs_error(link, ParseTuple, i); return; } /* Configure card */ do { /* * try to get manufacturer and card ID */ tuple.DesiredTuple = CISTPL_MANFID; tuple.Attributes = TUPLE_RETURN_COMMON; if( first_tuple(link,&tuple,&parse) == 0 ) { dev->manfid = parse.manfid.manf; dev->cardid = parse.manfid.card; printk(KERN_DEBUG "ines_cs: manufacturer: 0x%x card: 0x%x\n", dev->manfid, dev->cardid); } /* try to get board information from CIS */ tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; tuple.Attributes = 0; if( first_tuple(link,&tuple,&parse) == 0 ) { while(1) { if( parse.cftable_entry.io.nwin > 0) { link->io.BasePort1 = parse.cftable_entry.io.win[0].base; link->io.NumPorts1 = 32; link->io.BasePort2 = 0; link->io.NumPorts2 = 0; i = pcmcia_request_io(link, &link->io); if (i == 0) { printk( KERN_DEBUG "ines_cs: base=0x%x len=%d registered\n", link->io.BasePort1, link->io.NumPorts1 ); link->conf.ConfigIndex = parse.cftable_entry.index; break; } } if ( next_tuple(link,&tuple,&parse) != 0 ) break; } if (i != 0) { cs_error(link, RequestIO, i); } } else { printk("ines_cs: can't get card information\n"); } link->conf.Status = CCSR_IOIS8; /* for the ines card we have to setup the configuration registers in attribute memory here */ req.Attributes=WIN_MEMORY_TYPE_AM | WIN_DATA_WIDTH_8 | WIN_ENABLE; req.Base=0; req.Size=0x1000; req.AccessSpeed=250; i= pcmcia_request_window(&link, &req, &link->win); if (i != 0) { cs_error(link, RequestWindow, i); break; } mem.CardOffset=0; mem.Page=0; i= pcmcia_map_mem_page(link->win, &mem); if (i != 0) { cs_error(link, MapMemPage, i); break; } virt = ioremap( req.Base, req.Size ); writeb( ( link->io.BasePort1 >> 2 ) & 0xff, virt + 0xf0 ); // IOWindow base iounmap( ( void* ) virt ); } while (0); /* Now allocate an interrupt line. */ if (link->conf.Attributes & CONF_ENABLE_IRQ) { i = pcmcia_request_irq(link, &link->irq); if (i != 0) { cs_error(link, RequestIRQ, i); } printk(KERN_DEBUG "ines_cs: IRQ_Line=%d\n",link->irq.AssignedIRQ); } /* This actually configures the PCMCIA socket -- setting up the I/O windows and the interrupt mapping. */ i = pcmcia_request_configuration(link, &link->conf); if (i != 0) { cs_error(link, RequestConfiguration, i); } /* If any step failed, release any partially configured state */ if (i != 0) { ines_gpib_release(link); return; } printk(KERN_DEBUG "ines gpib device loaded\n"); } /* gpib_config */
static int airo_config(struct pcmcia_device *link) { tuple_t tuple; cisparse_t parse; local_info_t *dev; int last_fn, last_ret; u_char buf[64]; win_req_t req; memreq_t map; dev = link->priv; DEBUG(0, "airo_config(0x%p)\n", link); /* 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.Attributes = 0; tuple.TupleData = buf; tuple.TupleDataMax = sizeof(buf); tuple.TupleOffset = 0; tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); while (1) { cistpl_cftable_entry_t dflt = { 0 }; cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); if (pcmcia_get_tuple_data(link, &tuple) != 0 || pcmcia_parse_tuple(link, &tuple, &parse) != 0) 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; } /* Use power settings for Vcc and Vpp if present */ /* Note that the CIS values need to be rescaled */ if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM)) link->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM]/10000; else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM)) link->conf.Vpp = dflt.vpp1.param[CISTPL_POWER_VNOM]/10000; /* 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.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; /* Now set up a common memory window, if needed. There is room in the struct pcmcia_device structure for one memory window handle, but if the base addresses need to be saved, or if multiple windows are needed, the info should go in the private data structure for this device. Note that the memory window base is a physical address, and needs to be mapped to virtual space with ioremap() before it is used. */ if ((cfg->mem.nwin > 0) || (dflt.mem.nwin > 0)) { cistpl_mem_t *mem = (cfg->mem.nwin) ? &cfg->mem : &dflt.mem; req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM; req.Base = mem->win[0].host_addr; req.Size = mem->win[0].len; req.AccessSpeed = 0; if (pcmcia_request_window(&link, &req, &link->win) != 0) goto next_entry; map.Page = 0; map.CardOffset = mem->win[0].card_addr; if (pcmcia_map_mem_page(link->win, &map) != 0) goto next_entry; } /* If we got this far, we're cool! */ break; next_entry: CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple)); } /* Allocate an interrupt line. Note that this does not assign a handler to the interrupt, unless the 'Handler' member of the irq structure is initialized. */ if (link->conf.Attributes & CONF_ENABLE_IRQ) CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); /* 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. */ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); ((local_info_t*)link->priv)->eth_dev = init_airo_card( link->irq.AssignedIRQ, link->io.BasePort1, 1, &handle_to_dev(link) ); if (!((local_info_t*)link->priv)->eth_dev) 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_node. */ strcpy(dev->node.dev_name, ((local_info_t*)link->priv)->eth_dev->name ); 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.Vpp) printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10); if (link->conf.Attributes & CONF_ENABLE_IRQ) printk(", irq %d", 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); if (link->win) printk(", mem 0x%06lx-0x%06lx", req.Base, req.Base+req.Size-1); printk("\n"); return 0; cs_failed: cs_error(link, last_fn, last_ret); airo_release(link); return -ENODEV; } /* airo_config */
static void labpc_config(struct pcmcia_device *link) { struct local_info_t *dev = link->priv; tuple_t tuple; cisparse_t parse; int last_ret; u_char buf[64]; win_req_t req; memreq_t map; cistpl_cftable_entry_t dflt = { 0 }; DEBUG(0, "labpc_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_ret = pcmcia_get_first_tuple(link, &tuple); if (last_ret) { cs_error(link, GetFirstTuple, last_ret); goto cs_failed; } last_ret = pcmcia_get_tuple_data(link, &tuple); if (last_ret) { cs_error(link, GetTupleData, last_ret); goto cs_failed; } last_ret = pcmcia_parse_tuple(&tuple, &parse); if (last_ret) { cs_error(link, ParseTuple, 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_ret = pcmcia_get_first_tuple(link, &tuple); if (last_ret) { cs_error(link, GetFirstTuple, last_ret); goto cs_failed; } while (1) { cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); if (pcmcia_get_tuple_data(link, &tuple)) goto next_entry; if (pcmcia_parse_tuple(&tuple, &parse)) 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_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)) goto next_entry; } if ((cfg->mem.nwin > 0) || (dflt.mem.nwin > 0)) { cistpl_mem_t *mem = (cfg->mem.nwin) ? &cfg->mem : &dflt.mem; req.Attributes = WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM; req.Attributes |= WIN_ENABLE; req.Base = mem->win[0].host_addr; req.Size = mem->win[0].len; if (req.Size < 0x1000) req.Size = 0x1000; req.AccessSpeed = 0; link->win = (window_handle_t) link; if (pcmcia_request_window(&link, &req, &link->win)) goto next_entry; map.Page = 0; map.CardOffset = mem->win[0].card_addr; if (pcmcia_map_mem_page(link->win, &map)) goto next_entry; } /* If we got this far, we're cool! */ break; next_entry: last_ret = pcmcia_get_next_tuple(link, &tuple); if (last_ret) { cs_error(link, GetNextTuple, last_ret); goto cs_failed; } } /* Allocate an interrupt line. Note that this does not assign a handler to the interrupt, unless the 'Handler' member of the irq structure is initialized. */ if (link->conf.Attributes & CONF_ENABLE_IRQ) { last_ret = pcmcia_request_irq(link, &link->irq); if (last_ret) { cs_error(link, RequestIRQ, 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_ret = pcmcia_request_configuration(link, &link->conf); if (last_ret) { cs_error(link, RequestConfiguration, 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, "daqcard-1200"); 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 %d", 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); if (link->win) printk(", mem 0x%06lx-0x%06lx", req.Base, req.Base + req.Size - 1); printk("\n"); return; cs_failed: labpc_release(link); } /* labpc_config */
static int ipwireless_probe(struct pcmcia_device *p_dev, void *priv_data) { struct ipw_dev *ipw = priv_data; int ret; p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; /* 0x40 causes it to generate level mode interrupts. */ /* 0x04 enables IREQ pin. */ p_dev->config_index |= 0x44; p_dev->io_lines = 16; ret = pcmcia_request_io(p_dev); if (ret) return ret; if (!request_region(p_dev->resource[0]->start, resource_size(p_dev->resource[0]), IPWIRELESS_PCCARD_NAME)) { ret = -EBUSY; goto exit; } p_dev->resource[2]->flags |= WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM | WIN_ENABLE; ret = pcmcia_request_window(p_dev, p_dev->resource[2], 0); if (ret != 0) goto exit1; ret = pcmcia_map_mem_page(p_dev, p_dev->resource[2], p_dev->card_addr); if (ret != 0) goto exit1; ipw->is_v2_card = resource_size(p_dev->resource[2]) == 0x100; ipw->common_memory = ioremap(p_dev->resource[2]->start, resource_size(p_dev->resource[2])); if (!ipw->common_memory) { ret = -ENOMEM; goto exit1; } if (!request_mem_region(p_dev->resource[2]->start, resource_size(p_dev->resource[2]), IPWIRELESS_PCCARD_NAME)) { ret = -EBUSY; goto exit2; } p_dev->resource[3]->flags |= WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_AM | WIN_ENABLE; p_dev->resource[3]->end = 0; /* this used to be 0x1000 */ ret = pcmcia_request_window(p_dev, p_dev->resource[3], 0); if (ret != 0) goto exit3; ret = pcmcia_map_mem_page(p_dev, p_dev->resource[3], 0); if (ret != 0) goto exit3; ipw->attr_memory = ioremap(p_dev->resource[3]->start, resource_size(p_dev->resource[3])); if (!ipw->attr_memory) { ret = -ENOMEM; goto exit3; } if (!request_mem_region(p_dev->resource[3]->start, resource_size(p_dev->resource[3]), IPWIRELESS_PCCARD_NAME)) { ret = -EBUSY; goto exit4; } return 0; exit4: iounmap(ipw->attr_memory); exit3: release_mem_region(p_dev->resource[2]->start, resource_size(p_dev->resource[2])); exit2: iounmap(ipw->common_memory); exit1: release_region(p_dev->resource[0]->start, resource_size(p_dev->resource[0])); exit: pcmcia_disable_device(p_dev); return ret; }
static int airo_cs_config_check(struct pcmcia_device *p_dev, cistpl_cftable_entry_t *cfg, cistpl_cftable_entry_t *dflt, unsigned int vcc, void *priv_data) { win_req_t *req = priv_data; if (cfg->index == 0) return -ENODEV; /* Does this card need audio output? */ if (cfg->flags & CISTPL_CFTABLE_AUDIO) { p_dev->conf.Attributes |= CONF_ENABLE_SPKR; p_dev->conf.Status = CCSR_AUDIO_ENA; } /* Use power settings for Vcc and Vpp if present */ /* Note that the CIS values need to be rescaled */ if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM)) p_dev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM]/10000; else if (dflt->vpp1.present & (1<<CISTPL_POWER_VNOM)) p_dev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM]/10000; /* Do we need to allocate an interrupt? */ if (cfg->irq.IRQInfo1 || dflt->irq.IRQInfo1) p_dev->conf.Attributes |= CONF_ENABLE_IRQ; /* IO window settings */ p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0; if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; if (!(io->flags & CISTPL_IO_8BIT)) p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16; if (!(io->flags & CISTPL_IO_16BIT)) p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; p_dev->io.BasePort1 = io->win[0].base; p_dev->io.NumPorts1 = io->win[0].len; if (io->nwin > 1) { p_dev->io.Attributes2 = p_dev->io.Attributes1; p_dev->io.BasePort2 = io->win[1].base; p_dev->io.NumPorts2 = io->win[1].len; } } /* This reserves IO space but doesn't actually enable it */ if (pcmcia_request_io(p_dev, &p_dev->io) != 0) return -ENODEV; /* Now set up a common memory window, if needed. There is room in the struct pcmcia_device structure for one memory window handle, but if the base addresses need to be saved, or if multiple windows are needed, the info should go in the private data structure for this device. Note that the memory window base is a physical address, and needs to be mapped to virtual space with ioremap() before it is used. */ if ((cfg->mem.nwin > 0) || (dflt->mem.nwin > 0)) { cistpl_mem_t *mem = (cfg->mem.nwin) ? &cfg->mem : &dflt->mem; memreq_t map; req->Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM; req->Base = mem->win[0].host_addr; req->Size = mem->win[0].len; req->AccessSpeed = 0; if (pcmcia_request_window(&p_dev, req, &p_dev->win) != 0) return -ENODEV; map.Page = 0; map.CardOffset = mem->win[0].card_addr; if (pcmcia_map_mem_page(p_dev->win, &map) != 0) return -ENODEV; } /* If we got this far, we're cool! */ return 0; }
static int __devinit b43_pcmcia_probe(struct pcmcia_device *dev) { struct ssb_bus *ssb; win_req_t win; memreq_t mem; tuple_t tuple; cisparse_t parse; int err = -ENOMEM; int res = 0; unsigned char buf[64]; ssb = kzalloc(sizeof(*ssb), GFP_KERNEL); if (!ssb) goto out_error; err = -ENODEV; tuple.DesiredTuple = CISTPL_CONFIG; tuple.Attributes = 0; tuple.TupleData = buf; tuple.TupleDataMax = sizeof(buf); tuple.TupleOffset = 0; res = pcmcia_get_first_tuple(dev, &tuple); if (res != CS_SUCCESS) goto err_kfree_ssb; res = pcmcia_get_tuple_data(dev, &tuple); if (res != CS_SUCCESS) goto err_kfree_ssb; res = pcmcia_parse_tuple(dev, &tuple, &parse); if (res != CS_SUCCESS) goto err_kfree_ssb; dev->conf.ConfigBase = parse.config.base; dev->conf.Present = parse.config.rmask[0]; dev->io.BasePort2 = 0; dev->io.NumPorts2 = 0; dev->io.Attributes2 = 0; win.Attributes = WIN_ADDR_SPACE_MEM | WIN_MEMORY_TYPE_CM | WIN_ENABLE | WIN_DATA_WIDTH_16 | WIN_USE_WAIT; win.Base = 0; win.Size = SSB_CORE_SIZE; win.AccessSpeed = 250; res = pcmcia_request_window(&dev, &win, &dev->win); if (res != CS_SUCCESS) goto err_kfree_ssb; mem.CardOffset = 0; mem.Page = 0; res = pcmcia_map_mem_page(dev->win, &mem); if (res != CS_SUCCESS) goto err_disable; dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_FIRST_SHARED; dev->irq.IRQInfo1 = IRQ_LEVEL_ID | IRQ_SHARE_ID; dev->irq.Handler = NULL; /* The handler is registered later. */ dev->irq.Instance = NULL; res = pcmcia_request_irq(dev, &dev->irq); if (res != CS_SUCCESS) goto err_disable; res = pcmcia_request_configuration(dev, &dev->conf); if (res != CS_SUCCESS) goto err_disable; err = ssb_bus_pcmciabus_register(ssb, dev, win.Base); if (err) goto err_disable; dev->priv = ssb; return 0; err_disable: pcmcia_disable_device(dev); err_kfree_ssb: kfree(ssb); out_error: printk(KERN_ERR "b43-pcmcia: Initialization failed (%d, %d)\n", res, err); return err; }
static int config_ipwireless(struct ipw_dev *ipw) { struct pcmcia_device *link = ipw->link; int ret; tuple_t tuple; unsigned short buf[64]; cisparse_t parse; unsigned short cor_value; memreq_t memreq_attr_memory; memreq_t memreq_common_memory; ipw->is_v2_card = 0; tuple.Attributes = 0; tuple.TupleData = (cisdata_t *) buf; tuple.TupleDataMax = sizeof(buf); tuple.TupleOffset = 0; tuple.DesiredTuple = RETURN_FIRST_TUPLE; ret = pcmcia_get_first_tuple(link, &tuple); while (ret == 0) { ret = pcmcia_get_tuple_data(link, &tuple); if (ret != 0) { cs_error(link, GetTupleData, ret); goto exit0; } ret = pcmcia_get_next_tuple(link, &tuple); } tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; ret = pcmcia_get_first_tuple(link, &tuple); if (ret != 0) { cs_error(link, GetFirstTuple, ret); goto exit0; } ret = pcmcia_get_tuple_data(link, &tuple); if (ret != 0) { cs_error(link, GetTupleData, ret); goto exit0; } ret = pcmcia_parse_tuple(&tuple, &parse); if (ret != 0) { cs_error(link, ParseTuple, ret); goto exit0; } link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; link->io.BasePort1 = parse.cftable_entry.io.win[0].base; link->io.NumPorts1 = parse.cftable_entry.io.win[0].len; link->io.IOAddrLines = 16; link->irq.IRQInfo1 = parse.cftable_entry.irq.IRQInfo1; /* 0x40 causes it to generate level mode interrupts. */ /* 0x04 enables IREQ pin. */ cor_value = parse.cftable_entry.index | 0x44; link->conf.ConfigIndex = cor_value; /* IRQ and I/O settings */ tuple.DesiredTuple = CISTPL_CONFIG; ret = pcmcia_get_first_tuple(link, &tuple); if (ret != 0) { cs_error(link, GetFirstTuple, ret); goto exit0; } ret = pcmcia_get_tuple_data(link, &tuple); if (ret != 0) { cs_error(link, GetTupleData, ret); goto exit0; } ret = pcmcia_parse_tuple(&tuple, &parse); if (ret != 0) { cs_error(link, GetTupleData, ret); goto exit0; } link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; link->conf.IntType = INT_MEMORY_AND_IO; link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT; link->irq.Handler = ipwireless_interrupt; link->irq.Instance = ipw->hardware; ret = pcmcia_request_io(link, &link->io); if (ret != 0) { cs_error(link, RequestIO, ret); goto exit0; } request_region(link->io.BasePort1, link->io.NumPorts1, IPWIRELESS_PCCARD_NAME); /* memory settings */ tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; ret = pcmcia_get_first_tuple(link, &tuple); if (ret != 0) { cs_error(link, GetFirstTuple, ret); goto exit1; } ret = pcmcia_get_tuple_data(link, &tuple); if (ret != 0) { cs_error(link, GetTupleData, ret); goto exit1; } ret = pcmcia_parse_tuple(&tuple, &parse); if (ret != 0) { cs_error(link, ParseTuple, ret); goto exit1; } if (parse.cftable_entry.mem.nwin > 0) { ipw->request_common_memory.Attributes = WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM | WIN_ENABLE; ipw->request_common_memory.Base = parse.cftable_entry.mem.win[0].host_addr; ipw->request_common_memory.Size = parse.cftable_entry.mem.win[0].len; if (ipw->request_common_memory.Size < 0x1000) ipw->request_common_memory.Size = 0x1000; ipw->request_common_memory.AccessSpeed = 0; ret = pcmcia_request_window(&link, &ipw->request_common_memory, &ipw->handle_common_memory); if (ret != 0) { cs_error(link, RequestWindow, ret); goto exit1; } memreq_common_memory.CardOffset = parse.cftable_entry.mem.win[0].card_addr; memreq_common_memory.Page = 0; ret = pcmcia_map_mem_page(ipw->handle_common_memory, &memreq_common_memory); if (ret != 0) { cs_error(link, MapMemPage, ret); goto exit1; } ipw->is_v2_card = parse.cftable_entry.mem.win[0].len == 0x100; ipw->common_memory = ioremap(ipw->request_common_memory.Base, ipw->request_common_memory.Size); request_mem_region(ipw->request_common_memory.Base, ipw->request_common_memory.Size, IPWIRELESS_PCCARD_NAME); ipw->request_attr_memory.Attributes = WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_AM | WIN_ENABLE; ipw->request_attr_memory.Base = 0; ipw->request_attr_memory.Size = 0; /* this used to be 0x1000 */ ipw->request_attr_memory.AccessSpeed = 0; ret = pcmcia_request_window(&link, &ipw->request_attr_memory, &ipw->handle_attr_memory); if (ret != 0) { cs_error(link, RequestWindow, ret); goto exit2; } memreq_attr_memory.CardOffset = 0; memreq_attr_memory.Page = 0; ret = pcmcia_map_mem_page(ipw->handle_attr_memory, &memreq_attr_memory); if (ret != 0) { cs_error(link, MapMemPage, ret); goto exit2; } ipw->attr_memory = ioremap(ipw->request_attr_memory.Base, ipw->request_attr_memory.Size); request_mem_region(ipw->request_attr_memory.Base, ipw->request_attr_memory.Size, IPWIRELESS_PCCARD_NAME); } INIT_WORK(&ipw->work_reboot, signalled_reboot_work); ipwireless_init_hardware_v1(ipw->hardware, link->io.BasePort1, ipw->attr_memory, ipw->common_memory, ipw->is_v2_card, signalled_reboot_callback, ipw); ret = pcmcia_request_irq(link, &link->irq); if (ret != 0) { cs_error(link, RequestIRQ, ret); goto exit3; } printk(KERN_INFO IPWIRELESS_PCCARD_NAME ": Card type %s\n", ipw->is_v2_card ? "V2/V3" : "V1"); printk(KERN_INFO IPWIRELESS_PCCARD_NAME ": I/O ports 0x%04x-0x%04x, irq %d\n", (unsigned int) link->io.BasePort1, (unsigned int) (link->io.BasePort1 + link->io.NumPorts1 - 1), (unsigned int) link->irq.AssignedIRQ); if (ipw->attr_memory && ipw->common_memory) printk(KERN_INFO IPWIRELESS_PCCARD_NAME ": attr memory 0x%08lx-0x%08lx, common memory 0x%08lx-0x%08lx\n", ipw->request_attr_memory.Base, ipw->request_attr_memory.Base + ipw->request_attr_memory.Size - 1, ipw->request_common_memory.Base, ipw->request_common_memory.Base + ipw->request_common_memory.Size - 1); ipw->network = ipwireless_network_create(ipw->hardware); if (!ipw->network) goto exit3; ipw->tty = ipwireless_tty_create(ipw->hardware, ipw->network, ipw->nodes); if (!ipw->tty) goto exit3; ipwireless_init_hardware_v2_v3(ipw->hardware); /* * Do the RequestConfiguration last, because it enables interrupts. * Then we don't get any interrupts before we're ready for them. */ ret = pcmcia_request_configuration(link, &link->conf); if (ret != 0) { cs_error(link, RequestConfiguration, ret); goto exit4; } link->dev_node = &ipw->nodes[0]; return 0; exit4: pcmcia_disable_device(link); exit3: if (ipw->attr_memory) { release_mem_region(ipw->request_attr_memory.Base, ipw->request_attr_memory.Size); iounmap(ipw->attr_memory); pcmcia_release_window(ipw->handle_attr_memory); pcmcia_disable_device(link); } exit2: if (ipw->common_memory) { release_mem_region(ipw->request_common_memory.Base, ipw->request_common_memory.Size); iounmap(ipw->common_memory); pcmcia_release_window(ipw->handle_common_memory); } exit1: pcmcia_disable_device(link); exit0: return -1; }
static void cif60_config(dev_link_t *link) { client_handle_t handle = link->handle; cif60_dev_t *info = link->priv; //CARD_DEVICE *dev = info->dev; tuple_t tuple; cisparse_t parse; win_req_t req; memreq_t mem; int last_ret, last_fn; u_char buf[64]; DEBUG(0, "cif60_config(0x%p)\n", link); tuple.Attributes = 0; tuple.TupleData = buf; tuple.TupleDataMax = 64; tuple.TupleOffset = 0; tuple.DesiredTuple = CISTPL_CONFIG; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); DEBUG(0, "cif60_config:GetFirstTuple\n"); CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); DEBUG(0, "cif60_config:GetTupleData\n"); CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); DEBUG(0, "cif60_config:ParseTuple\n"); link->conf.ConfigBase = parse.config.base; DEBUG(0, "cif60_config:link->conf.ConfigBase=%d\n", link->conf.ConfigBase); /* Configure card */ link->state |= DEV_CONFIG; //link->conf.ConfigIndex = 0x61; /* Determine if this is PRIMARY or ALTERNATE. */ /* Try PRIMARY card at 0xA20-0xA23 */ /* link->io.BasePort1 = 0xd0000; i = pcmcia_request_io(link->handle, &link->io); DEBUG(0, "cif60_config:request_io ret=%d\n", i); if (i != CS_SUCCESS) { / * Couldn't get 0xA20-0xA23. Try ALTERNATE at 0xA24-0xA27. * / link->io.BasePort1 = 0xA24; CS_CHECK(RequestIO, pcmcia_request_io(link->handle, &link->io)); DEBUG(0, "cif60_config:retry request_io\n"); } dev->base_addr = link->io.BasePort1; DEBUG(0, "cif60_config:base_addr=%lx\n", dev->base_addr); */ /* CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); dev->irq = link->irq.AssignedIRQ; DEBUG(0, "cif60_config:irq=%d\n", dev->irq); */ /* Allocate the MMIO memory window */ /* req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE; req.Attributes |= WIN_USE_WAIT; req.Base = 0; req.Size = 0x2000; req.AccessSpeed = 250; CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &link->win)); DEBUG(0, "cif60_config:RequestWindow\n"); mem.CardOffset = mmiobase; mem.Page = 0; CS_CHECK(MapMemPage, pcmcia_map_mem_page(link->win, &mem)); dev->mmio = ioremap(req.Base, req.Size); */ /* Allocate the SRAM memory window */ req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE; req.Attributes |= WIN_USE_WAIT; req.Base = 0; req.Size = sramsize * 1024; req.AccessSpeed = 250; CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &info->sram_win_handle)); DEBUG(0, "cif60_config:RequestWindow2\n"); mem.CardOffset = srambase; mem.Page = 0; CS_CHECK(MapMemPage, pcmcia_map_mem_page(info->sram_win_handle, &mem)); DEBUG(0, "cif60_config:MapMemPage\n"); //dev->sram_base = mem.CardOffset >> 12; //dev->sram_virt = (u_long)ioremap(req.Base, req.Size); //CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf)); //DEBUG(0, "cif60_config:RequestConfiguration\n"); DEBUG(0, "cif60_config:return\n"); return; /* link->dev = &info->node; link->state &= ~DEV_CONFIG_PENDING; i = cif_scan_pci(); // i = cif60_probe_card(dev); if(i != -ENODEV) { printk(KERN_NOTICE "cif_cs: register_cif() failed\n"); link->dev = NULL; goto failed; } strcpy(info->node.dev_name, dev->name); printk(KERN_INFO "%s: port %#3lx, irq %d,", dev->name, dev->base_addr, dev->irq); printk("\n"); return; */ cs_failed: DEBUG(0, "cif60_config:cs_failed\n"); cs_error(link->handle, last_fn, last_ret); /* failed: cif60_release(link); */ } /* cif60_config */
static int xirc2ps_config(struct pcmcia_device * link) { struct net_device *dev = link->priv; local_info_t *local = netdev_priv(dev); unsigned int ioaddr; int err; u8 *buf; size_t len; local->dingo_ccr = NULL; dev_dbg(&link->dev, "config\n"); if (link->has_manf_id == 0) { pr_notice("manfid not found in CIS\n"); goto failure; } switch (link->manf_id) { case MANFID_XIRCOM: local->manf_str = "Xircom"; break; case MANFID_ACCTON: local->manf_str = "Accton"; break; case MANFID_COMPAQ: case MANFID_COMPAQ2: local->manf_str = "Compaq"; break; case MANFID_INTEL: local->manf_str = "Intel"; break; case MANFID_TOSHIBA: local->manf_str = "Toshiba"; break; default: pr_notice("Unknown Card Manufacturer ID: 0x%04x\n", (unsigned)link->manf_id); goto failure; } dev_dbg(&link->dev, "found %s card\n", local->manf_str); if (!set_card_type(link)) { pr_notice("this card is not supported\n"); goto failure; } err = pcmcia_get_mac_from_cis(link, dev); if (err) { len = pcmcia_get_tuple(link, 0x89, &buf); if (buf && len == 8) { if (*buf == CISTPL_FUNCE_LAN_NODE_ID) { int i; for (i = 2; i < 6; i++) dev->dev_addr[i] = buf[i+2]; } else err = -1; } kfree(buf); } if (err) err = pcmcia_loop_tuple(link, CISTPL_FUNCE, pcmcia_get_mac_ce, dev); if (err) { pr_notice("node-id not found in CIS\n"); goto failure; } if (local->modem) { int pass; link->config_flags |= CONF_AUTO_SET_IO; if (local->dingo) { if (!pcmcia_loop_config(link, xirc2ps_config_modem, NULL)) goto port_found; } else { for (pass=0; pass < 2; pass++) if (!pcmcia_loop_config(link, xirc2ps_config_check, &pass)) goto port_found; } pr_notice("no ports available\n"); } else { link->io_lines = 10; link->resource[0]->end = 16; link->resource[0]->flags |= IO_DATA_PATH_WIDTH_16; for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) { link->resource[0]->start = ioaddr; if (!(err = pcmcia_request_io(link))) goto port_found; } link->resource[0]->start = 0; if ((err = pcmcia_request_io(link))) goto config_error; } port_found: if (err) goto config_error; if ((err=pcmcia_request_irq(link, xirc2ps_interrupt))) goto config_error; link->config_flags |= CONF_ENABLE_IRQ; if (do_sound) link->config_flags |= CONF_ENABLE_SPKR; if ((err = pcmcia_enable_device(link))) goto config_error; if (local->dingo) { /* Reset the modem's BAR to the correct value * This is necessary because in the RequestConfiguration call, * the base address of the ethernet port (BasePort1) is written * to the BAR registers of the modem. */ err = pcmcia_write_config_byte(link, CISREG_IOBASE_0, (u8) link->resource[1]->start & 0xff); if (err) goto config_error; err = pcmcia_write_config_byte(link, CISREG_IOBASE_1, (link->resource[1]->start >> 8) & 0xff); if (err) goto config_error; link->resource[2]->flags = WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_AM | WIN_ENABLE; link->resource[2]->start = link->resource[2]->end = 0; if ((err = pcmcia_request_window(link, link->resource[2], 0))) goto config_error; local->dingo_ccr = ioremap(link->resource[2]->start, 0x1000) + 0x0800; if ((err = pcmcia_map_mem_page(link, link->resource[2], 0))) goto config_error; writeb(0x47, local->dingo_ccr + CISREG_COR); ioaddr = link->resource[0]->start; writeb(ioaddr & 0xff , local->dingo_ccr + CISREG_IOBASE_0); writeb((ioaddr >> 8)&0xff , local->dingo_ccr + CISREG_IOBASE_1); #if 0 { u_char tmp; pr_info("ECOR:"); for (i=0; i < 7; i++) { tmp = readb(local->dingo_ccr + i*2); pr_cont(" %02x", tmp); } pr_cont("\n"); pr_info("DCOR:"); for (i=0; i < 4; i++) { tmp = readb(local->dingo_ccr + 0x20 + i*2); pr_cont(" %02x", tmp); } pr_cont("\n"); pr_info("SCOR:"); for (i=0; i < 10; i++) { tmp = readb(local->dingo_ccr + 0x40 + i*2); pr_cont(" %02x", tmp); } pr_cont("\n"); } #endif writeb(0x01, local->dingo_ccr + 0x20); writeb(0x0c, local->dingo_ccr + 0x22); writeb(0x00, local->dingo_ccr + 0x24); writeb(0x00, local->dingo_ccr + 0x26); writeb(0x00, local->dingo_ccr + 0x28); }
static void ni_gpib_config(struct pcmcia_device *link) { //local_info_t *info = link->priv; //gpib_board_t *dev = info->dev; tuple_t tuple; cisparse_t parse; int last_fn, last_ret; u_char buf[64]; win_req_t req; memreq_t map; cistpl_cftable_entry_t dflt = { 0 }; DEBUG(0, "ni_gpib_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; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); CS_CHECK(ParseTuple, PCMCIA_PARSE_TUPLE(&tuple, &parse)); link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; /* Configure card */ /* 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; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); while (1) { cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); CS_CHECK(ParseTuple, PCMCIA_PARSE_TUPLE(&tuple, &parse)); 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 */ last_ret = pcmcia_request_io(link, &link->io); if(last_ret != 0) { goto next_entry; } } /* Now set up a common memory window, if needed. There is room in the dev_link_t structure for one memory window handle, but if the base addresses need to be saved, or if multiple windows are needed, the info should go in the private data structure for this device. Note that the memory window base is a physical address, and needs to be mapped to virtual space with ioremap() before it is used. */ if ((cfg->mem.nwin > 0) || (dflt.mem.nwin > 0)) { cistpl_mem_t *mem = (cfg->mem.nwin) ? &cfg->mem : &dflt.mem; req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM; req.Attributes |= WIN_ENABLE; req.Base = mem->win[0].host_addr; req.Size = mem->win[0].len; if (req.Size < 0x1000) req.Size = 0x1000; req.AccessSpeed = 0; link->win = (window_handle_t)link; if(pcmcia_request_window(&link, &req, &link->win) != 0) goto next_entry; map.Page = 0; map.CardOffset = mem->win[0].card_addr; if(pcmcia_map_mem_page(link->win, &map) != 0) goto next_entry; } /* If we got this far, we're cool! */ break; next_entry: CS_CHECK( GetNextTuple, pcmcia_get_next_tuple(link, &tuple)); } /* Allocate an interrupt line. Note that this does not assign a handler to the interrupt, unless the 'Handler' member of the irq structure is initialized. */ if (link->conf.Attributes & CONF_ENABLE_IRQ) CS_CHECK( RequestIRQ, pcmcia_request_irq(link, &link->irq) ); /* 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. */ CS_CHECK( RequestConfiguration, pcmcia_request_configuration(link, &link->conf) ); /* At this point, the dev_node_t structure(s) need to be initialized and arranged in a linked list at link->dev. */ return; cs_failed: cs_error(link, last_fn, last_ret); ni_gpib_release(link); } /* ni_gpib_config */
static int airo_cs_config_check(struct pcmcia_device *p_dev, cistpl_cftable_entry_t *cfg, cistpl_cftable_entry_t *dflt, unsigned int vcc, void *priv_data) { win_req_t *req = priv_data; if (cfg->index == 0) return -ENODEV; if (cfg->flags & CISTPL_CFTABLE_AUDIO) { p_dev->conf.Attributes |= CONF_ENABLE_SPKR; p_dev->conf.Status = CCSR_AUDIO_ENA; } if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM)) p_dev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM]/10000; else if (dflt->vpp1.present & (1<<CISTPL_POWER_VNOM)) p_dev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM]/10000; if (cfg->irq.IRQInfo1 || dflt->irq.IRQInfo1) p_dev->conf.Attributes |= CONF_ENABLE_IRQ; p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0; if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; if (!(io->flags & CISTPL_IO_8BIT)) p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16; if (!(io->flags & CISTPL_IO_16BIT)) p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; p_dev->io.BasePort1 = io->win[0].base; p_dev->io.NumPorts1 = io->win[0].len; if (io->nwin > 1) { p_dev->io.Attributes2 = p_dev->io.Attributes1; p_dev->io.BasePort2 = io->win[1].base; p_dev->io.NumPorts2 = io->win[1].len; } } if (pcmcia_request_io(p_dev, &p_dev->io) != 0) return -ENODEV; if ((cfg->mem.nwin > 0) || (dflt->mem.nwin > 0)) { cistpl_mem_t *mem = (cfg->mem.nwin) ? &cfg->mem : &dflt->mem; memreq_t map; req->Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM; req->Base = mem->win[0].host_addr; req->Size = mem->win[0].len; req->AccessSpeed = 0; if (pcmcia_request_window(&p_dev, req, &p_dev->win) != 0) return -ENODEV; map.Page = 0; map.CardOffset = mem->win[0].card_addr; if (pcmcia_map_mem_page(p_dev->win, &map) != 0) return -ENODEV; } return 0; }