1 /* $OpenBSD: if_bwfm_sdio.c,v 1.44 2022/04/06 18:59:30 naddy Exp $ */ 2 /* 3 * Copyright (c) 2010-2016 Broadcom Corporation 4 * Copyright (c) 2016,2017 Patrick Wildt <patrick@blueri.se> 5 * 6 * Permission to use, copy, modify, and/or distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include "bpfilter.h" 20 21 #include <sys/param.h> 22 #include <sys/systm.h> 23 #include <sys/buf.h> 24 #include <sys/kernel.h> 25 #include <sys/malloc.h> 26 #include <sys/device.h> 27 #include <sys/queue.h> 28 #include <sys/socket.h> 29 #include <sys/pool.h> 30 31 #if defined(__HAVE_FDT) 32 #include <machine/fdt.h> 33 #include <dev/ofw/openfirm.h> 34 #endif 35 36 #if NBPFILTER > 0 37 #include <net/bpf.h> 38 #endif 39 #include <net/if.h> 40 #include <net/if_dl.h> 41 #include <net/if_media.h> 42 43 #include <netinet/in.h> 44 #include <netinet/if_ether.h> 45 46 #include <net80211/ieee80211_var.h> 47 48 #include <dev/sdmmc/sdmmcdevs.h> 49 #include <dev/sdmmc/sdmmcvar.h> 50 51 #include <dev/ic/bwfmvar.h> 52 #include <dev/ic/bwfmreg.h> 53 #include <dev/sdmmc/if_bwfm_sdio.h> 54 55 #define BWFM_SDIO_CCCR_BRCM_CARDCAP 0xf0 56 #define BWFM_SDIO_CCCR_BRCM_CARDCAP_CMD14_SUPPORT 0x02 57 #define BWFM_SDIO_CCCR_BRCM_CARDCAP_CMD14_EXT 0x04 58 #define BWFM_SDIO_CCCR_BRCM_CARDCAP_CMD_NODEC 0x08 59 #define BWFM_SDIO_CCCR_BRCM_CARDCTRL 0xf1 60 #define BWFM_SDIO_CCCR_BRCM_CARDCTRL_WLANRESET 0x02 61 #define BWFM_SDIO_CCCR_BRCM_SEPINT 0xf2 62 63 /* #define BWFM_DEBUG */ 64 #ifdef BWFM_DEBUG 65 #define DPRINTF(x) do { if (bwfm_debug > 0) printf x; } while (0) 66 #define DPRINTFN(n, x) do { if (bwfm_debug >= (n)) printf x; } while (0) 67 static int bwfm_debug = 1; 68 #else 69 #define DPRINTF(x) do { ; } while (0) 70 #define DPRINTFN(n, x) do { ; } while (0) 71 #endif 72 73 #undef DEVNAME 74 #define DEVNAME(sc) ((sc)->sc_sc.sc_dev.dv_xname) 75 76 enum bwfm_sdio_clkstate { 77 CLK_NONE, 78 CLK_SDONLY, 79 CLK_PENDING, 80 CLK_AVAIL, 81 }; 82 83 struct bwfm_sdio_softc { 84 struct bwfm_softc sc_sc; 85 struct sdmmc_function **sc_sf; 86 struct rwlock *sc_lock; 87 void *sc_ih; 88 int sc_oob; 89 90 int sc_initialized; 91 92 uint32_t sc_bar0; 93 int sc_clkstate; 94 int sc_alp_only; 95 int sc_sr_enabled; 96 uint32_t sc_console_addr; 97 98 char *sc_bounce_buf; 99 size_t sc_bounce_size; 100 101 char *sc_console_buf; 102 size_t sc_console_buf_size; 103 uint32_t sc_console_readidx; 104 105 struct bwfm_core *sc_cc; 106 107 uint8_t sc_tx_seq; 108 uint8_t sc_tx_max_seq; 109 struct mbuf_list sc_tx_queue; 110 int sc_tx_count; 111 112 struct task sc_task; 113 }; 114 115 int bwfm_sdio_match(struct device *, void *, void *); 116 void bwfm_sdio_attach(struct device *, struct device *, void *); 117 int bwfm_sdio_preinit(struct bwfm_softc *); 118 int bwfm_sdio_detach(struct device *, int); 119 120 int bwfm_sdio_intr(void *); 121 int bwfm_sdio_oob_intr(void *); 122 void bwfm_sdio_task(void *); 123 int bwfm_sdio_load_microcode(struct bwfm_sdio_softc *, 124 u_char *, size_t, u_char *, size_t); 125 126 void bwfm_sdio_clkctl(struct bwfm_sdio_softc *, 127 enum bwfm_sdio_clkstate, int); 128 void bwfm_sdio_htclk(struct bwfm_sdio_softc *, int, int); 129 void bwfm_sdio_readshared(struct bwfm_sdio_softc *); 130 131 void bwfm_sdio_backplane(struct bwfm_sdio_softc *, uint32_t); 132 uint8_t bwfm_sdio_read_1(struct bwfm_sdio_softc *, uint32_t); 133 uint32_t bwfm_sdio_read_4(struct bwfm_sdio_softc *, uint32_t); 134 void bwfm_sdio_write_1(struct bwfm_sdio_softc *, uint32_t, 135 uint8_t); 136 void bwfm_sdio_write_4(struct bwfm_sdio_softc *, uint32_t, 137 uint32_t); 138 int bwfm_sdio_buf_read(struct bwfm_sdio_softc *, 139 struct sdmmc_function *, uint32_t, char *, size_t); 140 int bwfm_sdio_buf_write(struct bwfm_sdio_softc *, 141 struct sdmmc_function *, uint32_t, char *, size_t); 142 uint32_t bwfm_sdio_ram_read_write(struct bwfm_sdio_softc *, 143 uint32_t, char *, size_t, int); 144 uint32_t bwfm_sdio_frame_read_write(struct bwfm_sdio_softc *, 145 char *, size_t, int); 146 147 uint32_t bwfm_sdio_dev_read(struct bwfm_sdio_softc *, uint32_t); 148 void bwfm_sdio_dev_write(struct bwfm_sdio_softc *, uint32_t, 149 uint32_t); 150 151 uint32_t bwfm_sdio_buscore_read(struct bwfm_softc *, uint32_t); 152 void bwfm_sdio_buscore_write(struct bwfm_softc *, uint32_t, 153 uint32_t); 154 int bwfm_sdio_buscore_prepare(struct bwfm_softc *); 155 void bwfm_sdio_buscore_activate(struct bwfm_softc *, uint32_t); 156 157 struct mbuf * bwfm_sdio_newbuf(void); 158 int bwfm_sdio_tx_ok(struct bwfm_sdio_softc *); 159 void bwfm_sdio_tx_frames(struct bwfm_sdio_softc *); 160 void bwfm_sdio_tx_ctrlframe(struct bwfm_sdio_softc *, struct mbuf *); 161 void bwfm_sdio_tx_dataframe(struct bwfm_sdio_softc *, struct mbuf *); 162 void bwfm_sdio_rx_frames(struct bwfm_sdio_softc *); 163 void bwfm_sdio_rx_glom(struct bwfm_sdio_softc *, uint16_t *, int, 164 uint16_t *, struct mbuf_list *); 165 166 int bwfm_sdio_txcheck(struct bwfm_softc *); 167 int bwfm_sdio_txdata(struct bwfm_softc *, struct mbuf *); 168 int bwfm_sdio_txctl(struct bwfm_softc *, void *); 169 170 #ifdef BWFM_DEBUG 171 void bwfm_sdio_debug_console(struct bwfm_sdio_softc *); 172 #endif 173 174 struct bwfm_bus_ops bwfm_sdio_bus_ops = { 175 .bs_preinit = bwfm_sdio_preinit, 176 .bs_stop = NULL, 177 .bs_txcheck = bwfm_sdio_txcheck, 178 .bs_txdata = bwfm_sdio_txdata, 179 .bs_txctl = bwfm_sdio_txctl, 180 }; 181 182 struct bwfm_buscore_ops bwfm_sdio_buscore_ops = { 183 .bc_read = bwfm_sdio_buscore_read, 184 .bc_write = bwfm_sdio_buscore_write, 185 .bc_prepare = bwfm_sdio_buscore_prepare, 186 .bc_reset = NULL, 187 .bc_setup = NULL, 188 .bc_activate = bwfm_sdio_buscore_activate, 189 }; 190 191 const struct cfattach bwfm_sdio_ca = { 192 sizeof(struct bwfm_sdio_softc), 193 bwfm_sdio_match, 194 bwfm_sdio_attach, 195 bwfm_sdio_detach, 196 }; 197 198 int 199 bwfm_sdio_match(struct device *parent, void *match, void *aux) 200 { 201 struct sdmmc_attach_args *saa = aux; 202 struct sdmmc_function *sf = saa->sf; 203 struct sdmmc_cis *cis; 204 205 /* Not SDIO. */ 206 if (sf == NULL) 207 return 0; 208 209 /* Look for Broadcom. */ 210 cis = &sf->sc->sc_fn0->cis; 211 if (cis->manufacturer != SDMMC_VENDOR_BROADCOM) 212 return 0; 213 214 /* Look for supported chips. */ 215 switch (cis->product) { 216 case SDMMC_PRODUCT_BROADCOM_BCM4324: 217 case SDMMC_PRODUCT_BROADCOM_BCM4329: 218 case SDMMC_PRODUCT_BROADCOM_BCM4330: 219 case SDMMC_PRODUCT_BROADCOM_BCM4334: 220 case SDMMC_PRODUCT_BROADCOM_BCM4335: 221 case SDMMC_PRODUCT_BROADCOM_BCM4339: 222 case SDMMC_PRODUCT_BROADCOM_BCM4345: 223 case SDMMC_PRODUCT_BROADCOM_BCM4354: 224 case SDMMC_PRODUCT_BROADCOM_BCM4356: 225 case SDMMC_PRODUCT_BROADCOM_BCM4359: 226 case SDMMC_PRODUCT_BROADCOM_BCM43143: 227 case SDMMC_PRODUCT_BROADCOM_BCM43340: 228 case SDMMC_PRODUCT_BROADCOM_BCM43341: 229 case SDMMC_PRODUCT_BROADCOM_BCM43362: 230 case SDMMC_PRODUCT_BROADCOM_BCM43430: 231 case SDMMC_PRODUCT_BROADCOM_BCM43364: 232 break; 233 default: 234 return 0; 235 } 236 237 /* We need both functions, but ... */ 238 if (sf->sc->sc_function_count <= 1) 239 return 0; 240 241 /* ... only attach for one. */ 242 if (sf->number != 1) 243 return 0; 244 245 return 1; 246 } 247 248 void 249 bwfm_sdio_attach(struct device *parent, struct device *self, void *aux) 250 { 251 struct bwfm_sdio_softc *sc = (struct bwfm_sdio_softc *)self; 252 struct sdmmc_attach_args *saa = aux; 253 struct sdmmc_function *sf = saa->sf; 254 struct bwfm_core *core; 255 uint32_t reg; 256 257 printf("\n"); 258 259 #if defined(__HAVE_FDT) 260 if (sf->cookie) 261 sc->sc_sc.sc_node = *(int *)sf->cookie; 262 #endif 263 264 task_set(&sc->sc_task, bwfm_sdio_task, sc); 265 ml_init(&sc->sc_tx_queue); 266 sc->sc_bounce_size = 64 * 1024; 267 sc->sc_bounce_buf = dma_alloc(sc->sc_bounce_size, PR_WAITOK); 268 sc->sc_tx_seq = 0xff; 269 270 rw_assert_wrlock(&sf->sc->sc_lock); 271 sc->sc_lock = &sf->sc->sc_lock; 272 273 sc->sc_sf = mallocarray(sf->sc->sc_function_count + 1, 274 sizeof(struct sdmmc_function *), M_DEVBUF, M_WAITOK); 275 276 /* Copy all function pointers. */ 277 SIMPLEQ_FOREACH(sf, &saa->sf->sc->sf_head, sf_list) { 278 sc->sc_sf[sf->number] = sf; 279 } 280 sf = saa->sf; 281 282 sdmmc_io_set_blocklen(sc->sc_sf[1], 64); 283 sdmmc_io_set_blocklen(sc->sc_sf[2], 512); 284 285 /* Enable Function 1. */ 286 if (sdmmc_io_function_enable(sc->sc_sf[1]) != 0) { 287 printf("%s: cannot enable function 1\n", DEVNAME(sc)); 288 goto err; 289 } 290 291 DPRINTF(("%s: F1 signature read @0x18000000=%x\n", DEVNAME(sc), 292 bwfm_sdio_read_4(sc, 0x18000000))); 293 294 /* Force PLL off */ 295 bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR, 296 BWFM_SDIO_FUNC1_CHIPCLKCSR_FORCE_HW_CLKREQ_OFF | 297 BWFM_SDIO_FUNC1_CHIPCLKCSR_ALP_AVAIL_REQ); 298 299 sc->sc_sc.sc_buscore_ops = &bwfm_sdio_buscore_ops; 300 if (bwfm_chip_attach(&sc->sc_sc) != 0) { 301 printf("%s: cannot attach chip\n", DEVNAME(sc)); 302 goto err; 303 } 304 305 sc->sc_cc = bwfm_chip_get_core(&sc->sc_sc, BWFM_AGENT_CORE_CHIPCOMMON); 306 if (sc->sc_cc == NULL) { 307 printf("%s: cannot find chipcommon core\n", DEVNAME(sc)); 308 goto err; 309 } 310 311 core = bwfm_chip_get_core(&sc->sc_sc, BWFM_AGENT_CORE_SDIO_DEV); 312 if (core->co_rev >= 12) { 313 reg = bwfm_sdio_read_1(sc, BWFM_SDIO_FUNC1_SLEEPCSR); 314 if (!(reg & BWFM_SDIO_FUNC1_SLEEPCSR_KSO)) { 315 reg |= BWFM_SDIO_FUNC1_SLEEPCSR_KSO; 316 bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_SLEEPCSR, reg); 317 } 318 } 319 320 /* TODO: drive strength */ 321 322 bwfm_sdio_write_1(sc, BWFM_SDIO_CCCR_BRCM_CARDCTRL, 323 bwfm_sdio_read_1(sc, BWFM_SDIO_CCCR_BRCM_CARDCTRL) | 324 BWFM_SDIO_CCCR_BRCM_CARDCTRL_WLANRESET); 325 326 core = bwfm_chip_get_pmu(&sc->sc_sc); 327 bwfm_sdio_write_4(sc, core->co_base + BWFM_CHIP_REG_PMUCONTROL, 328 bwfm_sdio_read_4(sc, core->co_base + BWFM_CHIP_REG_PMUCONTROL) | 329 (BWFM_CHIP_REG_PMUCONTROL_RES_RELOAD << 330 BWFM_CHIP_REG_PMUCONTROL_RES_SHIFT)); 331 332 sdmmc_io_function_disable(sc->sc_sf[2]); 333 334 bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR, 0); 335 sc->sc_clkstate = CLK_SDONLY; 336 337 sc->sc_sc.sc_bus_ops = &bwfm_sdio_bus_ops; 338 sc->sc_sc.sc_proto_ops = &bwfm_proto_bcdc_ops; 339 bwfm_attach(&sc->sc_sc); 340 config_mountroot(self, bwfm_attachhook); 341 return; 342 343 err: 344 free(sc->sc_sf, M_DEVBUF, 0); 345 } 346 347 int 348 bwfm_sdio_preinit(struct bwfm_softc *bwfm) 349 { 350 struct bwfm_sdio_softc *sc = (void *)bwfm; 351 const char *chip = NULL; 352 uint32_t clk, reg; 353 u_char *ucode, *nvram; 354 size_t size = 0, nvsize, nvlen = 0; 355 356 if (sc->sc_initialized) 357 return 0; 358 359 rw_enter_write(sc->sc_lock); 360 361 switch (bwfm->sc_chip.ch_chip) 362 { 363 case BRCM_CC_43241_CHIP_ID: 364 if (bwfm->sc_chip.ch_chiprev <= 4) 365 chip = "43241b0"; 366 else if (bwfm->sc_chip.ch_chiprev == 5) 367 chip = "43241b4"; 368 else 369 chip = "43241b5"; 370 break; 371 case BRCM_CC_4330_CHIP_ID: 372 chip = "4330"; 373 break; 374 case BRCM_CC_4334_CHIP_ID: 375 chip = "4334"; 376 break; 377 case BRCM_CC_4345_CHIP_ID: 378 if (bwfm->sc_chip.ch_chiprev == 9) 379 chip = "43456"; 380 else 381 chip = "43455"; 382 break; 383 case BRCM_CC_43340_CHIP_ID: 384 case BRCM_CC_43341_CHIP_ID: 385 chip = "43340"; 386 break; 387 case BRCM_CC_4335_CHIP_ID: 388 if (bwfm->sc_chip.ch_chiprev < 2) 389 chip = "4335"; 390 else 391 chip = "4339"; 392 break; 393 case BRCM_CC_4339_CHIP_ID: 394 chip = "4339"; 395 break; 396 case BRCM_CC_43430_CHIP_ID: 397 if (bwfm->sc_chip.ch_chiprev == 0) 398 chip = "43430a0"; 399 else if (bwfm->sc_chip.ch_chiprev == 2) 400 chip = "43436"; 401 else 402 chip = "43430"; 403 break; 404 case BRCM_CC_4356_CHIP_ID: 405 chip = "4356"; 406 break; 407 case BRCM_CC_4359_CHIP_ID: 408 chip = "4359"; 409 break; 410 default: 411 printf("%s: unknown firmware for chip %s\n", 412 DEVNAME(sc), bwfm->sc_chip.ch_name); 413 goto err; 414 } 415 416 if (bwfm_loadfirmware(bwfm, chip, "-sdio", &ucode, &size, 417 &nvram, &nvsize, &nvlen) != 0) 418 goto err; 419 420 sc->sc_alp_only = 1; 421 if (bwfm_sdio_load_microcode(sc, ucode, size, 422 nvram, nvlen) != 0) { 423 printf("%s: could not load microcode\n", 424 DEVNAME(sc)); 425 free(ucode, M_DEVBUF, size); 426 free(nvram, M_DEVBUF, nvsize); 427 goto err; 428 } 429 sc->sc_alp_only = 0; 430 free(ucode, M_DEVBUF, size); 431 free(nvram, M_DEVBUF, nvsize); 432 433 bwfm_sdio_clkctl(sc, CLK_AVAIL, 0); 434 if (sc->sc_clkstate != CLK_AVAIL) 435 goto err; 436 437 clk = bwfm_sdio_read_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR); 438 bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR, 439 clk | BWFM_SDIO_FUNC1_CHIPCLKCSR_FORCE_HT); 440 441 bwfm_sdio_dev_write(sc, SDPCMD_TOSBMAILBOXDATA, 442 SDPCM_PROT_VERSION << SDPCM_PROT_VERSION_SHIFT); 443 if (sdmmc_io_function_enable(sc->sc_sf[2]) != 0) { 444 printf("%s: cannot enable function 2\n", DEVNAME(sc)); 445 goto err; 446 } 447 448 bwfm_sdio_dev_write(sc, SDPCMD_HOSTINTMASK, 449 SDPCMD_INTSTATUS_HMB_SW_MASK|SDPCMD_INTSTATUS_CHIPACTIVE); 450 bwfm_sdio_write_1(sc, BWFM_SDIO_WATERMARK, 8); 451 452 if (bwfm_chip_sr_capable(bwfm)) { 453 reg = bwfm_sdio_read_1(sc, BWFM_SDIO_FUNC1_WAKEUPCTRL); 454 reg |= BWFM_SDIO_FUNC1_WAKEUPCTRL_HTWAIT; 455 bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_WAKEUPCTRL, reg); 456 bwfm_sdio_write_1(sc, BWFM_SDIO_CCCR_CARDCAP, 457 BWFM_SDIO_CCCR_CARDCAP_CMD14_SUPPORT | 458 BWFM_SDIO_CCCR_CARDCAP_CMD14_EXT); 459 bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR, 460 BWFM_SDIO_FUNC1_CHIPCLKCSR_FORCE_HT); 461 sc->sc_sr_enabled = 1; 462 } else { 463 bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR, clk); 464 } 465 466 #if defined(__HAVE_FDT) 467 if (sc->sc_sc.sc_node) { 468 sc->sc_ih = fdt_intr_establish(sc->sc_sc.sc_node, 469 IPL_NET, bwfm_sdio_oob_intr, sc, DEVNAME(sc)); 470 if (sc->sc_ih != NULL) { 471 bwfm_sdio_write_1(sc, BWFM_SDIO_CCCR_SEPINT, 472 BWFM_SDIO_CCCR_SEPINT_MASK | 473 BWFM_SDIO_CCCR_SEPINT_OE | 474 BWFM_SDIO_CCCR_SEPINT_ACT_HI); 475 sc->sc_oob = 1; 476 } 477 } 478 if (sc->sc_ih == NULL) 479 #endif 480 sc->sc_ih = sdmmc_intr_establish(bwfm->sc_dev.dv_parent, 481 bwfm_sdio_intr, sc, DEVNAME(sc)); 482 if (sc->sc_ih == NULL) { 483 printf("%s: can't establish interrupt\n", DEVNAME(sc)); 484 bwfm_sdio_clkctl(sc, CLK_NONE, 0); 485 goto err; 486 } 487 sdmmc_intr_enable(sc->sc_sf[1]); 488 rw_exit(sc->sc_lock); 489 490 sc->sc_initialized = 1; 491 return 0; 492 493 err: 494 rw_exit(sc->sc_lock); 495 return 1; 496 } 497 498 int 499 bwfm_sdio_load_microcode(struct bwfm_sdio_softc *sc, u_char *ucode, size_t size, 500 u_char *nvram, size_t nvlen) 501 { 502 struct bwfm_softc *bwfm = (void *)sc; 503 char *verify = NULL; 504 int err = 0; 505 506 bwfm_sdio_clkctl(sc, CLK_AVAIL, 0); 507 508 /* Upload firmware */ 509 err = bwfm_sdio_ram_read_write(sc, bwfm->sc_chip.ch_rambase, 510 ucode, size, 1); 511 if (err) 512 goto out; 513 514 /* Verify firmware */ 515 verify = malloc(size, M_TEMP, M_WAITOK | M_ZERO); 516 err = bwfm_sdio_ram_read_write(sc, bwfm->sc_chip.ch_rambase, 517 verify, size, 0); 518 if (err || memcmp(verify, ucode, size)) { 519 printf("%s: firmware verification failed\n", 520 DEVNAME(sc)); 521 free(verify, M_TEMP, size); 522 goto out; 523 } 524 free(verify, M_TEMP, size); 525 526 /* Upload nvram */ 527 err = bwfm_sdio_ram_read_write(sc, bwfm->sc_chip.ch_rambase + 528 bwfm->sc_chip.ch_ramsize - nvlen, nvram, nvlen, 1); 529 if (err) 530 goto out; 531 532 /* Verify nvram */ 533 verify = malloc(nvlen, M_TEMP, M_WAITOK | M_ZERO); 534 err = bwfm_sdio_ram_read_write(sc, bwfm->sc_chip.ch_rambase + 535 bwfm->sc_chip.ch_ramsize - nvlen, verify, nvlen, 0); 536 if (err || memcmp(verify, nvram, nvlen)) { 537 printf("%s: nvram verification failed\n", 538 DEVNAME(sc)); 539 free(verify, M_TEMP, nvlen); 540 goto out; 541 } 542 free(verify, M_TEMP, nvlen); 543 544 /* Load reset vector from firmware and kickstart core. */ 545 bwfm_chip_set_active(bwfm, *(uint32_t *)ucode); 546 547 out: 548 bwfm_sdio_clkctl(sc, CLK_SDONLY, 0); 549 return err; 550 } 551 552 void 553 bwfm_sdio_clkctl(struct bwfm_sdio_softc *sc, enum bwfm_sdio_clkstate newstate, 554 int pendok) 555 { 556 enum bwfm_sdio_clkstate oldstate; 557 558 oldstate = sc->sc_clkstate; 559 if (sc->sc_clkstate == newstate) 560 return; 561 562 switch (newstate) { 563 case CLK_AVAIL: 564 if (sc->sc_clkstate == CLK_NONE) 565 sc->sc_clkstate = CLK_SDONLY; 566 bwfm_sdio_htclk(sc, 1, pendok); 567 break; 568 case CLK_SDONLY: 569 if (sc->sc_clkstate == CLK_NONE) 570 sc->sc_clkstate = CLK_SDONLY; 571 else if (sc->sc_clkstate == CLK_AVAIL) 572 bwfm_sdio_htclk(sc, 0, 0); 573 else 574 printf("%s: request for %d -> %d\n", 575 DEVNAME(sc), sc->sc_clkstate, newstate); 576 break; 577 case CLK_NONE: 578 if (sc->sc_clkstate == CLK_AVAIL) 579 bwfm_sdio_htclk(sc, 0, 0); 580 sc->sc_clkstate = CLK_NONE; 581 break; 582 default: 583 break; 584 } 585 586 DPRINTF(("%s: %d -> %d = %d\n", DEVNAME(sc), oldstate, newstate, 587 sc->sc_clkstate)); 588 } 589 590 void 591 bwfm_sdio_htclk(struct bwfm_sdio_softc *sc, int on, int pendok) 592 { 593 uint32_t clkctl, devctl, req; 594 int i; 595 596 if (sc->sc_sr_enabled) { 597 if (on) 598 sc->sc_clkstate = CLK_AVAIL; 599 else 600 sc->sc_clkstate = CLK_SDONLY; 601 return; 602 } 603 604 if (on) { 605 if (sc->sc_alp_only) 606 req = BWFM_SDIO_FUNC1_CHIPCLKCSR_ALP_AVAIL_REQ; 607 else 608 req = BWFM_SDIO_FUNC1_CHIPCLKCSR_HT_AVAIL_REQ; 609 bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR, req); 610 611 clkctl = bwfm_sdio_read_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR); 612 if (!BWFM_SDIO_FUNC1_CHIPCLKCSR_CLKAV(clkctl, sc->sc_alp_only) 613 && pendok) { 614 devctl = bwfm_sdio_read_1(sc, BWFM_SDIO_DEVICE_CTL); 615 devctl |= BWFM_SDIO_DEVICE_CTL_CA_INT_ONLY; 616 bwfm_sdio_write_1(sc, BWFM_SDIO_DEVICE_CTL, devctl); 617 sc->sc_clkstate = CLK_PENDING; 618 return; 619 } else if (sc->sc_clkstate == CLK_PENDING) { 620 devctl = bwfm_sdio_read_1(sc, BWFM_SDIO_DEVICE_CTL); 621 devctl &= ~BWFM_SDIO_DEVICE_CTL_CA_INT_ONLY; 622 bwfm_sdio_write_1(sc, BWFM_SDIO_DEVICE_CTL, devctl); 623 } 624 625 for (i = 0; i < 5000; i++) { 626 if (BWFM_SDIO_FUNC1_CHIPCLKCSR_CLKAV(clkctl, 627 sc->sc_alp_only)) 628 break; 629 clkctl = bwfm_sdio_read_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR); 630 delay(1000); 631 } 632 if (!BWFM_SDIO_FUNC1_CHIPCLKCSR_CLKAV(clkctl, sc->sc_alp_only)) { 633 printf("%s: HT avail timeout\n", DEVNAME(sc)); 634 return; 635 } 636 637 sc->sc_clkstate = CLK_AVAIL; 638 } else { 639 if (sc->sc_clkstate == CLK_PENDING) { 640 devctl = bwfm_sdio_read_1(sc, BWFM_SDIO_DEVICE_CTL); 641 devctl &= ~BWFM_SDIO_DEVICE_CTL_CA_INT_ONLY; 642 bwfm_sdio_write_1(sc, BWFM_SDIO_DEVICE_CTL, devctl); 643 } 644 sc->sc_clkstate = CLK_SDONLY; 645 bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR, 0); 646 } 647 } 648 649 void 650 bwfm_sdio_readshared(struct bwfm_sdio_softc *sc) 651 { 652 struct bwfm_softc *bwfm = (void *)sc; 653 struct bwfm_sdio_sdpcm sdpcm; 654 uint32_t addr, shaddr; 655 int err; 656 657 shaddr = bwfm->sc_chip.ch_rambase + bwfm->sc_chip.ch_ramsize - 4; 658 if (!bwfm->sc_chip.ch_rambase && bwfm_chip_sr_capable(bwfm)) 659 shaddr -= bwfm->sc_chip.ch_srsize; 660 661 err = bwfm_sdio_ram_read_write(sc, shaddr, (char *)&addr, 662 sizeof(addr), 0); 663 if (err) 664 return; 665 666 addr = letoh32(addr); 667 if (addr == 0 || ((~addr >> 16) & 0xffff) == (addr & 0xffff)) 668 return; 669 670 err = bwfm_sdio_ram_read_write(sc, addr, (char *)&sdpcm, 671 sizeof(sdpcm), 0); 672 if (err) 673 return; 674 675 sc->sc_console_addr = letoh32(sdpcm.console_addr); 676 } 677 678 int 679 bwfm_sdio_intr(void *v) 680 { 681 bwfm_sdio_task(v); 682 return 1; 683 } 684 685 #if defined(__HAVE_FDT) 686 int 687 bwfm_sdio_oob_intr(void *v) 688 { 689 struct bwfm_sdio_softc *sc = (void *)v; 690 if (!sc->sc_oob) 691 return 0; 692 fdt_intr_disable(sc->sc_ih); 693 task_add(systq, &sc->sc_task); 694 return 1; 695 } 696 #endif 697 698 void 699 bwfm_sdio_task(void *v) 700 { 701 struct bwfm_sdio_softc *sc = (void *)v; 702 uint32_t clkctl, devctl, intstat, hostint; 703 704 rw_enter_write(sc->sc_lock); 705 706 if (!sc->sc_sr_enabled && sc->sc_clkstate == CLK_PENDING) { 707 clkctl = bwfm_sdio_read_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR); 708 if (BWFM_SDIO_FUNC1_CHIPCLKCSR_HTAV(clkctl)) { 709 devctl = bwfm_sdio_read_1(sc, BWFM_SDIO_DEVICE_CTL); 710 devctl &= ~BWFM_SDIO_DEVICE_CTL_CA_INT_ONLY; 711 bwfm_sdio_write_1(sc, BWFM_SDIO_DEVICE_CTL, devctl); 712 sc->sc_clkstate = CLK_AVAIL; 713 } 714 } 715 716 intstat = bwfm_sdio_dev_read(sc, BWFM_SDPCMD_INTSTATUS); 717 intstat &= (SDPCMD_INTSTATUS_HMB_SW_MASK|SDPCMD_INTSTATUS_CHIPACTIVE); 718 /* XXX fc state */ 719 if (intstat) 720 bwfm_sdio_dev_write(sc, BWFM_SDPCMD_INTSTATUS, intstat); 721 722 if (intstat & SDPCMD_INTSTATUS_HMB_HOST_INT) { 723 hostint = bwfm_sdio_dev_read(sc, SDPCMD_TOHOSTMAILBOXDATA); 724 bwfm_sdio_dev_write(sc, SDPCMD_TOSBMAILBOX, 725 SDPCMD_TOSBMAILBOX_INT_ACK); 726 if (hostint & SDPCMD_TOHOSTMAILBOXDATA_NAKHANDLED) 727 intstat |= SDPCMD_INTSTATUS_HMB_FRAME_IND; 728 if (hostint & SDPCMD_TOHOSTMAILBOXDATA_DEVREADY || 729 hostint & SDPCMD_TOHOSTMAILBOXDATA_FWREADY) 730 bwfm_sdio_readshared(sc); 731 } 732 733 /* FIXME: Might stall if we don't when not set. */ 734 if (1 || intstat & SDPCMD_INTSTATUS_HMB_FRAME_IND) { 735 bwfm_sdio_rx_frames(sc); 736 } 737 738 if (!ml_empty(&sc->sc_tx_queue)) { 739 bwfm_sdio_tx_frames(sc); 740 } 741 742 #ifdef BWFM_DEBUG 743 bwfm_sdio_debug_console(sc); 744 #endif 745 746 rw_exit(sc->sc_lock); 747 748 #if defined(__HAVE_FDT) 749 if (sc->sc_oob) 750 fdt_intr_enable(sc->sc_ih); 751 #endif 752 } 753 754 int 755 bwfm_sdio_detach(struct device *self, int flags) 756 { 757 struct bwfm_sdio_softc *sc = (struct bwfm_sdio_softc *)self; 758 759 bwfm_detach(&sc->sc_sc, flags); 760 761 dma_free(sc->sc_bounce_buf, sc->sc_bounce_size); 762 free(sc->sc_sf, M_DEVBUF, 0); 763 764 return 0; 765 } 766 767 void 768 bwfm_sdio_backplane(struct bwfm_sdio_softc *sc, uint32_t bar0) 769 { 770 if (sc->sc_bar0 == bar0) 771 return; 772 773 bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_SBADDRLOW, 774 (bar0 >> 8) & 0x80); 775 bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_SBADDRMID, 776 (bar0 >> 16) & 0xff); 777 bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_SBADDRHIGH, 778 (bar0 >> 24) & 0xff); 779 sc->sc_bar0 = bar0; 780 } 781 782 uint8_t 783 bwfm_sdio_read_1(struct bwfm_sdio_softc *sc, uint32_t addr) 784 { 785 struct sdmmc_function *sf; 786 uint8_t rv; 787 788 /* 789 * figure out how to read the register based on address range 790 * 0x00 ~ 0x7FF: function 0 CCCR and FBR 791 * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers 792 * The rest: function 1 silicon backplane core registers 793 */ 794 if ((addr & ~0x7ff) == 0) 795 sf = sc->sc_sf[0]; 796 else 797 sf = sc->sc_sf[1]; 798 799 rv = sdmmc_io_read_1(sf, addr); 800 return rv; 801 } 802 803 uint32_t 804 bwfm_sdio_read_4(struct bwfm_sdio_softc *sc, uint32_t addr) 805 { 806 struct sdmmc_function *sf; 807 uint32_t bar0 = addr & ~BWFM_SDIO_SB_OFT_ADDR_MASK; 808 uint32_t rv; 809 810 bwfm_sdio_backplane(sc, bar0); 811 812 addr &= BWFM_SDIO_SB_OFT_ADDR_MASK; 813 addr |= BWFM_SDIO_SB_ACCESS_2_4B_FLAG; 814 815 /* 816 * figure out how to read the register based on address range 817 * 0x00 ~ 0x7FF: function 0 CCCR and FBR 818 * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers 819 * The rest: function 1 silicon backplane core registers 820 */ 821 if ((addr & ~0x7ff) == 0) 822 sf = sc->sc_sf[0]; 823 else 824 sf = sc->sc_sf[1]; 825 826 rv = sdmmc_io_read_4(sf, addr); 827 return rv; 828 } 829 830 void 831 bwfm_sdio_write_1(struct bwfm_sdio_softc *sc, uint32_t addr, uint8_t data) 832 { 833 struct sdmmc_function *sf; 834 835 /* 836 * figure out how to read the register based on address range 837 * 0x00 ~ 0x7FF: function 0 CCCR and FBR 838 * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers 839 * The rest: function 1 silicon backplane core registers 840 */ 841 if ((addr & ~0x7ff) == 0) 842 sf = sc->sc_sf[0]; 843 else 844 sf = sc->sc_sf[1]; 845 846 sdmmc_io_write_1(sf, addr, data); 847 } 848 849 void 850 bwfm_sdio_write_4(struct bwfm_sdio_softc *sc, uint32_t addr, uint32_t data) 851 { 852 struct sdmmc_function *sf; 853 uint32_t bar0 = addr & ~BWFM_SDIO_SB_OFT_ADDR_MASK; 854 855 bwfm_sdio_backplane(sc, bar0); 856 857 addr &= BWFM_SDIO_SB_OFT_ADDR_MASK; 858 addr |= BWFM_SDIO_SB_ACCESS_2_4B_FLAG; 859 860 /* 861 * figure out how to read the register based on address range 862 * 0x00 ~ 0x7FF: function 0 CCCR and FBR 863 * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers 864 * The rest: function 1 silicon backplane core registers 865 */ 866 if ((addr & ~0x7ff) == 0) 867 sf = sc->sc_sf[0]; 868 else 869 sf = sc->sc_sf[1]; 870 871 sdmmc_io_write_4(sf, addr, data); 872 } 873 874 int 875 bwfm_sdio_buf_read(struct bwfm_sdio_softc *sc, struct sdmmc_function *sf, 876 uint32_t reg, char *data, size_t size) 877 { 878 int err; 879 880 KASSERT(((vaddr_t)data & 0x3) == 0); 881 KASSERT((size & 0x3) == 0); 882 883 if (sf == sc->sc_sf[1]) 884 err = sdmmc_io_read_region_1(sf, reg, data, size); 885 else 886 err = sdmmc_io_read_multi_1(sf, reg, data, size); 887 888 if (err) 889 printf("%s: error %d\n", __func__, err); 890 891 return err; 892 } 893 894 int 895 bwfm_sdio_buf_write(struct bwfm_sdio_softc *sc, struct sdmmc_function *sf, 896 uint32_t reg, char *data, size_t size) 897 { 898 int err; 899 900 KASSERT(((vaddr_t)data & 0x3) == 0); 901 KASSERT((size & 0x3) == 0); 902 903 err = sdmmc_io_write_region_1(sf, reg, data, size); 904 905 if (err) 906 printf("%s: error %d\n", __func__, err); 907 908 return err; 909 } 910 911 uint32_t 912 bwfm_sdio_ram_read_write(struct bwfm_sdio_softc *sc, uint32_t reg, 913 char *data, size_t left, int write) 914 { 915 uint32_t sbaddr, sdaddr, off; 916 size_t size; 917 int err; 918 919 err = off = 0; 920 while (left > 0) { 921 sbaddr = reg + off; 922 bwfm_sdio_backplane(sc, sbaddr); 923 924 sdaddr = sbaddr & BWFM_SDIO_SB_OFT_ADDR_MASK; 925 size = min(left, (BWFM_SDIO_SB_OFT_ADDR_PAGE - sdaddr)); 926 sdaddr |= BWFM_SDIO_SB_ACCESS_2_4B_FLAG; 927 928 if (write) { 929 memcpy(sc->sc_bounce_buf, data + off, size); 930 if (roundup(size, 4) != size) 931 memset(sc->sc_bounce_buf + size, 0, 932 roundup(size, 4) - size); 933 err = bwfm_sdio_buf_write(sc, sc->sc_sf[1], sdaddr, 934 sc->sc_bounce_buf, roundup(size, 4)); 935 } else { 936 err = bwfm_sdio_buf_read(sc, sc->sc_sf[1], sdaddr, 937 sc->sc_bounce_buf, roundup(size, 4)); 938 memcpy(data + off, sc->sc_bounce_buf, size); 939 } 940 if (err) 941 break; 942 943 off += size; 944 left -= size; 945 } 946 947 return err; 948 } 949 950 uint32_t 951 bwfm_sdio_frame_read_write(struct bwfm_sdio_softc *sc, 952 char *data, size_t size, int write) 953 { 954 uint32_t addr; 955 int err; 956 957 addr = sc->sc_cc->co_base; 958 bwfm_sdio_backplane(sc, addr); 959 960 addr &= BWFM_SDIO_SB_OFT_ADDR_MASK; 961 addr |= BWFM_SDIO_SB_ACCESS_2_4B_FLAG; 962 963 if (write) 964 err = bwfm_sdio_buf_write(sc, sc->sc_sf[2], addr, data, size); 965 else 966 err = bwfm_sdio_buf_read(sc, sc->sc_sf[2], addr, data, size); 967 968 return err; 969 } 970 971 uint32_t 972 bwfm_sdio_dev_read(struct bwfm_sdio_softc *sc, uint32_t reg) 973 { 974 struct bwfm_core *core; 975 core = bwfm_chip_get_core(&sc->sc_sc, BWFM_AGENT_CORE_SDIO_DEV); 976 return bwfm_sdio_read_4(sc, core->co_base + reg); 977 } 978 979 void 980 bwfm_sdio_dev_write(struct bwfm_sdio_softc *sc, uint32_t reg, uint32_t val) 981 { 982 struct bwfm_core *core; 983 core = bwfm_chip_get_core(&sc->sc_sc, BWFM_AGENT_CORE_SDIO_DEV); 984 bwfm_sdio_write_4(sc, core->co_base + reg, val); 985 } 986 987 uint32_t 988 bwfm_sdio_buscore_read(struct bwfm_softc *bwfm, uint32_t reg) 989 { 990 struct bwfm_sdio_softc *sc = (void *)bwfm; 991 return bwfm_sdio_read_4(sc, reg); 992 } 993 994 void 995 bwfm_sdio_buscore_write(struct bwfm_softc *bwfm, uint32_t reg, uint32_t val) 996 { 997 struct bwfm_sdio_softc *sc = (void *)bwfm; 998 bwfm_sdio_write_4(sc, reg, val); 999 } 1000 1001 int 1002 bwfm_sdio_buscore_prepare(struct bwfm_softc *bwfm) 1003 { 1004 struct bwfm_sdio_softc *sc = (void *)bwfm; 1005 uint8_t clkval, clkset, clkmask; 1006 int i; 1007 1008 clkset = BWFM_SDIO_FUNC1_CHIPCLKCSR_ALP_AVAIL_REQ | 1009 BWFM_SDIO_FUNC1_CHIPCLKCSR_FORCE_HW_CLKREQ_OFF; 1010 bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR, clkset); 1011 1012 clkmask = BWFM_SDIO_FUNC1_CHIPCLKCSR_ALP_AVAIL | 1013 BWFM_SDIO_FUNC1_CHIPCLKCSR_HT_AVAIL; 1014 clkval = bwfm_sdio_read_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR); 1015 1016 if ((clkval & ~clkmask) != clkset) { 1017 printf("%s: wrote 0x%02x read 0x%02x\n", DEVNAME(sc), 1018 clkset, clkval); 1019 return 1; 1020 } 1021 1022 for (i = 1000; i > 0; i--) { 1023 clkval = bwfm_sdio_read_1(sc, 1024 BWFM_SDIO_FUNC1_CHIPCLKCSR); 1025 if (clkval & clkmask) 1026 break; 1027 } 1028 if (i == 0) { 1029 printf("%s: timeout on ALPAV wait, clkval 0x%02x\n", 1030 DEVNAME(sc), clkval); 1031 return 1; 1032 } 1033 1034 clkset = BWFM_SDIO_FUNC1_CHIPCLKCSR_FORCE_HW_CLKREQ_OFF | 1035 BWFM_SDIO_FUNC1_CHIPCLKCSR_FORCE_ALP; 1036 bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR, clkset); 1037 delay(65); 1038 1039 bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_SDIOPULLUP, 0); 1040 1041 return 0; 1042 } 1043 1044 void 1045 bwfm_sdio_buscore_activate(struct bwfm_softc *bwfm, uint32_t rstvec) 1046 { 1047 struct bwfm_sdio_softc *sc = (void *)bwfm; 1048 1049 bwfm_sdio_dev_write(sc, BWFM_SDPCMD_INTSTATUS, 0xFFFFFFFF); 1050 1051 if (rstvec) 1052 bwfm_sdio_ram_read_write(sc, 0, (char *)&rstvec, 1053 sizeof(rstvec), 1); 1054 } 1055 1056 struct mbuf * 1057 bwfm_sdio_newbuf(void) 1058 { 1059 struct mbuf *m; 1060 1061 MGETHDR(m, M_DONTWAIT, MT_DATA); 1062 if (m == NULL) 1063 return (NULL); 1064 1065 MCLGET(m, M_DONTWAIT); 1066 if (!(m->m_flags & M_EXT)) { 1067 m_freem(m); 1068 return (NULL); 1069 } 1070 1071 m->m_len = m->m_pkthdr.len = MCLBYTES; 1072 1073 return (m); 1074 } 1075 1076 int 1077 bwfm_sdio_tx_ok(struct bwfm_sdio_softc *sc) 1078 { 1079 return (uint8_t)(sc->sc_tx_max_seq - sc->sc_tx_seq) != 0 && 1080 ((uint8_t)(sc->sc_tx_max_seq - sc->sc_tx_seq) & 0x80) == 0; 1081 } 1082 1083 void 1084 bwfm_sdio_tx_frames(struct bwfm_sdio_softc *sc) 1085 { 1086 struct ifnet *ifp = &sc->sc_sc.sc_ic.ic_if; 1087 struct mbuf *m; 1088 int i; 1089 1090 if (!bwfm_sdio_tx_ok(sc)) 1091 return; 1092 1093 i = min((uint8_t)(sc->sc_tx_max_seq - sc->sc_tx_seq), 32); 1094 while (i--) { 1095 m = ml_dequeue(&sc->sc_tx_queue); 1096 if (m == NULL) 1097 break; 1098 1099 if (m->m_type == MT_CONTROL) 1100 bwfm_sdio_tx_ctrlframe(sc, m); 1101 else 1102 bwfm_sdio_tx_dataframe(sc, m); 1103 1104 m_freem(m); 1105 } 1106 1107 if (sc->sc_tx_count < 64) 1108 ifq_restart(&ifp->if_snd); 1109 } 1110 1111 void 1112 bwfm_sdio_tx_ctrlframe(struct bwfm_sdio_softc *sc, struct mbuf *m) 1113 { 1114 struct bwfm_sdio_hwhdr *hwhdr; 1115 struct bwfm_sdio_swhdr *swhdr; 1116 size_t len, roundto; 1117 1118 len = sizeof(*hwhdr) + sizeof(*swhdr) + m->m_len; 1119 1120 /* Zero-pad to either block-size or 4-byte alignment. */ 1121 if (len > 512 && (len % 512) != 0) 1122 roundto = 512; 1123 else 1124 roundto = 4; 1125 1126 KASSERT(roundup(len, roundto) <= sc->sc_bounce_size); 1127 1128 hwhdr = (void *)sc->sc_bounce_buf; 1129 hwhdr->frmlen = htole16(len); 1130 hwhdr->cksum = htole16(~len); 1131 1132 swhdr = (void *)&hwhdr[1]; 1133 swhdr->seqnr = sc->sc_tx_seq++; 1134 swhdr->chanflag = BWFM_SDIO_SWHDR_CHANNEL_CONTROL; 1135 swhdr->nextlen = 0; 1136 swhdr->dataoff = sizeof(*hwhdr) + sizeof(*swhdr); 1137 swhdr->maxseqnr = 0; 1138 1139 m_copydata(m, 0, m->m_len, (caddr_t)&swhdr[1]); 1140 1141 if (roundup(len, roundto) != len) 1142 memset(sc->sc_bounce_buf + len, 0, 1143 roundup(len, roundto) - len); 1144 1145 bwfm_sdio_frame_read_write(sc, sc->sc_bounce_buf, 1146 roundup(len, roundto), 1); 1147 } 1148 1149 void 1150 bwfm_sdio_tx_dataframe(struct bwfm_sdio_softc *sc, struct mbuf *m) 1151 { 1152 struct bwfm_sdio_hwhdr *hwhdr; 1153 struct bwfm_sdio_swhdr *swhdr; 1154 struct bwfm_proto_bcdc_hdr *bcdc; 1155 size_t len, roundto; 1156 1157 len = sizeof(*hwhdr) + sizeof(*swhdr) + sizeof(*bcdc) 1158 + m->m_pkthdr.len; 1159 1160 /* Zero-pad to either block-size or 4-byte alignment. */ 1161 if (len > 512 && (len % 512) != 0) 1162 roundto = 512; 1163 else 1164 roundto = 4; 1165 1166 KASSERT(roundup(len, roundto) <= sc->sc_bounce_size); 1167 1168 hwhdr = (void *)sc->sc_bounce_buf; 1169 hwhdr->frmlen = htole16(len); 1170 hwhdr->cksum = htole16(~len); 1171 1172 swhdr = (void *)&hwhdr[1]; 1173 swhdr->seqnr = sc->sc_tx_seq++; 1174 swhdr->chanflag = BWFM_SDIO_SWHDR_CHANNEL_DATA; 1175 swhdr->nextlen = 0; 1176 swhdr->dataoff = sizeof(*hwhdr) + sizeof(*swhdr); 1177 swhdr->maxseqnr = 0; 1178 1179 bcdc = (void *)&swhdr[1]; 1180 bcdc->data_offset = 0; 1181 bcdc->priority = ieee80211_classify(&sc->sc_sc.sc_ic, m); 1182 bcdc->flags = BWFM_BCDC_FLAG_VER(BWFM_BCDC_FLAG_PROTO_VER); 1183 bcdc->flags2 = 0; 1184 1185 m_copydata(m, 0, m->m_pkthdr.len, (caddr_t)&bcdc[1]); 1186 1187 if (roundup(len, roundto) != len) 1188 memset(sc->sc_bounce_buf + len, 0, 1189 roundup(len, roundto) - len); 1190 1191 bwfm_sdio_frame_read_write(sc, sc->sc_bounce_buf, 1192 roundup(len, roundto), 1); 1193 1194 sc->sc_tx_count--; 1195 } 1196 1197 void 1198 bwfm_sdio_rx_frames(struct bwfm_sdio_softc *sc) 1199 { 1200 struct ifnet *ifp = &sc->sc_sc.sc_ic.ic_if; 1201 struct mbuf_list ml = MBUF_LIST_INITIALIZER(); 1202 struct bwfm_sdio_hwhdr *hwhdr; 1203 struct bwfm_sdio_swhdr *swhdr; 1204 uint16_t *sublen, nextlen = 0; 1205 struct mbuf *m; 1206 size_t flen; 1207 char *data; 1208 off_t off; 1209 int nsub; 1210 1211 hwhdr = (struct bwfm_sdio_hwhdr *)sc->sc_bounce_buf; 1212 swhdr = (struct bwfm_sdio_swhdr *)&hwhdr[1]; 1213 data = (char *)&swhdr[1]; 1214 1215 for (;;) { 1216 /* If we know the next size, just read ahead. */ 1217 if (nextlen) { 1218 if (bwfm_sdio_frame_read_write(sc, sc->sc_bounce_buf, 1219 nextlen, 0)) 1220 break; 1221 } else { 1222 if (bwfm_sdio_frame_read_write(sc, sc->sc_bounce_buf, 1223 sizeof(*hwhdr) + sizeof(*swhdr), 0)) 1224 break; 1225 } 1226 1227 hwhdr->frmlen = letoh16(hwhdr->frmlen); 1228 hwhdr->cksum = letoh16(hwhdr->cksum); 1229 1230 if (hwhdr->frmlen == 0 && hwhdr->cksum == 0) 1231 break; 1232 1233 if ((hwhdr->frmlen ^ hwhdr->cksum) != 0xffff) { 1234 printf("%s: checksum error\n", DEVNAME(sc)); 1235 break; 1236 } 1237 1238 if (hwhdr->frmlen < sizeof(*hwhdr) + sizeof(*swhdr)) { 1239 printf("%s: length error\n", DEVNAME(sc)); 1240 break; 1241 } 1242 1243 if (nextlen && hwhdr->frmlen > nextlen) { 1244 printf("%s: read ahead length error (%u > %u)\n", 1245 DEVNAME(sc), hwhdr->frmlen, nextlen); 1246 break; 1247 } 1248 1249 sc->sc_tx_max_seq = swhdr->maxseqnr; 1250 1251 flen = hwhdr->frmlen - (sizeof(*hwhdr) + sizeof(*swhdr)); 1252 if (flen == 0) { 1253 nextlen = swhdr->nextlen << 4; 1254 continue; 1255 } 1256 1257 if (!nextlen) { 1258 KASSERT(roundup(flen, 4) <= sc->sc_bounce_size - 1259 (sizeof(*hwhdr) + sizeof(*swhdr))); 1260 if (bwfm_sdio_frame_read_write(sc, data, 1261 roundup(flen, 4), 0)) 1262 break; 1263 } 1264 1265 if (swhdr->dataoff < (sizeof(*hwhdr) + sizeof(*swhdr))) 1266 break; 1267 1268 off = swhdr->dataoff - (sizeof(*hwhdr) + sizeof(*swhdr)); 1269 if (off > flen) 1270 break; 1271 1272 switch (swhdr->chanflag & BWFM_SDIO_SWHDR_CHANNEL_MASK) { 1273 case BWFM_SDIO_SWHDR_CHANNEL_CONTROL: 1274 sc->sc_sc.sc_proto_ops->proto_rxctl(&sc->sc_sc, 1275 data + off, flen - off); 1276 nextlen = swhdr->nextlen << 4; 1277 break; 1278 case BWFM_SDIO_SWHDR_CHANNEL_EVENT: 1279 case BWFM_SDIO_SWHDR_CHANNEL_DATA: 1280 m = bwfm_sdio_newbuf(); 1281 if (m == NULL) 1282 break; 1283 if (flen - off > m->m_len) { 1284 printf("%s: frame bigger than anticipated\n", 1285 DEVNAME(sc)); 1286 m_freem(m); 1287 break; 1288 } 1289 m->m_len = m->m_pkthdr.len = flen - off; 1290 memcpy(mtod(m, char *), data + off, flen - off); 1291 sc->sc_sc.sc_proto_ops->proto_rx(&sc->sc_sc, m, &ml); 1292 nextlen = swhdr->nextlen << 4; 1293 break; 1294 case BWFM_SDIO_SWHDR_CHANNEL_GLOM: 1295 if ((flen % sizeof(uint16_t)) != 0) 1296 break; 1297 nsub = flen / sizeof(uint16_t); 1298 sublen = mallocarray(nsub, sizeof(uint16_t), 1299 M_DEVBUF, M_WAITOK | M_ZERO); 1300 memcpy(sublen, data, nsub * sizeof(uint16_t)); 1301 bwfm_sdio_rx_glom(sc, sublen, nsub, &nextlen, &ml); 1302 free(sublen, M_DEVBUF, nsub * sizeof(uint16_t)); 1303 break; 1304 default: 1305 printf("%s: unknown channel\n", DEVNAME(sc)); 1306 break; 1307 } 1308 } 1309 1310 if_input(ifp, &ml); 1311 } 1312 1313 void 1314 bwfm_sdio_rx_glom(struct bwfm_sdio_softc *sc, uint16_t *sublen, int nsub, 1315 uint16_t *nextlen, struct mbuf_list *ml) 1316 { 1317 struct bwfm_sdio_hwhdr hwhdr; 1318 struct bwfm_sdio_swhdr swhdr; 1319 struct mbuf_list glom, drop; 1320 struct mbuf *m; 1321 size_t flen; 1322 off_t off; 1323 int i; 1324 1325 ml_init(&glom); 1326 ml_init(&drop); 1327 1328 if (nsub == 0) 1329 return; 1330 1331 for (i = 0; i < nsub; i++) { 1332 m = bwfm_sdio_newbuf(); 1333 if (m == NULL) { 1334 ml_purge(&glom); 1335 return; 1336 } 1337 ml_enqueue(&glom, m); 1338 if (letoh16(sublen[i]) > m->m_len) { 1339 ml_purge(&glom); 1340 return; 1341 } 1342 if (bwfm_sdio_frame_read_write(sc, mtod(m, char *), 1343 letoh16(sublen[i]), 0)) { 1344 ml_purge(&glom); 1345 return; 1346 } 1347 m->m_len = m->m_pkthdr.len = letoh16(sublen[i]); 1348 } 1349 1350 /* TODO: Verify actual superframe header */ 1351 m = MBUF_LIST_FIRST(&glom); 1352 if (m->m_len >= sizeof(hwhdr) + sizeof(swhdr)) { 1353 m_copydata(m, 0, sizeof(hwhdr), (caddr_t)&hwhdr); 1354 m_copydata(m, sizeof(hwhdr), sizeof(swhdr), (caddr_t)&swhdr); 1355 *nextlen = swhdr.nextlen << 4; 1356 m_adj(m, sizeof(struct bwfm_sdio_hwhdr) + 1357 sizeof(struct bwfm_sdio_swhdr)); 1358 } 1359 1360 while ((m = ml_dequeue(&glom)) != NULL) { 1361 if (m->m_len < sizeof(hwhdr) + sizeof(swhdr)) 1362 goto drop; 1363 1364 m_copydata(m, 0, sizeof(hwhdr), (caddr_t)&hwhdr); 1365 m_copydata(m, sizeof(hwhdr), sizeof(swhdr), (caddr_t)&swhdr); 1366 1367 hwhdr.frmlen = letoh16(hwhdr.frmlen); 1368 hwhdr.cksum = letoh16(hwhdr.cksum); 1369 1370 if (hwhdr.frmlen == 0 && hwhdr.cksum == 0) 1371 goto drop; 1372 1373 if ((hwhdr.frmlen ^ hwhdr.cksum) != 0xffff) { 1374 printf("%s: checksum error\n", DEVNAME(sc)); 1375 goto drop; 1376 } 1377 1378 if (hwhdr.frmlen < sizeof(hwhdr) + sizeof(swhdr)) { 1379 printf("%s: length error\n", DEVNAME(sc)); 1380 goto drop; 1381 } 1382 1383 flen = hwhdr.frmlen - (sizeof(hwhdr) + sizeof(swhdr)); 1384 if (flen == 0) 1385 goto drop; 1386 if (m->m_len < flen) 1387 goto drop; 1388 1389 if (swhdr.dataoff < (sizeof(hwhdr) + sizeof(swhdr))) 1390 goto drop; 1391 1392 off = swhdr.dataoff - (sizeof(hwhdr) + sizeof(swhdr)); 1393 if (off > flen) 1394 goto drop; 1395 1396 switch (swhdr.chanflag & BWFM_SDIO_SWHDR_CHANNEL_MASK) { 1397 case BWFM_SDIO_SWHDR_CHANNEL_CONTROL: 1398 printf("%s: control channel not allowed in glom\n", 1399 DEVNAME(sc)); 1400 goto drop; 1401 case BWFM_SDIO_SWHDR_CHANNEL_EVENT: 1402 case BWFM_SDIO_SWHDR_CHANNEL_DATA: 1403 m_adj(m, swhdr.dataoff); 1404 sc->sc_sc.sc_proto_ops->proto_rx(&sc->sc_sc, m, ml); 1405 break; 1406 case BWFM_SDIO_SWHDR_CHANNEL_GLOM: 1407 printf("%s: glom not allowed in glom\n", 1408 DEVNAME(sc)); 1409 goto drop; 1410 default: 1411 printf("%s: unknown channel\n", DEVNAME(sc)); 1412 goto drop; 1413 } 1414 1415 continue; 1416 drop: 1417 ml_enqueue(&drop, m); 1418 } 1419 1420 ml_purge(&drop); 1421 } 1422 1423 int 1424 bwfm_sdio_txcheck(struct bwfm_softc *bwfm) 1425 { 1426 struct bwfm_sdio_softc *sc = (void *)bwfm; 1427 1428 if (sc->sc_tx_count >= 64) 1429 return ENOBUFS; 1430 1431 return 0; 1432 } 1433 1434 int 1435 bwfm_sdio_txdata(struct bwfm_softc *bwfm, struct mbuf *m) 1436 { 1437 struct bwfm_sdio_softc *sc = (void *)bwfm; 1438 1439 if (sc->sc_tx_count >= 64) 1440 return ENOBUFS; 1441 1442 sc->sc_tx_count++; 1443 ml_enqueue(&sc->sc_tx_queue, m); 1444 task_add(systq, &sc->sc_task); 1445 return 0; 1446 } 1447 1448 int 1449 bwfm_sdio_txctl(struct bwfm_softc *bwfm, void *arg) 1450 { 1451 struct bwfm_sdio_softc *sc = (void *)bwfm; 1452 struct bwfm_proto_bcdc_ctl *ctl = arg; 1453 struct mbuf *m; 1454 1455 KASSERT(ctl->len <= MCLBYTES); 1456 1457 MGET(m, M_DONTWAIT, MT_CONTROL); 1458 if (m == NULL) 1459 goto fail; 1460 if (ctl->len > MLEN) { 1461 MCLGET(m, M_DONTWAIT); 1462 if (!(m->m_flags & M_EXT)) { 1463 m_freem(m); 1464 goto fail; 1465 } 1466 } 1467 memcpy(mtod(m, char *), ctl->buf, ctl->len); 1468 m->m_len = ctl->len; 1469 1470 TAILQ_INSERT_TAIL(&sc->sc_sc.sc_bcdc_rxctlq, ctl, next); 1471 ml_enqueue(&sc->sc_tx_queue, m); 1472 task_add(systq, &sc->sc_task); 1473 return 0; 1474 1475 fail: 1476 free(ctl->buf, M_TEMP, ctl->len); 1477 free(ctl, M_TEMP, sizeof(*ctl)); 1478 return 1; 1479 } 1480 1481 #ifdef BWFM_DEBUG 1482 void 1483 bwfm_sdio_debug_console(struct bwfm_sdio_softc *sc) 1484 { 1485 struct bwfm_sdio_console c; 1486 uint32_t newidx; 1487 int err; 1488 1489 if (!sc->sc_console_addr) 1490 return; 1491 1492 err = bwfm_sdio_ram_read_write(sc, sc->sc_console_addr, 1493 (char *)&c, sizeof(c), 0); 1494 if (err) 1495 return; 1496 1497 c.log_buf = letoh32(c.log_buf); 1498 c.log_bufsz = letoh32(c.log_bufsz); 1499 c.log_idx = letoh32(c.log_idx); 1500 1501 if (sc->sc_console_buf == NULL) { 1502 sc->sc_console_buf = malloc(c.log_bufsz, M_DEVBUF, 1503 M_WAITOK|M_ZERO); 1504 sc->sc_console_buf_size = c.log_bufsz; 1505 } 1506 1507 newidx = c.log_idx; 1508 if (newidx >= sc->sc_console_buf_size) 1509 return; 1510 1511 err = bwfm_sdio_ram_read_write(sc, c.log_buf, sc->sc_console_buf, 1512 sc->sc_console_buf_size, 0); 1513 if (err) 1514 return; 1515 1516 if (newidx != sc->sc_console_readidx) 1517 DPRINTFN(3, ("BWFM CONSOLE: ")); 1518 while (newidx != sc->sc_console_readidx) { 1519 uint8_t ch = sc->sc_console_buf[sc->sc_console_readidx]; 1520 sc->sc_console_readidx++; 1521 if (sc->sc_console_readidx == sc->sc_console_buf_size) 1522 sc->sc_console_readidx = 0; 1523 if (ch == '\r') 1524 continue; 1525 DPRINTFN(3, ("%c", ch)); 1526 } 1527 } 1528 #endif 1529