static int wi_pccard_attach(device_t dev) { struct wi_softc *sc; int error; sc = device_get_softc(dev); sc->wi_gone = 0; sc->wi_bus_type = WI_BUS_PCCARD; error = wi_alloc(dev, 0); if (error == 0) { /* Make sure interrupts are disabled. */ CSR_WRITE_2(sc, WI_INT_EN, 0); CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF); error = wi_attach(dev); if (error != 0) wi_free(dev); } return error; }
void wi_usb_thread(void *arg) { struct wi_usb_softc *sc = arg; struct wi_usb_thread_info *wi_thread_info; int s; wi_thread_info = malloc(sizeof(*wi_thread_info), M_DEVBUF, M_WAITOK); /* * is there a remote possibility that the device could * be removed before the kernel thread starts up? */ sc->wi_usb_refcnt++; sc->wi_thread_info = wi_thread_info; wi_thread_info->dying = 0; wi_thread_info->status = 0; wi_usb_ctl_lock(sc); wi_attach(&sc->sc_wi, &wi_func_usb); wi_usb_ctl_unlock(sc); for(;;) { if (wi_thread_info->dying) { if (--sc->wi_usb_refcnt < 0) usb_detach_wakeup(&sc->wi_usb_dev); kthread_exit(0); } DPRINTFN(5,("%s: %s: dying %x status %x\n", sc->wi_usb_dev.dv_xname, __func__, wi_thread_info->dying, wi_thread_info->status)); wi_usb_ctl_lock(sc); DPRINTFN(5,("%s: %s: starting %x\n", sc->wi_usb_dev.dv_xname, __func__, wi_thread_info->status)); s = splusb(); if (wi_thread_info->status & WI_START) { wi_thread_info->status &= ~WI_START; wi_usb_tx_lock(sc); wi_func_io.f_start(&sc->sc_wi.sc_ic.ic_if); /* * tx_unlock is explicitly missing here * it is done in txeof_frm */ } else if (wi_thread_info->status & WI_INQUIRE) { wi_thread_info->status &= ~WI_INQUIRE; wi_func_io.f_inquire(&sc->sc_wi); } else if (wi_thread_info->status & WI_WATCHDOG) { wi_thread_info->status &= ~WI_WATCHDOG; wi_func_io.f_watchdog( &sc->sc_wi.sc_ic.ic_if); } splx(s); DPRINTFN(5,("%s: %s: ending %x\n", sc->wi_usb_dev.dv_xname, __func__, wi_thread_info->status)); wi_usb_ctl_unlock(sc); if (wi_thread_info->status == 0) { s = splnet(); wi_thread_info->idle = 1; tsleep(wi_thread_info, PRIBIO, "wiIDL", 0); wi_thread_info->idle = 0; splx(s); } } }
static void wi_pci_attach(device_t parent, device_t self, void *aux) { struct wi_pci_softc *psc = device_private(self); struct wi_softc *sc = &psc->psc_wi; struct pci_attach_args *pa = aux; pci_chipset_tag_t pc = pa->pa_pc; const char *intrstr; const struct wi_pci_product *wpp; pci_intr_handle_t ih; bus_space_tag_t memt, iot, plxt, tmdt; bus_space_handle_t memh, ioh, plxh, tmdh; char intrbuf[PCI_INTRSTR_LEN]; sc->sc_dev = self; psc->psc_pc = pc; psc->psc_pcitag = pa->pa_tag; wpp = wi_pci_lookup(pa); #ifdef DIAGNOSTIC if (wpp == NULL) { printf("\n"); panic("wi_pci_attach: impossible"); } #endif switch (wpp->wpp_chip) { case CHIP_PLX_OTHER: case CHIP_PLX_9052: /* Map memory and I/O registers. */ if (pci_mapreg_map(pa, WI_PCI_LOMEM, PCI_MAPREG_TYPE_MEM, 0, &memt, &memh, NULL, NULL) != 0) { aprint_error(": can't map mem space\n"); return; } if (pci_mapreg_map(pa, WI_PCI_LOIO, PCI_MAPREG_TYPE_IO, 0, &iot, &ioh, NULL, NULL) != 0) { aprint_error(": can't map I/O space\n"); return; } if (wpp->wpp_chip == CHIP_PLX_OTHER) { /* The PLX 9052 doesn't have IO at 0x14. Perhaps other chips have, so we'll make this conditional. */ if (pci_mapreg_map(pa, WI_PCI_PLX_LOIO, PCI_MAPREG_TYPE_IO, 0, &plxt, &plxh, NULL, NULL) != 0) { aprint_error(": can't map PLX\n"); return; } } break; case CHIP_TMD_7160: /* Used instead of PLX on at least one revision of * the National Datacomm Corporation NCP130. Values * for registers acquired from OpenBSD, which in * turn got them from a Linux driver. */ /* Map COR and I/O registers. */ if (pci_mapreg_map(pa, WI_TMD_COR, PCI_MAPREG_TYPE_IO, 0, &tmdt, &tmdh, NULL, NULL) != 0) { aprint_error(": can't map TMD\n"); return; } if (pci_mapreg_map(pa, WI_TMD_IO, PCI_MAPREG_TYPE_IO, 0, &iot, &ioh, NULL, NULL) != 0) { aprint_error(": can't map I/O space\n"); return; } break; default: if (pci_mapreg_map(pa, WI_PCI_CBMA, PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0, &iot, &ioh, NULL, NULL) != 0) { aprint_error(": can't map mem space\n"); return; } memt = iot; memh = ioh; sc->sc_pci = 1; break; } pci_aprint_devinfo(pa, NULL); sc->sc_enabled = 1; sc->sc_enable = wi_pci_enable; sc->sc_iot = iot; sc->sc_ioh = ioh; /* Make sure interrupts are disabled. */ CSR_WRITE_2(sc, WI_INT_EN, 0); CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF); if (wpp->wpp_chip == CHIP_PLX_OTHER) { uint32_t command; #define WI_LOCAL_INTCSR 0x4c #define WI_LOCAL_INTEN 0x40 /* poke this into INTCSR */ command = bus_space_read_4(plxt, plxh, WI_LOCAL_INTCSR); command |= WI_LOCAL_INTEN; bus_space_write_4(plxt, plxh, WI_LOCAL_INTCSR, command); } /* Map and establish the interrupt. */ if (pci_intr_map(pa, &ih)) { aprint_error_dev(self, "couldn't map interrupt\n"); return; } intrstr = pci_intr_string(pc, ih, intrbuf, sizeof(intrbuf)); psc->psc_ih = ih; sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, wi_intr, sc); if (sc->sc_ih == NULL) { aprint_error_dev(self, "couldn't establish interrupt"); if (intrstr != NULL) aprint_error(" at %s", intrstr); aprint_error("\n"); return; } aprint_normal_dev(self, "interrupting at %s\n", intrstr); switch (wpp->wpp_chip) { case CHIP_PLX_OTHER: case CHIP_PLX_9052: /* * Setup the PLX chip for level interrupts and config index 1 * XXX - should really reset the PLX chip too. */ bus_space_write_1(memt, memh, WI_PLX_COR_OFFSET, WI_PLX_COR_VALUE); break; case CHIP_TMD_7160: /* Enable I/O mode and level interrupts on the embedded * card. The card's COR is the first byte of BAR 0. */ bus_space_write_1(tmdt, tmdh, 0, WI_COR_IOMODE); break; default: /* reset HFA3842 MAC core */ wi_pci_reset(sc); break; } printf("%s:", device_xname(self)); if (wi_attach(sc, 0) != 0) { aprint_error_dev(self, "failed to attach controller\n"); pci_intr_disestablish(pa->pa_pc, sc->sc_ih); return; } if (!wpp->wpp_chip) sc->sc_reset = wi_pci_reset; if (pmf_device_register(self, NULL, NULL)) pmf_class_network_register(self, &sc->sc_if); else aprint_error_dev(self, "couldn't establish power handler\n"); }
static int wi_pci_attach(device_t dev) { struct wi_softc *sc; u_int32_t command; u_int16_t reg; int error; int timeout; sc = device_get_softc(dev); if (sc->wi_bus_type != WI_BUS_PCI_NATIVE) { error = wi_alloc(dev, WI_PCI_IORES); if (error) return (error); /* Make sure interrupts are disabled. */ CSR_WRITE_2(sc, WI_INT_EN, 0); CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF); /* We have to do a magic PLX poke to enable interrupts */ sc->local_rid = WI_PCI_LOCALRES; sc->local = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &sc->local_rid, RF_ACTIVE); sc->wi_localtag = rman_get_bustag(sc->local); sc->wi_localhandle = rman_get_bushandle(sc->local); command = bus_space_read_4(sc->wi_localtag, sc->wi_localhandle, WI_LOCAL_INTCSR); command |= WI_LOCAL_INTEN; bus_space_write_4(sc->wi_localtag, sc->wi_localhandle, WI_LOCAL_INTCSR, command); bus_release_resource(dev, SYS_RES_IOPORT, sc->local_rid, sc->local); sc->local = NULL; sc->mem_rid = WI_PCI_MEMRES; sc->mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->mem_rid, RF_ACTIVE); if (sc->mem == NULL) { device_printf(dev, "couldn't allocate memory\n"); wi_free(dev); return (ENXIO); } sc->wi_bmemtag = rman_get_bustag(sc->mem); sc->wi_bmemhandle = rman_get_bushandle(sc->mem); /* * Write COR to enable PC card * This is a subset of the protocol that the pccard bus code * would do. In theory, we should parse the CIS to find the * COR offset. In practice, the COR_OFFSET is always 0x3e0. */ CSM_WRITE_1(sc, WI_COR_OFFSET, WI_COR_VALUE); reg = CSM_READ_1(sc, WI_COR_OFFSET); if (reg != WI_COR_VALUE) { device_printf(dev, "CSM_READ_1(WI_COR_OFFSET) " "wanted %d, got %d\n", WI_COR_VALUE, reg); wi_free(dev); return (ENXIO); } } else { error = wi_alloc(dev, WI_PCI_LMEMRES); if (error) return (error); CSR_WRITE_2(sc, WI_PCICOR_OFF, WI_PCICOR_RESET); DELAY(250000); CSR_WRITE_2(sc, WI_PCICOR_OFF, 0x0000); DELAY(500000); timeout=2000000; while ((--timeout > 0) && (CSR_READ_2(sc, WI_COMMAND) & WI_CMD_BUSY)) DELAY(10); if (timeout == 0) { device_printf(dev, "couldn't reset prism pci core.\n"); wi_free(dev); return(ENXIO); } } CSR_WRITE_2(sc, WI_HFA384X_SWSUPPORT0_OFF, WI_PRISM2STA_MAGIC); reg = CSR_READ_2(sc, WI_HFA384X_SWSUPPORT0_OFF); if (reg != WI_PRISM2STA_MAGIC) { device_printf(dev, "CSR_READ_2(WI_HFA384X_SWSUPPORT0_OFF) " "wanted %d, got %d\n", WI_PRISM2STA_MAGIC, reg); wi_free(dev); return (ENXIO); } error = wi_attach(dev); if (error != 0) wi_free(dev); return (error); }
static void wi_pcmcia_attach(device_t parent, device_t self, void *aux) { struct wi_pcmcia_softc *psc = device_private(self); struct wi_softc *sc = &psc->sc_wi; struct pcmcia_attach_args *pa = aux; struct pcmcia_config_entry *cfe; int haveaddr; int error; aprint_naive("\n"); sc->sc_dev = self; psc->sc_pf = pa->pf; error = pcmcia_function_configure(pa->pf, wi_pcmcia_validate_config); if (error) { aprint_error_dev(self, "configure failed, error=%d\n", error); return; } cfe = pa->pf->cfe; sc->sc_iot = cfe->iospace[0].handle.iot; sc->sc_ioh = cfe->iospace[0].handle.ioh; if (pa->manufacturer == PCMCIA_VENDOR_SYMBOL && pa->product == PCMCIA_PRODUCT_SYMBOL_LA4100) psc->sc_symbol_cf = 1; /* * XXX: Sony PEGA-WL100 CF card has a same vendor/product id as * Intel PCMCIA card. It may be incorrect to detect by the * initial value of COR register. */ if (pa->manufacturer == PCMCIA_VENDOR_INTEL && pa->product == PCMCIA_PRODUCT_INTEL_PRO_WLAN_2011 && CSR_READ_2(sc, WI_COR) == WI_COR_IOMODE) psc->sc_symbol_cf = 1; error = wi_pcmcia_enable(self, 1); if (error) goto fail; sc->sc_pci = 0; sc->sc_enable = wi_pcmcia_enable; printf("%s:", device_xname(self)); haveaddr = pa->pf->pf_funce_lan_nidlen == IEEE80211_ADDR_LEN; if (wi_attach(sc, haveaddr ? pa->pf->pf_funce_lan_nid : 0) != 0) { aprint_error_dev(self, "failed to attach controller\n"); goto fail2; } if (pmf_device_register(self, NULL, NULL)) pmf_class_network_register(self, &sc->sc_if); else aprint_error_dev(self, "couldn't establish power handler\n"); wi_pcmcia_enable(self, 0); psc->sc_state = WI_PCMCIA_ATTACHED; return; fail2: wi_pcmcia_enable(self, 0); fail: pcmcia_function_unconfigure(pa->pf); }
void wi_pcmcia_attach(struct device *parent, struct device *self, void *aux) { struct wi_pcmcia_softc *psc = (struct wi_pcmcia_softc *)self; struct wi_softc *sc = &psc->sc_wi; struct pcmcia_attach_args *pa = aux; struct pcmcia_function *pf = pa->pf; struct pcmcia_config_entry *cfe = SIMPLEQ_FIRST(&pf->cfe_head); const char *intrstr; int state = 0; psc->sc_pf = pf; /* Enable the card. */ pcmcia_function_init(pf, cfe); if (pcmcia_function_enable(pf)) { printf(": function enable failed\n"); goto bad; } state++; if (pcmcia_io_alloc(pf, 0, WI_IOSIZ, WI_IOSIZ, &psc->sc_pcioh)) { printf(": can't alloc i/o space\n"); goto bad; } state++; if (pcmcia_io_map(pf, PCMCIA_WIDTH_IO16, 0, WI_IOSIZ, &psc->sc_pcioh, &psc->sc_io_window)) { printf(": can't map io space\n"); goto bad; } state++; printf(" port 0x%lx/%lu", psc->sc_pcioh.addr, (u_long)psc->sc_pcioh.size); sc->wi_ltag = sc->wi_btag = psc->sc_pcioh.iot; sc->wi_lhandle = sc->wi_bhandle = psc->sc_pcioh.ioh; sc->wi_cor_offset = WI_COR_OFFSET; sc->wi_flags |= WI_FLAGS_BUS_PCMCIA; /* Make sure interrupts are disabled. */ CSR_WRITE_2(sc, WI_INT_EN, 0); CSR_WRITE_2(sc, WI_EVENT_ACK, 0xffff); /* Establish the interrupt. */ sc->sc_ih = pcmcia_intr_establish(pa->pf, IPL_NET, wi_intr, psc, sc->sc_dev.dv_xname); if (sc->sc_ih == NULL) { printf("%s: couldn't establish interrupt\n", sc->sc_dev.dv_xname); goto bad; } intrstr = pcmcia_intr_string(psc->sc_pf, sc->sc_ih); printf("%s%s\n", *intrstr ? ", " : "", intrstr); if (wi_attach(sc, &wi_func_io) == 0) return; /* wi_attach() failed, do some cleanup */ pcmcia_intr_disestablish(psc->sc_pf, sc->sc_ih); sc->sc_ih = NULL; bad: if (state > 2) pcmcia_io_unmap(pf, psc->sc_io_window); if (state > 1) pcmcia_io_free(pf, &psc->sc_pcioh); if (state > 0) pcmcia_function_disable(pf); }