📄 prism2_pci.c
字号:
#define WLAN_HOSTIF WLAN_PCI#include "hfa384x.c"#include "prism2mgmt.c"#include "prism2mib.c"#include "prism2sta.c"#define PCI_SIZE 0x1000 /* Memory size - 4K bytes *//* ISL3874A 11Mb/s WLAN controller */#define PCIVENDOR_INTERSIL 0x1260UL#define PCIDEVICE_ISL3874 0x3873UL /* [MSM] yeah I know...the ID says 3873. Trust me, it's a 3874. *//* Samsung SWL-2210P 11Mb/s WLAN controller (uses ISL3874A) */#define PCIVENDOR_SAMSUNG 0x167dUL#define PCIDEVICE_SWL_2210P 0xa000UL#define PCIVENDOR_NETGEAR 0x1385UL /* for MA311 *//* PCI Class & Sub-Class code, Network-'Other controller' */#define PCI_CLASS_NETWORK_OTHERS 0x280/*----------------------------------------------------------------* prism2sta_probe_pci** Probe routine called when a PCI device w/ matching ID is found. * The ISL3874 implementation uses the following map:* BAR0: Prism2.x registers memory mapped, size=4k* Here's the sequence:* - Allocate the PCI resources. * - Read the PCMCIA attribute memory to make sure we have a WLAN card* - Reset the MAC * - Initialize the netdev and wlan data* - Initialize the MAC** Arguments:* pdev ptr to pci device structure containing info about * pci configuration.* id ptr to the device id entry that matched this device.** Returns: * zero - success* negative - failed** Side effects:* ** Call context:* process thread* ----------------------------------------------------------------*/static int __devinitprism2sta_probe_pci( struct pci_dev *pdev, const struct pci_device_id *id){ int result; phys_t phymem = 0; void *mem = NULL; wlandevice_t *wlandev = NULL; hfa384x_t *hw = NULL; DBFENTER; /* Enable the pci device */ if (pci_enable_device(pdev)) { WLAN_LOG_ERROR("%s: pci_enable_device() failed.\n", dev_info); result = -EIO; goto fail; } /* Figure out our resources */ phymem = pci_resource_start(pdev, 0); if (!request_mem_region(phymem, pci_resource_len(pdev, 0), "Prism2")) { printk(KERN_ERR "prism2: Cannot reserve PCI memory region\n"); result = -EIO; goto fail; } mem = ioremap(phymem, PCI_SIZE); if ( mem == 0 ) { WLAN_LOG_ERROR("%s: ioremap() failed.\n", dev_info); result = -EIO; goto fail; } /* Log the device */ WLAN_LOG_INFO("A Prism2.5 PCI device found, " "phymem:0x%llx, irq:%d, mem:0x%p\n", (unsigned long long)phymem, pdev->irq, mem); if ((wlandev = create_wlan()) == NULL) { WLAN_LOG_ERROR("%s: Memory allocation failure.\n", dev_info); result = -EIO; goto fail; } hw = wlandev->priv; if ( wlan_setup(wlandev) != 0 ) { WLAN_LOG_ERROR("%s: wlan_setup() failed.\n", dev_info); result = -EIO; goto fail; } /* Setup netdevice's ability to report resources * Note: the netdevice was allocated by wlan_setup() */ wlandev->netdev->irq = pdev->irq; wlandev->netdev->mem_start = (unsigned long) mem; wlandev->netdev->mem_end = wlandev->netdev->mem_start + pci_resource_len(pdev, 0); /* Initialize the hw data */ hfa384x_create(hw, wlandev->netdev->irq, 0, mem); hw->wlandev = wlandev; /* Register the wlandev, this gets us a name and registers the * linux netdevice. */ SET_MODULE_OWNER(wlandev->netdev);#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) SET_NETDEV_DEV(wlandev->netdev, &(pdev->dev));#endif if ( register_wlandev(wlandev) != 0 ) { WLAN_LOG_ERROR("%s: register_wlandev() failed.\n", dev_info); result = -EIO; goto fail; }#if 0 /* TODO: Move this and an irq test into an hfa384x_testif() routine. */ outw(PRISM2STA_MAGIC, HFA384x_SWSUPPORT(wlandev->netdev->base_addr)); reg=inw( HFA384x_SWSUPPORT(wlandev->netdev->base_addr)); if ( reg != PRISM2STA_MAGIC ) { WLAN_LOG_ERROR("MAC register access test failed!\n"); result = -EIO; goto fail; } #endif /* Do a chip-level reset on the MAC */ if (prism2_doreset) { result = hfa384x_corereset(hw, prism2_reset_holdtime, prism2_reset_settletime, 0); if (result != 0) { WLAN_LOG_ERROR( "%s: hfa384x_corereset() failed.\n", dev_info); unregister_wlandev(wlandev); hfa384x_destroy(hw); result = -EIO; goto fail; } } pci_set_drvdata(pdev, wlandev); /* Shouldn't actually hook up the IRQ until we * _know_ things are alright. A test routine would help. */ request_irq(wlandev->netdev->irq, hfa384x_interrupt, SA_SHIRQ, wlandev->name, wlandev); wlandev->msdstate = WLAN_MSD_HWPRESENT; result = 0; goto done; fail: pci_set_drvdata(pdev, NULL); if (wlandev) kfree(wlandev); if (hw) kfree(hw); if (mem) iounmap((void *) mem); pci_release_regions(pdev); pci_disable_device(pdev); done: DBFEXIT; return result;}static void __devexit prism2sta_remove_pci(struct pci_dev *pdev){ wlandevice_t *wlandev; hfa384x_t *hw; wlandev = (wlandevice_t *) pci_get_drvdata(pdev); hw = wlandev->priv; p80211netdev_hwremoved(wlandev); /* reset hardware */ prism2sta_ifstate(wlandev, P80211ENUM_ifstate_disable); if (pdev->irq) free_irq(pdev->irq, wlandev); unregister_wlandev(wlandev); /* free local stuff */ if (hw) { hfa384x_destroy(hw); kfree(hw); } iounmap((void*) wlandev->netdev->mem_start); wlan_unsetup(wlandev); pci_release_regions(pdev); pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); kfree(wlandev);}static struct pci_device_id pci_id_tbl[] = { { PCIVENDOR_INTERSIL, PCIDEVICE_ISL3874, PCI_ANY_ID, PCI_ANY_ID, 0, 0, /* Driver data, we just put the name here */ (unsigned long)"Intersil Prism2.5 ISL3874 11Mb/s WLAN Controller" }, { PCIVENDOR_INTERSIL, 0x3872, PCI_ANY_ID, PCI_ANY_ID, 0, 0, /* Driver data, we just put the name here */ (unsigned long)"Intersil Prism2.5 ISL3872 11Mb/s WLAN Controller" }, { PCIVENDOR_SAMSUNG, PCIDEVICE_SWL_2210P, PCI_ANY_ID, PCI_ANY_ID, 0, 0, /* Driver data, we just put the name here */ (unsigned long)"Samsung MagicLAN SWL-2210P 11Mb/s WLAN Controller" }, { /* for NetGear MA311 */ PCIVENDOR_NETGEAR, 0x3872, PCI_ANY_ID, PCI_ANY_ID, 0, 0, /* Driver data, we just put the name here */ (unsigned long)"Netgear MA311 WLAN Controller" }, { 0, 0, 0, 0, 0, 0, 0 }};MODULE_DEVICE_TABLE(pci, pci_id_tbl);/* Function declared here because of ptr reference below */static int __devinit prism2sta_probe_pci(struct pci_dev *pdev, const struct pci_device_id *id);static void __devexit prism2sta_remove_pci(struct pci_dev *pdev);struct pci_driver prism2_pci_drv_id = { .name = "prism2_pci", .id_table = pci_id_tbl, .probe = prism2sta_probe_pci, .remove = prism2sta_remove_pci,#ifdef CONFIG_PM .suspend = prism2sta_suspend_pci, .resume = prism2sta_resume_pci,#endif};#ifdef MODULEstatic int __init prism2pci_init(void){ WLAN_LOG_NOTICE("%s Loaded\n", version); return pci_module_init(&prism2_pci_drv_id);};static void __exit prism2pci_cleanup(void){ pci_unregister_driver(&prism2_pci_drv_id);};module_init(prism2pci_init);module_exit(prism2pci_cleanup);#endifint hfa384x_corereset(hfa384x_t *hw, int holdtime, int settletime, int genesis){ int result = 0; unsigned long timeout; UINT16 reg; DBFENTER; /* Assert reset and wait awhile * (note: these delays are _really_ long, but they appear to be * necessary.) */ hfa384x_setreg(hw, 0xc5, HFA384x_PCICOR); timeout = jiffies + HZ/4; while(time_before(jiffies, timeout)) udelay(5); if (genesis) { hfa384x_setreg(hw, genesis, HFA384x_PCIHCR); timeout = jiffies + HZ/4; while(time_before(jiffies, timeout)) udelay(5); } /* Clear the reset and wait some more */ hfa384x_setreg(hw, 0x45, HFA384x_PCICOR); timeout = jiffies + HZ/2; while(time_before(jiffies, timeout)) udelay(5); /* Wait for f/w to complete initialization (CMD:BUSY == 0) */ timeout = jiffies + 2*HZ; reg = hfa384x_getreg(hw, HFA384x_CMD); while ( HFA384x_CMD_ISBUSY(reg) && time_before( jiffies, timeout) ) { reg = hfa384x_getreg(hw, HFA384x_CMD); udelay(10); } if (HFA384x_CMD_ISBUSY(reg)) { WLAN_LOG_WARNING("corereset: Timed out waiting for cmd register.\n"); result=1; } DBFEXIT; return result;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -