[BACK]Return to if_wpi.c CVS log [TXT][DIR] Up to [local] / sys / dev / pci

Annotation of sys/dev/pci/if_wpi.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: if_wpi.c,v 1.50 2007/08/10 16:29:27 jasper Exp $      */
        !             2:
        !             3: /*-
        !             4:  * Copyright (c) 2006, 2007
        !             5:  *     Damien Bergamini <damien.bergamini@free.fr>
        !             6:  *
        !             7:  * Permission to use, copy, modify, and distribute this software for any
        !             8:  * purpose with or without fee is hereby granted, provided that the above
        !             9:  * copyright notice and this permission notice appear in all copies.
        !            10:  *
        !            11:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
        !            12:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
        !            13:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
        !            14:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
        !            15:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
        !            16:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
        !            17:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
        !            18:  */
        !            19:
        !            20: /*
        !            21:  * Driver for Intel PRO/Wireless 3945ABG 802.11 network adapters.
        !            22:  */
        !            23:
        !            24: #include "bpfilter.h"
        !            25:
        !            26: #include <sys/param.h>
        !            27: #include <sys/sockio.h>
        !            28: #include <sys/sysctl.h>
        !            29: #include <sys/mbuf.h>
        !            30: #include <sys/kernel.h>
        !            31: #include <sys/socket.h>
        !            32: #include <sys/systm.h>
        !            33: #include <sys/malloc.h>
        !            34: #include <sys/conf.h>
        !            35: #include <sys/device.h>
        !            36: #include <sys/sensors.h>
        !            37:
        !            38: #include <machine/bus.h>
        !            39: #include <machine/endian.h>
        !            40: #include <machine/intr.h>
        !            41:
        !            42: #include <dev/pci/pcireg.h>
        !            43: #include <dev/pci/pcivar.h>
        !            44: #include <dev/pci/pcidevs.h>
        !            45:
        !            46: #if NBPFILTER > 0
        !            47: #include <net/bpf.h>
        !            48: #endif
        !            49: #include <net/if.h>
        !            50: #include <net/if_arp.h>
        !            51: #include <net/if_dl.h>
        !            52: #include <net/if_media.h>
        !            53: #include <net/if_types.h>
        !            54:
        !            55: #include <netinet/in.h>
        !            56: #include <netinet/in_systm.h>
        !            57: #include <netinet/in_var.h>
        !            58: #include <netinet/if_ether.h>
        !            59: #include <netinet/ip.h>
        !            60:
        !            61: #include <net80211/ieee80211_var.h>
        !            62: #include <net80211/ieee80211_amrr.h>
        !            63: #include <net80211/ieee80211_radiotap.h>
        !            64:
        !            65: #include <dev/pci/if_wpireg.h>
        !            66: #include <dev/pci/if_wpivar.h>
        !            67:
        !            68: static const struct pci_matchid wpi_devices[] = {
        !            69:        { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_PRO_WL_3945ABG_1 },
        !            70:        { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_PRO_WL_3945ABG_2 }
        !            71: };
        !            72:
        !            73: int            wpi_match(struct device *, void *, void *);
        !            74: void           wpi_attach(struct device *, struct device *, void *);
        !            75: void           wpi_power(int, void *);
        !            76: int            wpi_dma_contig_alloc(bus_dma_tag_t, struct wpi_dma_info *,
        !            77:                    void **, bus_size_t, bus_size_t, int);
        !            78: void           wpi_dma_contig_free(struct wpi_dma_info *);
        !            79: int            wpi_alloc_shared(struct wpi_softc *);
        !            80: void           wpi_free_shared(struct wpi_softc *);
        !            81: int            wpi_alloc_fwmem(struct wpi_softc *);
        !            82: void           wpi_free_fwmem(struct wpi_softc *);
        !            83: struct         wpi_rbuf *wpi_alloc_rbuf(struct wpi_softc *);
        !            84: void           wpi_free_rbuf(caddr_t, u_int, void *);
        !            85: int            wpi_alloc_rpool(struct wpi_softc *);
        !            86: void           wpi_free_rpool(struct wpi_softc *);
        !            87: int            wpi_alloc_rx_ring(struct wpi_softc *, struct wpi_rx_ring *);
        !            88: void           wpi_reset_rx_ring(struct wpi_softc *, struct wpi_rx_ring *);
        !            89: void           wpi_free_rx_ring(struct wpi_softc *, struct wpi_rx_ring *);
        !            90: int            wpi_alloc_tx_ring(struct wpi_softc *, struct wpi_tx_ring *,
        !            91:                    int, int);
        !            92: void           wpi_reset_tx_ring(struct wpi_softc *, struct wpi_tx_ring *);
        !            93: void           wpi_free_tx_ring(struct wpi_softc *, struct wpi_tx_ring *);
        !            94: struct         ieee80211_node *wpi_node_alloc(struct ieee80211com *);
        !            95: void           wpi_newassoc(struct ieee80211com *, struct ieee80211_node *,
        !            96:                    int);
        !            97: int            wpi_media_change(struct ifnet *);
        !            98: int            wpi_newstate(struct ieee80211com *, enum ieee80211_state, int);
        !            99: void           wpi_mem_lock(struct wpi_softc *);
        !           100: void           wpi_mem_unlock(struct wpi_softc *);
        !           101: uint32_t       wpi_mem_read(struct wpi_softc *, uint16_t);
        !           102: void           wpi_mem_write(struct wpi_softc *, uint16_t, uint32_t);
        !           103: void           wpi_mem_write_region_4(struct wpi_softc *, uint16_t,
        !           104:                    const uint32_t *, int);
        !           105: int            wpi_read_prom_data(struct wpi_softc *, uint32_t, void *, int);
        !           106: int            wpi_load_microcode(struct wpi_softc *, const uint8_t *, int);
        !           107: int            wpi_load_firmware(struct wpi_softc *);
        !           108: void           wpi_calib_timeout(void *);
        !           109: void           wpi_iter_func(void *, struct ieee80211_node *);
        !           110: void           wpi_power_calibration(struct wpi_softc *, int);
        !           111: void           wpi_rx_intr(struct wpi_softc *, struct wpi_rx_desc *,
        !           112:                    struct wpi_rx_data *);
        !           113: void           wpi_tx_intr(struct wpi_softc *, struct wpi_rx_desc *);
        !           114: void           wpi_cmd_intr(struct wpi_softc *, struct wpi_rx_desc *);
        !           115: void           wpi_notif_intr(struct wpi_softc *);
        !           116: int            wpi_intr(void *);
        !           117: void           wpi_read_eeprom(struct wpi_softc *);
        !           118: void           wpi_read_eeprom_channels(struct wpi_softc *, int);
        !           119: void           wpi_read_eeprom_group(struct wpi_softc *, int);
        !           120: uint8_t                wpi_plcp_signal(int);
        !           121: int            wpi_tx_data(struct wpi_softc *, struct mbuf *,
        !           122:                    struct ieee80211_node *, int);
        !           123: void           wpi_start(struct ifnet *);
        !           124: void           wpi_watchdog(struct ifnet *);
        !           125: int            wpi_ioctl(struct ifnet *, u_long, caddr_t);
        !           126: int            wpi_cmd(struct wpi_softc *, int, const void *, int, int);
        !           127: int            wpi_mrr_setup(struct wpi_softc *);
        !           128: void           wpi_set_led(struct wpi_softc *, uint8_t, uint8_t, uint8_t);
        !           129: void           wpi_enable_tsf(struct wpi_softc *, struct ieee80211_node *);
        !           130: int            wpi_set_txpower(struct wpi_softc *,
        !           131:                    struct ieee80211_channel *, int);
        !           132: int            wpi_get_power_index(struct wpi_softc *,
        !           133:                    struct wpi_power_group *, struct ieee80211_channel *, int);
        !           134: #ifdef notyet
        !           135: int            wpi_setup_beacon(struct wpi_softc *, struct ieee80211_node *);
        !           136: #endif
        !           137: int            wpi_auth(struct wpi_softc *);
        !           138: int            wpi_scan(struct wpi_softc *, uint16_t);
        !           139: int            wpi_config(struct wpi_softc *);
        !           140: void           wpi_stop_master(struct wpi_softc *);
        !           141: int            wpi_power_up(struct wpi_softc *);
        !           142: int            wpi_reset(struct wpi_softc *);
        !           143: void           wpi_hw_config(struct wpi_softc *);
        !           144: int            wpi_init(struct ifnet *);
        !           145: void           wpi_stop(struct ifnet *, int);
        !           146:
        !           147: #ifdef WPI_DEBUG
        !           148: #define DPRINTF(x)     do { if (wpi_debug > 0) printf x; } while (0)
        !           149: #define DPRINTFN(n, x) do { if (wpi_debug >= (n)) printf x; } while (0)
        !           150: int wpi_debug = 1;
        !           151: #else
        !           152: #define DPRINTF(x)
        !           153: #define DPRINTFN(n, x)
        !           154: #endif
        !           155:
        !           156: struct cfattach wpi_ca = {
        !           157:        sizeof (struct wpi_softc), wpi_match, wpi_attach
        !           158: };
        !           159:
        !           160: int
        !           161: wpi_match(struct device *parent, void *match, void *aux)
        !           162: {
        !           163:        return pci_matchbyid((struct pci_attach_args *)aux, wpi_devices,
        !           164:            sizeof (wpi_devices) / sizeof (wpi_devices[0]));
        !           165: }
        !           166:
        !           167: /* Base Address Register */
        !           168: #define WPI_PCI_BAR0   0x10
        !           169:
        !           170: void
        !           171: wpi_attach(struct device *parent, struct device *self, void *aux)
        !           172: {
        !           173:        struct wpi_softc *sc = (struct wpi_softc *)self;
        !           174:        struct ieee80211com *ic = &sc->sc_ic;
        !           175:        struct ifnet *ifp = &ic->ic_if;
        !           176:        struct pci_attach_args *pa = aux;
        !           177:        const char *intrstr;
        !           178:        bus_space_tag_t memt;
        !           179:        bus_space_handle_t memh;
        !           180:        pci_intr_handle_t ih;
        !           181:        pcireg_t data;
        !           182:        int ac, error;
        !           183:
        !           184:        sc->sc_pct = pa->pa_pc;
        !           185:        sc->sc_pcitag = pa->pa_tag;
        !           186:
        !           187:        /* clear device specific PCI configuration register 0x41 */
        !           188:        data = pci_conf_read(sc->sc_pct, sc->sc_pcitag, 0x40);
        !           189:        data &= ~0x0000ff00;
        !           190:        pci_conf_write(sc->sc_pct, sc->sc_pcitag, 0x40, data);
        !           191:
        !           192:        /* map the register window */
        !           193:        error = pci_mapreg_map(pa, WPI_PCI_BAR0, PCI_MAPREG_TYPE_MEM |
        !           194:            PCI_MAPREG_MEM_TYPE_32BIT, 0, &memt, &memh, NULL, &sc->sc_sz, 0);
        !           195:        if (error != 0) {
        !           196:                printf(": could not map memory space\n");
        !           197:                return;
        !           198:        }
        !           199:
        !           200:        sc->sc_st = memt;
        !           201:        sc->sc_sh = memh;
        !           202:        sc->sc_dmat = pa->pa_dmat;
        !           203:
        !           204:        if (pci_intr_map(pa, &ih) != 0) {
        !           205:                printf(": could not map interrupt\n");
        !           206:                return;
        !           207:        }
        !           208:
        !           209:        intrstr = pci_intr_string(sc->sc_pct, ih);
        !           210:        sc->sc_ih = pci_intr_establish(sc->sc_pct, ih, IPL_NET, wpi_intr, sc,
        !           211:            sc->sc_dev.dv_xname);
        !           212:        if (sc->sc_ih == NULL) {
        !           213:                printf(": could not establish interrupt");
        !           214:                if (intrstr != NULL)
        !           215:                        printf(" at %s", intrstr);
        !           216:                printf("\n");
        !           217:                return;
        !           218:        }
        !           219:        printf(": %s", intrstr);
        !           220:
        !           221:        /*
        !           222:         * Put adapter into a known state.
        !           223:         */
        !           224:        if ((error = wpi_reset(sc)) != 0) {
        !           225:                printf(": could not reset adapter\n");
        !           226:                return;
        !           227:        }
        !           228:
        !           229:        /*
        !           230:         * Allocate DMA memory for firmware transfers.
        !           231:         */
        !           232:        if ((error = wpi_alloc_fwmem(sc)) != 0) {
        !           233:                printf(": could not allocate firmware memory\n");
        !           234:                return;
        !           235:        }
        !           236:
        !           237:        /*
        !           238:         * Allocate shared page and Tx/Rx rings.
        !           239:         */
        !           240:        if ((error = wpi_alloc_shared(sc)) != 0) {
        !           241:                printf(": could not allocate shared area\n");
        !           242:                goto fail1;
        !           243:        }
        !           244:
        !           245:        if ((error = wpi_alloc_rpool(sc)) != 0) {
        !           246:                printf(": could not allocate Rx buffers\n");
        !           247:                goto fail2;
        !           248:        }
        !           249:
        !           250:        for (ac = 0; ac < 4; ac++) {
        !           251:                error = wpi_alloc_tx_ring(sc, &sc->txq[ac], WPI_TX_RING_COUNT,
        !           252:                    ac);
        !           253:                if (error != 0) {
        !           254:                        printf(": could not allocate Tx ring %d\n", ac);
        !           255:                        goto fail3;
        !           256:                }
        !           257:        }
        !           258:
        !           259:        error = wpi_alloc_tx_ring(sc, &sc->cmdq, WPI_CMD_RING_COUNT, 4);
        !           260:        if (error != 0) {
        !           261:                printf(": could not allocate command ring\n");
        !           262:                goto fail3;
        !           263:        }
        !           264:
        !           265:        error = wpi_alloc_rx_ring(sc, &sc->rxq);
        !           266:        if (error != 0) {
        !           267:                printf(": could not allocate Rx ring\n");
        !           268:                goto fail4;
        !           269:        }
        !           270:
        !           271:        ic->ic_phytype = IEEE80211_T_OFDM;      /* not only, but not used */
        !           272:        ic->ic_opmode = IEEE80211_M_STA;        /* default to BSS mode */
        !           273:        ic->ic_state = IEEE80211_S_INIT;
        !           274:
        !           275:        /* set device capabilities */
        !           276:        ic->ic_caps =
        !           277:            IEEE80211_C_WEP |           /* s/w WEP */
        !           278:            IEEE80211_C_MONITOR |       /* monitor mode supported */
        !           279:            IEEE80211_C_TXPMGT |        /* tx power management */
        !           280:            IEEE80211_C_SHSLOT |        /* short slot time supported */
        !           281:            IEEE80211_C_SHPREAMBLE;     /* short preamble supported */
        !           282:
        !           283:        /* read supported channels and MAC address from EEPROM */
        !           284:        wpi_read_eeprom(sc);
        !           285:
        !           286:        /* set supported .11a, .11b and .11g rates */
        !           287:        ic->ic_sup_rates[IEEE80211_MODE_11A] = ieee80211_std_rateset_11a;
        !           288:        ic->ic_sup_rates[IEEE80211_MODE_11B] = ieee80211_std_rateset_11b;
        !           289:        ic->ic_sup_rates[IEEE80211_MODE_11G] = ieee80211_std_rateset_11g;
        !           290:
        !           291:        /* IBSS channel undefined for now */
        !           292:        ic->ic_ibss_chan = &ic->ic_channels[0];
        !           293:
        !           294:        ifp->if_softc = sc;
        !           295:        ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
        !           296:        ifp->if_init = wpi_init;
        !           297:        ifp->if_ioctl = wpi_ioctl;
        !           298:        ifp->if_start = wpi_start;
        !           299:        ifp->if_watchdog = wpi_watchdog;
        !           300:        IFQ_SET_READY(&ifp->if_snd);
        !           301:        memcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ);
        !           302:
        !           303:        if_attach(ifp);
        !           304:        ieee80211_ifattach(ifp);
        !           305:        ic->ic_node_alloc = wpi_node_alloc;
        !           306:        ic->ic_newassoc = wpi_newassoc;
        !           307:
        !           308:        /* override state transition machine */
        !           309:        sc->sc_newstate = ic->ic_newstate;
        !           310:        ic->ic_newstate = wpi_newstate;
        !           311:        ieee80211_media_init(ifp, wpi_media_change, ieee80211_media_status);
        !           312:
        !           313:        sc->amrr.amrr_min_success_threshold =  1;
        !           314:        sc->amrr.amrr_max_success_threshold = 15;
        !           315:
        !           316:        /* register thermal sensor with the sensor framework */
        !           317:        strlcpy(sc->sensordev.xname, sc->sc_dev.dv_xname,
        !           318:            sizeof sc->sensordev.xname);
        !           319:        strlcpy(sc->sensor.desc, "temperature 0 - 285",
        !           320:            sizeof sc->sensor.desc);
        !           321:        sc->sensor.type = SENSOR_INTEGER;       /* not in muK! */
        !           322:        /* temperature invalid until interface is up */
        !           323:        sc->sensor.value = 0;
        !           324:        sc->sensor.flags = SENSOR_FINVALID;
        !           325:        sensor_attach(&sc->sensordev, &sc->sensor);
        !           326:        sensordev_install(&sc->sensordev);
        !           327:
        !           328:        timeout_set(&sc->calib_to, wpi_calib_timeout, sc);
        !           329:
        !           330:        sc->powerhook = powerhook_establish(wpi_power, sc);
        !           331:
        !           332: #if NBPFILTER > 0
        !           333:        bpfattach(&sc->sc_drvbpf, ifp, DLT_IEEE802_11_RADIO,
        !           334:            sizeof (struct ieee80211_frame) + IEEE80211_RADIOTAP_HDRLEN);
        !           335:
        !           336:        sc->sc_rxtap_len = sizeof sc->sc_rxtapu;
        !           337:        sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len);
        !           338:        sc->sc_rxtap.wr_ihdr.it_present = htole32(WPI_RX_RADIOTAP_PRESENT);
        !           339:
        !           340:        sc->sc_txtap_len = sizeof sc->sc_txtapu;
        !           341:        sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len);
        !           342:        sc->sc_txtap.wt_ihdr.it_present = htole32(WPI_TX_RADIOTAP_PRESENT);
        !           343: #endif
        !           344:
        !           345:        return;
        !           346:
        !           347:        /* free allocated memory if something failed during attachment */
        !           348: fail4: wpi_free_tx_ring(sc, &sc->cmdq);
        !           349: fail3: while (--ac >= 0)
        !           350:                wpi_free_tx_ring(sc, &sc->txq[ac]);
        !           351:        wpi_free_rpool(sc);
        !           352: fail2: wpi_free_shared(sc);
        !           353: fail1: wpi_free_fwmem(sc);
        !           354: }
        !           355:
        !           356: void
        !           357: wpi_power(int why, void *arg)
        !           358: {
        !           359:        struct wpi_softc *sc = arg;
        !           360:        struct ifnet *ifp;
        !           361:        pcireg_t data;
        !           362:        int s;
        !           363:
        !           364:        if (why != PWR_RESUME)
        !           365:                return;
        !           366:
        !           367:        /* clear device specific PCI configuration register 0x41 */
        !           368:        data = pci_conf_read(sc->sc_pct, sc->sc_pcitag, 0x40);
        !           369:        data &= ~0x0000ff00;
        !           370:        pci_conf_write(sc->sc_pct, sc->sc_pcitag, 0x40, data);
        !           371:
        !           372:        s = splnet();
        !           373:        ifp = &sc->sc_ic.ic_if;
        !           374:        if (ifp->if_flags & IFF_UP) {
        !           375:                ifp->if_init(ifp);
        !           376:                if (ifp->if_flags & IFF_RUNNING)
        !           377:                        ifp->if_start(ifp);
        !           378:        }
        !           379:        splx(s);
        !           380: }
        !           381:
        !           382: int
        !           383: wpi_dma_contig_alloc(bus_dma_tag_t tag, struct wpi_dma_info *dma, void **kvap,
        !           384:     bus_size_t size, bus_size_t alignment, int flags)
        !           385: {
        !           386:        int nsegs, error;
        !           387:
        !           388:        dma->tag = tag;
        !           389:        dma->size = size;
        !           390:
        !           391:        error = bus_dmamap_create(tag, size, 1, size, 0, flags, &dma->map);
        !           392:        if (error != 0)
        !           393:                goto fail;
        !           394:
        !           395:        error = bus_dmamem_alloc(tag, size, alignment, 0, &dma->seg, 1, &nsegs,
        !           396:            flags);
        !           397:        if (error != 0)
        !           398:                goto fail;
        !           399:
        !           400:        error = bus_dmamem_map(tag, &dma->seg, 1, size, &dma->vaddr, flags);
        !           401:        if (error != 0)
        !           402:                goto fail;
        !           403:
        !           404:        error = bus_dmamap_load_raw(tag, dma->map, &dma->seg, 1, size, flags);
        !           405:        if (error != 0)
        !           406:                goto fail;
        !           407:
        !           408:        memset(dma->vaddr, 0, size);
        !           409:
        !           410:        dma->paddr = dma->map->dm_segs[0].ds_addr;
        !           411:        if (kvap != NULL)
        !           412:                *kvap = dma->vaddr;
        !           413:
        !           414:        return 0;
        !           415:
        !           416: fail:  wpi_dma_contig_free(dma);
        !           417:        return error;
        !           418: }
        !           419:
        !           420: void
        !           421: wpi_dma_contig_free(struct wpi_dma_info *dma)
        !           422: {
        !           423:        if (dma->map != NULL) {
        !           424:                if (dma->vaddr != NULL) {
        !           425:                        bus_dmamap_unload(dma->tag, dma->map);
        !           426:                        bus_dmamem_unmap(dma->tag, dma->vaddr, dma->size);
        !           427:                        bus_dmamem_free(dma->tag, &dma->seg, 1);
        !           428:                        dma->vaddr = NULL;
        !           429:                }
        !           430:                bus_dmamap_destroy(dma->tag, dma->map);
        !           431:                dma->map = NULL;
        !           432:        }
        !           433: }
        !           434:
        !           435: /*
        !           436:  * Allocate a shared page between host and NIC.
        !           437:  */
        !           438: int
        !           439: wpi_alloc_shared(struct wpi_softc *sc)
        !           440: {
        !           441:        /* must be aligned on a 4K-page boundary */
        !           442:        return wpi_dma_contig_alloc(sc->sc_dmat, &sc->shared_dma,
        !           443:            (void **)&sc->shared, sizeof (struct wpi_shared), PAGE_SIZE,
        !           444:            BUS_DMA_NOWAIT);
        !           445: }
        !           446:
        !           447: void
        !           448: wpi_free_shared(struct wpi_softc *sc)
        !           449: {
        !           450:        wpi_dma_contig_free(&sc->shared_dma);
        !           451: }
        !           452:
        !           453: /*
        !           454:  * Allocate DMA-safe memory for firmware transfer.
        !           455:  */
        !           456: int
        !           457: wpi_alloc_fwmem(struct wpi_softc *sc)
        !           458: {
        !           459:        /* allocate enough contiguous space to store text and data */
        !           460:        return wpi_dma_contig_alloc(sc->sc_dmat, &sc->fw_dma, NULL,
        !           461:            WPI_FW_MAIN_TEXT_MAXSZ + WPI_FW_MAIN_DATA_MAXSZ, 0,
        !           462:            BUS_DMA_NOWAIT);
        !           463: }
        !           464:
        !           465: void
        !           466: wpi_free_fwmem(struct wpi_softc *sc)
        !           467: {
        !           468:        wpi_dma_contig_free(&sc->fw_dma);
        !           469: }
        !           470:
        !           471: struct wpi_rbuf *
        !           472: wpi_alloc_rbuf(struct wpi_softc *sc)
        !           473: {
        !           474:        struct wpi_rbuf *rbuf;
        !           475:
        !           476:        rbuf = SLIST_FIRST(&sc->rxq.freelist);
        !           477:        if (rbuf == NULL)
        !           478:                return NULL;
        !           479:        SLIST_REMOVE_HEAD(&sc->rxq.freelist, next);
        !           480:        return rbuf;
        !           481: }
        !           482:
        !           483: /*
        !           484:  * This is called automatically by the network stack when the mbuf to which our
        !           485:  * Rx buffer is attached is freed.
        !           486:  */
        !           487: void
        !           488: wpi_free_rbuf(caddr_t buf, u_int size, void *arg)
        !           489: {
        !           490:        struct wpi_rbuf *rbuf = arg;
        !           491:        struct wpi_softc *sc = rbuf->sc;
        !           492:
        !           493:        /* put the buffer back in the free list */
        !           494:        SLIST_INSERT_HEAD(&sc->rxq.freelist, rbuf, next);
        !           495: }
        !           496:
        !           497: int
        !           498: wpi_alloc_rpool(struct wpi_softc *sc)
        !           499: {
        !           500:        struct wpi_rx_ring *ring = &sc->rxq;
        !           501:        int i, error;
        !           502:
        !           503:        /* allocate a big chunk of DMA'able memory.. */
        !           504:        error = wpi_dma_contig_alloc(sc->sc_dmat, &ring->buf_dma, NULL,
        !           505:            WPI_RBUF_COUNT * WPI_RBUF_SIZE, PAGE_SIZE, BUS_DMA_NOWAIT);
        !           506:        if (error != 0) {
        !           507:                printf("%s: could not allocate Rx buffers DMA memory\n",
        !           508:                    sc->sc_dev.dv_xname);
        !           509:                return error;
        !           510:        }
        !           511:
        !           512:        /* ..and split it into 3KB chunks */
        !           513:        SLIST_INIT(&ring->freelist);
        !           514:        for (i = 0; i < WPI_RBUF_COUNT; i++) {
        !           515:                struct wpi_rbuf *rbuf = &ring->rbuf[i];
        !           516:
        !           517:                rbuf->sc = sc;  /* backpointer for callbacks */
        !           518:                rbuf->vaddr = ring->buf_dma.vaddr + i * WPI_RBUF_SIZE;
        !           519:                rbuf->paddr = ring->buf_dma.paddr + i * WPI_RBUF_SIZE;
        !           520:
        !           521:                SLIST_INSERT_HEAD(&ring->freelist, rbuf, next);
        !           522:        }
        !           523:        return 0;
        !           524: }
        !           525:
        !           526: void
        !           527: wpi_free_rpool(struct wpi_softc *sc)
        !           528: {
        !           529:        wpi_dma_contig_free(&sc->rxq.buf_dma);
        !           530: }
        !           531:
        !           532: int
        !           533: wpi_alloc_rx_ring(struct wpi_softc *sc, struct wpi_rx_ring *ring)
        !           534: {
        !           535:        int i, error;
        !           536:
        !           537:        ring->cur = 0;
        !           538:
        !           539:        error = wpi_dma_contig_alloc(sc->sc_dmat, &ring->desc_dma,
        !           540:            (void **)&ring->desc, WPI_RX_RING_COUNT * sizeof (uint32_t),
        !           541:            WPI_RING_DMA_ALIGN, BUS_DMA_NOWAIT);
        !           542:        if (error != 0) {
        !           543:                printf("%s: could not allocate rx ring DMA memory\n",
        !           544:                    sc->sc_dev.dv_xname);
        !           545:                goto fail;
        !           546:        }
        !           547:
        !           548:        /*
        !           549:         * Setup Rx buffers.
        !           550:         */
        !           551:        for (i = 0; i < WPI_RX_RING_COUNT; i++) {
        !           552:                struct wpi_rx_data *data = &ring->data[i];
        !           553:                struct wpi_rbuf *rbuf;
        !           554:
        !           555:                MGETHDR(data->m, M_DONTWAIT, MT_DATA);
        !           556:                if (data->m == NULL) {
        !           557:                        printf("%s: could not allocate rx mbuf\n",
        !           558:                            sc->sc_dev.dv_xname);
        !           559:                        error = ENOMEM;
        !           560:                        goto fail;
        !           561:                }
        !           562:                if ((rbuf = wpi_alloc_rbuf(sc)) == NULL) {
        !           563:                        m_freem(data->m);
        !           564:                        data->m = NULL;
        !           565:                        printf("%s: could not allocate rx buffer\n",
        !           566:                            sc->sc_dev.dv_xname);
        !           567:                        error = ENOMEM;
        !           568:                        goto fail;
        !           569:                }
        !           570:                /* attach Rx buffer to mbuf */
        !           571:                MEXTADD(data->m, rbuf->vaddr, WPI_RBUF_SIZE, 0, wpi_free_rbuf,
        !           572:                    rbuf);
        !           573:
        !           574:                ring->desc[i] = htole32(rbuf->paddr);
        !           575:        }
        !           576:
        !           577:        return 0;
        !           578:
        !           579: fail:  wpi_free_rx_ring(sc, ring);
        !           580:        return error;
        !           581: }
        !           582:
        !           583: void
        !           584: wpi_reset_rx_ring(struct wpi_softc *sc, struct wpi_rx_ring *ring)
        !           585: {
        !           586:        int ntries;
        !           587:
        !           588:        wpi_mem_lock(sc);
        !           589:
        !           590:        WPI_WRITE(sc, WPI_RX_CONFIG, 0);
        !           591:        for (ntries = 0; ntries < 100; ntries++) {
        !           592:                if (WPI_READ(sc, WPI_RX_STATUS) & WPI_RX_IDLE)
        !           593:                        break;
        !           594:                DELAY(10);
        !           595:        }
        !           596: #ifdef WPI_DEBUG
        !           597:        if (ntries == 100 && wpi_debug > 0)
        !           598:                printf("%s: timeout resetting Rx ring\n", sc->sc_dev.dv_xname);
        !           599: #endif
        !           600:        wpi_mem_unlock(sc);
        !           601:
        !           602:        ring->cur = 0;
        !           603: }
        !           604:
        !           605: void
        !           606: wpi_free_rx_ring(struct wpi_softc *sc, struct wpi_rx_ring *ring)
        !           607: {
        !           608:        int i;
        !           609:
        !           610:        wpi_dma_contig_free(&ring->desc_dma);
        !           611:
        !           612:        for (i = 0; i < WPI_RX_RING_COUNT; i++) {
        !           613:                if (ring->data[i].m != NULL)
        !           614:                        m_freem(ring->data[i].m);
        !           615:        }
        !           616: }
        !           617:
        !           618: int
        !           619: wpi_alloc_tx_ring(struct wpi_softc *sc, struct wpi_tx_ring *ring, int count,
        !           620:     int qid)
        !           621: {
        !           622:        int i, error;
        !           623:
        !           624:        ring->qid = qid;
        !           625:        ring->count = count;
        !           626:        ring->queued = 0;
        !           627:        ring->cur = 0;
        !           628:
        !           629:        error = wpi_dma_contig_alloc(sc->sc_dmat, &ring->desc_dma,
        !           630:            (void **)&ring->desc, count * sizeof (struct wpi_tx_desc),
        !           631:            WPI_RING_DMA_ALIGN, BUS_DMA_NOWAIT);
        !           632:        if (error != 0) {
        !           633:                printf("%s: could not allocate tx ring DMA memory\n",
        !           634:                    sc->sc_dev.dv_xname);
        !           635:                goto fail;
        !           636:        }
        !           637:
        !           638:        /* update shared page with ring's base address */
        !           639:        sc->shared->txbase[qid] = htole32(ring->desc_dma.paddr);
        !           640:
        !           641:        error = wpi_dma_contig_alloc(sc->sc_dmat, &ring->cmd_dma,
        !           642:            (void **)&ring->cmd, count * sizeof (struct wpi_tx_cmd), 4,
        !           643:            BUS_DMA_NOWAIT);
        !           644:        if (error != 0) {
        !           645:                printf("%s: could not allocate tx cmd DMA memory\n",
        !           646:                    sc->sc_dev.dv_xname);
        !           647:                goto fail;
        !           648:        }
        !           649:
        !           650:        ring->data = malloc(count * sizeof (struct wpi_tx_data), M_DEVBUF,
        !           651:            M_NOWAIT);
        !           652:        if (ring->data == NULL) {
        !           653:                printf("%s: could not allocate tx data slots\n",
        !           654:                    sc->sc_dev.dv_xname);
        !           655:                goto fail;
        !           656:        }
        !           657:
        !           658:        memset(ring->data, 0, count * sizeof (struct wpi_tx_data));
        !           659:
        !           660:        for (i = 0; i < count; i++) {
        !           661:                struct wpi_tx_data *data = &ring->data[i];
        !           662:
        !           663:                error = bus_dmamap_create(sc->sc_dmat, MCLBYTES,
        !           664:                    WPI_MAX_SCATTER - 1, MCLBYTES, 0, BUS_DMA_NOWAIT,
        !           665:                    &data->map);
        !           666:                if (error != 0) {
        !           667:                        printf("%s: could not create tx buf DMA map\n",
        !           668:                            sc->sc_dev.dv_xname);
        !           669:                        goto fail;
        !           670:                }
        !           671:        }
        !           672:
        !           673:        return 0;
        !           674:
        !           675: fail:  wpi_free_tx_ring(sc, ring);
        !           676:        return error;
        !           677: }
        !           678:
        !           679: void
        !           680: wpi_reset_tx_ring(struct wpi_softc *sc, struct wpi_tx_ring *ring)
        !           681: {
        !           682:        int i, ntries;
        !           683:
        !           684:        wpi_mem_lock(sc);
        !           685:
        !           686:        WPI_WRITE(sc, WPI_TX_CONFIG(ring->qid), 0);
        !           687:        for (ntries = 0; ntries < 100; ntries++) {
        !           688:                if (WPI_READ(sc, WPI_TX_STATUS) & WPI_TX_IDLE(ring->qid))
        !           689:                        break;
        !           690:                DELAY(10);
        !           691:        }
        !           692: #ifdef WPI_DEBUG
        !           693:        if (ntries == 100 && wpi_debug > 0) {
        !           694:                printf("%s: timeout resetting Tx ring %d\n",
        !           695:                    sc->sc_dev.dv_xname, ring->qid);
        !           696:        }
        !           697: #endif
        !           698:        wpi_mem_unlock(sc);
        !           699:
        !           700:        for (i = 0; i < ring->count; i++) {
        !           701:                struct wpi_tx_data *data = &ring->data[i];
        !           702:
        !           703:                if (data->m != NULL) {
        !           704:                        bus_dmamap_unload(sc->sc_dmat, data->map);
        !           705:                        m_freem(data->m);
        !           706:                        data->m = NULL;
        !           707:                }
        !           708:        }
        !           709:
        !           710:        ring->queued = 0;
        !           711:        ring->cur = 0;
        !           712: }
        !           713:
        !           714: void
        !           715: wpi_free_tx_ring(struct wpi_softc *sc, struct wpi_tx_ring *ring)
        !           716: {
        !           717:        int i;
        !           718:
        !           719:        wpi_dma_contig_free(&ring->desc_dma);
        !           720:        wpi_dma_contig_free(&ring->cmd_dma);
        !           721:
        !           722:        if (ring->data != NULL) {
        !           723:                for (i = 0; i < ring->count; i++) {
        !           724:                        struct wpi_tx_data *data = &ring->data[i];
        !           725:
        !           726:                        if (data->m != NULL) {
        !           727:                                bus_dmamap_unload(sc->sc_dmat, data->map);
        !           728:                                m_freem(data->m);
        !           729:                        }
        !           730:                }
        !           731:                free(ring->data, M_DEVBUF);
        !           732:        }
        !           733: }
        !           734:
        !           735: struct ieee80211_node *
        !           736: wpi_node_alloc(struct ieee80211com *ic)
        !           737: {
        !           738:        struct wpi_node *wn;
        !           739:
        !           740:        wn = malloc(sizeof (struct wpi_node), M_DEVBUF, M_NOWAIT);
        !           741:        if (wn != NULL)
        !           742:                memset(wn, 0, sizeof (struct wpi_node));
        !           743:        return (struct ieee80211_node *)wn;
        !           744: }
        !           745:
        !           746: void
        !           747: wpi_newassoc(struct ieee80211com *ic, struct ieee80211_node *ni, int isnew)
        !           748: {
        !           749:        struct wpi_softc *sc = ic->ic_if.if_softc;
        !           750:        int i;
        !           751:
        !           752:        ieee80211_amrr_node_init(&sc->amrr, &((struct wpi_node *)ni)->amn);
        !           753:
        !           754:        /* set rate to some reasonable initial value */
        !           755:        for (i = ni->ni_rates.rs_nrates - 1;
        !           756:             i > 0 && (ni->ni_rates.rs_rates[i] & IEEE80211_RATE_VAL) > 72;
        !           757:             i--);
        !           758:        ni->ni_txrate = i;
        !           759: }
        !           760:
        !           761: int
        !           762: wpi_media_change(struct ifnet *ifp)
        !           763: {
        !           764:        int error;
        !           765:
        !           766:        error = ieee80211_media_change(ifp);
        !           767:        if (error != ENETRESET)
        !           768:                return error;
        !           769:
        !           770:        if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING))
        !           771:                wpi_init(ifp);
        !           772:
        !           773:        return 0;
        !           774: }
        !           775:
        !           776: int
        !           777: wpi_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
        !           778: {
        !           779:        struct ifnet *ifp = &ic->ic_if;
        !           780:        struct wpi_softc *sc = ifp->if_softc;
        !           781:        struct ieee80211_node *ni;
        !           782:        int error;
        !           783:
        !           784:        timeout_del(&sc->calib_to);
        !           785:
        !           786:        if (ic->ic_state == IEEE80211_S_SCAN)
        !           787:                ic->ic_scan_lock = IEEE80211_SCAN_UNLOCKED;
        !           788:
        !           789:        switch (nstate) {
        !           790:        case IEEE80211_S_SCAN:
        !           791:                /* make the link LED blink while we're scanning */
        !           792:                wpi_set_led(sc, WPI_LED_LINK, 20, 2);
        !           793:
        !           794:                if ((error = wpi_scan(sc, IEEE80211_CHAN_G)) != 0) {
        !           795:                        printf("%s: could not initiate scan\n",
        !           796:                            sc->sc_dev.dv_xname);
        !           797:                        return error;
        !           798:                }
        !           799:                ic->ic_state = nstate;
        !           800:                return 0;
        !           801:
        !           802:        case IEEE80211_S_ASSOC:
        !           803:                if (ic->ic_state != IEEE80211_S_RUN)
        !           804:                        break;
        !           805:                /* FALLTHROUGH */
        !           806:        case IEEE80211_S_AUTH:
        !           807:                /* reset state to handle reassociations correctly */
        !           808:                sc->config.associd = 0;
        !           809:                sc->config.filter &= ~htole32(WPI_FILTER_BSS);
        !           810:
        !           811:                if ((error = wpi_auth(sc)) != 0) {
        !           812:                        printf("%s: could not send authentication request\n",
        !           813:                            sc->sc_dev.dv_xname);
        !           814:                        return error;
        !           815:                }
        !           816:                break;
        !           817:
        !           818:        case IEEE80211_S_RUN:
        !           819:                if (ic->ic_opmode == IEEE80211_M_MONITOR) {
        !           820:                        /* link LED blinks while monitoring */
        !           821:                        wpi_set_led(sc, WPI_LED_LINK, 5, 5);
        !           822:                        break;
        !           823:                }
        !           824:                ni = ic->ic_bss;
        !           825:
        !           826:                wpi_enable_tsf(sc, ni);
        !           827:
        !           828:                /* update adapter's configuration */
        !           829:                sc->config.associd = htole16(ni->ni_associd & ~0xc000);
        !           830:                /* short preamble/slot time are negotiated when associating */
        !           831:                sc->config.flags &= ~htole32(WPI_CONFIG_SHPREAMBLE |
        !           832:                    WPI_CONFIG_SHSLOT);
        !           833:                if (ic->ic_flags & IEEE80211_F_SHSLOT)
        !           834:                        sc->config.flags |= htole32(WPI_CONFIG_SHSLOT);
        !           835:                if (ic->ic_flags & IEEE80211_F_SHPREAMBLE)
        !           836:                        sc->config.flags |= htole32(WPI_CONFIG_SHPREAMBLE);
        !           837:                sc->config.filter |= htole32(WPI_FILTER_BSS);
        !           838:
        !           839:                DPRINTF(("config chan %d flags %x\n", sc->config.chan,
        !           840:                    sc->config.flags));
        !           841:                error = wpi_cmd(sc, WPI_CMD_CONFIGURE, &sc->config,
        !           842:                    sizeof (struct wpi_config), 1);
        !           843:                if (error != 0) {
        !           844:                        printf("%s: could not update configuration\n",
        !           845:                            sc->sc_dev.dv_xname);
        !           846:                        return error;
        !           847:                }
        !           848:
        !           849:                /* configuration has changed, set Tx power accordingly */
        !           850:                if ((error = wpi_set_txpower(sc, ni->ni_chan, 1)) != 0) {
        !           851:                        printf("%s: could not set Tx power\n",
        !           852:                            sc->sc_dev.dv_xname);
        !           853:                        return error;
        !           854:                }
        !           855:
        !           856:                if (ic->ic_opmode == IEEE80211_M_STA) {
        !           857:                        /* fake a join to init the tx rate */
        !           858:                        wpi_newassoc(ic, ni, 1);
        !           859:                }
        !           860:
        !           861:                /* start periodic calibration timer */
        !           862:                sc->calib_cnt = 0;
        !           863:                timeout_add(&sc->calib_to, hz / 2);
        !           864:
        !           865:                /* link LED always on while associated */
        !           866:                wpi_set_led(sc, WPI_LED_LINK, 0, 1);
        !           867:                break;
        !           868:
        !           869:        case IEEE80211_S_INIT:
        !           870:                break;
        !           871:        }
        !           872:
        !           873:        return sc->sc_newstate(ic, nstate, arg);
        !           874: }
        !           875:
        !           876: /*
        !           877:  * Grab exclusive access to NIC memory.
        !           878:  */
        !           879: void
        !           880: wpi_mem_lock(struct wpi_softc *sc)
        !           881: {
        !           882:        uint32_t tmp;
        !           883:        int ntries;
        !           884:
        !           885:        tmp = WPI_READ(sc, WPI_GPIO_CTL);
        !           886:        WPI_WRITE(sc, WPI_GPIO_CTL, tmp | WPI_GPIO_MAC);
        !           887:
        !           888:        /* spin until we actually get the lock */
        !           889:        for (ntries = 0; ntries < 1000; ntries++) {
        !           890:                if ((WPI_READ(sc, WPI_GPIO_CTL) &
        !           891:                    (WPI_GPIO_CLOCK | WPI_GPIO_SLEEP)) == WPI_GPIO_CLOCK)
        !           892:                        break;
        !           893:                DELAY(10);
        !           894:        }
        !           895:        if (ntries == 1000)
        !           896:                printf("%s: could not lock memory\n", sc->sc_dev.dv_xname);
        !           897: }
        !           898:
        !           899: /*
        !           900:  * Release lock on NIC memory.
        !           901:  */
        !           902: void
        !           903: wpi_mem_unlock(struct wpi_softc *sc)
        !           904: {
        !           905:        uint32_t tmp = WPI_READ(sc, WPI_GPIO_CTL);
        !           906:        WPI_WRITE(sc, WPI_GPIO_CTL, tmp & ~WPI_GPIO_MAC);
        !           907: }
        !           908:
        !           909: uint32_t
        !           910: wpi_mem_read(struct wpi_softc *sc, uint16_t addr)
        !           911: {
        !           912:        WPI_WRITE(sc, WPI_READ_MEM_ADDR, WPI_MEM_4 | addr);
        !           913:        return WPI_READ(sc, WPI_READ_MEM_DATA);
        !           914: }
        !           915:
        !           916: void
        !           917: wpi_mem_write(struct wpi_softc *sc, uint16_t addr, uint32_t data)
        !           918: {
        !           919:        WPI_WRITE(sc, WPI_WRITE_MEM_ADDR, WPI_MEM_4 | addr);
        !           920:        WPI_WRITE(sc, WPI_WRITE_MEM_DATA, data);
        !           921: }
        !           922:
        !           923: void
        !           924: wpi_mem_write_region_4(struct wpi_softc *sc, uint16_t addr,
        !           925:     const uint32_t *data, int wlen)
        !           926: {
        !           927:        for (; wlen > 0; wlen--, data++, addr += 4)
        !           928:                wpi_mem_write(sc, addr, *data);
        !           929: }
        !           930:
        !           931: /*
        !           932:  * Read `len' bytes from the EEPROM.  We access the EEPROM through the MAC
        !           933:  * instead of using the traditional bit-bang method.
        !           934:  */
        !           935: int
        !           936: wpi_read_prom_data(struct wpi_softc *sc, uint32_t addr, void *data, int len)
        !           937: {
        !           938:        uint8_t *out = data;
        !           939:        uint32_t val;
        !           940:        int ntries;
        !           941:
        !           942:        wpi_mem_lock(sc);
        !           943:        for (; len > 0; len -= 2, addr++) {
        !           944:                WPI_WRITE(sc, WPI_EEPROM_CTL, addr << 2);
        !           945:
        !           946:                for (ntries = 0; ntries < 10; ntries++) {
        !           947:                        if ((val = WPI_READ(sc, WPI_EEPROM_CTL)) &
        !           948:                            WPI_EEPROM_READY)
        !           949:                                break;
        !           950:                        DELAY(5);
        !           951:                }
        !           952:                if (ntries == 10) {
        !           953:                        printf("%s: could not read EEPROM\n",
        !           954:                            sc->sc_dev.dv_xname);
        !           955:                        return ETIMEDOUT;
        !           956:                }
        !           957:                *out++ = val >> 16;
        !           958:                if (len > 1)
        !           959:                        *out++ = val >> 24;
        !           960:        }
        !           961:        wpi_mem_unlock(sc);
        !           962:
        !           963:        return 0;
        !           964: }
        !           965:
        !           966: /*
        !           967:  * The firmware boot code is small and is intended to be copied directly into
        !           968:  * the NIC internal memory.
        !           969:  */
        !           970: int
        !           971: wpi_load_microcode(struct wpi_softc *sc, const uint8_t *ucode, int size)
        !           972: {
        !           973:        int ntries;
        !           974:
        !           975:        size /= sizeof (uint32_t);
        !           976:
        !           977:        wpi_mem_lock(sc);
        !           978:
        !           979:        /* copy microcode image into NIC memory */
        !           980:        wpi_mem_write_region_4(sc, WPI_MEM_UCODE_BASE,
        !           981:            (const uint32_t *)ucode, size);
        !           982:
        !           983:        wpi_mem_write(sc, WPI_MEM_UCODE_SRC, 0);
        !           984:        wpi_mem_write(sc, WPI_MEM_UCODE_DST, WPI_FW_TEXT);
        !           985:        wpi_mem_write(sc, WPI_MEM_UCODE_SIZE, size);
        !           986:
        !           987:        /* run microcode */
        !           988:        wpi_mem_write(sc, WPI_MEM_UCODE_CTL, WPI_UC_RUN);
        !           989:
        !           990:        /* wait for transfer to complete */
        !           991:        for (ntries = 0; ntries < 1000; ntries++) {
        !           992:                if (!(wpi_mem_read(sc, WPI_MEM_UCODE_CTL) & WPI_UC_RUN))
        !           993:                        break;
        !           994:                DELAY(10);
        !           995:        }
        !           996:        if (ntries == 1000) {
        !           997:                wpi_mem_unlock(sc);
        !           998:                printf("%s: could not load boot firmware\n",
        !           999:                    sc->sc_dev.dv_xname);
        !          1000:                return ETIMEDOUT;
        !          1001:        }
        !          1002:        wpi_mem_write(sc, WPI_MEM_UCODE_CTL, WPI_UC_ENABLE);
        !          1003:
        !          1004:        wpi_mem_unlock(sc);
        !          1005:
        !          1006:        return 0;
        !          1007: }
        !          1008:
        !          1009: int
        !          1010: wpi_load_firmware(struct wpi_softc *sc)
        !          1011: {
        !          1012:        struct wpi_dma_info *dma = &sc->fw_dma;
        !          1013:        const struct wpi_firmware_hdr *hdr;
        !          1014:        const uint8_t *init_text, *init_data, *main_text, *main_data;
        !          1015:        const uint8_t *boot_text;
        !          1016:        uint32_t init_textsz, init_datasz, main_textsz, main_datasz;
        !          1017:        uint32_t boot_textsz;
        !          1018:        u_char *fw;
        !          1019:        size_t size;
        !          1020:        int error;
        !          1021:
        !          1022:        /* load firmware image from disk */
        !          1023:        if ((error = loadfirmware("wpi-3945abg", &fw, &size)) != 0) {
        !          1024:                printf("%s: could not read firmware file\n",
        !          1025:                    sc->sc_dev.dv_xname);
        !          1026:                goto fail1;
        !          1027:        }
        !          1028:
        !          1029:        /* extract firmware header information */
        !          1030:        if (size < sizeof (struct wpi_firmware_hdr)) {
        !          1031:                printf("%s: truncated firmware header: %d bytes\n",
        !          1032:                    sc->sc_dev.dv_xname, size);
        !          1033:                error = EINVAL;
        !          1034:                goto fail2;
        !          1035:        }
        !          1036:        hdr = (const struct wpi_firmware_hdr *)fw;
        !          1037:        main_textsz = letoh32(hdr->main_textsz);
        !          1038:        main_datasz = letoh32(hdr->main_datasz);
        !          1039:        init_textsz = letoh32(hdr->init_textsz);
        !          1040:        init_datasz = letoh32(hdr->init_datasz);
        !          1041:        boot_textsz = letoh32(hdr->boot_textsz);
        !          1042:
        !          1043:        /* sanity-check firmware segments sizes */
        !          1044:        if (main_textsz > WPI_FW_MAIN_TEXT_MAXSZ ||
        !          1045:            main_datasz > WPI_FW_MAIN_DATA_MAXSZ ||
        !          1046:            init_textsz > WPI_FW_INIT_TEXT_MAXSZ ||
        !          1047:            init_datasz > WPI_FW_INIT_DATA_MAXSZ ||
        !          1048:            boot_textsz > WPI_FW_BOOT_TEXT_MAXSZ ||
        !          1049:            (boot_textsz & 3) != 0) {
        !          1050:                printf("%s: invalid firmware header\n", sc->sc_dev.dv_xname);
        !          1051:                error = EINVAL;
        !          1052:                goto fail2;
        !          1053:        }
        !          1054:
        !          1055:        /* check that all firmware segments are present */
        !          1056:        if (size < sizeof (struct wpi_firmware_hdr) + main_textsz +
        !          1057:            main_datasz + init_textsz + init_datasz + boot_textsz) {
        !          1058:                printf("%s: firmware file too short: %d bytes\n",
        !          1059:                    sc->sc_dev.dv_xname, size);
        !          1060:                error = EINVAL;
        !          1061:                goto fail2;
        !          1062:        }
        !          1063:
        !          1064:        /* get pointers to firmware segments */
        !          1065:        main_text = (const uint8_t *)(hdr + 1);
        !          1066:        main_data = main_text + main_textsz;
        !          1067:        init_text = main_data + main_datasz;
        !          1068:        init_data = init_text + init_textsz;
        !          1069:        boot_text = init_data + init_datasz;
        !          1070:
        !          1071:        /* copy initialization images into pre-allocated DMA-safe memory */
        !          1072:        memcpy(dma->vaddr, init_data, init_datasz);
        !          1073:        memcpy(dma->vaddr + WPI_FW_INIT_DATA_MAXSZ, init_text, init_textsz);
        !          1074:
        !          1075:        /* tell adapter where to find initialization images */
        !          1076:        wpi_mem_lock(sc);
        !          1077:        wpi_mem_write(sc, WPI_MEM_DATA_BASE, dma->paddr);
        !          1078:        wpi_mem_write(sc, WPI_MEM_DATA_SIZE, init_datasz);
        !          1079:        wpi_mem_write(sc, WPI_MEM_TEXT_BASE,
        !          1080:            dma->paddr + WPI_FW_INIT_DATA_MAXSZ);
        !          1081:        wpi_mem_write(sc, WPI_MEM_TEXT_SIZE, init_textsz);
        !          1082:        wpi_mem_unlock(sc);
        !          1083:
        !          1084:        /* load firmware boot code */
        !          1085:        if ((error = wpi_load_microcode(sc, boot_text, boot_textsz)) != 0) {
        !          1086:                printf("%s: could not load boot firmware\n",
        !          1087:                    sc->sc_dev.dv_xname);
        !          1088:                goto fail2;
        !          1089:        }
        !          1090:
        !          1091:        /* now press "execute" ;-) */
        !          1092:        WPI_WRITE(sc, WPI_RESET, 0);
        !          1093:
        !          1094:        /* wait at most one second for first alive notification */
        !          1095:        if ((error = tsleep(sc, PCATCH, "wpiinit", hz)) != 0) {
        !          1096:                /* this isn't what was supposed to happen.. */
        !          1097:                printf("%s: timeout waiting for adapter to initialize\n",
        !          1098:                    sc->sc_dev.dv_xname);
        !          1099:                goto fail2;
        !          1100:        }
        !          1101:
        !          1102:        /* copy runtime images into pre-allocated DMA-safe memory */
        !          1103:        memcpy(dma->vaddr, main_data, main_datasz);
        !          1104:        memcpy(dma->vaddr + WPI_FW_MAIN_DATA_MAXSZ, main_text, main_textsz);
        !          1105:
        !          1106:        /* tell adapter where to find runtime images */
        !          1107:        wpi_mem_lock(sc);
        !          1108:        wpi_mem_write(sc, WPI_MEM_DATA_BASE, dma->paddr);
        !          1109:        wpi_mem_write(sc, WPI_MEM_DATA_SIZE, main_datasz);
        !          1110:        wpi_mem_write(sc, WPI_MEM_TEXT_BASE,
        !          1111:            dma->paddr + WPI_FW_MAIN_DATA_MAXSZ);
        !          1112:        wpi_mem_write(sc, WPI_MEM_TEXT_SIZE, WPI_FW_UPDATED | main_textsz);
        !          1113:        wpi_mem_unlock(sc);
        !          1114:
        !          1115:        /* wait at most one second for second alive notification */
        !          1116:        if ((error = tsleep(sc, PCATCH, "wpiinit", hz)) != 0) {
        !          1117:                /* this isn't what was supposed to happen.. */
        !          1118:                printf("%s: timeout waiting for adapter to initialize\n",
        !          1119:                    sc->sc_dev.dv_xname);
        !          1120:        }
        !          1121:
        !          1122: fail2: free(fw, M_DEVBUF);
        !          1123: fail1: return error;
        !          1124: }
        !          1125:
        !          1126: void
        !          1127: wpi_calib_timeout(void *arg)
        !          1128: {
        !          1129:        struct wpi_softc *sc = arg;
        !          1130:        struct ieee80211com *ic = &sc->sc_ic;
        !          1131:        int temp, s;
        !          1132:
        !          1133:        /* automatic rate control triggered every 500ms */
        !          1134:        if (ic->ic_fixed_rate == -1) {
        !          1135:                s = splnet();
        !          1136:                if (ic->ic_opmode == IEEE80211_M_STA)
        !          1137:                        wpi_iter_func(sc, ic->ic_bss);
        !          1138:                else
        !          1139:                        ieee80211_iterate_nodes(ic, wpi_iter_func, sc);
        !          1140:                splx(s);
        !          1141:        }
        !          1142:
        !          1143:        /* update sensor data */
        !          1144:        temp = (int)WPI_READ(sc, WPI_TEMPERATURE);
        !          1145:        sc->sensor.value = temp + 260;
        !          1146:
        !          1147:        /* automatic power calibration every 60s */
        !          1148:        if (++sc->calib_cnt >= 120) {
        !          1149:                wpi_power_calibration(sc, temp);
        !          1150:                sc->calib_cnt = 0;
        !          1151:        }
        !          1152:
        !          1153:        timeout_add(&sc->calib_to, hz / 2);
        !          1154: }
        !          1155:
        !          1156: void
        !          1157: wpi_iter_func(void *arg, struct ieee80211_node *ni)
        !          1158: {
        !          1159:        struct wpi_softc *sc = arg;
        !          1160:        struct wpi_node *wn = (struct wpi_node *)ni;
        !          1161:
        !          1162:        ieee80211_amrr_choose(&sc->amrr, ni, &wn->amn);
        !          1163: }
        !          1164:
        !          1165: /*
        !          1166:  * This function is called periodically (every 60 seconds) to adjust output
        !          1167:  * power to temperature changes.
        !          1168:  */
        !          1169: void
        !          1170: wpi_power_calibration(struct wpi_softc *sc, int temp)
        !          1171: {
        !          1172:        /* sanity-check read value */
        !          1173:        if (temp < -260 || temp > 25) {
        !          1174:                /* this can't be correct, ignore */
        !          1175:                DPRINTF(("out-of-range temperature reported: %d\n", temp));
        !          1176:                return;
        !          1177:        }
        !          1178:
        !          1179:        DPRINTF(("temperature %d->%d\n", sc->temp, temp));
        !          1180:
        !          1181:        /* adjust Tx power if need be */
        !          1182:        if (abs(temp - sc->temp) <= 6)
        !          1183:                return;
        !          1184:
        !          1185:        sc->temp = temp;
        !          1186:
        !          1187:        if (wpi_set_txpower(sc, sc->sc_ic.ic_bss->ni_chan, 1) != 0) {
        !          1188:                /* just warn, too bad for the automatic calibration... */
        !          1189:                printf("%s: could not adjust Tx power\n",
        !          1190:                    sc->sc_dev.dv_xname);
        !          1191:        }
        !          1192: }
        !          1193:
        !          1194: void
        !          1195: wpi_rx_intr(struct wpi_softc *sc, struct wpi_rx_desc *desc,
        !          1196:     struct wpi_rx_data *data)
        !          1197: {
        !          1198:        struct ieee80211com *ic = &sc->sc_ic;
        !          1199:        struct ifnet *ifp = &ic->ic_if;
        !          1200:        struct wpi_rx_ring *ring = &sc->rxq;
        !          1201:        struct wpi_rx_stat *stat;
        !          1202:        struct wpi_rx_head *head;
        !          1203:        struct wpi_rx_tail *tail;
        !          1204:        struct wpi_rbuf *rbuf;
        !          1205:        struct ieee80211_frame *wh;
        !          1206:        struct ieee80211_node *ni;
        !          1207:        struct mbuf *m, *mnew;
        !          1208:
        !          1209:        stat = (struct wpi_rx_stat *)(desc + 1);
        !          1210:
        !          1211:        if (stat->len > WPI_STAT_MAXLEN) {
        !          1212:                printf("%s: invalid rx statistic header\n",
        !          1213:                    sc->sc_dev.dv_xname);
        !          1214:                ifp->if_ierrors++;
        !          1215:                return;
        !          1216:        }
        !          1217:
        !          1218:        head = (struct wpi_rx_head *)((caddr_t)(stat + 1) + stat->len);
        !          1219:        tail = (struct wpi_rx_tail *)((caddr_t)(head + 1) + letoh16(head->len));
        !          1220:
        !          1221:        DPRINTFN(4, ("rx intr: idx=%d len=%d stat len=%d rssi=%d rate=%x "
        !          1222:            "chan=%d tstamp=%llu\n", ring->cur, letoh32(desc->len),
        !          1223:            letoh16(head->len), (int8_t)stat->rssi, head->rate, head->chan,
        !          1224:            letoh64(tail->tstamp)));
        !          1225:
        !          1226:        /*
        !          1227:         * Discard Rx frames with bad CRC early (XXX we may want to pass them
        !          1228:         * to radiotap in monitor mode).
        !          1229:         */
        !          1230:        if ((letoh32(tail->flags) & WPI_RX_NOERROR) != WPI_RX_NOERROR) {
        !          1231:                DPRINTFN(2, ("rx tail flags error %x\n",
        !          1232:                    letoh32(tail->flags)));
        !          1233:                ifp->if_ierrors++;
        !          1234:                return;
        !          1235:        }
        !          1236:
        !          1237:        MGETHDR(mnew, M_DONTWAIT, MT_DATA);
        !          1238:        if (mnew == NULL) {
        !          1239:                ifp->if_ierrors++;
        !          1240:                return;
        !          1241:        }
        !          1242:        if ((rbuf = wpi_alloc_rbuf(sc)) == NULL) {
        !          1243:                m_freem(mnew);
        !          1244:                ifp->if_ierrors++;
        !          1245:                return;
        !          1246:        }
        !          1247:        /* attach Rx buffer to mbuf */
        !          1248:        MEXTADD(mnew, rbuf->vaddr, WPI_RBUF_SIZE, 0, wpi_free_rbuf, rbuf);
        !          1249:
        !          1250:        m = data->m;
        !          1251:        data->m = mnew;
        !          1252:
        !          1253:        /* update Rx descriptor */
        !          1254:        ring->desc[ring->cur] = htole32(rbuf->paddr);
        !          1255:
        !          1256:        /* finalize mbuf */
        !          1257:        m->m_pkthdr.rcvif = ifp;
        !          1258:        m->m_data = (caddr_t)(head + 1);
        !          1259:        m->m_pkthdr.len = m->m_len = letoh16(head->len);
        !          1260:
        !          1261: #if NBPFILTER > 0
        !          1262:        if (sc->sc_drvbpf != NULL) {
        !          1263:                struct mbuf mb;
        !          1264:                struct wpi_rx_radiotap_header *tap = &sc->sc_rxtap;
        !          1265:
        !          1266:                tap->wr_flags = 0;
        !          1267:                tap->wr_chan_freq =
        !          1268:                    htole16(ic->ic_channels[head->chan].ic_freq);
        !          1269:                tap->wr_chan_flags =
        !          1270:                    htole16(ic->ic_channels[head->chan].ic_flags);
        !          1271:                tap->wr_dbm_antsignal = (int8_t)(stat->rssi - WPI_RSSI_OFFSET);
        !          1272:                tap->wr_dbm_antnoise = (int8_t)letoh16(stat->noise);
        !          1273:                tap->wr_tsft = tail->tstamp;
        !          1274:                tap->wr_antenna = (letoh16(head->flags) >> 4) & 0xf;
        !          1275:                switch (head->rate) {
        !          1276:                /* CCK rates */
        !          1277:                case  10: tap->wr_rate =   2; break;
        !          1278:                case  20: tap->wr_rate =   4; break;
        !          1279:                case  55: tap->wr_rate =  11; break;
        !          1280:                case 110: tap->wr_rate =  22; break;
        !          1281:                /* OFDM rates */
        !          1282:                case 0xd: tap->wr_rate =  12; break;
        !          1283:                case 0xf: tap->wr_rate =  18; break;
        !          1284:                case 0x5: tap->wr_rate =  24; break;
        !          1285:                case 0x7: tap->wr_rate =  36; break;
        !          1286:                case 0x9: tap->wr_rate =  48; break;
        !          1287:                case 0xb: tap->wr_rate =  72; break;
        !          1288:                case 0x1: tap->wr_rate =  96; break;
        !          1289:                case 0x3: tap->wr_rate = 108; break;
        !          1290:                /* unknown rate: should not happen */
        !          1291:                default:  tap->wr_rate =   0;
        !          1292:                }
        !          1293:                if (letoh16(head->flags) & 0x4)
        !          1294:                        tap->wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
        !          1295:
        !          1296:                mb.m_data = (caddr_t)tap;
        !          1297:                mb.m_len = sc->sc_rxtap_len;
        !          1298:                mb.m_next = m;
        !          1299:                mb.m_nextpkt = NULL;
        !          1300:                mb.m_type = 0;
        !          1301:                mb.m_flags = 0;
        !          1302:                bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_IN);
        !          1303:        }
        !          1304: #endif
        !          1305:
        !          1306:        /* grab a reference to the source node */
        !          1307:        wh = mtod(m, struct ieee80211_frame *);
        !          1308:        ni = ieee80211_find_rxnode(ic, wh);
        !          1309:
        !          1310:        /* send the frame to the 802.11 layer */
        !          1311:        ieee80211_input(ifp, m, ni, stat->rssi, 0);
        !          1312:
        !          1313:        /* node is no longer needed */
        !          1314:        ieee80211_release_node(ic, ni);
        !          1315: }
        !          1316:
        !          1317: void
        !          1318: wpi_tx_intr(struct wpi_softc *sc, struct wpi_rx_desc *desc)
        !          1319: {
        !          1320:        struct ieee80211com *ic = &sc->sc_ic;
        !          1321:        struct ifnet *ifp = &ic->ic_if;
        !          1322:        struct wpi_tx_ring *ring = &sc->txq[desc->qid & 0x3];
        !          1323:        struct wpi_tx_data *data = &ring->data[desc->idx];
        !          1324:        struct wpi_tx_stat *stat = (struct wpi_tx_stat *)(desc + 1);
        !          1325:        struct wpi_node *wn = (struct wpi_node *)data->ni;
        !          1326:
        !          1327:        DPRINTFN(4, ("tx done: qid=%d idx=%d retries=%d nkill=%d rate=%x "
        !          1328:            "duration=%d status=%x\n", desc->qid, desc->idx, stat->ntries,
        !          1329:            stat->nkill, stat->rate, letoh32(stat->duration),
        !          1330:            letoh32(stat->status)));
        !          1331:
        !          1332:        /*
        !          1333:         * Update rate control statistics for the node.
        !          1334:         * XXX we should not count mgmt frames since they're always sent at
        !          1335:         * the lowest available bit-rate.
        !          1336:         */
        !          1337:        wn->amn.amn_txcnt++;
        !          1338:        if (stat->ntries > 0) {
        !          1339:                DPRINTFN(3, ("tx intr ntries %d\n", stat->ntries));
        !          1340:                wn->amn.amn_retrycnt++;
        !          1341:        }
        !          1342:
        !          1343:        if ((letoh32(stat->status) & 0xff) != 1)
        !          1344:                ifp->if_oerrors++;
        !          1345:        else
        !          1346:                ifp->if_opackets++;
        !          1347:
        !          1348:        bus_dmamap_unload(sc->sc_dmat, data->map);
        !          1349:        m_freem(data->m);
        !          1350:        data->m = NULL;
        !          1351:        ieee80211_release_node(ic, data->ni);
        !          1352:        data->ni = NULL;
        !          1353:
        !          1354:        ring->queued--;
        !          1355:
        !          1356:        sc->sc_tx_timer = 0;
        !          1357:        ifp->if_flags &= ~IFF_OACTIVE;
        !          1358:        (*ifp->if_start)(ifp);
        !          1359: }
        !          1360:
        !          1361: void
        !          1362: wpi_cmd_intr(struct wpi_softc *sc, struct wpi_rx_desc *desc)
        !          1363: {
        !          1364:        struct wpi_tx_ring *ring = &sc->cmdq;
        !          1365:        struct wpi_tx_data *data;
        !          1366:
        !          1367:        if ((desc->qid & 7) != 4)
        !          1368:                return; /* not a command ack */
        !          1369:
        !          1370:        data = &ring->data[desc->idx];
        !          1371:
        !          1372:        /* if the command was mapped in a mbuf, free it */
        !          1373:        if (data->m != NULL) {
        !          1374:                bus_dmamap_unload(sc->sc_dmat, data->map);
        !          1375:                m_freem(data->m);
        !          1376:                data->m = NULL;
        !          1377:        }
        !          1378:
        !          1379:        wakeup(&ring->cmd[desc->idx]);
        !          1380: }
        !          1381:
        !          1382: void
        !          1383: wpi_notif_intr(struct wpi_softc *sc)
        !          1384: {
        !          1385:        struct ieee80211com *ic = &sc->sc_ic;
        !          1386:        struct ifnet *ifp = &ic->ic_if;
        !          1387:        uint32_t hw;
        !          1388:
        !          1389:        hw = letoh32(sc->shared->next);
        !          1390:        while (sc->rxq.cur != hw) {
        !          1391:                struct wpi_rx_data *data = &sc->rxq.data[sc->rxq.cur];
        !          1392:                struct wpi_rx_desc *desc = mtod(data->m, struct wpi_rx_desc *);
        !          1393:
        !          1394:                DPRINTFN(4, ("rx notification qid=%x idx=%d flags=%x type=%d "
        !          1395:                    "len=%d\n", desc->qid, desc->idx, desc->flags, desc->type,
        !          1396:                    letoh32(desc->len)));
        !          1397:
        !          1398:                if (!(desc->qid & 0x80))        /* reply to a command */
        !          1399:                        wpi_cmd_intr(sc, desc);
        !          1400:
        !          1401:                switch (desc->type) {
        !          1402:                case WPI_RX_DONE:
        !          1403:                        /* a 802.11 frame was received */
        !          1404:                        wpi_rx_intr(sc, desc, data);
        !          1405:                        break;
        !          1406:
        !          1407:                case WPI_TX_DONE:
        !          1408:                        /* a 802.11 frame has been transmitted */
        !          1409:                        wpi_tx_intr(sc, desc);
        !          1410:                        break;
        !          1411:
        !          1412:                case WPI_UC_READY:
        !          1413:                {
        !          1414:                        struct wpi_ucode_info *uc =
        !          1415:                            (struct wpi_ucode_info *)(desc + 1);
        !          1416:
        !          1417:                        /* the microcontroller is ready */
        !          1418:                        DPRINTF(("microcode alive notification version %x "
        !          1419:                            "alive %x\n", letoh32(uc->version),
        !          1420:                            letoh32(uc->valid)));
        !          1421:
        !          1422:                        if (letoh32(uc->valid) != 1) {
        !          1423:                                printf("%s: microcontroller initialization "
        !          1424:                                    "failed\n", sc->sc_dev.dv_xname);
        !          1425:                        }
        !          1426:                        break;
        !          1427:                }
        !          1428:                case WPI_STATE_CHANGED:
        !          1429:                {
        !          1430:                        uint32_t *status = (uint32_t *)(desc + 1);
        !          1431:
        !          1432:                        /* enabled/disabled notification */
        !          1433:                        DPRINTF(("state changed to %x\n", letoh32(*status)));
        !          1434:
        !          1435:                        if (letoh32(*status) & 1) {
        !          1436:                                /* the radio button has to be pushed */
        !          1437:                                printf("%s: Radio transmitter is off\n",
        !          1438:                                    sc->sc_dev.dv_xname);
        !          1439:                                /* turn the interface down */
        !          1440:                                ifp->if_flags &= ~IFF_UP;
        !          1441:                                wpi_stop(ifp, 1);
        !          1442:                                return; /* no further processing */
        !          1443:                        }
        !          1444:                        break;
        !          1445:                }
        !          1446:                case WPI_START_SCAN:
        !          1447:                {
        !          1448:                        struct wpi_start_scan *scan =
        !          1449:                            (struct wpi_start_scan *)(desc + 1);
        !          1450:
        !          1451:                        DPRINTFN(2, ("scanning channel %d status %x\n",
        !          1452:                            scan->chan, letoh32(scan->status)));
        !          1453:
        !          1454:                        /* fix current channel */
        !          1455:                        ic->ic_bss->ni_chan = &ic->ic_channels[scan->chan];
        !          1456:                        break;
        !          1457:                }
        !          1458:                case WPI_STOP_SCAN:
        !          1459:                {
        !          1460:                        struct wpi_stop_scan *scan =
        !          1461:                            (struct wpi_stop_scan *)(desc + 1);
        !          1462:
        !          1463:                        DPRINTF(("scan finished nchan=%d status=%d chan=%d\n",
        !          1464:                            scan->nchan, scan->status, scan->chan));
        !          1465:
        !          1466:                        if (scan->status == 1 && scan->chan <= 14) {
        !          1467:                                /*
        !          1468:                                 * We just finished scanning 802.11g channels,
        !          1469:                                 * start scanning 802.11a ones.
        !          1470:                                 */
        !          1471:                                if (wpi_scan(sc, IEEE80211_CHAN_A) == 0)
        !          1472:                                        break;
        !          1473:                        }
        !          1474:                        ieee80211_end_scan(ifp);
        !          1475:                        break;
        !          1476:                }
        !          1477:                }
        !          1478:
        !          1479:                sc->rxq.cur = (sc->rxq.cur + 1) % WPI_RX_RING_COUNT;
        !          1480:        }
        !          1481:
        !          1482:        /* tell the firmware what we have processed */
        !          1483:        hw = (hw == 0) ? WPI_RX_RING_COUNT - 1 : hw - 1;
        !          1484:        WPI_WRITE(sc, WPI_RX_WIDX, hw & ~7);
        !          1485: }
        !          1486:
        !          1487: int
        !          1488: wpi_intr(void *arg)
        !          1489: {
        !          1490:        struct wpi_softc *sc = arg;
        !          1491:        struct ifnet *ifp = &sc->sc_ic.ic_if;
        !          1492:        uint32_t r;
        !          1493:
        !          1494:        r = WPI_READ(sc, WPI_INTR);
        !          1495:        if (r == 0 || r == 0xffffffff)
        !          1496:                return 0;       /* not for us */
        !          1497:
        !          1498:        DPRINTFN(6, ("interrupt reg %x\n", r));
        !          1499:
        !          1500:        /* disable interrupts */
        !          1501:        WPI_WRITE(sc, WPI_MASK, 0);
        !          1502:        /* ack interrupts */
        !          1503:        WPI_WRITE(sc, WPI_INTR, r);
        !          1504:
        !          1505:        if (r & (WPI_SW_ERROR | WPI_HW_ERROR)) {
        !          1506:                /* SYSTEM FAILURE, SYSTEM FAILURE */
        !          1507:                printf("%s: fatal firmware error\n", sc->sc_dev.dv_xname);
        !          1508:                ifp->if_flags &= ~IFF_UP;
        !          1509:                wpi_stop(ifp, 1);
        !          1510:                return 1;
        !          1511:        }
        !          1512:
        !          1513:        if (r & WPI_RX_INTR)
        !          1514:                wpi_notif_intr(sc);
        !          1515:
        !          1516:        if (r & WPI_ALIVE_INTR) /* firmware initialized */
        !          1517:                wakeup(sc);
        !          1518:
        !          1519:        /* re-enable interrupts */
        !          1520:        if (ifp->if_flags & IFF_UP)
        !          1521:                WPI_WRITE(sc, WPI_MASK, WPI_INTR_MASK);
        !          1522:
        !          1523:        return 1;
        !          1524: }
        !          1525:
        !          1526: uint8_t
        !          1527: wpi_plcp_signal(int rate)
        !          1528: {
        !          1529:        switch (rate) {
        !          1530:        /* CCK rates (returned values are device-dependent) */
        !          1531:        case 2:         return 10;
        !          1532:        case 4:         return 20;
        !          1533:        case 11:        return 55;
        !          1534:        case 22:        return 110;
        !          1535:
        !          1536:        /* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
        !          1537:        /* R1-R4, (u)ral is R4-R1 */
        !          1538:        case 12:        return 0xd;
        !          1539:        case 18:        return 0xf;
        !          1540:        case 24:        return 0x5;
        !          1541:        case 36:        return 0x7;
        !          1542:        case 48:        return 0x9;
        !          1543:        case 72:        return 0xb;
        !          1544:        case 96:        return 0x1;
        !          1545:        case 108:       return 0x3;
        !          1546:
        !          1547:        /* unsupported rates (should not get there) */
        !          1548:        default:        return 0;
        !          1549:        }
        !          1550: }
        !          1551:
        !          1552: /* quickly determine if a given rate is CCK or OFDM */
        !          1553: #define WPI_RATE_IS_OFDM(rate) ((rate) >= 12 && (rate) != 22)
        !          1554:
        !          1555: int
        !          1556: wpi_tx_data(struct wpi_softc *sc, struct mbuf *m0, struct ieee80211_node *ni,
        !          1557:     int ac)
        !          1558: {
        !          1559:        struct ieee80211com *ic = &sc->sc_ic;
        !          1560:        struct wpi_tx_ring *ring = &sc->txq[ac];
        !          1561:        struct wpi_tx_desc *desc;
        !          1562:        struct wpi_tx_data *data;
        !          1563:        struct wpi_tx_cmd *cmd;
        !          1564:        struct wpi_cmd_data *tx;
        !          1565:        struct ieee80211_frame *wh;
        !          1566:        struct mbuf *mnew;
        !          1567:        int i, rate, error, ovhd = 0;
        !          1568:
        !          1569:        desc = &ring->desc[ring->cur];
        !          1570:        data = &ring->data[ring->cur];
        !          1571:
        !          1572:        wh = mtod(m0, struct ieee80211_frame *);
        !          1573:
        !          1574:        /* pickup a rate */
        !          1575:        if (IEEE80211_IS_MULTICAST(wh->i_addr1) ||
        !          1576:            ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
        !          1577:             IEEE80211_FC0_TYPE_MGT)) {
        !          1578:                /* mgmt/multicast frames are sent at the lowest avail. rate */
        !          1579:                rate = ni->ni_rates.rs_rates[0];
        !          1580:        } else if (ic->ic_fixed_rate != -1) {
        !          1581:                rate = ic->ic_sup_rates[ic->ic_curmode].
        !          1582:                    rs_rates[ic->ic_fixed_rate];
        !          1583:        } else
        !          1584:                rate = ni->ni_rates.rs_rates[ni->ni_txrate];
        !          1585:        rate &= IEEE80211_RATE_VAL;
        !          1586:
        !          1587: #if NBPFILTER > 0
        !          1588:        if (sc->sc_drvbpf != NULL) {
        !          1589:                struct mbuf mb;
        !          1590:                struct wpi_tx_radiotap_header *tap = &sc->sc_txtap;
        !          1591:
        !          1592:                tap->wt_flags = 0;
        !          1593:                tap->wt_chan_freq = htole16(ni->ni_chan->ic_freq);
        !          1594:                tap->wt_chan_flags = htole16(ni->ni_chan->ic_flags);
        !          1595:                tap->wt_rate = rate;
        !          1596:                tap->wt_hwqueue = ac;
        !          1597:                if (wh->i_fc[1] & IEEE80211_FC1_WEP)
        !          1598:                        tap->wt_flags |= IEEE80211_RADIOTAP_F_WEP;
        !          1599:
        !          1600:                mb.m_data = (caddr_t)tap;
        !          1601:                mb.m_len = sc->sc_txtap_len;
        !          1602:                mb.m_next = m0;
        !          1603:                mb.m_nextpkt = NULL;
        !          1604:                mb.m_type = 0;
        !          1605:                mb.m_flags = 0;
        !          1606:                bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_OUT);
        !          1607:        }
        !          1608: #endif
        !          1609:
        !          1610:        cmd = &ring->cmd[ring->cur];
        !          1611:        cmd->code = WPI_CMD_TX_DATA;
        !          1612:        cmd->flags = 0;
        !          1613:        cmd->qid = ring->qid;
        !          1614:        cmd->idx = ring->cur;
        !          1615:
        !          1616:        tx = (struct wpi_cmd_data *)cmd->data;
        !          1617:        /* no need to zero tx, all fields are reinitialized here */
        !          1618:        tx->flags = 0;
        !          1619:
        !          1620:        if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
        !          1621:                const struct ieee80211_key *key =
        !          1622:                    &ic->ic_nw_keys[ic->ic_wep_txkey];
        !          1623:                if (key->k_cipher == IEEE80211_CIPHER_WEP40)
        !          1624:                        tx->security = WPI_CIPHER_WEP40;
        !          1625:                else
        !          1626:                        tx->security = WPI_CIPHER_WEP104;
        !          1627:                tx->security |= ic->ic_wep_txkey << 6;
        !          1628:                memcpy(&tx->key[3], key->k_key, key->k_len);
        !          1629:                /* compute crypto overhead */
        !          1630:                ovhd = IEEE80211_WEP_TOTLEN;
        !          1631:        } else
        !          1632:                tx->security = 0;
        !          1633:
        !          1634:        if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
        !          1635:                tx->id = WPI_ID_BSS;
        !          1636:                tx->flags |= htole32(WPI_TX_NEED_ACK);
        !          1637:        } else
        !          1638:                tx->id = WPI_ID_BROADCAST;
        !          1639:
        !          1640:        /* check if RTS/CTS or CTS-to-self protection must be used */
        !          1641:        if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
        !          1642:                /* multicast frames are not sent at OFDM rates in 802.11b/g */
        !          1643:                if (m0->m_pkthdr.len + ovhd + IEEE80211_CRC_LEN >
        !          1644:                    ic->ic_rtsthreshold) {
        !          1645:                        tx->flags |= htole32(WPI_TX_NEED_RTS |
        !          1646:                            WPI_TX_FULL_TXOP);
        !          1647:                } else if ((ic->ic_flags & IEEE80211_F_USEPROT) &&
        !          1648:                    WPI_RATE_IS_OFDM(rate)) {
        !          1649:                        if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) {
        !          1650:                                tx->flags |= htole32(WPI_TX_NEED_CTS |
        !          1651:                                    WPI_TX_FULL_TXOP);
        !          1652:                        } else if (ic->ic_protmode == IEEE80211_PROT_RTSCTS) {
        !          1653:                                tx->flags |= htole32(WPI_TX_NEED_RTS |
        !          1654:                                    WPI_TX_FULL_TXOP);
        !          1655:                        }
        !          1656:                }
        !          1657:        }
        !          1658:
        !          1659:        tx->flags |= htole32(WPI_TX_AUTO_SEQ);
        !          1660:
        !          1661:        if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
        !          1662:            IEEE80211_FC0_TYPE_MGT) {
        !          1663:                uint8_t subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
        !          1664:
        !          1665:                /* tell h/w to set timestamp in probe responses */
        !          1666:                if (subtype == IEEE80211_FC0_SUBTYPE_PROBE_RESP)
        !          1667:                        tx->flags |= htole32(WPI_TX_INSERT_TSTAMP);
        !          1668:
        !          1669:                if (subtype == IEEE80211_FC0_SUBTYPE_ASSOC_REQ ||
        !          1670:                    subtype == IEEE80211_FC0_SUBTYPE_REASSOC_REQ)
        !          1671:                        tx->timeout = htole16(3);
        !          1672:                else
        !          1673:                        tx->timeout = htole16(2);
        !          1674:        } else
        !          1675:                tx->timeout = htole16(0);
        !          1676:
        !          1677:        tx->rate = wpi_plcp_signal(rate);
        !          1678:
        !          1679:        /* be very persistant at sending frames out */
        !          1680:        tx->rts_ntries = 7;
        !          1681:        tx->data_ntries = 15;
        !          1682:
        !          1683:        tx->ofdm_mask = 0xff;
        !          1684:        tx->cck_mask = 0x0f;
        !          1685:        tx->lifetime = htole32(WPI_LIFETIME_INFINITE);
        !          1686:
        !          1687:        tx->len = htole16(m0->m_pkthdr.len);
        !          1688:
        !          1689:        /* save and trim IEEE802.11 header */
        !          1690:        m_copydata(m0, 0, sizeof (struct ieee80211_frame), (caddr_t)&tx->wh);
        !          1691:        m_adj(m0, sizeof (struct ieee80211_frame));
        !          1692:
        !          1693:        error = bus_dmamap_load_mbuf(sc->sc_dmat, data->map, m0,
        !          1694:            BUS_DMA_NOWAIT);
        !          1695:        if (error != 0 && error != EFBIG) {
        !          1696:                printf("%s: could not map mbuf (error %d)\n",
        !          1697:                    sc->sc_dev.dv_xname, error);
        !          1698:                m_freem(m0);
        !          1699:                return error;
        !          1700:        }
        !          1701:        if (error != 0) {
        !          1702:                /* too many fragments, linearize */
        !          1703:
        !          1704:                MGETHDR(mnew, M_DONTWAIT, MT_DATA);
        !          1705:                if (mnew == NULL) {
        !          1706:                        m_freem(m0);
        !          1707:                        return ENOMEM;
        !          1708:                }
        !          1709:                M_DUP_PKTHDR(mnew, m0);
        !          1710:                if (m0->m_pkthdr.len > MHLEN) {
        !          1711:                        MCLGET(mnew, M_DONTWAIT);
        !          1712:                        if (!(mnew->m_flags & M_EXT)) {
        !          1713:                                m_freem(m0);
        !          1714:                                m_freem(mnew);
        !          1715:                                return ENOMEM;
        !          1716:                        }
        !          1717:                }
        !          1718:
        !          1719:                m_copydata(m0, 0, m0->m_pkthdr.len, mtod(mnew, caddr_t));
        !          1720:                m_freem(m0);
        !          1721:                mnew->m_len = mnew->m_pkthdr.len;
        !          1722:                m0 = mnew;
        !          1723:
        !          1724:                error = bus_dmamap_load_mbuf(sc->sc_dmat, data->map, m0,
        !          1725:                    BUS_DMA_NOWAIT);
        !          1726:                if (error != 0) {
        !          1727:                        printf("%s: could not map mbuf (error %d)\n",
        !          1728:                            sc->sc_dev.dv_xname, error);
        !          1729:                        m_freem(m0);
        !          1730:                        return error;
        !          1731:                }
        !          1732:        }
        !          1733:
        !          1734:        data->m = m0;
        !          1735:        data->ni = ni;
        !          1736:
        !          1737:        DPRINTFN(4, ("sending data: qid=%d idx=%d len=%d nsegs=%d\n",
        !          1738:            ring->qid, ring->cur, m0->m_pkthdr.len, data->map->dm_nsegs));
        !          1739:
        !          1740:        /* first scatter/gather segment is used by the tx data command */
        !          1741:        desc->flags = htole32(WPI_PAD32(m0->m_pkthdr.len) << 28 |
        !          1742:            (1 + data->map->dm_nsegs) << 24);
        !          1743:        desc->segs[0].addr = htole32(ring->cmd_dma.paddr +
        !          1744:            ring->cur * sizeof (struct wpi_tx_cmd));
        !          1745:        desc->segs[0].len  = htole32(4 + sizeof (struct wpi_cmd_data));
        !          1746:        for (i = 1; i <= data->map->dm_nsegs; i++) {
        !          1747:                desc->segs[i].addr =
        !          1748:                    htole32(data->map->dm_segs[i - 1].ds_addr);
        !          1749:                desc->segs[i].len  =
        !          1750:                    htole32(data->map->dm_segs[i - 1].ds_len);
        !          1751:        }
        !          1752:
        !          1753:        ring->queued++;
        !          1754:
        !          1755:        /* kick ring */
        !          1756:        ring->cur = (ring->cur + 1) % WPI_TX_RING_COUNT;
        !          1757:        WPI_WRITE(sc, WPI_TX_WIDX, ring->qid << 8 | ring->cur);
        !          1758:
        !          1759:        return 0;
        !          1760: }
        !          1761:
        !          1762: void
        !          1763: wpi_start(struct ifnet *ifp)
        !          1764: {
        !          1765:        struct wpi_softc *sc = ifp->if_softc;
        !          1766:        struct ieee80211com *ic = &sc->sc_ic;
        !          1767:        struct ieee80211_node *ni;
        !          1768:        struct mbuf *m0;
        !          1769:
        !          1770:        /*
        !          1771:         * net80211 may still try to send management frames even if the
        !          1772:         * IFF_RUNNING flag is not set...
        !          1773:         */
        !          1774:        if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
        !          1775:                return;
        !          1776:
        !          1777:        for (;;) {
        !          1778:                IF_POLL(&ic->ic_mgtq, m0);
        !          1779:                if (m0 != NULL) {
        !          1780:                        /* management frames go into ring 0 */
        !          1781:                        if (sc->txq[0].queued >= sc->txq[0].count - 8) {
        !          1782:                                ifp->if_flags |= IFF_OACTIVE;
        !          1783:                                break;
        !          1784:                        }
        !          1785:                        IF_DEQUEUE(&ic->ic_mgtq, m0);
        !          1786:
        !          1787:                        ni = (struct ieee80211_node *)m0->m_pkthdr.rcvif;
        !          1788:                        m0->m_pkthdr.rcvif = NULL;
        !          1789: #if NBPFILTER > 0
        !          1790:                        if (ic->ic_rawbpf != NULL)
        !          1791:                                bpf_mtap(ic->ic_rawbpf, m0, BPF_DIRECTION_OUT);
        !          1792: #endif
        !          1793:                        if (wpi_tx_data(sc, m0, ni, 0) != 0)
        !          1794:                                break;
        !          1795:
        !          1796:                } else {
        !          1797:                        if (ic->ic_state != IEEE80211_S_RUN)
        !          1798:                                break;
        !          1799:                        IFQ_POLL(&ifp->if_snd, m0);
        !          1800:                        if (m0 == NULL)
        !          1801:                                break;
        !          1802:                        if (sc->txq[0].queued >= sc->txq[0].count - 8) {
        !          1803:                                /* there is no place left in this ring */
        !          1804:                                ifp->if_flags |= IFF_OACTIVE;
        !          1805:                                break;
        !          1806:                        }
        !          1807:                        IFQ_DEQUEUE(&ifp->if_snd, m0);
        !          1808: #if NBPFILTER > 0
        !          1809:                        if (ifp->if_bpf != NULL)
        !          1810:                                bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT);
        !          1811: #endif
        !          1812:                        m0 = ieee80211_encap(ifp, m0, &ni);
        !          1813:                        if (m0 == NULL)
        !          1814:                                continue;
        !          1815: #if NBPFILTER > 0
        !          1816:                        if (ic->ic_rawbpf != NULL)
        !          1817:                                bpf_mtap(ic->ic_rawbpf, m0, BPF_DIRECTION_OUT);
        !          1818: #endif
        !          1819:                        if (wpi_tx_data(sc, m0, ni, 0) != 0) {
        !          1820:                                if (ni != NULL)
        !          1821:                                        ieee80211_release_node(ic, ni);
        !          1822:                                ifp->if_oerrors++;
        !          1823:                                break;
        !          1824:                        }
        !          1825:                }
        !          1826:
        !          1827:                sc->sc_tx_timer = 5;
        !          1828:                ifp->if_timer = 1;
        !          1829:        }
        !          1830: }
        !          1831:
        !          1832: void
        !          1833: wpi_watchdog(struct ifnet *ifp)
        !          1834: {
        !          1835:        struct wpi_softc *sc = ifp->if_softc;
        !          1836:
        !          1837:        ifp->if_timer = 0;
        !          1838:
        !          1839:        if (sc->sc_tx_timer > 0) {
        !          1840:                if (--sc->sc_tx_timer == 0) {
        !          1841:                        printf("%s: device timeout\n", sc->sc_dev.dv_xname);
        !          1842:                        ifp->if_flags &= ~IFF_UP;
        !          1843:                        wpi_stop(ifp, 1);
        !          1844:                        ifp->if_oerrors++;
        !          1845:                        return;
        !          1846:                }
        !          1847:                ifp->if_timer = 1;
        !          1848:        }
        !          1849:
        !          1850:        ieee80211_watchdog(ifp);
        !          1851: }
        !          1852:
        !          1853: int
        !          1854: wpi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
        !          1855: {
        !          1856:        struct wpi_softc *sc = ifp->if_softc;
        !          1857:        struct ieee80211com *ic = &sc->sc_ic;
        !          1858:        struct ifaddr *ifa;
        !          1859:        struct ifreq *ifr;
        !          1860:        int s, error = 0;
        !          1861:
        !          1862:        s = splnet();
        !          1863:
        !          1864:        switch (cmd) {
        !          1865:        case SIOCSIFADDR:
        !          1866:                ifa = (struct ifaddr *)data;
        !          1867:                ifp->if_flags |= IFF_UP;
        !          1868: #ifdef INET
        !          1869:                if (ifa->ifa_addr->sa_family == AF_INET)
        !          1870:                        arp_ifinit(&ic->ic_ac, ifa);
        !          1871: #endif
        !          1872:                /* FALLTHROUGH */
        !          1873:        case SIOCSIFFLAGS:
        !          1874:                if (ifp->if_flags & IFF_UP) {
        !          1875:                        if (!(ifp->if_flags & IFF_RUNNING))
        !          1876:                                wpi_init(ifp);
        !          1877:                } else {
        !          1878:                        if (ifp->if_flags & IFF_RUNNING)
        !          1879:                                wpi_stop(ifp, 1);
        !          1880:                }
        !          1881:                break;
        !          1882:
        !          1883:        case SIOCADDMULTI:
        !          1884:        case SIOCDELMULTI:
        !          1885:                ifr = (struct ifreq *)data;
        !          1886:                error = (cmd == SIOCADDMULTI) ?
        !          1887:                    ether_addmulti(ifr, &ic->ic_ac) :
        !          1888:                    ether_delmulti(ifr, &ic->ic_ac);
        !          1889:
        !          1890:                if (error == ENETRESET)
        !          1891:                        error = 0;
        !          1892:                break;
        !          1893:
        !          1894:        default:
        !          1895:                error = ieee80211_ioctl(ifp, cmd, data);
        !          1896:        }
        !          1897:
        !          1898:        if (error == ENETRESET) {
        !          1899:                if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
        !          1900:                    (IFF_UP | IFF_RUNNING))
        !          1901:                        wpi_init(ifp);
        !          1902:                error = 0;
        !          1903:        }
        !          1904:
        !          1905:        splx(s);
        !          1906:        return error;
        !          1907: }
        !          1908:
        !          1909: void
        !          1910: wpi_read_eeprom(struct wpi_softc *sc)
        !          1911: {
        !          1912:        struct ieee80211com *ic = &sc->sc_ic;
        !          1913:        char domain[4];
        !          1914:        int i;
        !          1915:
        !          1916:        wpi_read_prom_data(sc, WPI_EEPROM_CAPABILITIES, &sc->cap, 1);
        !          1917:        wpi_read_prom_data(sc, WPI_EEPROM_REVISION, &sc->rev, 2);
        !          1918:        wpi_read_prom_data(sc, WPI_EEPROM_TYPE, &sc->type, 1);
        !          1919:
        !          1920:        DPRINTF(("cap=%x rev=%x type=%x\n", sc->cap, letoh16(sc->rev),
        !          1921:            sc->type));
        !          1922:
        !          1923:        /* read and print regulatory domain */
        !          1924:        wpi_read_prom_data(sc, WPI_EEPROM_DOMAIN, domain, 4);
        !          1925:        printf(", %.4s", domain);
        !          1926:
        !          1927:        /* read and print MAC address */
        !          1928:        wpi_read_prom_data(sc, WPI_EEPROM_MAC, ic->ic_myaddr, 6);
        !          1929:        printf(", address %s\n", ether_sprintf(ic->ic_myaddr));
        !          1930:
        !          1931:        /* read the list of authorized channels */
        !          1932:        for (i = 0; i < WPI_CHAN_BANDS_COUNT; i++)
        !          1933:                wpi_read_eeprom_channels(sc, i);
        !          1934:
        !          1935:        /* read the list of power groups */
        !          1936:        for (i = 0; i < WPI_POWER_GROUPS_COUNT; i++)
        !          1937:                wpi_read_eeprom_group(sc, i);
        !          1938: }
        !          1939:
        !          1940: void
        !          1941: wpi_read_eeprom_channels(struct wpi_softc *sc, int n)
        !          1942: {
        !          1943:        struct ieee80211com *ic = &sc->sc_ic;
        !          1944:        const struct wpi_chan_band *band = &wpi_bands[n];
        !          1945:        struct wpi_eeprom_chan channels[WPI_MAX_CHAN_PER_BAND];
        !          1946:        int chan, i;
        !          1947:
        !          1948:        wpi_read_prom_data(sc, band->addr, channels,
        !          1949:            band->nchan * sizeof (struct wpi_eeprom_chan));
        !          1950:
        !          1951:        for (i = 0; i < band->nchan; i++) {
        !          1952:                if (!(channels[i].flags & WPI_EEPROM_CHAN_VALID))
        !          1953:                        continue;
        !          1954:
        !          1955:                chan = band->chan[i];
        !          1956:
        !          1957:                if (n == 0) {   /* 2GHz band */
        !          1958:                        ic->ic_channels[chan].ic_freq =
        !          1959:                            ieee80211_ieee2mhz(chan, IEEE80211_CHAN_2GHZ);
        !          1960:                        ic->ic_channels[chan].ic_flags =
        !          1961:                            IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM |
        !          1962:                            IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ;
        !          1963:
        !          1964:                } else {        /* 5GHz band */
        !          1965:                        /*
        !          1966:                         * Some 3945ABG adapters support channels 7, 8, 11
        !          1967:                         * and 12 in the 2GHz *and* 5GHz bands.
        !          1968:                         * Because of limitations in our net80211(9) stack,
        !          1969:                         * we can't support these channels in 5GHz band.
        !          1970:                         */
        !          1971:                        if (chan <= 14)
        !          1972:                                continue;
        !          1973:
        !          1974:                        ic->ic_channels[chan].ic_freq =
        !          1975:                            ieee80211_ieee2mhz(chan, IEEE80211_CHAN_5GHZ);
        !          1976:                        ic->ic_channels[chan].ic_flags = IEEE80211_CHAN_A;
        !          1977:                }
        !          1978:
        !          1979:                /* is active scan allowed on this channel? */
        !          1980:                if (!(channels[i].flags & WPI_EEPROM_CHAN_ACTIVE)) {
        !          1981:                        ic->ic_channels[chan].ic_flags |=
        !          1982:                            IEEE80211_CHAN_PASSIVE;
        !          1983:                }
        !          1984:
        !          1985:                /* save maximum allowed power for this channel */
        !          1986:                sc->maxpwr[chan] = channels[i].maxpwr;
        !          1987:
        !          1988:                DPRINTF(("adding chan %d flags=0x%x maxpwr=%d\n",
        !          1989:                    chan, channels[i].flags, sc->maxpwr[chan]));
        !          1990:        }
        !          1991: }
        !          1992:
        !          1993: void
        !          1994: wpi_read_eeprom_group(struct wpi_softc *sc, int n)
        !          1995: {
        !          1996:        struct wpi_power_group *group = &sc->groups[n];
        !          1997:        struct wpi_eeprom_group rgroup;
        !          1998:        int i;
        !          1999:
        !          2000:        wpi_read_prom_data(sc, WPI_EEPROM_POWER_GRP + n * 32, &rgroup,
        !          2001:            sizeof rgroup);
        !          2002:
        !          2003:        /* save power group information */
        !          2004:        group->chan   = rgroup.chan;
        !          2005:        group->maxpwr = rgroup.maxpwr;
        !          2006:        /* temperature at which the samples were taken */
        !          2007:        group->temp   = (int16_t)letoh16(rgroup.temp);
        !          2008:
        !          2009:        DPRINTF(("power group %d: chan=%d maxpwr=%d temp=%d\n", n,
        !          2010:            group->chan, group->maxpwr, group->temp));
        !          2011:
        !          2012:        for (i = 0; i < WPI_SAMPLES_COUNT; i++) {
        !          2013:                group->samples[i].index = rgroup.samples[i].index;
        !          2014:                group->samples[i].power = rgroup.samples[i].power;
        !          2015:
        !          2016:                DPRINTF(("\tsample %d: index=%d power=%d\n", i,
        !          2017:                    group->samples[i].index, group->samples[i].power));
        !          2018:        }
        !          2019: }
        !          2020:
        !          2021: /*
        !          2022:  * Send a command to the firmware.
        !          2023:  */
        !          2024: int
        !          2025: wpi_cmd(struct wpi_softc *sc, int code, const void *buf, int size, int async)
        !          2026: {
        !          2027:        struct wpi_tx_ring *ring = &sc->cmdq;
        !          2028:        struct wpi_tx_desc *desc;
        !          2029:        struct wpi_tx_cmd *cmd;
        !          2030:
        !          2031:        KASSERT(size <= sizeof cmd->data);
        !          2032:
        !          2033:        desc = &ring->desc[ring->cur];
        !          2034:        cmd = &ring->cmd[ring->cur];
        !          2035:
        !          2036:        cmd->code = code;
        !          2037:        cmd->flags = 0;
        !          2038:        cmd->qid = ring->qid;
        !          2039:        cmd->idx = ring->cur;
        !          2040:        memcpy(cmd->data, buf, size);
        !          2041:
        !          2042:        desc->flags = htole32(WPI_PAD32(size) << 28 | 1 << 24);
        !          2043:        desc->segs[0].addr = htole32(ring->cmd_dma.paddr +
        !          2044:            ring->cur * sizeof (struct wpi_tx_cmd));
        !          2045:        desc->segs[0].len  = htole32(4 + size);
        !          2046:
        !          2047:        /* kick cmd ring */
        !          2048:        ring->cur = (ring->cur + 1) % WPI_CMD_RING_COUNT;
        !          2049:        WPI_WRITE(sc, WPI_TX_WIDX, ring->qid << 8 | ring->cur);
        !          2050:
        !          2051:        return async ? 0 : tsleep(cmd, PCATCH, "wpicmd", hz);
        !          2052: }
        !          2053:
        !          2054: /*
        !          2055:  * Configure h/w multi-rate retries.
        !          2056:  */
        !          2057: int
        !          2058: wpi_mrr_setup(struct wpi_softc *sc)
        !          2059: {
        !          2060:        struct ieee80211com *ic = &sc->sc_ic;
        !          2061:        struct wpi_mrr_setup mrr;
        !          2062:        int i, error;
        !          2063:
        !          2064:        /* CCK rates (not used with 802.11a) */
        !          2065:        for (i = WPI_CCK1; i <= WPI_CCK11; i++) {
        !          2066:                mrr.rates[i].flags = 0;
        !          2067:                mrr.rates[i].plcp = wpi_ridx_to_plcp[i];
        !          2068:                /* fallback to the immediate lower CCK rate (if any) */
        !          2069:                mrr.rates[i].next = (i == WPI_CCK1) ? WPI_CCK1 : i - 1;
        !          2070:                /* try one time at this rate before falling back to "next" */
        !          2071:                mrr.rates[i].ntries = 1;
        !          2072:        }
        !          2073:
        !          2074:        /* OFDM rates (not used with 802.11b) */
        !          2075:        for (i = WPI_OFDM6; i <= WPI_OFDM54; i++) {
        !          2076:                mrr.rates[i].flags = 0;
        !          2077:                mrr.rates[i].plcp = wpi_ridx_to_plcp[i];
        !          2078:                /* fallback to the immediate lower rate (if any) */
        !          2079:                /* we allow fallback from OFDM/6 to CCK/2 in 11b/g mode */
        !          2080:                mrr.rates[i].next = (i == WPI_OFDM6) ?
        !          2081:                    ((ic->ic_curmode == IEEE80211_MODE_11A) ?
        !          2082:                        WPI_OFDM6 : WPI_CCK2) :
        !          2083:                    i - 1;
        !          2084:                /* try one time at this rate before falling back to "next" */
        !          2085:                mrr.rates[i].ntries = 1;
        !          2086:        }
        !          2087:
        !          2088:        /* setup MRR for control frames */
        !          2089:        mrr.which = htole32(WPI_MRR_CTL);
        !          2090:        error = wpi_cmd(sc, WPI_CMD_MRR_SETUP, &mrr, sizeof mrr, 0);
        !          2091:        if (error != 0) {
        !          2092:                printf("%s: could not setup MRR for control frames\n",
        !          2093:                    sc->sc_dev.dv_xname);
        !          2094:                return error;
        !          2095:        }
        !          2096:
        !          2097:        /* setup MRR for data frames */
        !          2098:        mrr.which = htole32(WPI_MRR_DATA);
        !          2099:        error = wpi_cmd(sc, WPI_CMD_MRR_SETUP, &mrr, sizeof mrr, 0);
        !          2100:        if (error != 0) {
        !          2101:                printf("%s: could not setup MRR for data frames\n",
        !          2102:                    sc->sc_dev.dv_xname);
        !          2103:                return error;
        !          2104:        }
        !          2105:
        !          2106:        return 0;
        !          2107: }
        !          2108:
        !          2109: void
        !          2110: wpi_set_led(struct wpi_softc *sc, uint8_t which, uint8_t off, uint8_t on)
        !          2111: {
        !          2112:        struct wpi_cmd_led led;
        !          2113:
        !          2114:        led.which = which;
        !          2115:        led.unit = htole32(100000);     /* on/off in unit of 100ms */
        !          2116:        led.off = off;
        !          2117:        led.on = on;
        !          2118:
        !          2119:        (void)wpi_cmd(sc, WPI_CMD_SET_LED, &led, sizeof led, 1);
        !          2120: }
        !          2121:
        !          2122: void
        !          2123: wpi_enable_tsf(struct wpi_softc *sc, struct ieee80211_node *ni)
        !          2124: {
        !          2125:        struct wpi_cmd_tsf tsf;
        !          2126:        uint64_t val, mod;
        !          2127:
        !          2128:        memset(&tsf, 0, sizeof tsf);
        !          2129:        memcpy(&tsf.tstamp, ni->ni_tstamp, sizeof (uint64_t));
        !          2130:        tsf.bintval = htole16(ni->ni_intval);
        !          2131:        tsf.lintval = htole16(10);
        !          2132:
        !          2133:        /* compute remaining time until next beacon */
        !          2134:        val = (uint64_t)ni->ni_intval * 1024;   /* msecs -> usecs */
        !          2135:        mod = letoh64(tsf.tstamp) % val;
        !          2136:        tsf.binitval = htole32((uint32_t)(val - mod));
        !          2137:
        !          2138:        DPRINTF(("TSF bintval=%u tstamp=%llu, init=%u\n",
        !          2139:            ni->ni_intval, letoh64(tsf.tstamp), (uint32_t)(val - mod)));
        !          2140:
        !          2141:        if (wpi_cmd(sc, WPI_CMD_TSF, &tsf, sizeof tsf, 1) != 0)
        !          2142:                printf("%s: could not enable TSF\n", sc->sc_dev.dv_xname);
        !          2143: }
        !          2144:
        !          2145: /*
        !          2146:  * Update Tx power to match what is defined for channel `c'.
        !          2147:  */
        !          2148: int
        !          2149: wpi_set_txpower(struct wpi_softc *sc, struct ieee80211_channel *c, int async)
        !          2150: {
        !          2151:        struct ieee80211com *ic = &sc->sc_ic;
        !          2152:        struct wpi_power_group *group;
        !          2153:        struct wpi_cmd_txpower txpower;
        !          2154:        u_int chan;
        !          2155:        int i;
        !          2156:
        !          2157:        /* get channel number */
        !          2158:        chan = ieee80211_chan2ieee(ic, c);
        !          2159:
        !          2160:        /* find the power group to which this channel belongs */
        !          2161:        if (IEEE80211_IS_CHAN_5GHZ(c)) {
        !          2162:                for (group = &sc->groups[1]; group < &sc->groups[4]; group++)
        !          2163:                        if (chan <= group->chan)
        !          2164:                                break;
        !          2165:        } else
        !          2166:                group = &sc->groups[0];
        !          2167:
        !          2168:        memset(&txpower, 0, sizeof txpower);
        !          2169:        txpower.band = IEEE80211_IS_CHAN_5GHZ(c) ? 0 : 1;
        !          2170:        txpower.chan = htole16(chan);
        !          2171:
        !          2172:        /* set Tx power for all OFDM and CCK rates */
        !          2173:        for (i = 0; i <= 11 ; i++) {
        !          2174:                /* retrieve Tx power for this channel/rate combination */
        !          2175:                int idx = wpi_get_power_index(sc, group, c,
        !          2176:                    wpi_ridx_to_rate[i]);
        !          2177:
        !          2178:                txpower.rates[i].plcp = wpi_ridx_to_plcp[i];
        !          2179:
        !          2180:                if (IEEE80211_IS_CHAN_5GHZ(c)) {
        !          2181:                        txpower.rates[i].rf_gain = wpi_rf_gain_5ghz[idx];
        !          2182:                        txpower.rates[i].dsp_gain = wpi_dsp_gain_5ghz[idx];
        !          2183:                } else {
        !          2184:                        txpower.rates[i].rf_gain = wpi_rf_gain_2ghz[idx];
        !          2185:                        txpower.rates[i].dsp_gain = wpi_dsp_gain_2ghz[idx];
        !          2186:                }
        !          2187:                DPRINTF(("chan %d/rate %d: power index %d\n", chan,
        !          2188:                    wpi_ridx_to_rate[i], idx));
        !          2189:        }
        !          2190:
        !          2191:        return wpi_cmd(sc, WPI_CMD_TXPOWER, &txpower, sizeof txpower, async);
        !          2192: }
        !          2193:
        !          2194: /*
        !          2195:  * Determine Tx power index for a given channel/rate combination.
        !          2196:  * This takes into account the regulatory information from EEPROM and the
        !          2197:  * current temperature.
        !          2198:  */
        !          2199: int
        !          2200: wpi_get_power_index(struct wpi_softc *sc, struct wpi_power_group *group,
        !          2201:     struct ieee80211_channel *c, int rate)
        !          2202: {
        !          2203: /* fixed-point arithmetic division using a n-bit fractional part */
        !          2204: #define fdivround(a, b, n)     \
        !          2205:        ((((1 << n) * (a)) / (b) + (1 << n) / 2) / (1 << n))
        !          2206:
        !          2207: /* linear interpolation */
        !          2208: #define interpolate(x, x1, y1, x2, y2, n)      \
        !          2209:        ((y1) + fdivround(((x) - (x1)) * ((y2) - (y1)), (x2) - (x1), n))
        !          2210:
        !          2211:        struct ieee80211com *ic = &sc->sc_ic;
        !          2212:        struct wpi_power_sample *sample;
        !          2213:        int pwr, idx;
        !          2214:        u_int chan;
        !          2215:
        !          2216:        /* get channel number */
        !          2217:        chan = ieee80211_chan2ieee(ic, c);
        !          2218:
        !          2219:        /* default power is group's maximum power - 3dB */
        !          2220:        pwr = group->maxpwr / 2;
        !          2221:
        !          2222:        /* decrease power for highest OFDM rates to reduce distortion */
        !          2223:        switch (rate) {
        !          2224:        case 72:        /* 36Mb/s */
        !          2225:                pwr -= IEEE80211_IS_CHAN_2GHZ(c) ? 0 :  5;
        !          2226:                break;
        !          2227:        case 96:        /* 48Mb/s */
        !          2228:                pwr -= IEEE80211_IS_CHAN_2GHZ(c) ? 7 : 10;
        !          2229:                break;
        !          2230:        case 108:       /* 54Mb/s */
        !          2231:                pwr -= IEEE80211_IS_CHAN_2GHZ(c) ? 9 : 12;
        !          2232:                break;
        !          2233:        }
        !          2234:
        !          2235:        /* never exceed channel's maximum allowed Tx power */
        !          2236:        pwr = min(pwr, sc->maxpwr[chan]);
        !          2237:
        !          2238:        /* retrieve power index into gain tables from samples */
        !          2239:        for (sample = group->samples; sample < &group->samples[3]; sample++)
        !          2240:                if (pwr > sample[1].power)
        !          2241:                        break;
        !          2242:        /* fixed-point linear interpolation using a 19-bit fractional part */
        !          2243:        idx = interpolate(pwr, sample[0].power, sample[0].index,
        !          2244:            sample[1].power, sample[1].index, 19);
        !          2245:
        !          2246:        /*-
        !          2247:         * Adjust power index based on current temperature:
        !          2248:         * - if cooler than factory-calibrated: decrease output power
        !          2249:         * - if warmer than factory-calibrated: increase output power
        !          2250:         */
        !          2251:        idx -= (sc->temp - group->temp) * 11 / 100;
        !          2252:
        !          2253:        /* decrease power for CCK rates (-5dB) */
        !          2254:        if (!WPI_RATE_IS_OFDM(rate))
        !          2255:                idx += 10;
        !          2256:
        !          2257:        /* keep power index in a valid range */
        !          2258:        if (idx < 0)
        !          2259:                return 0;
        !          2260:        if (idx > WPI_MAX_PWR_INDEX)
        !          2261:                return WPI_MAX_PWR_INDEX;
        !          2262:        return idx;
        !          2263:
        !          2264: #undef interpolate
        !          2265: #undef fdivround
        !          2266: }
        !          2267:
        !          2268: /*
        !          2269:  * Build a beacon frame that the firmware will broadcast periodically in
        !          2270:  * IBSS or HostAP modes.
        !          2271:  */
        !          2272: #ifdef notyet
        !          2273: int
        !          2274: wpi_setup_beacon(struct wpi_softc *sc, struct ieee80211_node *ni)
        !          2275: {
        !          2276:        struct ieee80211com *ic = &sc->sc_ic;
        !          2277:        struct wpi_tx_ring *ring = &sc->cmdq;
        !          2278:        struct wpi_tx_desc *desc;
        !          2279:        struct wpi_tx_data *data;
        !          2280:        struct wpi_tx_cmd *cmd;
        !          2281:        struct wpi_cmd_beacon *bcn;
        !          2282:        struct mbuf *m0;
        !          2283:        int error;
        !          2284:
        !          2285:        desc = &ring->desc[ring->cur];
        !          2286:        data = &ring->data[ring->cur];
        !          2287:
        !          2288:        m0 = ieee80211_beacon_alloc(ic, ni);
        !          2289:        if (m0 == NULL) {
        !          2290:                printf("%s: could not allocate beacon frame\n",
        !          2291:                    sc->sc_dev.dv_xname);
        !          2292:                return ENOMEM;
        !          2293:        }
        !          2294:
        !          2295:        cmd = &ring->cmd[ring->cur];
        !          2296:        cmd->code = WPI_CMD_SET_BEACON;
        !          2297:        cmd->flags = 0;
        !          2298:        cmd->qid = ring->qid;
        !          2299:        cmd->idx = ring->cur;
        !          2300:
        !          2301:        bcn = (struct wpi_cmd_beacon *)cmd->data;
        !          2302:        memset(bcn, 0, sizeof (struct wpi_cmd_beacon));
        !          2303:        bcn->id = WPI_ID_BROADCAST;
        !          2304:        bcn->ofdm_mask = 0xff;
        !          2305:        bcn->cck_mask = 0x0f;
        !          2306:        bcn->lifetime = htole32(WPI_LIFETIME_INFINITE);
        !          2307:        bcn->len = htole16(m0->m_pkthdr.len);
        !          2308:        bcn->rate = (ic->ic_curmode == IEEE80211_MODE_11A) ?
        !          2309:            wpi_plcp_signal(12) : wpi_plcp_signal(2);
        !          2310:        bcn->flags = htole32(WPI_TX_AUTO_SEQ | WPI_TX_INSERT_TSTAMP);
        !          2311:
        !          2312:        /* save and trim IEEE802.11 header */
        !          2313:        m_copydata(m0, 0, sizeof (struct ieee80211_frame), (caddr_t)&bcn->wh);
        !          2314:        m_adj(m0, sizeof (struct ieee80211_frame));
        !          2315:
        !          2316:        /* assume beacon frame is contiguous */
        !          2317:        error = bus_dmamap_load(sc->sc_dmat, data->map, mtod(m0, void *),
        !          2318:            m0->m_pkthdr.len, NULL, BUS_DMA_NOWAIT);
        !          2319:        if (error != 0) {
        !          2320:                printf("%s: could not map beacon\n", sc->sc_dev.dv_xname);
        !          2321:                m_freem(m0);
        !          2322:                return error;
        !          2323:        }
        !          2324:
        !          2325:        data->m = m0;
        !          2326:
        !          2327:        /* first scatter/gather segment is used by the beacon command */
        !          2328:        desc->flags = htole32(WPI_PAD32(m0->m_pkthdr.len) << 28 | 2 << 24);
        !          2329:        desc->segs[0].addr = htole32(ring->cmd_dma.paddr +
        !          2330:            ring->cur * sizeof (struct wpi_tx_cmd));
        !          2331:        desc->segs[0].len  = htole32(4 + sizeof (struct wpi_cmd_beacon));
        !          2332:        desc->segs[1].addr = htole32(data->map->dm_segs[0].ds_addr);
        !          2333:        desc->segs[1].len  = htole32(data->map->dm_segs[0].ds_len);
        !          2334:
        !          2335:        /* kick cmd ring */
        !          2336:        ring->cur = (ring->cur + 1) % WPI_CMD_RING_COUNT;
        !          2337:        WPI_WRITE(sc, WPI_TX_WIDX, ring->qid << 8 | ring->cur);
        !          2338:
        !          2339:        return 0;
        !          2340: }
        !          2341: #endif
        !          2342:
        !          2343: int
        !          2344: wpi_auth(struct wpi_softc *sc)
        !          2345: {
        !          2346:        struct ieee80211com *ic = &sc->sc_ic;
        !          2347:        struct ieee80211_node *ni = ic->ic_bss;
        !          2348:        struct wpi_node_info node;
        !          2349:        int error;
        !          2350:
        !          2351:        /* update adapter's configuration */
        !          2352:        IEEE80211_ADDR_COPY(sc->config.bssid, ni->ni_bssid);
        !          2353:        sc->config.chan = ieee80211_chan2ieee(ic, ni->ni_chan);
        !          2354:        if (IEEE80211_IS_CHAN_2GHZ(ni->ni_chan)) {
        !          2355:                sc->config.flags |= htole32(WPI_CONFIG_AUTO |
        !          2356:                    WPI_CONFIG_24GHZ);
        !          2357:        }
        !          2358:        switch (ic->ic_curmode) {
        !          2359:        case IEEE80211_MODE_11A:
        !          2360:                sc->config.cck_mask  = 0;
        !          2361:                sc->config.ofdm_mask = 0x15;
        !          2362:                break;
        !          2363:        case IEEE80211_MODE_11B:
        !          2364:                sc->config.cck_mask  = 0x03;
        !          2365:                sc->config.ofdm_mask = 0;
        !          2366:                break;
        !          2367:        default:        /* assume 802.11b/g */
        !          2368:                sc->config.cck_mask  = 0x0f;
        !          2369:                sc->config.ofdm_mask = 0x15;
        !          2370:        }
        !          2371:        if (ic->ic_flags & IEEE80211_F_SHSLOT)
        !          2372:                sc->config.flags |= htole32(WPI_CONFIG_SHSLOT);
        !          2373:        if (ic->ic_flags & IEEE80211_F_SHPREAMBLE)
        !          2374:                sc->config.flags |= htole32(WPI_CONFIG_SHPREAMBLE);
        !          2375:        DPRINTF(("config chan %d flags %x cck %x ofdm %x\n", sc->config.chan,
        !          2376:            sc->config.flags, sc->config.cck_mask, sc->config.ofdm_mask));
        !          2377:        error = wpi_cmd(sc, WPI_CMD_CONFIGURE, &sc->config,
        !          2378:            sizeof (struct wpi_config), 1);
        !          2379:        if (error != 0) {
        !          2380:                printf("%s: could not configure\n", sc->sc_dev.dv_xname);
        !          2381:                return error;
        !          2382:        }
        !          2383:
        !          2384:        /* configuration has changed, set Tx power accordingly */
        !          2385:        if ((error = wpi_set_txpower(sc, ni->ni_chan, 1)) != 0) {
        !          2386:                printf("%s: could not set Tx power\n", sc->sc_dev.dv_xname);
        !          2387:                return error;
        !          2388:        }
        !          2389:
        !          2390:        /* add default node */
        !          2391:        memset(&node, 0, sizeof node);
        !          2392:        IEEE80211_ADDR_COPY(node.bssid, ni->ni_bssid);
        !          2393:        node.id = WPI_ID_BSS;
        !          2394:        node.rate = (ic->ic_curmode == IEEE80211_MODE_11A) ?
        !          2395:            wpi_plcp_signal(12) : wpi_plcp_signal(2);
        !          2396:        node.action = htole32(WPI_ACTION_SET_RATE);
        !          2397:        node.antenna = WPI_ANTENNA_BOTH;
        !          2398:        error = wpi_cmd(sc, WPI_CMD_ADD_NODE, &node, sizeof node, 1);
        !          2399:        if (error != 0) {
        !          2400:                printf("%s: could not add BSS node\n", sc->sc_dev.dv_xname);
        !          2401:                return error;
        !          2402:        }
        !          2403:
        !          2404:        return 0;
        !          2405: }
        !          2406:
        !          2407: /*
        !          2408:  * Send a scan request to the firmware.  Since this command is huge, we map it
        !          2409:  * into a mbuf instead of using the pre-allocated set of commands.
        !          2410:  */
        !          2411: int
        !          2412: wpi_scan(struct wpi_softc *sc, uint16_t flags)
        !          2413: {
        !          2414:        struct ieee80211com *ic = &sc->sc_ic;
        !          2415:        struct wpi_tx_ring *ring = &sc->cmdq;
        !          2416:        struct wpi_tx_desc *desc;
        !          2417:        struct wpi_tx_data *data;
        !          2418:        struct wpi_tx_cmd *cmd;
        !          2419:        struct wpi_scan_hdr *hdr;
        !          2420:        struct wpi_scan_chan *chan;
        !          2421:        struct ieee80211_frame *wh;
        !          2422:        struct ieee80211_rateset *rs;
        !          2423:        struct ieee80211_channel *c;
        !          2424:        enum ieee80211_phymode mode;
        !          2425:        uint8_t *frm;
        !          2426:        int pktlen, error;
        !          2427:
        !          2428:        desc = &ring->desc[ring->cur];
        !          2429:        data = &ring->data[ring->cur];
        !          2430:
        !          2431:        MGETHDR(data->m, M_DONTWAIT, MT_DATA);
        !          2432:        if (data->m == NULL) {
        !          2433:                printf("%s: could not allocate mbuf for scan command\n",
        !          2434:                    sc->sc_dev.dv_xname);
        !          2435:                return ENOMEM;
        !          2436:        }
        !          2437:        MCLGET(data->m, M_DONTWAIT);
        !          2438:        if (!(data->m->m_flags & M_EXT)) {
        !          2439:                m_freem(data->m);
        !          2440:                data->m = NULL;
        !          2441:                printf("%s: could not allocate mbuf for scan command\n",
        !          2442:                    sc->sc_dev.dv_xname);
        !          2443:                return ENOMEM;
        !          2444:        }
        !          2445:
        !          2446:        cmd = mtod(data->m, struct wpi_tx_cmd *);
        !          2447:        cmd->code = WPI_CMD_SCAN;
        !          2448:        cmd->flags = 0;
        !          2449:        cmd->qid = ring->qid;
        !          2450:        cmd->idx = ring->cur;
        !          2451:
        !          2452:        hdr = (struct wpi_scan_hdr *)cmd->data;
        !          2453:        memset(hdr, 0, sizeof (struct wpi_scan_hdr));
        !          2454:        hdr->txflags = htole32(WPI_TX_AUTO_SEQ);
        !          2455:        hdr->id = WPI_ID_BROADCAST;
        !          2456:        hdr->lifetime = htole32(WPI_LIFETIME_INFINITE);
        !          2457:        /*
        !          2458:         * Move to the next channel if no packets are received within 5 msecs
        !          2459:         * after sending the probe request (this helps to reduce the duration
        !          2460:         * of active scans).
        !          2461:         */
        !          2462:        hdr->quiet = htole16(5);        /* timeout in milliseconds */
        !          2463:        hdr->plcp_threshold = htole16(1);       /* min # of packets */
        !          2464:
        !          2465:        if (flags & IEEE80211_CHAN_A) {
        !          2466:                hdr->crc_threshold = htole16(1);
        !          2467:                /* send probe requests at 6Mbps */
        !          2468:                hdr->rate = wpi_plcp_signal(12);
        !          2469:        } else {
        !          2470:                hdr->flags = htole32(WPI_CONFIG_24GHZ | WPI_CONFIG_AUTO);
        !          2471:                /* send probe requests at 1Mbps */
        !          2472:                hdr->rate = wpi_plcp_signal(2);
        !          2473:        }
        !          2474:
        !          2475:        /* for directed scans, firmware inserts the essid IE itself */
        !          2476:        hdr->essid[0].id  = IEEE80211_ELEMID_SSID;
        !          2477:        hdr->essid[0].len = ic->ic_des_esslen;
        !          2478:        memcpy(hdr->essid[0].data, ic->ic_des_essid, ic->ic_des_esslen);
        !          2479:
        !          2480:        /*
        !          2481:         * Build a probe request frame.  Most of the following code is a
        !          2482:         * copy & paste of what is done in net80211.
        !          2483:         */
        !          2484:        wh = (struct ieee80211_frame *)(hdr + 1);
        !          2485:        wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT |
        !          2486:            IEEE80211_FC0_SUBTYPE_PROBE_REQ;
        !          2487:        wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
        !          2488:        IEEE80211_ADDR_COPY(wh->i_addr1, etherbroadcastaddr);
        !          2489:        IEEE80211_ADDR_COPY(wh->i_addr2, ic->ic_myaddr);
        !          2490:        IEEE80211_ADDR_COPY(wh->i_addr3, etherbroadcastaddr);
        !          2491:        *(u_int16_t *)&wh->i_dur[0] = 0;        /* filled by h/w */
        !          2492:        *(u_int16_t *)&wh->i_seq[0] = 0;        /* filled by h/w */
        !          2493:
        !          2494:        frm = (uint8_t *)(wh + 1);
        !          2495:
        !          2496:        /* add empty essid IE (firmware generates it for directed scans) */
        !          2497:        *frm++ = IEEE80211_ELEMID_SSID;
        !          2498:        *frm++ = 0;
        !          2499:
        !          2500:        mode = ieee80211_chan2mode(ic, ic->ic_ibss_chan);
        !          2501:        rs = &ic->ic_sup_rates[mode];
        !          2502:
        !          2503:        /* add supported rates IE */
        !          2504:        frm = ieee80211_add_rates(frm, rs);
        !          2505:
        !          2506:        /* add supported xrates IE */
        !          2507:        if (rs->rs_nrates > IEEE80211_RATE_SIZE)
        !          2508:                frm = ieee80211_add_xrates(frm, rs);
        !          2509:
        !          2510:        /* setup length of probe request */
        !          2511:        hdr->paylen = htole16(frm - (uint8_t *)wh);
        !          2512:
        !          2513:        chan = (struct wpi_scan_chan *)frm;
        !          2514:        for (c  = &ic->ic_channels[1];
        !          2515:             c <= &ic->ic_channels[IEEE80211_CHAN_MAX]; c++) {
        !          2516:                if ((c->ic_flags & flags) != flags)
        !          2517:                        continue;
        !          2518:
        !          2519:                chan->chan = ieee80211_chan2ieee(ic, c);
        !          2520:                chan->flags = 0;
        !          2521:                if (!(c->ic_flags & IEEE80211_CHAN_PASSIVE)) {
        !          2522:                        chan->flags |= WPI_CHAN_ACTIVE;
        !          2523:                        if (ic->ic_des_esslen != 0)
        !          2524:                                chan->flags |= WPI_CHAN_DIRECT;
        !          2525:                }
        !          2526:                chan->dsp_gain = 0x6e;
        !          2527:                if (IEEE80211_IS_CHAN_5GHZ(c)) {
        !          2528:                        chan->rf_gain = 0x3b;
        !          2529:                        chan->active  = htole16(10);
        !          2530:                        chan->passive = htole16(110);
        !          2531:                } else {
        !          2532:                        chan->rf_gain = 0x28;
        !          2533:                        chan->active  = htole16(20);
        !          2534:                        chan->passive = htole16(120);
        !          2535:                }
        !          2536:                hdr->nchan++;
        !          2537:                chan++;
        !          2538:
        !          2539:                frm += sizeof (struct wpi_scan_chan);
        !          2540:        }
        !          2541:
        !          2542:        hdr->len = htole16(frm - (uint8_t *)hdr);
        !          2543:        pktlen = frm - (uint8_t *)cmd;
        !          2544:
        !          2545:        error = bus_dmamap_load(sc->sc_dmat, data->map, cmd, pktlen, NULL,
        !          2546:            BUS_DMA_NOWAIT);
        !          2547:        if (error != 0) {
        !          2548:                printf("%s: could not map scan command\n",
        !          2549:                    sc->sc_dev.dv_xname);
        !          2550:                m_freem(data->m);
        !          2551:                data->m = NULL;
        !          2552:                return error;
        !          2553:        }
        !          2554:
        !          2555:        desc->flags = htole32(WPI_PAD32(pktlen) << 28 | 1 << 24);
        !          2556:        desc->segs[0].addr = htole32(data->map->dm_segs[0].ds_addr);
        !          2557:        desc->segs[0].len  = htole32(data->map->dm_segs[0].ds_len);
        !          2558:
        !          2559:        /* kick cmd ring */
        !          2560:        ring->cur = (ring->cur + 1) % WPI_CMD_RING_COUNT;
        !          2561:        WPI_WRITE(sc, WPI_TX_WIDX, ring->qid << 8 | ring->cur);
        !          2562:
        !          2563:        return 0;       /* will be notified async. of failure/success */
        !          2564: }
        !          2565:
        !          2566: int
        !          2567: wpi_config(struct wpi_softc *sc)
        !          2568: {
        !          2569:        struct ieee80211com *ic = &sc->sc_ic;
        !          2570:        struct ifnet *ifp = &ic->ic_if;
        !          2571:        struct wpi_power power;
        !          2572:        struct wpi_bluetooth bluetooth;
        !          2573:        struct wpi_node_info node;
        !          2574:        int error;
        !          2575:
        !          2576:        /* set power mode */
        !          2577:        memset(&power, 0, sizeof power);
        !          2578:        power.flags = htole32(WPI_POWER_CAM | 0x8);
        !          2579:        error = wpi_cmd(sc, WPI_CMD_SET_POWER_MODE, &power, sizeof power, 0);
        !          2580:        if (error != 0) {
        !          2581:                printf("%s: could not set power mode\n", sc->sc_dev.dv_xname);
        !          2582:                return error;
        !          2583:        }
        !          2584:
        !          2585:        /* configure bluetooth coexistence */
        !          2586:        memset(&bluetooth, 0, sizeof bluetooth);
        !          2587:        bluetooth.flags = 3;
        !          2588:        bluetooth.lead = 0xaa;
        !          2589:        bluetooth.kill = 1;
        !          2590:        error = wpi_cmd(sc, WPI_CMD_BLUETOOTH, &bluetooth, sizeof bluetooth,
        !          2591:            0);
        !          2592:        if (error != 0) {
        !          2593:                printf("%s: could not configure bluetooth coexistence\n",
        !          2594:                    sc->sc_dev.dv_xname);
        !          2595:                return error;
        !          2596:        }
        !          2597:
        !          2598:        /* configure adapter */
        !          2599:        memset(&sc->config, 0, sizeof (struct wpi_config));
        !          2600:        IEEE80211_ADDR_COPY(ic->ic_myaddr, LLADDR(ifp->if_sadl));
        !          2601:        IEEE80211_ADDR_COPY(sc->config.myaddr, ic->ic_myaddr);
        !          2602:        /* set default channel */
        !          2603:        sc->config.chan = ieee80211_chan2ieee(ic, ic->ic_ibss_chan);
        !          2604:        sc->config.flags = htole32(WPI_CONFIG_TSF);
        !          2605:        if (IEEE80211_IS_CHAN_2GHZ(ic->ic_ibss_chan)) {
        !          2606:                sc->config.flags |= htole32(WPI_CONFIG_AUTO |
        !          2607:                    WPI_CONFIG_24GHZ);
        !          2608:        }
        !          2609:        sc->config.filter = 0;
        !          2610:        switch (ic->ic_opmode) {
        !          2611:        case IEEE80211_M_STA:
        !          2612:                sc->config.mode = WPI_MODE_STA;
        !          2613:                sc->config.filter |= htole32(WPI_FILTER_MULTICAST);
        !          2614:                break;
        !          2615:        case IEEE80211_M_IBSS:
        !          2616:        case IEEE80211_M_AHDEMO:
        !          2617:                sc->config.mode = WPI_MODE_IBSS;
        !          2618:                break;
        !          2619:        case IEEE80211_M_HOSTAP:
        !          2620:                sc->config.mode = WPI_MODE_HOSTAP;
        !          2621:                break;
        !          2622:        case IEEE80211_M_MONITOR:
        !          2623:                sc->config.mode = WPI_MODE_MONITOR;
        !          2624:                sc->config.filter |= htole32(WPI_FILTER_MULTICAST |
        !          2625:                    WPI_FILTER_CTL | WPI_FILTER_PROMISC);
        !          2626:                break;
        !          2627:        }
        !          2628:        sc->config.cck_mask  = 0x0f;    /* not yet negotiated */
        !          2629:        sc->config.ofdm_mask = 0xff;    /* not yet negotiated */
        !          2630:        error = wpi_cmd(sc, WPI_CMD_CONFIGURE, &sc->config,
        !          2631:            sizeof (struct wpi_config), 0);
        !          2632:        if (error != 0) {
        !          2633:                printf("%s: configure command failed\n", sc->sc_dev.dv_xname);
        !          2634:                return error;
        !          2635:        }
        !          2636:
        !          2637:        /* configuration has changed, set Tx power accordingly */
        !          2638:        if ((error = wpi_set_txpower(sc, ic->ic_ibss_chan, 0)) != 0) {
        !          2639:                printf("%s: could not set Tx power\n", sc->sc_dev.dv_xname);
        !          2640:                return error;
        !          2641:        }
        !          2642:
        !          2643:        /* add broadcast node */
        !          2644:        memset(&node, 0, sizeof node);
        !          2645:        IEEE80211_ADDR_COPY(node.bssid, etherbroadcastaddr);
        !          2646:        node.id = WPI_ID_BROADCAST;
        !          2647:        node.rate = wpi_plcp_signal(2);
        !          2648:        node.action = htole32(WPI_ACTION_SET_RATE);
        !          2649:        node.antenna = WPI_ANTENNA_BOTH;
        !          2650:        error = wpi_cmd(sc, WPI_CMD_ADD_NODE, &node, sizeof node, 0);
        !          2651:        if (error != 0) {
        !          2652:                printf("%s: could not add broadcast node\n",
        !          2653:                    sc->sc_dev.dv_xname);
        !          2654:                return error;
        !          2655:        }
        !          2656:
        !          2657:        if ((error = wpi_mrr_setup(sc)) != 0) {
        !          2658:                printf("%s: could not setup MRR\n", sc->sc_dev.dv_xname);
        !          2659:                return error;
        !          2660:        }
        !          2661:
        !          2662:        return 0;
        !          2663: }
        !          2664:
        !          2665: void
        !          2666: wpi_stop_master(struct wpi_softc *sc)
        !          2667: {
        !          2668:        uint32_t tmp;
        !          2669:        int ntries;
        !          2670:
        !          2671:        tmp = WPI_READ(sc, WPI_RESET);
        !          2672:        WPI_WRITE(sc, WPI_RESET, tmp | WPI_STOP_MASTER);
        !          2673:
        !          2674:        tmp = WPI_READ(sc, WPI_GPIO_CTL);
        !          2675:        if ((tmp & WPI_GPIO_PWR_STATUS) == WPI_GPIO_PWR_SLEEP)
        !          2676:                return; /* already asleep */
        !          2677:
        !          2678:        for (ntries = 0; ntries < 100; ntries++) {
        !          2679:                if (WPI_READ(sc, WPI_RESET) & WPI_MASTER_DISABLED)
        !          2680:                        break;
        !          2681:                DELAY(10);
        !          2682:        }
        !          2683:        if (ntries == 100) {
        !          2684:                printf("%s: timeout waiting for master\n",
        !          2685:                    sc->sc_dev.dv_xname);
        !          2686:        }
        !          2687: }
        !          2688:
        !          2689: int
        !          2690: wpi_power_up(struct wpi_softc *sc)
        !          2691: {
        !          2692:        uint32_t tmp;
        !          2693:        int ntries;
        !          2694:
        !          2695:        wpi_mem_lock(sc);
        !          2696:        tmp = wpi_mem_read(sc, WPI_MEM_POWER);
        !          2697:        wpi_mem_write(sc, WPI_MEM_POWER, tmp & ~0x03000000);
        !          2698:        wpi_mem_unlock(sc);
        !          2699:
        !          2700:        for (ntries = 0; ntries < 5000; ntries++) {
        !          2701:                if (WPI_READ(sc, WPI_GPIO_STATUS) & WPI_POWERED)
        !          2702:                        break;
        !          2703:                DELAY(10);
        !          2704:        }
        !          2705:        if (ntries == 5000) {
        !          2706:                printf("%s: timeout waiting for NIC to power up\n",
        !          2707:                    sc->sc_dev.dv_xname);
        !          2708:                return ETIMEDOUT;
        !          2709:        }
        !          2710:        return 0;
        !          2711: }
        !          2712:
        !          2713: int
        !          2714: wpi_reset(struct wpi_softc *sc)
        !          2715: {
        !          2716:        uint32_t tmp;
        !          2717:        int ntries;
        !          2718:
        !          2719:        /* clear any pending interrupts */
        !          2720:        WPI_WRITE(sc, WPI_INTR, 0xffffffff);
        !          2721:
        !          2722:        tmp = WPI_READ(sc, WPI_PLL_CTL);
        !          2723:        WPI_WRITE(sc, WPI_PLL_CTL, tmp | WPI_PLL_INIT);
        !          2724:
        !          2725:        tmp = WPI_READ(sc, WPI_CHICKEN);
        !          2726:        WPI_WRITE(sc, WPI_CHICKEN, tmp | WPI_CHICKEN_RXNOLOS);
        !          2727:
        !          2728:        tmp = WPI_READ(sc, WPI_GPIO_CTL);
        !          2729:        WPI_WRITE(sc, WPI_GPIO_CTL, tmp | WPI_GPIO_INIT);
        !          2730:
        !          2731:        /* wait for clock stabilization */
        !          2732:        for (ntries = 0; ntries < 1000; ntries++) {
        !          2733:                if (WPI_READ(sc, WPI_GPIO_CTL) & WPI_GPIO_CLOCK)
        !          2734:                        break;
        !          2735:                DELAY(10);
        !          2736:        }
        !          2737:        if (ntries == 1000) {
        !          2738:                printf("%s: timeout waiting for clock stabilization\n",
        !          2739:                    sc->sc_dev.dv_xname);
        !          2740:                return ETIMEDOUT;
        !          2741:        }
        !          2742:
        !          2743:        /* initialize EEPROM */
        !          2744:        tmp = WPI_READ(sc, WPI_EEPROM_STATUS);
        !          2745:        if ((tmp & WPI_EEPROM_VERSION) == 0) {
        !          2746:                printf("%s: EEPROM not found\n", sc->sc_dev.dv_xname);
        !          2747:                return EIO;
        !          2748:        }
        !          2749:        WPI_WRITE(sc, WPI_EEPROM_STATUS, tmp & ~WPI_EEPROM_LOCKED);
        !          2750:
        !          2751:        return 0;
        !          2752: }
        !          2753:
        !          2754: void
        !          2755: wpi_hw_config(struct wpi_softc *sc)
        !          2756: {
        !          2757:        uint32_t rev, hw;
        !          2758:
        !          2759:        /* voodoo from the reference driver */
        !          2760:        hw = WPI_READ(sc, WPI_HWCONFIG);
        !          2761:
        !          2762:        rev = pci_conf_read(sc->sc_pct, sc->sc_pcitag, PCI_CLASS_REG);
        !          2763:        rev = PCI_REVISION(rev);
        !          2764:        if ((rev & 0xc0) == 0x40)
        !          2765:                hw |= WPI_HW_ALM_MB;
        !          2766:        else if (!(rev & 0x80))
        !          2767:                hw |= WPI_HW_ALM_MM;
        !          2768:
        !          2769:        if (sc->cap == 0x80)
        !          2770:                hw |= WPI_HW_SKU_MRC;
        !          2771:
        !          2772:        hw &= ~WPI_HW_REV_D;
        !          2773:        if ((letoh16(sc->rev) & 0xf0) == 0xd0)
        !          2774:                hw |= WPI_HW_REV_D;
        !          2775:
        !          2776:        if (sc->type > 1)
        !          2777:                hw |= WPI_HW_TYPE_B;
        !          2778:
        !          2779:        DPRINTF(("setting h/w config %x\n", hw));
        !          2780:        WPI_WRITE(sc, WPI_HWCONFIG, hw);
        !          2781: }
        !          2782:
        !          2783: int
        !          2784: wpi_init(struct ifnet *ifp)
        !          2785: {
        !          2786:        struct wpi_softc *sc = ifp->if_softc;
        !          2787:        struct ieee80211com *ic = &sc->sc_ic;
        !          2788:        uint32_t tmp;
        !          2789:        int qid, ntries, error;
        !          2790:
        !          2791:        (void)wpi_reset(sc);
        !          2792:
        !          2793:        wpi_mem_lock(sc);
        !          2794:        wpi_mem_write(sc, WPI_MEM_CLOCK1, 0xa00);
        !          2795:        DELAY(20);
        !          2796:        tmp = wpi_mem_read(sc, WPI_MEM_PCIDEV);
        !          2797:        wpi_mem_write(sc, WPI_MEM_PCIDEV, tmp | 0x800);
        !          2798:        wpi_mem_unlock(sc);
        !          2799:
        !          2800:        (void)wpi_power_up(sc);
        !          2801:        wpi_hw_config(sc);
        !          2802:
        !          2803:        /* init Rx ring */
        !          2804:        wpi_mem_lock(sc);
        !          2805:        WPI_WRITE(sc, WPI_RX_BASE, sc->rxq.desc_dma.paddr);
        !          2806:        WPI_WRITE(sc, WPI_RX_RIDX_PTR, sc->shared_dma.paddr +
        !          2807:            offsetof(struct wpi_shared, next));
        !          2808:        WPI_WRITE(sc, WPI_RX_WIDX, (WPI_RX_RING_COUNT - 1) & ~7);
        !          2809:        WPI_WRITE(sc, WPI_RX_CONFIG, 0xa9601010);
        !          2810:        wpi_mem_unlock(sc);
        !          2811:
        !          2812:        /* init Tx rings */
        !          2813:        wpi_mem_lock(sc);
        !          2814:        wpi_mem_write(sc, WPI_MEM_MODE, 2);     /* bypass mode */
        !          2815:        wpi_mem_write(sc, WPI_MEM_RA, 1);       /* enable RA0 */
        !          2816:        wpi_mem_write(sc, WPI_MEM_TXCFG, 0x3f); /* enable all 6 Tx rings */
        !          2817:        wpi_mem_write(sc, WPI_MEM_BYPASS1, 0x10000);
        !          2818:        wpi_mem_write(sc, WPI_MEM_BYPASS2, 0x30002);
        !          2819:        wpi_mem_write(sc, WPI_MEM_MAGIC4, 4);
        !          2820:        wpi_mem_write(sc, WPI_MEM_MAGIC5, 5);
        !          2821:
        !          2822:        WPI_WRITE(sc, WPI_TX_BASE_PTR, sc->shared_dma.paddr);
        !          2823:        WPI_WRITE(sc, WPI_MSG_CONFIG, 0xffff05a5);
        !          2824:
        !          2825:        for (qid = 0; qid < 6; qid++) {
        !          2826:                WPI_WRITE(sc, WPI_TX_CTL(qid), 0);
        !          2827:                WPI_WRITE(sc, WPI_TX_BASE(qid), 0);
        !          2828:                WPI_WRITE(sc, WPI_TX_CONFIG(qid), 0x80200008);
        !          2829:        }
        !          2830:        wpi_mem_unlock(sc);
        !          2831:
        !          2832:        /* clear "radio off" and "disable command" bits (reversed logic) */
        !          2833:        WPI_WRITE(sc, WPI_UCODE_CLR, WPI_RADIO_OFF);
        !          2834:        WPI_WRITE(sc, WPI_UCODE_CLR, WPI_DISABLE_CMD);
        !          2835:
        !          2836:        /* clear any pending interrupts */
        !          2837:        WPI_WRITE(sc, WPI_INTR, 0xffffffff);
        !          2838:        /* enable interrupts */
        !          2839:        WPI_WRITE(sc, WPI_MASK, WPI_INTR_MASK);
        !          2840:
        !          2841:        /* not sure why/if this is necessary... */
        !          2842:        WPI_WRITE(sc, WPI_UCODE_CLR, WPI_RADIO_OFF);
        !          2843:        WPI_WRITE(sc, WPI_UCODE_CLR, WPI_RADIO_OFF);
        !          2844:
        !          2845:        if ((error = wpi_load_firmware(sc)) != 0) {
        !          2846:                printf("%s: could not load firmware\n", sc->sc_dev.dv_xname);
        !          2847:                goto fail1;
        !          2848:        }
        !          2849:
        !          2850:        /* wait for thermal sensors to calibrate */
        !          2851:        for (ntries = 0; ntries < 1000; ntries++) {
        !          2852:                if ((sc->temp = (int)WPI_READ(sc, WPI_TEMPERATURE)) != 0)
        !          2853:                        break;
        !          2854:                DELAY(10);
        !          2855:        }
        !          2856:        if (ntries == 1000) {
        !          2857:                printf("%s: timeout waiting for thermal sensors calibration\n",
        !          2858:                    sc->sc_dev.dv_xname);
        !          2859:                error = ETIMEDOUT;
        !          2860:                goto fail1;
        !          2861:        }
        !          2862:        DPRINTF(("temperature %d\n", sc->temp));
        !          2863:        sc->sensor.value = sc->temp + 260;
        !          2864:        sc->sensor.flags &= ~SENSOR_FINVALID;
        !          2865:
        !          2866:        if ((error = wpi_config(sc)) != 0) {
        !          2867:                printf("%s: could not configure device\n",
        !          2868:                    sc->sc_dev.dv_xname);
        !          2869:                goto fail1;
        !          2870:        }
        !          2871:
        !          2872:        ifp->if_flags &= ~IFF_OACTIVE;
        !          2873:        ifp->if_flags |= IFF_RUNNING;
        !          2874:
        !          2875:        if (ic->ic_opmode != IEEE80211_M_MONITOR)
        !          2876:                ieee80211_begin_scan(ifp);
        !          2877:        else
        !          2878:                ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
        !          2879:
        !          2880:        return 0;
        !          2881:
        !          2882: fail1: wpi_stop(ifp, 1);
        !          2883:        return error;
        !          2884: }
        !          2885:
        !          2886: void
        !          2887: wpi_stop(struct ifnet *ifp, int disable)
        !          2888: {
        !          2889:        struct wpi_softc *sc = ifp->if_softc;
        !          2890:        struct ieee80211com *ic = &sc->sc_ic;
        !          2891:        uint32_t tmp;
        !          2892:        int ac;
        !          2893:
        !          2894:        ifp->if_timer = sc->sc_tx_timer = 0;
        !          2895:        ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
        !          2896:
        !          2897:        ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
        !          2898:
        !          2899:        /* disable interrupts */
        !          2900:        WPI_WRITE(sc, WPI_MASK, 0);
        !          2901:        WPI_WRITE(sc, WPI_INTR, WPI_INTR_MASK);
        !          2902:        WPI_WRITE(sc, WPI_INTR_STATUS, 0xff);
        !          2903:        WPI_WRITE(sc, WPI_INTR_STATUS, 0x00070000);
        !          2904:
        !          2905:        wpi_mem_lock(sc);
        !          2906:        wpi_mem_write(sc, WPI_MEM_MODE, 0);
        !          2907:        wpi_mem_unlock(sc);
        !          2908:
        !          2909:        /* reset all Tx rings */
        !          2910:        for (ac = 0; ac < 4; ac++)
        !          2911:                wpi_reset_tx_ring(sc, &sc->txq[ac]);
        !          2912:        wpi_reset_tx_ring(sc, &sc->cmdq);
        !          2913:
        !          2914:        /* reset Rx ring */
        !          2915:        wpi_reset_rx_ring(sc, &sc->rxq);
        !          2916:
        !          2917:        /* temperature is no longer valid */
        !          2918:        sc->sensor.value = 0;
        !          2919:        sc->sensor.flags |= SENSOR_FINVALID;
        !          2920:
        !          2921:        wpi_mem_lock(sc);
        !          2922:        wpi_mem_write(sc, WPI_MEM_CLOCK2, 0x200);
        !          2923:        wpi_mem_unlock(sc);
        !          2924:
        !          2925:        DELAY(5);
        !          2926:
        !          2927:        wpi_stop_master(sc);
        !          2928:
        !          2929:        tmp = WPI_READ(sc, WPI_RESET);
        !          2930:        WPI_WRITE(sc, WPI_RESET, tmp | WPI_SW_RESET);
        !          2931: }
        !          2932:
        !          2933: struct cfdriver wpi_cd = {
        !          2934:        NULL, "wpi", DV_IFNET
        !          2935: };

CVSweb