void wl_adapter_insert( struct pcmcia_device *link ) { struct net_device *dev; int i; int ret; /*------------------------------------------------------------------------*/ DBG_FUNC( "wl_adapter_insert" ); DBG_ENTER( DbgInfo ); DBG_PARAM( DbgInfo, "link", "0x%p", link ); dev = link->priv; /* Do we need to allocate an interrupt? */ link->conf.Attributes |= CONF_ENABLE_IRQ; ret = pcmcia_request_io(link, &link->io); if (ret != 0) goto failed; ret = pcmcia_request_irq(link, (void *) wl_isr); if (ret != 0) goto failed; ret = pcmcia_request_configuration(link, &link->conf); if (ret != 0) goto failed; dev->irq = link->irq; dev->base_addr = link->io.BasePort1; SET_NETDEV_DEV(dev, &link->dev); if (register_netdev(dev) != 0) { printk("%s: register_netdev() failed\n", MODULE_NAME); goto failed; } register_wlags_sysfs(dev); printk(KERN_INFO "%s: Wireless, io_addr %#03lx, irq %d, ""mac_address ", dev->name, dev->base_addr, dev->irq); for( i = 0; i < ETH_ALEN; i++ ) { printk("%02X%c", dev->dev_addr[i], ((i < (ETH_ALEN-1)) ? ':' : '\n')); } DBG_LEAVE( DbgInfo ); return; failed: wl_adapter_release( link ); DBG_LEAVE(DbgInfo); return; } // wl_adapter_insert
void wl_adapter_insert(struct pcmcia_device *link) { struct net_device *dev; int i; int ret; /*--------------------------------------------------------------------*/ DBG_FUNC("wl_adapter_insert"); DBG_ENTER(DbgInfo); DBG_PARAM(DbgInfo, "link", "0x%p", link); dev = link->priv; /* Do we need to allocate an interrupt? */ link->config_flags |= CONF_ENABLE_IRQ; link->io_lines = 6; ret = pcmcia_request_io(link); if (ret != 0) goto failed; ret = pcmcia_request_irq(link, (void *) wl_isr); if (ret != 0) goto failed; ret = pcmcia_enable_device(link); if (ret != 0) goto failed; dev->irq = link->irq; dev->base_addr = link->resource[0]->start; SET_NETDEV_DEV(dev, &link->dev); if (register_netdev(dev) != 0) { ; goto failed; } register_wlags_sysfs(dev); // printk(KERN_INFO "%s: Wireless, io_addr %#03lx, irq %d, ""mac_address ", ; for (i = 0; i < ETH_ALEN; i++) ; DBG_LEAVE(DbgInfo); return; failed: wl_adapter_release(link); DBG_LEAVE(DbgInfo); return; } /* wl_adapter_insert */
static void pdacf_config(dev_link_t *link) { client_handle_t handle = link->handle; struct snd_pdacf *pdacf = link->priv; tuple_t tuple; cisparse_t *parse = NULL; config_info_t conf; u_short buf[32]; int last_fn, last_ret; snd_printdd(KERN_DEBUG "pdacf_config called\n"); parse = kmalloc(sizeof(*parse), GFP_KERNEL); if (! parse) { snd_printk(KERN_ERR "pdacf_config: cannot allocate\n"); return; } tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; tuple.Attributes = 0; tuple.TupleData = (cisdata_t *)buf; tuple.TupleDataMax = sizeof(buf); tuple.TupleOffset = 0; tuple.DesiredTuple = CISTPL_CONFIG; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, parse)); link->conf.ConfigBase = parse->config.base; link->conf.ConfigIndex = 0x5; kfree(parse); CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf)); link->conf.Vcc = conf.Vcc; /* Configure card */ link->state |= DEV_CONFIG; CS_CHECK(RequestIO, pcmcia_request_io(handle, &link->io)); CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf)); if (snd_pdacf_assign_resources(pdacf, link->io.BasePort1, link->irq.AssignedIRQ) < 0) goto failed; link->dev = &pdacf->node; link->state &= ~DEV_CONFIG_PENDING; return; cs_failed: cs_error(link->handle, last_fn, last_ret); failed: pcmcia_release_configuration(link->handle); pcmcia_release_io(link->handle, &link->io); pcmcia_release_irq(link->handle, &link->irq); }
static int atmel_config(struct pcmcia_device *link) { local_info_t *dev; int last_fn, last_ret; struct pcmcia_device_id *did; dev = link->priv; did = dev_get_drvdata(&handle_to_dev(link)); DEBUG(0, "atmel_config(0x%p)\n", link); if (pcmcia_loop_config(link, atmel_config_check, NULL)) goto failed; if (link->conf.Attributes & CONF_ENABLE_IRQ) CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); if (link->irq.AssignedIRQ == 0) { printk(KERN_ALERT "atmel: cannot assign IRQ: check that CONFIG_ISA is set in kernel config."); goto cs_failed; } ((local_info_t*)link->priv)->eth_dev = init_atmel_card(link->irq.AssignedIRQ, link->io.BasePort1, did ? did->driver_info : ATMEL_FW_TYPE_NONE, &handle_to_dev(link), card_present, link); if (!((local_info_t*)link->priv)->eth_dev) goto cs_failed; 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; return 0; cs_failed: cs_error(link, last_fn, last_ret); failed: atmel_release(link); return -ENODEV; }
static int qlogic_config(struct pcmcia_device * link) { scsi_info_t *info = link->priv; int last_ret, last_fn; struct Scsi_Host *host; DEBUG(0, "qlogic_config(0x%p)\n", link); last_ret = pcmcia_loop_config(link, qlogic_config_check, NULL); if (last_ret) { cs_error(link, RequestIO, last_ret); goto failed; } CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); if ((info->manf_id == MANFID_MACNICA) || (info->manf_id == MANFID_PIONEER) || (info->manf_id == 0x0098)) { /* set ATAcmd */ outb(0xb4, link->io.BasePort1 + 0xd); outb(0x24, link->io.BasePort1 + 0x9); outb(0x04, link->io.BasePort1 + 0xd); } /* The KXL-810AN has a bigger IO port window */ if (link->io.NumPorts1 == 32) host = qlogic_detect(&qlogicfas_driver_template, link, link->io.BasePort1 + 16, link->irq.AssignedIRQ); else host = qlogic_detect(&qlogicfas_driver_template, link, link->io.BasePort1, link->irq.AssignedIRQ); if (!host) { printk(KERN_INFO "%s: no SCSI devices found\n", qlogic_name); goto cs_failed; } sprintf(info->node.dev_name, "scsi%d", host->host_no); link->dev_node = &info->node; info->host = host; return 0; cs_failed: cs_error(link, last_fn, last_ret); pcmcia_disable_device(link); failed: return -ENODEV; } /* qlogic_config */
static int aha152x_config_cs(struct pcmcia_device *link) { scsi_info_t *info = link->priv; struct aha152x_setup s; int last_ret, last_fn; struct Scsi_Host *host; DEBUG(0, "aha152x_config(0x%p)\n", link); last_ret = pcmcia_loop_config(link, aha152x_config_check, NULL); if (last_ret) { cs_error(link, RequestIO, last_ret); goto failed; } CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); memset(&s, 0, sizeof(s)); s.conf = "PCMCIA setup"; s.io_port = link->io.BasePort1; s.irq = link->irq.AssignedIRQ; s.scsiid = host_id; s.reconnect = reconnect; s.parity = parity; s.synchronous = synchronous; s.delay = reset_delay; if (ext_trans) s.ext_trans = ext_trans; host = aha152x_probe_one(&s); if (host == NULL) { printk(KERN_INFO "aha152x_cs: no SCSI devices found\n"); goto cs_failed; } sprintf(info->node.dev_name, "scsi%d", host->host_no); link->dev_node = &info->node; info->host = host; return 0; cs_failed: cs_error(link, last_fn, last_ret); failed: aha152x_release_cs(link); return -ENODEV; }
static int sl811_cs_config(struct pcmcia_device *link) { struct device *parent = &link->dev; local_info_t *dev = link->priv; int ret; dev_dbg(&link->dev, "sl811_cs_config\n"); if (pcmcia_loop_config(link, sl811_cs_config_check, NULL)) goto failed; /* require an IRQ and two registers */ if (!link->io.NumPorts1 || link->io.NumPorts1 < 2) goto failed; if (link->conf.Attributes & CONF_ENABLE_IRQ) { ret = pcmcia_request_irq(link, &link->irq); if (ret) goto failed; } else goto failed; ret = pcmcia_request_configuration(link, &link->conf); if (ret) goto failed; sprintf(dev->node.dev_name, driver_name); 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.Vpp) printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10); printk(", irq %d", link->irq.AssignedIRQ); printk(", io 0x%04x-0x%04x", link->io.BasePort1, link->io.BasePort1+link->io.NumPorts1-1); printk("\n"); if (sl811_hc_init(parent, link->io.BasePort1, link->irq.AssignedIRQ) < 0) { failed: printk(KERN_WARNING "sl811_cs_config failed\n"); sl811_cs_release(link); return -ENODEV; } return 0; }
static int parport_config(struct pcmcia_device *link) { parport_info_t *info = link->priv; struct parport *p; int last_ret, last_fn; DEBUG(0, "parport_config(0x%p)\n", link); last_ret = pcmcia_loop_config(link, parport_config_check, NULL); if (last_ret) { cs_error(link, RequestIO, last_ret); goto failed; } CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); p = parport_pc_probe_port(link->io.BasePort1, link->io.BasePort2, link->irq.AssignedIRQ, PARPORT_DMA_NONE, &link->dev); if (p == NULL) { printk(KERN_NOTICE "parport_cs: parport_pc_probe_port() at " "0x%3x, irq %u failed\n", link->io.BasePort1, link->irq.AssignedIRQ); goto failed; } p->modes |= PARPORT_MODE_PCSPP; if (epp_mode) p->modes |= PARPORT_MODE_TRISTATE | PARPORT_MODE_EPP; info->ndev = 1; info->node.major = LP_MAJOR; info->node.minor = p->number; info->port = p; strcpy(info->node.dev_name, p->name); link->dev_node = &info->node; return 0; cs_failed: cs_error(link, last_fn, last_ret); failed: parport_cs_release(link); return -ENODEV; } /* parport_config */
static int bluecard_config(struct pcmcia_device *link) { bluecard_info_t *info = link->priv; int i, n; link->conf.ConfigIndex = 0x20; link->io.NumPorts1 = 64; link->io.IOAddrLines = 6; for (n = 0; n < 0x400; n += 0x40) { link->io.BasePort1 = n ^ 0x300; i = pcmcia_request_io(link, &link->io); if (i == CS_SUCCESS) break; } if (i != CS_SUCCESS) { cs_error(link, RequestIO, i); goto failed; } i = pcmcia_request_irq(link, &link->irq); if (i != CS_SUCCESS) { cs_error(link, RequestIRQ, i); link->irq.AssignedIRQ = 0; } i = pcmcia_request_configuration(link, &link->conf); if (i != CS_SUCCESS) { cs_error(link, RequestConfiguration, i); goto failed; } if (bluecard_open(info) != 0) goto failed; strcpy(info->node.dev_name, info->hdev->name); link->dev_node = &info->node; return 0; failed: bluecard_release(link); return -ENODEV; }
static int vxpocket_config(struct pcmcia_device *link) { struct vx_core *chip = link->priv; int ret; snd_printdd(KERN_DEBUG "vxpocket_config called\n"); /* redefine hardware record according to the VERSION1 string */ if (!strcmp(link->prod_id[1], "VX-POCKET")) { snd_printdd("VX-pocket is detected\n"); } else { snd_printdd("VX-pocket 440 is detected\n"); /* overwrite the hardware information */ chip->hw = &vxp440_hw; chip->type = vxp440_hw.type; strcpy(chip->card->driver, vxp440_hw.name); } ret = pcmcia_request_io(link); if (ret) goto failed; ret = pcmcia_request_irq(link, snd_vx_irq_handler); if (ret) goto failed; ret = pcmcia_enable_device(link); if (ret) goto failed; chip->dev = &link->dev; snd_card_set_dev(chip->card, chip->dev); if (snd_vxpocket_assign_resources(chip, link->resource[0]->start, link->irq) < 0) goto failed; return 0; failed: pcmcia_disable_device(link); return -ENODEV; }
static int pdacf_config(struct pcmcia_device *link) { struct snd_pdacf *pdacf = link->priv; tuple_t tuple; cisparse_t *parse = NULL; u_short buf[32]; int last_fn, last_ret; snd_printdd(KERN_DEBUG "pdacf_config called\n"); parse = kmalloc(sizeof(*parse), GFP_KERNEL); if (! parse) { snd_printk(KERN_ERR "pdacf_config: cannot allocate\n"); return -ENOMEM; } tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; tuple.Attributes = 0; tuple.TupleData = (cisdata_t *)buf; tuple.TupleDataMax = sizeof(buf); tuple.TupleOffset = 0; tuple.DesiredTuple = CISTPL_CONFIG; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, parse)); link->conf.ConfigBase = parse->config.base; link->conf.ConfigIndex = 0x5; kfree(parse); CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io)); CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); if (snd_pdacf_assign_resources(pdacf, link->io.BasePort1, link->irq.AssignedIRQ) < 0) goto failed; link->dev_node = &pdacf->node; return 0; cs_failed: cs_error(link, last_fn, last_ret); failed: pcmcia_disable_device(link); return -ENODEV; }
static int bluecard_config(struct pcmcia_device *link) { struct bluecard_info *info = link->priv; int i, n; link->config_index = 0x20; link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; link->resource[0]->end = 64; link->io_lines = 6; for (n = 0; n < 0x400; n += 0x40) { link->resource[0]->start = n ^ 0x300; i = pcmcia_request_io(link); if (i == 0) break; } if (i != 0) goto failed; i = pcmcia_request_irq(link, bluecard_interrupt); if (i != 0) goto failed; i = pcmcia_enable_device(link); if (i != 0) goto failed; if (bluecard_open(info) != 0) goto failed; return 0; failed: bluecard_release(link); return -ENODEV; }
static int pdacf_config(struct pcmcia_device *link) { struct snd_pdacf *pdacf = link->priv; int last_fn, last_ret; snd_printdd(KERN_DEBUG "pdacf_config called\n"); link->conf.ConfigIndex = 0x5; CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io)); CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); if (snd_pdacf_assign_resources(pdacf, link->io.BasePort1, link->irq.AssignedIRQ) < 0) goto failed; link->dev_node = &pdacf->node; return 0; cs_failed: cs_error(link, last_fn, last_ret); failed: pcmcia_disable_device(link); return -ENODEV; }
static int bluecard_config(struct pcmcia_device *link) { bluecard_info_t *info = link->priv; int i, n; link->conf.ConfigIndex = 0x20; link->io.NumPorts1 = 64; link->io.IOAddrLines = 6; for (n = 0; n < 0x400; n += 0x40) { link->io.BasePort1 = n ^ 0x300; i = pcmcia_request_io(link, &link->io); if (i == 0) break; } if (i != 0) goto failed; i = pcmcia_request_irq(link, bluecard_interrupt); if (i != 0) goto failed; i = pcmcia_request_configuration(link, &link->conf); if (i != 0) goto failed; if (bluecard_open(info) != 0) goto failed; return 0; failed: bluecard_release(link); return -ENODEV; }
static void sl811_cs_config(dev_link_t *link) { client_handle_t handle = link->handle; struct device *parent = &handle_to_dev(handle); local_info_t *dev = link->priv; tuple_t tuple; cisparse_t parse; int last_fn, last_ret; u_char buf[64]; config_info_t conf; cistpl_cftable_entry_t dflt = { 0 }; DBG(0, "sl811_cs_config(0x%p)\n", link); tuple.DesiredTuple = CISTPL_CONFIG; tuple.Attributes = 0; tuple.TupleData = buf; tuple.TupleDataMax = sizeof(buf); tuple.TupleOffset = 0; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; /* Configure card */ link->state |= DEV_CONFIG; /* Look up the current Vcc */ CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf)); link->conf.Vcc = conf.Vcc; tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); while (1) { cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); if (pcmcia_get_tuple_data(handle, &tuple) != 0 || pcmcia_parse_tuple(handle, &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; /* Use power settings for Vcc and Vpp if present */ /* Note that the CIS values need to be rescaled */ if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) { if (cfg->vcc.param[CISTPL_POWER_VNOM]/10000 != conf.Vcc) goto next_entry; } else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM)) { if (dflt.vcc.param[CISTPL_POWER_VNOM]/10000 != conf.Vcc) goto next_entry; } if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM)) link->conf.Vpp1 = link->conf.Vpp2 = cfg->vpp1.param[CISTPL_POWER_VNOM]/10000; else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM)) link->conf.Vpp1 = link->conf.Vpp2 = dflt.vpp1.param[CISTPL_POWER_VNOM]/10000; /* we need 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 (pcmcia_request_io(link->handle, &link->io) != 0) goto next_entry; } break; next_entry: if (link->io.NumPorts1) pcmcia_release_io(link->handle, &link->io); last_ret = pcmcia_get_next_tuple(handle, &tuple); } /* require an IRQ and two registers */ if (!link->io.NumPorts1 || link->io.NumPorts1 < 2) goto cs_failed; if (link->conf.Attributes & CONF_ENABLE_IRQ) CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); else goto cs_failed; CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf)); sprintf(dev->node.dev_name, driver_name); dev->node.major = dev->node.minor = 0; link->dev = &dev->node; printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d", dev->node.dev_name, link->conf.ConfigIndex, link->conf.Vcc/10, link->conf.Vcc%10); if (link->conf.Vpp1) printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10); printk(", irq %d", link->irq.AssignedIRQ); printk(", io 0x%04x-0x%04x", link->io.BasePort1, link->io.BasePort1+link->io.NumPorts1-1); printk("\n"); link->state &= ~DEV_CONFIG_PENDING; if (sl811_hc_init(parent, link->io.BasePort1, link->irq.AssignedIRQ) < 0) { cs_failed: printk("sl811_cs_config failed\n"); cs_error(link->handle, last_fn, last_ret); sl811_cs_release(link); link->state &= ~DEV_CONFIG_PENDING; } }
static int spectrum_cs_config(struct pcmcia_device *link) { struct orinoco_private *priv = link->priv; hermes_t *hw = &priv->hw; int ret; void __iomem *mem; /* * 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. */ ret = pcmcia_loop_config(link, spectrum_cs_config_check, NULL); if (ret) { if (!ignore_cis_vcc) printk(KERN_ERR PFX "GetNextTuple(): No matching " "CIS configuration. Maybe you need the " "ignore_cis_vcc=1 parameter.\n"); goto failed; } ret = pcmcia_request_irq(link, orinoco_interrupt); if (ret) goto failed; /* We initialize the hermes structure before completing PCMCIA * configuration just in case the interrupt handler gets * called. */ mem = ioport_map(link->io.BasePort1, link->io.NumPorts1); if (!mem) goto failed; hermes_struct_init(hw, mem, HERMES_16BIT_REGSPACING); hw->eeprom_pda = true; /* * 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; /* Reset card */ if (spectrum_cs_hard_reset(priv) != 0) goto failed; /* Initialise the main driver */ if (orinoco_init(priv) != 0) { printk(KERN_ERR PFX "orinoco_init() failed\n"); goto failed; } /* Register an interface with the stack */ if (orinoco_if_add(priv, link->io.BasePort1, link->irq, NULL) != 0) { printk(KERN_ERR PFX "orinoco_if_add() failed\n"); goto failed; } return 0; failed: spectrum_cs_release(link); return -ENODEV; } /* spectrum_cs_config */
static int tc589_config(struct pcmcia_device *link) { struct net_device *dev = link->priv; __be16 *phys_addr; int ret, i, j, multi = 0, fifo; unsigned int ioaddr; char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"}; u8 *buf; size_t len; dev_dbg(&link->dev, "3c589_config\n"); phys_addr = (__be16 *)dev->dev_addr; /* Is this a 3c562? */ if (link->manf_id != MANFID_3COM) printk(KERN_INFO "3c589_cs: hmmm, is this really a " "3Com card??\n"); multi = (link->card_id == PRODID_3COM_3C562); link->io_lines = 16; /* For the 3c562, the base address must be xx00-xx7f */ for (i = j = 0; j < 0x400; j += 0x10) { if (multi && (j & 0x80)) continue; link->resource[0]->start = j ^ 0x300; i = pcmcia_request_io(link); if (i == 0) break; } if (i != 0) goto failed; ret = pcmcia_request_irq(link, el3_interrupt); if (ret) goto failed; ret = pcmcia_request_configuration(link, &link->conf); if (ret) goto failed; dev->irq = link->irq; dev->base_addr = link->resource[0]->start; ioaddr = dev->base_addr; EL3WINDOW(0); /* The 3c589 has an extra EEPROM for configuration info, including the hardware address. The 3c562 puts the address in the CIS. */ len = pcmcia_get_tuple(link, 0x88, &buf); if (buf && len >= 6) { for (i = 0; i < 3; i++) phys_addr[i] = htons(le16_to_cpu(buf[i*2])); kfree(buf); } else { kfree(buf); /* 0 < len < 6 */ for (i = 0; i < 3; i++) phys_addr[i] = htons(read_eeprom(ioaddr, i)); if (phys_addr[0] == htons(0x6060)) { printk(KERN_ERR "3c589_cs: IO port conflict at 0x%03lx" "-0x%03lx\n", dev->base_addr, dev->base_addr+15); goto failed; } } /* The address and resource configuration register aren't loaded from the EEPROM and *must* be set to 0 and IRQ3 for the PCMCIA version. */ outw(0x3f00, ioaddr + 8); fifo = inl(ioaddr); /* The if_port symbol can be set when the module is loaded */ if ((if_port >= 0) && (if_port <= 3)) dev->if_port = if_port; else printk(KERN_ERR "3c589_cs: invalid if_port requested\n"); SET_NETDEV_DEV(dev, &link->dev); if (register_netdev(dev) != 0) { printk(KERN_ERR "3c589_cs: register_netdev() failed\n"); goto failed; } netdev_info(dev, "3Com 3c%s, io %#3lx, irq %d, hw_addr %pM\n", (multi ? "562" : "589"), dev->base_addr, dev->irq, dev->dev_addr); netdev_info(dev, " %dK FIFO split %s Rx:Tx, %s xcvr\n", (fifo & 7) ? 32 : 8, ram_split[(fifo >> 16) & 3], if_names[dev->if_port]); return 0; failed: tc589_release(link); return -ENODEV; } /* tc589_config */
static int tc589_config(struct pcmcia_device *link) { struct net_device *dev = link->priv; struct el3_private *lp = netdev_priv(dev); tuple_t tuple; __le16 buf[32]; __be16 *phys_addr; int last_fn, last_ret, i, j, multi = 0, fifo; unsigned int ioaddr; char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"}; DECLARE_MAC_BUF(mac); DEBUG(0, "3c589_config(0x%p)\n", link); phys_addr = (__be16 *)dev->dev_addr; tuple.Attributes = 0; tuple.TupleData = (cisdata_t *)buf; tuple.TupleDataMax = sizeof(buf); tuple.TupleOffset = 0; tuple.Attributes = TUPLE_RETURN_COMMON; /* Is this a 3c562? */ if (link->manf_id != MANFID_3COM) printk(KERN_INFO "3c589_cs: hmmm, is this really a " "3Com card??\n"); multi = (link->card_id == PRODID_3COM_3C562); /* For the 3c562, the base address must be xx00-xx7f */ link->io.IOAddrLines = 16; for (i = j = 0; j < 0x400; j += 0x10) { if (multi && (j & 0x80)) continue; link->io.BasePort1 = j ^ 0x300; i = pcmcia_request_io(link, &link->io); if (i == CS_SUCCESS) break; } if (i != CS_SUCCESS) { cs_error(link, RequestIO, i); goto failed; } CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); dev->irq = link->irq.AssignedIRQ; dev->base_addr = link->io.BasePort1; ioaddr = dev->base_addr; EL3WINDOW(0); /* The 3c589 has an extra EEPROM for configuration info, including the hardware address. The 3c562 puts the address in the CIS. */ tuple.DesiredTuple = 0x88; if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) { pcmcia_get_tuple_data(link, &tuple); for (i = 0; i < 3; i++) phys_addr[i] = htons(le16_to_cpu(buf[i])); } else { for (i = 0; i < 3; i++) phys_addr[i] = htons(read_eeprom(ioaddr, i)); if (phys_addr[0] == htons(0x6060)) { printk(KERN_ERR "3c589_cs: IO port conflict at 0x%03lx" "-0x%03lx\n", dev->base_addr, dev->base_addr+15); goto failed; } } /* The address and resource configuration register aren't loaded from the EEPROM and *must* be set to 0 and IRQ3 for the PCMCIA version. */ outw(0x3f00, ioaddr + 8); fifo = inl(ioaddr); /* The if_port symbol can be set when the module is loaded */ if ((if_port >= 0) && (if_port <= 3)) dev->if_port = if_port; else printk(KERN_ERR "3c589_cs: invalid if_port requested\n"); link->dev_node = &lp->node; SET_NETDEV_DEV(dev, &handle_to_dev(link)); if (register_netdev(dev) != 0) { printk(KERN_ERR "3c589_cs: register_netdev() failed\n"); link->dev_node = NULL; goto failed; } strcpy(lp->node.dev_name, dev->name); printk(KERN_INFO "%s: 3Com 3c%s, io %#3lx, irq %d, " "hw_addr %s\n", dev->name, (multi ? "562" : "589"), dev->base_addr, dev->irq, print_mac(mac, dev->dev_addr)); printk(KERN_INFO " %dK FIFO split %s Rx:Tx, %s xcvr\n", (fifo & 7) ? 32 : 8, ram_split[(fifo >> 16) & 3], if_names[dev->if_port]); return 0; cs_failed: cs_error(link, last_fn, last_ret); failed: tc589_release(link); return -ENODEV; } /* tc589_config */
static void aha152x_config_cs(dev_link_t *link) { client_handle_t handle = link->handle; scsi_info_t *info = link->priv; struct aha152x_setup s; tuple_t tuple; cisparse_t parse; int i, last_ret, last_fn; u_char tuple_data[64]; struct Scsi_Host *host; DEBUG(0, "aha152x_config(0x%p)\n", link); tuple.DesiredTuple = CISTPL_CONFIG; tuple.TupleData = tuple_data; tuple.TupleDataMax = 64; tuple.TupleOffset = 0; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); link->conf.ConfigBase = parse.config.base; /* Configure card */ link->state |= DEV_CONFIG; tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); while (1) { if (pcmcia_get_tuple_data(handle, &tuple) != 0 || pcmcia_parse_tuple(handle, &tuple, &parse) != 0) goto next_entry; /* For New Media T&J, look for a SCSI window */ if (parse.cftable_entry.io.win[0].len >= 0x20) link->io.BasePort1 = parse.cftable_entry.io.win[0].base; else if ((parse.cftable_entry.io.nwin > 1) && (parse.cftable_entry.io.win[1].len >= 0x20)) link->io.BasePort1 = parse.cftable_entry.io.win[1].base; if ((parse.cftable_entry.io.nwin > 0) && (link->io.BasePort1 < 0xffff)) { link->conf.ConfigIndex = parse.cftable_entry.index; i = pcmcia_request_io(handle, &link->io); if (i == CS_SUCCESS) break; } next_entry: CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple)); } CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq)); CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf)); /* Set configuration options for the aha152x driver */ memset(&s, 0, sizeof(s)); s.conf = "PCMCIA setup"; s.io_port = link->io.BasePort1; s.irq = link->irq.AssignedIRQ; s.scsiid = host_id; s.reconnect = reconnect; s.parity = parity; s.synchronous = synchronous; s.delay = reset_delay; if (ext_trans) s.ext_trans = ext_trans; host = aha152x_probe_one(&s); if (host == NULL) { printk(KERN_INFO "aha152x_cs: no SCSI devices found\n"); goto cs_failed; } sprintf(info->node.dev_name, "scsi%d", host->host_no); link->dev = &info->node; info->host = host; link->state &= ~DEV_CONFIG_PENDING; return; cs_failed: cs_error(link->handle, last_fn, last_ret); aha152x_release_cs(link); return; }
static int orinoco_cs_config(struct pcmcia_device *link) { struct net_device *dev = link->priv; struct orinoco_private *priv = netdev_priv(dev); struct orinoco_pccard *card = priv->card; hermes_t *hw = &priv->hw; int last_fn, last_ret; void __iomem *mem; /* * 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. */ last_ret = pcmcia_loop_config(link, orinoco_cs_config_check, NULL); if (last_ret) { if (!ignore_cis_vcc) printk(KERN_ERR PFX "GetNextTuple(): No matching " "CIS configuration. Maybe you need the " "ignore_cis_vcc=1 parameter.\n"); cs_error(link, RequestIO, last_ret); goto 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. */ CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); /* We initialize the hermes structure before completing PCMCIA * configuration just in case the interrupt handler gets * called. */ mem = ioport_map(link->io.BasePort1, link->io.NumPorts1); if (!mem) goto cs_failed; hermes_struct_init(hw, mem, HERMES_16BIT_REGSPACING); /* * 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)); /* Ok, we have the configuration, prepare to register the netdev */ dev->base_addr = link->io.BasePort1; dev->irq = link->irq.AssignedIRQ; card->node.major = card->node.minor = 0; SET_NETDEV_DEV(dev, &handle_to_dev(link)); /* Tell the stack we exist */ if (register_netdev(dev) != 0) { printk(KERN_ERR PFX "register_netdev() failed\n"); goto failed; } /* At this point, the dev_node_t structure(s) needs to be * initialized and arranged in a linked list at link->dev_node. */ strcpy(card->node.dev_name, dev->name); link->dev_node = &card->node; /* link->dev_node being non-NULL is also * used to indicate that the * net_device has been registered */ /* Finally, report what we've done */ printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s, irq %d, io " "0x%04x-0x%04x\n", dev->name, dev_name(dev->dev.parent), link->irq.AssignedIRQ, link->io.BasePort1, link->io.BasePort1 + link->io.NumPorts1 - 1); return 0; cs_failed: cs_error(link, last_fn, last_ret); failed: orinoco_cs_release(link); return -ENODEV; } /* orinoco_cs_config */
static int nmclan_config(struct pcmcia_device *link) { struct net_device *dev = link->priv; mace_private *lp = netdev_priv(dev); tuple_t tuple; u_char buf[64]; int i, last_ret, last_fn; kio_addr_t ioaddr; DEBUG(0, "nmclan_config(0x%p)\n", link); CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io)); CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); dev->irq = link->irq.AssignedIRQ; dev->base_addr = link->io.BasePort1; ioaddr = dev->base_addr; /* Read the ethernet address from the CIS. */ tuple.DesiredTuple = 0x80 /* CISTPL_CFTABLE_ENTRY_MISC */; tuple.TupleData = buf; tuple.TupleDataMax = 64; tuple.TupleOffset = 0; tuple.Attributes = 0; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); memcpy(dev->dev_addr, tuple.TupleData, ETHER_ADDR_LEN); /* Verify configuration by reading the MACE ID. */ { char sig[2]; sig[0] = mace_read(lp, ioaddr, MACE_CHIPIDL); sig[1] = mace_read(lp, ioaddr, MACE_CHIPIDH); if ((sig[0] == 0x40) && ((sig[1] & 0x0F) == 0x09)) { DEBUG(0, "nmclan_cs configured: mace id=%x %x\n", sig[0], sig[1]); } else { printk(KERN_NOTICE "nmclan_cs: mace id not found: %x %x should" " be 0x40 0x?9\n", sig[0], sig[1]); return -ENODEV; } } if(mace_init(lp, ioaddr, dev->dev_addr) == -1) goto failed; /* The if_port symbol can be set when the module is loaded */ if (if_port <= 2) dev->if_port = if_port; else printk(KERN_NOTICE "nmclan_cs: invalid if_port requested\n"); link->dev_node = &lp->node; SET_NETDEV_DEV(dev, &handle_to_dev(link)); i = register_netdev(dev); if (i != 0) { printk(KERN_NOTICE "nmclan_cs: register_netdev() failed\n"); link->dev_node = NULL; goto failed; } strcpy(lp->node.dev_name, dev->name); printk(KERN_INFO "%s: nmclan: port %#3lx, irq %d, %s port, hw_addr ", dev->name, dev->base_addr, dev->irq, if_names[dev->if_port]); for (i = 0; i < 6; i++) printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n")); return 0; cs_failed: cs_error(link, last_fn, last_ret); failed: nmclan_release(link); return -ENODEV; } /* nmclan_config */
static int ide_config(struct pcmcia_device *link) { ide_info_t *info = link->priv; struct pcmcia_config_check *stk = NULL; int ret = 0, is_kme = 0; unsigned long io_base, ctl_base; struct ide_host *host; dev_dbg(&link->dev, "ide_config(0x%p)\n", link); is_kme = ((link->manf_id == MANFID_KME) && ((link->card_id == PRODID_KME_KXLC005_A) || (link->card_id == PRODID_KME_KXLC005_B))); stk = kzalloc(sizeof(*stk), GFP_KERNEL); if (!stk) goto err_mem; stk->is_kme = is_kme; stk->skip_vcc = io_base = ctl_base = 0; if (pcmcia_loop_config(link, pcmcia_check_one_config, stk)) { stk->skip_vcc = 1; if (pcmcia_loop_config(link, pcmcia_check_one_config, stk)) goto failed; /* No suitable config found */ } io_base = link->io.BasePort1; ctl_base = stk->ctl_base; ret = pcmcia_request_irq(link, &link->irq); if (ret) goto failed; ret = pcmcia_request_configuration(link, &link->conf); if (ret) goto failed; /* disable drive interrupts during IDE probe */ outb(0x02, ctl_base); /* special setup for KXLC005 card */ if (is_kme) outb(0x81, ctl_base+1); host = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ, link); if (host == NULL && link->io.NumPorts1 == 0x20) { outb(0x02, ctl_base + 0x10); host = idecs_register(io_base + 0x10, ctl_base + 0x10, link->irq.AssignedIRQ, link); } if (host == NULL) goto failed; info->ndev = 1; sprintf(info->node.dev_name, "hd%c", 'a' + host->ports[0]->index * 2); info->node.major = host->ports[0]->major; info->node.minor = 0; info->host = host; link->dev_node = &info->node; printk(KERN_INFO "ide-cs: %s: Vpp = %d.%d\n", info->node.dev_name, link->conf.Vpp / 10, link->conf.Vpp % 10); kfree(stk); return 0; err_mem: printk(KERN_NOTICE "ide-cs: ide_config failed memory allocation\n"); goto failed; failed: kfree(stk); ide_release(link); return -ENODEV; } /* ide_config */
void prism2sta_config(dev_link_t *link) { client_handle_t handle; wlandevice_t *wlandev; hfa384x_t *hw; int last_fn; int last_ret; tuple_t tuple; cisparse_t parse; config_info_t socketconf; UINT8 buf[64]; int minVcc = 0; int maxVcc = 0; cistpl_cftable_entry_t dflt = { 0 }; DBFENTER; handle = link->handle; wlandev = (wlandevice_t*)link->priv; hw = wlandev->priv; /* Collect the config register info */ tuple.DesiredTuple = CISTPL_CONFIG; tuple.Attributes = 0; tuple.TupleData = buf; tuple.TupleDataMax = sizeof(buf); tuple.TupleOffset = 0; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; /* Configure card */ link->state |= DEV_CONFIG; /* Acquire the current socket config (need Vcc setting) */ CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &socketconf)); /* Loop through the config table entries until we find one that works */ /* Assumes a complete and valid CIS */ tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); while (1) { cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); CFG_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); CFG_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); if (cfg->index == 0) goto next_entry; link->conf.ConfigIndex = cfg->index; /* Lets print out the Vcc that the controller+pcmcia-cs set * for us, cause that's what we're going to use. */ WLAN_LOG_DEBUG(1,"Initial Vcc=%d/10v\n", socketconf.Vcc); if (prism2_ignorevcc) { link->conf.Vcc = socketconf.Vcc; goto skipvcc; } /* Use power settings for Vcc and Vpp if present */ /* Note that the CIS values need to be rescaled */ if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) { WLAN_LOG_DEBUG(1, "Vcc obtained from curtupl.VNOM\n"); minVcc = maxVcc = cfg->vcc.param[CISTPL_POWER_VNOM]/10000; } else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM)) { WLAN_LOG_DEBUG(1, "Vcc set from dflt.VNOM\n"); minVcc = maxVcc = dflt.vcc.param[CISTPL_POWER_VNOM]/10000; } else if ((cfg->vcc.present & (1<<CISTPL_POWER_VMAX)) && (cfg->vcc.present & (1<<CISTPL_POWER_VMIN)) ) { WLAN_LOG_DEBUG(1, "Vcc set from curtupl(VMIN,VMAX)\n"); minVcc = cfg->vcc.param[CISTPL_POWER_VMIN]/10000; maxVcc = cfg->vcc.param[CISTPL_POWER_VMAX]/10000; } else if ((dflt.vcc.present & (1<<CISTPL_POWER_VMAX)) && (dflt.vcc.present & (1<<CISTPL_POWER_VMIN)) ) { WLAN_LOG_DEBUG(1, "Vcc set from dflt(VMIN,VMAX)\n"); minVcc = dflt.vcc.param[CISTPL_POWER_VMIN]/10000; maxVcc = dflt.vcc.param[CISTPL_POWER_VMAX]/10000; } if ( socketconf.Vcc >= minVcc && socketconf.Vcc <= maxVcc) { link->conf.Vcc = socketconf.Vcc; } else { /* [MSM]: Note that I've given up trying to change * the Vcc if a change is indicated. It seems the * system&socketcontroller&card vendors can't seem * to get it right, so I'm tired of trying to hack * my way around it. pcmcia-cs does its best using * the voltage sense pins but sometimes the controller * lies. Then, even if we have a good read on the VS * pins, some system designs will silently ignore our * requests to set the voltage. Additionally, some * vendors have 3.3v indicated on their sense pins, * but 5v specified in the CIS or vice-versa. I've * had it. My only recommendation is "let the buyer * beware". Your system might supply 5v to a 3v card * (possibly causing damage) or a 3v capable system * might supply 5v to a 3v capable card (wasting * precious battery life). * My only recommendation (if you care) is to get * yourself an extender card (I don't know where, I * have only one myself) and a meter and test it for * yourself. */ goto next_entry; } skipvcc: WLAN_LOG_DEBUG(1, "link->conf.Vcc=%d\n", link->conf.Vcc); /* Do we need to allocate an interrupt? */ /* HACK: due to a bad CIS....we ALWAYS need 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; if ( link->io.BasePort1 != 0 ) { WLAN_LOG_WARNING( "Brain damaged CIS: hard coded iobase=" "0x%x, try letting pcmcia_cs decide...\n", link->io.BasePort1 ); link->io.BasePort1 = 0; } 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 */ CFG_CHECK(RequestIO, pcmcia_request_io(link->handle, &link->io)); /* If we got this far, we're cool! */ break; next_entry: if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg; CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &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) { #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) ) int i; link->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_LEVEL_ID; if (irq_list[0] == -1) link->irq.IRQInfo2 = irq_mask; else for (i=0; i<4; i++) link->irq.IRQInfo2 |= 1 << irq_list[i]; #else link->irq.IRQInfo1 = IRQ_LEVEL_ID; #endif link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; link->irq.Handler = hfa384x_interrupt; link->irq.Instance = wlandev; CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &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->handle, &link->conf)); /* Fill the netdevice with this info */ wlandev->netdev->irq = link->irq.AssignedIRQ; wlandev->netdev->base_addr = link->io.BasePort1; /* Report what we've done */ WLAN_LOG_INFO("%s: index 0x%02x: Vcc %d.%d", dev_info, link->conf.ConfigIndex, link->conf.Vcc/10, link->conf.Vcc%10); if (link->conf.Vpp1) printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%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); printk("\n"); link->state &= ~DEV_CONFIG_PENDING; /* Let pcmcia know the device name */ link->dev = &hw->node; /* Register the network device and get assigned a name */ SET_MODULE_OWNER(wlandev->netdev); #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11) ) SET_NETDEV_DEV(wlandev->netdev, &handle_to_dev(link->handle)); #endif if (register_wlandev(wlandev) != 0) { WLAN_LOG_NOTICE("prism2sta_cs: register_wlandev() failed.\n"); goto failed; } strcpy(hw->node.dev_name, wlandev->name); /* Any device custom config/query stuff should be done here */ /* For a netdevice, we should at least grab the mac address */ return; cs_failed: cs_error(link->handle, last_fn, last_ret); WLAN_LOG_ERROR("NextTuple failure? It's probably a Vcc mismatch.\n"); failed: prism2sta_release((u_long)link); return; }
static void elsa_cs_config(dev_link_t *link) { client_handle_t handle; tuple_t tuple; cisparse_t parse; local_info_t *dev; int i, j, last_fn; u_short buf[128]; cistpl_cftable_entry_t *cf = &parse.cftable_entry; IsdnCard_t icard; DEBUG(0, "elsa_config(0x%p)\n", link); handle = link->handle; dev = link->priv; /* This reads the card's CONFIG tuple to find its configuration registers. */ tuple.DesiredTuple = CISTPL_CONFIG; tuple.TupleData = (cisdata_t *)buf; tuple.TupleDataMax = 255; tuple.TupleOffset = 0; tuple.Attributes = 0; i = first_tuple(handle, &tuple, &parse); if (i != CS_SUCCESS) { last_fn = ParseTuple; goto cs_failed; } link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; /* Configure card */ link->state |= DEV_CONFIG; 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) && cf->io.win[0].base) { printk(KERN_INFO "(elsa_cs: looks like the 96 model)\n"); link->conf.ConfigIndex = cf->index; link->io.BasePort1 = cf->io.win[0].base; i = pcmcia_request_io(link->handle, &link->io); if (i == CS_SUCCESS) break; } else { printk(KERN_INFO "(elsa_cs: looks like the 97 model)\n"); link->conf.ConfigIndex = cf->index; for (i = 0, j = 0x2f0; j > 0x100; j -= 0x10) { link->io.BasePort1 = j; i = pcmcia_request_io(link->handle, &link->io); if (i == CS_SUCCESS) break; } break; } i = next_tuple(handle, &tuple, &parse); } if (i != CS_SUCCESS) { last_fn = RequestIO; goto cs_failed; } i = pcmcia_request_irq(link->handle, &link->irq); if (i != CS_SUCCESS) { link->irq.AssignedIRQ = 0; last_fn = RequestIRQ; goto cs_failed; } i = pcmcia_request_configuration(link->handle, &link->conf); if (i != CS_SUCCESS) { last_fn = RequestConfiguration; goto cs_failed; } /* At this point, the dev_node_t structure(s) should be initialized and arranged in a linked list at link->dev. *//* */ sprintf(dev->node.dev_name, "elsa"); dev->node.major = dev->node.minor = 0x0; link->dev = &dev->node; /* Finally, report what we've done */ printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d", dev->node.dev_name, link->conf.ConfigIndex, link->conf.Vcc/10, link->conf.Vcc%10); if (link->conf.Vpp1) printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%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); printk("\n"); link->state &= ~DEV_CONFIG_PENDING; icard.para[0] = link->irq.AssignedIRQ; icard.para[1] = link->io.BasePort1; icard.protocol = protocol; icard.typ = ISDN_CTYPE_ELSA_PCMCIA; i = hisax_init_pcmcia(link, &(((local_info_t*)link->priv)->busy), &icard); if (i < 0) { printk(KERN_ERR "elsa_cs: failed to initialize Elsa PCMCIA %d at i/o %#x\n", i, link->io.BasePort1); elsa_cs_release(link); } else ((local_info_t*)link->priv)->cardnr = i; return; cs_failed: cs_error(link->handle, last_fn, i); elsa_cs_release(link); } /* elsa_cs_config */
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 prism2_config(struct pcmcia_device *link) { struct net_device *dev; struct hostap_interface *iface; local_info_t *local; int ret = 1; struct hostap_cs_priv *hw_priv; unsigned long flags; PDEBUG(DEBUG_FLOW, "prism2_config()\n"); hw_priv = kzalloc(sizeof(*hw_priv), GFP_KERNEL); if (hw_priv == NULL) { ret = -ENOMEM; goto failed; } /* Look for an appropriate configuration table entry in the CIS */ link->config_flags |= CONF_AUTO_SET_VPP | CONF_AUTO_AUDIO | CONF_AUTO_CHECK_VCC | CONF_AUTO_SET_IO | CONF_ENABLE_IRQ; if (ignore_cis_vcc) link->config_flags &= ~CONF_AUTO_CHECK_VCC; ret = pcmcia_loop_config(link, prism2_config_check, NULL); if (ret) { if (!ignore_cis_vcc) printk(KERN_ERR "GetNextTuple(): No matching " "CIS configuration. Maybe you need the " "ignore_cis_vcc=1 parameter.\n"); goto failed; } /* Need to allocate net_device before requesting IRQ handler */ dev = prism2_init_local_data(&prism2_pccard_funcs, 0, &link->dev); if (dev == NULL) goto failed; link->priv = dev; iface = netdev_priv(dev); local = iface->local; local->hw_priv = hw_priv; hw_priv->link = link; /* * We enable IRQ here, but IRQ handler will not proceed * until dev->base_addr is set below. This protect us from * receive interrupts when driver is not initialized. */ ret = pcmcia_request_irq(link, prism2_interrupt); if (ret) goto failed; ret = pcmcia_enable_device(link); if (ret) goto failed; spin_lock_irqsave(&local->irq_init_lock, flags); dev->irq = link->irq; dev->base_addr = link->resource[0]->start; spin_unlock_irqrestore(&local->irq_init_lock, flags); local->shutdown = 0; sandisk_enable_wireless(dev); ret = prism2_hw_config(dev, 1); if (!ret) ret = hostap_hw_ready(dev); return ret; failed: kfree(hw_priv); prism2_release((u_long)link); return ret; }
static int ide_config(struct pcmcia_device *link) { ide_info_t *info = link->priv; tuple_t tuple; struct { u_short buf[128]; cisparse_t parse; config_info_t conf; cistpl_cftable_entry_t dflt; } *stk = NULL; cistpl_cftable_entry_t *cfg; int i, pass, last_ret = 0, last_fn = 0, hd, is_kme = 0; unsigned long io_base, ctl_base; DEBUG(0, "ide_config(0x%p)\n", link); stk = kzalloc(sizeof(*stk), GFP_KERNEL); if (!stk) goto err_mem; cfg = &stk->parse.cftable_entry; tuple.TupleData = (cisdata_t *)&stk->buf; tuple.TupleOffset = 0; tuple.TupleDataMax = 255; tuple.Attributes = 0; is_kme = ((link->manf_id == MANFID_KME) && ((link->card_id == PRODID_KME_KXLC005_A) || (link->card_id == PRODID_KME_KXLC005_B))); /* Not sure if this is right... look up the current Vcc */ CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &stk->conf)); pass = io_base = ctl_base = 0; tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; tuple.Attributes = 0; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); while (1) { if (pcmcia_get_tuple_data(link, &tuple) != 0) goto next_entry; if (pcmcia_parse_tuple(link, &tuple, &stk->parse) != 0) goto next_entry; /* Check for matching Vcc, unless we're desperate */ if (!pass) { if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) { if (stk->conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) goto next_entry; } else if (stk->dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) { if (stk->conf.Vcc != stk->dflt.vcc.param[CISTPL_POWER_VNOM] / 10000) goto next_entry; } } if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) link->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; else if (stk->dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) link->conf.Vpp = stk->dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000; if ((cfg->io.nwin > 0) || (stk->dflt.io.nwin > 0)) { cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &stk->dflt.io; link->conf.ConfigIndex = cfg->index; link->io.BasePort1 = io->win[0].base; link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; if (!(io->flags & CISTPL_IO_16BIT)) link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; if (io->nwin == 2) { link->io.NumPorts1 = 8; link->io.BasePort2 = io->win[1].base; link->io.NumPorts2 = (is_kme) ? 2 : 1; if (pcmcia_request_io(link, &link->io) != 0) goto next_entry; io_base = link->io.BasePort1; ctl_base = link->io.BasePort2; } else if ((io->nwin == 1) && (io->win[0].len >= 16)) { link->io.NumPorts1 = io->win[0].len; link->io.NumPorts2 = 0; if (pcmcia_request_io(link, &link->io) != 0) goto next_entry; io_base = link->io.BasePort1; ctl_base = link->io.BasePort1 + 0x0e; } else goto next_entry; /* If we've got this far, we're done */ break; } next_entry: if (cfg->flags & CISTPL_CFTABLE_DEFAULT) memcpy(&stk->dflt, cfg, sizeof(stk->dflt)); if (pass) { CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple)); } else if (pcmcia_get_next_tuple(link, &tuple) != 0) { CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); memset(&stk->dflt, 0, sizeof(stk->dflt)); pass++; } } CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); /* disable drive interrupts during IDE probe */ outb(0x02, ctl_base); /* special setup for KXLC005 card */ if (is_kme) outb(0x81, ctl_base+1); /* retry registration in case device is still spinning up */ for (hd = -1, i = 0; i < 10; i++) { hd = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ, link); if (hd >= 0) break; if (link->io.NumPorts1 == 0x20) { outb(0x02, ctl_base + 0x10); hd = idecs_register(io_base + 0x10, ctl_base + 0x10, link->irq.AssignedIRQ, link); if (hd >= 0) { io_base += 0x10; ctl_base += 0x10; break; } } msleep(100); } if (hd < 0) { printk(KERN_NOTICE "ide-cs: ide_register() at 0x%3lx & 0x%3lx" ", irq %u failed\n", io_base, ctl_base, link->irq.AssignedIRQ); goto failed; } info->ndev = 1; sprintf(info->node.dev_name, "hd%c", 'a' + (hd * 2)); info->node.major = ide_major[hd]; info->node.minor = 0; info->hd = hd; link->dev_node = &info->node; printk(KERN_INFO "ide-cs: %s: Vpp = %d.%d\n", info->node.dev_name, link->conf.Vpp / 10, link->conf.Vpp % 10); kfree(stk); return 0; err_mem: printk(KERN_NOTICE "ide-cs: ide_config failed memory allocation\n"); goto failed; cs_failed: cs_error(link, last_fn, last_ret); failed: kfree(stk); ide_release(link); return -ENODEV; } /* ide_config */
static int btuart_config(struct pcmcia_device *link) { static kio_addr_t base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 }; btuart_info_t *info = link->priv; tuple_t tuple; u_short buf[256]; cisparse_t parse; cistpl_cftable_entry_t *cf = &parse.cftable_entry; int i, j, try; /* First pass: look for a config entry that looks normal. */ tuple.TupleData = (cisdata_t *) buf; tuple.TupleOffset = 0; tuple.TupleDataMax = 255; tuple.Attributes = 0; tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; /* Two tries: without IO aliases, then with aliases */ for (try = 0; try < 2; try++) { i = first_tuple(link, &tuple, &parse); while (i != CS_NO_MORE_ITEMS) { if (i != CS_SUCCESS) goto next_entry; if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM)) link->conf.Vpp = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000; if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) && (cf->io.win[0].base != 0)) { link->conf.ConfigIndex = cf->index; link->io.BasePort1 = cf->io.win[0].base; link->io.IOAddrLines = (try == 0) ? 16 : cf->io.flags & CISTPL_IO_LINES_MASK; i = pcmcia_request_io(link, &link->io); if (i == CS_SUCCESS) goto found_port; } next_entry: i = next_tuple(link, &tuple, &parse); } } /* Second pass: try to find an entry that isn't picky about its base address, then try to grab any standard serial port address, and finally try to get any free port. */ i = first_tuple(link, &tuple, &parse); while (i != CS_NO_MORE_ITEMS) { if ((i == CS_SUCCESS) && (cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) { link->conf.ConfigIndex = cf->index; for (j = 0; j < 5; j++) { link->io.BasePort1 = base[j]; link->io.IOAddrLines = base[j] ? 16 : 3; 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) { BT_ERR("No usable port range found"); cs_error(link, RequestIO, i); goto failed; } i = pcmcia_request_irq(link, &link->irq); if (i != CS_SUCCESS) { cs_error(link, RequestIRQ, i); link->irq.AssignedIRQ = 0; } i = pcmcia_request_configuration(link, &link->conf); if (i != CS_SUCCESS) { cs_error(link, RequestConfiguration, i); goto failed; } if (btuart_open(info) != 0) goto failed; strcpy(info->node.dev_name, info->hdev->name); link->dev_node = &info->node; return 0; failed: btuart_release(link); return -ENODEV; }
static int com20020_config(struct pcmcia_device *link) { struct arcnet_local *lp; tuple_t tuple; cisparse_t parse; com20020_dev_t *info; struct net_device *dev; int i, last_ret, last_fn; u_char buf[64]; int ioaddr; info = link->priv; dev = info->dev; DEBUG(1,"config...\n"); DEBUG(0, "com20020_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(link, &tuple)); CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); link->conf.ConfigBase = parse.config.base; DEBUG(1,"arcnet: baseport1 is %Xh\n", link->io.BasePort1); i = !CS_SUCCESS; if (!link->io.BasePort1) { for (ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x10) { link->io.BasePort1 = ioaddr; i = pcmcia_request_io(link, &link->io); if (i == CS_SUCCESS) break; } } else i = pcmcia_request_io(link, &link->io); if (i != CS_SUCCESS) { DEBUG(1,"arcnet: requestIO failed totally!\n"); goto failed; } ioaddr = dev->base_addr = link->io.BasePort1; DEBUG(1,"arcnet: got ioaddr %Xh\n", ioaddr); DEBUG(1,"arcnet: request IRQ %d (%Xh/%Xh)\n", link->irq.AssignedIRQ, link->irq.IRQInfo1, link->irq.IRQInfo2); i = pcmcia_request_irq(link, &link->irq); if (i != CS_SUCCESS) { DEBUG(1,"arcnet: requestIRQ failed totally!\n"); goto failed; } dev->irq = link->irq.AssignedIRQ; CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); if (com20020_check(dev)) { regdump(dev); goto failed; } lp = dev->priv; lp->card_name = "PCMCIA COM20020"; lp->card_flags = ARC_CAN_10MBIT; /* pretend all of them can 10Mbit */ link->dev_node = &info->node; SET_NETDEV_DEV(dev, &handle_to_dev(link)); i = com20020_found(dev, 0); /* calls register_netdev */ if (i != 0) { DEBUG(1,KERN_NOTICE "com20020_cs: com20020_found() failed\n"); link->dev_node = NULL; goto failed; } strcpy(info->node.dev_name, dev->name); DEBUG(1,KERN_INFO "%s: port %#3lx, irq %d\n", dev->name, dev->base_addr, dev->irq); return 0; cs_failed: cs_error(link, last_fn, last_ret); failed: DEBUG(1,"com20020_config failed...\n"); com20020_release(link); return -ENODEV; } /* com20020_config */
static int prism2_cs_probe(struct pcmcia_device *pdev) { int rval = 0; struct wlandevice *wlandev = NULL; hfa384x_t *hw = NULL; config_info_t socketconf; cisparse_t *parse = NULL; tuple_t tuple; uint8_t buf[64]; int last_fn, last_ret; cistpl_cftable_entry_t dflt = { 0 }; #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) dev_link_t *link; #endif DBFENTER; #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) /* Set up interrupt type */ pdev->conf.IntType = INT_MEMORY_AND_IO; #else link = kmalloc(sizeof(dev_link_t), GFP_KERNEL); if (link == NULL) return -ENOMEM; memset(link, 0, sizeof(dev_link_t)); link->conf.Vcc = 33; link->conf.IntType = INT_MEMORY_AND_IO; link->handle = pdev; pdev->instance = link; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; #endif // VCC crap? parse = kmalloc(sizeof(cisparse_t), GFP_KERNEL); wlandev = create_wlan(); if (!wlandev || !parse) { WLAN_LOG_ERROR("%s: Memory allocation failure.\n", dev_info); rval = -EIO; goto failed; } hw = wlandev->priv; if ( wlan_setup(wlandev) != 0 ) { WLAN_LOG_ERROR("%s: wlan_setup() failed.\n", dev_info); rval = -EIO; goto failed; } /* Initialize the hw struct for now */ hfa384x_create(hw, 0, 0, NULL); hw->wlandev = wlandev; #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) hw->pdev = pdev; pdev->priv = wlandev; #else hw->link = link; link->priv = wlandev; #endif tuple.DesiredTuple = CISTPL_CONFIG; tuple.Attributes = 0; tuple.TupleData = buf; tuple.TupleDataMax = sizeof(buf); tuple.TupleOffset = 0; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(pdev, &tuple)); CS_CHECK(GetTupleData, pcmcia_get_tuple_data(pdev, &tuple)); CS_CHECK(ParseTuple, pcmcia_parse_tuple(pdev, &tuple, parse)); #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) pdev->conf.ConfigBase = parse->config.base; pdev->conf.Present = parse->config.rmask[0]; #else link->conf.ConfigBase = parse->config.base; link->conf.Present = parse->config.rmask[0]; link->conf.Vcc = socketconf.Vcc; #endif CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(pdev, &socketconf)); tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(pdev, &tuple)); for (;;) { cistpl_cftable_entry_t *cfg = &(parse->cftable_entry); CFG_CHECK(GetTupleData, pcmcia_get_tuple_data(pdev, &tuple)); CFG_CHECK(ParseTuple, pcmcia_parse_tuple(pdev, &tuple, parse)); if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg; if (cfg->index == 0) goto next_entry; #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) pdev->conf.ConfigIndex = cfg->index; #else link->conf.ConfigIndex = cfg->index; #endif /* Does this card need audio output? */ if (cfg->flags & CISTPL_CFTABLE_AUDIO) { #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) pdev->conf.Attributes |= CONF_ENABLE_SPKR; pdev->conf.Status = CCSR_AUDIO_ENA; #else link->conf.Attributes |= CONF_ENABLE_SPKR; link->conf.Status = CCSR_AUDIO_ENA; #endif } /* Use power settings for Vcc and Vpp if present */ /* Note that the CIS values need to be rescaled */ if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) { if (socketconf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000 && !prism2_ignorevcc) { WLAN_LOG_DEBUG(1, " Vcc mismatch - skipping" " this entry\n"); goto next_entry; } } else if (dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) { if (socketconf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM] / 10000 && !prism2_ignorevcc) { WLAN_LOG_DEBUG(1, " Vcc (default) mismatch " "- skipping this entry\n"); goto next_entry; } } if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) { #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) pdev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; #else link->conf.Vpp1 = link->conf.Vpp2 = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; #endif } else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) { #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) pdev->conf.Vpp = dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000; #else link->conf.Vpp1 = link->conf.Vpp2 = dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000; #endif } /* Do we need to allocate an interrupt? */ /* HACK: due to a bad CIS....we ALWAYS need an interrupt */ /* if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1) */ #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) pdev->conf.Attributes |= CONF_ENABLE_IRQ; #else link->conf.Attributes |= CONF_ENABLE_IRQ; #endif /* IO window settings */ #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) pdev->io.NumPorts1 = pdev->io.NumPorts2 = 0; if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; pdev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; if (!(io->flags & CISTPL_IO_8BIT)) pdev->io.Attributes1 = IO_DATA_PATH_WIDTH_16; if (!(io->flags & CISTPL_IO_16BIT)) pdev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; pdev->io.BasePort1 = io->win[0].base; if ( pdev->io.BasePort1 != 0 ) { WLAN_LOG_WARNING( "Brain damaged CIS: hard coded iobase=" "0x%x, try letting pcmcia_cs decide...\n", pdev->io.BasePort1 ); pdev->io.BasePort1 = 0; } pdev->io.NumPorts1 = io->win[0].len; if (io->nwin > 1) { pdev->io.Attributes2 = pdev->io.Attributes1; pdev->io.BasePort2 = io->win[1].base; pdev->io.NumPorts2 = io->win[1].len; } } /* This reserves IO space but doesn't actually enable it */ CFG_CHECK(RequestIO, pcmcia_request_io(pdev, &pdev->io)); #else 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; if ( link->io.BasePort1 != 0 ) { WLAN_LOG_WARNING( "Brain damaged CIS: hard coded iobase=" "0x%x, try letting pcmcia_cs decide...\n", link->io.BasePort1 ); link->io.BasePort1 = 0; } 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 */ CFG_CHECK(RequestIO, pcmcia_request_io(pdev, &link->io)); #endif /* If we got this far, we're cool! */ break; next_entry: if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg; CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(pdev, &tuple)); } /* Let pcmcia know the device name */ #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) pdev->dev_node = &hw->node; #else link->dev = &hw->node; #endif /* Register the network device and get assigned a name */ SET_MODULE_OWNER(wlandev->netdev); SET_NETDEV_DEV(wlandev->netdev, &handle_to_dev(pdev)); if (register_wlandev(wlandev) != 0) { WLAN_LOG_NOTICE("prism2sta_cs: register_wlandev() failed.\n"); goto failed; } strcpy(hw->node.dev_name, wlandev->name); /* 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 LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) if (pdev->conf.Attributes & CONF_ENABLE_IRQ) { pdev->irq.IRQInfo1 = IRQ_LEVEL_ID; pdev->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; pdev->irq.Handler = hfa384x_interrupt; pdev->irq.Instance = wlandev; CS_CHECK(RequestIRQ, pcmcia_request_irq(pdev, &pdev->irq)); } #else if (link->conf.Attributes & CONF_ENABLE_IRQ) { link->irq.IRQInfo1 = IRQ_LEVEL_ID; link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; link->irq.Handler = hfa384x_interrupt; link->irq.Instance = wlandev; CS_CHECK(RequestIRQ, pcmcia_request_irq(pdev, &link->irq)); } #endif /* 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. */ #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) CS_CHECK(RequestConfiguration, pcmcia_request_configuration(pdev, &pdev->conf)); #else CS_CHECK(RequestConfiguration, pcmcia_request_configuration(pdev, &link->conf)); #endif /* Fill the netdevice with this info */ #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) wlandev->netdev->irq = pdev->irq.AssignedIRQ; wlandev->netdev->base_addr = pdev->io.BasePort1; #else wlandev->netdev->irq = link->irq.AssignedIRQ; wlandev->netdev->base_addr = link->io.BasePort1; #endif /* And the rest of the hw structure */ hw->irq = wlandev->netdev->irq; hw->iobase = wlandev->netdev->base_addr; #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) link->state |= DEV_CONFIG; link->state &= ~DEV_CONFIG_PENDING; #endif /* And now we're done! */ wlandev->msdstate = WLAN_MSD_HWPRESENT; goto done; cs_failed: cs_error(pdev, last_fn, last_ret); failed: // wlandev, hw, etc etc.. #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) pdev->priv = NULL; #else pdev->instance = NULL; if (link) { link->priv = NULL; kfree(link); } #endif if (wlandev) { wlan_unsetup(wlandev); if (wlandev->priv) { hw = wlandev->priv; wlandev->priv = NULL; if (hw) { hfa384x_destroy(hw); kfree(hw); } } kfree(wlandev); } done: if (parse) kfree(parse); DBFEXIT; return rval; }