[BACK]Return to if_bwfm_pci.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev / pci

Annotation of src/sys/dev/pci/if_bwfm_pci.c, Revision 1.6

1.6     ! jdolecek    1: /*     $NetBSD: if_bwfm_pci.c,v 1.5 2018/11/01 13:09:35 martin Exp $   */
1.1       maya        2: /*     $OpenBSD: if_bwfm_pci.c,v 1.18 2018/02/08 05:00:38 patrick Exp $        */
                      3: /*
                      4:  * Copyright (c) 2010-2016 Broadcom Corporation
                      5:  * Copyright (c) 2017 Patrick Wildt <patrick@blueri.se>
                      6:  *
                      7:  * Permission to use, copy, modify, and/or 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: #include <sys/param.h>
                     21: #include <sys/systm.h>
                     22: #include <sys/buf.h>
                     23: #include <sys/kernel.h>
                     24: #include <sys/kmem.h>
                     25: #include <sys/device.h>
                     26: #include <sys/pool.h>
                     27: #include <sys/workqueue.h>
                     28: #include <sys/socket.h>
                     29:
                     30: #include <net/bpf.h>
                     31: #include <net/if.h>
                     32: #include <net/if_dl.h>
                     33: #include <net/if_ether.h>
                     34: #include <net/if_media.h>
                     35:
                     36: #include <netinet/in.h>
                     37:
                     38: #include <net80211/ieee80211_var.h>
                     39:
                     40: #include <dev/firmload.h>
                     41:
                     42: #include <dev/pci/pcireg.h>
                     43: #include <dev/pci/pcivar.h>
                     44: #include <dev/pci/pcidevs.h>
                     45:
                     46: #include <dev/ic/bwfmvar.h>
                     47: #include <dev/ic/bwfmreg.h>
                     48: #include <dev/pci/if_bwfm_pci.h>
                     49:
                     50: #define BWFM_DMA_D2H_SCRATCH_BUF_LEN           8
                     51: #define BWFM_DMA_D2H_RINGUPD_BUF_LEN           1024
                     52: #define BWFM_DMA_H2D_IOCTL_BUF_LEN             ETHER_MAX_LEN
                     53:
                     54: #define BWFM_NUM_TX_MSGRINGS                   2
                     55: #define BWFM_NUM_RX_MSGRINGS                   3
                     56:
                     57: #define BWFM_NUM_TX_PKTIDS                     2048
                     58: #define BWFM_NUM_RX_PKTIDS                     1024
                     59:
                     60: #define BWFM_NUM_TX_DESCS                      1
                     61: #define BWFM_NUM_RX_DESCS                      1
                     62:
                     63: #ifdef BWFM_DEBUG
                     64: #define DPRINTF(x)     do { if (bwfm_debug > 0) printf x; } while (0)
                     65: #define DPRINTFN(n, x) do { if (bwfm_debug >= (n)) printf x; } while (0)
                     66: static int bwfm_debug = 2;
                     67: #else
                     68: #define DPRINTF(x)     do { ; } while (0)
                     69: #define DPRINTFN(n, x) do { ; } while (0)
                     70: #endif
                     71:
                     72: #define DEVNAME(sc)    device_xname((sc)->sc_sc.sc_dev)
                     73: #define letoh16                htole16
                     74: #define letoh32                htole32
                     75: #define nitems(x)      __arraycount(x)
                     76:
                     77: enum ring_status {
                     78:        RING_CLOSED,
                     79:        RING_CLOSING,
                     80:        RING_OPEN,
                     81:        RING_OPENING,
                     82: };
                     83:
                     84: struct bwfm_pci_msgring {
                     85:        uint32_t                 w_idx_addr;
                     86:        uint32_t                 r_idx_addr;
                     87:        uint32_t                 w_ptr;
                     88:        uint32_t                 r_ptr;
                     89:        int                      nitem;
                     90:        int                      itemsz;
                     91:        enum ring_status         status;
                     92:        struct bwfm_pci_dmamem  *ring;
                     93:        struct mbuf             *m;
                     94:
                     95:        int                      fifo;
                     96:        uint8_t                  mac[ETHER_ADDR_LEN];
                     97: };
                     98:
                     99: struct bwfm_pci_buf {
                    100:        bus_dmamap_t     bb_map;
                    101:        struct mbuf     *bb_m;
                    102: };
                    103:
                    104: struct bwfm_pci_pkts {
                    105:        struct bwfm_pci_buf     *pkts;
                    106:        uint32_t                 npkt;
                    107:        int                      last;
                    108: };
                    109:
                    110: struct if_rxring {
                    111:        u_int   rxr_total;
                    112:        u_int   rxr_inuse;
                    113: };
                    114:
                    115: struct bwfm_cmd_flowring_create {
                    116:        struct work              wq_cookie;
                    117:        struct bwfm_pci_softc   *sc;
                    118:        struct mbuf             *m;
                    119:        int                      flowid;
                    120:        int                      prio;
                    121: };
                    122:
                    123: struct bwfm_pci_softc {
                    124:        struct bwfm_softc        sc_sc;
                    125:        pci_chipset_tag_t        sc_pc;
                    126:        pcitag_t                 sc_tag;
                    127:        pcireg_t                 sc_id;
                    128:        void                    *sc_ih;
                    129:        pci_intr_handle_t       *sc_pihp;
                    130:
                    131:        bus_space_tag_t          sc_reg_iot;
                    132:        bus_space_handle_t       sc_reg_ioh;
                    133:        bus_size_t               sc_reg_ios;
                    134:
                    135:        bus_space_tag_t          sc_tcm_iot;
                    136:        bus_space_handle_t       sc_tcm_ioh;
                    137:        bus_size_t               sc_tcm_ios;
                    138:
                    139:        bus_dma_tag_t            sc_dmat;
                    140:
                    141:        uint32_t                 sc_shared_address;
                    142:        uint32_t                 sc_shared_flags;
                    143:        uint8_t                  sc_shared_version;
                    144:
                    145:        uint8_t                  sc_dma_idx_sz;
                    146:        struct bwfm_pci_dmamem  *sc_dma_idx_buf;
                    147:        size_t                   sc_dma_idx_bufsz;
                    148:
                    149:        uint16_t                 sc_max_rxbufpost;
                    150:        uint32_t                 sc_rx_dataoffset;
                    151:        uint32_t                 sc_htod_mb_data_addr;
                    152:        uint32_t                 sc_dtoh_mb_data_addr;
                    153:        uint32_t                 sc_ring_info_addr;
                    154:
                    155:        uint32_t                 sc_console_base_addr;
                    156:        uint32_t                 sc_console_buf_addr;
                    157:        uint32_t                 sc_console_buf_size;
                    158:        uint32_t                 sc_console_readidx;
                    159:
                    160:        struct pool              sc_flowring_pool;
                    161:        struct workqueue        *flowring_wq;
                    162:
                    163:        uint16_t                 sc_max_flowrings;
                    164:        uint16_t                 sc_max_submissionrings;
                    165:        uint16_t                 sc_max_completionrings;
                    166:
                    167:        struct bwfm_pci_msgring  sc_ctrl_submit;
                    168:        struct bwfm_pci_msgring  sc_rxpost_submit;
                    169:        struct bwfm_pci_msgring  sc_ctrl_complete;
                    170:        struct bwfm_pci_msgring  sc_tx_complete;
                    171:        struct bwfm_pci_msgring  sc_rx_complete;
                    172:        struct bwfm_pci_msgring *sc_flowrings;
                    173:
                    174:        struct bwfm_pci_dmamem  *sc_scratch_buf;
                    175:        struct bwfm_pci_dmamem  *sc_ringupd_buf;
                    176:
                    177:        struct bwfm_pci_dmamem  *sc_ioctl_buf;
                    178:        int                      sc_ioctl_reqid;
                    179:        uint32_t                 sc_ioctl_resp_pktid;
                    180:        uint32_t                 sc_ioctl_resp_ret_len;
                    181:        uint32_t                 sc_ioctl_resp_status;
                    182:        int                      sc_ioctl_poll;
                    183:
                    184:        struct if_rxring         sc_ioctl_ring;
                    185:        struct if_rxring         sc_event_ring;
                    186:        struct if_rxring         sc_rxbuf_ring;
                    187:
                    188:        struct bwfm_pci_pkts     sc_rx_pkts;
                    189:        struct bwfm_pci_pkts     sc_tx_pkts;
                    190:        int                      sc_tx_pkts_full;
                    191: };
                    192:
                    193: struct bwfm_pci_dmamem {
                    194:        bus_dmamap_t            bdm_map;
                    195:        bus_dma_segment_t       bdm_seg;
                    196:        size_t                  bdm_size;
                    197:        char *                  bdm_kva;
                    198: };
                    199:
                    200: #define BWFM_PCI_DMA_MAP(_bdm) ((_bdm)->bdm_map)
                    201: #define BWFM_PCI_DMA_LEN(_bdm) ((_bdm)->bdm_size)
1.5       martin    202: #define BWFM_PCI_DMA_DVA(_bdm) (uint64_t)((_bdm)->bdm_map->dm_segs[0].ds_addr)
1.1       maya      203: #define BWFM_PCI_DMA_KVA(_bdm) ((_bdm)->bdm_kva)
                    204:
                    205: static u_int    if_rxr_get(struct if_rxring *rxr, unsigned int max);
                    206: static void     if_rxr_put(struct if_rxring *rxr, unsigned int n);
                    207: static void     if_rxr_init(struct if_rxring *rxr, unsigned int lwm, unsigned int hwm);
                    208:
                    209: int             bwfm_pci_match(device_t parent, cfdata_t match, void *aux);
                    210: void            bwfm_pci_attachhook(device_t);
                    211: void            bwfm_pci_attach(device_t, device_t, void *);
                    212: int             bwfm_pci_detach(device_t, int);
                    213:
                    214: int             bwfm_pci_intr(void *);
                    215: void            bwfm_pci_intr_enable(struct bwfm_pci_softc *);
                    216: void            bwfm_pci_intr_disable(struct bwfm_pci_softc *);
                    217: int             bwfm_pci_load_microcode(struct bwfm_pci_softc *, const u_char *,
                    218:                    size_t);
                    219: void            bwfm_pci_select_core(struct bwfm_pci_softc *, int );
                    220:
                    221: struct bwfm_pci_dmamem *
                    222:                 bwfm_pci_dmamem_alloc(struct bwfm_pci_softc *, bus_size_t,
                    223:                    bus_size_t);
                    224: void            bwfm_pci_dmamem_free(struct bwfm_pci_softc *, struct bwfm_pci_dmamem *);
                    225: int             bwfm_pci_pktid_avail(struct bwfm_pci_softc *,
                    226:                    struct bwfm_pci_pkts *);
                    227: int             bwfm_pci_pktid_new(struct bwfm_pci_softc *,
1.2       riastrad  228:                    struct bwfm_pci_pkts *, struct mbuf **,
1.1       maya      229:                    uint32_t *, paddr_t *);
                    230: struct mbuf *   bwfm_pci_pktid_free(struct bwfm_pci_softc *,
                    231:                    struct bwfm_pci_pkts *, uint32_t);
                    232: void            bwfm_pci_fill_rx_ioctl_ring(struct bwfm_pci_softc *,
                    233:                    struct if_rxring *, uint32_t);
                    234: void            bwfm_pci_fill_rx_buf_ring(struct bwfm_pci_softc *);
                    235: void            bwfm_pci_fill_rx_rings(struct bwfm_pci_softc *);
                    236: int             bwfm_pci_setup_ring(struct bwfm_pci_softc *, struct bwfm_pci_msgring *,
                    237:                    int, size_t, uint32_t, uint32_t, int, uint32_t, uint32_t *);
                    238: int             bwfm_pci_setup_flowring(struct bwfm_pci_softc *, struct bwfm_pci_msgring *,
                    239:                    int, size_t);
                    240:
                    241: void            bwfm_pci_ring_bell(struct bwfm_pci_softc *,
                    242:                    struct bwfm_pci_msgring *);
                    243: void            bwfm_pci_ring_update_rptr(struct bwfm_pci_softc *,
                    244:                    struct bwfm_pci_msgring *);
                    245: void            bwfm_pci_ring_update_wptr(struct bwfm_pci_softc *,
                    246:                    struct bwfm_pci_msgring *);
                    247: void            bwfm_pci_ring_write_rptr(struct bwfm_pci_softc *,
                    248:                    struct bwfm_pci_msgring *);
                    249: void            bwfm_pci_ring_write_wptr(struct bwfm_pci_softc *,
                    250:                    struct bwfm_pci_msgring *);
                    251: void *          bwfm_pci_ring_write_reserve(struct bwfm_pci_softc *,
                    252:                    struct bwfm_pci_msgring *);
                    253: void *          bwfm_pci_ring_write_reserve_multi(struct bwfm_pci_softc *,
                    254:                    struct bwfm_pci_msgring *, int, int *);
                    255: void *          bwfm_pci_ring_read_avail(struct bwfm_pci_softc *,
                    256:                    struct bwfm_pci_msgring *, int *);
                    257: void            bwfm_pci_ring_read_commit(struct bwfm_pci_softc *,
                    258:                    struct bwfm_pci_msgring *, int);
                    259: void            bwfm_pci_ring_write_commit(struct bwfm_pci_softc *,
                    260:                    struct bwfm_pci_msgring *);
                    261: void            bwfm_pci_ring_write_cancel(struct bwfm_pci_softc *,
                    262:                    struct bwfm_pci_msgring *, int);
                    263:
                    264: void            bwfm_pci_ring_rx(struct bwfm_pci_softc *,
                    265:                    struct bwfm_pci_msgring *);
                    266: void            bwfm_pci_msg_rx(struct bwfm_pci_softc *, void *);
                    267:
                    268: uint32_t        bwfm_pci_buscore_read(struct bwfm_softc *, uint32_t);
                    269: void            bwfm_pci_buscore_write(struct bwfm_softc *, uint32_t,
                    270:                    uint32_t);
                    271: int             bwfm_pci_buscore_prepare(struct bwfm_softc *);
                    272: int             bwfm_pci_buscore_reset(struct bwfm_softc *);
                    273: void            bwfm_pci_buscore_activate(struct bwfm_softc *, const uint32_t);
                    274:
                    275: int             bwfm_pci_flowring_lookup(struct bwfm_pci_softc *,
                    276:                     struct mbuf *);
                    277: void            bwfm_pci_flowring_create(struct bwfm_pci_softc *,
                    278:                     struct mbuf *);
                    279: void            bwfm_pci_flowring_create_cb(struct work *, void *);
                    280: void            bwfm_pci_flowring_delete(struct bwfm_pci_softc *, int);
                    281:
                    282: void            bwfm_pci_stop(struct bwfm_softc *);
                    283: int             bwfm_pci_txcheck(struct bwfm_softc *);
1.2       riastrad  284: int             bwfm_pci_txdata(struct bwfm_softc *, struct mbuf **);
1.1       maya      285:
                    286: #ifdef BWFM_DEBUG
                    287: void            bwfm_pci_debug_console(struct bwfm_pci_softc *);
                    288: #endif
                    289:
                    290: int             bwfm_pci_msgbuf_query_dcmd(struct bwfm_softc *, int,
                    291:                    int, char *, size_t *);
                    292: int             bwfm_pci_msgbuf_set_dcmd(struct bwfm_softc *, int,
                    293:                    int, char *, size_t);
                    294:
                    295: struct bwfm_buscore_ops bwfm_pci_buscore_ops = {
                    296:        .bc_read = bwfm_pci_buscore_read,
                    297:        .bc_write = bwfm_pci_buscore_write,
                    298:        .bc_prepare = bwfm_pci_buscore_prepare,
                    299:        .bc_reset = bwfm_pci_buscore_reset,
                    300:        .bc_setup = NULL,
                    301:        .bc_activate = bwfm_pci_buscore_activate,
                    302: };
                    303:
                    304: struct bwfm_bus_ops bwfm_pci_bus_ops = {
                    305:        .bs_init = NULL,
                    306:        .bs_stop = bwfm_pci_stop,
                    307:        .bs_txcheck = bwfm_pci_txcheck,
                    308:        .bs_txdata = bwfm_pci_txdata,
                    309:        .bs_txctl = NULL,
                    310:        .bs_rxctl = NULL,
                    311: };
                    312:
                    313: struct bwfm_proto_ops bwfm_pci_msgbuf_ops = {
                    314:        .proto_query_dcmd = bwfm_pci_msgbuf_query_dcmd,
                    315:        .proto_set_dcmd = bwfm_pci_msgbuf_set_dcmd,
                    316: };
                    317:
                    318:
                    319: CFATTACH_DECL_NEW(bwfm_pci, sizeof(struct bwfm_pci_softc),
                    320:     bwfm_pci_match, bwfm_pci_attach, bwfm_pci_detach, NULL);
                    321:
                    322: static const struct bwfm_pci_matchid {
                    323:        pci_vendor_id_t         bwfm_vendor;
                    324:        pci_product_id_t        bwfm_product;
                    325: } bwfm_pci_devices[] = {
                    326:        { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM43602 },
                    327:        { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM4350 },
                    328: };
                    329:
                    330: static struct mbuf *
                    331: MCLGETI(struct bwfm_pci_softc *sc __unused, int how,
                    332:     struct ifnet *ifp __unused, u_int size)
                    333: {
                    334:        struct mbuf *m;
                    335:
                    336:        MGETHDR(m, how, MT_DATA);
                    337:        if (m == NULL)
                    338:                return NULL;
                    339:
                    340:        MEXTMALLOC(m, size, how);
                    341:        if ((m->m_flags & M_EXT) == 0) {
                    342:                m_freem(m);
                    343:                return NULL;
                    344:        }
                    345:        return m;
                    346: }
                    347:
                    348: int
                    349: bwfm_pci_match(device_t parent, cfdata_t match, void *aux)
                    350: {
                    351:        struct pci_attach_args *pa = aux;
                    352:
                    353:        if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_BROADCOM)
                    354:                return 0;
                    355:
                    356:        for (size_t i = 0; i < __arraycount(bwfm_pci_devices); i++)
                    357:                if (PCI_PRODUCT(pa->pa_id) == bwfm_pci_devices[i].bwfm_product)
                    358:                        return 1;
                    359:
                    360:        return 0;
                    361: }
                    362:
                    363: void
                    364: bwfm_pci_attach(device_t parent, device_t self, void *aux)
                    365: {
                    366:        struct bwfm_pci_softc *sc = device_private(self);
                    367:        struct pci_attach_args *pa = (struct pci_attach_args *)aux;
                    368:        const char *intrstr;
                    369:        char intrbuf[PCI_INTRSTR_LEN];
                    370:
                    371:        sc->sc_sc.sc_dev = self;
                    372:
                    373:        if (pci_mapreg_map(pa, PCI_MAPREG_START + 0x00,
                    374:            PCI_MAPREG_MEM_TYPE_64BIT, 0, &sc->sc_reg_iot, &sc->sc_reg_ioh,
                    375:            NULL, &sc->sc_reg_ios)) {
                    376:                printf(": can't map bar0\n");
                    377:                return;
                    378:        }
                    379:
                    380:        if (pci_mapreg_map(pa, PCI_MAPREG_START + 0x08,
                    381:            PCI_MAPREG_MEM_TYPE_64BIT, 0, &sc->sc_tcm_iot, &sc->sc_tcm_ioh,
                    382:            NULL, &sc->sc_tcm_ios)) {
                    383:                printf(": can't map bar1\n");
                    384:                goto bar0;
                    385:        }
                    386:
                    387:        sc->sc_pc = pa->pa_pc;
                    388:        sc->sc_tag = pa->pa_tag;
                    389:        sc->sc_id = pa->pa_id;
                    390:
                    391:        if (pci_dma64_available(pa))
                    392:                sc->sc_dmat = pa->pa_dmat64;
                    393:        else
                    394:                sc->sc_dmat = pa->pa_dmat;
                    395:
                    396:        /* Map and establish the interrupt. */
                    397:        if (pci_intr_alloc(pa, &sc->sc_pihp, NULL, 0) != 0) {
                    398:                printf(": couldn't map interrupt\n");
                    399:                goto bar1;
                    400:        }
                    401:        intrstr = pci_intr_string(pa->pa_pc, sc->sc_pihp[0], intrbuf, sizeof(intrbuf));
                    402:
