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