📄 prism2_cs.c
字号:
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) { hfa384x_t *hw = wlandev->priv; wlandev->priv = NULL; if (hw) { hfa384x_destroy(hw); kfree(hw); } } kfree(wlandev); }done: if (parse) kfree(parse); DBFEXIT; return rval;}#else // <= 2.6.15#define CS_CHECK(fn, ret) \do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)#define CFG_CHECK(fn, retf) \do { int ret = (retf); \if (ret != 0) { \ WLAN_LOG_DEBUG(1, "CardServices(" #fn ") returned %d\n", ret); \ cs_error(link->handle, fn, ret); \ goto next_entry; \} \} while (0)/*----------------------------------------------------------------* prism2sta_attach** Half of the attach/detach pair. Creates and registers a device* instance with Card Services. In this case, it also creates the* wlandev structure and device private structure. These are * linked to the device instance via its priv member.** Arguments:* none** Returns: * A valid ptr to dev_link_t on success, NULL otherwise** Side effects:* ** Call context:* process thread (insmod/init_module/register_pccard_driver)----------------------------------------------------------------*/dev_link_t *prism2sta_attach(void){ client_reg_t client_reg; int result; dev_link_t *link = NULL; wlandevice_t *wlandev = NULL; hfa384x_t *hw = NULL; DBFENTER; /* Alloc our structures */ link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL); if (!link || ((wlandev = create_wlan()) == NULL)) { WLAN_LOG_ERROR("%s: Memory allocation failure.\n", dev_info); result = -EIO; goto failed; } hw = wlandev->priv; /* Clear all the structs */ memset(link, 0, sizeof(struct dev_link_t)); if ( wlan_setup(wlandev) != 0 ) { WLAN_LOG_ERROR("%s: wlan_setup() failed.\n", dev_info); result = -EIO; goto failed; } /* Initialize the hw struct for now */ hfa384x_create(hw, 0, 0, NULL); hw->wlandev = wlandev; /* Initialize the PC card device object. */#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) init_timer(&link->release); link->release.function = &prism2sta_release; link->release.data = (u_long)link;#endif link->conf.IntType = INT_MEMORY_AND_IO; link->priv = wlandev;#if (defined(CS_RELEASE_CODE) && (CS_RELEASE_CODE < 0x2911)) link->irq.Instance = wlandev;#endif /* Link in to the list of devices managed by this driver */ link->next = dev_list; dev_list = link; /* Register with Card Services */ client_reg.dev_info = &dev_info;#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) ) client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;#endif#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13) ) client_reg.EventMask = CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | CS_EVENT_RESET_REQUEST | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; client_reg.event_handler = &prism2sta_event;#endif client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; result = pcmcia_register_client(&link->handle, &client_reg); if (result != 0) { cs_error(link->handle, RegisterClient, result); prism2sta_detach(link); return NULL; } goto done; failed: if (link) kfree(link); if (wlandev) kfree(wlandev); if (hw) kfree(hw); link = NULL; done: DBFEXIT; return link;}/*----------------------------------------------------------------* prism2sta_detach** Remove one of the device instances managed by this driver.* Search the list for the given instance, * check our flags for a waiting timer'd release call* call release* Deregister the instance with Card Services* (netdevice) unregister the network device.* unlink the instance from the list
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -