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