static int prism2sta_resume(struct usb_interface *interface) { int result = 0; hfa384x_t *hw = NULL; wlandevice_t *wlandev; wlandev = (wlandevice_t *)usb_get_intfdata(interface); if (!wlandev) return -ENODEV; hw = wlandev->priv; if (!hw) return -ENODEV; /* 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) { unregister_wlandev(wlandev); hfa384x_destroy(hw); dev_err(&interface->dev, "hfa384x_corereset() failed.\n"); kfree(wlandev); kfree(hw); wlandev = NULL; return -ENODEV; } } prism2sta_ifstate(wlandev, P80211ENUM_ifstate_enable); return 0; }
/*---------------------------------------------------------------- * prism2sta_event * * Handler for card services events. * * Arguments: * event The event code * priority hi/low - REMOVAL is the only hi * args ptr to card services struct containing info about * pcmcia status * * Returns: * Zero on success, non-zero otherwise * * Side effects: * * * Call context: * Both interrupt and process thread, depends on the event. ----------------------------------------------------------------*/ static int prism2sta_event ( event_t event, int priority, event_callback_args_t *args) { int result = 0; dev_link_t *link = (dev_link_t *) args->client_data; wlandevice_t *wlandev = (wlandevice_t*)link->priv; hfa384x_t *hw = NULL; DBFENTER; if (wlandev) hw = wlandev->priv; switch (event) { case CS_EVENT_CARD_INSERTION: WLAN_LOG_DEBUG(5,"event is INSERTION\n"); link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; prism2sta_config(link); if (!(link->state & DEV_CONFIG)) { wlandev->netdev->irq = 0; WLAN_LOG_ERROR( "%s: Initialization failed!\n", dev_info); wlandev->msdstate = WLAN_MSD_HWFAIL; break; } /* Fill in the rest of the hw struct */ hw->irq = wlandev->netdev->irq; hw->iobase = wlandev->netdev->base_addr; hw->link = link; if (prism2_doreset) { result = hfa384x_corereset(hw, prism2_reset_holdtime, prism2_reset_settletime, 0); if ( result ) { WLAN_LOG_ERROR( "corereset() failed, result=%d.\n", result); wlandev->msdstate = WLAN_MSD_HWFAIL; break; } } #if 0 /* * TODO: test_hostif() not implemented yet. */ result = hfa384x_test_hostif(hw); if (result) { WLAN_LOG_ERROR( "test_hostif() failed, result=%d.\n", result); wlandev->msdstate = WLAN_MSD_HWFAIL; break; } #endif wlandev->msdstate = WLAN_MSD_HWPRESENT; break; case CS_EVENT_CARD_REMOVAL: WLAN_LOG_DEBUG(5,"event is REMOVAL\n"); link->state &= ~DEV_PRESENT; if (wlandev) { p80211netdev_hwremoved(wlandev); } #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) if (link->state & DEV_CONFIG) { link->release.expires = jiffies + (HZ/20); add_timer(&link->release); } #endif break; case CS_EVENT_RESET_REQUEST: WLAN_LOG_DEBUG(5,"event is RESET_REQUEST\n"); WLAN_LOG_NOTICE( "prism2 card reset not supported " "due to post-reset user mode configuration " "requirements.\n"); WLAN_LOG_NOTICE( " From user mode, use " "'cardctl suspend;cardctl resume' " "instead.\n"); break; case CS_EVENT_RESET_PHYSICAL: case CS_EVENT_CARD_RESET: WLAN_LOG_WARNING("Rx'd CS_EVENT_RESET_xxx, should not " "be possible since RESET_REQUEST was denied.\n"); break; case CS_EVENT_PM_SUSPEND: WLAN_LOG_DEBUG(5,"event is SUSPEND\n"); link->state |= DEV_SUSPEND; if (link->state & DEV_CONFIG) { prism2sta_ifstate(wlandev, P80211ENUM_ifstate_disable); pcmcia_release_configuration(link->handle); } break; case CS_EVENT_PM_RESUME: WLAN_LOG_DEBUG(5,"event is RESUME\n"); link->state &= ~DEV_SUSPEND; if (link->state & DEV_CONFIG) { pcmcia_request_configuration(link->handle, &link->conf); } break; } DBFEXIT; return 0; /* noone else does anthing with the return value */ }
/*---------------------------------------------------------------- * prism2sta_probe_plx * * Probe routine called when a PCI device w/ matching ID is found. * This PLX implementation uses the following map: * BAR0: Unused * BAR1: ???? * BAR2: PCMCIA attribute memory * BAR3: PCMCIA i/o space * Here's the sequence: * - Allocate the PCI resources. * - Read the PCMCIA attribute memory to make sure we have a WLAN card * - Reset the MAC using the PCMCIA COR * - 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 __devinit prism2sta_probe_plx( struct pci_dev *pdev, const struct pci_device_id *id) { int result; phys_t pccard_ioaddr; phys_t pccard_attr_mem; unsigned int pccard_attr_len; void __iomem *attr_mem = NULL; UINT32 plx_addr; wlandevice_t *wlandev = NULL; hfa384x_t *hw = NULL; int reg; u32 regic; if (pci_enable_device(pdev)) return -EIO; /* TMC7160 boards are special */ if ((pdev->vendor == PCIVENDOR_NDC) && (pdev->device == PCIDEVICE_NCP130_ASIC)) { unsigned long delay; pccard_attr_mem = 0; pccard_ioaddr = pci_resource_start(pdev, 1); outb(0x45, pccard_ioaddr); delay = jiffies + 1*HZ; while (time_before(jiffies, delay)); if (inb(pccard_ioaddr) != 0x45) { WLAN_LOG_ERROR("Initialize the TMC7160 failed. (0x%x)\n", inb(pccard_ioaddr)); return -EIO; } pccard_ioaddr = pci_resource_start(pdev, 2); prism2_doreset = 0; WLAN_LOG_INFO("NDC NCP130 with TMC716(ASIC) PCI interface device found at io:0x%x, irq:%d\n", pccard_ioaddr, pdev->irq); goto init; } /* Collect the resource requirements */ pccard_attr_mem = pci_resource_start(pdev, 2); pccard_attr_len = pci_resource_len(pdev, 2); if (pccard_attr_len < PLX_MIN_ATTR_LEN) return -EIO; pccard_ioaddr = pci_resource_start(pdev, 3); /* bjoern: We need to tell the card to enable interrupts, in * case the serial eprom didn't do this already. See the * PLX9052 data book, p8-1 and 8-24 for reference. * [MSM]: This bit of code came from the orinoco_cs driver. */ plx_addr = pci_resource_start(pdev, 1); regic = 0; regic = inl(plx_addr+PLX_INTCSR); if(regic & PLX_INTCSR_INTEN) { WLAN_LOG_DEBUG(1, "%s: Local Interrupt already enabled\n", dev_info); } else { regic |= PLX_INTCSR_INTEN; outl(regic, plx_addr+PLX_INTCSR); regic = inl(plx_addr+PLX_INTCSR); if(!(regic & PLX_INTCSR_INTEN)) { WLAN_LOG_ERROR( "%s: Couldn't enable Local Interrupts\n", dev_info); return -EIO; } } /* These assignments are here in case of future mappings for * io space and irq that might be similar to ioremap */ if (!request_mem_region(pccard_attr_mem, pci_resource_len(pdev, 2), "Prism2")) { WLAN_LOG_ERROR("%s: Couldn't reserve PCI memory region\n", dev_info); return -EIO; } attr_mem = ioremap(pccard_attr_mem, pccard_attr_len); WLAN_LOG_INFO("A PLX PCI/PCMCIA interface device found, " "phymem:0x%llx, phyio=0x%x, irq:%d, " "mem: 0x%lx\n", (unsigned long long)pccard_attr_mem, pccard_ioaddr, pdev->irq, (unsigned long)attr_mem); /* Verify whether PC card is present. * [MSM] This needs improvement, the right thing to do is * probably to walk the CIS looking for the vendor and product * IDs. It would be nice if this could be tied in with the * etc/pcmcia/wlan-ng.conf file. Any volunteers? ;-) */ if ( readb(attr_mem + 0) != 0x01 || readb(attr_mem + 2) != 0x03 || readb(attr_mem + 4) != 0x00 || readb(attr_mem + 6) != 0x00 || readb(attr_mem + 8) != 0xFF || readb(attr_mem + 10) != 0x17 || readb(attr_mem + 12) != 0x04 || readb(attr_mem + 14) != 0x67) { WLAN_LOG_ERROR("Prism2 PC card CIS is invalid.\n"); return -EIO; } WLAN_LOG_INFO("A PCMCIA WLAN adapter was found.\n"); /* Write COR to enable PC card */ writeb(COR_VALUE, attr_mem + COR_OFFSET); reg = readb(attr_mem + COR_OFFSET); init: /* * Now do everything the same as a PCI device * [MSM] TODO: We could probably factor this out of pcmcia/pci/plx * and perhaps usb. Perhaps a task for another day....... */ if ((wlandev = create_wlan()) == NULL) { WLAN_LOG_ERROR("%s: Memory allocation failure.\n", dev_info); result = -EIO; goto failed; } hw = wlandev->priv; if ( wlan_setup(wlandev) != 0 ) { WLAN_LOG_ERROR("%s: wlan_setup() failed.\n", dev_info); result = -EIO; goto failed; } /* Setup netdevice's ability to report resources * Note: the netdevice was allocated by wlan_setup() */ wlandev->netdev->irq = pdev->irq; wlandev->netdev->base_addr = pccard_ioaddr; wlandev->netdev->mem_start = (unsigned long)attr_mem; wlandev->netdev->mem_end = (unsigned long)attr_mem + pci_resource_len(pdev, 0); /* Initialize the hw data */ hfa384x_create(hw, wlandev->netdev->irq, pccard_ioaddr, attr_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 failed; } #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 failed; } #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) { unregister_wlandev(wlandev); hfa384x_destroy(hw); WLAN_LOG_ERROR( "%s: hfa384x_corereset() failed.\n", dev_info); result = -EIO; goto failed; } } 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; failed: pci_set_drvdata(pdev, NULL); if (wlandev) kfree(wlandev); if (hw) kfree(hw); if (attr_mem) iounmap(attr_mem); pci_release_regions(pdev); pci_disable_device(pdev); done: DBFEXIT; return result; }
static int prism2sta_probe_usb(struct usb_interface *interface, const struct usb_device_id *id) { struct usb_device *dev; wlandevice_t *wlandev = NULL; hfa384x_t *hw = NULL; int result = 0; dev = interface_to_usbdev(interface); wlandev = create_wlan(); if (!wlandev) { dev_err(&interface->dev, "Memory allocation failure.\n"); result = -EIO; goto failed; } hw = wlandev->priv; if (wlan_setup(wlandev, &(interface->dev)) != 0) { dev_err(&interface->dev, "wlan_setup() failed.\n"); result = -EIO; goto failed; } /* Initialize the hw data */ hfa384x_create(hw, dev); hw->wlandev = wlandev; /* Register the wlandev, this gets us a name and registers the * linux netdevice. */ SET_NETDEV_DEV(wlandev->netdev, &(interface->dev)); /* 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) { result = -EIO; dev_err(&interface->dev, "hfa384x_corereset() failed.\n"); goto failed_reset; } } usb_get_dev(dev); wlandev->msdstate = WLAN_MSD_HWPRESENT; /* Try and load firmware, then enable card before we register */ prism2_fwtry(dev, wlandev); prism2sta_ifstate(wlandev, P80211ENUM_ifstate_enable); if (register_wlandev(wlandev) != 0) { dev_err(&interface->dev, "register_wlandev() failed.\n"); result = -EIO; goto failed_register; } goto done; failed_register: usb_put_dev(dev); failed_reset: wlan_unsetup(wlandev); failed: kfree(wlandev); kfree(hw); wlandev = NULL; done: usb_set_intfdata(interface, wlandev); return result; }
/*---------------------------------------------------------------- * 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 __devinit prism2sta_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); /* Register the wlandev, this gets us a name and registers the * linux netdevice. */ SET_MODULE_OWNER(wlandev->netdev); 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 /* Initialize the hw data */ hfa384x_create(hw, wlandev->netdev->irq, 0, mem); hw->wlandev = wlandev; /* 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; }