1.6     ! jdolecek  403:        sc->sc_ih = pci_intr_establish_xname(pa->pa_pc, sc->sc_pihp[0], IPL_NET,
        !           404:            bwfm_pci_intr, sc, device_xname(self));
1.1       maya      405:        if (sc->sc_ih == NULL) {
                    406:                printf(": couldn't establish interrupt");
                    407:                if (intrstr != NULL)
                    408:                        printf(" at %s", intrstr);
                    409:                printf("\n");
                    410:                goto bar1;
                    411:        }
                    412:        printf(": %s\n", intrstr);
                    413:
                    414:        config_mountroot(self, bwfm_pci_attachhook);
                    415:        return;
                    416:
                    417: bar1:
                    418:        bus_space_unmap(sc->sc_tcm_iot, sc->sc_tcm_ioh, sc->sc_tcm_ios);
                    419: bar0:
                    420:        bus_space_unmap(sc->sc_reg_iot, sc->sc_reg_ioh, sc->sc_reg_ios);
                    421: }
                    422:
                    423: void
                    424: bwfm_pci_attachhook(device_t self)
                    425: {
                    426:        struct bwfm_pci_softc *sc = device_private(self);
                    427:        struct bwfm_softc *bwfm = (void *)sc;
                    428:        struct bwfm_pci_ringinfo ringinfo;
                    429:        const char *name = NULL;
                    430:        firmware_handle_t fwh;
                    431:        u_char *ucode; size_t size;
                    432:        uint32_t d2h_w_idx_ptr, d2h_r_idx_ptr;
                    433:        uint32_t h2d_w_idx_ptr, h2d_r_idx_ptr;
                    434:        uint32_t idx_offset, reg;
                    435:        int i;
                    436:        int error;
                    437:
                    438:        sc->sc_sc.sc_buscore_ops = &bwfm_pci_buscore_ops;
                    439:        if (bwfm_chip_attach(&sc->sc_sc) != 0) {
                    440:                printf("%s: cannot attach chip\n", DEVNAME(sc));
                    441:                return;
                    442:        }
                    443:
                    444:        bwfm_pci_select_core(sc, BWFM_AGENT_CORE_PCIE2);
                    445:        bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,
                    446:            BWFM_PCI_PCIE2REG_CONFIGADDR, 0x4e0);
                    447:        reg = bus_space_read_4(sc->sc_reg_iot, sc->sc_reg_ioh,
                    448:            BWFM_PCI_PCIE2REG_CONFIGDATA);
                    449:        bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,
                    450:            BWFM_PCI_PCIE2REG_CONFIGDATA, reg);
                    451:
                    452:        switch (bwfm->sc_chip.ch_chip)
                    453:        {
                    454:        case BRCM_CC_4350_CHIP_ID:
                    455:                if (bwfm->sc_chip.ch_chiprev > 7)
                    456:                        name = "brcmfmac4350-pcie.bin";
                    457:                else
                    458:                        name = "brcmfmac4350c2-pcie.bin";
                    459:                break;
                    460:        case BRCM_CC_43602_CHIP_ID:
                    461:                name = "brcmfmac43602-pcie.bin";
                    462:                break;
                    463:        default:
                    464:                printf("%s: unknown firmware for chip %s\n",
                    465:                    DEVNAME(sc), bwfm->sc_chip.ch_name);
                    466:                return;
                    467:        }
                    468:
                    469:        if (firmware_open("if_bwfm", name, &fwh) != 0) {
                    470:                printf("%s: failed firmware_open of file %s\n",
                    471:                    DEVNAME(sc), name);
                    472:                return;
                    473:        }
                    474:        size = firmware_get_size(fwh);
                    475:        ucode = firmware_malloc(size);
                    476:        if (ucode == NULL) {
                    477:                printf("%s: failed to allocate firmware memory\n",
                    478:                    DEVNAME(sc));
                    479:                firmware_close(fwh);
                    480:                return;
                    481:        }
                    482:        error = firmware_read(fwh, 0, ucode, size);
                    483:        firmware_close(fwh);
                    484:        if (error != 0) {
                    485:                printf("%s: failed to read firmware (error %d)\n",
                    486:                    DEVNAME(sc), error);
                    487:                firmware_free(ucode, size);
                    488:                return;
                    489:        }
                    490:
                    491:        /* Retrieve RAM size from firmware. */
                    492:        if (size >= BWFM_RAMSIZE + 8) {
                    493:                uint32_t *ramsize = (uint32_t *)&ucode[BWFM_RAMSIZE];
                    494:                if (letoh32(ramsize[0]) == BWFM_RAMSIZE_MAGIC)
                    495:                        bwfm->sc_chip.ch_ramsize = letoh32(ramsize[1]);
                    496:        }
                    497:
                    498:        if (bwfm_pci_load_microcode(sc, ucode, size) != 0) {
                    499:                printf("%s: could not load microcode\n",
                    500:                    DEVNAME(sc));
                    501:                kmem_free(ucode, size);
                    502:                return;
                    503:        }
                    504:
                    505:        firmware_free(ucode, size);
                    506:
                    507:        sc->sc_shared_flags = bus_space_read_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,
                    508:            sc->sc_shared_address + BWFM_SHARED_INFO);
                    509:        sc->sc_shared_version = sc->sc_shared_flags;
                    510:        if (sc->sc_shared_version > BWFM_SHARED_INFO_MAX_VERSION ||
                    511:            sc->sc_shared_version < BWFM_SHARED_INFO_MIN_VERSION) {
                    512:                printf("%s: PCIe version %d unsupported\n",
                    513:                    DEVNAME(sc), sc->sc_shared_version);
                    514:                return;
                    515:        }
                    516:
                    517:        if (sc->sc_shared_flags & BWFM_SHARED_INFO_DMA_INDEX) {
                    518:                if (sc->sc_shared_flags & BWFM_SHARED_INFO_DMA_2B_IDX)
                    519:                        sc->sc_dma_idx_sz = sizeof(uint16_t);
                    520:                else
                    521:                        sc->sc_dma_idx_sz = sizeof(uint32_t);
                    522:        }
                    523:
                    524:        /* Maximum RX data buffers in the ring. */
                    525:        sc->sc_max_rxbufpost = bus_space_read_2(sc->sc_tcm_iot, sc->sc_tcm_ioh,
                    526:            sc->sc_shared_address + BWFM_SHARED_MAX_RXBUFPOST);
                    527:        if (sc->sc_max_rxbufpost == 0)
                    528:                sc->sc_max_rxbufpost = BWFM_SHARED_MAX_RXBUFPOST_DEFAULT;
                    529:
                    530:        /* Alternative offset of data in a packet */
                    531:        sc->sc_rx_dataoffset = bus_space_read_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,
                    532:            sc->sc_shared_address + BWFM_SHARED_RX_DATAOFFSET);
                    533:
                    534:        /* For Power Management */
                    535:        sc->sc_htod_mb_data_addr = bus_space_read_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,
                    536:            sc->sc_shared_address + BWFM_SHARED_HTOD_MB_DATA_ADDR);
                    537:        sc->sc_dtoh_mb_data_addr = bus_space_read_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,
                    538:            sc->sc_shared_address + BWFM_SHARED_DTOH_MB_DATA_ADDR);
                    539:
                    540:        /* Ring information */
                    541:        sc->sc_ring_info_addr = bus_space_read_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,
                    542:            sc->sc_shared_address + BWFM_SHARED_RING_INFO_ADDR);
                    543:
                    544:        /* Firmware's "dmesg" */
                    545:        sc->sc_console_base_addr = bus_space_read_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,
                    546:            sc->sc_shared_address + BWFM_SHARED_CONSOLE_ADDR);
                    547:        sc->sc_console_buf_addr = bus_space_read_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,
                    548:            sc->sc_console_base_addr + BWFM_CONSOLE_BUFADDR);
                    549:        sc->sc_console_buf_size = bus_space_read_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,
                    550:            sc->sc_console_base_addr + BWFM_CONSOLE_BUFSIZE);
                    551:
                    552:        /* Read ring information. */
                    553:        bus_space_read_region_1(sc->sc_tcm_iot, sc->sc_tcm_ioh,
                    554:            sc->sc_ring_info_addr, (void *)&ringinfo, sizeof(ringinfo));
                    555:
                    556:        if (sc->sc_shared_version >= 6) {
                    557:                sc->sc_max_submissionrings = le16toh(ringinfo.max_submissionrings);
                    558:                sc->sc_max_flowrings = le16toh(ringinfo.max_flowrings);
                    559:                sc->sc_max_completionrings = le16toh(ringinfo.max_completionrings);
                    560:        } else {
                    561:                sc->sc_max_submissionrings = le16toh(ringinfo.max_flowrings);
                    562:                sc->sc_max_flowrings = sc->sc_max_submissionrings -
                    563:                    BWFM_NUM_TX_MSGRINGS;
                    564:                sc->sc_max_completionrings = BWFM_NUM_RX_MSGRINGS;
                    565:        }
                    566:
                    567:        if (sc->sc_dma_idx_sz == 0) {
                    568:                d2h_w_idx_ptr = letoh32(ringinfo.d2h_w_idx_ptr);
                    569:                d2h_r_idx_ptr = letoh32(ringinfo.d2h_r_idx_ptr);
                    570:                h2d_w_idx_ptr = letoh32(ringinfo.h2d_w_idx_ptr);
                    571:                h2d_r_idx_ptr = letoh32(ringinfo.h2d_r_idx_ptr);
                    572:                idx_offset = sizeof(uint32_t);
                    573:        } else {
                    574:                uint64_t address;
                    575:
                    576:                /* Each TX/RX Ring has a Read and Write Ptr */
                    577:                sc->sc_dma_idx_bufsz = (sc->sc_max_submissionrings +
                    578:                    sc->sc_max_completionrings) * sc->sc_dma_idx_sz * 2;
                    579:                sc->sc_dma_idx_buf = bwfm_pci_dmamem_alloc(sc,
                    580:                    sc->sc_dma_idx_bufsz, 8);
                    581:                if (sc->sc_dma_idx_buf == NULL) {
                    582:                        /* XXX: Fallback to TCM? */
                    583:                        printf("%s: cannot allocate idx buf\n",
                    584:                            DEVNAME(sc));
                    585:                        return;
                    586:                }
                    587:
                    588:                idx_offset = sc->sc_dma_idx_sz;
                    589:                h2d_w_idx_ptr = 0;
                    590:                address = BWFM_PCI_DMA_DVA(sc->sc_dma_idx_buf);
                    591:                ringinfo.h2d_w_idx_hostaddr_low =
                    592:                    htole32(address & 0xffffffff);
                    593:                ringinfo.h2d_w_idx_hostaddr_high =
                    594:                    htole32(address >> 32);
                    595:
                    596:                h2d_r_idx_ptr = h2d_w_idx_ptr +
                    597:                    sc->sc_max_submissionrings * idx_offset;
                    598:                address += sc->sc_max_submissionrings * idx_offset;
                    599:                ringinfo.h2d_r_idx_hostaddr_low =
                    600:                    htole32(address & 0xffffffff);
                    601:                ringinfo.h2d_r_idx_hostaddr_high =
                    602:                    htole32(address >> 32);
                    603:
                    604:                d2h_w_idx_ptr = h2d_r_idx_ptr +
                    605:                    sc->sc_max_submissionrings * idx_offset;
                    606:                address += sc->sc_max_submissionrings * idx_offset;
                    607:                ringinfo.d2h_w_idx_hostaddr_low =
                    608:                    htole32(address & 0xffffffff);
                    609:                ringinfo.d2h_w_idx_hostaddr_high =
                    610:                    htole32(address >> 32);
                    611:
                    612:                d2h_r_idx_ptr = d2h_w_idx_ptr +
                    613:                    sc->sc_max_completionrings * idx_offset;
                    614:                address += sc->sc_max_completionrings * idx_offset;
                    615:                ringinfo.d2h_r_idx_hostaddr_low =
                    616:                    htole32(address & 0xffffffff);
                    617:                ringinfo.d2h_r_idx_hostaddr_high =
                    618:                    htole32(address >> 32);
                    619:
                    620:                bus_space_write_region_1(sc->sc_tcm_iot, sc->sc_tcm_ioh,
                    621:                    sc->sc_ring_info_addr, (void *)&ringinfo, sizeof(ringinfo));
                    622:        }
                    623:
                    624:        uint32_t ring_mem_ptr = letoh32(ringinfo.ringmem);
                    625:        /* TX ctrl ring: Send ctrl buffers, send IOCTLs */
                    626:        if (bwfm_pci_setup_ring(sc, &sc->sc_ctrl_submit, 64, 40,
                    627:            h2d_w_idx_ptr, h2d_r_idx_ptr, 0, idx_offset,
                    628:            &ring_mem_ptr))
                    629:                goto cleanup;
                    630:        /* TX rxpost ring: Send clean data mbufs for RX */
                    631:        if (bwfm_pci_setup_ring(sc, &sc->sc_rxpost_submit, 512, 32,
                    632:            h2d_w_idx_ptr, h2d_r_idx_ptr, 1, idx_offset,
                    633:            &ring_mem_ptr))
                    634:                goto cleanup;
                    635:        /* RX completion rings: recv our filled buffers back */
                    636:        if (bwfm_pci_setup_ring(sc, &sc->sc_ctrl_complete, 64, 24,
                    637:            d2h_w_idx_ptr, d2h_r_idx_ptr, 0, idx_offset,
                    638:            &ring_mem_ptr))
                    639:                goto cleanup;
                    640:        if (bwfm_pci_setup_ring(sc, &sc->sc_tx_complete, 1024, 16,
                    641:            d2h_w_idx_ptr, d2h_r_idx_ptr, 1, idx_offset,
                    642:            &ring_mem_ptr))
                    643:                goto cleanup;
                    644:        if (bwfm_pci_setup_ring(sc, &sc->sc_rx_complete, 512, 32,
                    645:            d2h_w_idx_ptr, d2h_r_idx_ptr, 2, idx_offset,
                    646:            &ring_mem_ptr))
                    647:                goto cleanup;
                    648:
                    649:        /* Dynamic TX rings for actual data */
                    650:        sc->sc_flowrings = kmem_zalloc(sc->sc_max_flowrings *
                    651:            sizeof(struct bwfm_pci_msgring), KM_SLEEP);
                    652:        for (i = 0; i < sc->sc_max_flowrings; i++) {
                    653:                struct bwfm_pci_msgring *ring = &sc->sc_flowrings[i];
                    654:                ring->w_idx_addr = h2d_w_idx_ptr + (i + 2) * idx_offset;
                    655:                ring->r_idx_addr = h2d_r_idx_ptr + (i + 2) * idx_offset;
                    656:        }
                    657:
                    658:        pool_init(&sc->sc_flowring_pool, sizeof(struct bwfm_cmd_flowring_create),
                    659:            0, 0, 0, "bwfmpl", NULL, IPL_NET);
                    660:
                    661:        /* Scratch and ring update buffers for firmware */
                    662:        if ((sc->sc_scratch_buf = bwfm_pci_dmamem_alloc(sc,
                    663:            BWFM_DMA_D2H_SCRATCH_BUF_LEN, 8)) == NULL)
                    664:                goto cleanup;
                    665:        bus_space_write_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,
                    666:            sc->sc_shared_address + BWFM_SHARED_DMA_SCRATCH_ADDR_LOW,
                    667:            BWFM_PCI_DMA_DVA(sc->sc_scratch_buf) & 0xffffffff);
                    668:        bus_space_write_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,
                    669:            sc->sc_shared_address + BWFM_SHARED_DMA_SCRATCH_ADDR_HIGH,
                    670:            BWFM_PCI_DMA_DVA(sc->sc_scratch_buf) >> 32);
                    671:        bus_space_write_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,
                    672:            sc->sc_shared_address + BWFM_SHARED_DMA_SCRATCH_LEN,
                    673:            BWFM_DMA_D2H_SCRATCH_BUF_LEN);
                    674:
                    675:        if ((sc->sc_ringupd_buf = bwfm_pci_dmamem_alloc(sc,
                    676:            BWFM_DMA_D2H_RINGUPD_BUF_LEN, 8)) == NULL)
                    677:                goto cleanup;
                    678:        bus_space_write_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,
                    679:            sc->sc_shared_address + BWFM_SHARED_DMA_RINGUPD_ADDR_LOW,
                    680:            BWFM_PCI_DMA_DVA(sc->sc_ringupd_buf) & 0xffffffff);
                    681:        bus_space_write_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,
                    682:            sc->sc_shared_address + BWFM_SHARED_DMA_RINGUPD_ADDR_HIGH,
                    683:            BWFM_PCI_DMA_DVA(sc->sc_ringupd_buf) >> 32);
                    684:        bus_space_write_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,
                    685:            sc->sc_shared_address + BWFM_SHARED_DMA_RINGUPD_LEN,
                    686:            BWFM_DMA_D2H_RINGUPD_BUF_LEN);
                    687:
                    688:        if ((sc->sc_ioctl_buf = bwfm_pci_dmamem_alloc(sc,
                    689:            BWFM_DMA_H2D_IOCTL_BUF_LEN, 8)) == NULL)
                    690:                goto cleanup;
                    691:
                    692:        if (workqueue_create(&sc->flowring_wq, "bwfmflow",
                    693:            bwfm_pci_flowring_create_cb, sc, PRI_SOFTNET, IPL_NET, 0))
                    694:                goto cleanup;
                    695:
                    696:        bwfm_pci_select_core(sc, BWFM_AGENT_CORE_PCIE2);
                    697:        bwfm_pci_intr_enable(sc);
                    698:
                    699:        /* Maps RX mbufs to a packet id and back. */
                    700:        sc->sc_rx_pkts.npkt = BWFM_NUM_RX_PKTIDS;
                    701:        sc->sc_rx_pkts.pkts = kmem_zalloc(BWFM_NUM_RX_PKTIDS *
                    702:            sizeof(struct bwfm_pci_buf), KM_SLEEP);
                    703:        for (i = 0; i < BWFM_NUM_RX_PKTIDS; i++)
                    704:                bus_dmamap_create(sc->sc_dmat, MSGBUF_MAX_PKT_SIZE,
                    705:                    BWFM_NUM_RX_DESCS, MSGBUF_MAX_PKT_SIZE, 0, BUS_DMA_WAITOK,
                    706:                    &sc->sc_rx_pkts.pkts[i].bb_map);
                    707:
                    708:        /* Maps TX mbufs to a packet id and back. */
                    709:        sc->sc_tx_pkts.npkt = BWFM_NUM_TX_PKTIDS;
                    710:        sc->sc_tx_pkts.pkts = kmem_zalloc(BWFM_NUM_TX_PKTIDS
                    711:            * sizeof(struct bwfm_pci_buf), KM_SLEEP);
                    712:        for (i = 0; i < BWFM_NUM_TX_PKTIDS; i++)
                    713:                bus_dmamap_create(sc->sc_dmat, MSGBUF_MAX_PKT_SIZE,
                    714:                    BWFM_NUM_TX_DESCS, MSGBUF_MAX_PKT_SIZE, 0, BUS_DMA_WAITOK,
                    715:                    &sc->sc_tx_pkts.pkts[i].bb_map);
                    716:
                    717:        /*
                    718:         * For whatever reason, could also be a bug somewhere in this
                    719:         * driver, the firmware needs a bunch of RX buffers otherwise
                    720:         * it won't send any RX complete messages.  64 buffers don't
                    721:         * suffice, but 128 buffers are enough.
                    722:         */
                    723:        if_rxr_init(&sc->sc_rxbuf_ring, 128, sc->sc_max_rxbufpost);
                    724:        if_rxr_init(&sc->sc_ioctl_ring, 8, 8);
                    725:        if_rxr_init(&sc->sc_event_ring, 8, 8);
                    726:        bwfm_pci_fill_rx_rings(sc);
                    727:
                    728:
                    729: #ifdef BWFM_DEBUG
                    730:        sc->sc_console_readidx = 0;
                    731:        bwfm_pci_debug_console(sc);
                    732: #endif
                    733:
                    734:        sc->sc_ioctl_poll = 1;
                    735:        sc->sc_sc.sc_bus_ops = &bwfm_pci_bus_ops;
                    736:        sc->sc_sc.sc_proto_ops = &bwfm_pci_msgbuf_ops;
                    737:        bwfm_attach(&sc->sc_sc);
                    738:        sc->sc_ioctl_poll = 0;
                    739:        return;
                    740:
                    741: cleanup:
                    742:        if (sc->flowring_wq != NULL)
                    743:                workqueue_destroy(sc->flowring_wq);
                    744:        if (sc->sc_ih != NULL) {
                    745:                pci_intr_disestablish(sc->sc_pc, sc->sc_ih);
                    746:                pci_intr_release(sc->sc_pc, sc->sc_pihp, 1);
                    747:        }
                    748:        if (sc->sc_ioctl_buf)
                    749:                bwfm_pci_dmamem_free(sc, sc->sc_ioctl_buf);
                    750:        if (sc->sc_ringupd_buf)
                    751:                bwfm_pci_dmamem_free(sc, sc->sc_ringupd_buf);
                    752:        if (sc->sc_scratch_buf)
                    753:                bwfm_pci_dmamem_free(sc, sc->sc_scratch_buf);
                    754:        if (sc->sc_rx_complete.ring)
                    755:                bwfm_pci_dmamem_free(sc, sc->sc_rx_complete.ring);
                    756:        if (sc->sc_tx_complete.ring)
                    757:                bwfm_pci_dmamem_free(sc, sc->sc_tx_complete.ring);
                    758:        if (sc->sc_ctrl_complete.ring)
                    759:                bwfm_pci_dmamem_free(sc, sc->sc_ctrl_complete.ring);
                    760:        if (sc->sc_rxpost_submit.ring)
                    761:                bwfm_pci_dmamem_free(sc, sc->sc_rxpost_submit.ring);
                    762:        if (sc->sc_ctrl_submit.ring)
                    763:                bwfm_pci_dmamem_free(sc, sc->sc_ctrl_submit.ring);
                    764:        if (sc->sc_dma_idx_buf)
                    765:                bwfm_pci_dmamem_free(sc, sc->sc_dma_idx_buf);
                    766: }
                    767:
                    768: int
                    769: bwfm_pci_load_microcode(struct bwfm_pci_softc *sc, const u_char *ucode, size_t size)
                    770: {
                    771:        struct bwfm_softc *bwfm = (void *)sc;
                    772:        struct bwfm_core *core;
                    773:        uint32_t shared;
                    774:        int i;
                    775:
                    776:        if (bwfm->sc_chip.ch_chip == BRCM_CC_43602_CHIP_ID) {
                    777:                bwfm_pci_select_core(sc, BWFM_AGENT_CORE_ARM_CR4);
                    778:                bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,
                    779:                    BWFM_PCI_ARMCR4REG_BANKIDX, 5);
                    780:                bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,
                    781:                    BWFM_PCI_ARMCR4REG_BANKPDA, 0);
                    782:                bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,
                    783:                    BWFM_PCI_ARMCR4REG_BANKIDX, 7);
                    784:                bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,
                    785:                    BWFM_PCI_ARMCR4REG_BANKPDA, 0);
                    786:        }
                    787:
                    788:        for (i = 0; i < size; i++)
                    789:                bus_space_write_1(sc->sc_tcm_iot, sc->sc_tcm_ioh,
                    790:                    bwfm->sc_chip.ch_rambase + i, ucode[i]);
                    791:
                    792:        /* Firmware replaces this with a pointer once up. */
                    793:        bus_space_write_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,
                    794:            bwfm->sc_chip.ch_rambase + bwfm->sc_chip.ch_ramsize - 4, 0);
                    795:
                    796:        /* TODO: restore NVRAM */
                    797:
                    798:        /* Load reset vector from firmware and kickstart core. */
                    799:        if (bwfm->sc_chip.ch_chip == BRCM_CC_43602_CHIP_ID) {
                    800:                core = bwfm_chip_get_core(bwfm, BWFM_AGENT_INTERNAL_MEM);
                    801:                bwfm->sc_chip.ch_core_reset(bwfm, core, 0, 0, 0);
                    802:        }
                    803:        bwfm_chip_set_active(bwfm, *(const uint32_t *)ucode);
                    804:
                    805:        for (i = 0; i < 40; i++) {
                    806:                delay(50 * 1000);
                    807:                shared = bus_space_read_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,
                    808:                    bwfm->sc_chip.ch_rambase + bwfm->sc_chip.ch_ramsize - 4);
                    809:                if (shared)
                    810:                        break;
                    811:        }
                    812:        if (!shared) {
                    813:                printf("%s: firmware did not come up\n", DEVNAME(sc));
                    814:                return 1;
                    815:        }
                    816:
                    817:        sc->sc_shared_address = shared;
                    818:        return 0;
                    819: }
                    820:
                    821: int
                    822: bwfm_pci_detach(device_t self, int flags)
                    823: {
                    824:        struct bwfm_pci_softc *sc = device_private(self);
                    825:
                    826:        bwfm_detach(&sc->sc_sc, flags);
                    827:
                    828:        /* FIXME: free RX buffers */
                    829:        /* FIXME: free TX buffers */
                    830:        /* FIXME: free more memory */
                    831:
                    832:        kmem_free(sc->sc_flowrings, sc->sc_max_flowrings
                    833:            * sizeof(struct bwfm_pci_msgring));
                    834:        pool_destroy(&sc->sc_flowring_pool);
                    835:
                    836:        workqueue_destroy(sc->flowring_wq);
                    837:        pci_intr_disestablish(sc->sc_pc, sc->sc_ih);
                    838:        pci_intr_release(sc->sc_pc, sc->sc_pihp, 1);
                    839:        bwfm_pci_dmamem_free(sc, sc->sc_ioctl_buf);
                    840:        bwfm_pci_dmamem_free(sc, sc->sc_ringupd_buf);
                    841:        bwfm_pci_dmamem_free(sc, sc->sc_scratch_buf);
                    842:        bwfm_pci_dmamem_free(sc, sc->sc_rx_complete.ring);
                    843:        bwfm_pci_dmamem_free(sc, sc->sc_tx_complete.ring);
                    844:        bwfm_pci_dmamem_free(sc, sc->sc_ctrl_complete.ring);
                    845:        bwfm_pci_dmamem_free(sc, sc->sc_rxpost_submit.ring);
                    846:        bwfm_pci_dmamem_free(sc, sc->sc_ctrl_submit.ring);
                    847:        bwfm_pci_dmamem_free(sc, sc->sc_dma_idx_buf);
                    848:        return 0;
                    849: }
                    850:
                    851: /* DMA code */
                    852: struct bwfm_pci_dmamem *
                    853: bwfm_pci_dmamem_alloc(struct bwfm_pci_softc *sc, bus_size_t size, bus_size_t align)
                    854: {
                    855:        struct bwfm_pci_dmamem *bdm;
                    856:        int nsegs;
                    857:
                    858:        bdm = kmem_zalloc(sizeof(*bdm), KM_SLEEP);
                    859:        bdm->bdm_size = size;
                    860:
                    861:        if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
                    862:            BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW, &bdm->bdm_map) != 0)
                    863:                goto bdmfree;
                    864:
                    865:        if (bus_dmamem_alloc(sc->sc_dmat, size, align, 0, &bdm->bdm_seg, 1,
                    866:            &nsegs, BUS_DMA_WAITOK) != 0)
                    867:                goto destroy;
                    868:
                    869:        if (bus_dmamem_map(sc->sc_dmat, &bdm->bdm_seg, nsegs, size,
                    870:            (void **) &bdm->bdm_kva, BUS_DMA_WAITOK | BUS_DMA_COHERENT) != 0)
                    871:                goto free;
                    872:
                    873:        if (bus_dmamap_load(sc->sc_dmat, bdm->bdm_map, bdm->bdm_kva, size,
                    874:            NULL, BUS_DMA_WAITOK) != 0)
                    875:                goto unmap;
                    876:
                    877:        bzero(bdm->bdm_kva, size);
                    878:
                    879:        return (bdm);
                    880:
                    881: unmap:
                    882:        bus_dmamem_unmap(sc->sc_dmat, bdm->bdm_kva, size);
                    883: free:
                    884:        bus_dmamem_free(sc->sc_dmat, &bdm->bdm_seg, 1);
                    885: destroy:
                    886:        bus_dmamap_destroy(sc->sc_dmat, bdm->bdm_map);
                    887: bdmfree:
                    888:        kmem_free(bdm, sizeof(*bdm));
                    889:
                    890:        return (NULL);
                    891: }
                    892:
                    893: void
                    894: bwfm_pci_dmamem_free(struct bwfm_pci_softc *sc, struct bwfm_pci_dmamem *bdm)
                    895: {
                    896:        bus_dmamem_unmap(sc->sc_dmat, bdm->bdm_kva, bdm->bdm_size);
                    897:        bus_dmamem_free(sc->sc_dmat, &bdm->bdm_seg, 1);
                    898:        bus_dmamap_destroy(sc->sc_dmat, bdm->bdm_map);
                    899:        kmem_free(bdm, sizeof(*bdm));
                    900: }
                    901:
                    902: /*
                    903:  * We need a simple mapping from a packet ID to mbufs, because when
                    904:  * a transfer completed, we only know the ID so we have to look up
                    905:  * the memory for the ID.  This simply looks for an empty slot.
                    906:  */
                    907: int
                    908: bwfm_pci_pktid_avail(struct bwfm_pci_softc *sc, struct bwfm_pci_pkts *pkts)
                    909: {
                    910:        int i, idx;
                    911:
                    912:        idx = pkts->last + 1;
                    913:        for (i = 0; i < pkts->npkt; i++) {
                    914:                if (idx == pkts->npkt)
                    915:                        idx = 0;
                    916:                if (pkts->pkts[idx].bb_m == NULL)
                    917:                        return 0;
                    918:                idx++;
                    919:        }
                    920:        return ENOBUFS;
                    921: }
                    922:
                    923: int
                    924: bwfm_pci_pktid_new(struct bwfm_pci_softc *sc, struct bwfm_pci_pkts *pkts,
1.2       riastrad  925:     struct mbuf **mp, uint32_t *pktid, paddr_t *paddr)
1.1       maya      926: {
                    927:        int i, idx;
                    928:
                    929:        idx = pkts->last + 1;
                    930:        for (i = 0; i < pkts->npkt; i++) {
                    931:                if (idx == pkts->npkt)
                    932:                        idx = 0;
                    933:                if (pkts->pkts[idx].bb_m == NULL) {
                    934:                        if (bus_dmamap_load_mbuf(sc->sc_dmat,
1.2       riastrad  935:                            pkts->pkts[idx].bb_map, *mp, BUS_DMA_NOWAIT) != 0) {
                    936:                                /*
                    937:                                 * Didn't fit.  Maybe it has too many
                    938:                                 * segments.  If it has only one
                    939:                                 * segment, fail; otherwise try to
                    940:                                 * compact it into a single mbuf
                    941:                                 * segment.
                    942:                                 */
                    943:                                if ((*mp)->m_next == NULL)
                    944:                                        return ENOBUFS;
                    945:                                struct mbuf *m0 = MCLGETI(NULL, M_DONTWAIT,
                    946:                                    NULL, MSGBUF_MAX_PKT_SIZE);
                    947:                                if (m0 == NULL)
                    948:                                        return ENOBUFS;
                    949:                                m_copydata(*mp, 0, (*mp)->m_pkthdr.len,
                    950:                                    mtod(m0, void *));
                    951:                                m0->m_pkthdr.len = m0->m_len =
                    952:                                    (*mp)->m_pkthdr.len;
                    953:                                m_freem(*mp);
                    954:                                *mp = m0;
1.1       maya      955:                                if (bus_dmamap_load_mbuf(sc->sc_dmat,
1.2       riastrad  956:                                    pkts->pkts[idx].bb_map, *mp, BUS_DMA_NOWAIT) != 0)
1.1       maya      957:                                        return EFBIG;
                    958:                        }
1.4       maya      959:                        bus_dmamap_sync(sc->sc_dmat, pkts->pkts[idx].bb_map,
                    960:                            0, pkts->pkts[idx].bb_map->dm_mapsize,
                    961:                            BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1.1       maya      962:                        pkts->last = idx;
1.2       riastrad  963:                        pkts->pkts[idx].bb_m = *mp;
1.1       maya      964:                        *pktid = idx;
                    965:                        *paddr = pkts->pkts[idx].bb_map->dm_segs[0].ds_addr;
                    966:                        return 0;
                    967:                }
                    968:                idx++;
                    969:        }
                    970:        return ENOBUFS;
                    971: }
                    972:
                    973: struct mbuf *
                    974: bwfm_pci_pktid_free(struct bwfm_pci_softc *sc, struct bwfm_pci_pkts *pkts,
                    975:     uint32_t pktid)
                    976: {
                    977:        struct mbuf *m;
                    978:
                    979:        if (pktid >= pkts->npkt || pkts->pkts[pktid].bb_m == NULL)
                    980:                return NULL;
1.4       maya      981:        bus_dmamap_sync(sc->sc_dmat, pkts->pkts[pktid].bb_map, 0,
                    982:            pkts->pkts[pktid].bb_map->dm_mapsize,
                    983:            BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
1.1       maya      984:        bus_dmamap_unload(sc->sc_dmat, pkts->pkts[pktid].bb_map);
                    985:        m = pkts->pkts[pktid].bb_m;
                    986:        pkts->pkts[pktid].bb_m = NULL;
                    987:        return m;
                    988: }
                    989:
                    990: void
                    991: bwfm_pci_fill_rx_rings(struct bwfm_pci_softc *sc)
                    992: {
                    993:        bwfm_pci_fill_rx_buf_ring(sc);
                    994:        bwfm_pci_fill_rx_ioctl_ring(sc, &sc->sc_ioctl_ring,
                    995:            MSGBUF_TYPE_IOCTLRESP_BUF_POST);
                    996:        bwfm_pci_fill_rx_ioctl_ring(sc, &sc->sc_event_ring,
                    997:            MSGBUF_TYPE_EVENT_BUF_POST);
                    998: }
                    999:
                   1000: void
                   1001: bwfm_pci_fill_rx_ioctl_ring(struct bwfm_pci_softc *sc, struct if_rxring *rxring,
                   1002:     uint32_t msgtype)
                   1003: {
                   1004:        struct msgbuf_rx_ioctl_resp_or_event *req;
                   1005:        struct mbuf *m;
                   1006:        uint32_t pktid;
                   1007:        paddr_t paddr;
                   1008:        int s, slots;
1.5       martin   1009:        uint64_t devaddr;
1.1       maya     1010:
                   1011:        s = splnet();
                   1012:        for (slots = if_rxr_get(rxring, 8); slots > 0; slots--) {
                   1013:                if (bwfm_pci_pktid_avail(sc, &sc->sc_rx_pkts))
                   1014:                        break;
                   1015:                req = bwfm_pci_ring_write_reserve(sc, &sc->sc_ctrl_submit);
                   1016:                if (req == NULL)
                   1017:                        break;
                   1018:                m = MCLGETI(NULL, M_DONTWAIT, NULL, MSGBUF_MAX_PKT_SIZE);
                   1019:                if (m == NULL) {
                   1020:                        bwfm_pci_ring_write_cancel(sc, &sc->sc_ctrl_submit, 1);
                   1021:                        break;
                   1022:                }
                   1023:                m->m_len = m->m_pkthdr.len = MSGBUF_MAX_PKT_SIZE;
1.2       riastrad 1024:                if (bwfm_pci_pktid_new(sc, &sc->sc_rx_pkts, &m, &pktid, &paddr)) {
1.1       maya     1025:                        bwfm_pci_ring_write_cancel(sc, &sc->sc_ctrl_submit, 1);
                   1026:                        m_freem(m);
                   1027:                        break;
                   1028:                }
1.5       martin   1029:                devaddr = paddr;
1.1       maya     1030:                memset(req, 0, sizeof(*req));
                   1031:                req->msg.msgtype = msgtype;
                   1032:                req->msg.request_id = htole32(pktid);
                   1033:                req->host_buf_len = htole16(MSGBUF_MAX_PKT_SIZE);
1.5       martin   1034:                req->host_buf_addr.high_addr = htole32(devaddr >> 32);
                   1035:                req->host_buf_addr.low_addr = htole32(devaddr & 0xffffffff);
1.1       maya     1036:                bwfm_pci_ring_write_commit(sc, &sc->sc_ctrl_submit);
                   1037:        }
                   1038:        if_rxr_put(rxring, slots);
                   1039:        splx(s);
                   1040: }
                   1041:
                   1042: void
                   1043: bwfm_pci_fill_rx_buf_ring(struct bwfm_pci_softc *sc)
                   1044: {
                   1045:        struct msgbuf_rx_bufpost *req;
                   1046:        struct mbuf *m;
                   1047:        uint32_t pktid;
                   1048:        paddr_t paddr;
                   1049:        int s, slots;
1.5       martin   1050:        uint64_t devaddr;
1.1       maya     1051:
                   1052:        s = splnet();
                   1053:        for (slots = if_rxr_get(&sc->sc_rxbuf_ring, sc->sc_max_rxbufpost);
                   1054:            slots > 0; slots--) {
                   1055:                if (bwfm_pci_pktid_avail(sc, &sc->sc_rx_pkts))
                   1056:                        break;
                   1057:                req = bwfm_pci_ring_write_reserve(sc, &sc->sc_rxpost_submit);
                   1058:                if (req == NULL)
                   1059:                        break;
                   1060:                m = MCLGETI(NULL, M_DONTWAIT, NULL, MSGBUF_MAX_PKT_SIZE);
                   1061:                if (m == NULL) {
                   1062:                        bwfm_pci_ring_write_cancel(sc, &sc->sc_rxpost_submit, 1);
                   1063:                        break;
                   1064:                }
                   1065:                m->m_len = m->m_pkthdr.len = MSGBUF_MAX_PKT_SIZE;
1.2       riastrad 1066:                if (bwfm_pci_pktid_new(sc, &sc->sc_rx_pkts, &m, &pktid, &paddr)) {
1.1       maya     1067:                        bwfm_pci_ring_write_cancel(sc, &sc->sc_rxpost_submit, 1);
                   1068:                        m_freem(m);
                   1069:                        break;
                   1070:                }
1.5       martin   1071:                devaddr = paddr;
1.1       maya     1072:                memset(req, 0, sizeof(*req));
                   1073:                req->msg.msgtype = MSGBUF_TYPE_RXBUF_POST;
                   1074:                req->msg.request_id = htole32(pktid);
                   1075:                req->data_buf_len = htole16(MSGBUF_MAX_PKT_SIZE);
1.5       martin   1076:                req->data_buf_addr.high_addr = htole32(devaddr >> 32);
                   1077:                req->data_buf_addr.low_addr = htole32(devaddr & 0xffffffff);
1.1       maya     1078:                bwfm_pci_ring_write_commit(sc, &sc->sc_rxpost_submit);
                   1079:        }
                   1080:        if_rxr_put(&sc->sc_rxbuf_ring, slots);
                   1081:        splx(s);
                   1082: }
                   1083:
                   1084: int
                   1085: bwfm_pci_setup_ring(struct bwfm_pci_softc *sc, struct bwfm_pci_msgring *ring,
                   1086:     int nitem, size_t itemsz, uint32_t w_idx, uint32_t r_idx,
                   1087:     int idx, uint32_t idx_off, uint32_t *ring_mem)
                   1088: {
                   1089:        ring->w_idx_addr = w_idx + idx * idx_off;
                   1090:        ring->r_idx_addr = r_idx + idx * idx_off;
                   1091:        ring->nitem = nitem;
                   1092:        ring->itemsz = itemsz;
                   1093:        bwfm_pci_ring_write_rptr(sc, ring);
                   1094:        bwfm_pci_ring_write_wptr(sc, ring);
                   1095:
                   1096:        ring->ring = bwfm_pci_dmamem_alloc(sc, nitem * itemsz, 8);
                   1097:        if (ring->ring == NULL)
                   1098:                return ENOMEM;
                   1099:        bus_space_write_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,
                   1100:            *ring_mem + BWFM_RING_MEM_BASE_ADDR_LOW,
                   1101:            BWFM_PCI_DMA_DVA(ring->ring) & 0xffffffff);
                   1102:        bus_space_write_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,
                   1103:            *ring_mem + BWFM_RING_MEM_BASE_ADDR_HIGH,
                   1104:            BWFM_PCI_DMA_DVA(ring->ring) >> 32);
                   1105:        bus_space_write_2(sc->sc_tcm_iot, sc->sc_tcm_ioh,
                   1106:            *ring_mem + BWFM_RING_MAX_ITEM, nitem);
                   1107:        bus_space_write_2(sc->sc_tcm_iot, sc->sc_tcm_ioh,
                   1108:            *ring_mem + BWFM_RING_LEN_ITEMS, itemsz);
                   1109:        *ring_mem = *ring_mem + BWFM_RING_MEM_SZ;
                   1110:        return 0;
                   1111: }
                   1112:
                   1113: int
                   1114: bwfm_pci_setup_flowring(struct bwfm_pci_softc *sc, struct bwfm_pci_msgring *ring,
                   1115:     int nitem, size_t itemsz)
                   1116: {
                   1117:        ring->w_ptr = 0;
                   1118:        ring->r_ptr = 0;
                   1119:        ring->nitem = nitem;
                   1120:        ring->itemsz = itemsz;
                   1121:        bwfm_pci_ring_write_rptr(sc, ring);
                   1122:        bwfm_pci_ring_write_wptr(sc, ring);
                   1123:
                   1124:        ring->ring = bwfm_pci_dmamem_alloc(sc, nitem * itemsz, 8);
                   1125:        if (ring->ring == NULL)
                   1126:                return ENOMEM;
                   1127:        return 0;
                   1128: }
                   1129:
                   1130: /* Ring helpers */
                   1131: void
                   1132: bwfm_pci_ring_bell(struct bwfm_pci_softc *sc,
                   1133:     struct bwfm_pci_msgring *ring)
                   1134: {
                   1135:        bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,
                   1136:            BWFM_PCI_PCIE2REG_H2D_MAILBOX, 1);
                   1137: }
                   1138:
                   1139: void
                   1140: bwfm_pci_ring_update_rptr(struct bwfm_pci_softc *sc,
                   1141:     struct bwfm_pci_msgring *ring)
                   1142: {
                   1143:        if (sc->sc_dma_idx_sz == 0) {
                   1144:                ring->r_ptr = bus_space_read_2(sc->sc_tcm_iot,
                   1145:                    sc->sc_tcm_ioh, ring->r_idx_addr);
                   1146:        } else {
1.4       maya     1147:                bus_dmamap_sync(sc->sc_dmat,
                   1148:                    BWFM_PCI_DMA_MAP(sc->sc_dma_idx_buf), ring->r_idx_addr,
                   1149:                    sizeof(uint16_t), BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
1.1       maya     1150:                ring->r_ptr = *(uint16_t *)(BWFM_PCI_DMA_KVA(sc->sc_dma_idx_buf)
                   1151:                    + ring->r_idx_addr);
                   1152:        }
                   1153: }
                   1154:
                   1155: static u_int
                   1156: if_rxr_get(struct if_rxring *rxr, unsigned int max)
                   1157: {
                   1158:        u_int taken = MIN(max, (rxr->rxr_total - rxr->rxr_inuse));
                   1159:
                   1160:        KASSERTMSG(rxr->rxr_inuse + taken <= rxr->rxr_total,
                   1161:                        "rxr->rxr_inuse: %d\n"
                   1162:                        "taken: %d\n"
                   1163:                        "rxr->rxr_total: %d\n",
                   1164:                        rxr->rxr_inuse, taken, rxr->rxr_total);
                   1165:        rxr->rxr_inuse += taken;
                   1166:
                   1167:        return taken;
                   1168: }
                   1169:
                   1170: static void
                   1171: if_rxr_put(struct if_rxring *rxr, unsigned int n)
                   1172: {
                   1173:        KASSERTMSG(rxr->rxr_inuse >= n,
                   1174:                        "rxr->rxr_inuse: %d\n"
                   1175:                        "n: %d\n"
                   1176:                        "rxr->rxr_total: %d\n",
                   1177:                        rxr->rxr_inuse, n, rxr->rxr_total);
                   1178:
                   1179:        rxr->rxr_inuse -= n;
                   1180: }
                   1181:
                   1182: static void
                   1183: if_rxr_init(struct if_rxring *rxr, unsigned int lwm __unused, unsigned int hwm)
                   1184: {
                   1185:        (void) lwm;
                   1186:
                   1187:        rxr->rxr_total = hwm;
                   1188:        rxr->rxr_inuse = 0;
                   1189: }
                   1190:
                   1191: void
                   1192: bwfm_pci_ring_update_wptr(struct bwfm_pci_softc *sc,
                   1193:     struct bwfm_pci_msgring *ring)
                   1194: {
                   1195:        if (sc->sc_dma_idx_sz == 0) {
                   1196:                ring->w_ptr = bus_space_read_2(sc->sc_tcm_iot,
                   1197:                    sc->sc_tcm_ioh, ring->w_idx_addr);
                   1198:        } else {
                   1199:                ring->w_ptr = *(uint16_t *)(BWFM_PCI_DMA_KVA(sc->sc_dma_idx_buf)
                   1200:                    + ring->w_idx_addr);
1.4       maya     1201:                bus_dmamap_sync(sc->sc_dmat,
                   1202:                    BWFM_PCI_DMA_MAP(sc->sc_dma_idx_buf), ring->w_idx_addr,
                   1203:                    sizeof(uint16_t), BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
1.1       maya     1204:        }
                   1205: }
                   1206:
                   1207: void
                   1208: bwfm_pci_ring_write_rptr(struct bwfm_pci_softc *sc,
                   1209:     struct bwfm_pci_msgring *ring)
                   1210: {
                   1211:        if (sc->sc_dma_idx_sz == 0) {
                   1212:                bus_space_write_2(sc->sc_tcm_iot, sc->sc_tcm_ioh,
                   1213:                    ring->r_idx_addr, ring->r_ptr);
                   1214:        } else {
                   1215:                *(uint16_t *)(BWFM_PCI_DMA_KVA(sc->sc_dma_idx_buf)
                   1216:                    + ring->r_idx_addr) = ring->r_ptr;
1.4       maya     1217:                bus_dmamap_sync(sc->sc_dmat,
                   1218:                    BWFM_PCI_DMA_MAP(sc->sc_dma_idx_buf), ring->r_idx_addr,
                   1219:                    sizeof(uint16_t), BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1.1       maya     1220:        }
                   1221: }
                   1222:
                   1223: void
                   1224: bwfm_pci_ring_write_wptr(struct bwfm_pci_softc *sc,
                   1225:     struct bwfm_pci_msgring *ring)
                   1226: {
                   1227:        if (sc->sc_dma_idx_sz == 0) {
                   1228:                bus_space_write_2(sc->sc_tcm_iot, sc->sc_tcm_ioh,
                   1229:                    ring->w_idx_addr, ring->w_ptr);
                   1230:        } else {
                   1231:                *(uint16_t *)(BWFM_PCI_DMA_KVA(sc->sc_dma_idx_buf)
                   1232:                    + ring->w_idx_addr) = ring->w_ptr;
1.4       maya     1233:                bus_dmamap_sync(sc->sc_dmat,
                   1234:                    BWFM_PCI_DMA_MAP(sc->sc_dma_idx_buf), ring->w_idx_addr,
                   1235:                    sizeof(uint16_t), BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1.1       maya     1236:        }
                   1237: }
                   1238:
                   1239: /*
                   1240:  * Retrieve a free descriptor to put new stuff in, but don't commit
                   1241:  * to it yet so we can rollback later if any error occurs.
                   1242:  */
                   1243: void *
                   1244: bwfm_pci_ring_write_reserve(struct bwfm_pci_softc *sc,
                   1245:     struct bwfm_pci_msgring *ring)
                   1246: {
                   1247:        int available;
                   1248:        char *ret;
                   1249:
                   1250:        bwfm_pci_ring_update_rptr(sc, ring);
                   1251:
                   1252:        if (ring->r_ptr > ring->w_ptr)
                   1253:                available = ring->r_ptr - ring->w_ptr;
                   1254:        else
                   1255:                available = ring->r_ptr + (ring->nitem - ring->w_ptr);
                   1256:
                   1257:        if (available < 1)
                   1258:                return NULL;
                   1259:
                   1260:        ret = BWFM_PCI_DMA_KVA(ring->ring) + (ring->w_ptr * ring->itemsz);
                   1261:        ring->w_ptr += 1;
                   1262:        if (ring->w_ptr == ring->nitem)
                   1263:                ring->w_ptr = 0;
                   1264:        return ret;
                   1265: }
                   1266:
                   1267: void *
                   1268: bwfm_pci_ring_write_reserve_multi(struct bwfm_pci_softc *sc,
                   1269:     struct bwfm_pci_msgring *ring, int count, int *avail)
                   1270: {
                   1271:        int available;
                   1272:        char *ret;
                   1273:
                   1274:        bwfm_pci_ring_update_rptr(sc, ring);
                   1275:
                   1276:        if (ring->r_ptr > ring->w_ptr)
                   1277:                available = ring->r_ptr - ring->w_ptr;
                   1278:        else
                   1279:                available = ring->r_ptr + (ring->nitem - ring->w_ptr);
                   1280:
                   1281:        if (available < 1)
                   1282:                return NULL;
                   1283:
                   1284:        ret = BWFM_PCI_DMA_KVA(ring->ring) + (ring->w_ptr * ring->itemsz);
1.3       riastrad 1285:        *avail = uimin(count, available - 1);
1.1       maya     1286:        if (*avail + ring->w_ptr > ring->nitem)
                   1287:                *avail = ring->nitem - ring->w_ptr;
                   1288:        ring->w_ptr += *avail;
                   1289:        if (ring->w_ptr == ring->nitem)
                   1290:                ring->w_ptr = 0;
                   1291:        return ret;
                   1292: }
                   1293:
                   1294: /*
                   1295:  * Read number of descriptors available (submitted by the firmware)
                   1296:  * and retrieve pointer to first descriptor.
                   1297:  */
                   1298: void *
                   1299: bwfm_pci_ring_read_avail(struct bwfm_pci_softc *sc,
                   1300:     struct bwfm_pci_msgring *ring, int *avail)
                   1301: {
                   1302:        bwfm_pci_ring_update_wptr(sc, ring);
                   1303:
                   1304:        if (ring->w_ptr >= ring->r_ptr)
                   1305:                *avail = ring->w_ptr - ring->r_ptr;
                   1306:        else
                   1307:                *avail = ring->nitem - ring->r_ptr;
                   1308:
                   1309:        if (*avail == 0)
                   1310:                return NULL;
1.4       maya     1311:        bus_dmamap_sync(sc->sc_dmat, BWFM_PCI_DMA_MAP(ring->ring),
                   1312:            ring->r_ptr * ring->itemsz, *avail * ring->itemsz,
                   1313:            BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
1.1       maya     1314:        return BWFM_PCI_DMA_KVA(ring->ring) + (ring->r_ptr * ring->itemsz);
                   1315: }
                   1316:
                   1317: /*
                   1318:  * Let firmware know we read N descriptors.
                   1319:  */
                   1320: void
                   1321: bwfm_pci_ring_read_commit(struct bwfm_pci_softc *sc,
                   1322:     struct bwfm_pci_msgring *ring, int nitem)
                   1323: {
                   1324:        ring->r_ptr += nitem;
                   1325:        if (ring->r_ptr == ring->nitem)
                   1326:                ring->r_ptr = 0;
                   1327:        bwfm_pci_ring_write_rptr(sc, ring);
                   1328: }
                   1329:
                   1330: /*
                   1331:  * Let firmware know that we submitted some descriptors.
                   1332:  */
                   1333: void
                   1334: bwfm_pci_ring_write_commit(struct bwfm_pci_softc *sc,
                   1335:     struct bwfm_pci_msgring *ring)
                   1336: {
1.4       maya     1337:        bus_dmamap_sync(sc->sc_dmat, BWFM_PCI_DMA_MAP(ring->ring),
                   1338:            0, BWFM_PCI_DMA_LEN(ring->ring), BUS_DMASYNC_PREREAD |
                   1339:            BUS_DMASYNC_PREWRITE);
1.1       maya     1340:        bwfm_pci_ring_write_wptr(sc, ring);
                   1341:        bwfm_pci_ring_bell(sc, ring);
                   1342: }
                   1343:
                   1344: /*
                   1345:  * Rollback N descriptors in case we don't actually want
                   1346:  * to commit to it.
                   1347:  */
                   1348: void
                   1349: bwfm_pci_ring_write_cancel(struct bwfm_pci_softc *sc,
                   1350:     struct bwfm_pci_msgring *ring, int nitem)
                   1351: {
                   1352:        if (ring->w_ptr == 0)
                   1353:                ring->w_ptr = ring->nitem - nitem;
                   1354:        else
                   1355:                ring->w_ptr -= nitem;
                   1356: }
                   1357:
                   1358: /*
                   1359:  * Foreach written descriptor on the ring, pass the descriptor to
                   1360:  * a message handler and let the firmware know we handled it.
                   1361:  */
                   1362: void
                   1363: bwfm_pci_ring_rx(struct bwfm_pci_softc *sc, struct bwfm_pci_msgring *ring)
                   1364: {
                   1365:        char *buf;
                   1366:        int avail, processed;
                   1367:
                   1368: again:
                   1369:        buf = bwfm_pci_ring_read_avail(sc, ring, &avail);
                   1370:        if (buf == NULL)
                   1371:                return;
                   1372:
                   1373:        processed = 0;
                   1374:        while (avail) {
                   1375:                bwfm_pci_msg_rx(sc, buf + sc->sc_rx_dataoffset);
                   1376:                buf += ring->itemsz;
                   1377:                processed++;
                   1378:                if (processed == 48) {
                   1379:                        bwfm_pci_ring_read_commit(sc, ring, processed);
                   1380:                        processed = 0;
                   1381:                }
                   1382:                avail--;
                   1383:        }
                   1384:        if (processed)
                   1385:                bwfm_pci_ring_read_commit(sc, ring, processed);
                   1386:        if (ring->r_ptr == 0)
                   1387:                goto again;
                   1388: }
                   1389:
                   1390: void
                   1391: bwfm_pci_msg_rx(struct bwfm_pci_softc *sc, void *buf)
                   1392: {
                   1393:        struct ifnet *ifp = sc->sc_sc.sc_ic.ic_ifp;
                   1394:        struct msgbuf_ioctl_resp_hdr *resp;
                   1395:        struct msgbuf_tx_status *tx;
                   1396:        struct msgbuf_rx_complete *rx;
                   1397:        struct msgbuf_rx_event *event;
                   1398:        struct msgbuf_common_hdr *msg;
                   1399:        struct msgbuf_flowring_create_resp *fcr;
                   1400:        struct msgbuf_flowring_delete_resp *fdr;
                   1401:        struct bwfm_pci_msgring *ring;
                   1402:        struct mbuf *m;
                   1403:        int flowid;
                   1404:
                   1405:        msg = (struct msgbuf_common_hdr *)buf;
                   1406:        switch (msg->msgtype)
                   1407:        {
                   1408:        case MSGBUF_TYPE_FLOW_RING_CREATE_CMPLT:
                   1409:                fcr = (struct msgbuf_flowring_create_resp *)buf;
                   1410:                flowid = letoh16(fcr->compl_hdr.flow_ring_id);
                   1411:                if (flowid < 2)
                   1412:                        break;
                   1413:                flowid -= 2;
                   1414:                if (flowid >= sc->sc_max_flowrings)
                   1415:                        break;
                   1416:                ring = &sc->sc_flowrings[flowid];
                   1417:                if (ring->status != RING_OPENING)
                   1418:                        break;
                   1419:                if (fcr->compl_hdr.status) {
                   1420:                        printf("%s: failed to open flowring %d\n",
                   1421:                            DEVNAME(sc), flowid);
                   1422:                        ring->status = RING_CLOSED;
                   1423:                        if (ring->m) {
                   1424:                                m_freem(ring->m);
                   1425:                                ring->m = NULL;
                   1426:                        }
                   1427:                        ifp->if_flags &= ~IFF_OACTIVE;
                   1428:                        ifp->if_start(ifp);
                   1429:                        break;
                   1430:                }
                   1431:                ring->status = RING_OPEN;
                   1432:                if (ring->m != NULL) {
                   1433:                        m = ring->m;
                   1434:                        ring->m = NULL;
1.2       riastrad 1435:                        if (bwfm_pci_txdata(&sc->sc_sc, &m))
1.1       maya     1436:                                m_freem(ring->m);
                   1437:                }
                   1438:                ifp->if_flags &= ~IFF_OACTIVE;
                   1439:                ifp->if_start(ifp);
                   1440:                break;
                   1441:        case MSGBUF_TYPE_FLOW_RING_DELETE_CMPLT:
                   1442:                fdr = (struct msgbuf_flowring_delete_resp *)buf;
                   1443:                flowid = letoh16(fdr->compl_hdr.flow_ring_id);
                   1444:                if (flowid < 2)
                   1445:                        break;
                   1446:                flowid -= 2;
                   1447:                if (flowid >= sc->sc_max_flowrings)
                   1448:                        break;
                   1449:                ring = &sc->sc_flowrings[flowid];
                   1450:                if (ring->status != RING_CLOSING)
                   1451:                        break;
                   1452:                if (fdr->compl_hdr.status) {
                   1453:                        printf("%s: failed to delete flowring %d\n",
                   1454:                            DEVNAME(sc), flowid);
                   1455:                        break;
                   1456:                }
                   1457:                bwfm_pci_dmamem_free(sc, ring->ring);
                   1458:                ring->status = RING_CLOSED;
                   1459:                break;
                   1460:        case MSGBUF_TYPE_IOCTLPTR_REQ_ACK:
                   1461:                break;
                   1462:        case MSGBUF_TYPE_IOCTL_CMPLT:
                   1463:                resp = (struct msgbuf_ioctl_resp_hdr *)buf;
                   1464:                sc->sc_ioctl_resp_pktid = letoh32(resp->msg.request_id);
                   1465:                sc->sc_ioctl_resp_ret_len = letoh16(resp->resp_len);
                   1466:                sc->sc_ioctl_resp_status = letoh16(resp->compl_hdr.status);
                   1467:                if_rxr_put(&sc->sc_ioctl_ring, 1);
                   1468:                bwfm_pci_fill_rx_rings(sc);
                   1469:                wakeup(&sc->sc_ioctl_buf);
                   1470:                break;
                   1471:        case MSGBUF_TYPE_WL_EVENT:
                   1472:                event = (struct msgbuf_rx_event *)buf;
                   1473:                m = bwfm_pci_pktid_free(sc, &sc->sc_rx_pkts,
                   1474:                    letoh32(event->msg.request_id));
                   1475:                if (m == NULL)
                   1476:                        break;
                   1477:                m_adj(m, sc->sc_rx_dataoffset);
                   1478:                m->m_len = m->m_pkthdr.len = letoh16(event->event_data_len);
                   1479:                bwfm_rx(&sc->sc_sc, m);
                   1480:                if_rxr_put(&sc->sc_event_ring, 1);
                   1481:                bwfm_pci_fill_rx_rings(sc);
                   1482:                break;
                   1483:        case MSGBUF_TYPE_TX_STATUS:
                   1484:                tx = (struct msgbuf_tx_status *)buf;
                   1485:                m = bwfm_pci_pktid_free(sc, &sc->sc_tx_pkts,
                   1486:                    letoh32(tx->msg.request_id));
                   1487:                if (m == NULL)
                   1488:                        break;
                   1489:                m_freem(m);
                   1490:                if (sc->sc_tx_pkts_full) {
                   1491:                        sc->sc_tx_pkts_full = 0;
                   1492:                        ifp->if_flags &= ~IFF_OACTIVE;
                   1493:                        ifp->if_start(ifp);
                   1494:                }
                   1495:                break;
                   1496:        case MSGBUF_TYPE_RX_CMPLT:
                   1497:                rx = (struct msgbuf_rx_complete *)buf;
                   1498:                m = bwfm_pci_pktid_free(sc, &sc->sc_rx_pkts,
                   1499:                    letoh32(rx->msg.request_id));
                   1500:                if (m == NULL)
                   1501:                        break;
                   1502:                if (letoh16(rx->data_offset))
                   1503:                        m_adj(m, letoh16(rx->data_offset));
                   1504:                else if (sc->sc_rx_dataoffset)
                   1505:                        m_adj(m, sc->sc_rx_dataoffset);
                   1506:                m->m_len = m->m_pkthdr.len = letoh16(rx->data_len);
                   1507:                bwfm_rx(&sc->sc_sc, m);
                   1508:                if_rxr_put(&sc->sc_rxbuf_ring, 1);
                   1509:                bwfm_pci_fill_rx_rings(sc);
                   1510:                break;
                   1511:        default:
                   1512:                printf("%s: msgtype 0x%08x\n", __func__, msg->msgtype);
                   1513:                break;
                   1514:        }
                   1515: }
                   1516:
                   1517: /* Bus core helpers */
                   1518: void
                   1519: bwfm_pci_select_core(struct bwfm_pci_softc *sc, int id)
                   1520: {
                   1521:        struct bwfm_softc *bwfm = (void *)sc;
                   1522:        struct bwfm_core *core;
                   1523:
                   1524:        core = bwfm_chip_get_core(bwfm, id);
                   1525:        if (core == NULL) {
                   1526:                printf("%s: could not find core to select", DEVNAME(sc));
                   1527:                return;
                   1528:        }
                   1529:
                   1530:        pci_conf_write(sc->sc_pc, sc->sc_tag,
                   1531:            BWFM_PCI_BAR0_WINDOW, core->co_base);
                   1532:        if (pci_conf_read(sc->sc_pc, sc->sc_tag,
                   1533:            BWFM_PCI_BAR0_WINDOW) != core->co_base)
                   1534:                pci_conf_write(sc->sc_pc, sc->sc_tag,
                   1535:                    BWFM_PCI_BAR0_WINDOW, core->co_base);
                   1536: }
                   1537:
                   1538: uint32_t
                   1539: bwfm_pci_buscore_read(struct bwfm_softc *bwfm, uint32_t reg)
                   1540: {
                   1541:        struct bwfm_pci_softc *sc = (void *)bwfm;
                   1542:        uint32_t page, offset;
                   1543:
                   1544:        page = reg & ~(BWFM_PCI_BAR0_REG_SIZE - 1);
                   1545:        offset = reg & (BWFM_PCI_BAR0_REG_SIZE - 1);
                   1546:        pci_conf_write(sc->sc_pc, sc->sc_tag, BWFM_PCI_BAR0_WINDOW, page);
                   1547:        return bus_space_read_4(sc->sc_reg_iot, sc->sc_reg_ioh, offset);
                   1548: }
                   1549:
                   1550: void
                   1551: bwfm_pci_buscore_write(struct bwfm_softc *bwfm, uint32_t reg, uint32_t val)
                   1552: {
                   1553:        struct bwfm_pci_softc *sc = (void *)bwfm;
                   1554:        uint32_t page, offset;
                   1555:
                   1556:        page = reg & ~(BWFM_PCI_BAR0_REG_SIZE - 1);
                   1557:        offset = reg & (BWFM_PCI_BAR0_REG_SIZE - 1);
                   1558:        pci_conf_write(sc->sc_pc, sc->sc_tag, BWFM_PCI_BAR0_WINDOW, page);
                   1559:        bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh, offset, val);
                   1560: }
                   1561:
                   1562: int
                   1563: bwfm_pci_buscore_prepare(struct bwfm_softc *bwfm)
                   1564: {
                   1565:        return 0;
                   1566: }
                   1567:
                   1568: int
                   1569: bwfm_pci_buscore_reset(struct bwfm_softc *bwfm)
                   1570: {
                   1571:        struct bwfm_pci_softc *sc = (void *)bwfm;
                   1572:        struct bwfm_core *core;
                   1573:        uint32_t reg;
                   1574:        int i;
                   1575:
                   1576:        bwfm_pci_select_core(sc, BWFM_AGENT_CORE_PCIE2);
                   1577:        reg = pci_conf_read(sc->sc_pc, sc->sc_tag,
                   1578:            BWFM_PCI_CFGREG_LINK_STATUS_CTRL);
                   1579:        pci_conf_write(sc->sc_pc, sc->sc_tag, BWFM_PCI_CFGREG_LINK_STATUS_CTRL,
                   1580:            reg & ~BWFM_PCI_CFGREG_LINK_STATUS_CTRL_ASPM_ENAB);
                   1581:
                   1582:        bwfm_pci_select_core(sc, BWFM_AGENT_CORE_CHIPCOMMON);
                   1583:        bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,
                   1584:            BWFM_CHIP_REG_WATCHDOG, 4);
                   1585:        delay(100 * 1000);
                   1586:
                   1587:        bwfm_pci_select_core(sc, BWFM_AGENT_CORE_PCIE2);
                   1588:        pci_conf_write(sc->sc_pc, sc->sc_tag,
                   1589:            BWFM_PCI_CFGREG_LINK_STATUS_CTRL, reg);
                   1590:
                   1591:        core = bwfm_chip_get_core(bwfm, BWFM_AGENT_CORE_PCIE2);
                   1592:        if (core->co_rev <= 13) {
                   1593:                uint16_t cfg_offset[] = {
                   1594:                    BWFM_PCI_CFGREG_STATUS_CMD,
                   1595:                    BWFM_PCI_CFGREG_PM_CSR,
                   1596:                    BWFM_PCI_CFGREG_MSI_CAP,
                   1597:                    BWFM_PCI_CFGREG_MSI_ADDR_L,
                   1598:                    BWFM_PCI_CFGREG_MSI_ADDR_H,
                   1599:                    BWFM_PCI_CFGREG_MSI_DATA,
                   1600:                    BWFM_PCI_CFGREG_LINK_STATUS_CTRL2,
                   1601:                    BWFM_PCI_CFGREG_RBAR_CTRL,
                   1602:                    BWFM_PCI_CFGREG_PML1_SUB_CTRL1,
                   1603:                    BWFM_PCI_CFGREG_REG_BAR2_CONFIG,
                   1604:                    BWFM_PCI_CFGREG_REG_BAR3_CONFIG,
                   1605:                };
                   1606:
                   1607:                for (i = 0; i < nitems(cfg_offset); i++) {
                   1608:                        bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,
                   1609:                            BWFM_PCI_PCIE2REG_CONFIGADDR, cfg_offset[i]);
                   1610:                        reg = bus_space_read_4(sc->sc_reg_iot, sc->sc_reg_ioh,
                   1611:                            BWFM_PCI_PCIE2REG_CONFIGDATA);
                   1612:                        DPRINTFN(3, ("%s: config offset 0x%04x, value 0x%04x\n",
                   1613:                            DEVNAME(sc), cfg_offset[i], reg));
                   1614:                        bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,
                   1615:                            BWFM_PCI_PCIE2REG_CONFIGDATA, reg);
                   1616:                }
                   1617:        }
                   1618:
                   1619:        reg = bus_space_read_4(sc->sc_reg_iot, sc->sc_reg_ioh,
                   1620:            BWFM_PCI_PCIE2REG_MAILBOXINT);
                   1621:        if (reg != 0xffffffff)
                   1622:                bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,
                   1623:                    BWFM_PCI_PCIE2REG_MAILBOXINT, reg);
                   1624:
                   1625:        return 0;
                   1626: }
                   1627:
                   1628: void
                   1629: bwfm_pci_buscore_activate(struct bwfm_softc *bwfm, const uint32_t rstvec)
                   1630: {
                   1631:        struct bwfm_pci_softc *sc = (void *)bwfm;
                   1632:        bus_space_write_4(sc->sc_tcm_iot, sc->sc_tcm_ioh, 0, rstvec);
                   1633: }
                   1634:
                   1635: static int bwfm_pci_prio2fifo[8] = {
                   1636:        1, /* best effort */
                   1637:        0, /* IPTOS_PREC_IMMEDIATE */
                   1638:        0, /* IPTOS_PREC_PRIORITY */
                   1639:        1, /* IPTOS_PREC_FLASH */
                   1640:        2, /* IPTOS_PREC_FLASHOVERRIDE */
                   1641:        2, /* IPTOS_PREC_CRITIC_ECP */
                   1642:        3, /* IPTOS_PREC_INTERNETCONTROL */
                   1643:        3, /* IPTOS_PREC_NETCONTROL */
                   1644: };
                   1645:
                   1646: int
                   1647: bwfm_pci_flowring_lookup(struct bwfm_pci_softc *sc, struct mbuf *m)
                   1648: {
                   1649:        struct ieee80211com *ic = &sc->sc_sc.sc_ic;
                   1650:        uint8_t *da = mtod(m, uint8_t *);
                   1651:        struct ether_header *eh;
                   1652:        int flowid, prio, fifo;
                   1653:        int i, found, ac;
                   1654:
                   1655:        /* No QoS for EAPOL frames. */
                   1656:        eh = mtod(m, struct ether_header *);
                   1657:        ac = (eh->ether_type != htons(ETHERTYPE_PAE)) ?
                   1658:            M_WME_GETAC(m) : WME_AC_BE;
                   1659:
                   1660:        prio = ac;
                   1661:        fifo = bwfm_pci_prio2fifo[prio];
                   1662:
                   1663:        switch (ic->ic_opmode)
                   1664:        {
                   1665:        case IEEE80211_M_STA:
                   1666:                flowid = fifo;
                   1667:                break;
                   1668: #ifndef IEEE80211_STA_ONLY
                   1669:        case IEEE80211_M_HOSTAP:
                   1670:                if (ETHER_IS_MULTICAST(da))
                   1671:                        da = __UNCONST(etherbroadcastaddr);
                   1672:                flowid = da[5] * 2 + fifo;
                   1673:                break;
                   1674: #endif
                   1675:        default:
                   1676:                printf("%s: state not supported\n", DEVNAME(sc));
                   1677:                return ENOBUFS;
                   1678:        }
                   1679:
                   1680:        found = 0;
                   1681:        flowid = flowid % sc->sc_max_flowrings;
                   1682:        for (i = 0; i < sc->sc_max_flowrings; i++) {
                   1683:                if (ic->ic_opmode == IEEE80211_M_STA &&
                   1684:                    sc->sc_flowrings[flowid].status >= RING_OPEN &&
                   1685:                    sc->sc_flowrings[flowid].fifo == fifo) {
                   1686:                        found = 1;
                   1687:                        break;
                   1688:                }
                   1689: #ifndef IEEE80211_STA_ONLY
                   1690:                if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
                   1691:                    sc->sc_flowrings[flowid].status >= RING_OPEN &&
                   1692:                    sc->sc_flowrings[flowid].fifo == fifo &&
                   1693:                    !memcmp(sc->sc_flowrings[flowid].mac, da, ETHER_ADDR_LEN)) {
                   1694:                        found = 1;
                   1695:                        break;
                   1696:                }
                   1697: #endif
                   1698:                flowid = (flowid + 1) % sc->sc_max_flowrings;
                   1699:        }
                   1700:
                   1701:        if (found)
                   1702:                return flowid;
                   1703:
                   1704:        return -1;
                   1705: }
                   1706:
                   1707: void
                   1708: bwfm_pci_flowring_create(struct bwfm_pci_softc *sc, struct mbuf *m)
                   1709: {
                   1710:        struct ieee80211com *ic = &sc->sc_sc.sc_ic;
                   1711:        struct bwfm_cmd_flowring_create * cmd;
                   1712:        uint8_t *da = mtod(m, uint8_t *);
                   1713:        struct ether_header *eh;
                   1714:        struct bwfm_pci_msgring *ring;
                   1715:        int flowid, prio, fifo;
                   1716:        int i, found, ac;
                   1717:
                   1718:        cmd = pool_get(&sc->sc_flowring_pool, PR_NOWAIT);
                   1719:        if (__predict_false(cmd == NULL))
                   1720:                return;
                   1721:
                   1722:        /* No QoS for EAPOL frames. */
                   1723:        eh = mtod(m, struct ether_header *);
                   1724:        ac = (eh->ether_type != htons(ETHERTYPE_PAE)) ?
                   1725:            M_WME_GETAC(m) : WME_AC_BE;
                   1726:
                   1727:        prio = ac;
                   1728:        fifo = bwfm_pci_prio2fifo[prio];
                   1729:
                   1730:        switch (ic->ic_opmode)
                   1731:        {
                   1732:        case IEEE80211_M_STA:
                   1733:                flowid = fifo;
                   1734:                break;
                   1735: #ifndef IEEE80211_STA_ONLY
                   1736:        case IEEE80211_M_HOSTAP:
                   1737:                if (ETHER_IS_MULTICAST(da))
                   1738:                        da = __UNCONST(etherbroadcastaddr);
                   1739:                flowid = da[5] * 2 + fifo;
                   1740:                break;
                   1741: #endif
                   1742:        default:
                   1743:                printf("%s: state not supported\n", DEVNAME(sc));
                   1744:                return;
                   1745:        }
                   1746:
                   1747:        found = 0;
                   1748:        flowid = flowid % sc->sc_max_flowrings;
                   1749:        for (i = 0; i < sc->sc_max_flowrings; i++) {
                   1750:                ring = &sc->sc_flowrings[flowid];
                   1751:                if (ring->status == RING_CLOSED) {
                   1752:                        ring->status = RING_OPENING;
                   1753:                        found = 1;
                   1754:                        break;
                   1755:                }
                   1756:                flowid = (flowid + 1) % sc->sc_max_flowrings;
                   1757:        }
                   1758:
                   1759:        /*
                   1760:         * We cannot recover from that so far.  Only a stop/init
                   1761:         * cycle can revive this if it ever happens at all.
                   1762:         */
                   1763:        if (!found) {
                   1764:                printf("%s: no flowring available\n", DEVNAME(sc));
                   1765:                return;
                   1766:        }
                   1767:
                   1768:        cmd->sc = sc;
                   1769:        cmd->m = m;
                   1770:        cmd->prio = prio;
                   1771:        cmd->flowid = flowid;
                   1772:        workqueue_enqueue(sc->flowring_wq, &cmd->wq_cookie, NULL);
                   1773: }
                   1774:
                   1775: void
                   1776: bwfm_pci_flowring_create_cb(struct work *wk, void *arg) //(struct bwfm_softc *bwfm, void *arg)
                   1777: {
                   1778:        struct bwfm_cmd_flowring_create *cmd = container_of(wk, struct bwfm_cmd_flowring_create, wq_cookie);
                   1779:        struct bwfm_pci_softc *sc = cmd->sc; // (void *)bwfm;
                   1780:        struct ieee80211com *ic = &sc->sc_sc.sc_ic;
                   1781:        struct msgbuf_tx_flowring_create_req *req;
                   1782:        struct bwfm_pci_msgring *ring;
                   1783:        uint8_t *da, *sa;
                   1784:
                   1785:        da = mtod(cmd->m, char *) + 0 * ETHER_ADDR_LEN;
                   1786:        sa = mtod(cmd->m, char *) + 1 * ETHER_ADDR_LEN;
                   1787:
                   1788:        ring = &sc->sc_flowrings[cmd->flowid];
                   1789:        if (ring->status != RING_OPENING) {
                   1790:                printf("%s: flowring not opening\n", DEVNAME(sc));
                   1791:                return;
                   1792:        }
                   1793:
                   1794:        if (bwfm_pci_setup_flowring(sc, ring, 512, 48)) {
                   1795:                printf("%s: cannot setup flowring\n", DEVNAME(sc));
                   1796:                return;
                   1797:        }
                   1798:
                   1799:        req = bwfm_pci_ring_write_reserve(sc, &sc->sc_ctrl_submit);
                   1800:        if (req == NULL) {
                   1801:                printf("%s: cannot reserve for flowring\n", DEVNAME(sc));
                   1802:                return;
                   1803:        }
                   1804:
                   1805:        ring->status = RING_OPENING;
                   1806:        ring->fifo = bwfm_pci_prio2fifo[cmd->prio];
                   1807:        ring->m = cmd->m;
                   1808:        memcpy(ring->mac, da, ETHER_ADDR_LEN);
                   1809: #ifndef IEEE80211_STA_ONLY
                   1810:        if (ic->ic_opmode == IEEE80211_M_HOSTAP && ETHER_IS_MULTICAST(da))
                   1811:                memcpy(ring->mac, etherbroadcastaddr, ETHER_ADDR_LEN);
                   1812: #endif
                   1813:
                   1814:        req->msg.msgtype = MSGBUF_TYPE_FLOW_RING_CREATE;
                   1815:        req->msg.ifidx = 0;
                   1816:        req->msg.request_id = 0;
                   1817:        req->tid = bwfm_pci_prio2fifo[cmd->prio];
                   1818:        req->flow_ring_id = letoh16(cmd->flowid + 2);
                   1819:        memcpy(req->da, da, ETHER_ADDR_LEN);
                   1820:        memcpy(req->sa, sa, ETHER_ADDR_LEN);
                   1821:        req->flow_ring_addr.high_addr =
                   1822:            letoh32(BWFM_PCI_DMA_DVA(ring->ring) >> 32);
                   1823:        req->flow_ring_addr.low_addr =
                   1824:            letoh32(BWFM_PCI_DMA_DVA(ring->ring) & 0xffffffff);
                   1825:        req->max_items = letoh16(512);
                   1826:        req->len_item = letoh16(48);
                   1827:
                   1828:        bwfm_pci_ring_write_commit(sc, &sc->sc_ctrl_submit);
                   1829:        pool_put(&sc->sc_flowring_pool, cmd);
                   1830: }
                   1831:
                   1832: void
                   1833: bwfm_pci_flowring_delete(struct bwfm_pci_softc *sc, int flowid)
                   1834: {
                   1835:        struct msgbuf_tx_flowring_delete_req *req;
                   1836:        struct bwfm_pci_msgring *ring;
                   1837:
                   1838:        ring = &sc->sc_flowrings[flowid];
                   1839:        if (ring->status != RING_OPEN) {
                   1840:                printf("%s: flowring not open\n", DEVNAME(sc));
                   1841:                return;
                   1842:        }
                   1843:
                   1844:        req = bwfm_pci_ring_write_reserve(sc, &sc->sc_ctrl_submit);
                   1845:        if (req == NULL) {
                   1846:                printf("%s: cannot reserve for flowring\n", DEVNAME(sc));
                   1847:                return;
                   1848:        }
                   1849:
                   1850:        ring->status = RING_CLOSING;
                   1851:
                   1852:        req->msg.msgtype = MSGBUF_TYPE_FLOW_RING_DELETE;
                   1853:        req->msg.ifidx = 0;
                   1854:        req->msg.request_id = 0;
                   1855:        req->flow_ring_id = letoh16(flowid + 2);
                   1856:        req->reason = 0;
                   1857:
                   1858:        bwfm_pci_ring_write_commit(sc, &sc->sc_ctrl_submit);
                   1859: }
                   1860:
                   1861: void
                   1862: bwfm_pci_stop(struct bwfm_softc *bwfm)
                   1863: {
                   1864:        struct bwfm_pci_softc *sc = (void *)bwfm;
                   1865:        struct bwfm_pci_msgring *ring;
                   1866:        int i;
                   1867:
                   1868:        for (i = 0; i < sc->sc_max_flowrings; i++) {
                   1869:                ring = &sc->sc_flowrings[i];
                   1870:                if (ring->status == RING_OPEN)
                   1871:                        bwfm_pci_flowring_delete(sc, i);
                   1872:        }
                   1873: }
                   1874:
                   1875: int
                   1876: bwfm_pci_txcheck(struct bwfm_softc *bwfm)
                   1877: {
                   1878:        struct bwfm_pci_softc *sc = (void *)bwfm;
                   1879:        struct bwfm_pci_msgring *ring;
                   1880:        int i;
                   1881:
                   1882:        /* If we are transitioning, we cannot send. */
                   1883:        for (i = 0; i < sc->sc_max_flowrings; i++) {
                   1884:                ring = &sc->sc_flowrings[i];
                   1885:                if (ring->status == RING_OPENING)
                   1886:                        return ENOBUFS;
                   1887:        }
                   1888:
                   1889:        if (bwfm_pci_pktid_avail(sc, &sc->sc_tx_pkts)) {
                   1890:                sc->sc_tx_pkts_full = 1;
                   1891:                return ENOBUFS;
                   1892:        }
                   1893:
                   1894:        return 0;
                   1895: }
                   1896:
                   1897: int
