The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/ic/pgt.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $OpenBSD: pgt.c,v 1.103 2022/04/21 21:03:02 stsp Exp $  */
    2 
    3 /*
    4  * Copyright (c) 2006 Claudio Jeker <claudio@openbsd.org>
    5  * Copyright (c) 2006 Marcus Glocker <mglocker@openbsd.org>
    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  * Copyright (c) 2004 Fujitsu Laboratories of America, Inc.
   22  * Copyright (c) 2004 Brian Fundakowski Feldman
   23  * All rights reserved.
   24  *
   25  * Redistribution and use in source and binary forms, with or without
   26  * modification, are permitted provided that the following conditions
   27  * are met:
   28  * 1. Redistributions of source code must retain the above copyright
   29  *    notice, this list of conditions and the following disclaimer.
   30  * 2. Redistributions in binary form must reproduce the above copyright
   31  *    notice, this list of conditions and the following disclaimer in the
   32  *    documentation and/or other materials provided with the distribution.
   33  *
   34  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   35  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   36  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   37  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   38  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   39  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   40  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   41  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   42  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   43  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   44  * SUCH DAMAGE.
   45  */
   46 
   47 #include "bpfilter.h"
   48 
   49 #include <sys/param.h>
   50 #include <sys/systm.h>
   51 #include <sys/kernel.h>
   52 #include <sys/malloc.h>
   53 #include <sys/socket.h>
   54 #include <sys/mbuf.h>
   55 #include <sys/endian.h>
   56 #include <sys/sockio.h>
   57 #include <sys/kthread.h>
   58 #include <sys/time.h>
   59 #include <sys/ioctl.h>
   60 #include <sys/device.h>
   61 
   62 #include <machine/bus.h>
   63 #include <machine/intr.h>
   64 
   65 #include <net/if.h>
   66 #include <net/if_llc.h>
   67 #include <net/if_media.h>
   68 
   69 #if NBPFILTER > 0
   70 #include <net/bpf.h>
   71 #endif
   72 
   73 #include <netinet/in.h>
   74 #include <netinet/if_ether.h>
   75 
   76 #include <net80211/ieee80211_var.h>
   77 #include <net80211/ieee80211_radiotap.h>
   78 
   79 #include <dev/ic/pgtreg.h>
   80 #include <dev/ic/pgtvar.h>
   81 
   82 #include <dev/ic/if_wireg.h>
   83 #include <dev/ic/if_wi_ieee.h>
   84 #include <dev/ic/if_wivar.h>
   85 
   86 #ifdef PGT_DEBUG
   87 #define DPRINTF(x)      do { printf x; } while (0)
   88 #else
   89 #define DPRINTF(x)
   90 #endif
   91 
   92 #define SETOID(oid, var, size) {                                        \
   93         if (pgt_oid_set(sc, oid, var, size) != 0)                       \
   94                 break;                                                  \
   95 }
   96 
   97 /*
   98  * This is a driver for the Intersil Prism family of 802.11g network cards,
   99  * based upon version 1.2 of the Linux driver.
  100  */
  101 
  102 #define SCAN_TIMEOUT                    5       /* 5 seconds */
  103 
  104 struct cfdriver pgt_cd = {
  105         NULL, "pgt", DV_IFNET
  106 };
  107 
  108 void     pgt_media_status(struct ifnet *ifp, struct ifmediareq *imr);
  109 int      pgt_media_change(struct ifnet *ifp);
  110 void     pgt_write_memory_barrier(struct pgt_softc *);
  111 uint32_t pgt_read_4(struct pgt_softc *, uint16_t);
  112 void     pgt_write_4(struct pgt_softc *, uint16_t, uint32_t);
  113 void     pgt_write_4_flush(struct pgt_softc *, uint16_t, uint32_t);
  114 void     pgt_debug_events(struct pgt_softc *, const char *);
  115 uint32_t pgt_queue_frags_pending(struct pgt_softc *, enum pgt_queue);
  116 void     pgt_reinit_rx_desc_frag(struct pgt_softc *, struct pgt_desc *);
  117 int      pgt_load_tx_desc_frag(struct pgt_softc *, enum pgt_queue,
  118              struct pgt_desc *);
  119 void     pgt_unload_tx_desc_frag(struct pgt_softc *, struct pgt_desc *);
  120 int      pgt_load_firmware(struct pgt_softc *);
  121 void     pgt_cleanup_queue(struct pgt_softc *, enum pgt_queue,
  122              struct pgt_frag *);
  123 int      pgt_reset(struct pgt_softc *);
  124 void     pgt_stop(struct pgt_softc *, unsigned int);
  125 void     pgt_reboot(struct pgt_softc *);
  126 void     pgt_init_intr(struct pgt_softc *);
  127 void     pgt_update_intr(struct pgt_softc *, int);
  128 struct mbuf
  129         *pgt_ieee80211_encap(struct pgt_softc *, struct ether_header *,
  130              struct mbuf *, struct ieee80211_node **);
  131 void     pgt_input_frames(struct pgt_softc *, struct mbuf *);
  132 void     pgt_wakeup_intr(struct pgt_softc *);
  133 void     pgt_sleep_intr(struct pgt_softc *);
  134 void     pgt_empty_traps(struct pgt_softc_kthread *);
  135 void     pgt_per_device_kthread(void *);
  136 void     pgt_async_reset(struct pgt_softc *);
  137 void     pgt_async_update(struct pgt_softc *);
  138 void     pgt_txdone(struct pgt_softc *, enum pgt_queue);
  139 void     pgt_rxdone(struct pgt_softc *, enum pgt_queue);
  140 void     pgt_trap_received(struct pgt_softc *, uint32_t, void *, size_t);
  141 void     pgt_mgmtrx_completion(struct pgt_softc *, struct pgt_mgmt_desc *);
  142 struct mbuf
  143         *pgt_datarx_completion(struct pgt_softc *, enum pgt_queue);
  144 int      pgt_oid_get(struct pgt_softc *, enum pgt_oid, void *, size_t);
  145 int      pgt_oid_retrieve(struct pgt_softc *, enum pgt_oid, void *, size_t);
  146 int      pgt_oid_set(struct pgt_softc *, enum pgt_oid, const void *, size_t);
  147 void     pgt_state_dump(struct pgt_softc *);
  148 int      pgt_mgmt_request(struct pgt_softc *, struct pgt_mgmt_desc *);
  149 void     pgt_desc_transmit(struct pgt_softc *, enum pgt_queue,
  150              struct pgt_desc *, uint16_t, int);
  151 void     pgt_maybe_trigger(struct pgt_softc *, enum pgt_queue);
  152 struct ieee80211_node
  153         *pgt_ieee80211_node_alloc(struct ieee80211com *);
  154 void     pgt_ieee80211_newassoc(struct ieee80211com *,
  155              struct ieee80211_node *, int);
  156 void     pgt_ieee80211_node_free(struct ieee80211com *,
  157             struct ieee80211_node *);
  158 void     pgt_ieee80211_node_copy(struct ieee80211com *,
  159              struct ieee80211_node *,
  160              const struct ieee80211_node *);
  161 int      pgt_ieee80211_send_mgmt(struct ieee80211com *,
  162              struct ieee80211_node *, int, int, int);
  163 int      pgt_net_attach(struct pgt_softc *);
  164 void     pgt_start(struct ifnet *);
  165 int      pgt_ioctl(struct ifnet *, u_long, caddr_t);
  166 void     pgt_obj_bss2scanres(struct pgt_softc *,
  167              struct pgt_obj_bss *, struct wi_scan_res *, uint32_t);
  168 void     node_mark_active_ap(void *, struct ieee80211_node *);
  169 void     node_mark_active_adhoc(void *, struct ieee80211_node *);
  170 void     pgt_watchdog(struct ifnet *);
  171 int      pgt_init(struct ifnet *);
  172 void     pgt_update_hw_from_sw(struct pgt_softc *, int);
  173 void     pgt_hostap_handle_mlme(struct pgt_softc *, uint32_t,
  174              struct pgt_obj_mlme *);
  175 void     pgt_update_sw_from_hw(struct pgt_softc *,
  176              struct pgt_async_trap *, struct mbuf *);
  177 int      pgt_newstate(struct ieee80211com *, enum ieee80211_state, int);
  178 int      pgt_drain_tx_queue(struct pgt_softc *, enum pgt_queue);
  179 int      pgt_dma_alloc(struct pgt_softc *);
  180 int      pgt_dma_alloc_queue(struct pgt_softc *sc, enum pgt_queue pq);
  181 void     pgt_dma_free(struct pgt_softc *);
  182 void     pgt_dma_free_queue(struct pgt_softc *sc, enum pgt_queue pq);
  183 void     pgt_wakeup(struct pgt_softc *);
  184 
  185 void
  186 pgt_write_memory_barrier(struct pgt_softc *sc)
  187 {
  188         bus_space_barrier(sc->sc_iotag, sc->sc_iohandle, 0, 0,
  189             BUS_SPACE_BARRIER_WRITE);
  190 }
  191 
  192 u_int32_t
  193 pgt_read_4(struct pgt_softc *sc, uint16_t offset)
  194 {
  195         return (bus_space_read_4(sc->sc_iotag, sc->sc_iohandle, offset));
  196 }
  197 
  198 void
  199 pgt_write_4(struct pgt_softc *sc, uint16_t offset, uint32_t value)
  200 {
  201         bus_space_write_4(sc->sc_iotag, sc->sc_iohandle, offset, value);
  202 }
  203 
  204 /*
  205  * Write out 4 bytes and cause a PCI flush by reading back in on a
  206  * harmless register.
  207  */
  208 void
  209 pgt_write_4_flush(struct pgt_softc *sc, uint16_t offset, uint32_t value)
  210 {
  211         bus_space_write_4(sc->sc_iotag, sc->sc_iohandle, offset, value);
  212         (void)bus_space_read_4(sc->sc_iotag, sc->sc_iohandle, PGT_REG_INT_EN);
  213 }
  214 
  215 /*
  216  * Print the state of events in the queues from an interrupt or a trigger.
  217  */
  218 void
  219 pgt_debug_events(struct pgt_softc *sc, const char *when)
  220 {
  221 #define COUNT(i)                                                        \
  222         letoh32(sc->sc_cb->pcb_driver_curfrag[i]) -                     \
  223         letoh32(sc->sc_cb->pcb_device_curfrag[i])
  224         if (sc->sc_debug & SC_DEBUG_EVENTS)
  225                 DPRINTF(("%s: ev%s: %u %u %u %u %u %u\n",
  226                     sc->sc_dev.dv_xname, when, COUNT(0), COUNT(1), COUNT(2),
  227                     COUNT(3), COUNT(4), COUNT(5)));
  228 #undef COUNT
  229 }
  230 
  231 uint32_t
  232 pgt_queue_frags_pending(struct pgt_softc *sc, enum pgt_queue pq)
  233 {
  234         return (letoh32(sc->sc_cb->pcb_driver_curfrag[pq]) -
  235             letoh32(sc->sc_cb->pcb_device_curfrag[pq]));
  236 }
  237 
  238 void
  239 pgt_reinit_rx_desc_frag(struct pgt_softc *sc, struct pgt_desc *pd)
  240 {
  241         pd->pd_fragp->pf_addr = htole32((uint32_t)pd->pd_dmaaddr);
  242         pd->pd_fragp->pf_size = htole16(PGT_FRAG_SIZE);
  243         pd->pd_fragp->pf_flags = 0;
  244 
  245         bus_dmamap_sync(sc->sc_dmat, pd->pd_dmam, 0, pd->pd_dmam->dm_mapsize,
  246             BUS_DMASYNC_POSTWRITE);
  247 }
  248 
  249 int
  250 pgt_load_tx_desc_frag(struct pgt_softc *sc, enum pgt_queue pq,
  251     struct pgt_desc *pd)
  252 {
  253         int error;
  254 
  255         error = bus_dmamap_load(sc->sc_dmat, pd->pd_dmam, pd->pd_mem,
  256             PGT_FRAG_SIZE, NULL, BUS_DMA_NOWAIT);
  257         if (error) {
  258                 DPRINTF(("%s: unable to load %s tx DMA: %d\n",
  259                     sc->sc_dev.dv_xname,
  260                     pgt_queue_is_data(pq) ? "data" : "mgmt", error));
  261                 return (error);
  262         }
  263         pd->pd_dmaaddr = pd->pd_dmam->dm_segs[0].ds_addr;
  264         pd->pd_fragp->pf_addr = htole32((uint32_t)pd->pd_dmaaddr);
  265         pd->pd_fragp->pf_size = htole16(PGT_FRAG_SIZE);
  266         pd->pd_fragp->pf_flags = htole16(0);
  267 
  268         bus_dmamap_sync(sc->sc_dmat, pd->pd_dmam, 0, pd->pd_dmam->dm_mapsize,
  269             BUS_DMASYNC_POSTWRITE);
  270 
  271         return (0);
  272 }
  273 
  274 void
  275 pgt_unload_tx_desc_frag(struct pgt_softc *sc, struct pgt_desc *pd)
  276 {
  277         bus_dmamap_unload(sc->sc_dmat, pd->pd_dmam);
  278         pd->pd_dmaaddr = 0;
  279 }
  280 
  281 int
  282 pgt_load_firmware(struct pgt_softc *sc)
  283 {
  284         int error, reg, dirreg, fwoff, ucodeoff, fwlen;
  285         uint8_t *ucode;
  286         uint32_t *uc;
  287         size_t size;
  288         char *name;
  289 
  290         if (sc->sc_flags & SC_ISL3877)
  291                 name = "pgt-isl3877";
  292         else
  293                 name = "pgt-isl3890";   /* includes isl3880 */
  294 
  295         error = loadfirmware(name, &ucode, &size);
  296 
  297         if (error != 0) {
  298                 DPRINTF(("%s: error %d, could not read firmware %s\n",
  299                     sc->sc_dev.dv_xname, error, name));
  300                 return (EIO);
  301         }
  302 
  303         if (size & 3) {
  304                 DPRINTF(("%s: bad firmware size %u\n",
  305                     sc->sc_dev.dv_xname, size));
  306                 free(ucode, M_DEVBUF, 0);
  307                 return (EINVAL);
  308         }
  309 
  310         pgt_reboot(sc);
  311 
  312         fwoff = 0;
  313         ucodeoff = 0;
  314         uc = (uint32_t *)ucode;
  315         reg = PGT_FIRMWARE_INTERNAL_OFFSET;
  316         while (fwoff < size) {
  317                 pgt_write_4_flush(sc, PGT_REG_DIR_MEM_BASE, reg);
  318 
  319                 if ((size - fwoff) >= PGT_DIRECT_MEMORY_SIZE)
  320                         fwlen = PGT_DIRECT_MEMORY_SIZE;
  321                 else
  322                         fwlen = size - fwoff;
  323 
  324                 dirreg = PGT_DIRECT_MEMORY_OFFSET;
  325                 while (fwlen > 4) {
  326                         pgt_write_4(sc, dirreg, uc[ucodeoff]);
  327                         fwoff += 4;
  328                         dirreg += 4;
  329                         reg += 4;
  330                         fwlen -= 4;
  331                         ucodeoff++;
  332                 }
  333                 pgt_write_4_flush(sc, dirreg, uc[ucodeoff]);
  334                 fwoff += 4;
  335                 dirreg += 4;
  336                 reg += 4;
  337                 fwlen -= 4;
  338                 ucodeoff++;
  339         }
  340         DPRINTF(("%s: %d bytes microcode loaded from %s\n",
  341             sc->sc_dev.dv_xname, fwoff, name));
  342 
  343         reg = pgt_read_4(sc, PGT_REG_CTRL_STAT);
  344         reg &= ~(PGT_CTRL_STAT_RESET | PGT_CTRL_STAT_CLOCKRUN);
  345         reg |= PGT_CTRL_STAT_RAMBOOT;
  346         pgt_write_4_flush(sc, PGT_REG_CTRL_STAT, reg);
  347         pgt_write_memory_barrier(sc);
  348         DELAY(PGT_WRITEIO_DELAY);
  349 
  350         reg |= PGT_CTRL_STAT_RESET;
  351         pgt_write_4(sc, PGT_REG_CTRL_STAT, reg);
  352         pgt_write_memory_barrier(sc);
  353         DELAY(PGT_WRITEIO_DELAY);
  354 
  355         reg &= ~PGT_CTRL_STAT_RESET;
  356         pgt_write_4(sc, PGT_REG_CTRL_STAT, reg);
  357         pgt_write_memory_barrier(sc);
  358         DELAY(PGT_WRITEIO_DELAY);
  359 
  360         free(ucode, M_DEVBUF, 0);
  361         
  362         return (0);
  363 }
  364 
  365 void
  366 pgt_cleanup_queue(struct pgt_softc *sc, enum pgt_queue pq,
  367     struct pgt_frag *pqfrags)
  368 {
  369         struct pgt_desc *pd;
  370         unsigned int i;
  371 
  372         sc->sc_cb->pcb_device_curfrag[pq] = 0;
  373         i = 0;
  374         /* XXX why only freeq ??? */
  375         TAILQ_FOREACH(pd, &sc->sc_freeq[pq], pd_link) {
  376                 pd->pd_fragnum = i;
  377                 pd->pd_fragp = &pqfrags[i];
  378                 if (pgt_queue_is_rx(pq))
  379                         pgt_reinit_rx_desc_frag(sc, pd);
  380                 i++;
  381         }
  382         sc->sc_freeq_count[pq] = i;
  383         /*
  384          * The ring buffer describes how many free buffers are available from
  385          * the host (for receive queues) or how many are pending (for
  386          * transmit queues).
  387          */
  388         if (pgt_queue_is_rx(pq))
  389                 sc->sc_cb->pcb_driver_curfrag[pq] = htole32(i);
  390         else
  391                 sc->sc_cb->pcb_driver_curfrag[pq] = 0;
  392 }
  393 
  394 /*
  395  * Turn off interrupts, reset the device (possibly loading firmware),
  396  * and put everything in a known state.
  397  */
  398 int
  399 pgt_reset(struct pgt_softc *sc)
  400 {
  401         int error;
  402 
  403         /* disable all interrupts */
  404         pgt_write_4_flush(sc, PGT_REG_INT_EN, 0);
  405         DELAY(PGT_WRITEIO_DELAY);
  406 
  407         /*
  408          * Set up the management receive queue, assuming there are no
  409          * requests in progress.
  410          */
  411         bus_dmamap_sync(sc->sc_dmat, sc->sc_cbdmam, 0,
  412             sc->sc_cbdmam->dm_mapsize,
  413             BUS_DMASYNC_POSTREAD | BUS_DMASYNC_PREWRITE);
  414         pgt_cleanup_queue(sc, PGT_QUEUE_DATA_LOW_RX,
  415             &sc->sc_cb->pcb_data_low_rx[0]);
  416         pgt_cleanup_queue(sc, PGT_QUEUE_DATA_LOW_TX,
  417             &sc->sc_cb->pcb_data_low_tx[0]);
  418         pgt_cleanup_queue(sc, PGT_QUEUE_DATA_HIGH_RX,
  419             &sc->sc_cb->pcb_data_high_rx[0]);
  420         pgt_cleanup_queue(sc, PGT_QUEUE_DATA_HIGH_TX,
  421             &sc->sc_cb->pcb_data_high_tx[0]);
  422         pgt_cleanup_queue(sc, PGT_QUEUE_MGMT_RX,
  423             &sc->sc_cb->pcb_mgmt_rx[0]);
  424         pgt_cleanup_queue(sc, PGT_QUEUE_MGMT_TX,
  425             &sc->sc_cb->pcb_mgmt_tx[0]);
  426         bus_dmamap_sync(sc->sc_dmat, sc->sc_cbdmam, 0,
  427             sc->sc_cbdmam->dm_mapsize,
  428             BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_PREREAD);
  429 
  430         /* load firmware */
  431         if (sc->sc_flags & SC_NEEDS_FIRMWARE) {
  432                 error = pgt_load_firmware(sc);
  433                 if (error) {
  434                         printf("%s: firmware load failed\n",
  435                             sc->sc_dev.dv_xname);
  436                         return (error);
  437                 }
  438                 sc->sc_flags &= ~SC_NEEDS_FIRMWARE;
  439                 DPRINTF(("%s: firmware loaded\n", sc->sc_dev.dv_xname));
  440         }
  441 
  442         /* upload the control block's DMA address */
  443         pgt_write_4_flush(sc, PGT_REG_CTRL_BLK_BASE,
  444             htole32((uint32_t)sc->sc_cbdmam->dm_segs[0].ds_addr));
  445         DELAY(PGT_WRITEIO_DELAY);
  446 
  447         /* send a reset event */
  448         pgt_write_4_flush(sc, PGT_REG_DEV_INT, PGT_DEV_INT_RESET);
  449         DELAY(PGT_WRITEIO_DELAY);
  450 
  451         /* await only the initialization interrupt */
  452         pgt_write_4_flush(sc, PGT_REG_INT_EN, PGT_INT_STAT_INIT);       
  453         DELAY(PGT_WRITEIO_DELAY);
  454 
  455         return (0);
  456 }
  457 
  458 /*
  459  * If we're trying to reset and the device has seemingly not been detached,
  460  * we'll spend a minute seeing if we can't do the reset.
  461  */
  462 void
  463 pgt_stop(struct pgt_softc *sc, unsigned int flag)
  464 {
  465         struct ieee80211com *ic;
  466         unsigned int wokeup;
  467         int tryagain = 0;
  468 
  469         ic = &sc->sc_ic;
  470 
  471         ic->ic_if.if_flags &= ~IFF_RUNNING;
  472         sc->sc_flags |= SC_UNINITIALIZED;
  473         sc->sc_flags |= flag;
  474 
  475         pgt_drain_tx_queue(sc, PGT_QUEUE_DATA_LOW_TX);
  476         pgt_drain_tx_queue(sc, PGT_QUEUE_DATA_HIGH_TX);
  477         pgt_drain_tx_queue(sc, PGT_QUEUE_MGMT_TX);
  478 
  479 trying_again:
  480         /* disable all interrupts */
  481         pgt_write_4_flush(sc, PGT_REG_INT_EN, 0);
  482         DELAY(PGT_WRITEIO_DELAY);
  483 
  484         /* reboot card */
  485         pgt_reboot(sc);
  486 
  487         do {
  488                 wokeup = 0;
  489                 /*
  490                  * We don't expect to be woken up, just to drop the lock
  491                  * and time out.  Only tx queues can have anything valid
  492                  * on them outside of an interrupt.
  493                  */
  494                 while (!TAILQ_EMPTY(&sc->sc_mgmtinprog)) {
  495                         struct pgt_mgmt_desc *pmd;
  496 
  497                         pmd = TAILQ_FIRST(&sc->sc_mgmtinprog);
  498                         TAILQ_REMOVE(&sc->sc_mgmtinprog, pmd, pmd_link);
  499                         pmd->pmd_error = ENETRESET;
  500                         wakeup_one(pmd);
  501                         if (sc->sc_debug & SC_DEBUG_MGMT)
  502                                 DPRINTF(("%s: queue: mgmt %p <- %#x "
  503                                     "(drained)\n", sc->sc_dev.dv_xname,
  504                                     pmd, pmd->pmd_oid));
  505                         wokeup++;
  506                 }
  507                 if (wokeup > 0) {
  508                         if (flag == SC_NEEDS_RESET && sc->sc_flags & SC_DYING) {
  509                                 sc->sc_flags &= ~flag;
  510                                 return;
  511                         }
  512                 }
  513         } while (wokeup > 0);
  514 
  515         if (flag == SC_NEEDS_RESET) {
  516                 int error;
  517 
  518                 DPRINTF(("%s: resetting\n", sc->sc_dev.dv_xname));
  519                 sc->sc_flags &= ~SC_POWERSAVE;
  520                 sc->sc_flags |= SC_NEEDS_FIRMWARE;
  521                 error = pgt_reset(sc);
  522                 if (error == 0) {
  523                         tsleep_nsec(&sc->sc_flags, 0, "pgtres", SEC_TO_NSEC(1));
  524                         if (sc->sc_flags & SC_UNINITIALIZED) {
  525                                 printf("%s: not responding\n",
  526                                     sc->sc_dev.dv_xname);
  527                                 /* Thud.  It was probably removed. */
  528                                 if (tryagain)
  529                                         panic("pgt went for lunch"); /* XXX */
  530                                 tryagain = 1;
  531                         } else {
  532                                 /* await all interrupts */
  533                                 pgt_write_4_flush(sc, PGT_REG_INT_EN,
  534                                     PGT_INT_STAT_SOURCES);      
  535                                 DELAY(PGT_WRITEIO_DELAY);
  536                                 ic->ic_if.if_flags |= IFF_RUNNING;
  537                         }
  538                 }
  539 
  540                 if (tryagain)
  541                         goto trying_again;
  542 
  543                 sc->sc_flags &= ~flag;
  544                 if (ic->ic_if.if_flags & IFF_RUNNING)
  545                         pgt_update_hw_from_sw(sc,
  546                             ic->ic_state != IEEE80211_S_INIT);
  547         }
  548 
  549         ic->ic_if.if_flags &= ~IFF_RUNNING;
  550         ifq_clr_oactive(&ic->ic_if.if_snd);
  551         ieee80211_new_state(&sc->sc_ic, IEEE80211_S_INIT, -1);
  552 }
  553 
  554 void
  555 pgt_attach(struct device *self)
  556 {
  557         struct pgt_softc *sc = (struct pgt_softc *)self;
  558         int error;
  559 
  560         /* debug flags */
  561         //sc->sc_debug |= SC_DEBUG_QUEUES;      /* super verbose */
  562         //sc->sc_debug |= SC_DEBUG_MGMT;
  563         sc->sc_debug |= SC_DEBUG_UNEXPECTED;
  564         //sc->sc_debug |= SC_DEBUG_TRIGGER;     /* verbose */
  565         //sc->sc_debug |= SC_DEBUG_EVENTS;      /* super verbose */
  566         //sc->sc_debug |= SC_DEBUG_POWER;
  567         sc->sc_debug |= SC_DEBUG_TRAP;
  568         sc->sc_debug |= SC_DEBUG_LINK;
  569         //sc->sc_debug |= SC_DEBUG_RXANNEX;
  570         //sc->sc_debug |= SC_DEBUG_RXFRAG;
  571         //sc->sc_debug |= SC_DEBUG_RXETHER;
  572 
  573         /* enable card if possible */
  574         if (sc->sc_enable != NULL)
  575                 (*sc->sc_enable)(sc);
  576 
  577         error = pgt_dma_alloc(sc);
  578         if (error)
  579                 return;
  580 
  581         sc->sc_ic.ic_if.if_softc = sc;
  582         TAILQ_INIT(&sc->sc_mgmtinprog);
  583         TAILQ_INIT(&sc->sc_kthread.sck_traps);
  584         sc->sc_flags |= SC_NEEDS_FIRMWARE | SC_UNINITIALIZED;
  585         sc->sc_80211_ioc_auth = IEEE80211_AUTH_OPEN;
  586 
  587         error = pgt_reset(sc);
  588         if (error)
  589                 return;
  590 
  591         tsleep_nsec(&sc->sc_flags, 0, "pgtres", SEC_TO_NSEC(1));
  592         if (sc->sc_flags & SC_UNINITIALIZED) {
  593                 printf("%s: not responding\n", sc->sc_dev.dv_xname);
  594                 sc->sc_flags |= SC_NEEDS_FIRMWARE;
  595                 return;
  596         } else {
  597                 /* await all interrupts */
  598                 pgt_write_4_flush(sc, PGT_REG_INT_EN, PGT_INT_STAT_SOURCES);
  599                 DELAY(PGT_WRITEIO_DELAY);
  600         }
  601 
  602         error = pgt_net_attach(sc);
  603         if (error)
  604                 return;
  605 
  606         if (kthread_create(pgt_per_device_kthread, sc, NULL,
  607             sc->sc_dev.dv_xname) != 0)
  608                 return;
  609 
  610         ieee80211_new_state(&sc->sc_ic, IEEE80211_S_INIT, -1);
  611 }
  612 
  613 int
  614 pgt_detach(struct pgt_softc *sc)
  615 {
  616         if (sc->sc_flags & SC_NEEDS_FIRMWARE || sc->sc_flags & SC_UNINITIALIZED)
  617                 /* device was not initialized correctly, so leave early */
  618                 goto out;
  619 
  620         /* stop card */
  621         pgt_stop(sc, SC_DYING);
  622         pgt_reboot(sc);
  623 
  624         ieee80211_ifdetach(&sc->sc_ic.ic_if);
  625         if_detach(&sc->sc_ic.ic_if);
  626 
  627 out:
  628         /* disable card if possible */
  629         if (sc->sc_disable != NULL)
  630                 (*sc->sc_disable)(sc);
  631 
  632         pgt_dma_free(sc);
  633 
  634         return (0);
  635 }
  636 
  637 void
  638 pgt_reboot(struct pgt_softc *sc)
  639 {
  640         uint32_t reg;
  641 
  642         reg = pgt_read_4(sc, PGT_REG_CTRL_STAT);
  643         reg &= ~(PGT_CTRL_STAT_RESET | PGT_CTRL_STAT_RAMBOOT);
  644         pgt_write_4(sc, PGT_REG_CTRL_STAT, reg);
  645         pgt_write_memory_barrier(sc);
  646         DELAY(PGT_WRITEIO_DELAY);
  647 
  648         reg |= PGT_CTRL_STAT_RESET;
  649         pgt_write_4(sc, PGT_REG_CTRL_STAT, reg);
  650         pgt_write_memory_barrier(sc);
  651         DELAY(PGT_WRITEIO_DELAY);
  652 
  653         reg &= ~PGT_CTRL_STAT_RESET;
  654         pgt_write_4(sc, PGT_REG_CTRL_STAT, reg);
  655         pgt_write_memory_barrier(sc);
  656         DELAY(PGT_RESET_DELAY);
  657 }
  658 
  659 void
  660 pgt_init_intr(struct pgt_softc *sc)
  661 {
  662         if ((sc->sc_flags & SC_UNINITIALIZED) == 0) {
  663                 if (sc->sc_debug & SC_DEBUG_UNEXPECTED)
  664                         DPRINTF(("%s: spurious initialization\n",
  665                             sc->sc_dev.dv_xname));
  666         } else {
  667                 sc->sc_flags &= ~SC_UNINITIALIZED;
  668                 wakeup(&sc->sc_flags);
  669         }
  670 }
  671 
  672 /*
  673  * If called with a NULL last_nextpkt, only the mgmt queue will be checked
  674  * for new packets.
  675  */
  676 void
  677 pgt_update_intr(struct pgt_softc *sc, int hack)
  678 {
  679         /* priority order */
  680         enum pgt_queue pqs[PGT_QUEUE_COUNT] = {
  681             PGT_QUEUE_MGMT_TX, PGT_QUEUE_MGMT_RX, 
  682             PGT_QUEUE_DATA_HIGH_TX, PGT_QUEUE_DATA_HIGH_RX, 
  683             PGT_QUEUE_DATA_LOW_TX, PGT_QUEUE_DATA_LOW_RX
  684         };
  685         struct mbuf *m;
  686         uint32_t npend;
  687         unsigned int dirtycount;
  688         int i;
  689 
  690         bus_dmamap_sync(sc->sc_dmat, sc->sc_cbdmam, 0,
  691             sc->sc_cbdmam->dm_mapsize,
  692             BUS_DMASYNC_POSTREAD | BUS_DMASYNC_PREWRITE);
  693         pgt_debug_events(sc, "intr");
  694         /*
  695          * Check for completion of tx in their dirty queues.
  696          * Check completion of rx into their dirty queues.
  697          */
  698         for (i = 0; i < PGT_QUEUE_COUNT; i++) {
  699                 size_t qdirty, qfree;
  700 
  701                 qdirty = sc->sc_dirtyq_count[pqs[i]];
  702                 qfree = sc->sc_freeq_count[pqs[i]];
  703                 /*
  704                  * We want the wrap-around here.
  705                  */
  706                 if (pgt_queue_is_rx(pqs[i])) {
  707                         int data;
  708 
  709                         data = pgt_queue_is_data(pqs[i]);
  710 #ifdef PGT_BUGGY_INTERRUPT_RECOVERY
  711                         if (hack && data)
  712                                 continue;
  713 #endif
  714                         npend = pgt_queue_frags_pending(sc, pqs[i]);
  715                         /*
  716                          * Receive queues clean up below, so qdirty must
  717                          * always be 0.
  718                          */
  719                         if (npend > qfree) {
  720                                 if (sc->sc_debug & SC_DEBUG_UNEXPECTED)
  721                                         DPRINTF(("%s: rx queue [%u] "
  722                                             "overflowed by %u\n",
  723                                             sc->sc_dev.dv_xname, pqs[i],
  724                                             npend - qfree));
  725                                 sc->sc_flags |= SC_INTR_RESET;
  726                                 break;
  727                         }
  728                         while (qfree-- > npend)
  729                                 pgt_rxdone(sc, pqs[i]);
  730                 } else {
  731                         npend = pgt_queue_frags_pending(sc, pqs[i]);
  732                         if (npend > qdirty) {
  733                                 if (sc->sc_debug & SC_DEBUG_UNEXPECTED)
  734                                         DPRINTF(("%s: tx queue [%u] "
  735                                             "underflowed by %u\n",
  736                                             sc->sc_dev.dv_xname, pqs[i],
  737                                             npend - qdirty));
  738                                 sc->sc_flags |= SC_INTR_RESET;
  739                                 break;
  740                         }
  741                         /*
  742                          * If the free queue was empty, or the data transmit
  743                          * queue just became empty, wake up any waiters.
  744                          */
  745                         if (qdirty > npend) {
  746                                 if (pgt_queue_is_data(pqs[i])) {
  747                                         sc->sc_ic.ic_if.if_timer = 0;
  748                                         ifq_clr_oactive(
  749                                             &sc->sc_ic.ic_if.if_snd);
  750                                 }
  751                                 while (qdirty-- > npend)
  752                                         pgt_txdone(sc, pqs[i]);
  753                         }
  754                 }
  755         }
  756 
  757         /*
  758          * This is the deferred completion for received management frames
  759          * and where we queue network frames for stack input. 
  760          */
  761         dirtycount = sc->sc_dirtyq_count[PGT_QUEUE_MGMT_RX];
  762         while (!TAILQ_EMPTY(&sc->sc_dirtyq[PGT_QUEUE_MGMT_RX])) {
  763                 struct pgt_mgmt_desc *pmd;
  764 
  765                 pmd = TAILQ_FIRST(&sc->sc_mgmtinprog);
  766                 /*
  767                  * If there is no mgmt request in progress or the operation
  768                  * returned is explicitly a trap, this pmd will essentially
  769                  * be ignored.
  770                  */
  771                 pgt_mgmtrx_completion(sc, pmd);
  772         }
  773         sc->sc_cb->pcb_driver_curfrag[PGT_QUEUE_MGMT_RX] =
  774             htole32(dirtycount +
  775                 letoh32(sc->sc_cb->pcb_driver_curfrag[PGT_QUEUE_MGMT_RX]));
  776 
  777         dirtycount = sc->sc_dirtyq_count[PGT_QUEUE_DATA_HIGH_RX];
  778         while (!TAILQ_EMPTY(&sc->sc_dirtyq[PGT_QUEUE_DATA_HIGH_RX])) {
  779                 if ((m = pgt_datarx_completion(sc, PGT_QUEUE_DATA_HIGH_RX)))
  780                         pgt_input_frames(sc, m);
  781         }
  782         sc->sc_cb->pcb_driver_curfrag[PGT_QUEUE_DATA_HIGH_RX] =
  783             htole32(dirtycount +
  784                 letoh32(sc->sc_cb->pcb_driver_curfrag[PGT_QUEUE_DATA_HIGH_RX]));
  785 
  786         dirtycount = sc->sc_dirtyq_count[PGT_QUEUE_DATA_LOW_RX];
  787         while (!TAILQ_EMPTY(&sc->sc_dirtyq[PGT_QUEUE_DATA_LOW_RX])) {
  788                 if ((m = pgt_datarx_completion(sc, PGT_QUEUE_DATA_LOW_RX)))
  789                         pgt_input_frames(sc, m);
  790         }
  791         sc->sc_cb->pcb_driver_curfrag[PGT_QUEUE_DATA_LOW_RX] =
  792             htole32(dirtycount +
  793                 letoh32(sc->sc_cb->pcb_driver_curfrag[PGT_QUEUE_DATA_LOW_RX]));
  794 
  795         /*
  796          * Write out what we've finished with.
  797          */
  798         bus_dmamap_sync(sc->sc_dmat, sc->sc_cbdmam, 0,
  799             sc->sc_cbdmam->dm_mapsize,
  800             BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_PREREAD);
  801 }
  802 
  803 struct mbuf *
  804 pgt_ieee80211_encap(struct pgt_softc *sc, struct ether_header *eh,
  805     struct mbuf *m, struct ieee80211_node **ni)
  806 {
  807         struct ieee80211com *ic;
  808         struct ieee80211_frame *frame;
  809         struct llc *snap;
  810 
  811         ic = &sc->sc_ic;
  812         if (ni != NULL && ic->ic_opmode == IEEE80211_M_MONITOR) {
  813                 *ni = ieee80211_ref_node(ic->ic_bss);
  814                 (*ni)->ni_inact = 0;
  815                 return (m);
  816         }
  817 
  818         M_PREPEND(m, sizeof(*frame) + sizeof(*snap), M_DONTWAIT);
  819         if (m == NULL)
  820                 return (m);
  821         if (m->m_len < sizeof(*frame) + sizeof(*snap)) {
  822                 m = m_pullup(m, sizeof(*frame) + sizeof(*snap));
  823                 if (m == NULL)
  824                         return (m);
  825         }
  826         frame = mtod(m, struct ieee80211_frame *);
  827         snap = (struct llc *)&frame[1];
  828         if (ni != NULL) {
  829                 if (ic->ic_opmode == IEEE80211_M_STA) {
  830                         *ni = ieee80211_ref_node(ic->ic_bss);
  831                 }
  832 #ifndef IEEE80211_STA_ONLY
  833                 else {
  834                         *ni = ieee80211_find_node(ic, eh->ether_shost);
  835                         /*
  836                          * Make up associations for ad-hoc mode.  To support
  837                          * ad-hoc WPA, we'll need to maintain a bounded
  838                          * pool of ad-hoc stations.
  839                          */
  840                         if (*ni == NULL &&
  841                             ic->ic_opmode != IEEE80211_M_HOSTAP) {
  842                                 *ni = ieee80211_dup_bss(ic, eh->ether_shost);
  843                                 if (*ni != NULL) {
  844                                         (*ni)->ni_associd = 1;
  845                                         ic->ic_newassoc(ic, *ni, 1);
  846                                 }
  847                         }
  848                         if (*ni == NULL) {
  849                                 m_freem(m);
  850                                 return (NULL);
  851                         }
  852                 }
  853 #endif
  854                 (*ni)->ni_inact = 0;
  855         }
  856         snap->llc_dsap = snap->llc_ssap = LLC_SNAP_LSAP;
  857         snap->llc_control = LLC_UI;
  858         snap->llc_snap.org_code[0] = 0;
  859         snap->llc_snap.org_code[1] = 0;
  860         snap->llc_snap.org_code[2] = 0;
  861         snap->llc_snap.ether_type = eh->ether_type;
  862         frame->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_DATA;
  863         /* Doesn't look like much of the 802.11 header is available. */
  864         *(uint16_t *)frame->i_dur = *(uint16_t *)frame->i_seq = 0;
  865         /*
  866          * Translate the addresses; WDS is not handled.
  867          */
  868         switch (ic->ic_opmode) {
  869         case IEEE80211_M_STA:
  870                 frame->i_fc[1] = IEEE80211_FC1_DIR_FROMDS;
  871                 IEEE80211_ADDR_COPY(frame->i_addr1, eh->ether_dhost);
  872                 IEEE80211_ADDR_COPY(frame->i_addr2, ic->ic_bss->ni_bssid);
  873                 IEEE80211_ADDR_COPY(frame->i_addr3, eh->ether_shost);
  874                 break;
  875 #ifndef IEEE80211_STA_ONLY
  876         case IEEE80211_M_IBSS:
  877         case IEEE80211_M_AHDEMO:
  878                 frame->i_fc[1] = IEEE80211_FC1_DIR_NODS;
  879                 IEEE80211_ADDR_COPY(frame->i_addr1, eh->ether_dhost);
  880                 IEEE80211_ADDR_COPY(frame->i_addr2, eh->ether_shost);
  881                 IEEE80211_ADDR_COPY(frame->i_addr3, ic->ic_bss->ni_bssid);
  882                 break;
  883         case IEEE80211_M_HOSTAP:
  884                 /* HostAP forwarding defaults to being done on firmware. */
  885                 frame->i_fc[1] = IEEE80211_FC1_DIR_TODS;
  886                 IEEE80211_ADDR_COPY(frame->i_addr1, ic->ic_bss->ni_bssid);
  887                 IEEE80211_ADDR_COPY(frame->i_addr2, eh->ether_shost);
  888                 IEEE80211_ADDR_COPY(frame->i_addr3, eh->ether_dhost);
  889                 break;
  890 #endif
  891         default:
  892                 break;
  893         }
  894         return (m);
  895 }
  896 
  897 void
  898 pgt_input_frames(struct pgt_softc *sc, struct mbuf *m)
  899 {
  900         struct ether_header eh;
  901         struct mbuf_list ml = MBUF_LIST_INITIALIZER();
  902         struct ifnet *ifp;
  903         struct ieee80211_channel *chan;
  904         struct ieee80211_rxinfo rxi;
  905         struct ieee80211_node *ni;
  906         struct ieee80211com *ic;
  907         struct pgt_rx_annex *pra;
  908         struct pgt_rx_header *pha;
  909         struct mbuf *next;
  910         unsigned int n;
  911         uint32_t rstamp;
  912         uint8_t rssi;
  913 
  914         ic = &sc->sc_ic;
  915         ifp = &ic->ic_if;
  916         for (next = m; m != NULL; m = next) {
  917                 next = m->m_nextpkt;
  918                 m->m_nextpkt = NULL;
  919 
  920                 if (ic->ic_opmode == IEEE80211_M_MONITOR) {
  921                         if (m->m_len < sizeof(*pha)) {
  922                                 m = m_pullup(m, sizeof(*pha));
  923                                 if (m == NULL) {
  924                                         if (sc->sc_debug & SC_DEBUG_UNEXPECTED)
  925                                                 DPRINTF(("%s: m_pullup "
  926                                                     "failure\n",
  927                                                     sc->sc_dev.dv_xname));
  928                                         ifp->if_ierrors++;
  929                                         continue;
  930                                 }
  931                         }
  932                         pha = mtod(m, struct pgt_rx_header *);
  933                         pra = NULL;
  934                         goto input;
  935                 }
  936 
  937                 if (m->m_len < sizeof(*pra)) {
  938                         m = m_pullup(m, sizeof(*pra));
  939                         if (m == NULL) {
  940                                 if (sc->sc_debug & SC_DEBUG_UNEXPECTED)
  941                                         DPRINTF(("%s: m_pullup failure\n",
  942                                             sc->sc_dev.dv_xname));
  943                                 ifp->if_ierrors++;
  944                                 continue;
  945                         }
  946                 }
  947                 pra = mtod(m, struct pgt_rx_annex *);
  948                 pha = &pra->pra_header;
  949                 if (sc->sc_debug & SC_DEBUG_RXANNEX)
  950                         DPRINTF(("%s: rx annex: ? %04x "
  951                             "len %u clock %u flags %02x ? %02x rate %u ? %02x "
  952                             "freq %u ? %04x rssi %u pad %02x%02x%02x\n",
  953                             sc->sc_dev.dv_xname,
  954                             letoh16(pha->pra_unknown0),
  955                             letoh16(pha->pra_length),
  956                             letoh32(pha->pra_clock), pha->pra_flags,
  957                             pha->pra_unknown1, pha->pra_rate,
  958                             pha->pra_unknown2, letoh32(pha->pra_frequency),
  959                             pha->pra_unknown3, pha->pra_rssi,
  960                             pha->pra_pad[0], pha->pra_pad[1], pha->pra_pad[2]));
  961                 if (sc->sc_debug & SC_DEBUG_RXETHER)
  962                         DPRINTF(("%s: rx ether: %s < %s 0x%04x\n",
  963                             sc->sc_dev.dv_xname,
  964                             ether_sprintf(pra->pra_ether_dhost),
  965                             ether_sprintf(pra->pra_ether_shost),
  966                             ntohs(pra->pra_ether_type)));
  967 
  968                 memcpy(eh.ether_dhost, pra->pra_ether_dhost, ETHER_ADDR_LEN);
  969                 memcpy(eh.ether_shost, pra->pra_ether_shost, ETHER_ADDR_LEN);
  970                 eh.ether_type = pra->pra_ether_type;
  971 
  972 input:
  973                 /*
  974                  * This flag is set if e.g. packet could not be decrypted.
  975                  */
  976                 if (pha->pra_flags & PRA_FLAG_BAD) {
  977                         ifp->if_ierrors++;
  978                         m_freem(m);
  979                         continue;
  980                 }
  981 
  982                 /*
  983                  * After getting what we want, chop off the annex, then
  984                  * turn into something that looks like it really was
  985                  * 802.11.
  986                  */
  987                 rssi = pha->pra_rssi;
  988                 rstamp = letoh32(pha->pra_clock);
  989                 n = ieee80211_mhz2ieee(letoh32(pha->pra_frequency), 0);
  990                 if (n <= IEEE80211_CHAN_MAX)
  991                         chan = &ic->ic_channels[n];
  992                 else
  993                         chan = ic->ic_bss->ni_chan;
  994                 /* Send to 802.3 listeners. */
  995                 if (pra) {
  996                         m_adj(m, sizeof(*pra));
  997                 } else
  998                         m_adj(m, sizeof(*pha));
  999 
 1000                 m = pgt_ieee80211_encap(sc, &eh, m, &ni);
 1001                 if (m != NULL) {
 1002 #if NBPFILTER > 0
 1003                         if (sc->sc_drvbpf != NULL) {
 1004                                 struct mbuf mb;
 1005                                 struct pgt_rx_radiotap_hdr *tap = &sc->sc_rxtap;
 1006 
 1007                                 tap->wr_flags = 0;
 1008                                 tap->wr_chan_freq = htole16(chan->ic_freq);
 1009                                 tap->wr_chan_flags = htole16(chan->ic_flags);
 1010                                 tap->wr_rssi = rssi;
 1011                                 tap->wr_max_rssi = ic->ic_max_rssi;
 1012 
 1013                                 mb.m_data = (caddr_t)tap;
 1014                                 mb.m_len = sc->sc_rxtap_len;
 1015                                 mb.m_next = m;
 1016                                 mb.m_nextpkt = NULL;
 1017                                 mb.m_type = 0;
 1018                                 mb.m_flags = 0;
 1019                                 bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_IN);
 1020                         }
 1021 #endif
 1022                         memset(&rxi, 0, sizeof(rxi));
 1023                         ni->ni_rssi = rxi.rxi_rssi = rssi;
 1024                         ni->ni_rstamp = rxi.rxi_tstamp = rstamp;
 1025                         ieee80211_inputm(ifp, m, ni, &rxi, &ml);
 1026                         /*
 1027                          * The frame may have caused the node to be marked for
 1028                          * reclamation (e.g. in response to a DEAUTH message)
 1029                          * so use free_node here instead of unref_node.
 1030                          */
 1031                         if (ni == ic->ic_bss)
 1032                                 ieee80211_unref_node(&ni);
 1033                         else
 1034                                 ieee80211_release_node(&sc->sc_ic, ni);
 1035                 } else {
 1036                         ifp->if_ierrors++;
 1037                 }
 1038         }
 1039         if_input(ifp, &ml);
 1040 }
 1041 
 1042 void
 1043 pgt_wakeup_intr(struct pgt_softc *sc)
 1044 {
 1045         int shouldupdate;
 1046         int i;
 1047 
 1048         shouldupdate = 0;
 1049         /* Check for any queues being empty before updating. */
 1050         bus_dmamap_sync(sc->sc_dmat, sc->sc_cbdmam, 0,
 1051             sc->sc_cbdmam->dm_mapsize,
 1052             BUS_DMASYNC_POSTREAD);
 1053         for (i = 0; !shouldupdate && i < PGT_QUEUE_COUNT; i++) {
 1054                 if (pgt_queue_is_tx(i))
 1055                         shouldupdate = pgt_queue_frags_pending(sc, i);
 1056                 else
 1057                         shouldupdate = pgt_queue_frags_pending(sc, i) <
 1058                             sc->sc_freeq_count[i];
 1059         }
 1060         if (!TAILQ_EMPTY(&sc->sc_mgmtinprog))
 1061                 shouldupdate = 1;
 1062         if (sc->sc_debug & SC_DEBUG_POWER)
 1063                 DPRINTF(("%s: wakeup interrupt (update = %d)\n",
 1064                     sc->sc_dev.dv_xname, shouldupdate));
 1065         sc->sc_flags &= ~SC_POWERSAVE;
 1066         if (shouldupdate) {
 1067                 pgt_write_4_flush(sc, PGT_REG_DEV_INT, PGT_DEV_INT_UPDATE);
 1068                 DELAY(PGT_WRITEIO_DELAY);
 1069         }
 1070 }
 1071 
 1072 void
 1073 pgt_sleep_intr(struct pgt_softc *sc)
 1074 {
 1075         int allowed;
 1076         int i;
 1077 
 1078         allowed = 1;
 1079         /* Check for any queues not being empty before allowing. */
 1080         bus_dmamap_sync(sc->sc_dmat, sc->sc_cbdmam, 0,
 1081             sc->sc_cbdmam->dm_mapsize,
 1082             BUS_DMASYNC_POSTREAD);
 1083         for (i = 0; allowed && i < PGT_QUEUE_COUNT; i++) {
 1084                 if (pgt_queue_is_tx(i))
 1085                         allowed = pgt_queue_frags_pending(sc, i) == 0;
 1086                 else
 1087                         allowed = pgt_queue_frags_pending(sc, i) >=
 1088                             sc->sc_freeq_count[i];
 1089         }
 1090         if (!TAILQ_EMPTY(&sc->sc_mgmtinprog))
 1091                 allowed = 0;
 1092         if (sc->sc_debug & SC_DEBUG_POWER)
 1093                 DPRINTF(("%s: sleep interrupt (allowed = %d)\n",
 1094                     sc->sc_dev.dv_xname, allowed));
 1095         if (allowed && sc->sc_ic.ic_flags & IEEE80211_F_PMGTON) {
 1096                 sc->sc_flags |= SC_POWERSAVE;
 1097                 pgt_write_4_flush(sc, PGT_REG_DEV_INT, PGT_DEV_INT_SLEEP);
 1098                 DELAY(PGT_WRITEIO_DELAY);
 1099         }
 1100 }
 1101 
 1102 void
 1103 pgt_empty_traps(struct pgt_softc_kthread *sck)
 1104 {
 1105         struct pgt_async_trap *pa;
 1106         struct mbuf *m;
 1107 
 1108         while (!TAILQ_EMPTY(&sck->sck_traps)) {
 1109                 pa = TAILQ_FIRST(&sck->sck_traps);
 1110                 TAILQ_REMOVE(&sck->sck_traps, pa, pa_link);
 1111                 m = pa->pa_mbuf;
 1112                 m_freem(m);
 1113         }
 1114 }
 1115 
 1116 void
 1117 pgt_per_device_kthread(void *argp)
 1118 {
 1119         struct pgt_softc *sc;
 1120         struct pgt_softc_kthread *sck;
 1121         struct pgt_async_trap *pa;
 1122         struct mbuf *m;
 1123         int s;
 1124 
 1125         sc = argp;
 1126         sck = &sc->sc_kthread;
 1127         while (!sck->sck_exit) {
 1128                 if (!sck->sck_update && !sck->sck_reset &&
 1129                     TAILQ_EMPTY(&sck->sck_traps))
 1130                         tsleep_nsec(&sc->sc_kthread, 0, "pgtkth", INFSLP);
 1131                 if (sck->sck_reset) {
 1132                         DPRINTF(("%s: [thread] async reset\n",
 1133                             sc->sc_dev.dv_xname));
 1134                         sck->sck_reset = 0;
 1135                         sck->sck_update = 0;
 1136                         pgt_empty_traps(sck);
 1137                         s = splnet();
 1138                         pgt_stop(sc, SC_NEEDS_RESET);
 1139                         splx(s);
 1140                 } else if (!TAILQ_EMPTY(&sck->sck_traps)) {
 1141                         DPRINTF(("%s: [thread] got a trap\n",
 1142                             sc->sc_dev.dv_xname));
 1143                         pa = TAILQ_FIRST(&sck->sck_traps);
 1144                         TAILQ_REMOVE(&sck->sck_traps, pa, pa_link);
 1145                         m = pa->pa_mbuf;
 1146                         m_adj(m, sizeof(*pa));
 1147                         pgt_update_sw_from_hw(sc, pa, m);
 1148                         m_freem(m);
 1149                 } else if (sck->sck_update) {
 1150                         sck->sck_update = 0;
 1151                         pgt_update_sw_from_hw(sc, NULL, NULL);
 1152                 }
 1153         }
 1154         pgt_empty_traps(sck);
 1155         kthread_exit(0);
 1156 }
 1157 
 1158 void
 1159 pgt_async_reset(struct pgt_softc *sc)
 1160 {
 1161         if (sc->sc_flags & (SC_DYING | SC_NEEDS_RESET))
 1162                 return;
 1163         sc->sc_kthread.sck_reset = 1;
 1164         wakeup(&sc->sc_kthread);
 1165 }
 1166 
 1167 void
 1168 pgt_async_update(struct pgt_softc *sc)
 1169 {
 1170         if (sc->sc_flags & SC_DYING)
 1171                 return;
 1172         sc->sc_kthread.sck_update = 1;
 1173         wakeup(&sc->sc_kthread);
 1174 }
 1175 
 1176 int
 1177 pgt_intr(void *arg)
 1178 {
 1179         struct pgt_softc *sc;
 1180         struct ifnet *ifp;
 1181         u_int32_t reg;
 1182 
 1183         sc = arg;
 1184         ifp = &sc->sc_ic.ic_if;
 1185 
 1186         /*
 1187          * Here the Linux driver ands in the value of the INT_EN register,
 1188          * and masks off everything but the documented interrupt bits.  Why?
 1189          *
 1190          * Unknown bit 0x4000 is set upon initialization, 0x8000000 some
 1191          * other times.
 1192          */
 1193         if (sc->sc_ic.ic_flags & IEEE80211_F_PMGTON &&
 1194             sc->sc_flags & SC_POWERSAVE) {
 1195                 /*
 1196                  * Don't try handling the interrupt in sleep mode.
 1197                  */
 1198                 reg = pgt_read_4(sc, PGT_REG_CTRL_STAT);
 1199                 if (reg & PGT_CTRL_STAT_SLEEPMODE)
 1200                         return (0);
 1201         }
 1202         reg = pgt_read_4(sc, PGT_REG_INT_STAT);
 1203         if (reg == 0)
 1204                 return (0); /* This interrupt is not from us */
 1205 
 1206         pgt_write_4_flush(sc, PGT_REG_INT_ACK, reg);
 1207         if (reg & PGT_INT_STAT_INIT)
 1208                 pgt_init_intr(sc);
 1209         if (reg & PGT_INT_STAT_UPDATE) {
 1210                 pgt_update_intr(sc, 0);
 1211                 /*
 1212                  * If we got an update, it's not really asleep.
 1213                  */
 1214                 sc->sc_flags &= ~SC_POWERSAVE;
 1215                 /*
 1216                  * Pretend I have any idea what the documentation
 1217                  * would say, and just give it a shot sending an
 1218                  * "update" after acknowledging the interrupt
 1219                  * bits and writing out the new control block.
 1220                  */
 1221                 pgt_write_4_flush(sc, PGT_REG_DEV_INT, PGT_DEV_INT_UPDATE);
 1222                 DELAY(PGT_WRITEIO_DELAY);
 1223         }
 1224         if (reg & PGT_INT_STAT_SLEEP && !(reg & PGT_INT_STAT_WAKEUP))
 1225                 pgt_sleep_intr(sc);
 1226         if (reg & PGT_INT_STAT_WAKEUP)
 1227                 pgt_wakeup_intr(sc);
 1228 
 1229         if (sc->sc_flags & SC_INTR_RESET) {
 1230                 sc->sc_flags &= ~SC_INTR_RESET;
 1231                 pgt_async_reset(sc);
 1232         }
 1233 
 1234         if (reg & ~PGT_INT_STAT_SOURCES && sc->sc_debug & SC_DEBUG_UNEXPECTED) {
 1235                 DPRINTF(("%s: unknown interrupt bits %#x (stat %#x)\n",
 1236                     sc->sc_dev.dv_xname,
 1237                     reg & ~PGT_INT_STAT_SOURCES,
 1238                     pgt_read_4(sc, PGT_REG_CTRL_STAT)));
 1239         }
 1240 
 1241         if (!ifq_empty(&ifp->if_snd))
 1242                 pgt_start(ifp);
 1243 
 1244         return (1);
 1245 }
 1246 
 1247 void
 1248 pgt_txdone(struct pgt_softc *sc, enum pgt_queue pq)
 1249 {
 1250         struct pgt_desc *pd;
 1251 
 1252         pd = TAILQ_FIRST(&sc->sc_dirtyq[pq]);
 1253         TAILQ_REMOVE(&sc->sc_dirtyq[pq], pd, pd_link);
 1254         sc->sc_dirtyq_count[pq]--;
 1255         TAILQ_INSERT_TAIL(&sc->sc_freeq[pq], pd, pd_link);
 1256         sc->sc_freeq_count[pq]++;
 1257         bus_dmamap_sync(sc->sc_dmat, pd->pd_dmam, 0,
 1258             pd->pd_dmam->dm_mapsize,
 1259             BUS_DMASYNC_POSTREAD);
 1260         /* Management frames want completion information. */
 1261         if (sc->sc_debug & SC_DEBUG_QUEUES) {
 1262                 DPRINTF(("%s: queue: tx %u <- [%u]\n",
 1263                     sc->sc_dev.dv_xname, pd->pd_fragnum, pq));
 1264                 if (sc->sc_debug & SC_DEBUG_MGMT && pgt_queue_is_mgmt(pq)) {
 1265                         struct pgt_mgmt_frame *pmf;
 1266 
 1267                         pmf = (struct pgt_mgmt_frame *)pd->pd_mem;
 1268                         DPRINTF(("%s: queue: txmgmt %p <- "
 1269                             "(ver %u, op %u, flags %#x)\n",
 1270                             sc->sc_dev.dv_xname,
 1271                             pd, pmf->pmf_version, pmf->pmf_operation,
 1272                             pmf->pmf_flags));
 1273                 }
 1274         }
 1275         pgt_unload_tx_desc_frag(sc, pd);
 1276 }
 1277 
 1278 void
 1279 pgt_rxdone(struct pgt_softc *sc, enum pgt_queue pq)
 1280 {
 1281         struct pgt_desc *pd;
 1282 
 1283         pd = TAILQ_FIRST(&sc->sc_freeq[pq]);
 1284         TAILQ_REMOVE(&sc->sc_freeq[pq], pd, pd_link);
 1285         sc->sc_freeq_count[pq]--;
 1286         TAILQ_INSERT_TAIL(&sc->sc_dirtyq[pq], pd, pd_link);
 1287         sc->sc_dirtyq_count[pq]++;
 1288         bus_dmamap_sync(sc->sc_dmat, pd->pd_dmam, 0,
 1289             pd->pd_dmam->dm_mapsize,
 1290             BUS_DMASYNC_POSTREAD);
 1291         if (sc->sc_debug & SC_DEBUG_QUEUES)
 1292                 DPRINTF(("%s: queue: rx %u <- [%u]\n",
 1293                     sc->sc_dev.dv_xname, pd->pd_fragnum, pq));
 1294         if (sc->sc_debug & SC_DEBUG_UNEXPECTED &&
 1295             pd->pd_fragp->pf_flags & ~htole16(PF_FLAG_MF))
 1296                 DPRINTF(("%s: unknown flags on rx [%u]: %#x\n",
 1297                     sc->sc_dev.dv_xname, pq, letoh16(pd->pd_fragp->pf_flags)));
 1298 }
 1299 
 1300 /*
 1301  * Traps are generally used for the firmware to report changes in state
 1302  * back to the host.  Mostly this processes changes in link state, but
 1303  * it needs to also be used to initiate WPA and other authentication
 1304  * schemes in terms of client (station) or server (access point).
 1305  */
 1306 void
 1307 pgt_trap_received(struct pgt_softc *sc, uint32_t oid, void *trapdata,
 1308     size_t size)
 1309 {
 1310         struct pgt_async_trap *pa;
 1311         struct mbuf *m;
 1312         char *p;
 1313         size_t total;
 1314 
 1315         if (sc->sc_flags & SC_DYING)
 1316                 return;
 1317 
 1318         total = sizeof(oid) + size + sizeof(struct pgt_async_trap);
 1319         if (total > MLEN) {
 1320                 MGETHDR(m, M_DONTWAIT, MT_DATA);
 1321                 if (m == NULL)
 1322                         return;
 1323                 MCLGET(m, M_DONTWAIT);
 1324                 if (!(m->m_flags & M_EXT)) {
 1325                         m_freem(m);
 1326                         m = NULL;
 1327                 }
 1328         } else
 1329                 m = m_get(M_DONTWAIT, MT_DATA);
 1330 
 1331         if (m == NULL)
 1332                 return;
 1333         else
 1334                 m->m_len = total;
 1335 
 1336         pa = mtod(m, struct pgt_async_trap *);
 1337         p = mtod(m, char *) + sizeof(*pa);
 1338         *(uint32_t *)p = oid;
 1339         p += sizeof(uint32_t);
 1340         memcpy(p, trapdata, size);
 1341         pa->pa_mbuf = m;
 1342 
 1343         TAILQ_INSERT_TAIL(&sc->sc_kthread.sck_traps, pa, pa_link);
 1344         wakeup(&sc->sc_kthread);
 1345 }
 1346 
 1347 /*
 1348  * Process a completed management response (all requests should be
 1349  * responded to, quickly) or an event (trap).
 1350  */
 1351 void
 1352 pgt_mgmtrx_completion(struct pgt_softc *sc, struct pgt_mgmt_desc *pmd)
 1353 {
 1354         struct pgt_desc *pd;
 1355         struct pgt_mgmt_frame *pmf;
 1356         uint32_t oid, size;
 1357 
 1358         pd = TAILQ_FIRST(&sc->sc_dirtyq[PGT_QUEUE_MGMT_RX]);
 1359         TAILQ_REMOVE(&sc->sc_dirtyq[PGT_QUEUE_MGMT_RX], pd, pd_link);
 1360         sc->sc_dirtyq_count[PGT_QUEUE_MGMT_RX]--;
 1361         TAILQ_INSERT_TAIL(&sc->sc_freeq[PGT_QUEUE_MGMT_RX],
 1362             pd, pd_link);
 1363         sc->sc_freeq_count[PGT_QUEUE_MGMT_RX]++;
 1364         if (letoh16(pd->pd_fragp->pf_size) < sizeof(*pmf)) {
 1365                 if (sc->sc_debug & SC_DEBUG_UNEXPECTED)
 1366                         DPRINTF(("%s: mgmt desc too small: %u\n",
 1367                             sc->sc_dev.dv_xname,
 1368                             letoh16(pd->pd_fragp->pf_size)));
 1369                 goto out_nopmd;
 1370         }
 1371         pmf = (struct pgt_mgmt_frame *)pd->pd_mem;
 1372         if (pmf->pmf_version != PMF_VER) {
 1373                 if (sc->sc_debug & SC_DEBUG_UNEXPECTED)
 1374                         DPRINTF(("%s: unknown mgmt version %u\n",
 1375                             sc->sc_dev.dv_xname, pmf->pmf_version));
 1376                 goto out_nopmd;
 1377         }
 1378         if (pmf->pmf_device != PMF_DEV) {
 1379                 if (sc->sc_debug & SC_DEBUG_UNEXPECTED)
 1380                         DPRINTF(("%s: unknown mgmt dev %u\n",
 1381                             sc->sc_dev.dv_xname, pmf->pmf_device));
 1382                 goto out;
 1383         }
 1384         if (pmf->pmf_flags & ~PMF_FLAG_VALID) {
 1385                 if (sc->sc_debug & SC_DEBUG_UNEXPECTED)
 1386                         DPRINTF(("%s: unknown mgmt flags %x\n",
 1387                             sc->sc_dev.dv_xname,
 1388                             pmf->pmf_flags & ~PMF_FLAG_VALID));
 1389                 goto out;
 1390         }
 1391         if (pmf->pmf_flags & PMF_FLAG_LE) {
 1392                 oid = letoh32(pmf->pmf_oid);
 1393                 size = letoh32(pmf->pmf_size);
 1394         } else {
 1395                 oid = betoh32(pmf->pmf_oid);
 1396                 size = betoh32(pmf->pmf_size);
 1397         }
 1398         if (pmf->pmf_operation == PMF_OP_TRAP) {
 1399                 pmd = NULL; /* ignored */
 1400                 DPRINTF(("%s: mgmt trap received (op %u, oid %#x, len %u)\n",
 1401                     sc->sc_dev.dv_xname,
 1402                     pmf->pmf_operation, oid, size));
 1403                 pgt_trap_received(sc, oid, (char *)pmf + sizeof(*pmf),
 1404                     min(size, PGT_FRAG_SIZE - sizeof(*pmf)));
 1405                 goto out_nopmd;
 1406         }
 1407         if (pmd == NULL) {
 1408                 if (sc->sc_debug & (SC_DEBUG_UNEXPECTED | SC_DEBUG_MGMT))
 1409                         DPRINTF(("%s: spurious mgmt received "
 1410                             "(op %u, oid %#x, len %u)\n", sc->sc_dev.dv_xname,
 1411                             pmf->pmf_operation, oid, size));
 1412                 goto out_nopmd;
 1413         }
 1414         switch (pmf->pmf_operation) {
 1415         case PMF_OP_RESPONSE:
 1416                 pmd->pmd_error = 0;
 1417                 break;
 1418         case PMF_OP_ERROR:
 1419                 pmd->pmd_error = EPERM;
 1420                 goto out;
 1421         default:
 1422                 if (sc->sc_debug & SC_DEBUG_UNEXPECTED)
 1423                         DPRINTF(("%s: unknown mgmt op %u\n",
 1424                             sc->sc_dev.dv_xname, pmf->pmf_operation));
 1425                 pmd->pmd_error = EIO;
 1426                 goto out;
 1427         }
 1428         if (oid != pmd->pmd_oid) {
 1429                 if (sc->sc_debug & SC_DEBUG_UNEXPECTED)
 1430                         DPRINTF(("%s: mgmt oid changed from %#x -> %#x\n",
 1431                             sc->sc_dev.dv_xname, pmd->pmd_oid, oid));
 1432                 pmd->pmd_oid = oid;
 1433         }
 1434         if (pmd->pmd_recvbuf != NULL) {
 1435                 if (size > PGT_FRAG_SIZE) {
 1436                         if (sc->sc_debug & SC_DEBUG_UNEXPECTED)
 1437                                 DPRINTF(("%s: mgmt oid %#x has bad size %u\n",
 1438                                     sc->sc_dev.dv_xname, oid, size));
 1439                         pmd->pmd_error = EIO;
 1440                         goto out;
 1441                 }
 1442                 if (size > pmd->pmd_len)
 1443                         pmd->pmd_error = ENOMEM;
 1444                 else
 1445                         memcpy(pmd->pmd_recvbuf, (char *)pmf + sizeof(*pmf),
 1446                             size);
 1447                 pmd->pmd_len = size;
 1448         }
 1449 
 1450 out:
 1451         TAILQ_REMOVE(&sc->sc_mgmtinprog, pmd, pmd_link);
 1452         wakeup_one(pmd);
 1453         if (sc->sc_debug & SC_DEBUG_MGMT)
 1454                 DPRINTF(("%s: queue: mgmt %p <- (op %u, oid %#x, len %u)\n",
 1455                     sc->sc_dev.dv_xname, pmd, pmf->pmf_operation,
 1456                     pmd->pmd_oid, pmd->pmd_len));
 1457 out_nopmd:
 1458         pgt_reinit_rx_desc_frag(sc, pd);
 1459 }
 1460 
 1461 /*
 1462  * Queue packets for reception and defragmentation.  I don't know now
 1463  * whether the rx queue being full enough to start, but not finish,
 1464  * queueing a fragmented packet, can happen.
 1465  */
 1466 struct mbuf *
 1467 pgt_datarx_completion(struct pgt_softc *sc, enum pgt_queue pq)
 1468 {
 1469         struct ifnet *ifp;
 1470         struct pgt_desc *pd;
 1471         struct mbuf *top, **mp, *m;
 1472         size_t datalen;
 1473         uint16_t morefrags, dataoff;
 1474         int tlen = 0;
 1475 
 1476         ifp = &sc->sc_ic.ic_if;
 1477         m = NULL;
 1478         top = NULL;
 1479         mp = &top;
 1480 
 1481         while ((pd = TAILQ_FIRST(&sc->sc_dirtyq[pq])) != NULL) {
 1482                 TAILQ_REMOVE(&sc->sc_dirtyq[pq], pd, pd_link);
 1483                 sc->sc_dirtyq_count[pq]--;
 1484                 datalen = letoh16(pd->pd_fragp->pf_size);
 1485                 dataoff = letoh32(pd->pd_fragp->pf_addr) - pd->pd_dmaaddr;
 1486                 morefrags = pd->pd_fragp->pf_flags & htole16(PF_FLAG_MF);
 1487 
 1488                 if (sc->sc_debug & SC_DEBUG_RXFRAG)
 1489                         DPRINTF(("%s: rx frag: len %u memoff %u flags %x\n",
 1490                             sc->sc_dev.dv_xname, datalen, dataoff,
 1491                             pd->pd_fragp->pf_flags));
 1492 
 1493                 /* Add the (two+?) bytes for the header. */
 1494                 if (datalen + dataoff > PGT_FRAG_SIZE) {
 1495                         if (sc->sc_debug & SC_DEBUG_UNEXPECTED)
 1496                                 DPRINTF(("%s data rx too big: %u\n",
 1497                                     sc->sc_dev.dv_xname, datalen));
 1498                         goto fail;
 1499                 }
 1500 
 1501                 if (m == NULL)
 1502                         MGETHDR(m, M_DONTWAIT, MT_DATA);
 1503                 else
 1504                         m = m_get(M_DONTWAIT, MT_DATA);
 1505 
 1506                 if (m == NULL)
 1507                         goto fail;
 1508                 if (datalen > MHLEN) {
 1509                         MCLGET(m, M_DONTWAIT);
 1510                         if (!(m->m_flags & M_EXT)) {
 1511                                 m_free(m);
 1512                                 goto fail;
 1513                         }
 1514                 }
 1515                 bcopy(pd->pd_mem + dataoff, mtod(m, char *), datalen);
 1516                 m->m_len = datalen;
 1517                 tlen += datalen;
 1518 
 1519                 *mp = m;
 1520                 mp = &m->m_next;
 1521 
 1522                 TAILQ_INSERT_TAIL(&sc->sc_freeq[pq], pd, pd_link);
 1523                 sc->sc_freeq_count[pq]++;
 1524                 pgt_reinit_rx_desc_frag(sc, pd);
 1525 
 1526                 if (!morefrags)
 1527                         break;
 1528         }
 1529 
 1530         if (top) {
 1531                 top->m_pkthdr.len = tlen;
 1532         }
 1533         return (top);
 1534 
 1535 fail:
 1536         TAILQ_INSERT_TAIL(&sc->sc_freeq[pq], pd, pd_link);
 1537         sc->sc_freeq_count[pq]++;
 1538         pgt_reinit_rx_desc_frag(sc, pd);
 1539 
 1540         ifp->if_ierrors++;
 1541         m_freem(top);
 1542         return (NULL);
 1543 }
 1544 
 1545 int
 1546 pgt_oid_get(struct pgt_softc *sc, enum pgt_oid oid,
 1547     void *arg, size_t arglen)
 1548 {
 1549         struct pgt_mgmt_desc pmd;
 1550         int error;
 1551 
 1552         bzero(&pmd, sizeof(pmd));
 1553         pmd.pmd_recvbuf = arg;
 1554         pmd.pmd_len = arglen;
 1555         pmd.pmd_oid = oid;
 1556 
 1557         error = pgt_mgmt_request(sc, &pmd);
 1558         if (error == 0)
 1559                 error = pmd.pmd_error;
 1560         if (error != 0 && error != EPERM && sc->sc_debug & SC_DEBUG_UNEXPECTED)
 1561                 DPRINTF(("%s: failure getting oid %#x: %d\n",
 1562                     sc->sc_dev.dv_xname, oid, error));
 1563 
 1564         return (error);
 1565 }
 1566 
 1567 int
 1568 pgt_oid_retrieve(struct pgt_softc *sc, enum pgt_oid oid,
 1569     void *arg, size_t arglen)
 1570 {
 1571         struct pgt_mgmt_desc pmd;
 1572         int error;
 1573 
 1574         bzero(&pmd, sizeof(pmd));
 1575         pmd.pmd_sendbuf = arg;
 1576         pmd.pmd_recvbuf = arg;
 1577         pmd.pmd_len = arglen;
 1578         pmd.pmd_oid = oid;
 1579 
 1580         error = pgt_mgmt_request(sc, &pmd);
 1581         if (error == 0)
 1582                 error = pmd.pmd_error;
 1583         if (error != 0 && error != EPERM && sc->sc_debug & SC_DEBUG_UNEXPECTED)
 1584                 DPRINTF(("%s: failure retrieving oid %#x: %d\n",
 1585                     sc->sc_dev.dv_xname, oid, error));
 1586 
 1587         return (error);
 1588 }
 1589 
 1590 int
 1591 pgt_oid_set(struct pgt_softc *sc, enum pgt_oid oid,
 1592     const void *arg, size_t arglen)
 1593 {
 1594         struct pgt_mgmt_desc pmd;
 1595         int error;
 1596 
 1597         bzero(&pmd, sizeof(pmd));
 1598         pmd.pmd_sendbuf = arg;
 1599         pmd.pmd_len = arglen;
 1600         pmd.pmd_oid = oid;
 1601 
 1602         error = pgt_mgmt_request(sc, &pmd);
 1603         if (error == 0)
 1604                 error = pmd.pmd_error;
 1605         if (error != 0 && error != EPERM && sc->sc_debug & SC_DEBUG_UNEXPECTED)
 1606                 DPRINTF(("%s: failure setting oid %#x: %d\n",
 1607                     sc->sc_dev.dv_xname, oid, error));
 1608 
 1609         return (error);
 1610 }
 1611 
 1612 void
 1613 pgt_state_dump(struct pgt_softc *sc)
 1614 {
 1615         printf("%s: state dump: control 0x%08x interrupt 0x%08x\n",
 1616             sc->sc_dev.dv_xname,
 1617             pgt_read_4(sc, PGT_REG_CTRL_STAT),
 1618             pgt_read_4(sc, PGT_REG_INT_STAT));
 1619 
 1620         printf("%s: state dump: driver curfrag[]\n",
 1621             sc->sc_dev.dv_xname);
 1622 
 1623         printf("%s: 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n",
 1624             sc->sc_dev.dv_xname,
 1625             letoh32(sc->sc_cb->pcb_driver_curfrag[0]),
 1626             letoh32(sc->sc_cb->pcb_driver_curfrag[1]),
 1627             letoh32(sc->sc_cb->pcb_driver_curfrag[2]),
 1628             letoh32(sc->sc_cb->pcb_driver_curfrag[3]),
 1629             letoh32(sc->sc_cb->pcb_driver_curfrag[4]),
 1630             letoh32(sc->sc_cb->pcb_driver_curfrag[5]));
 1631 
 1632         printf("%s: state dump: device curfrag[]\n",
 1633             sc->sc_dev.dv_xname);
 1634 
 1635         printf("%s: 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n",
 1636             sc->sc_dev.dv_xname,
 1637             letoh32(sc->sc_cb->pcb_device_curfrag[0]),
 1638             letoh32(sc->sc_cb->pcb_device_curfrag[1]),
 1639             letoh32(sc->sc_cb->pcb_device_curfrag[2]),
 1640             letoh32(sc->sc_cb->pcb_device_curfrag[3]),
 1641             letoh32(sc->sc_cb->pcb_device_curfrag[4]),
 1642             letoh32(sc->sc_cb->pcb_device_curfrag[5]));
 1643 }
 1644 
 1645 int
 1646 pgt_mgmt_request(struct pgt_softc *sc, struct pgt_mgmt_desc *pmd)
 1647 {
 1648         struct pgt_desc *pd;
 1649         struct pgt_mgmt_frame *pmf;
 1650         int error, i, ret;
 1651 
 1652         if (sc->sc_flags & (SC_DYING | SC_NEEDS_RESET))
 1653                 return (EIO);
 1654         if (pmd->pmd_len > PGT_FRAG_SIZE - sizeof(*pmf))
 1655                 return (ENOMEM);
 1656         pd = TAILQ_FIRST(&sc->sc_freeq[PGT_QUEUE_MGMT_TX]);
 1657         if (pd == NULL)
 1658                 return (ENOMEM);
 1659         error = pgt_load_tx_desc_frag(sc, PGT_QUEUE_MGMT_TX, pd);
 1660         if (error)
 1661                 return (error);
 1662         pmf = (struct pgt_mgmt_frame *)pd->pd_mem;
 1663         pmf->pmf_version = PMF_VER;
 1664         /* "get" and "retrieve" operations look the same */
 1665         if (pmd->pmd_recvbuf != NULL)
 1666                 pmf->pmf_operation = PMF_OP_GET;
 1667         else
 1668                 pmf->pmf_operation = PMF_OP_SET;
 1669         pmf->pmf_oid = htobe32(pmd->pmd_oid);
 1670         pmf->pmf_device = PMF_DEV;
 1671         pmf->pmf_flags = 0;
 1672         pmf->pmf_size = htobe32(pmd->pmd_len);
 1673         /* "set" and "retrieve" operations both send data */
 1674         if (pmd->pmd_sendbuf != NULL)
 1675                 memcpy(pmf + 1, pmd->pmd_sendbuf, pmd->pmd_len);
 1676         else
 1677                 bzero(pmf + 1, pmd->pmd_len);
 1678         pmd->pmd_error = EINPROGRESS;
 1679         TAILQ_INSERT_TAIL(&sc->sc_mgmtinprog, pmd, pmd_link);
 1680         if (sc->sc_debug & SC_DEBUG_MGMT)
 1681                 DPRINTF(("%s: queue: mgmt %p -> (op %u, oid %#x, len %u)\n",
 1682                     sc->sc_dev.dv_xname,
 1683                     pmd, pmf->pmf_operation,
 1684                     pmd->pmd_oid, pmd->pmd_len));
 1685         pgt_desc_transmit(sc, PGT_QUEUE_MGMT_TX, pd,
 1686             sizeof(*pmf) + pmd->pmd_len, 0);
 1687         /*
 1688          * Try for one second, triggering 10 times.
 1689          *
 1690          * Do our best to work around seemingly buggy CardBus controllers
 1691          * on Soekris 4521 that fail to get interrupts with alarming
 1692          * regularity: run as if an interrupt occurred and service every
 1693          * queue except for mbuf reception.
 1694          */
 1695         i = 0;
 1696         do {
 1697                 ret = tsleep_nsec(pmd, 0, "pgtmgm", MSEC_TO_NSEC(100));
 1698                 if (ret != EWOULDBLOCK)
 1699                         break;
 1700                 if (pmd->pmd_error != EINPROGRESS)
 1701                         break;
 1702                 if (sc->sc_flags & (SC_DYING | SC_NEEDS_RESET)) {
 1703                         pmd->pmd_error = EIO;
 1704                         TAILQ_REMOVE(&sc->sc_mgmtinprog, pmd, pmd_link);
 1705                         break;
 1706                 }
 1707                 if (i != 9)
 1708                         pgt_maybe_trigger(sc, PGT_QUEUE_MGMT_RX);
 1709 #ifdef PGT_BUGGY_INTERRUPT_RECOVERY
 1710                 pgt_update_intr(sc, 0);
 1711 #endif
 1712         } while (i++ < 10);
 1713 
 1714         if (pmd->pmd_error == EINPROGRESS) {
 1715                 printf("%s: timeout waiting for management "
 1716                     "packet response to %#x\n",
 1717                     sc->sc_dev.dv_xname, pmd->pmd_oid);
 1718                 TAILQ_REMOVE(&sc->sc_mgmtinprog, pmd, pmd_link);
 1719                 if (sc->sc_debug & SC_DEBUG_UNEXPECTED)
 1720                         pgt_state_dump(sc);
 1721                 pgt_async_reset(sc);
 1722                 error = ETIMEDOUT;
 1723         } else
 1724                 error = 0;
 1725 
 1726         return (error);
 1727 }
 1728 
 1729 void
 1730 pgt_desc_transmit(struct pgt_softc *sc, enum pgt_queue pq, struct pgt_desc *pd,
 1731     uint16_t len, int morecoming)
 1732 {
 1733         TAILQ_REMOVE(&sc->sc_freeq[pq], pd, pd_link);
 1734         sc->sc_freeq_count[pq]--;
 1735         TAILQ_INSERT_TAIL(&sc->sc_dirtyq[pq], pd, pd_link);
 1736         sc->sc_dirtyq_count[pq]++;
 1737         if (sc->sc_debug & SC_DEBUG_QUEUES)
 1738                 DPRINTF(("%s: queue: tx %u -> [%u]\n", sc->sc_dev.dv_xname,
 1739                     pd->pd_fragnum, pq));
 1740         bus_dmamap_sync(sc->sc_dmat, sc->sc_cbdmam, 0,
 1741             sc->sc_cbdmam->dm_mapsize,
 1742             BUS_DMASYNC_POSTREAD | BUS_DMASYNC_PREWRITE);
 1743         if (morecoming)
 1744                 pd->pd_fragp->pf_flags |= htole16(PF_FLAG_MF);
 1745         pd->pd_fragp->pf_size = htole16(len);
 1746         bus_dmamap_sync(sc->sc_dmat, pd->pd_dmam, 0,
 1747             pd->pd_dmam->dm_mapsize,
 1748             BUS_DMASYNC_POSTWRITE);
 1749         sc->sc_cb->pcb_driver_curfrag[pq] =
 1750             htole32(letoh32(sc->sc_cb->pcb_driver_curfrag[pq]) + 1);
 1751         bus_dmamap_sync(sc->sc_dmat, sc->sc_cbdmam, 0,
 1752             sc->sc_cbdmam->dm_mapsize,
 1753             BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_PREREAD);
 1754         if (!morecoming)
 1755                 pgt_maybe_trigger(sc, pq);
 1756 }
 1757 
 1758 void
 1759 pgt_maybe_trigger(struct pgt_softc *sc, enum pgt_queue pq)
 1760 {
 1761         unsigned int tries = 1000000 / PGT_WRITEIO_DELAY; /* one second */
 1762         uint32_t reg;
 1763 
 1764         if (sc->sc_debug & SC_DEBUG_TRIGGER)
 1765                 DPRINTF(("%s: triggered by queue [%u]\n",
 1766                     sc->sc_dev.dv_xname, pq));
 1767         pgt_debug_events(sc, "trig");
 1768         if (sc->sc_flags & SC_POWERSAVE) {
 1769                 /* Magic values ahoy? */
 1770                 if (pgt_read_4(sc, PGT_REG_INT_STAT) == 0xabadface) {
 1771                         do {
 1772                                 reg = pgt_read_4(sc, PGT_REG_CTRL_STAT);
 1773                                 if (!(reg & PGT_CTRL_STAT_SLEEPMODE))
 1774                                         DELAY(PGT_WRITEIO_DELAY);
 1775                         } while (tries-- != 0);
 1776                         if (!(reg & PGT_CTRL_STAT_SLEEPMODE)) {
 1777                                 if (sc->sc_debug & SC_DEBUG_UNEXPECTED)
 1778                                         DPRINTF(("%s: timeout triggering from "
 1779                                             "sleep mode\n",
 1780                                             sc->sc_dev.dv_xname));
 1781                                 pgt_async_reset(sc);
 1782                                 return;
 1783                         }
 1784                 }
 1785                 pgt_write_4_flush(sc, PGT_REG_DEV_INT,
 1786                     PGT_DEV_INT_WAKEUP);
 1787                 DELAY(PGT_WRITEIO_DELAY);
 1788                 /* read the status back in */
 1789                 (void)pgt_read_4(sc, PGT_REG_CTRL_STAT);
 1790                 DELAY(PGT_WRITEIO_DELAY);
 1791         } else {
 1792                 pgt_write_4_flush(sc, PGT_REG_DEV_INT, PGT_DEV_INT_UPDATE);
 1793                 DELAY(PGT_WRITEIO_DELAY);
 1794         }
 1795 }
 1796 
 1797 struct ieee80211_node *
 1798 pgt_ieee80211_node_alloc(struct ieee80211com *ic)
 1799 {
 1800         struct pgt_ieee80211_node *pin;
 1801 
 1802         pin = malloc(sizeof(*pin), M_DEVBUF, M_NOWAIT | M_ZERO);
 1803         if (pin != NULL) {
 1804                 pin->pin_dot1x_auth = PIN_DOT1X_UNAUTHORIZED;
 1805         }
 1806         return (struct ieee80211_node *)pin;
 1807 }
 1808 
 1809 void
 1810 pgt_ieee80211_newassoc(struct ieee80211com *ic, struct ieee80211_node *ni,
 1811     int reallynew)
 1812 {
 1813         ieee80211_ref_node(ni);
 1814 }
 1815 
 1816 void
 1817 pgt_ieee80211_node_free(struct ieee80211com *ic, struct ieee80211_node *ni)
 1818 {
 1819         struct pgt_ieee80211_node *pin;
 1820 
 1821         pin = (struct pgt_ieee80211_node *)ni;
 1822         free(pin, M_DEVBUF, 0);
 1823 }
 1824 
 1825 void
 1826 pgt_ieee80211_node_copy(struct ieee80211com *ic, struct ieee80211_node *dst,
 1827     const struct ieee80211_node *src)
 1828 {
 1829         const struct pgt_ieee80211_node *psrc;
 1830         struct pgt_ieee80211_node *pdst;
 1831 
 1832         psrc = (const struct pgt_ieee80211_node *)src;
 1833         pdst = (struct pgt_ieee80211_node *)dst;
 1834         bcopy(psrc, pdst, sizeof(*psrc));
 1835 }
 1836 
 1837 int
 1838 pgt_ieee80211_send_mgmt(struct ieee80211com *ic, struct ieee80211_node *ni,
 1839     int type, int arg1, int arg2)
 1840 {
 1841         return (EOPNOTSUPP);
 1842 }
 1843 
 1844 int
 1845 pgt_net_attach(struct pgt_softc *sc)
 1846 {
 1847         struct ieee80211com *ic = &sc->sc_ic;
 1848         struct ifnet *ifp = &ic->ic_if;
 1849         struct ieee80211_rateset *rs;
 1850         uint8_t rates[IEEE80211_RATE_MAXSIZE];
 1851         struct pgt_obj_buffer psbuffer;
 1852         struct pgt_obj_frequencies *freqs;
 1853         uint32_t phymode, country;
 1854         unsigned int chan, i, j, firstchan = -1;
 1855         int error;
 1856 
 1857         psbuffer.pob_size = htole32(PGT_FRAG_SIZE * PGT_PSM_BUFFER_FRAME_COUNT);
 1858         psbuffer.pob_addr = htole32(sc->sc_psmdmam->dm_segs[0].ds_addr);
 1859         error = pgt_oid_set(sc, PGT_OID_PSM_BUFFER, &psbuffer, sizeof(country));
 1860         if (error)
 1861                 return (error);
 1862         error = pgt_oid_get(sc, PGT_OID_PHY, &phymode, sizeof(phymode));
 1863         if (error)
 1864                 return (error);
 1865         error = pgt_oid_get(sc, PGT_OID_MAC_ADDRESS, ic->ic_myaddr,
 1866             sizeof(ic->ic_myaddr));
 1867         if (error)
 1868                 return (error);
 1869         error = pgt_oid_get(sc, PGT_OID_COUNTRY, &country, sizeof(country));
 1870         if (error)
 1871                 return (error);
 1872 
 1873         ifp->if_softc = sc;
 1874         ifp->if_ioctl = pgt_ioctl;
 1875         ifp->if_start = pgt_start;
 1876         ifp->if_watchdog = pgt_watchdog;
 1877         ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST;
 1878         strlcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ);
 1879 
 1880         ifq_set_maxlen(&ifp->if_snd, IFQ_MAXLEN);
 1881 
 1882         /*
 1883          * Set channels
 1884          *
 1885          * Prism hardware likes to report supported frequencies that are
 1886          * not actually available for the country of origin.
 1887          */
 1888         j = sizeof(*freqs) + (IEEE80211_CHAN_MAX + 1) * sizeof(uint16_t);
 1889         freqs = malloc(j, M_DEVBUF, M_WAITOK);
 1890         error = pgt_oid_get(sc, PGT_OID_SUPPORTED_FREQUENCIES, freqs, j);
 1891         if (error) {
 1892                 free(freqs, M_DEVBUF, 0);
 1893                 return (error);
 1894         }
 1895 
 1896         for (i = 0, j = letoh16(freqs->pof_count); i < j; i++) {
 1897                 chan = ieee80211_mhz2ieee(letoh16(freqs->pof_freqlist_mhz[i]),
 1898                     0);
 1899 
 1900                 if (chan > IEEE80211_CHAN_MAX) {
 1901                         printf("%s: reported bogus channel (%uMHz)\n",
 1902                             sc->sc_dev.dv_xname, chan);
 1903                         free(freqs, M_DEVBUF, 0);
 1904                         return (EIO);
 1905                 }
 1906 
 1907                 if (letoh16(freqs->pof_freqlist_mhz[i]) < 5000) {
 1908                         if (!(phymode & htole32(PGT_OID_PHY_2400MHZ)))
 1909                                 continue;
 1910                         if (country == letoh32(PGT_COUNTRY_USA)) {
 1911                                 if (chan >= 12 && chan <= 14)
 1912                                         continue;
 1913                         }
 1914                         if (chan <= 14)
 1915                                 ic->ic_channels[chan].ic_flags |=
 1916                                     IEEE80211_CHAN_B;
 1917                         ic->ic_channels[chan].ic_flags |= IEEE80211_CHAN_PUREG;
 1918                 } else {
 1919                         if (!(phymode & htole32(PGT_OID_PHY_5000MHZ)))
 1920                                 continue;
 1921                         ic->ic_channels[chan].ic_flags |= IEEE80211_CHAN_A;
 1922                 }
 1923 
 1924                 ic->ic_channels[chan].ic_freq =
 1925                     letoh16(freqs->pof_freqlist_mhz[i]);
 1926 
 1927                 if (firstchan == -1)
 1928                         firstchan = chan;
 1929 
 1930                 DPRINTF(("%s: set channel %d to freq %uMHz\n",
 1931                     sc->sc_dev.dv_xname, chan,
 1932                     letoh16(freqs->pof_freqlist_mhz[i])));
 1933         }
 1934         free(freqs, M_DEVBUF, 0);
 1935         if (firstchan == -1) {
 1936                 printf("%s: no channels found\n", sc->sc_dev.dv_xname);
 1937                 return (EIO);
 1938         }
 1939 
 1940         /*
 1941          * Set rates
 1942          */
 1943         bzero(rates, sizeof(rates));
 1944         error = pgt_oid_get(sc, PGT_OID_SUPPORTED_RATES, rates, sizeof(rates));
 1945         if (error)
 1946                 return (error);
 1947         for (i = 0; i < sizeof(rates) && rates[i] != 0; i++) {
 1948                 switch (rates[i]) {
 1949                 case 2:
 1950                 case 4:
 1951                 case 11:
 1952                 case 22:
 1953                 case 44: /* maybe */
 1954                         if (phymode & htole32(PGT_OID_PHY_2400MHZ)) {
 1955                                 rs = &ic->ic_sup_rates[IEEE80211_MODE_11B];
 1956                                 rs->rs_rates[rs->rs_nrates++] = rates[i];
 1957                         }
 1958                 default:
 1959                         if (phymode & htole32(PGT_OID_PHY_2400MHZ)) {
 1960                                 rs = &ic->ic_sup_rates[IEEE80211_MODE_11G];
 1961                                 rs->rs_rates[rs->rs_nrates++] = rates[i];
 1962                         }
 1963                         if (phymode & htole32(PGT_OID_PHY_5000MHZ)) {
 1964                                 rs = &ic->ic_sup_rates[IEEE80211_MODE_11A];
 1965                                 rs->rs_rates[rs->rs_nrates++] = rates[i];
 1966                         }
 1967                         rs = &ic->ic_sup_rates[IEEE80211_MODE_AUTO];
 1968                         rs->rs_rates[rs->rs_nrates++] = rates[i];
 1969                 }
 1970         }
 1971 
 1972         ic->ic_caps = IEEE80211_C_WEP | IEEE80211_C_PMGT | IEEE80211_C_TXPMGT |
 1973             IEEE80211_C_SHSLOT | IEEE80211_C_SHPREAMBLE | IEEE80211_C_MONITOR;
 1974 #ifndef IEEE80211_STA_ONLY
 1975         ic->ic_caps |= IEEE80211_C_IBSS | IEEE80211_C_HOSTAP;
 1976 #endif
 1977         ic->ic_opmode = IEEE80211_M_STA;
 1978         ic->ic_state = IEEE80211_S_INIT;
 1979 
 1980         if_attach(ifp);
 1981         ieee80211_ifattach(ifp);
 1982 
 1983         /* setup post-attach/pre-lateattach vector functions */
 1984         sc->sc_newstate = ic->ic_newstate;
 1985         ic->ic_newstate = pgt_newstate;
 1986         ic->ic_node_alloc = pgt_ieee80211_node_alloc;
 1987         ic->ic_newassoc = pgt_ieee80211_newassoc;
 1988         ic->ic_node_free = pgt_ieee80211_node_free;
 1989         ic->ic_node_copy = pgt_ieee80211_node_copy;
 1990         ic->ic_send_mgmt = pgt_ieee80211_send_mgmt;
 1991         ic->ic_max_rssi = 255;  /* rssi is a u_int8_t */
 1992 
 1993         /* let net80211 handle switching around the media + resetting */
 1994         ieee80211_media_init(ifp, pgt_media_change, pgt_media_status);
 1995 
 1996 #if NBPFILTER > 0
 1997         bpfattach(&sc->sc_drvbpf, ifp, DLT_IEEE802_11_RADIO,
 1998             sizeof(struct ieee80211_frame) + 64);
 1999 
 2000         sc->sc_rxtap_len = sizeof(sc->sc_rxtapu);
 2001         sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len);
 2002         sc->sc_rxtap.wr_ihdr.it_present = htole32(PGT_RX_RADIOTAP_PRESENT);
 2003 
 2004         sc->sc_txtap_len = sizeof(sc->sc_txtapu);
 2005         sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len);
 2006         sc->sc_txtap.wt_ihdr.it_present = htole32(PGT_TX_RADIOTAP_PRESENT);
 2007 #endif
 2008         return (0);
 2009 }
 2010 
 2011 int
 2012 pgt_media_change(struct ifnet *ifp)
 2013 {
 2014         struct pgt_softc *sc = ifp->if_softc;
 2015         int error;
 2016 
 2017         error = ieee80211_media_change(ifp);
 2018         if (error == ENETRESET) {
 2019                 pgt_update_hw_from_sw(sc, 0);
 2020                 error = 0;
 2021         }
 2022 
 2023         return (error);
 2024 }
 2025 
 2026 void
 2027 pgt_media_status(struct ifnet *ifp, struct ifmediareq *imr)
 2028 {
 2029         struct pgt_softc *sc = ifp->if_softc;
 2030         struct ieee80211com *ic = &sc->sc_ic;
 2031         uint32_t rate;
 2032         int s;
 2033 
 2034         imr->ifm_status = 0;
 2035         imr->ifm_active = IFM_IEEE80211 | IFM_NONE;
 2036 
 2037         if (!(ifp->if_flags & IFF_UP))
 2038                 return;
 2039 
 2040         s = splnet();
 2041 
 2042         if (ic->ic_fixed_rate != -1) {
 2043                 rate = ic->ic_sup_rates[ic->ic_curmode].
 2044                     rs_rates[ic->ic_fixed_rate] & IEEE80211_RATE_VAL;
 2045         } else {
 2046                 if (pgt_oid_get(sc, PGT_OID_LINK_STATE, &rate, sizeof(rate)))
 2047                         goto out;
 2048                 rate = letoh32(rate);
 2049                 if (sc->sc_debug & SC_DEBUG_LINK) {
 2050                         DPRINTF(("%s: %s: link rate %u\n",
 2051                             sc->sc_dev.dv_xname, __func__, rate));
 2052                 }
 2053                 if (rate == 0)
 2054                         goto out;
 2055         }
 2056 
 2057         imr->ifm_status = IFM_AVALID;
 2058         imr->ifm_active = IFM_IEEE80211;
 2059         if (ic->ic_state == IEEE80211_S_RUN)
 2060                 imr->ifm_status |= IFM_ACTIVE;
 2061 
 2062         imr->ifm_active |= ieee80211_rate2media(ic, rate, ic->ic_curmode);
 2063 
 2064         switch (ic->ic_opmode) {
 2065         case IEEE80211_M_STA:
 2066                 break;
 2067 #ifndef IEEE80211_STA_ONLY
 2068         case IEEE80211_M_IBSS:
 2069                 imr->ifm_active |= IFM_IEEE80211_ADHOC;
 2070                 break;
 2071         case IEEE80211_M_AHDEMO:
 2072                 imr->ifm_active |= IFM_IEEE80211_ADHOC | IFM_FLAG0;
 2073                 break;
 2074         case IEEE80211_M_HOSTAP:
 2075                 imr->ifm_active |= IFM_IEEE80211_HOSTAP;
 2076                 break;
 2077 #endif
 2078         case IEEE80211_M_MONITOR:
 2079                 imr->ifm_active |= IFM_IEEE80211_MONITOR;
 2080                 break;
 2081         default:
 2082                 break;
 2083         }
 2084 
 2085 out:
 2086         splx(s);
 2087 }
 2088 
 2089 /*
 2090  * Start data frames.  Critical sections surround the boundary of
 2091  * management frame transmission / transmission acknowledgement / response
 2092  * and data frame transmission / transmission acknowledgement.
 2093  */
 2094 void
 2095 pgt_start(struct ifnet *ifp)
 2096 {
 2097         struct pgt_softc *sc;
 2098         struct ieee80211com *ic;
 2099         struct pgt_desc *pd;
 2100         struct mbuf *m;
 2101         int error;
 2102 
 2103         sc = ifp->if_softc;
 2104         ic = &sc->sc_ic;
 2105 
 2106         if (sc->sc_flags & (SC_DYING | SC_NEEDS_RESET) ||
 2107             !(ifp->if_flags & IFF_RUNNING) ||
 2108             ic->ic_state != IEEE80211_S_RUN) {
 2109                 return;
 2110         }
 2111 
 2112         /*
 2113          * Management packets should probably be MLME frames
 2114          * (i.e. hostap "managed" mode); we don't touch the
 2115          * net80211 management queue.
 2116          */
 2117         for (; sc->sc_dirtyq_count[PGT_QUEUE_DATA_LOW_TX] <
 2118             PGT_QUEUE_FULL_THRESHOLD && !ifq_empty(&ifp->if_snd);) {
 2119                 pd = TAILQ_FIRST(&sc->sc_freeq[PGT_QUEUE_DATA_LOW_TX]);
 2120                 m = ifq_deq_begin(&ifp->if_snd);
 2121                 if (m == NULL)
 2122                         break;
 2123                 if (m->m_pkthdr.len <= PGT_FRAG_SIZE) {
 2124                         error = pgt_load_tx_desc_frag(sc,
 2125                             PGT_QUEUE_DATA_LOW_TX, pd);
 2126                         if (error) {
 2127                                 ifq_deq_rollback(&ifp->if_snd, m);
 2128                                 break;
 2129                         }
 2130                         ifq_deq_commit(&ifp->if_snd, m);
 2131                         m_copydata(m, 0, m->m_pkthdr.len, pd->pd_mem);
 2132                         pgt_desc_transmit(sc, PGT_QUEUE_DATA_LOW_TX,
 2133                             pd, m->m_pkthdr.len, 0);
 2134                 } else if (m->m_pkthdr.len <= PGT_FRAG_SIZE * 2) {
 2135                         struct pgt_desc *pd2;
 2136 
 2137                         /*
 2138                          * Transmit a fragmented frame if there is
 2139                          * not enough room in one fragment; limit
 2140                          * to two fragments (802.11 itself couldn't
 2141                          * even support a full two.)
 2142                          */
 2143                         if (sc->sc_dirtyq_count[PGT_QUEUE_DATA_LOW_TX] + 2 >
 2144                             PGT_QUEUE_FULL_THRESHOLD) {
 2145                                 ifq_deq_rollback(&ifp->if_snd, m);
 2146                                 break;
 2147                         }
 2148                         pd2 = TAILQ_NEXT(pd, pd_link);
 2149                         error = pgt_load_tx_desc_frag(sc,
 2150                             PGT_QUEUE_DATA_LOW_TX, pd);
 2151                         if (error == 0) {
 2152                                 error = pgt_load_tx_desc_frag(sc,
 2153                                     PGT_QUEUE_DATA_LOW_TX, pd2);
 2154                                 if (error) {
 2155                                         pgt_unload_tx_desc_frag(sc, pd);
 2156                                         TAILQ_INSERT_HEAD(&sc->sc_freeq[
 2157                                             PGT_QUEUE_DATA_LOW_TX], pd,
 2158                                             pd_link);
 2159                                 }
 2160                         }
 2161                         if (error) {
 2162                                 ifq_deq_rollback(&ifp->if_snd, m);
 2163                                 break;
 2164                         }
 2165                         ifq_deq_commit(&ifp->if_snd, m);
 2166                         m_copydata(m, 0, PGT_FRAG_SIZE, pd->pd_mem);
 2167                         pgt_desc_transmit(sc, PGT_QUEUE_DATA_LOW_TX,
 2168                             pd, PGT_FRAG_SIZE, 1);
 2169                         m_copydata(m, PGT_FRAG_SIZE,
 2170                             m->m_pkthdr.len - PGT_FRAG_SIZE, pd2->pd_mem);
 2171                         pgt_desc_transmit(sc, PGT_QUEUE_DATA_LOW_TX,
 2172                             pd2, m->m_pkthdr.len - PGT_FRAG_SIZE, 0);
 2173                 } else {
 2174                         ifq_deq_commit(&ifp->if_snd, m);
 2175                         ifp->if_oerrors++;
 2176                         m_freem(m);
 2177                         m = NULL;
 2178                 }
 2179                 if (m != NULL) {
 2180                         struct ieee80211_node *ni;
 2181 #if NBPFILTER > 0
 2182                         if (ifp->if_bpf != NULL)
 2183                                 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
 2184 #endif
 2185                         ifp->if_timer = 1;
 2186                         sc->sc_txtimer = 5;
 2187                         ni = ieee80211_find_txnode(&sc->sc_ic,
 2188                             mtod(m, struct ether_header *)->ether_dhost);
 2189                         if (ni != NULL) {
 2190                                 ni->ni_inact = 0;
 2191                                 if (ni != ic->ic_bss)
 2192                                         ieee80211_release_node(&sc->sc_ic, ni);
 2193                         }
 2194 #if NBPFILTER > 0
 2195                         if (sc->sc_drvbpf != NULL) {
 2196                                 struct mbuf mb;
 2197                                 struct ether_header eh;
 2198                                 struct pgt_tx_radiotap_hdr *tap = &sc->sc_txtap;
 2199 
 2200                                 bcopy(mtod(m, struct ether_header *), &eh,
 2201                                     sizeof(eh));
 2202                                 m_adj(m, sizeof(eh));
 2203                                 m = pgt_ieee80211_encap(sc, &eh, m, NULL);
 2204 
 2205                                 tap->wt_flags = 0;
 2206                                 //tap->wt_rate = rate;
 2207                                 tap->wt_rate = 0;
 2208                                 tap->wt_chan_freq =
 2209                                     htole16(ic->ic_bss->ni_chan->ic_freq);
 2210                                 tap->wt_chan_flags =
 2211                                     htole16(ic->ic_bss->ni_chan->ic_flags);
 2212 
 2213                                 if (m != NULL) {
 2214                                         mb.m_data = (caddr_t)tap;
 2215                                         mb.m_len = sc->sc_txtap_len;
 2216                                         mb.m_next = m;
 2217                                         mb.m_nextpkt = NULL;
 2218                                         mb.m_type = 0;
 2219                                         mb.m_flags = 0;
 2220 
 2221                                         bpf_mtap(sc->sc_drvbpf, &mb,
 2222                                             BPF_DIRECTION_OUT);
 2223                                 }
 2224                         }
 2225 #endif
 2226                         m_freem(m);
 2227                 }
 2228         }
 2229 }
 2230 
 2231 int
 2232 pgt_ioctl(struct ifnet *ifp, u_long cmd, caddr_t req)
 2233 {
 2234         struct pgt_softc *sc = ifp->if_softc;
 2235         struct ifreq *ifr;
 2236         struct wi_req *wreq;
 2237         struct ieee80211_nodereq_all *na;
 2238         struct ieee80211com *ic;
 2239         struct pgt_obj_bsslist *pob;
 2240         struct wi_scan_p2_hdr *p2hdr;
 2241         struct wi_scan_res *res;
 2242         uint32_t noise;
 2243         int maxscan, i, j, s, error = 0;
 2244 
 2245         ic = &sc->sc_ic;
 2246         ifr = (struct ifreq *)req;
 2247 
 2248         s = splnet();
 2249         switch (cmd) {
 2250         case SIOCS80211SCAN:
 2251                 /*
 2252                  * This chip scans always as soon as it gets initialized.
 2253                  */
 2254                 break;
 2255         case SIOCG80211ALLNODES: {
 2256                 struct ieee80211_nodereq *nr = NULL;
 2257                 na = (struct ieee80211_nodereq_all *)req;
 2258                 wreq = malloc(sizeof(*wreq), M_DEVBUF, M_WAITOK | M_ZERO);
 2259 
 2260                 maxscan = PGT_OBJ_BSSLIST_NBSS;
 2261                 pob = malloc(sizeof(*pob) +
 2262                     sizeof(struct pgt_obj_bss) * maxscan, M_DEVBUF, M_WAITOK);
 2263                 error = pgt_oid_get(sc, PGT_OID_NOISE_FLOOR, &noise,
 2264                     sizeof(noise));
 2265 
 2266                 if (error == 0) {
 2267                         noise = letoh32(noise);
 2268                         error = pgt_oid_get(sc, PGT_OID_BSS_LIST, pob,
 2269                             sizeof(*pob) +
 2270                             sizeof(struct pgt_obj_bss) * maxscan);
 2271                 }
 2272 
 2273                 if (error == 0) {
 2274                         maxscan = min(PGT_OBJ_BSSLIST_NBSS,
 2275                             letoh32(pob->pob_count));
 2276                         maxscan = min(maxscan,
 2277                             (sizeof(wreq->wi_val) - sizeof(*p2hdr)) /
 2278                             WI_PRISM2_RES_SIZE);
 2279                         p2hdr = (struct wi_scan_p2_hdr *)&wreq->wi_val;
 2280                         p2hdr->wi_rsvd = 0;
 2281                         p2hdr->wi_reason = 1;
 2282                         wreq->wi_len = (maxscan * WI_PRISM2_RES_SIZE) / 2 +
 2283                             sizeof(*p2hdr) / 2;
 2284                         wreq->wi_type = WI_RID_SCAN_RES;
 2285                 }
 2286 
 2287                 for (na->na_nodes = j = i = 0; i < maxscan &&
 2288                     (na->na_size >= j + sizeof(struct ieee80211_nodereq));
 2289                     i++) {
 2290                         /* allocate node space */
 2291                         if (nr == NULL)
 2292                                 nr = malloc(sizeof(*nr), M_DEVBUF, M_WAITOK);
 2293 
 2294                         /* get next BSS scan result */
 2295                         res = (struct wi_scan_res *)
 2296                             ((char *)&wreq->wi_val + sizeof(*p2hdr) +
 2297                             i * WI_PRISM2_RES_SIZE);
 2298                         pgt_obj_bss2scanres(sc, &pob->pob_bsslist[i],
 2299                             res, noise);
 2300 
 2301                         /* copy it to node structure for ifconfig to read */
 2302                         bzero(nr, sizeof(*nr));
 2303                         IEEE80211_ADDR_COPY(nr->nr_macaddr, res->wi_bssid);
 2304                         IEEE80211_ADDR_COPY(nr->nr_bssid, res->wi_bssid);
 2305                         nr->nr_channel = letoh16(res->wi_chan);
 2306                         nr->nr_chan_flags = IEEE80211_CHAN_B;
 2307                         nr->nr_rssi = letoh16(res->wi_signal);
 2308                         nr->nr_max_rssi = 0; /* XXX */
 2309                         nr->nr_nwid_len = letoh16(res->wi_ssid_len);
 2310                         bcopy(res->wi_ssid, nr->nr_nwid, nr->nr_nwid_len);
 2311                         nr->nr_intval = letoh16(res->wi_interval);
 2312                         nr->nr_capinfo = letoh16(res->wi_capinfo);
 2313                         nr->nr_txrate = res->wi_rate == WI_WAVELAN_RES_1M ? 2 :
 2314                             (res->wi_rate == WI_WAVELAN_RES_2M ? 4 :
 2315                             (res->wi_rate == WI_WAVELAN_RES_5M ? 11 :
 2316                             (res->wi_rate == WI_WAVELAN_RES_11M ? 22 : 0)));
 2317                         nr->nr_nrates = 0;
 2318                         while (res->wi_srates[nr->nr_nrates] != 0) {
 2319                                 nr->nr_rates[nr->nr_nrates] =
 2320                                     res->wi_srates[nr->nr_nrates] &
 2321                                     WI_VAR_SRATES_MASK;
 2322                                 nr->nr_nrates++;
 2323                         }
 2324                         nr->nr_flags = 0;
 2325                         if (bcmp(nr->nr_macaddr, nr->nr_bssid,
 2326                             IEEE80211_ADDR_LEN) == 0)
 2327                                 nr->nr_flags |= IEEE80211_NODEREQ_AP;
 2328                         error = copyout(nr, (caddr_t)na->na_node + j,
 2329                             sizeof(struct ieee80211_nodereq));
 2330                         if (error)
 2331                                 break;
 2332 
 2333                         /* point to next node entry */
 2334                         j += sizeof(struct ieee80211_nodereq);
 2335                         na->na_nodes++;
 2336                 }
 2337                 if (nr)
 2338                         free(nr, M_DEVBUF, 0);
 2339                 free(pob, M_DEVBUF, 0);
 2340                 free(wreq, M_DEVBUF, 0);
 2341                 break;
 2342         }
 2343         case SIOCSIFADDR:
 2344                 ifp->if_flags |= IFF_UP;
 2345                 /* FALLTHROUGH */
 2346         case SIOCSIFFLAGS:
 2347                 if (ifp->if_flags & IFF_UP) {
 2348                         if ((ifp->if_flags & IFF_RUNNING) == 0) {
 2349                                 pgt_init(ifp);
 2350                                 error = ENETRESET;
 2351                         }
 2352                 } else {
 2353                         if (ifp->if_flags & IFF_RUNNING) {
 2354                                 pgt_stop(sc, SC_NEEDS_RESET);
 2355                                 error = ENETRESET;
 2356                         }
 2357                 }
 2358                 break;
 2359         case SIOCSIFMTU:
 2360                 if (ifr->ifr_mtu > PGT_FRAG_SIZE) {
 2361                         error = EINVAL;
 2362                         break;
 2363                 }
 2364                 /* FALLTHROUGH */
 2365         default:
 2366                 error = ieee80211_ioctl(ifp, cmd, req);
 2367                 break;
 2368         }
 2369 
 2370         if (error == ENETRESET) {
 2371                 pgt_update_hw_from_sw(sc, 0);
 2372                 error = 0;
 2373         }
 2374         splx(s);
 2375 
 2376         return (error);
 2377 }
 2378 
 2379 void
 2380 pgt_obj_bss2scanres(struct pgt_softc *sc, struct pgt_obj_bss *pob,
 2381     struct wi_scan_res *scanres, uint32_t noise)
 2382 {
 2383         struct ieee80211_rateset *rs;
 2384         struct wi_scan_res ap;
 2385         unsigned int i, n;
 2386 
 2387         rs = &sc->sc_ic.ic_sup_rates[IEEE80211_MODE_AUTO];
 2388         bzero(&ap, sizeof(ap));
 2389         ap.wi_chan = ieee80211_mhz2ieee(letoh16(pob->pob_channel), 0);
 2390         ap.wi_noise = noise;
 2391         ap.wi_signal = letoh16(pob->pob_rssi);
 2392         IEEE80211_ADDR_COPY(ap.wi_bssid, pob->pob_address);
 2393         ap.wi_interval = letoh16(pob->pob_beacon_period);
 2394         ap.wi_capinfo = letoh16(pob->pob_capinfo);
 2395         ap.wi_ssid_len = min(sizeof(ap.wi_ssid), pob->pob_ssid.pos_length);
 2396         memcpy(ap.wi_ssid, pob->pob_ssid.pos_ssid, ap.wi_ssid_len);
 2397         n = 0;
 2398         for (i = 0; i < 16; i++) {
 2399                 if (letoh16(pob->pob_rates) & (1 << i)) {
 2400                         if (i >= rs->rs_nrates)
 2401                                 break;
 2402                         ap.wi_srates[n++] = ap.wi_rate = rs->rs_rates[i];
 2403                         if (n >= sizeof(ap.wi_srates) / sizeof(ap.wi_srates[0]))
 2404                                 break;
 2405                 }
 2406         }
 2407         memcpy(scanres, &ap, WI_PRISM2_RES_SIZE);
 2408 }
 2409 
 2410 void
 2411 node_mark_active_ap(void *arg, struct ieee80211_node *ni)
 2412 {
 2413         /*
 2414          * HostAP mode lets all nodes stick around unless
 2415          * the firmware AP kicks them off.
 2416          */
 2417         ni->ni_inact = 0;
 2418 }
 2419 
 2420 void
 2421 node_mark_active_adhoc(void *arg, struct ieee80211_node *ni)
 2422 {
 2423         struct pgt_ieee80211_node *pin;
 2424 
 2425         /*
 2426          * As there is no association in ad-hoc, we let links just
 2427          * time out naturally as long they are not holding any private
 2428          * configuration, such as 802.1x authorization.
 2429          */
 2430         pin = (struct pgt_ieee80211_node *)ni;
 2431         if (pin->pin_dot1x_auth == PIN_DOT1X_AUTHORIZED)
 2432                 pin->pin_node.ni_inact = 0;
 2433 }
 2434 
 2435 void
 2436 pgt_watchdog(struct ifnet *ifp)
 2437 {
 2438         struct pgt_softc *sc;
 2439 
 2440         sc = ifp->if_softc;
 2441         /*
 2442          * Check for timed out transmissions (and make sure to set
 2443          * this watchdog to fire again if there is still data in the
 2444          * output device queue).
 2445          */
 2446         if (sc->sc_dirtyq_count[PGT_QUEUE_DATA_LOW_TX] != 0) {
 2447                 int count;
 2448 
 2449                 ifp->if_timer = 1;
 2450                 if (sc->sc_txtimer && --sc->sc_txtimer == 0) {
 2451                         count = pgt_drain_tx_queue(sc, PGT_QUEUE_DATA_LOW_TX);
 2452                         if (sc->sc_debug & SC_DEBUG_UNEXPECTED)
 2453                                 DPRINTF(("%s: timeout %d data transmissions\n",
 2454                                     sc->sc_dev.dv_xname, count));
 2455                 }
 2456         }
 2457         if (sc->sc_flags & (SC_DYING | SC_NEEDS_RESET))
 2458                 return;
 2459         /*
 2460          * If we're going to kick the device out of power-save mode
 2461          * just to update the BSSID and such, we should not do it
 2462          * very often; need to determine in what way to do that.
 2463          */
 2464         if (ifp->if_flags & IFF_RUNNING &&
 2465             sc->sc_ic.ic_state != IEEE80211_S_INIT &&
 2466             sc->sc_ic.ic_opmode != IEEE80211_M_MONITOR)
 2467                 pgt_async_update(sc);
 2468 
 2469 #ifndef IEEE80211_STA_ONLY
 2470         /*
 2471          * As a firmware-based HostAP, we should not time out
 2472          * nodes inside the driver additionally to the timeout
 2473          * that exists in the firmware.  The only things we
 2474          * should have to deal with timing out when doing HostAP
 2475          * are the privacy-related.
 2476          */
 2477         switch (sc->sc_ic.ic_opmode) {
 2478         case IEEE80211_M_HOSTAP:
 2479                 ieee80211_iterate_nodes(&sc->sc_ic,
 2480                     node_mark_active_ap, NULL);
 2481                 break;
 2482         case IEEE80211_M_IBSS:
 2483                 ieee80211_iterate_nodes(&sc->sc_ic,
 2484                     node_mark_active_adhoc, NULL);
 2485                 break;
 2486         default:
 2487                 break;
 2488         }
 2489 #endif
 2490         ieee80211_watchdog(ifp);
 2491         ifp->if_timer = 1;
 2492 }
 2493 
 2494 int
 2495 pgt_init(struct ifnet *ifp)
 2496 {
 2497         struct pgt_softc *sc = ifp->if_softc;
 2498         struct ieee80211com *ic = &sc->sc_ic;
 2499 
 2500         /* set default channel */
 2501         ic->ic_bss->ni_chan = ic->ic_ibss_chan;
 2502 
 2503         if (!(sc->sc_flags & (SC_DYING | SC_UNINITIALIZED)))
 2504                 pgt_update_hw_from_sw(sc,
 2505                     ic->ic_state != IEEE80211_S_INIT);
 2506 
 2507         ifp->if_flags |= IFF_RUNNING;
 2508         ifq_clr_oactive(&ifp->if_snd);
 2509 
 2510         /* Begin background scanning */
 2511         ieee80211_new_state(&sc->sc_ic, IEEE80211_S_SCAN, -1);
 2512 
 2513         return (0);
 2514 }
 2515 
 2516 /*
 2517  * After most every configuration change, everything needs to be fully
 2518  * reinitialized.  For some operations (currently, WEP settings
 2519  * in ad-hoc+802.1x mode), the change is "soft" and doesn't remove
 2520  * "associations," and allows EAP authorization to occur again.
 2521  * If keepassoc is specified, the reset operation should try to go
 2522  * back to the BSS had before.
 2523  */
 2524 void
 2525 pgt_update_hw_from_sw(struct pgt_softc *sc, int keepassoc)
 2526 {
 2527         struct ieee80211com *ic = &sc->sc_ic;
 2528         struct arpcom *ac = &ic->ic_ac;
 2529         struct ifnet *ifp = &ac->ac_if;
 2530         struct pgt_obj_key keyobj;
 2531         struct pgt_obj_ssid essid;
 2532         uint8_t availrates[IEEE80211_RATE_MAXSIZE + 1];
 2533         uint32_t mode, bsstype, config, profile, channel, slot, preamble;
 2534         uint32_t wep, exunencrypted, wepkey, dot1x, auth, mlme;
 2535         unsigned int i;
 2536         int success, shouldbeup, s;
 2537 
 2538         config = PGT_CONFIG_MANUAL_RUN | PGT_CONFIG_RX_ANNEX;
 2539 
 2540         /*
 2541          * Promiscuous mode is currently a no-op since packets transmitted,
 2542          * while in promiscuous mode, don't ever seem to go anywhere.
 2543          */
 2544         shouldbeup = ifp->if_flags & IFF_RUNNING && ifp->if_flags & IFF_UP;
 2545 
 2546         if (shouldbeup) {
 2547                 switch (ic->ic_opmode) {
 2548                 case IEEE80211_M_STA:
 2549                         if (ifp->if_flags & IFF_PROMISC)
 2550                                 mode = PGT_MODE_CLIENT; /* what to do? */
 2551                         else
 2552                                 mode = PGT_MODE_CLIENT;
 2553                         bsstype = PGT_BSS_TYPE_STA;
 2554                         dot1x = PGT_DOT1X_AUTH_ENABLED;
 2555                         break;
 2556 #ifndef IEEE80211_STA_ONLY
 2557                 case IEEE80211_M_IBSS:
 2558                         if (ifp->if_flags & IFF_PROMISC)
 2559                                 mode = PGT_MODE_CLIENT; /* what to do? */
 2560                         else
 2561                                 mode = PGT_MODE_CLIENT;
 2562                         bsstype = PGT_BSS_TYPE_IBSS;
 2563                         dot1x = PGT_DOT1X_AUTH_ENABLED;
 2564                         break;
 2565                 case IEEE80211_M_HOSTAP:
 2566                         mode = PGT_MODE_AP;
 2567                         bsstype = PGT_BSS_TYPE_STA;
 2568                         /*
 2569                          * For IEEE 802.1x, we need to authenticate and
 2570                          * authorize hosts from here on or they remain
 2571                          * associated but without the ability to send or
 2572                          * receive normal traffic to us (courtesy the
 2573                          * firmware AP implementation).
 2574                          */
 2575                         dot1x = PGT_DOT1X_AUTH_ENABLED;
 2576                         /*
 2577                          * WDS mode needs several things to work:
 2578                          * discovery of exactly how creating the WDS
 2579                          * links is meant to function, an interface
 2580                          * for this, and ability to encode or decode
 2581                          * the WDS frames.
 2582                          */
 2583                         if (sc->sc_wds)
 2584                                 config |= PGT_CONFIG_WDS;
 2585                         break;
 2586 #endif
 2587                 case IEEE80211_M_MONITOR:
 2588                         mode = PGT_MODE_PROMISCUOUS;
 2589                         bsstype = PGT_BSS_TYPE_ANY;
 2590                         dot1x = PGT_DOT1X_AUTH_NONE;
 2591                         break;
 2592                 default:
 2593                         goto badopmode;
 2594                 }
 2595         } else {
 2596 badopmode:
 2597                 mode = PGT_MODE_CLIENT;
 2598                 bsstype = PGT_BSS_TYPE_NONE;
 2599         }
 2600 
 2601         DPRINTF(("%s: current mode is ", sc->sc_dev.dv_xname));
 2602         switch (ic->ic_curmode) {
 2603         case IEEE80211_MODE_11A:
 2604                 profile = PGT_PROFILE_A_ONLY;
 2605                 preamble = PGT_OID_PREAMBLE_MODE_DYNAMIC;
 2606                 DPRINTF(("IEEE80211_MODE_11A\n"));
 2607                 break;
 2608         case IEEE80211_MODE_11B:
 2609                 profile = PGT_PROFILE_B_ONLY;
 2610                 preamble = PGT_OID_PREAMBLE_MODE_LONG;
 2611                 DPRINTF(("IEEE80211_MODE_11B\n"));
 2612                 break;
 2613         case IEEE80211_MODE_11G:
 2614                 profile = PGT_PROFILE_G_ONLY;
 2615                 preamble = PGT_OID_PREAMBLE_MODE_SHORT;
 2616                 DPRINTF(("IEEE80211_MODE_11G\n"));
 2617                 break;
 2618         case IEEE80211_MODE_AUTO:
 2619                 profile = PGT_PROFILE_MIXED_G_WIFI;
 2620                 preamble = PGT_OID_PREAMBLE_MODE_DYNAMIC;
 2621                 DPRINTF(("IEEE80211_MODE_AUTO\n"));
 2622                 break;
 2623         default:
 2624                 panic("unknown mode %d", ic->ic_curmode);
 2625         }
 2626 
 2627         switch (sc->sc_80211_ioc_auth) {
 2628         case IEEE80211_AUTH_NONE:
 2629                 auth = PGT_AUTH_MODE_NONE;
 2630                 break;
 2631         case IEEE80211_AUTH_OPEN:
 2632                 auth = PGT_AUTH_MODE_OPEN;
 2633                 break;
 2634         default:
 2635                 auth = PGT_AUTH_MODE_SHARED;
 2636                 break;
 2637         }
 2638 
 2639         if (sc->sc_ic.ic_flags & IEEE80211_F_WEPON) {
 2640                 wep = 1;
 2641                 exunencrypted = 1;
 2642         } else {
 2643                 wep = 0;
 2644                 exunencrypted = 0;
 2645         }
 2646 
 2647         mlme = htole32(PGT_MLME_AUTO_LEVEL_AUTO);
 2648         wep = htole32(wep);
 2649         exunencrypted = htole32(exunencrypted);
 2650         profile = htole32(profile);
 2651         preamble = htole32(preamble);
 2652         bsstype = htole32(bsstype);
 2653         config = htole32(config);
 2654         mode = htole32(mode);
 2655 
 2656         if (!wep || !sc->sc_dot1x)
 2657                 dot1x = PGT_DOT1X_AUTH_NONE;
 2658         dot1x = htole32(dot1x);
 2659         auth = htole32(auth);
 2660 
 2661         if (ic->ic_flags & IEEE80211_F_SHSLOT)
 2662                 slot = htole32(PGT_OID_SLOT_MODE_SHORT);
 2663         else
 2664                 slot = htole32(PGT_OID_SLOT_MODE_DYNAMIC);
 2665 
 2666         if (ic->ic_des_chan == IEEE80211_CHAN_ANYC) {
 2667                 if (keepassoc)
 2668                         channel = 0;
 2669                 else
 2670                         channel = ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan);
 2671         } else
 2672                 channel = ieee80211_chan2ieee(ic, ic->ic_des_chan);
 2673 
 2674         DPRINTF(("%s: set rates", sc->sc_dev.dv_xname));
 2675         for (i = 0; i < ic->ic_sup_rates[ic->ic_curmode].rs_nrates; i++) {
 2676                 availrates[i] = ic->ic_sup_rates[ic->ic_curmode].rs_rates[i];
 2677                 DPRINTF((" %d", availrates[i]));
 2678         }
 2679         DPRINTF(("\n"));
 2680         availrates[i++] = 0;
 2681 
 2682         essid.pos_length = min(ic->ic_des_esslen, sizeof(essid.pos_ssid));
 2683         memcpy(&essid.pos_ssid, ic->ic_des_essid, essid.pos_length);
 2684 
 2685         s = splnet();
 2686         for (success = 0; success == 0; success = 1) {
 2687                 SETOID(PGT_OID_PROFILE, &profile, sizeof(profile));
 2688                 SETOID(PGT_OID_CONFIG, &config, sizeof(config));
 2689                 SETOID(PGT_OID_MLME_AUTO_LEVEL, &mlme, sizeof(mlme));
 2690 
 2691                 if (!IEEE80211_ADDR_EQ(ic->ic_myaddr, ac->ac_enaddr)) {
 2692                         SETOID(PGT_OID_MAC_ADDRESS, ac->ac_enaddr,
 2693                             sizeof(ac->ac_enaddr));
 2694                         IEEE80211_ADDR_COPY(ic->ic_myaddr, ac->ac_enaddr);
 2695                 }
 2696 
 2697                 SETOID(PGT_OID_MODE, &mode, sizeof(mode));
 2698                 SETOID(PGT_OID_BSS_TYPE, &bsstype, sizeof(bsstype));
 2699 
 2700                 if (channel != 0 && channel != IEEE80211_CHAN_ANY)
 2701                         SETOID(PGT_OID_CHANNEL, &channel, sizeof(channel));
 2702 
 2703                 if (ic->ic_flags & IEEE80211_F_DESBSSID) {
 2704                         SETOID(PGT_OID_BSSID, ic->ic_des_bssid,
 2705                             sizeof(ic->ic_des_bssid));
 2706                 } else if (keepassoc) {
 2707                         SETOID(PGT_OID_BSSID, ic->ic_bss->ni_bssid,
 2708                             sizeof(ic->ic_bss->ni_bssid));
 2709                 }
 2710 
 2711                 SETOID(PGT_OID_SSID, &essid, sizeof(essid));
 2712 
 2713                 if (ic->ic_des_esslen > 0)
 2714                         SETOID(PGT_OID_SSID_OVERRIDE, &essid, sizeof(essid));
 2715 
 2716                 SETOID(PGT_OID_RATES, &availrates, i);
 2717                 SETOID(PGT_OID_EXTENDED_RATES, &availrates, i);
 2718                 SETOID(PGT_OID_PREAMBLE_MODE, &preamble, sizeof(preamble));
 2719                 SETOID(PGT_OID_SLOT_MODE, &slot, sizeof(slot));
 2720                 SETOID(PGT_OID_AUTH_MODE, &auth, sizeof(auth));
 2721                 SETOID(PGT_OID_EXCLUDE_UNENCRYPTED, &exunencrypted,
 2722                     sizeof(exunencrypted));
 2723                 SETOID(PGT_OID_DOT1X, &dot1x, sizeof(dot1x));
 2724                 SETOID(PGT_OID_PRIVACY_INVOKED, &wep, sizeof(wep));
 2725                 /*
 2726                  * Setting WEP key(s)
 2727                  */
 2728                 if (letoh32(wep) != 0) {
 2729                         keyobj.pok_type = PGT_OBJ_KEY_TYPE_WEP;
 2730                         /* key 1 */
 2731                         keyobj.pok_length = min(sizeof(keyobj.pok_key),
 2732                             IEEE80211_KEYBUF_SIZE);
 2733                         keyobj.pok_length = min(keyobj.pok_length,
 2734                             ic->ic_nw_keys[0].k_len);
 2735                         bcopy(ic->ic_nw_keys[0].k_key, keyobj.pok_key,
 2736                             keyobj.pok_length);
 2737                         SETOID(PGT_OID_DEFAULT_KEY0, &keyobj, sizeof(keyobj));
 2738                         /* key 2 */
 2739                         keyobj.pok_length = min(sizeof(keyobj.pok_key),
 2740                             IEEE80211_KEYBUF_SIZE);
 2741                         keyobj.pok_length = min(keyobj.pok_length,
 2742                             ic->ic_nw_keys[1].k_len);
 2743                         bcopy(ic->ic_nw_keys[1].k_key, keyobj.pok_key,
 2744                             keyobj.pok_length);
 2745                         SETOID(PGT_OID_DEFAULT_KEY1, &keyobj, sizeof(keyobj));
 2746                         /* key 3 */
 2747                         keyobj.pok_length = min(sizeof(keyobj.pok_key),
 2748                             IEEE80211_KEYBUF_SIZE);
 2749                         keyobj.pok_length = min(keyobj.pok_length,
 2750                             ic->ic_nw_keys[2].k_len);
 2751                         bcopy(ic->ic_nw_keys[2].k_key, keyobj.pok_key,
 2752                             keyobj.pok_length);
 2753                         SETOID(PGT_OID_DEFAULT_KEY2, &keyobj, sizeof(keyobj));
 2754                         /* key 4 */
 2755                         keyobj.pok_length = min(sizeof(keyobj.pok_key),
 2756                             IEEE80211_KEYBUF_SIZE);
 2757                         keyobj.pok_length = min(keyobj.pok_length,
 2758                             ic->ic_nw_keys[3].k_len);
 2759                         bcopy(ic->ic_nw_keys[3].k_key, keyobj.pok_key,
 2760                             keyobj.pok_length);
 2761                         SETOID(PGT_OID_DEFAULT_KEY3, &keyobj, sizeof(keyobj));
 2762 
 2763                         wepkey = htole32(ic->ic_wep_txkey);
 2764                         SETOID(PGT_OID_DEFAULT_KEYNUM, &wepkey, sizeof(wepkey));
 2765                 }
 2766                 /* set mode again to commit */
 2767                 SETOID(PGT_OID_MODE, &mode, sizeof(mode));
 2768         }
 2769         splx(s);
 2770 
 2771         if (success) {
 2772                 if (shouldbeup)
 2773                         ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
 2774                 else
 2775                         ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
 2776         } else {
 2777                 printf("%s: problem setting modes\n", sc->sc_dev.dv_xname);
 2778                 ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
 2779         }
 2780 }
 2781 
 2782 void
 2783 pgt_hostap_handle_mlme(struct pgt_softc *sc, uint32_t oid,
 2784     struct pgt_obj_mlme *mlme)
 2785 {
 2786         struct ieee80211com *ic = &sc->sc_ic;
 2787         struct pgt_ieee80211_node *pin;
 2788         struct ieee80211_node *ni;
 2789 
 2790         ni = ieee80211_find_node(ic, mlme->pom_address);
 2791         pin = (struct pgt_ieee80211_node *)ni;
 2792         switch (oid) {
 2793         case PGT_OID_DISASSOCIATE:
 2794                 if (ni != NULL)
 2795                         ieee80211_release_node(&sc->sc_ic, ni);
 2796                 break;
 2797         case PGT_OID_ASSOCIATE:
 2798                 if (ni == NULL) {
 2799                         ni = ieee80211_dup_bss(ic, mlme->pom_address);
 2800                         if (ni == NULL)
 2801                                 break;
 2802                         ic->ic_newassoc(ic, ni, 1);
 2803                         pin = (struct pgt_ieee80211_node *)ni;
 2804                 }
 2805                 ni->ni_associd = letoh16(mlme->pom_id);
 2806                 pin->pin_mlme_state = letoh16(mlme->pom_state);
 2807                 break;
 2808         default:
 2809                 if (pin != NULL)
 2810                         pin->pin_mlme_state = letoh16(mlme->pom_state);
 2811                 break;
 2812         }
 2813 }
 2814 
 2815 /*
 2816  * Either in response to an event or after a certain amount of time,
 2817  * synchronize our idea of the network we're part of from the hardware.
 2818  */
 2819 void
 2820 pgt_update_sw_from_hw(struct pgt_softc *sc, struct pgt_async_trap *pa,
 2821             struct mbuf *args)
 2822 {
 2823         struct ieee80211com *ic = &sc->sc_ic;
 2824         struct pgt_obj_ssid ssid;
 2825         struct pgt_obj_bss bss;
 2826         uint32_t channel, noise, ls;
 2827         int error, s;
 2828 
 2829         if (pa != NULL) {
 2830                 struct pgt_obj_mlme *mlme;
 2831                 uint32_t oid;
 2832 
 2833                 oid = *mtod(args, uint32_t *);
 2834                 m_adj(args, sizeof(uint32_t));
 2835                 if (sc->sc_debug & SC_DEBUG_TRAP)
 2836                         DPRINTF(("%s: trap: oid %#x len %u\n",
 2837                             sc->sc_dev.dv_xname, oid, args->m_len));
 2838                 switch (oid) {
 2839                 case PGT_OID_LINK_STATE:
 2840                         if (args->m_len < sizeof(uint32_t))
 2841                                 break;
 2842                         ls = letoh32(*mtod(args, uint32_t *));
 2843                         if (sc->sc_debug & (SC_DEBUG_TRAP | SC_DEBUG_LINK))
 2844                                 DPRINTF(("%s: %s: link rate %u\n",
 2845                                     sc->sc_dev.dv_xname, __func__, ls));
 2846                         if (ls)
 2847                                 ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
 2848                         else
 2849                                 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
 2850                         goto gotlinkstate;
 2851                 case PGT_OID_DEAUTHENTICATE:
 2852                 case PGT_OID_AUTHENTICATE:
 2853                 case PGT_OID_DISASSOCIATE:
 2854                 case PGT_OID_ASSOCIATE:
 2855                         if (args->m_len < sizeof(struct pgt_obj_mlme))
 2856                                 break;
 2857                         mlme = mtod(args, struct pgt_obj_mlme *);
 2858                         if (sc->sc_debug & SC_DEBUG_TRAP)
 2859                                 DPRINTF(("%s: mlme: address "
 2860                                     "%s id 0x%02x state 0x%02x code 0x%02x\n",
 2861                                     sc->sc_dev.dv_xname,
 2862                                     ether_sprintf(mlme->pom_address),
 2863                                     letoh16(mlme->pom_id),
 2864                                     letoh16(mlme->pom_state),
 2865                                     letoh16(mlme->pom_code)));
 2866 #ifndef IEEE80211_STA_ONLY
 2867                         if (ic->ic_opmode == IEEE80211_M_HOSTAP)
 2868                                 pgt_hostap_handle_mlme(sc, oid, mlme);
 2869 #endif
 2870                         break;
 2871                 }
 2872                 return;
 2873         }
 2874         if (ic->ic_state == IEEE80211_S_SCAN) {
 2875                 s = splnet();
 2876                 error = pgt_oid_get(sc, PGT_OID_LINK_STATE, &ls, sizeof(ls));
 2877                 splx(s);
 2878                 if (error)
 2879                         return;
 2880                 DPRINTF(("%s: up_sw_from_hw: link %u\n", sc->sc_dev.dv_xname,
 2881                     htole32(ls)));
 2882                 if (ls != 0)
 2883                         ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
 2884         }
 2885 
 2886 gotlinkstate:
 2887         s = splnet();
 2888         if (pgt_oid_get(sc, PGT_OID_NOISE_FLOOR, &noise, sizeof(noise)) != 0)
 2889                 goto out;
 2890         sc->sc_noise = letoh32(noise);
 2891         if (ic->ic_state == IEEE80211_S_RUN) {
 2892                 if (pgt_oid_get(sc, PGT_OID_CHANNEL, &channel,
 2893                     sizeof(channel)) != 0)
 2894                         goto out;
 2895                 channel = min(letoh32(channel), IEEE80211_CHAN_MAX);
 2896                 ic->ic_bss->ni_chan = &ic->ic_channels[channel];
 2897                 if (pgt_oid_get(sc, PGT_OID_BSSID, ic->ic_bss->ni_bssid,
 2898                     sizeof(ic->ic_bss->ni_bssid)) != 0)
 2899                         goto out;
 2900                 IEEE80211_ADDR_COPY(&bss.pob_address, ic->ic_bss->ni_bssid);
 2901                 error = pgt_oid_retrieve(sc, PGT_OID_BSS_FIND, &bss,
 2902                     sizeof(bss));
 2903                 if (error == 0)
 2904                         ic->ic_bss->ni_rssi = bss.pob_rssi;
 2905                 else if (error != EPERM)
 2906                         goto out;
 2907                 error = pgt_oid_get(sc, PGT_OID_SSID, &ssid, sizeof(ssid));
 2908                 if (error)
 2909                         goto out;
 2910                 ic->ic_bss->ni_esslen = min(ssid.pos_length,
 2911                     sizeof(ic->ic_bss->ni_essid));
 2912                 memcpy(ic->ic_bss->ni_essid, ssid.pos_ssid,
 2913                     ssid.pos_length);
 2914         }
 2915 
 2916 out:
 2917         splx(s);
 2918 }
 2919 
 2920 int
 2921 pgt_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
 2922 {
 2923         struct pgt_softc *sc = ic->ic_if.if_softc;
 2924         enum ieee80211_state ostate;
 2925 
 2926         ostate = ic->ic_state;
 2927 
 2928         DPRINTF(("%s: newstate %s -> %s\n", sc->sc_dev.dv_xname,
 2929             ieee80211_state_name[ostate], ieee80211_state_name[nstate]));
 2930 
 2931         switch (nstate) {
 2932         case IEEE80211_S_INIT:
 2933                 if (sc->sc_dirtyq_count[PGT_QUEUE_DATA_LOW_TX] == 0)
 2934                         ic->ic_if.if_timer = 0;
 2935                 ic->ic_mgt_timer = 0;
 2936                 ic->ic_flags &= ~IEEE80211_F_SIBSS;
 2937                 ieee80211_free_allnodes(ic, 1);
 2938                 ieee80211_set_link_state(ic, LINK_STATE_DOWN);
 2939                 break;
 2940         case IEEE80211_S_SCAN:
 2941                 ic->ic_if.if_timer = 1;
 2942                 ic->ic_mgt_timer = 0;
 2943                 ieee80211_node_cleanup(ic, ic->ic_bss);
 2944                 ieee80211_set_link_state(ic, LINK_STATE_DOWN);
 2945 #ifndef IEEE80211_STA_ONLY
 2946                 /* Just use any old channel; we override it anyway. */
 2947                 if (ic->ic_opmode == IEEE80211_M_HOSTAP)
 2948                         ieee80211_create_ibss(ic, ic->ic_ibss_chan);
 2949 #endif
 2950                 break;
 2951         case IEEE80211_S_RUN:
 2952                 ic->ic_if.if_timer = 1;
 2953                 break;
 2954         default:
 2955                 break;
 2956         }
 2957 
 2958         return (sc->sc_newstate(ic, nstate, arg));
 2959 }
 2960 
 2961 int
 2962 pgt_drain_tx_queue(struct pgt_softc *sc, enum pgt_queue pq)
 2963 {
 2964         int wokeup = 0;
 2965 
 2966         bus_dmamap_sync(sc->sc_dmat, sc->sc_cbdmam, 0,
 2967             sc->sc_cbdmam->dm_mapsize,
 2968             BUS_DMASYNC_POSTREAD | BUS_DMASYNC_PREWRITE);
 2969         sc->sc_cb->pcb_device_curfrag[pq] =
 2970             sc->sc_cb->pcb_driver_curfrag[pq];
 2971         bus_dmamap_sync(sc->sc_dmat, sc->sc_cbdmam, 0,
 2972             sc->sc_cbdmam->dm_mapsize,
 2973             BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_PREREAD);
 2974         while (!TAILQ_EMPTY(&sc->sc_dirtyq[pq])) {
 2975                 struct pgt_desc *pd;
 2976 
 2977                 pd = TAILQ_FIRST(&sc->sc_dirtyq[pq]);
 2978                 TAILQ_REMOVE(&sc->sc_dirtyq[pq], pd, pd_link);
 2979                 sc->sc_dirtyq_count[pq]--;
 2980                 TAILQ_INSERT_TAIL(&sc->sc_freeq[pq], pd, pd_link);
 2981                 sc->sc_freeq_count[pq]++;
 2982                 pgt_unload_tx_desc_frag(sc, pd);
 2983                 if (sc->sc_debug & SC_DEBUG_QUEUES)
 2984                         DPRINTF(("%s: queue: tx %u <- [%u] (drained)\n",
 2985                             sc->sc_dev.dv_xname, pd->pd_fragnum, pq));
 2986                 wokeup++;
 2987                 if (pgt_queue_is_data(pq))
 2988                         sc->sc_ic.ic_if.if_oerrors++;
 2989         }
 2990 
 2991         return (wokeup);
 2992 }
 2993 
 2994 int
 2995 pgt_dma_alloc(struct pgt_softc *sc)
 2996 {
 2997         size_t size;
 2998         int i, error, nsegs;
 2999 
 3000         for (i = 0; i < PGT_QUEUE_COUNT; i++) {
 3001                 TAILQ_INIT(&sc->sc_freeq[i]);
 3002                 TAILQ_INIT(&sc->sc_dirtyq[i]);
 3003         }
 3004 
 3005         /*
 3006          * control block
 3007          */
 3008         size = sizeof(struct pgt_control_block);
 3009 
 3010         error = bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
 3011             BUS_DMA_NOWAIT, &sc->sc_cbdmam);
 3012         if (error != 0) {
 3013                 printf("%s: can not create DMA tag for control block\n",
 3014                     sc->sc_dev.dv_xname);
 3015                 goto out;
 3016         }
 3017 
 3018         error = bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE,
 3019             0, &sc->sc_cbdmas, 1, &nsegs, BUS_DMA_NOWAIT | BUS_DMA_ZERO);
 3020         if (error != 0) {
 3021                 printf("%s: can not allocate DMA memory for control block\n",
 3022                     sc->sc_dev.dv_xname);
 3023                 goto out;
 3024         }
 3025 
 3026         error = bus_dmamem_map(sc->sc_dmat, &sc->sc_cbdmas, nsegs,
 3027             size, (caddr_t *)&sc->sc_cb, BUS_DMA_NOWAIT);
 3028         if (error != 0) {
 3029                 printf("%s: can not map DMA memory for control block\n",
 3030                     sc->sc_dev.dv_xname);
 3031                 goto out;
 3032         }
 3033 
 3034         error = bus_dmamap_load(sc->sc_dmat, sc->sc_cbdmam,
 3035             sc->sc_cb, size, NULL, BUS_DMA_NOWAIT);
 3036         if (error != 0) {
 3037                 printf("%s: can not load DMA map for control block\n",
 3038                     sc->sc_dev.dv_xname);
 3039                 goto out;
 3040         }
 3041 
 3042         /*
 3043          * powersave
 3044          */
 3045         size = PGT_FRAG_SIZE * PGT_PSM_BUFFER_FRAME_COUNT;
 3046 
 3047         error = bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
 3048             BUS_DMA_ALLOCNOW, &sc->sc_psmdmam);
 3049         if (error != 0) {
 3050                 printf("%s: can not create DMA tag for powersave\n",
 3051                     sc->sc_dev.dv_xname);
 3052                 goto out;
 3053         }
 3054 
 3055         error = bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE,
 3056            0, &sc->sc_psmdmas, 1, &nsegs, BUS_DMA_NOWAIT | BUS_DMA_ZERO);
 3057         if (error != 0) {
 3058                 printf("%s: can not allocate DMA memory for powersave\n",
 3059                     sc->sc_dev.dv_xname);
 3060                 goto out;
 3061         }
 3062 
 3063         error = bus_dmamem_map(sc->sc_dmat, &sc->sc_psmdmas, nsegs,
 3064             size, (caddr_t *)&sc->sc_psmbuf, BUS_DMA_NOWAIT);
 3065         if (error != 0) {
 3066                 printf("%s: can not map DMA memory for powersave\n",
 3067                     sc->sc_dev.dv_xname);
 3068                 goto out;
 3069         }
 3070 
 3071         error = bus_dmamap_load(sc->sc_dmat, sc->sc_psmdmam,
 3072             sc->sc_psmbuf, size, NULL, BUS_DMA_WAITOK);
 3073         if (error != 0) {
 3074                 printf("%s: can not load DMA map for powersave\n",
 3075                     sc->sc_dev.dv_xname);
 3076                 goto out;
 3077         }
 3078 
 3079         /*
 3080          * fragments
 3081          */
 3082         error = pgt_dma_alloc_queue(sc, PGT_QUEUE_DATA_LOW_RX);
 3083         if (error != 0)
 3084                 goto out;
 3085 
 3086         error = pgt_dma_alloc_queue(sc, PGT_QUEUE_DATA_LOW_TX);
 3087         if (error != 0)
 3088                 goto out;
 3089 
 3090         error = pgt_dma_alloc_queue(sc, PGT_QUEUE_DATA_HIGH_RX);
 3091         if (error != 0)
 3092                 goto out;
 3093 
 3094         error = pgt_dma_alloc_queue(sc, PGT_QUEUE_DATA_HIGH_TX);
 3095         if (error != 0)
 3096                 goto out;
 3097 
 3098         error = pgt_dma_alloc_queue(sc, PGT_QUEUE_MGMT_RX);
 3099         if (error != 0)
 3100                 goto out;
 3101 
 3102         error = pgt_dma_alloc_queue(sc, PGT_QUEUE_MGMT_TX);
 3103         if (error != 0)
 3104                 goto out;
 3105 
 3106 out:
 3107         if (error) {
 3108                 printf("%s: error in DMA allocation\n", sc->sc_dev.dv_xname);
 3109                 pgt_dma_free(sc);
 3110         }
 3111 
 3112         return (error);
 3113 }
 3114 
 3115 int
 3116 pgt_dma_alloc_queue(struct pgt_softc *sc, enum pgt_queue pq)
 3117 {
 3118         struct pgt_desc *pd;
 3119         size_t i, qsize;
 3120         int error, nsegs;
 3121 
 3122         switch (pq) {
 3123                 case PGT_QUEUE_DATA_LOW_RX:
 3124                         qsize = PGT_QUEUE_DATA_RX_SIZE;
 3125                         break;
 3126                 case PGT_QUEUE_DATA_LOW_TX:
 3127                         qsize = PGT_QUEUE_DATA_TX_SIZE;
 3128                         break;
 3129                 case PGT_QUEUE_DATA_HIGH_RX:
 3130                         qsize = PGT_QUEUE_DATA_RX_SIZE;
 3131                         break;
 3132                 case PGT_QUEUE_DATA_HIGH_TX:
 3133                         qsize = PGT_QUEUE_DATA_TX_SIZE;
 3134                         break;
 3135                 case PGT_QUEUE_MGMT_RX:
 3136                         qsize = PGT_QUEUE_MGMT_SIZE;
 3137                         break;
 3138                 case PGT_QUEUE_MGMT_TX:
 3139                         qsize = PGT_QUEUE_MGMT_SIZE;
 3140                         break;
 3141                 default:
 3142                         return (EINVAL);
 3143         }
 3144 
 3145         for (i = 0; i < qsize; i++) {
 3146                 pd = malloc(sizeof(*pd), M_DEVBUF, M_WAITOK);
 3147 
 3148                 error = bus_dmamap_create(sc->sc_dmat, PGT_FRAG_SIZE, 1,
 3149                     PGT_FRAG_SIZE, 0, BUS_DMA_ALLOCNOW, &pd->pd_dmam);
 3150                 if (error != 0) {
 3151                         printf("%s: can not create DMA tag for fragment\n",
 3152                             sc->sc_dev.dv_xname);
 3153                         free(pd, M_DEVBUF, 0);
 3154                         break;
 3155                 }
 3156 
 3157                 error = bus_dmamem_alloc(sc->sc_dmat, PGT_FRAG_SIZE, PAGE_SIZE,
 3158                     0, &pd->pd_dmas, 1, &nsegs, BUS_DMA_WAITOK);
 3159                 if (error != 0) {
 3160                         printf("%s: error alloc frag %zu on queue %u\n",
 3161                             sc->sc_dev.dv_xname, i, pq);
 3162                         free(pd, M_DEVBUF, 0);
 3163                         break;
 3164                 }
 3165 
 3166                 error = bus_dmamem_map(sc->sc_dmat, &pd->pd_dmas, nsegs,
 3167                     PGT_FRAG_SIZE, (caddr_t *)&pd->pd_mem, BUS_DMA_WAITOK);
 3168                 if (error != 0) {
 3169                         printf("%s: error map frag %zu on queue %u\n",
 3170                             sc->sc_dev.dv_xname, i, pq);
 3171                         free(pd, M_DEVBUF, 0);
 3172                         break;
 3173                 }
 3174 
 3175                 if (pgt_queue_is_rx(pq)) {
 3176                         error = bus_dmamap_load(sc->sc_dmat, pd->pd_dmam,
 3177                             pd->pd_mem, PGT_FRAG_SIZE, NULL, BUS_DMA_NOWAIT);
 3178                         if (error != 0) {
 3179                                 printf("%s: error load frag %zu on queue %u\n",
 3180                                     sc->sc_dev.dv_xname, i, pq);
 3181                                 bus_dmamem_free(sc->sc_dmat, &pd->pd_dmas,
 3182                                     nsegs);
 3183                                 free(pd, M_DEVBUF, 0);
 3184                                 break;
 3185                         }
 3186                         pd->pd_dmaaddr = pd->pd_dmam->dm_segs[0].ds_addr;
 3187                 }
 3188                 TAILQ_INSERT_TAIL(&sc->sc_freeq[pq], pd, pd_link);
 3189         }
 3190 
 3191         return (error);
 3192 }
 3193 
 3194 void
 3195 pgt_dma_free(struct pgt_softc *sc)
 3196 {
 3197         /*
 3198          * fragments
 3199          */
 3200         if (sc->sc_dmat != NULL) {
 3201                 pgt_dma_free_queue(sc, PGT_QUEUE_DATA_LOW_RX);
 3202                 pgt_dma_free_queue(sc, PGT_QUEUE_DATA_LOW_TX);
 3203                 pgt_dma_free_queue(sc, PGT_QUEUE_DATA_HIGH_RX);
 3204                 pgt_dma_free_queue(sc, PGT_QUEUE_DATA_HIGH_TX);
 3205                 pgt_dma_free_queue(sc, PGT_QUEUE_MGMT_RX);
 3206                 pgt_dma_free_queue(sc, PGT_QUEUE_MGMT_TX);
 3207         }
 3208 
 3209         /*
 3210          * powersave
 3211          */
 3212         if (sc->sc_psmbuf != NULL) {
 3213                 bus_dmamap_unload(sc->sc_dmat, sc->sc_psmdmam);
 3214                 bus_dmamem_free(sc->sc_dmat, &sc->sc_psmdmas, 1);
 3215                 sc->sc_psmbuf = NULL;
 3216                 sc->sc_psmdmam = NULL;
 3217         }
 3218 
 3219         /*
 3220          * control block
 3221          */
 3222         if (sc->sc_cb != NULL) {
 3223                 bus_dmamap_unload(sc->sc_dmat, sc->sc_cbdmam);
 3224                 bus_dmamem_free(sc->sc_dmat, &sc->sc_cbdmas, 1);
 3225                 sc->sc_cb = NULL;
 3226                 sc->sc_cbdmam = NULL;
 3227         }
 3228 }
 3229 
 3230 void
 3231 pgt_dma_free_queue(struct pgt_softc *sc, enum pgt_queue pq)
 3232 {
 3233         struct pgt_desc *pd;
 3234 
 3235         while (!TAILQ_EMPTY(&sc->sc_freeq[pq])) {
 3236                 pd = TAILQ_FIRST(&sc->sc_freeq[pq]);
 3237                 TAILQ_REMOVE(&sc->sc_freeq[pq], pd, pd_link);
 3238                 if (pd->pd_dmam != NULL) {
 3239                         bus_dmamap_unload(sc->sc_dmat, pd->pd_dmam);
 3240                         pd->pd_dmam = NULL;
 3241                 }
 3242                 bus_dmamem_free(sc->sc_dmat, &pd->pd_dmas, 1);
 3243                 free(pd, M_DEVBUF, 0);
 3244         }
 3245 }
 3246 
 3247 int
 3248 pgt_activate(struct device *self, int act)
 3249 {
 3250         struct pgt_softc *sc = (struct pgt_softc *)self;
 3251         struct ifnet *ifp = &sc->sc_ic.ic_if;
 3252 
 3253         DPRINTF(("%s: %s(%d)\n", sc->sc_dev.dv_xname, __func__, why));
 3254 
 3255         switch (act) {
 3256         case DVACT_SUSPEND:
 3257                 if (ifp->if_flags & IFF_RUNNING) {
 3258                         pgt_stop(sc, SC_NEEDS_RESET);
 3259                         pgt_update_hw_from_sw(sc, 0);
 3260                 }
 3261                 if (sc->sc_power != NULL)
 3262                         (*sc->sc_power)(sc, act);
 3263                 break;
 3264         case DVACT_WAKEUP:
 3265                 pgt_wakeup(sc);
 3266                 break;
 3267         }
 3268         return 0;
 3269 }
 3270 
 3271 void
 3272 pgt_wakeup(struct pgt_softc *sc)
 3273 {
 3274         struct ifnet *ifp = &sc->sc_ic.ic_if;
 3275 
 3276         if (sc->sc_power != NULL)
 3277                 (*sc->sc_power)(sc, DVACT_RESUME);
 3278 
 3279         pgt_stop(sc, SC_NEEDS_RESET);
 3280         pgt_update_hw_from_sw(sc, 0);
 3281 
 3282         if (ifp->if_flags & IFF_UP) {
 3283                 pgt_init(ifp);
 3284                 pgt_update_hw_from_sw(sc, 0);
 3285         }
 3286 }

Cache object: 6530f2279ea3843ae9d67eb857aaae8f


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.