1 /* $OpenBSD: if_bwfm_sdio.c,v 1.39 2021/02/26 00:07:41 patrick 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/sdmmcvar.h> 49 50 #include <dev/ic/bwfmvar.h> 51 #include <dev/ic/bwfmreg.h> 52 #include <dev/sdmmc/if_bwfm_sdio.h> 53 54 #define BWFM_SDIO_CCCR_BRCM_CARDCAP 0xf0 55 #define BWFM_SDIO_CCCR_BRCM_CARDCAP_CMD14_SUPPORT 0x02 56 #define BWFM_SDIO_CCCR_BRCM_CARDCAP_CMD14_EXT 0x04 57 #define BWFM_SDIO_CCCR_BRCM_CARDCAP_CMD_NODEC 0x08 58 #define BWFM_SDIO_CCCR_BRCM_CARDCTRL 0xf1 59 #define BWFM_SDIO_CCCR_BRCM_CARDCTRL_WLANRESET 0x02 60 #define BWFM_SDIO_CCCR_BRCM_SEPINT 0xf2 61 62 /* #define BWFM_DEBUG */ 63 #ifdef BWFM_DEBUG 64 #define DPRINTF(x) do { if (bwfm_debug > 0) printf x; } while (0) 65 #define DPRINTFN(n, x) do { if (bwfm_debug >= (n)) printf x; } while (0) 66 static int bwfm_debug = 1; 67 #else 68 #define DPRINTF(x) do { ; } while (0) 69 #define DPRINTFN(n, x) do { ; } while (0) 70 #endif 71 72 #undef DEVNAME 73 #define DEVNAME(sc) ((sc)->sc_sc.sc_dev.dv_xname) 74 75 enum bwfm_sdio_clkstate { 76 CLK_NONE, 77 CLK_SDONLY, 78 CLK_PENDING, 79 CLK_AVAIL, 80 }; 81 82 struct bwfm_sdio_softc { 83 struct bwfm_softc sc_sc; 84 struct sdmmc_function **sc_sf; 85 struct rwlock *sc_lock; 86 void *sc_ih; 87 int sc_node; 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 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 != 0x02d0) 212 return 0; 213 214 /* Look for supported chips. */ 215 switch (cis->product) { 216 case 0x4324: 217 case 0x4330: 218 case 0x4334: 219 case 0x4329: 220 case 0x4335: 221 case 0x4339: 222 case 0x4345: 223 case 0x4354: 224 case 0x4356: 225 case 0x4359: 226 case 0xa887: /* BCM43143 */ 227 case 0xa94c: /* BCM43340 */ 228 case 0xa94d: /* BCM43341 */ 229 case 0xa962: /* BCM43362 */ 230 case 0xa9a6: /* BCM43430 */ 231 case 0xa9bf: /* 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_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_4330_CHIP_ID: 364 chip = "4330"; 365 break; 366 case BRCM_CC_4334_CHIP_ID: 367 chip = "4334"; 368 break; 369 case BRCM_CC_4345_CHIP_ID: 370 if (bwfm->sc_chip.ch_chiprev == 9) 371 chip = "43456"; 372 else 373 chip = "43455"; 374 break; 375 case BRCM_CC_43340_CHIP_ID: 376 case BRCM_CC_43341_CHIP_ID: 377 chip = "43340"; 378 break; 379 case BRCM_CC_4335_CHIP_ID: 380 if (bwfm->sc_chip.ch_chiprev < 2) 381 chip = "4335"; 382 else 383 chip = "4339"; 384 break; 385 case BRCM_CC_4339_CHIP_ID: 386 chip = "4339"; 387 break; 388 case BRCM_CC_43430_CHIP_ID: 389 if (bwfm->sc_chip.ch_chiprev == 0) 390 chip = "43430a0"; 391 else 392 chip = "43430"; 393 break; 394 case BRCM_CC_4356_CHIP_ID: 395 chip = "4356"; 396 break; 397 case BRCM_CC_4359_CHIP_ID: 398 chip = "4359"; 399 break; 400 default: 401 printf("%s: unknown firmware for chip %s\n", 402 DEVNAME(sc), bwfm->sc_chip.ch_name); 403 goto err; 404 } 405 406 if (bwfm_loadfirmware(bwfm, chip, "-sdio", &ucode, &size, 407 &nvram, &nvsize, &nvlen) != 0) 408 goto err; 409 410 sc->sc_alp_only = 1; 411 if (bwfm_sdio_load_microcode(sc, ucode, size, 412 nvram, nvlen) != 0) { 413 printf("%s: could not load microcode\n", 414 DEVNAME(sc)); 415 free(ucode, M_DEVBUF, size); 416 free(nvram, M_DEVBUF, nvsize); 417 goto err; 418 } 419 sc->sc_alp_only = 0; 420 free(ucode, M_DEVBUF, size); 421 free(nvram, M_DEVBUF, nvsize); 422 423 bwfm_sdio_clkctl(sc, CLK_AVAIL, 0); 424 if (sc->sc_clkstate != CLK_AVAIL) 425 goto err; 426 427 clk = bwfm_sdio_read_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR); 428 bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR, 429 clk | BWFM_SDIO_FUNC1_CHIPCLKCSR_FORCE_HT); 430 431 bwfm_sdio_dev_write(sc, SDPCMD_TOSBMAILBOXDATA, 432 SDPCM_PROT_VERSION << SDPCM_PROT_VERSION_SHIFT); 433 if (sdmmc_io_function_enable(sc->sc_sf[2]) != 0) { 434 printf("%s: cannot enable function 2\n", DEVNAME(sc)); 435 goto err; 436 } 437 438 bwfm_sdio_dev_write(sc, SDPCMD_HOSTINTMASK, 439 SDPCMD_INTSTATUS_HMB_SW_MASK|SDPCMD_INTSTATUS_CHIPACTIVE); 440 bwfm_sdio_write_1(sc, BWFM_SDIO_WATERMARK, 8); 441 442 if (bwfm_chip_sr_capable(bwfm)) { 443 reg = bwfm_sdio_read_1(sc, BWFM_SDIO_FUNC1_WAKEUPCTRL); 444 reg |= BWFM_SDIO_FUNC1_WAKEUPCTRL_HTWAIT; 445 bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_WAKEUPCTRL, reg); 446 bwfm_sdio_write_1(sc, BWFM_SDIO_CCCR_CARDCAP, 447 BWFM_SDIO_CCCR_CARDCAP_CMD14_SUPPORT | 448 BWFM_SDIO_CCCR_CARDCAP_CMD14_EXT); 449 bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR, 450 BWFM_SDIO_FUNC1_CHIPCLKCSR_FORCE_HT); 451 sc->sc_sr_enabled = 1; 452 } else { 453 bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR, clk); 454 } 455 456 #if defined(__HAVE_FDT) 457 if (sc->sc_node) { 458 sc->sc_ih = fdt_intr_establish(sc->sc_node, 459 IPL_NET, bwfm_sdio_oob_intr, sc, DEVNAME(sc)); 460 if (sc->sc_ih != NULL) { 461 bwfm_sdio_write_1(sc, BWFM_SDIO_CCCR_SEPINT, 462 BWFM_SDIO_CCCR_SEPINT_MASK | 463 BWFM_SDIO_CCCR_SEPINT_OE | 464 BWFM_SDIO_CCCR_SEPINT_ACT_HI); 465 sc->sc_oob = 1; 466 } 467 } 468 if (sc->sc_ih == NULL) 469 #endif 470 sc->sc_ih = sdmmc_intr_establish(bwfm->sc_dev.dv_parent, 471 bwfm_sdio_intr, sc, DEVNAME(sc)); 472 if (sc->sc_ih == NULL) { 473 printf("%s: can't establish interrupt\n", DEVNAME(sc)); 474 bwfm_sdio_clkctl(sc, CLK_NONE, 0); 475 goto err; 476 } 477 sdmmc_intr_enable(sc->sc_sf[1]); 478 rw_exit(sc->sc_lock); 479 480 sc->sc_initialized = 1; 481 return 0; 482 483 err: 484 rw_exit(sc->sc_lock); 485 return 1; 486 } 487 488 int 489 bwfm_sdio_load_microcode(struct bwfm_sdio_softc *sc, u_char *ucode, size_t size, 490 u_char *nvram, size_t nvlen) 491 { 492 struct bwfm_softc *bwfm = (void *)sc; 493 char *verify = NULL; 494 int err = 0; 495 496 bwfm_sdio_clkctl(sc, CLK_AVAIL, 0); 497 498 /* Upload firmware */ 499 err = bwfm_sdio_ram_read_write(sc, bwfm->sc_chip.ch_rambase, 500 ucode, size, 1); 501 if (err) 502 goto out; 503 504 /* Verify firmware */ 505 verify = malloc(size, M_TEMP, M_WAITOK | M_ZERO); 506 err = bwfm_sdio_ram_read_write(sc, bwfm->sc_chip.ch_rambase, 507 verify, size, 0); 508 if (err || memcmp(verify, ucode, size)) { 509 printf("%s: firmware verification failed\n", 510 DEVNAME(sc)); 511 free(verify, M_TEMP, size); 512 goto out; 513 } 514 free(verify, M_TEMP, size); 515 516 /* Upload nvram */ 517 err = bwfm_sdio_ram_read_write(sc, bwfm->sc_chip.ch_rambase + 518 bwfm->sc_chip.ch_ramsize - nvlen, nvram, nvlen, 1); 519 if (err) 520 goto out; 521 522 /* Verify nvram */ 523 verify = malloc(nvlen, M_TEMP, M_WAITOK | M_ZERO); 524 err = bwfm_sdio_ram_read_write(sc, bwfm->sc_chip.ch_rambase + 525 bwfm->sc_chip.ch_ramsize - nvlen, verify, nvlen, 0); 526 if (err || memcmp(verify, nvram, nvlen)) { 527 printf("%s: nvram verification failed\n", 528 DEVNAME(sc)); 529 free(verify, M_TEMP, nvlen); 530 goto out; 531 } 532 free(verify, M_TEMP, nvlen); 533 534 /* Load reset vector from firmware and kickstart core. */ 535 bwfm_chip_set_active(bwfm, *(uint32_t *)ucode); 536 537 out: 538 bwfm_sdio_clkctl(sc, CLK_SDONLY, 0); 539 return err; 540 } 541 542 void 543 bwfm_sdio_clkctl(struct bwfm_sdio_softc *sc, enum bwfm_sdio_clkstate newstate, 544 int pendok) 545 { 546 enum bwfm_sdio_clkstate oldstate; 547 548 oldstate = sc->sc_clkstate; 549 if (sc->sc_clkstate == newstate) 550 return; 551 552 switch (newstate) { 553 case CLK_AVAIL: 554 if (sc->sc_clkstate == CLK_NONE) 555 sc->sc_clkstate = CLK_SDONLY; 556 bwfm_sdio_htclk(sc, 1, pendok); 557 break; 558 case CLK_SDONLY: 559 if (sc->sc_clkstate == CLK_NONE) 560 sc->sc_clkstate = CLK_SDONLY; 561 else if (sc->sc_clkstate == CLK_AVAIL) 562 bwfm_sdio_htclk(sc, 0, 0); 563 else 564 printf("%s: request for %d -> %d\n", 565 DEVNAME(sc), sc->sc_clkstate, newstate); 566 break; 567 case CLK_NONE: 568 if (sc->sc_clkstate == CLK_AVAIL) 569 bwfm_sdio_htclk(sc, 0, 0); 570 sc->sc_clkstate = CLK_NONE; 571 break; 572 default: 573 break; 574 } 575 576 DPRINTF(("%s: %d -> %d = %d\n", DEVNAME(sc), oldstate, newstate, 577 sc->sc_clkstate)); 578 } 579 580 void 581 bwfm_sdio_htclk(struct bwfm_sdio_softc *sc, int on, int pendok) 582 { 583 uint32_t clkctl, devctl, req; 584 int i; 585 586 if (sc->sc_sr_enabled) { 587 if (on) 588 sc->sc_clkstate = CLK_AVAIL; 589 else 590 sc->sc_clkstate = CLK_SDONLY; 591 return; 592 } 593 594 if (on) { 595 if (sc->sc_alp_only) 596 req = BWFM_SDIO_FUNC1_CHIPCLKCSR_ALP_AVAIL_REQ; 597 else 598 req = BWFM_SDIO_FUNC1_CHIPCLKCSR_HT_AVAIL_REQ; 599 bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR, req); 600 601 clkctl = bwfm_sdio_read_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR); 602 if (!BWFM_SDIO_FUNC1_CHIPCLKCSR_CLKAV(clkctl, sc->sc_alp_only) 603 && pendok) { 604 devctl = bwfm_sdio_read_1(sc, BWFM_SDIO_DEVICE_CTL); 605 devctl |= BWFM_SDIO_DEVICE_CTL_CA_INT_ONLY; 606 bwfm_sdio_write_1(sc, BWFM_SDIO_DEVICE_CTL, devctl); 607 sc->sc_clkstate = CLK_PENDING; 608 return; 609 } else if (sc->sc_clkstate == CLK_PENDING) { 610 devctl = bwfm_sdio_read_1(sc, BWFM_SDIO_DEVICE_CTL); 611 devctl &= ~BWFM_SDIO_DEVICE_CTL_CA_INT_ONLY; 612 bwfm_sdio_write_1(sc, BWFM_SDIO_DEVICE_CTL, devctl); 613 } 614 615 for (i = 0; i < 5000; i++) { 616 if (BWFM_SDIO_FUNC1_CHIPCLKCSR_CLKAV(clkctl, 617 sc->sc_alp_only)) 618 break; 619 clkctl = bwfm_sdio_read_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR); 620 delay(1000); 621 } 622 if (!BWFM_SDIO_FUNC1_CHIPCLKCSR_CLKAV(clkctl, sc->sc_alp_only)) { 623 printf("%s: HT avail timeout\n", DEVNAME(sc)); 624 return; 625 } 626 627 sc->sc_clkstate = CLK_AVAIL; 628 } else { 629 if (sc->sc_clkstate == CLK_PENDING) { 630 devctl = bwfm_sdio_read_1(sc, BWFM_SDIO_DEVICE_CTL); 631 devctl &= ~BWFM_SDIO_DEVICE_CTL_CA_INT_ONLY; 632 bwfm_sdio_write_1(sc, BWFM_SDIO_DEVICE_CTL, devctl); 633 } 634 sc->sc_clkstate = CLK_SDONLY; 635 bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR, 0); 636 } 637 } 638 639 void 640 bwfm_sdio_readshared(struct bwfm_sdio_softc *sc) 641 { 642 struct bwfm_softc *bwfm = (void *)sc; 643 struct bwfm_sdio_sdpcm sdpcm; 644 uint32_t addr, shaddr; 645 int err; 646 647 shaddr = bwfm->sc_chip.ch_rambase + bwfm->sc_chip.ch_ramsize - 4; 648 if (!bwfm->sc_chip.ch_rambase && bwfm_chip_sr_capable(bwfm)) 649 shaddr -= bwfm->sc_chip.ch_srsize; 650 651 err = bwfm_sdio_ram_read_write(sc, shaddr, (char *)&addr, 652 sizeof(addr), 0); 653 if (err) 654 return; 655 656 addr = letoh32(addr); 657 if (addr == 0 || ((~addr >> 16) & 0xffff) == (addr & 0xffff)) 658 return; 659 660 err = bwfm_sdio_ram_read_write(sc, addr, (char *)&sdpcm, 661 sizeof(sdpcm), 0); 662 if (err) 663 return; 664 665 sc->sc_console_addr = letoh32(sdpcm.console_addr); 666 } 667 668 int 669 bwfm_sdio_intr(void *v) 670 { 671 bwfm_sdio_task(v); 672 return 1; 673 } 674 675 #if defined(__HAVE_FDT) 676 int 677 bwfm_sdio_oob_intr(void *v) 678 { 679 struct bwfm_sdio_softc *sc = (void *)v; 680 if (!sc->sc_oob) 681 return 0; 682 fdt_intr_disable(sc->sc_ih); 683 task_add(systq, &sc->sc_task); 684 return 1; 685 } 686 #endif 687 688 void 689 bwfm_sdio_task(void *v) 690 { 691 struct bwfm_sdio_softc *sc = (void *)v; 692 uint32_t clkctl, devctl, intstat, hostint; 693 694 rw_enter_write(sc->sc_lock); 695 696 if (!sc->sc_sr_enabled && sc->sc_clkstate == CLK_PENDING) { 697 clkctl = bwfm_sdio_read_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR); 698 if (BWFM_SDIO_FUNC1_CHIPCLKCSR_HTAV(clkctl)) { 699 devctl = bwfm_sdio_read_1(sc, BWFM_SDIO_DEVICE_CTL); 700 devctl &= ~BWFM_SDIO_DEVICE_CTL_CA_INT_ONLY; 701 bwfm_sdio_write_1(sc, BWFM_SDIO_DEVICE_CTL, devctl); 702 sc->sc_clkstate = CLK_AVAIL; 703 } 704 } 705 706 intstat = bwfm_sdio_dev_read(sc, BWFM_SDPCMD_INTSTATUS); 707 intstat &= (SDPCMD_INTSTATUS_HMB_SW_MASK|SDPCMD_INTSTATUS_CHIPACTIVE); 708 /* XXX fc state */ 709 if (intstat) 710 bwfm_sdio_dev_write(sc, BWFM_SDPCMD_INTSTATUS, intstat); 711 712 if (intstat & SDPCMD_INTSTATUS_HMB_HOST_INT) { 713 hostint = bwfm_sdio_dev_read(sc, SDPCMD_TOHOSTMAILBOXDATA); 714 bwfm_sdio_dev_write(sc, SDPCMD_TOSBMAILBOX, 715 SDPCMD_TOSBMAILBOX_INT_ACK); 716 if (hostint & SDPCMD_TOHOSTMAILBOXDATA_NAKHANDLED) 717 intstat |= SDPCMD_INTSTATUS_HMB_FRAME_IND; 718 if (hostint & SDPCMD_TOHOSTMAILBOXDATA_DEVREADY || 719 hostint & SDPCMD_TOHOSTMAILBOXDATA_FWREADY) 720 bwfm_sdio_readshared(sc); 721 } 722 723 /* FIXME: Might stall if we don't when not set. */ 724 if (1 || intstat & SDPCMD_INTSTATUS_HMB_FRAME_IND) { 725 bwfm_sdio_rx_frames(sc); 726 } 727 728 if (!ml_empty(&sc->sc_tx_queue)) { 729 bwfm_sdio_tx_frames(sc); 730 } 731 732 #ifdef BWFM_DEBUG 733 bwfm_sdio_debug_console(sc); 734 #endif 735 736 rw_exit(sc->sc_lock); 737 738 #if defined(__HAVE_FDT) 739 if (sc->sc_oob) 740 fdt_intr_enable(sc->sc_ih); 741 #endif 742 } 743 744 int 745 bwfm_sdio_detach(struct device *self, int flags) 746 { 747 struct bwfm_sdio_softc *sc = (struct bwfm_sdio_softc *)self; 748 749 bwfm_detach(&sc->sc_sc, flags); 750 751 dma_free(sc->sc_bounce_buf, sc->sc_bounce_size); 752 free(sc->sc_sf, M_DEVBUF, 0); 753 754 return 0; 755 } 756 757 void 758 bwfm_sdio_backplane(struct bwfm_sdio_softc *sc, uint32_t bar0) 759 { 760 if (sc->sc_bar0 == bar0) 761 return; 762 763 bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_SBADDRLOW, 764 (bar0 >> 8) & 0x80); 765 bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_SBADDRMID, 766 (bar0 >> 16) & 0xff); 767 bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_SBADDRHIGH, 768 (bar0 >> 24) & 0xff); 769 sc->sc_bar0 = bar0; 770 } 771 772 uint8_t 773 bwfm_sdio_read_1(struct bwfm_sdio_softc *sc, uint32_t addr) 774 { 775 struct sdmmc_function *sf; 776 uint8_t rv; 777 778 /* 779 * figure out how to read the register based on address range 780 * 0x00 ~ 0x7FF: function 0 CCCR and FBR 781 * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers 782 * The rest: function 1 silicon backplane core registers 783 */ 784 if ((addr & ~0x7ff) == 0) 785 sf = sc->sc_sf[0]; 786 else 787 sf = sc->sc_sf[1]; 788 789 rv = sdmmc_io_read_1(sf, addr); 790 return rv; 791 } 792 793 uint32_t 794 bwfm_sdio_read_4(struct bwfm_sdio_softc *sc, uint32_t addr) 795 { 796 struct sdmmc_function *sf; 797 uint32_t bar0 = addr & ~BWFM_SDIO_SB_OFT_ADDR_MASK; 798 uint32_t rv; 799 800 bwfm_sdio_backplane(sc, bar0); 801 802 addr &= BWFM_SDIO_SB_OFT_ADDR_MASK; 803 addr |= BWFM_SDIO_SB_ACCESS_2_4B_FLAG; 804 805 /* 806 * figure out how to read the register based on address range 807 * 0x00 ~ 0x7FF: function 0 CCCR and FBR 808 * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers 809 * The rest: function 1 silicon backplane core registers 810 */ 811 if ((addr & ~0x7ff) == 0) 812 sf = sc->sc_sf[0]; 813 else 814 sf = sc->sc_sf[1]; 815 816 rv = sdmmc_io_read_4(sf, addr); 817 return rv; 818 } 819 820 void 821 bwfm_sdio_write_1(struct bwfm_sdio_softc *sc, uint32_t addr, uint8_t data) 822 { 823 struct sdmmc_function *sf; 824 825 /* 826 * figure out how to read the register based on address range 827 * 0x00 ~ 0x7FF: function 0 CCCR and FBR 828 * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers 829 * The rest: function 1 silicon backplane core registers 830 */ 831 if ((addr & ~0x7ff) == 0) 832 sf = sc->sc_sf[0]; 833 else 834 sf = sc->sc_sf[1]; 835 836 sdmmc_io_write_1(sf, addr, data); 837 } 838 839 void 840 bwfm_sdio_write_4(struct bwfm_sdio_softc *sc, uint32_t addr, uint32_t data) 841 { 842 struct sdmmc_function *sf; 843 uint32_t bar0 = addr & ~BWFM_SDIO_SB_OFT_ADDR_MASK; 844 845 bwfm_sdio_backplane(sc, bar0); 846 847 addr &= BWFM_SDIO_SB_OFT_ADDR_MASK; 848 addr |= BWFM_SDIO_SB_ACCESS_2_4B_FLAG; 849 850 /* 851 * figure out how to read the register based on address range 852 * 0x00 ~ 0x7FF: function 0 CCCR and FBR 853 * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers 854 * The rest: function 1 silicon backplane core registers 855 */ 856 if ((addr & ~0x7ff) == 0) 857 sf = sc->sc_sf[0]; 858 else 859 sf = sc->sc_sf[1]; 860 861 sdmmc_io_write_4(sf, addr, data); 862 } 863 864 int 865 bwfm_sdio_buf_read(struct bwfm_sdio_softc *sc, struct sdmmc_function *sf, 866 uint32_t reg, char *data, size_t size) 867 { 868 int err; 869 870 KASSERT(((vaddr_t)data & 0x3) == 0); 871 KASSERT((size & 0x3) == 0); 872 873 if (sf == sc->sc_sf[1]) 874 err = sdmmc_io_read_region_1(sf, reg, data, size); 875 else 876 err = sdmmc_io_read_multi_1(sf, reg, data, size); 877 878 if (err) 879 printf("%s: error %d\n", __func__, err); 880 881 return err; 882 } 883 884 int 885 bwfm_sdio_buf_write(struct bwfm_sdio_softc *sc, struct sdmmc_function *sf, 886 uint32_t reg, char *data, size_t size) 887 { 888 int err; 889 890 KASSERT(((vaddr_t)data & 0x3) == 0); 891 KASSERT((size & 0x3) == 0); 892 893 err = sdmmc_io_write_region_1(sf, reg, data, size); 894 895 if (err) 896 printf("%s: error %d\n", __func__, err); 897 898 return err; 899 } 900 901 uint32_t 902 bwfm_sdio_ram_read_write(struct bwfm_sdio_softc *sc, uint32_t reg, 903 char *data, size_t left, int write) 904 { 905 uint32_t sbaddr, sdaddr, off; 906 size_t size; 907 int err; 908 909 err = off = 0; 910 while (left > 0) { 911 sbaddr = reg + off; 912 bwfm_sdio_backplane(sc, sbaddr); 913 914 sdaddr = sbaddr & BWFM_SDIO_SB_OFT_ADDR_MASK; 915 size = min(left, (BWFM_SDIO_SB_OFT_ADDR_PAGE - sdaddr)); 916 sdaddr |= BWFM_SDIO_SB_ACCESS_2_4B_FLAG; 917 918 if (write) { 919 memcpy(sc->sc_bounce_buf, data + off, size); 920 if (roundup(size, 4) != size) 921 memset(sc->sc_bounce_buf + size, 0, 922 roundup(size, 4) - size); 923 err = bwfm_sdio_buf_write(sc, sc->sc_sf[1], sdaddr, 924 sc->sc_bounce_buf, roundup(size, 4)); 925 } else { 926 err = bwfm_sdio_buf_read(sc, sc->sc_sf[1], sdaddr, 927 sc->sc_bounce_buf, roundup(size, 4)); 928 memcpy(data + off, sc->sc_bounce_buf, size); 929 } 930 if (err) 931 break; 932 933 off += size; 934 left -= size; 935 } 936 937 return err; 938 } 939 940 uint32_t 941 bwfm_sdio_frame_read_write(struct bwfm_sdio_softc *sc, 942 char *data, size_t size, int write) 943 { 944 uint32_t addr; 945 int err; 946 947 addr = sc->sc_cc->co_base; 948 bwfm_sdio_backplane(sc, addr); 949 950 addr &= BWFM_SDIO_SB_OFT_ADDR_MASK; 951 addr |= BWFM_SDIO_SB_ACCESS_2_4B_FLAG; 952 953 if (write) 954 err = bwfm_sdio_buf_write(sc, sc->sc_sf[2], addr, data, size); 955 else 956 err = bwfm_sdio_buf_read(sc, sc->sc_sf[2], addr, data, size); 957 958 return err; 959 } 960 961 uint32_t 962 bwfm_sdio_dev_read(struct bwfm_sdio_softc *sc, uint32_t reg) 963 { 964 struct bwfm_core *core; 965 core = bwfm_chip_get_core(&sc->sc_sc, BWFM_AGENT_CORE_SDIO_DEV); 966 return bwfm_sdio_read_4(sc, core->co_base + reg); 967 } 968 969 void 970 bwfm_sdio_dev_write(struct bwfm_sdio_softc *sc, uint32_t reg, uint32_t val) 971 { 972 struct bwfm_core *core; 973 core = bwfm_chip_get_core(&sc->sc_sc, BWFM_AGENT_CORE_SDIO_DEV); 974 bwfm_sdio_write_4(sc, core->co_base + reg, val); 975 } 976 977 uint32_t 978 bwfm_sdio_buscore_read(struct bwfm_softc *bwfm, uint32_t reg) 979 { 980 struct bwfm_sdio_softc *sc = (void *)bwfm; 981 return bwfm_sdio_read_4(sc, reg); 982 } 983 984 void 985 bwfm_sdio_buscore_write(struct bwfm_softc *bwfm, uint32_t reg, uint32_t val) 986 { 987 struct bwfm_sdio_softc *sc = (void *)bwfm; 988 bwfm_sdio_write_4(sc, reg, val); 989 } 990 991 int 992 bwfm_sdio_buscore_prepare(struct bwfm_softc *bwfm) 993 { 994 struct bwfm_sdio_softc *sc = (void *)bwfm; 995 uint8_t clkval, clkset, clkmask; 996 int i; 997 998 clkset = BWFM_SDIO_FUNC1_CHIPCLKCSR_ALP_AVAIL_REQ | 999 BWFM_SDIO_FUNC1_CHIPCLKCSR_FORCE_HW_CLKREQ_OFF; 1000 bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR, clkset); 1001 1002 clkmask = BWFM_SDIO_FUNC1_CHIPCLKCSR_ALP_AVAIL | 1003 BWFM_SDIO_FUNC1_CHIPCLKCSR_HT_AVAIL; 1004 clkval = bwfm_sdio_read_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR); 1005 1006 if ((clkval & ~clkmask) != clkset) { 1007 printf("%s: wrote 0x%02x read 0x%02x\n", DEVNAME(sc), 1008 clkset, clkval); 1009 return 1; 1010 } 1011 1012 for (i = 1000; i > 0; i--) { 1013 clkval = bwfm_sdio_read_1(sc, 1014 BWFM_SDIO_FUNC1_CHIPCLKCSR); 1015 if (clkval & clkmask) 1016 break; 1017 } 1018 if (i == 0) { 1019 printf("%s: timeout on ALPAV wait, clkval 0x%02x\n", 1020 DEVNAME(sc), clkval); 1021 return 1; 1022 } 1023 1024 clkset = BWFM_SDIO_FUNC1_CHIPCLKCSR_FORCE_HW_CLKREQ_OFF | 1025 BWFM_SDIO_FUNC1_CHIPCLKCSR_FORCE_ALP; 1026 bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR, clkset); 1027 delay(65); 1028 1029 bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_SDIOPULLUP, 0); 1030 1031 return 0; 1032 } 1033 1034 void 1035 bwfm_sdio_buscore_activate(struct bwfm_softc *bwfm, uint32_t rstvec) 1036 { 1037 struct bwfm_sdio_softc *sc = (void *)bwfm; 1038 1039 bwfm_sdio_dev_write(sc, BWFM_SDPCMD_INTSTATUS, 0xFFFFFFFF); 1040 1041 if (rstvec) 1042 bwfm_sdio_ram_read_write(sc, 0, (char *)&rstvec, 1043 sizeof(rstvec), 1); 1044 } 1045 1046 struct mbuf * 1047 bwfm_sdio_newbuf(void) 1048 { 1049 struct mbuf *m; 1050 1051 MGETHDR(m, M_DONTWAIT, MT_DATA); 1052 if (m == NULL) 1053 return (NULL); 1054 1055 MCLGET(m, M_DONTWAIT); 1056 if (!(m->m_flags & M_EXT)) { 1057 m_freem(m); 1058 return (NULL); 1059 } 1060 1061 m->m_len = m->m_pkthdr.len = MCLBYTES; 1062 1063 return (m); 1064 } 1065 1066 int 1067 bwfm_sdio_tx_ok(struct bwfm_sdio_softc *sc) 1068 { 1069 return (uint8_t)(sc->sc_tx_max_seq - sc->sc_tx_seq) != 0 && 1070 ((uint8_t)(sc->sc_tx_max_seq - sc->sc_tx_seq) & 0x80) == 0; 1071 } 1072 1073 void 1074 bwfm_sdio_tx_frames(struct bwfm_sdio_softc *sc) 1075 { 1076 struct ifnet *ifp = &sc->sc_sc.sc_ic.ic_if; 1077 struct mbuf *m; 1078 int i; 1079 1080 if (!bwfm_sdio_tx_ok(sc)) 1081 return; 1082 1083 i = min((uint8_t)(sc->sc_tx_max_seq - sc->sc_tx_seq), 32); 1084 while (i--) { 1085 m = ml_dequeue(&sc->sc_tx_queue); 1086 if (m == NULL) 1087 break; 1088 1089 if (m->m_type == MT_CONTROL) 1090 bwfm_sdio_tx_ctrlframe(sc, m); 1091 else 1092 bwfm_sdio_tx_dataframe(sc, m); 1093 1094 m_freem(m); 1095 } 1096 1097 if (sc->sc_tx_count < 64) 1098 ifq_restart(&ifp->if_snd); 1099 } 1100 1101 void 1102 bwfm_sdio_tx_ctrlframe(struct bwfm_sdio_softc *sc, struct mbuf *m) 1103 { 1104 struct bwfm_sdio_hwhdr *hwhdr; 1105 struct bwfm_sdio_swhdr *swhdr; 1106 size_t len, roundto; 1107 1108 len = sizeof(*hwhdr) + sizeof(*swhdr) + m->m_len; 1109 1110 /* Zero-pad to either block-size or 4-byte alignment. */ 1111 if (len > 512 && (len % 512) != 0) 1112 roundto = 512; 1113 else 1114 roundto = 4; 1115 1116 KASSERT(roundup(len, roundto) <= sc->sc_bounce_size); 1117 1118 hwhdr = (void *)sc->sc_bounce_buf; 1119 hwhdr->frmlen = htole16(len); 1120 hwhdr->cksum = htole16(~len); 1121 1122 swhdr = (void *)&hwhdr[1]; 1123 swhdr->seqnr = sc->sc_tx_seq++; 1124 swhdr->chanflag = BWFM_SDIO_SWHDR_CHANNEL_CONTROL; 1125 swhdr->nextlen = 0; 1126 swhdr->dataoff = sizeof(*hwhdr) + sizeof(*swhdr); 1127 swhdr->maxseqnr = 0; 1128 1129 m_copydata(m, 0, m->m_len, (caddr_t)&swhdr[1]); 1130 1131 if (roundup(len, roundto) != len) 1132 memset(sc->sc_bounce_buf + len, 0, 1133 roundup(len, roundto) - len); 1134 1135 bwfm_sdio_frame_read_write(sc, sc->sc_bounce_buf, 1136 roundup(len, roundto), 1); 1137 } 1138 1139 void 1140 bwfm_sdio_tx_dataframe(struct bwfm_sdio_softc *sc, struct mbuf *m) 1141 { 1142 struct bwfm_sdio_hwhdr *hwhdr; 1143 struct bwfm_sdio_swhdr *swhdr; 1144 struct bwfm_proto_bcdc_hdr *bcdc; 1145 size_t len, roundto; 1146 1147 len = sizeof(*hwhdr) + sizeof(*swhdr) + sizeof(*bcdc) 1148 + m->m_pkthdr.len; 1149 1150 /* Zero-pad to either block-size or 4-byte alignment. */ 1151 if (len > 512 && (len % 512) != 0) 1152 roundto = 512; 1153 else 1154 roundto = 4; 1155 1156 KASSERT(roundup(len, roundto) <= sc->sc_bounce_size); 1157 1158 hwhdr = (void *)sc->sc_bounce_buf; 1159 hwhdr->frmlen = htole16(len); 1160 hwhdr->cksum = htole16(~len); 1161 1162 swhdr = (void *)&hwhdr[1]; 1163 swhdr->seqnr = sc->sc_tx_seq++; 1164 swhdr->chanflag = BWFM_SDIO_SWHDR_CHANNEL_DATA; 1165 swhdr->nextlen = 0; 1166 swhdr->dataoff = sizeof(*hwhdr) + sizeof(*swhdr); 1167 swhdr->maxseqnr = 0; 1168 1169 bcdc = (void *)&swhdr[1]; 1170 bcdc->data_offset = 0; 1171 bcdc->priority = ieee80211_classify(&sc->sc_sc.sc_ic, m); 1172 bcdc->flags = BWFM_BCDC_FLAG_VER(BWFM_BCDC_FLAG_PROTO_VER); 1173 bcdc->flags2 = 0; 1174 1175 m_copydata(m, 0, m->m_pkthdr.len, (caddr_t)&bcdc[1]); 1176 1177 if (roundup(len, roundto) != len) 1178 memset(sc->sc_bounce_buf + len, 0, 1179 roundup(len, roundto) - len); 1180 1181 bwfm_sdio_frame_read_write(sc, sc->sc_bounce_buf, 1182 roundup(len, roundto), 1); 1183 1184 sc->sc_tx_count--; 1185 } 1186 1187 void 1188 bwfm_sdio_rx_frames(struct bwfm_sdio_softc *sc) 1189 { 1190 struct ifnet *ifp = &sc->sc_sc.sc_ic.ic_if; 1191 struct mbuf_list ml = MBUF_LIST_INITIALIZER(); 1192 struct bwfm_sdio_hwhdr *hwhdr; 1193 struct bwfm_sdio_swhdr *swhdr; 1194 uint16_t *sublen, nextlen = 0; 1195 struct mbuf *m; 1196 size_t flen; 1197 char *data; 1198 off_t off; 1199 int nsub; 1200 1201 hwhdr = (struct bwfm_sdio_hwhdr *)sc->sc_bounce_buf; 1202 swhdr = (struct bwfm_sdio_swhdr *)&hwhdr[1]; 1203 data = (char *)&swhdr[1]; 1204 1205 for (;;) { 1206 /* If we know the next size, just read ahead. */ 1207 if (nextlen) { 1208 if (bwfm_sdio_frame_read_write(sc, sc->sc_bounce_buf, 1209 nextlen, 0)) 1210 break; 1211 } else { 1212 if (bwfm_sdio_frame_read_write(sc, sc->sc_bounce_buf, 1213 sizeof(*hwhdr) + sizeof(*swhdr), 0)) 1214 break; 1215 } 1216 1217 hwhdr->frmlen = letoh16(hwhdr->frmlen); 1218 hwhdr->cksum = letoh16(hwhdr->cksum); 1219 1220 if (hwhdr->frmlen == 0 && hwhdr->cksum == 0) 1221 break; 1222 1223 if ((hwhdr->frmlen ^ hwhdr->cksum) != 0xffff) { 1224 printf("%s: checksum error\n", DEVNAME(sc)); 1225 break; 1226 } 1227 1228 if (hwhdr->frmlen < sizeof(*hwhdr) + sizeof(*swhdr)) { 1229 printf("%s: length error\n", DEVNAME(sc)); 1230 break; 1231 } 1232 1233 if (nextlen && hwhdr->frmlen > nextlen) { 1234 printf("%s: read ahead length error (%u > %u)\n", 1235 DEVNAME(sc), hwhdr->frmlen, nextlen); 1236 break; 1237 } 1238 1239 sc->sc_tx_max_seq = swhdr->maxseqnr; 1240 1241 flen = hwhdr->frmlen - (sizeof(*hwhdr) + sizeof(*swhdr)); 1242 if (flen == 0) { 1243 nextlen = swhdr->nextlen << 4; 1244 continue; 1245 } 1246 1247 if (!nextlen) { 1248 KASSERT(roundup(flen, 4) <= sc->sc_bounce_size - 1249 (sizeof(*hwhdr) + sizeof(*swhdr))); 1250 if (bwfm_sdio_frame_read_write(sc, data, 1251 roundup(flen, 4), 0)) 1252 break; 1253 } 1254 1255 if (swhdr->dataoff < (sizeof(*hwhdr) + sizeof(*swhdr))) 1256 break; 1257 1258 off = swhdr->dataoff - (sizeof(*hwhdr) + sizeof(*swhdr)); 1259 if (off > flen) 1260 break; 1261 1262 switch (swhdr->chanflag & BWFM_SDIO_SWHDR_CHANNEL_MASK) { 1263 case BWFM_SDIO_SWHDR_CHANNEL_CONTROL: 1264 sc->sc_sc.sc_proto_ops->proto_rxctl(&sc->sc_sc, 1265 data + off, flen - off); 1266 nextlen = swhdr->nextlen << 4; 1267 break; 1268 case BWFM_SDIO_SWHDR_CHANNEL_EVENT: 1269 case BWFM_SDIO_SWHDR_CHANNEL_DATA: 1270 m = bwfm_sdio_newbuf(); 1271 if (m == NULL) 1272 break; 1273 if (flen - off > m->m_len) { 1274 printf("%s: frame bigger than anticipated\n", 1275 DEVNAME(sc)); 1276 m_freem(m); 1277 break; 1278 } 1279 m->m_len = m->m_pkthdr.len = flen - off; 1280 memcpy(mtod(m, char *), data + off, flen - off); 1281 sc->sc_sc.sc_proto_ops->proto_rx(&sc->sc_sc, m, &ml); 1282 nextlen = swhdr->nextlen << 4; 1283 break; 1284 case BWFM_SDIO_SWHDR_CHANNEL_GLOM: 1285 if ((flen % sizeof(uint16_t)) != 0) 1286 break; 1287 nsub = flen / sizeof(uint16_t); 1288 sublen = mallocarray(nsub, sizeof(uint16_t), 1289 M_DEVBUF, M_WAITOK | M_ZERO); 1290 memcpy(sublen, data, nsub * sizeof(uint16_t)); 1291 bwfm_sdio_rx_glom(sc, sublen, nsub, &nextlen, &ml); 1292 free(sublen, M_DEVBUF, nsub * sizeof(uint16_t)); 1293 break; 1294 default: 1295 printf("%s: unknown channel\n", DEVNAME(sc)); 1296 break; 1297 } 1298 } 1299 1300 if_input(ifp, &ml); 1301 } 1302 1303 void 1304 bwfm_sdio_rx_glom(struct bwfm_sdio_softc *sc, uint16_t *sublen, int nsub, 1305 uint16_t *nextlen, struct mbuf_list *ml) 1306 { 1307 struct bwfm_sdio_hwhdr hwhdr; 1308 struct bwfm_sdio_swhdr swhdr; 1309 struct mbuf_list glom, drop; 1310 struct mbuf *m; 1311 size_t flen; 1312 off_t off; 1313 int i; 1314 1315 ml_init(&glom); 1316 ml_init(&drop); 1317 1318 if (nsub == 0) 1319 return; 1320 1321 for (i = 0; i < nsub; i++) { 1322 m = bwfm_sdio_newbuf(); 1323 if (m == NULL) { 1324 ml_purge(&glom); 1325 return; 1326 } 1327 ml_enqueue(&glom, m); 1328 if (letoh16(sublen[i]) > m->m_len) { 1329 ml_purge(&glom); 1330 return; 1331 } 1332 if (bwfm_sdio_frame_read_write(sc, mtod(m, char *), 1333 letoh16(sublen[i]), 0)) { 1334 ml_purge(&glom); 1335 return; 1336 } 1337 m->m_len = m->m_pkthdr.len = letoh16(sublen[i]); 1338 } 1339 1340 /* TODO: Verify actual superframe header */ 1341 m = MBUF_LIST_FIRST(&glom); 1342 if (m->m_len >= sizeof(hwhdr) + sizeof(swhdr)) { 1343 m_copydata(m, 0, sizeof(hwhdr), (caddr_t)&hwhdr); 1344 m_copydata(m, sizeof(hwhdr), sizeof(swhdr), (caddr_t)&swhdr); 1345 *nextlen = swhdr.nextlen << 4; 1346 m_adj(m, sizeof(struct bwfm_sdio_hwhdr) + 1347 sizeof(struct bwfm_sdio_swhdr)); 1348 } 1349 1350 while ((m = ml_dequeue(&glom)) != NULL) { 1351 if (m->m_len < sizeof(hwhdr) + sizeof(swhdr)) 1352 goto drop; 1353 1354 m_copydata(m, 0, sizeof(hwhdr), (caddr_t)&hwhdr); 1355 m_copydata(m, sizeof(hwhdr), sizeof(swhdr), (caddr_t)&swhdr); 1356 1357 hwhdr.frmlen = letoh16(hwhdr.frmlen); 1358 hwhdr.cksum = letoh16(hwhdr.cksum); 1359 1360 if (hwhdr.frmlen == 0 && hwhdr.cksum == 0) 1361 goto drop; 1362 1363 if ((hwhdr.frmlen ^ hwhdr.cksum) != 0xffff) { 1364 printf("%s: checksum error\n", DEVNAME(sc)); 1365 goto drop; 1366 } 1367 1368 if (hwhdr.frmlen < sizeof(hwhdr) + sizeof(swhdr)) { 1369 printf("%s: length error\n", DEVNAME(sc)); 1370 goto drop; 1371 } 1372 1373 flen = hwhdr.frmlen - (sizeof(hwhdr) + sizeof(swhdr)); 1374 if (flen == 0) 1375 goto drop; 1376 if (m->m_len < flen) 1377 goto drop; 1378 1379 if (swhdr.dataoff < (sizeof(hwhdr) + sizeof(swhdr))) 1380 goto drop; 1381 1382 off = swhdr.dataoff - (sizeof(hwhdr) + sizeof(swhdr)); 1383 if (off > flen) 1384 goto drop; 1385 1386 switch (swhdr.chanflag & BWFM_SDIO_SWHDR_CHANNEL_MASK) { 1387 case BWFM_SDIO_SWHDR_CHANNEL_CONTROL: 1388 printf("%s: control channel not allowed in glom\n", 1389 DEVNAME(sc)); 1390 goto drop; 1391 case BWFM_SDIO_SWHDR_CHANNEL_EVENT: 1392 case BWFM_SDIO_SWHDR_CHANNEL_DATA: 1393 m_adj(m, swhdr.dataoff); 1394 sc->sc_sc.sc_proto_ops->proto_rx(&sc->sc_sc, m, ml); 1395 break; 1396 case BWFM_SDIO_SWHDR_CHANNEL_GLOM: 1397 printf("%s: glom not allowed in glom\n", 1398 DEVNAME(sc)); 1399 goto drop; 1400 default: 1401 printf("%s: unknown channel\n", DEVNAME(sc)); 1402 goto drop; 1403 } 1404 1405 continue; 1406 drop: 1407 ml_enqueue(&drop, m); 1408 } 1409 1410 ml_purge(&drop); 1411 } 1412 1413 int 1414 bwfm_sdio_txcheck(struct bwfm_softc *bwfm) 1415 { 1416 struct bwfm_sdio_softc *sc = (void *)bwfm; 1417 1418 if (sc->sc_tx_count >= 64) 1419 return ENOBUFS; 1420 1421 return 0; 1422 } 1423 1424 int 1425 bwfm_sdio_txdata(struct bwfm_softc *bwfm, struct mbuf *m) 1426 { 1427 struct bwfm_sdio_softc *sc = (void *)bwfm; 1428 1429 if (sc->sc_tx_count >= 64) 1430 return ENOBUFS; 1431 1432 sc->sc_tx_count++; 1433 ml_enqueue(&sc->sc_tx_queue, m); 1434 task_add(systq, &sc->sc_task); 1435 return 0; 1436 } 1437 1438 int 1439 bwfm_sdio_txctl(struct bwfm_softc *bwfm, void *arg) 1440 { 1441 struct bwfm_sdio_softc *sc = (void *)bwfm; 1442 struct bwfm_proto_bcdc_ctl *ctl = arg; 1443 struct mbuf *m; 1444 1445 KASSERT(ctl->len <= MCLBYTES); 1446 1447 MGET(m, M_DONTWAIT, MT_CONTROL); 1448 if (m == NULL) 1449 goto fail; 1450 if (ctl->len > MLEN) { 1451 MCLGET(m, M_DONTWAIT); 1452 if (!(m->m_flags & M_EXT)) { 1453 m_freem(m); 1454 goto fail; 1455 } 1456 } 1457 memcpy(mtod(m, char *), ctl->buf, ctl->len); 1458 m->m_len = ctl->len; 1459 1460 TAILQ_INSERT_TAIL(&sc->sc_sc.sc_bcdc_rxctlq, ctl, next); 1461 ml_enqueue(&sc->sc_tx_queue, m); 1462 task_add(systq, &sc->sc_task); 1463 return 0; 1464 1465 fail: 1466 free(ctl->buf, M_TEMP, ctl->len); 1467 free(ctl, M_TEMP, sizeof(*ctl)); 1468 return 1; 1469 } 1470 1471 #ifdef BWFM_DEBUG 1472 void 1473 bwfm_sdio_debug_console(struct bwfm_sdio_softc *sc) 1474 { 1475 struct bwfm_sdio_console c; 1476 uint32_t newidx; 1477 int err; 1478 1479 if (!sc->sc_console_addr) 1480 return; 1481 1482 err = bwfm_sdio_ram_read_write(sc, sc->sc_console_addr, 1483 (char *)&c, sizeof(c), 0); 1484 if (err) 1485 return; 1486 1487 c.log_buf = letoh32(c.log_buf); 1488 c.log_bufsz = letoh32(c.log_bufsz); 1489 c.log_idx = letoh32(c.log_idx); 1490 1491 if (sc->sc_console_buf == NULL) { 1492 sc->sc_console_buf = malloc(c.log_bufsz, M_DEVBUF, 1493 M_WAITOK|M_ZERO); 1494 sc->sc_console_buf_size = c.log_bufsz; 1495 } 1496 1497 newidx = c.log_idx; 1498 if (newidx >= sc->sc_console_buf_size) 1499 return; 1500 1501 err = bwfm_sdio_ram_read_write(sc, c.log_buf, sc->sc_console_buf, 1502 sc->sc_console_buf_size, 0); 1503 if (err) 1504 return; 1505 1506 if (newidx != sc->sc_console_readidx) 1507 DPRINTFN(3, ("BWFM CONSOLE: ")); 1508 while (newidx != sc->sc_console_readidx) { 1509 uint8_t ch = sc->sc_console_buf[sc->sc_console_readidx]; 1510 sc->sc_console_readidx++; 1511 if (sc->sc_console_readidx == sc->sc_console_buf_size) 1512 sc->sc_console_readidx = 0; 1513 if (ch == '\r') 1514 continue; 1515 DPRINTFN(3, ("%c", ch)); 1516 } 1517 } 1518 #endif 1519