Exemplo n.º 1
0
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;
}
Exemplo n.º 2
0
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);
		}
	}
}
Exemplo n.º 3
0
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");
}
Exemplo n.º 4
0
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);
}
Exemplo n.º 5
0
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);
}
Exemplo n.º 6
0
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);
}