1.2       riastrad 1898: bwfm_pci_txdata(struct bwfm_softc *bwfm, struct mbuf **mp)
1.1       maya     1899: {
                   1900:        struct bwfm_pci_softc *sc = (void *)bwfm;
                   1901:        struct bwfm_pci_msgring *ring;
                   1902:        struct msgbuf_tx_msghdr *tx;
                   1903:        uint32_t pktid;
                   1904:        paddr_t paddr;
1.5       martin   1905:        uint64_t devaddr;
1.1       maya     1906:        struct ether_header *eh;
                   1907:        int flowid, ret, ac;
                   1908:
1.2       riastrad 1909:        flowid = bwfm_pci_flowring_lookup(sc, *mp);
1.1       maya     1910:        if (flowid < 0) {
                   1911:                /*
                   1912:                 * We cannot send the packet right now as there is
                   1913:                 * no flowring yet.  The flowring will be created
                   1914:                 * asynchronously.  While the ring is transitioning
                   1915:                 * the TX check will tell the upper layers that we
                   1916:                 * cannot send packets right now.  When the flowring
                   1917:                 * is created the queue will be restarted and this
                   1918:                 * mbuf will be transmitted.
                   1919:                 */
1.2       riastrad 1920:                bwfm_pci_flowring_create(sc, *mp);
1.1       maya     1921:                return 0;
                   1922:        }
                   1923:
                   1924:        ring = &sc->sc_flowrings[flowid];
                   1925:        if (ring->status == RING_OPENING ||
                   1926:            ring->status == RING_CLOSING) {
                   1927:                printf("%s: tried to use a flow that was "
                   1928:                    "transitioning in status %d\n",
                   1929:                    DEVNAME(sc), ring->status);
                   1930:                return ENOBUFS;
                   1931:        }
                   1932:
                   1933:        tx = bwfm_pci_ring_write_reserve(sc, ring);
                   1934:        if (tx == NULL)
                   1935:                return ENOBUFS;
                   1936:
                   1937:        /* No QoS for EAPOL frames. */
1.2       riastrad 1938:        eh = mtod(*mp, struct ether_header *);
1.1       maya     1939:        ac = (eh->ether_type != htons(ETHERTYPE_PAE)) ?
1.2       riastrad 1940:            M_WME_GETAC(*mp) : WME_AC_BE;
1.1       maya     1941:
                   1942:        memset(tx, 0, sizeof(*tx));
                   1943:        tx->msg.msgtype = MSGBUF_TYPE_TX_POST;
                   1944:        tx->msg.ifidx = 0;
                   1945:        tx->flags = BWFM_MSGBUF_PKT_FLAGS_FRAME_802_3;
                   1946:        tx->flags |= ac << BWFM_MSGBUF_PKT_FLAGS_PRIO_SHIFT;
                   1947:        tx->seg_cnt = 1;
1.2       riastrad 1948:        memcpy(tx->txhdr, mtod(*mp, char *), ETHER_HDR_LEN);
1.1       maya     1949:
1.2       riastrad 1950:        ret = bwfm_pci_pktid_new(sc, &sc->sc_tx_pkts, mp, &pktid, &paddr);
1.1       maya     1951:        if (ret) {
                   1952:                if (ret == ENOBUFS) {
                   1953:                        printf("%s: no pktid available for TX\n",
                   1954:                            DEVNAME(sc));
                   1955:                        sc->sc_tx_pkts_full = 1;
                   1956:                }
                   1957:                bwfm_pci_ring_write_cancel(sc, ring, 1);
                   1958:                return ret;
                   1959:        }
1.5       martin   1960:        devaddr = paddr + ETHER_HDR_LEN;
1.1       maya     1961:
                   1962:        tx->msg.request_id = htole32(pktid);
1.2       riastrad 1963:        tx->data_len = htole16((*mp)->m_len - ETHER_HDR_LEN);
1.5       martin   1964:        tx->data_buf_addr.high_addr = htole32(devaddr >> 32);
                   1965:        tx->data_buf_addr.low_addr = htole32(devaddr & 0xffffffff);
1.1       maya     1966:
                   1967:        bwfm_pci_ring_write_commit(sc, ring);
                   1968:        return 0;
                   1969: }
                   1970:
                   1971: #ifdef BWFM_DEBUG
                   1972: void
                   1973: bwfm_pci_debug_console(struct bwfm_pci_softc *sc)
                   1974: {
                   1975:        uint32_t newidx = bus_space_read_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,
                   1976:            sc->sc_console_base_addr + BWFM_CONSOLE_WRITEIDX);
                   1977:
                   1978:        if (newidx != sc->sc_console_readidx)
                   1979:                DPRINTFN(3, ("BWFM CONSOLE: "));
                   1980:        while (newidx != sc->sc_console_readidx) {
                   1981:                uint8_t ch = bus_space_read_1(sc->sc_tcm_iot, sc->sc_tcm_ioh,
                   1982:                    sc->sc_console_buf_addr + sc->sc_console_readidx);
                   1983:                sc->sc_console_readidx++;
                   1984:                if (sc->sc_console_readidx == sc->sc_console_buf_size)
                   1985:                        sc->sc_console_readidx = 0;
                   1986:                if (ch == '\r')
                   1987:                        continue;
                   1988:                DPRINTFN(3, ("%c", ch));
                   1989:        }
                   1990: }
                   1991: #endif
                   1992:
                   1993: int
                   1994: bwfm_pci_intr(void *v)
                   1995: {
                   1996:        struct bwfm_pci_softc *sc = (void *)v;
                   1997:        uint32_t status;
                   1998:
                   1999:        if ((status = bus_space_read_4(sc->sc_reg_iot, sc->sc_reg_ioh,
                   2000:            BWFM_PCI_PCIE2REG_MAILBOXINT)) == 0)
                   2001:                return 0;
                   2002:
                   2003:        bwfm_pci_intr_disable(sc);
                   2004:        bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,
                   2005:            BWFM_PCI_PCIE2REG_MAILBOXINT, status);
                   2006:
                   2007:        if (status & (BWFM_PCI_PCIE2REG_MAILBOXMASK_INT_FN0_0 |
                   2008:            BWFM_PCI_PCIE2REG_MAILBOXMASK_INT_FN0_1))
                   2009:                printf("%s: handle MB data\n", __func__);
                   2010:
                   2011:        if (status & BWFM_PCI_PCIE2REG_MAILBOXMASK_INT_D2H_DB) {
                   2012:                bwfm_pci_ring_rx(sc, &sc->sc_rx_complete);
                   2013:                bwfm_pci_ring_rx(sc, &sc->sc_tx_complete);
                   2014:                bwfm_pci_ring_rx(sc, &sc->sc_ctrl_complete);
                   2015:        }
                   2016:
                   2017: #ifdef BWFM_DEBUG
                   2018:        bwfm_pci_debug_console(sc);
                   2019: #endif
                   2020:
                   2021:        bwfm_pci_intr_enable(sc);
                   2022:        return 1;
                   2023: }
                   2024:
                   2025: void
                   2026: bwfm_pci_intr_enable(struct bwfm_pci_softc *sc)
                   2027: {
                   2028:        bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,
                   2029:            BWFM_PCI_PCIE2REG_MAILBOXMASK,
                   2030:            BWFM_PCI_PCIE2REG_MAILBOXMASK_INT_FN0_0 |
                   2031:            BWFM_PCI_PCIE2REG_MAILBOXMASK_INT_FN0_1 |
                   2032:            BWFM_PCI_PCIE2REG_MAILBOXMASK_INT_D2H_DB);
                   2033: }
                   2034:
                   2035: void
                   2036: bwfm_pci_intr_disable(struct bwfm_pci_softc *sc)
                   2037: {
                   2038:        bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,
                   2039:            BWFM_PCI_PCIE2REG_MAILBOXMASK, 0);
                   2040: }
                   2041:
                   2042: /* Msgbuf protocol implementation */
                   2043: int
                   2044: bwfm_pci_msgbuf_query_dcmd(struct bwfm_softc *bwfm, int ifidx,
                   2045:     int cmd, char *buf, size_t *len)
                   2046: {
                   2047:        struct bwfm_pci_softc *sc = (void *)bwfm;
                   2048:        struct msgbuf_ioctl_req_hdr *req;
                   2049:        struct mbuf *m;
                   2050:        size_t buflen;
                   2051:        int s;
                   2052:
                   2053:        s = splnet();
                   2054:        sc->sc_ioctl_resp_pktid = -1;
                   2055:        req = bwfm_pci_ring_write_reserve(sc, &sc->sc_ctrl_submit);
                   2056:        if (req == NULL) {
                   2057:                printf("%s: cannot reserve for write\n", DEVNAME(sc));
                   2058:                splx(s);
                   2059:                return 1;
                   2060:        }
                   2061:        req->msg.msgtype = MSGBUF_TYPE_IOCTLPTR_REQ;
                   2062:        req->msg.ifidx = 0;
                   2063:        req->msg.flags = 0;
                   2064:        req->msg.request_id = htole32(MSGBUF_IOCTL_REQ_PKTID);
                   2065:        req->cmd = htole32(cmd);
                   2066:        req->output_buf_len = htole16(*len);
                   2067:        req->trans_id = htole16(sc->sc_ioctl_reqid++);
                   2068:
1.3       riastrad 2069:        buflen = uimin(*len, BWFM_DMA_H2D_IOCTL_BUF_LEN);
1.1       maya     2070:        req->input_buf_len = htole16(buflen);
                   2071:        req->req_buf_addr.high_addr =
                   2072:            htole32((uint64_t)BWFM_PCI_DMA_DVA(sc->sc_ioctl_buf) >> 32);
                   2073:        req->req_buf_addr.low_addr =
                   2074:            htole32((uint64_t)BWFM_PCI_DMA_DVA(sc->sc_ioctl_buf) & 0xffffffff);
                   2075:        if (buf)
                   2076:                memcpy(BWFM_PCI_DMA_KVA(sc->sc_ioctl_buf), buf, buflen);
                   2077:        else
                   2078:                memset(BWFM_PCI_DMA_KVA(sc->sc_ioctl_buf), 0, buflen);
                   2079:
                   2080:        bwfm_pci_ring_write_commit(sc, &sc->sc_ctrl_submit);
                   2081:        splx(s);
                   2082:
                   2083:        if (tsleep(&sc->sc_ioctl_buf, PCATCH, "bwfm", hz)) {
                   2084:                printf("%s: timeout waiting for ioctl response\n",
                   2085:                    DEVNAME(sc));
                   2086:                return 1;
                   2087:        }
                   2088:
                   2089:        m = bwfm_pci_pktid_free(sc, &sc->sc_rx_pkts, sc->sc_ioctl_resp_pktid);
                   2090:        if (m == NULL)
                   2091:                return 1;
                   2092:
1.3       riastrad 2093:        *len = uimin(buflen, sc->sc_ioctl_resp_ret_len);
1.1       maya     2094:        if (buf)
                   2095:                memcpy(buf, mtod(m, char *), *len);
                   2096:        m_freem(m);
                   2097:        splx(s);
                   2098:
                   2099:        return 0;
                   2100: }
                   2101:
                   2102: int
                   2103: bwfm_pci_msgbuf_set_dcmd(struct bwfm_softc *bwfm, int ifidx,
                   2104:     int cmd, char *buf, size_t len)
                   2105: {
                   2106:        return bwfm_pci_msgbuf_query_dcmd(bwfm, ifidx, cmd, buf, &len);
                   2107: }

CVSweb <webmaster@jp.NetBSD.org>