1 /* $NetBSD: if_bwfm_sdio.c,v 1.23 2020/07/22 17:23:12 riastradh Exp $ */ 2 /* $OpenBSD: if_bwfm_sdio.c,v 1.1 2017/10/11 17:19:50 patrick Exp $ */ 3 /* 4 * Copyright (c) 2010-2016 Broadcom Corporation 5 * Copyright (c) 2016,2017 Patrick Wildt <patrick@blueri.se> 6 * 7 * Permission to use, copy, modify, and/or distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #include <sys/param.h> 21 #include <sys/types.h> 22 23 #include <sys/buf.h> 24 #include <sys/device.h> 25 #include <sys/endian.h> 26 #include <sys/kernel.h> 27 #include <sys/kmem.h> 28 #include <sys/malloc.h> 29 #include <sys/mutex.h> 30 #include <sys/queue.h> 31 #include <sys/socket.h> 32 #include <sys/systm.h> 33 34 #include <net/bpf.h> 35 #include <net/if.h> 36 #include <net/if_dl.h> 37 #include <net/if_ether.h> 38 #include <net/if_media.h> 39 40 #include <netinet/in.h> 41 42 #include <net80211/ieee80211_var.h> 43 44 #include <dev/fdt/fdtvar.h> 45 #include <dev/ic/bwfmreg.h> 46 #include <dev/ic/bwfmvar.h> 47 #include <dev/ofw/openfirm.h> 48 #include <dev/sdmmc/if_bwfm_sdio.h> 49 #include <dev/sdmmc/sdmmcdevs.h> 50 #include <dev/sdmmc/sdmmcvar.h> 51 52 #ifdef BWFM_DEBUG 53 #define DPRINTF(x) do { if (bwfm_debug > 0) printf x; } while (0) 54 #define DPRINTFN(n, x) do { if (bwfm_debug >= (n)) printf x; } while (0) 55 static int bwfm_debug = 2; 56 #else 57 #define DPRINTF(x) do { ; } while (0) 58 #define DPRINTFN(n, x) do { ; } while (0) 59 #endif 60 61 #define DEVNAME(sc) device_xname((sc)->sc_sc.sc_dev) 62 63 enum bwfm_sdio_clkstate { 64 CLK_NONE, 65 CLK_SDONLY, 66 CLK_PENDING, 67 CLK_AVAIL 68 }; 69 70 struct bwfm_sdio_softc { 71 struct bwfm_softc sc_sc; 72 kmutex_t sc_lock; 73 74 bool sc_bwfm_attached; 75 76 struct sdmmc_function **sc_sf; 77 size_t sc_sf_size; 78 79 uint32_t sc_bar0; 80 enum bwfm_sdio_clkstate sc_clkstate; 81 bool sc_sr_enabled; 82 bool sc_alp_only; 83 bool sc_sleeping; 84 bool sc_rxskip; 85 86 struct sdmmc_task sc_task; 87 bool sc_task_queued; 88 89 uint8_t sc_tx_seq; 90 uint8_t sc_tx_max_seq; 91 int sc_tx_count; 92 MBUFQ_HEAD() sc_tx_queue; 93 94 struct mbuf *sc_rxctl_queue; 95 kcondvar_t sc_rxctl_cv; 96 97 void *sc_ih; 98 struct bwfm_core *sc_cc; 99 100 char *sc_bounce_buf; 101 size_t sc_bounce_size; 102 103 uint32_t sc_console_addr; 104 char *sc_console_buf; 105 size_t sc_console_buf_size; 106 uint32_t sc_console_readidx; 107 108 int sc_phandle; 109 void *sc_fdtih; 110 }; 111 112 static int bwfm_sdio_match(device_t, cfdata_t, void *); 113 static void bwfm_sdio_attach(device_t, device_t, void *); 114 static int bwfm_sdio_detach(device_t, int); 115 static void bwfm_sdio_attachhook(device_t); 116 static int bwfm_fdt_find_phandle(device_t, device_t); 117 static const char *bwfm_fdt_get_model(void); 118 119 static void bwfm_sdio_backplane(struct bwfm_sdio_softc *, uint32_t); 120 static uint8_t bwfm_sdio_read_1(struct bwfm_sdio_softc *, uint32_t); 121 static uint32_t bwfm_sdio_read_4(struct bwfm_sdio_softc *, uint32_t); 122 static void bwfm_sdio_write_1(struct bwfm_sdio_softc *, uint32_t, 123 uint8_t); 124 static void bwfm_sdio_write_4(struct bwfm_sdio_softc *, uint32_t, 125 uint32_t); 126 127 static uint32_t bwfm_sdio_dev_read(struct bwfm_sdio_softc *, uint32_t); 128 static void bwfm_sdio_dev_write(struct bwfm_sdio_softc *, uint32_t, 129 uint32_t); 130 131 static uint32_t bwfm_sdio_buscore_read(struct bwfm_softc *, uint32_t); 132 static void bwfm_sdio_buscore_write(struct bwfm_softc *, uint32_t, 133 uint32_t); 134 static int bwfm_sdio_buscore_prepare(struct bwfm_softc *); 135 static void bwfm_sdio_buscore_activate(struct bwfm_softc *, uint32_t); 136 137 static int bwfm_sdio_buf_read(struct bwfm_sdio_softc *, 138 struct sdmmc_function *, uint32_t, char *, size_t); 139 static int bwfm_sdio_buf_write(struct bwfm_sdio_softc *, 140 struct sdmmc_function *, uint32_t, char *, size_t); 141 142 static struct mbuf *bwfm_sdio_newbuf(void); 143 static void bwfm_qput(struct mbuf **, struct mbuf *); 144 static struct mbuf *bwfm_qget(struct mbuf **); 145 146 static uint32_t bwfm_sdio_ram_read_write(struct bwfm_sdio_softc *, 147 uint32_t, char *, size_t, int); 148 static uint32_t bwfm_sdio_frame_read_write(struct bwfm_sdio_softc *, 149 char *, size_t, int); 150 151 static int bwfm_sdio_intr1(void *, const char *); 152 static int bwfm_sdio_intr(void *); 153 static void bwfm_sdio_task(void *); 154 static void bwfm_sdio_task1(struct bwfm_sdio_softc *); 155 156 static int bwfm_nvram_convert(u_char *, size_t, size_t *); 157 static int bwfm_sdio_load_microcode(struct bwfm_sdio_softc *, 158 u_char *, size_t, u_char *, size_t); 159 static void bwfm_sdio_clkctl(struct bwfm_sdio_softc *, 160 enum bwfm_sdio_clkstate, bool); 161 static void bwfm_sdio_htclk(struct bwfm_sdio_softc *, bool, bool); 162 163 #ifdef notyet 164 static int bwfm_sdio_bus_sleep(struct bwfm_sdio_softc *, bool, bool); 165 #endif 166 static void bwfm_sdio_drivestrength(struct bwfm_sdio_softc *, unsigned); 167 static void bwfm_sdio_readshared(struct bwfm_sdio_softc *); 168 169 static int bwfm_sdio_txcheck(struct bwfm_softc *); 170 static int bwfm_sdio_txdata(struct bwfm_softc *, struct mbuf **); 171 static int bwfm_sdio_txctl(struct bwfm_softc *, char *, size_t); 172 static int bwfm_sdio_rxctl(struct bwfm_softc *, char *, size_t *); 173 174 static int bwfm_sdio_tx_ok(struct bwfm_sdio_softc *); 175 static void bwfm_sdio_tx_frames(struct bwfm_sdio_softc *); 176 static void bwfm_sdio_tx_ctrlframe(struct bwfm_sdio_softc *, 177 struct mbuf *); 178 static void bwfm_sdio_tx_dataframe(struct bwfm_sdio_softc *, 179 struct mbuf *); 180 181 static void bwfm_sdio_rx_frames(struct bwfm_sdio_softc *); 182 static void bwfm_sdio_rx_glom(struct bwfm_sdio_softc *, 183 uint16_t *, int, uint16_t *); 184 185 #ifdef BWFM_DEBUG 186 static void bwfm_sdio_debug_console(struct bwfm_sdio_softc *); 187 #endif 188 189 static const struct bwfm_firmware_selector bwfm_sdio_fwtab[] = { 190 BWFM_FW_ENTRY(BRCM_CC_43143_CHIP_ID, 191 BWFM_FWSEL_ALLREVS, "brcmfmac43143-sdio"), 192 193 BWFM_FW_ENTRY(BRCM_CC_43241_CHIP_ID, 194 BWFM_FWSEL_REV_LE(4), "brcmfmac43241b0-sdio"), 195 BWFM_FW_ENTRY(BRCM_CC_43241_CHIP_ID, 196 BWFM_FWSEL_REV_EQ(5), "brcmfmac43241b4-sdio"), 197 BWFM_FW_ENTRY(BRCM_CC_43241_CHIP_ID, 198 BWFM_FWSEL_REV_GE(6), "brcmfmac43241b5-sdio"), 199 200 BWFM_FW_ENTRY(BRCM_CC_4329_CHIP_ID, 201 BWFM_FWSEL_ALLREVS, "brcmfmac4329-sdio"), 202 203 BWFM_FW_ENTRY(BRCM_CC_4330_CHIP_ID, 204 BWFM_FWSEL_ALLREVS, "brcmfmac4330-sdio"), 205 206 BWFM_FW_ENTRY(BRCM_CC_4334_CHIP_ID, 207 BWFM_FWSEL_ALLREVS, "brcmfmac4334-sdio"), 208 209 BWFM_FW_ENTRY(BRCM_CC_43340_CHIP_ID, 210 BWFM_FWSEL_ALLREVS, "brcmfmac43340-sdio"), 211 BWFM_FW_ENTRY(BRCM_CC_43341_CHIP_ID, 212 BWFM_FWSEL_ALLREVS, "brcmfmac43340-sdio"), 213 214 BWFM_FW_ENTRY(BRCM_CC_4335_CHIP_ID, 215 BWFM_FWSEL_ALLREVS, "brcmfmac4335-sdio"), 216 217 BWFM_FW_ENTRY(BRCM_CC_43362_CHIP_ID, 218 BWFM_FWSEL_REV_GE(1), "brcmfmac43362-sdio"), 219 220 BWFM_FW_ENTRY(BRCM_CC_4339_CHIP_ID, 221 BWFM_FWSEL_ALLREVS, "brcmfmac4339-sdio"), 222 223 BWFM_FW_ENTRY(BRCM_CC_43430_CHIP_ID, 224 BWFM_FWSEL_REV_EQ(0), "brcmfmac43430a0-sdio"), 225 BWFM_FW_ENTRY(BRCM_CC_43430_CHIP_ID, 226 BWFM_FWSEL_REV_GE(1), "brcmfmac43430-sdio"), 227 228 BWFM_FW_ENTRY(BRCM_CC_4345_CHIP_ID, 229 BWFM_FWSEL_REV_EQ(9), "brcmfmac43456-sdio"), 230 BWFM_FW_ENTRY(BRCM_CC_4345_CHIP_ID, 231 BWFM_FWSEL_REV_LE(8) + BWFM_FWSEL_REV_GE(10), 232 "brcmfmac43455-sdio"), 233 234 BWFM_FW_ENTRY(BRCM_CC_4354_CHIP_ID, 235 BWFM_FWSEL_ALLREVS, "brcmfmac4354-sdio"), 236 237 BWFM_FW_ENTRY(BRCM_CC_4356_CHIP_ID, 238 BWFM_FWSEL_ALLREVS, "brcmfmac4356-sdio"), 239 240 BWFM_FW_ENTRY(CY_CC_4373_CHIP_ID, 241 BWFM_FWSEL_ALLREVS, "brcmfmac4373-sdio"), 242 243 BWFM_FW_ENTRY(CY_CC_43012_CHIP_ID, 244 BWFM_FWSEL_ALLREVS, "brcmfmac43012-sdio"), 245 246 BWFM_FW_ENTRY_END 247 }; 248 249 static const struct bwfm_bus_ops bwfm_sdio_bus_ops = { 250 .bs_init = NULL, 251 .bs_stop = NULL, 252 .bs_txcheck = bwfm_sdio_txcheck, 253 .bs_txdata = bwfm_sdio_txdata, 254 .bs_txctl = bwfm_sdio_txctl, 255 .bs_rxctl = bwfm_sdio_rxctl, 256 }; 257 258 static const struct bwfm_buscore_ops bwfm_sdio_buscore_ops = { 259 .bc_read = bwfm_sdio_buscore_read, 260 .bc_write = bwfm_sdio_buscore_write, 261 .bc_prepare = bwfm_sdio_buscore_prepare, 262 .bc_reset = NULL, 263 .bc_setup = NULL, 264 .bc_activate = bwfm_sdio_buscore_activate, 265 }; 266 267 CFATTACH_DECL_NEW(bwfm_sdio, sizeof(struct bwfm_sdio_softc), 268 bwfm_sdio_match, bwfm_sdio_attach, bwfm_sdio_detach, NULL); 269 270 static const struct bwfm_sdio_product { 271 uint32_t manufacturer; 272 uint32_t product; 273 const char *cisinfo[4]; 274 } bwfm_sdio_products[] = { 275 { 276 SDMMC_VENDOR_BROADCOM, 277 SDMMC_PRODUCT_BROADCOM_BCM4330, 278 SDMMC_CIS_BROADCOM_BCM4330 279 }, 280 { 281 SDMMC_VENDOR_BROADCOM, 282 SDMMC_PRODUCT_BROADCOM_BCM4334, 283 SDMMC_CIS_BROADCOM_BCM4334 284 }, 285 { 286 SDMMC_VENDOR_BROADCOM, 287 SDMMC_PRODUCT_BROADCOM_BCM43143, 288 SDMMC_CIS_BROADCOM_BCM43143 289 }, 290 { 291 SDMMC_VENDOR_BROADCOM, 292 SDMMC_PRODUCT_BROADCOM_BCM43430, 293 SDMMC_CIS_BROADCOM_BCM43430 294 }, 295 { 296 SDMMC_VENDOR_BROADCOM, 297 SDMMC_PRODUCT_BROADCOM_BCM43455, 298 SDMMC_CIS_BROADCOM_BCM43455 299 }, 300 { 301 SDMMC_VENDOR_BROADCOM, 302 SDMMC_PRODUCT_BROADCOM_BCM43362, 303 SDMMC_CIS_BROADCOM_BCM43362 304 }, 305 }; 306 307 static const char * const compatible[] = { 308 "brcm,bcm4329-fmac", 309 NULL 310 }; 311 312 static int 313 bwfm_sdio_match(device_t parent, cfdata_t match, void *aux) 314 { 315 struct sdmmc_attach_args *saa = aux; 316 struct sdmmc_function *sf = saa->sf; 317 struct sdmmc_cis *cis; 318 const struct bwfm_sdio_product *bsp; 319 int i; 320 321 /* Not SDIO. */ 322 if (sf == NULL) 323 return 0; 324 325 cis = &sf->sc->sc_fn0->cis; 326 for (i = 0; i < __arraycount(bwfm_sdio_products); ++i) { 327 bsp = &bwfm_sdio_products[i]; 328 if (cis->manufacturer == bsp->manufacturer && 329 cis->product == bsp->product) 330 break; 331 } 332 if (i >= __arraycount(bwfm_sdio_products)) 333 return 0; 334 335 /* We need both functions, but ... */ 336 if (sf->sc->sc_function_count <= 1) 337 return 0; 338 339 /* ... only attach for one. */ 340 if (sf->number != 1) 341 return 0; 342 343 return 1; 344 } 345 346 static void 347 bwfm_sdio_attach(device_t parent, device_t self, void *aux) 348 { 349 struct bwfm_sdio_softc *sc = device_private(self); 350 struct sdmmc_attach_args *saa = aux; 351 struct sdmmc_function *sf = saa->sf; 352 struct bwfm_core *core; 353 uint32_t reg; 354 355 sc->sc_sc.sc_dev = self; 356 357 aprint_naive("\n"); 358 aprint_normal("\n"); 359 360 sc->sc_phandle = bwfm_fdt_find_phandle(self, parent); 361 362 mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE); 363 cv_init(&sc->sc_rxctl_cv, "bwfmctl"); 364 365 sdmmc_init_task(&sc->sc_task, bwfm_sdio_task, sc); 366 367 sc->sc_bounce_size = 64 * 1024; 368 sc->sc_bounce_buf = kmem_alloc(sc->sc_bounce_size, KM_SLEEP); 369 sc->sc_tx_seq = 0xff; 370 MBUFQ_INIT(&sc->sc_tx_queue); 371 sc->sc_rxctl_queue = NULL; 372 373 sc->sc_sf_size = (sf->sc->sc_function_count + 1) 374 * sizeof(struct sdmmc_function *); 375 sc->sc_sf = kmem_zalloc(sc->sc_sf_size, KM_SLEEP); 376 377 /* Copy all function pointers. */ 378 SIMPLEQ_FOREACH(sf, &saa->sf->sc->sf_head, sf_list) { 379 sc->sc_sf[sf->number] = sf; 380 } 381 382 sdmmc_io_set_blocklen(sc->sc_sf[1], 64); 383 sdmmc_io_set_blocklen(sc->sc_sf[2], 512); 384 385 /* Enable Function 1. */ 386 if (sdmmc_io_function_enable(sc->sc_sf[1]) != 0) { 387 printf("%s: cannot enable function 1\n", DEVNAME(sc)); 388 return; 389 } 390 391 DPRINTF(("%s: F1 signature read @0x18000000=%x\n", DEVNAME(sc), 392 bwfm_sdio_read_4(sc, 0x18000000))); 393 394 /* Force PLL off */ 395 bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR, 396 BWFM_SDIO_FUNC1_CHIPCLKCSR_FORCE_HW_CLKREQ_OFF | 397 BWFM_SDIO_FUNC1_CHIPCLKCSR_ALP_AVAIL_REQ); 398 399 sc->sc_sc.sc_buscore_ops = &bwfm_sdio_buscore_ops; 400 if (bwfm_chip_attach(&sc->sc_sc) != 0) { 401 aprint_error_dev(self, "cannot attach chip\n"); 402 return; 403 } 404 405 sc->sc_cc = bwfm_chip_get_core(&sc->sc_sc, BWFM_AGENT_CORE_CHIPCOMMON); 406 if (sc->sc_cc == NULL) { 407 aprint_error_dev(self, "cannot find chipcommon core\n"); 408 return; 409 } 410 411 core = bwfm_chip_get_core(&sc->sc_sc, BWFM_AGENT_CORE_SDIO_DEV); 412 if (core->co_rev >= 12) { 413 reg = bwfm_sdio_read_1(sc, BWFM_SDIO_FUNC1_SLEEPCSR); 414 if ((reg & BWFM_SDIO_FUNC1_SLEEPCSR_KSO) == 0) { 415 reg |= BWFM_SDIO_FUNC1_SLEEPCSR_KSO; 416 bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_SLEEPCSR, reg); 417 } 418 } 419 420 /* Default, override from "brcm,drive-strength" */ 421 bwfm_sdio_drivestrength(sc, 6); 422 423 bwfm_sdio_write_1(sc, BWFM_SDIO_CCCR_CARDCTRL, 424 bwfm_sdio_read_1(sc, BWFM_SDIO_CCCR_CARDCTRL) | 425 BWFM_SDIO_CCCR_CARDCTRL_WLANRESET); 426 427 core = bwfm_chip_get_pmu(&sc->sc_sc); 428 bwfm_sdio_write_4(sc, core->co_base + BWFM_CHIP_REG_PMUCONTROL, 429 bwfm_sdio_read_4(sc, core->co_base + BWFM_CHIP_REG_PMUCONTROL) | 430 (BWFM_CHIP_REG_PMUCONTROL_RES_RELOAD << 431 BWFM_CHIP_REG_PMUCONTROL_RES_SHIFT)); 432 433 sdmmc_io_function_disable(sc->sc_sf[2]); 434 435 bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR, 0); 436 sc->sc_clkstate = CLK_SDONLY; 437 438 config_mountroot(self, bwfm_sdio_attachhook); 439 } 440 441 static void 442 bwfm_sdio_attachhook(device_t self) 443 { 444 struct bwfm_sdio_softc *sc = device_private(self); 445 struct bwfm_softc *bwfm = &sc->sc_sc; 446 struct bwfm_firmware_context fwctx; 447 size_t ucsize = 0, nvlen = 0, nvsize = 0; 448 uint8_t *ucode, *nvram; 449 uint32_t reg, clk; 450 451 DPRINTF(("%s: chip 0x%08x rev %u\n", DEVNAME(sc), 452 bwfm->sc_chip.ch_chip, bwfm->sc_chip.ch_chiprev)); 453 454 /* 455 * 4335s >= rev 2 are considered 4339s. 456 */ 457 if (bwfm->sc_chip.ch_chip == BRCM_CC_4335_CHIP_ID && 458 bwfm->sc_chip.ch_chiprev >= 2) 459 bwfm->sc_chip.ch_chip = BRCM_CC_4339_CHIP_ID; 460 461 bwfm_firmware_context_init(&fwctx, 462 bwfm->sc_chip.ch_chip, bwfm->sc_chip.ch_chiprev, 463 bwfm_fdt_get_model(), 464 BWFM_FWREQ(BWFM_FILETYPE_UCODE) | BWFM_FWREQ(BWFM_FILETYPE_NVRAM)); 465 466 if (!bwfm_firmware_open(bwfm, bwfm_sdio_fwtab, &fwctx)) { 467 /* Error message already displayed. */ 468 goto err; 469 } 470 471 ucode = bwfm_firmware_data(&fwctx, BWFM_FILETYPE_UCODE, &ucsize); 472 KASSERT(ucode != NULL); 473 nvram = bwfm_firmware_data(&fwctx, BWFM_FILETYPE_NVRAM, &nvlen); 474 KASSERT(nvram != NULL); 475 476 if (bwfm_nvram_convert(nvram, nvlen, &nvsize)) { 477 aprint_error_dev(bwfm->sc_dev, 478 "unable to convert %s file\n", 479 bwfm_firmware_description(BWFM_FILETYPE_NVRAM)); 480 goto err; 481 } 482 483 sc->sc_alp_only = true; 484 if (bwfm_sdio_load_microcode(sc, ucode, ucsize, nvram, nvsize) != 0) { 485 aprint_error_dev(bwfm->sc_dev, "could not load microcode\n"); 486 goto err; 487 } 488 sc->sc_alp_only = false; 489 490 sdmmc_pause(hztoms(1)*1000, NULL); 491 492 bwfm_sdio_clkctl(sc, CLK_AVAIL, false); 493 if (sc->sc_clkstate != CLK_AVAIL) { 494 aprint_error_dev(bwfm->sc_dev, "could not access clock\n"); 495 goto err; 496 } 497 498 clk = bwfm_sdio_read_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR); 499 bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR, 500 clk | BWFM_SDIO_FUNC1_CHIPCLKCSR_FORCE_HT); 501 502 bwfm_sdio_dev_write(sc, SDPCMD_TOSBMAILBOXDATA, 503 SDPCM_PROT_VERSION << SDPCM_PROT_VERSION_SHIFT); 504 if (sdmmc_io_function_enable(sc->sc_sf[2])) { 505 aprint_error_dev(bwfm->sc_dev, "cannot enable function 2\n"); 506 goto err; 507 } 508 509 bwfm_sdio_dev_write(sc, SDPCMD_HOSTINTMASK, 510 SDPCMD_INTSTATUS_HMB_SW_MASK | SDPCMD_INTSTATUS_CHIPACTIVE); 511 bwfm_sdio_write_1(sc, BWFM_SDIO_WATERMARK, 8); 512 513 if (bwfm_chip_sr_capable(bwfm)) { 514 reg = bwfm_sdio_read_1(sc, BWFM_SDIO_FUNC1_WAKEUPCTRL); 515 reg |= BWFM_SDIO_FUNC1_WAKEUPCTRL_HTWAIT; 516 bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_WAKEUPCTRL, reg); 517 bwfm_sdio_write_1(sc, BWFM_SDIO_CCCR_CARDCAP, 518 BWFM_SDIO_CCCR_CARDCAP_CMD14_SUPPORT | 519 BWFM_SDIO_CCCR_CARDCAP_CMD14_EXT); 520 bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR, 521 BWFM_SDIO_FUNC1_CHIPCLKCSR_FORCE_HT); 522 sc->sc_sr_enabled = 1; 523 } else { 524 bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR, clk); 525 } 526 527 #ifdef notyet 528 if (sc->sc_phandle >= 0) { 529 sc->sc_fdtih = fdtbus_intr_establish(sc->sc_phandle, 530 0, IPL_SDMMC, IST_LEVEL, bwfm_sdio_intr, sc); 531 } 532 #endif 533 if (sc->sc_fdtih != NULL) { 534 aprint_normal_dev(self, "enabling GPIO interrupt\n"); 535 } else { 536 sc->sc_ih = sdmmc_intr_establish(device_parent(self), 537 bwfm_sdio_intr, sc, DEVNAME(sc)); 538 } 539 540 if (sc->sc_ih == NULL && sc->sc_fdtih == NULL) { 541 aprint_error_dev(self, "could not establish interrupt\n"); 542 bwfm_sdio_clkctl(sc, CLK_NONE, false); 543 return; 544 } 545 sdmmc_intr_enable(sc->sc_sf[1]); 546 547 sdmmc_pause(100000, NULL); 548 549 sc->sc_sc.sc_bus_ops = &bwfm_sdio_bus_ops; 550 sc->sc_sc.sc_proto_ops = &bwfm_proto_bcdc_ops; 551 bwfm_attach(&sc->sc_sc); 552 sc->sc_bwfm_attached = true; 553 554 err: 555 bwfm_firmware_close(&fwctx); 556 } 557 558 static int 559 bwfm_fdt_find_phandle(device_t self, device_t parent) 560 { 561 prop_dictionary_t dict; 562 device_t dev; 563 const char *str; 564 int phandle; 565 566 /* locate in FDT */ 567 dict = device_properties(self); 568 if (prop_dictionary_get_cstring_nocopy(dict, "fdt-path", &str)) { 569 /* search in FDT */ 570 phandle = OF_finddevice(str); 571 } else { 572 573 /* parent parent is sdhc controller */ 574 dev = device_parent(parent); 575 if (dev == NULL) 576 return -1; 577 /* locate in FDT */ 578 dict = device_properties(dev); 579 if (!prop_dictionary_get_cstring_nocopy(dict, "fdt-path", &str)) 580 return -1; 581 582 /* are we the only FDT child ? */ 583 phandle = OF_child(OF_finddevice(str)); 584 } 585 586 if (!of_match_compatible(phandle, compatible)) 587 return -1; 588 589 return phandle; 590 } 591 592 static const char * 593 bwfm_fdt_get_model(void) 594 { 595 int phandle; 596 597 phandle = OF_finddevice("/"); 598 return fdtbus_get_string_index(phandle, "compatible", 0); 599 } 600 601 static int 602 bwfm_sdio_detach(device_t self, int flags) 603 { 604 struct bwfm_sdio_softc *sc = (struct bwfm_sdio_softc *)self; 605 606 #ifdef BWFM_DEBUG 607 bwfm_sdio_debug_console(sc); 608 #endif 609 610 if (sc->sc_ih || sc->sc_fdtih) { 611 sdmmc_intr_disable(sc->sc_sf[1]); 612 if (sc->sc_ih) 613 sdmmc_intr_disestablish(sc->sc_ih); 614 if (sc->sc_fdtih) 615 fdtbus_intr_disestablish(sc->sc_phandle, sc->sc_fdtih); 616 } 617 if (sc->sc_bwfm_attached) 618 bwfm_detach(&sc->sc_sc, flags); 619 620 sdmmc_del_task(sc->sc_sf[1]->sc, &sc->sc_task, NULL); 621 622 kmem_free(sc->sc_sf, sc->sc_sf_size); 623 kmem_free(sc->sc_bounce_buf, sc->sc_bounce_size); 624 625 cv_destroy(&sc->sc_rxctl_cv); 626 mutex_destroy(&sc->sc_lock); 627 628 return 0; 629 } 630 631 static void 632 bwfm_sdio_backplane(struct bwfm_sdio_softc *sc, uint32_t addr) 633 { 634 uint32_t bar0 = addr & ~BWFM_SDIO_SB_OFT_ADDR_MASK; 635 636 if (sc->sc_bar0 == bar0) 637 return; 638 639 bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_SBADDRLOW, 640 (bar0 >> 8) & 0xff); 641 bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_SBADDRMID, 642 (bar0 >> 16) & 0xff); 643 bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_SBADDRHIGH, 644 (bar0 >> 24) & 0xff); 645 sc->sc_bar0 = bar0; 646 } 647 648 static uint8_t 649 bwfm_sdio_read_1(struct bwfm_sdio_softc *sc, uint32_t addr) 650 { 651 struct sdmmc_function *sf; 652 uint8_t rv; 653 654 /* 655 * figure out how to read the register based on address range 656 * 0x00 ~ 0x7FF: function 0 CCCR and FBR 657 * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers 658 * The rest: function 1 silicon backplane core registers 659 */ 660 if ((addr & ~0x7ff) == 0) 661 sf = sc->sc_sf[0]; 662 else 663 sf = sc->sc_sf[1]; 664 665 rv = sdmmc_io_read_1(sf, addr); 666 return rv; 667 } 668 669 static uint32_t 670 bwfm_sdio_read_4(struct bwfm_sdio_softc *sc, uint32_t addr) 671 { 672 struct sdmmc_function *sf; 673 uint32_t rv; 674 675 bwfm_sdio_backplane(sc, addr); 676 677 addr &= BWFM_SDIO_SB_OFT_ADDR_MASK; 678 addr |= BWFM_SDIO_SB_ACCESS_2_4B_FLAG; 679 680 /* 681 * figure out how to read the register based on address range 682 * 0x00 ~ 0x7FF: function 0 CCCR and FBR 683 * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers 684 * The rest: function 1 silicon backplane core registers 685 */ 686 if ((addr & ~0x7ff) == 0) 687 sf = sc->sc_sf[0]; 688 else 689 sf = sc->sc_sf[1]; 690 691 rv = sdmmc_io_read_4(sf, addr); 692 return htole32(rv); 693 } 694 695 static void 696 bwfm_sdio_write_1(struct bwfm_sdio_softc *sc, uint32_t addr, uint8_t data) 697 { 698 struct sdmmc_function *sf; 699 700 /* 701 * figure out how to read the register based on address range 702 * 0x00 ~ 0x7FF: function 0 CCCR and FBR 703 * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers 704 * The rest: function 1 silicon backplane core registers 705 */ 706 if ((addr & ~0x7ff) == 0) 707 sf = sc->sc_sf[0]; 708 else 709 sf = sc->sc_sf[1]; 710 711 sdmmc_io_write_1(sf, addr, data); 712 } 713 714 static void 715 bwfm_sdio_write_4(struct bwfm_sdio_softc *sc, uint32_t addr, uint32_t data) 716 { 717 struct sdmmc_function *sf; 718 719 bwfm_sdio_backplane(sc, addr); 720 721 addr &= BWFM_SDIO_SB_OFT_ADDR_MASK; 722 addr |= BWFM_SDIO_SB_ACCESS_2_4B_FLAG; 723 724 /* 725 * figure out how to read the register based on address range 726 * 0x00 ~ 0x7FF: function 0 CCCR and FBR 727 * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers 728 * The rest: function 1 silicon backplane core registers 729 */ 730 if ((addr & ~0x7ff) == 0) 731 sf = sc->sc_sf[0]; 732 else 733 sf = sc->sc_sf[1]; 734 735 sdmmc_io_write_4(sf, addr, htole32(data)); 736 } 737 738 static int 739 bwfm_sdio_buf_read(struct bwfm_sdio_softc *sc, struct sdmmc_function *sf, 740 uint32_t reg, char *data, size_t size) 741 { 742 int err; 743 744 KASSERT(((vaddr_t)data & 0x3) == 0); 745 KASSERT((size & 0x3) == 0); 746 747 if (sf == sc->sc_sf[1]) 748 err = sdmmc_io_read_region_1(sf, reg, data, size); 749 else 750 err = sdmmc_io_read_multi_1(sf, reg, data, size); 751 752 if (err) 753 printf("%s: error %d\n", __func__, err); 754 755 return err; 756 } 757 758 static int 759 bwfm_sdio_buf_write(struct bwfm_sdio_softc *sc, struct sdmmc_function *sf, 760 uint32_t reg, char *data, size_t size) 761 { 762 int err; 763 764 KASSERT(((vaddr_t)data & 0x3) == 0); 765 KASSERT((size & 0x3) == 0); 766 767 err = sdmmc_io_write_region_1(sf, reg, data, size); 768 769 if (err) 770 printf("%s: error %d\n", __func__, err); 771 772 return err; 773 } 774 775 static uint32_t 776 bwfm_sdio_ram_read_write(struct bwfm_sdio_softc *sc, uint32_t reg, 777 char *data, size_t left, int write) 778 { 779 uint32_t sbaddr, sdaddr, off; 780 size_t size; 781 int err; 782 783 err = off = 0; 784 while (left > 0) { 785 sbaddr = reg + off; 786 bwfm_sdio_backplane(sc, sbaddr); 787 788 sdaddr = sbaddr & BWFM_SDIO_SB_OFT_ADDR_MASK; 789 size = ulmin(left, (BWFM_SDIO_SB_OFT_ADDR_PAGE - sdaddr)); 790 sdaddr |= BWFM_SDIO_SB_ACCESS_2_4B_FLAG; 791 792 if (write) { 793 memcpy(sc->sc_bounce_buf, data + off, size); 794 if (roundup(size, 4) != size) 795 memset(sc->sc_bounce_buf + size, 0, 796 roundup(size, 4) - size); 797 err = bwfm_sdio_buf_write(sc, sc->sc_sf[1], sdaddr, 798 sc->sc_bounce_buf, roundup(size, 4)); 799 } else { 800 err = bwfm_sdio_buf_read(sc, sc->sc_sf[1], sdaddr, 801 sc->sc_bounce_buf, roundup(size, 4)); 802 memcpy(data + off, sc->sc_bounce_buf, size); 803 } 804 if (err) 805 break; 806 807 off += size; 808 left -= size; 809 } 810 811 if (err) 812 printf("%s: error %d\n", __func__, err); 813 814 return err; 815 } 816 817 static uint32_t 818 bwfm_sdio_frame_read_write(struct bwfm_sdio_softc *sc, 819 char *data, size_t size, int write) 820 { 821 uint32_t addr; 822 int err; 823 824 addr = sc->sc_cc->co_base; 825 bwfm_sdio_backplane(sc, addr); 826 827 addr &= BWFM_SDIO_SB_OFT_ADDR_MASK; 828 addr |= BWFM_SDIO_SB_ACCESS_2_4B_FLAG; 829 830 if (write) 831 err = bwfm_sdio_buf_write(sc, sc->sc_sf[2], addr, data, size); 832 else 833 err = bwfm_sdio_buf_read(sc, sc->sc_sf[2], addr, data, size); 834 835 if (err) 836 printf("%s: error %d\n", __func__, err); 837 838 return err; 839 } 840 841 static uint32_t 842 bwfm_sdio_dev_read(struct bwfm_sdio_softc *sc, uint32_t reg) 843 { 844 struct bwfm_core *core; 845 uint32_t val; 846 847 core = bwfm_chip_get_core(&sc->sc_sc, BWFM_AGENT_CORE_SDIO_DEV); 848 val = bwfm_sdio_read_4(sc, core->co_base + reg); 849 /* TODO: Workaround for 4335/4339 */ 850 851 return val; 852 } 853 854 static void 855 bwfm_sdio_dev_write(struct bwfm_sdio_softc *sc, uint32_t reg, uint32_t val) 856 { 857 struct bwfm_core *core; 858 859 core = bwfm_chip_get_core(&sc->sc_sc, BWFM_AGENT_CORE_SDIO_DEV); 860 bwfm_sdio_write_4(sc, core->co_base + reg, val); 861 } 862 863 static uint32_t 864 bwfm_sdio_buscore_read(struct bwfm_softc *bwfm, uint32_t reg) 865 { 866 struct bwfm_sdio_softc *sc = (void *)bwfm; 867 uint32_t val; 868 869 mutex_enter(&sc->sc_lock); 870 val = bwfm_sdio_read_4(sc, reg); 871 /* TODO: Workaround for 4335/4339 */ 872 mutex_exit(&sc->sc_lock); 873 874 return val; 875 } 876 877 static void 878 bwfm_sdio_buscore_write(struct bwfm_softc *bwfm, uint32_t reg, uint32_t val) 879 { 880 struct bwfm_sdio_softc *sc = (void *)bwfm; 881 882 mutex_enter(&sc->sc_lock); 883 bwfm_sdio_write_4(sc, reg, val); 884 mutex_exit(&sc->sc_lock); 885 } 886 887 static int 888 bwfm_sdio_buscore_prepare(struct bwfm_softc *bwfm) 889 { 890 struct bwfm_sdio_softc *sc = (void *)bwfm; 891 uint8_t clkval, clkset, clkmask; 892 int i, error = 0; 893 894 mutex_enter(&sc->sc_lock); 895 896 clkset = BWFM_SDIO_FUNC1_CHIPCLKCSR_ALP_AVAIL_REQ | 897 BWFM_SDIO_FUNC1_CHIPCLKCSR_FORCE_HW_CLKREQ_OFF; 898 bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR, clkset); 899 900 clkmask = BWFM_SDIO_FUNC1_CHIPCLKCSR_ALP_AVAIL | 901 BWFM_SDIO_FUNC1_CHIPCLKCSR_HT_AVAIL; 902 clkval = bwfm_sdio_read_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR); 903 904 if ((clkval & ~clkmask) != clkset) { 905 printf("%s: wrote 0x%02x read 0x%02x\n", DEVNAME(sc), 906 clkset, clkval); 907 error = 1; 908 goto done; 909 } 910 911 for (i = 1000; i > 0; i--) { 912 clkval = bwfm_sdio_read_1(sc, 913 BWFM_SDIO_FUNC1_CHIPCLKCSR); 914 if (clkval & clkmask) 915 break; 916 } 917 if (i == 0) { 918 printf("%s: timeout on ALPAV wait, clkval 0x%02x\n", 919 DEVNAME(sc), clkval); 920 error = 1; 921 goto done; 922 } 923 924 clkset = BWFM_SDIO_FUNC1_CHIPCLKCSR_FORCE_HW_CLKREQ_OFF | 925 BWFM_SDIO_FUNC1_CHIPCLKCSR_FORCE_ALP; 926 bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR, clkset); 927 delay(65); 928 929 bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_SDIOPULLUP, 0); 930 931 done: 932 mutex_exit(&sc->sc_lock); 933 934 return error; 935 } 936 937 static void 938 bwfm_sdio_buscore_activate(struct bwfm_softc *bwfm, uint32_t rstvec) 939 { 940 struct bwfm_sdio_softc *sc = (void *)bwfm; 941 struct bwfm_core *core; 942 943 core = bwfm_chip_get_core(&sc->sc_sc, BWFM_AGENT_CORE_SDIO_DEV); 944 bwfm_sdio_buscore_write(&sc->sc_sc, 945 core->co_base + BWFM_SDPCMD_INTSTATUS, 0xFFFFFFFF); 946 947 mutex_enter(&sc->sc_lock); 948 if (rstvec) 949 bwfm_sdio_ram_read_write(sc, 0, (char *)&rstvec, 950 sizeof(rstvec), 1); 951 mutex_exit(&sc->sc_lock); 952 } 953 954 static struct mbuf * 955 bwfm_sdio_newbuf(void) 956 { 957 struct mbuf *m; 958 959 MGETHDR(m, M_DONTWAIT, MT_DATA); 960 if (m == NULL) 961 return NULL; 962 963 MCLGET(m, M_DONTWAIT); 964 if (!(m->m_flags & M_EXT)) { 965 m_freem(m); 966 return NULL; 967 } 968 969 m->m_len = m->m_pkthdr.len = MCLBYTES; 970 return m; 971 } 972 973 static struct mbuf * 974 bwfm_qget(struct mbuf **q) 975 { 976 struct mbuf *m = NULL; 977 978 if (*q != NULL) { 979 m = *q; 980 *q = m->m_next; 981 m->m_next = NULL; 982 } 983 984 return m; 985 } 986 987 static void 988 bwfm_qput(struct mbuf **q, struct mbuf *m) 989 { 990 991 if (*q == NULL) 992 *q = m; 993 else 994 m_cat(*q, m); 995 } 996 997 static int 998 bwfm_sdio_txcheck(struct bwfm_softc *bwfm) 999 { 1000 struct bwfm_sdio_softc *sc = (void *)bwfm; 1001 int error = 0; 1002 1003 mutex_enter(&sc->sc_lock); 1004 if (sc->sc_tx_count >= 64) 1005 error = ENOBUFS; 1006 mutex_exit(&sc->sc_lock); 1007 1008 return error; 1009 } 1010 1011 1012 static int 1013 bwfm_sdio_txdata(struct bwfm_softc *bwfm, struct mbuf **mp) 1014 { 1015 struct bwfm_sdio_softc *sc = (void *)bwfm; 1016 1017 if (sc->sc_tx_count >= 64) { 1018 printf("%s: tx count limit reached\n",DEVNAME(sc)); 1019 return ENOBUFS; 1020 } 1021 1022 mutex_enter(&sc->sc_lock); 1023 sc->sc_tx_count++; 1024 MBUFQ_ENQUEUE(&sc->sc_tx_queue, *mp); 1025 mutex_exit(&sc->sc_lock); 1026 1027 bwfm_sdio_intr1(sc, "sdio_txdata"); 1028 1029 return 0; 1030 } 1031 1032 static int 1033 bwfm_sdio_txctl(struct bwfm_softc *bwfm, char *buf, size_t len) 1034 { 1035 struct bwfm_sdio_softc *sc = (void *)bwfm; 1036 struct mbuf *m; 1037 1038 KASSERT(len <= MCLBYTES); 1039 1040 MGET(m, M_DONTWAIT, MT_CONTROL); 1041 if (m == NULL) 1042 goto fail; 1043 if (len > MLEN) { 1044 MCLGET(m, M_DONTWAIT); 1045 if (!(m->m_flags & M_EXT)) { 1046 m_freem(m); 1047 goto fail; 1048 } 1049 } 1050 memcpy(mtod(m, char *), buf, len); 1051 m->m_len = len; 1052 1053 mutex_enter(&sc->sc_lock); 1054 MBUFQ_ENQUEUE(&sc->sc_tx_queue, m); 1055 mutex_exit(&sc->sc_lock); 1056 1057 bwfm_sdio_intr1(sc, "sdio_txctl"); 1058 1059 return 0; 1060 1061 fail: 1062 return ENOBUFS; 1063 } 1064 1065 static int 1066 bwfm_nvram_convert(u_char *buf, size_t len, size_t *newlenp) 1067 { 1068 u_char *src, *dst, *end = buf + len; 1069 bool skip = false; 1070 size_t count = 0, pad; 1071 uint32_t token; 1072 1073 for (src = buf, dst = buf; src != end; ++src) { 1074 if (*src == '\n') { 1075 if (count > 0) 1076 *dst++ = '\0'; 1077 count = 0; 1078 skip = false; 1079 continue; 1080 } 1081 if (skip) 1082 continue; 1083 if (*src == '#' && count == 0) { 1084 skip = true; 1085 continue; 1086 } 1087 if (*src == '\r' || *src == ' ') 1088 continue; 1089 *dst++ = *src; 1090 ++count; 1091 } 1092 1093 count = dst - buf; 1094 pad = roundup(count + 1, 4) - count; 1095 1096 if (count + pad + sizeof(token) > len) 1097 return 1; 1098 1099 memset(dst, 0, pad); 1100 count += pad; 1101 dst += pad; 1102 1103 token = (count / 4) & 0xffff; 1104 token |= ~token << 16; 1105 token = htole32(token); 1106 1107 memcpy(dst, &token, sizeof(token)); 1108 count += sizeof(token); 1109 1110 *newlenp = count; 1111 1112 return 0; 1113 } 1114 1115 static int 1116 bwfm_sdio_load_microcode(struct bwfm_sdio_softc *sc, u_char *ucode, size_t size, 1117 u_char *nvram, size_t nvlen) 1118 { 1119 struct bwfm_softc *bwfm = &sc->sc_sc; 1120 char *verify = NULL; 1121 int err = 0; 1122 1123 bwfm_sdio_clkctl(sc, CLK_AVAIL, false); 1124 1125 DPRINTF(("ucode %zu bytes to 0x%08lx\n", size, 1126 (u_long)bwfm->sc_chip.ch_rambase)); 1127 /* Upload firmware */ 1128 err = bwfm_sdio_ram_read_write(sc, bwfm->sc_chip.ch_rambase, 1129 ucode, size, 1); 1130 if (err) 1131 goto out; 1132 1133 /* Verify firmware */ 1134 verify = kmem_zalloc(size, KM_SLEEP); 1135 err = bwfm_sdio_ram_read_write(sc, bwfm->sc_chip.ch_rambase, 1136 verify, size, 0); 1137 if (err || memcmp(verify, ucode, size)) { 1138 printf("%s: firmware verification failed\n", 1139 DEVNAME(sc)); 1140 kmem_free(verify, size); 1141 goto out; 1142 } 1143 kmem_free(verify, size); 1144 1145 DPRINTF(("nvram %zu bytes to 0x%08lx\n", nvlen, 1146 (u_long)bwfm->sc_chip.ch_rambase + bwfm->sc_chip.ch_ramsize 1147 - nvlen)); 1148 /* Upload nvram */ 1149 err = bwfm_sdio_ram_read_write(sc, bwfm->sc_chip.ch_rambase + 1150 bwfm->sc_chip.ch_ramsize - nvlen, nvram, nvlen, 1); 1151 if (err) 1152 goto out; 1153 1154 /* Verify nvram */ 1155 verify = kmem_zalloc(nvlen, KM_SLEEP); 1156 err = bwfm_sdio_ram_read_write(sc, bwfm->sc_chip.ch_rambase + 1157 bwfm->sc_chip.ch_ramsize - nvlen, verify, nvlen, 0); 1158 if (err || memcmp(verify, nvram, nvlen)) { 1159 printf("%s: nvram verification failed\n", 1160 DEVNAME(sc)); 1161 kmem_free(verify, nvlen); 1162 goto out; 1163 } 1164 kmem_free(verify, nvlen); 1165 1166 DPRINTF(("Reset core 0x%08x\n", *(uint32_t *)ucode)); 1167 /* Load reset vector from firmware and kickstart core. */ 1168 bwfm_chip_set_active(bwfm, *(uint32_t *)ucode); 1169 1170 out: 1171 bwfm_sdio_clkctl(sc, CLK_SDONLY, false); 1172 return err; 1173 } 1174 1175 static void 1176 bwfm_sdio_clkctl(struct bwfm_sdio_softc *sc, enum bwfm_sdio_clkstate newstate, 1177 bool pendok) 1178 { 1179 enum bwfm_sdio_clkstate oldstate; 1180 1181 oldstate = sc->sc_clkstate; 1182 if (oldstate == newstate) 1183 return; 1184 1185 switch (newstate) { 1186 case CLK_AVAIL: 1187 if (oldstate == CLK_NONE) 1188 sc->sc_clkstate = CLK_SDONLY; /* XXX */ 1189 bwfm_sdio_htclk(sc, true, pendok); 1190 break; 1191 case CLK_SDONLY: 1192 if (oldstate == CLK_NONE) 1193 sc->sc_clkstate = newstate; 1194 else if (oldstate == CLK_AVAIL) 1195 bwfm_sdio_htclk(sc, false, false); 1196 else 1197 printf("%s: clkctl %d -> %d\n", DEVNAME(sc), 1198 sc->sc_clkstate, newstate); 1199 break; 1200 case CLK_NONE: 1201 if (oldstate == CLK_AVAIL) 1202 bwfm_sdio_htclk(sc, false, false); 1203 sc->sc_clkstate = newstate; 1204 break; 1205 default: 1206 break; 1207 } 1208 1209 DPRINTF(("%s: %d -> %d = %d\n", DEVNAME(sc), oldstate, newstate, 1210 sc->sc_clkstate)); 1211 } 1212 1213 static void 1214 bwfm_sdio_htclk(struct bwfm_sdio_softc *sc, bool on, bool pendok) 1215 { 1216 uint32_t clkctl, devctl, req; 1217 int i; 1218 1219 if (sc->sc_sr_enabled) { 1220 if (on) 1221 sc->sc_clkstate = CLK_AVAIL; 1222 else 1223 sc->sc_clkstate = CLK_SDONLY; 1224 return; 1225 } 1226 1227 if (on) { 1228 if (sc->sc_alp_only) 1229 req = BWFM_SDIO_FUNC1_CHIPCLKCSR_ALP_AVAIL_REQ; 1230 else 1231 req = BWFM_SDIO_FUNC1_CHIPCLKCSR_HT_AVAIL_REQ; 1232 bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR, req); 1233 1234 clkctl = bwfm_sdio_read_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR); 1235 if (!BWFM_SDIO_FUNC1_CHIPCLKCSR_CLKAV(clkctl, sc->sc_alp_only) 1236 && pendok) { 1237 devctl = bwfm_sdio_read_1(sc, BWFM_SDIO_DEVICE_CTL); 1238 devctl |= BWFM_SDIO_DEVICE_CTL_CA_INT_ONLY; 1239 bwfm_sdio_write_1(sc, BWFM_SDIO_DEVICE_CTL, devctl); 1240 sc->sc_clkstate = CLK_PENDING; 1241 return; 1242 } else if (sc->sc_clkstate == CLK_PENDING) { 1243 devctl = bwfm_sdio_read_1(sc, BWFM_SDIO_DEVICE_CTL); 1244 devctl &= ~BWFM_SDIO_DEVICE_CTL_CA_INT_ONLY; 1245 bwfm_sdio_write_1(sc, BWFM_SDIO_DEVICE_CTL, devctl); 1246 } 1247 1248 for (i = 0; i < 50; i++) { 1249 if (BWFM_SDIO_FUNC1_CHIPCLKCSR_CLKAV(clkctl, 1250 sc->sc_alp_only)) 1251 break; 1252 clkctl = bwfm_sdio_read_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR 1253 ); 1254 sdmmc_pause(100000, NULL); 1255 } 1256 if (i >= 50) { 1257 printf("%s: HT avail timeout\n", DEVNAME(sc)); 1258 return; 1259 } 1260 1261 sc->sc_clkstate = CLK_AVAIL; 1262 } else { 1263 if (sc->sc_clkstate == CLK_PENDING) { 1264 devctl = bwfm_sdio_read_1(sc, BWFM_SDIO_DEVICE_CTL); 1265 devctl &= ~BWFM_SDIO_DEVICE_CTL_CA_INT_ONLY; 1266 bwfm_sdio_write_1(sc, BWFM_SDIO_DEVICE_CTL, devctl); 1267 } 1268 sc->sc_clkstate = CLK_SDONLY; 1269 bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR, 0); 1270 } 1271 } 1272 1273 struct bwfm_sdio_dstab { 1274 uint8_t milli; 1275 uint8_t val; 1276 }; 1277 1278 static struct bwfm_sdio_dstab pmu11_1v8[] = { 1279 {32, 0x6}, 1280 {26, 0x7}, 1281 {22, 0x4}, 1282 {16, 0x5}, 1283 {12, 0x2}, 1284 {8, 0x3}, 1285 {4, 0x0}, 1286 {0, 0x1} 1287 }, pmu13_1v8[] = { 1288 {6, 0x7}, 1289 {5, 0x6}, 1290 {4, 0x5}, 1291 {3, 0x4}, 1292 {2, 0x2}, 1293 {1, 0x1}, 1294 {0, 0x0} 1295 }, pmu17_1v8[] = { 1296 {3, 0x3}, 1297 {2, 0x2}, 1298 {1, 0x1}, 1299 {0, 0x0} 1300 }, pmu17_3v3[] = { 1301 {16, 0x7}, 1302 {12, 0x5}, 1303 {8, 0x3}, 1304 {4, 0x1}, 1305 {0, 0x0} 1306 }; 1307 1308 static void 1309 bwfm_sdio_drivestrength(struct bwfm_sdio_softc *sc, unsigned milli) 1310 { 1311 struct bwfm_softc *bwfm = &sc->sc_sc; 1312 struct bwfm_core *core; 1313 struct bwfm_sdio_dstab *tab; 1314 uint32_t tmp, mask; 1315 unsigned i; 1316 1317 if ((bwfm->sc_chip.ch_cc_caps & BWFM_CHIP_REG_CAPABILITIES_PMU) == 0) 1318 return; 1319 1320 switch (bwfm->sc_chip.ch_chip) { 1321 case BRCM_CC_4330_CHIP_ID: 1322 tab = pmu11_1v8; 1323 mask = __BITS(11,13); 1324 break; 1325 case BRCM_CC_4334_CHIP_ID: 1326 tab = pmu17_1v8; 1327 mask = __BITS(11,12); 1328 break; 1329 case BRCM_CC_43143_CHIP_ID: 1330 tab = pmu17_3v3; 1331 mask = __BITS(0,3); 1332 break; 1333 case BRCM_CC_43362_CHIP_ID: 1334 tab = pmu13_1v8; 1335 mask = __BITS(11,13); 1336 break; 1337 default: 1338 return; 1339 } 1340 1341 for (i=0; tab[i].milli != 0; ++i) { 1342 if (milli >= tab[i].milli) 1343 break; 1344 } 1345 if (tab[i].milli == 0) 1346 return; 1347 1348 core = bwfm_chip_get_pmu(&sc->sc_sc); 1349 tmp = bwfm_sdio_read_4(sc, core->co_base + BWFM_CHIP_REG_CHIPCONTROL_ADDR); 1350 tmp &= mask; 1351 tmp |= __SHIFTIN(tab[i].val, mask); 1352 bwfm_sdio_write_4(sc, core->co_base + BWFM_CHIP_REG_CHIPCONTROL_ADDR, tmp); 1353 } 1354 1355 1356 #if notyet 1357 static int 1358 bwfm_sdio_bus_sleep(struct bwfm_sdio_softc *sc, bool sleep, bool pendok) 1359 { 1360 uint32_t clkctl; 1361 1362 if (sc->sleeping == sleep) 1363 return 0; 1364 1365 if (sc->sc_sr_enabled) { 1366 if (sleep) { 1367 clkctl = bwfm_sdio_read_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR); 1368 if ((clkctl & BWFM_SDIO_FUNC1_CHIPCLKCSR_CSR_MASK) == 0) 1369 bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR, BWFM_SDIO_FUNC1_CHIPCLKCSR_ALP_AVAIL_REQ); 1370 } 1371 /* kso_ctrl(sc, sleep) */ 1372 } 1373 1374 if (sleep) { 1375 if (!sc->sc_sr_enabled) 1376 bwfm_sdio_clkctl(sc, CLK_NONE, pendok); 1377 } else { 1378 bwfm_sdio_clkctl(sc, CLK_AVAIL, pendok); 1379 } 1380 1381 sc->sleeping = sleep; 1382 1383 return 0; 1384 } 1385 #endif 1386 1387 static void 1388 bwfm_sdio_readshared(struct bwfm_sdio_softc *sc) 1389 { 1390 struct bwfm_softc *bwfm = &sc->sc_sc; 1391 struct bwfm_sdio_sdpcm sdpcm; 1392 uint32_t addr, shaddr; 1393 int err; 1394 1395 bwfm_sdio_clkctl(sc, CLK_AVAIL, false); 1396 if (sc->sc_clkstate != CLK_AVAIL) 1397 return; 1398 1399 shaddr = bwfm->sc_chip.ch_rambase + bwfm->sc_chip.ch_ramsize - 4; 1400 if (!bwfm->sc_chip.ch_rambase && sc->sc_sr_enabled) 1401 shaddr -= bwfm->sc_chip.ch_srsize; 1402 1403 err = bwfm_sdio_ram_read_write(sc, shaddr, (char *)&addr, 1404 sizeof(addr), 0); 1405 if (err) 1406 return; 1407 1408 addr = le32toh(addr); 1409 if (addr == 0 || ((~addr >> 16) & 0xffff) == (addr & 0xffff)) 1410 return; 1411 1412 err = bwfm_sdio_ram_read_write(sc, addr, (char *)&sdpcm, 1413 sizeof(sdpcm), 0); 1414 if (err) 1415 return; 1416 1417 sc->sc_console_addr = le32toh(sdpcm.console_addr); 1418 } 1419 1420 static int 1421 bwfm_sdio_intr1(void *v, const char *name) 1422 { 1423 struct bwfm_sdio_softc *sc = (void *)v; 1424 1425 DPRINTF(("%s: %s\n", DEVNAME(sc), name)); 1426 1427 sdmmc_add_task(sc->sc_sf[1]->sc, &sc->sc_task); 1428 return 1; 1429 } 1430 1431 static int 1432 bwfm_sdio_intr(void *v) 1433 { 1434 return bwfm_sdio_intr1(v, "sdio_intr"); 1435 } 1436 1437 static void 1438 bwfm_sdio_task(void *v) 1439 { 1440 struct bwfm_sdio_softc *sc = (void *)v; 1441 1442 mutex_enter(&sc->sc_lock); 1443 bwfm_sdio_task1(sc); 1444 #ifdef BWFM_DEBUG 1445 bwfm_sdio_debug_console(sc); 1446 #endif 1447 mutex_exit(&sc->sc_lock); 1448 } 1449 1450 static void 1451 bwfm_sdio_task1(struct bwfm_sdio_softc *sc) 1452 { 1453 uint32_t clkctl, devctl, intstat, hostint; 1454 bool dorecv, dosend; 1455 1456 if (!sc->sc_sr_enabled && sc->sc_clkstate == CLK_PENDING) { 1457 clkctl = bwfm_sdio_read_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR); 1458 if (BWFM_SDIO_FUNC1_CHIPCLKCSR_HTAV(clkctl)) { 1459 devctl = bwfm_sdio_read_1(sc, BWFM_SDIO_DEVICE_CTL); 1460 devctl &= ~BWFM_SDIO_DEVICE_CTL_CA_INT_ONLY; 1461 bwfm_sdio_write_1(sc, BWFM_SDIO_DEVICE_CTL, devctl); 1462 sc->sc_clkstate = CLK_AVAIL; 1463 } 1464 } 1465 1466 dorecv = dosend = sc->sc_clkstate == CLK_AVAIL; 1467 1468 intstat = bwfm_sdio_dev_read(sc, BWFM_SDPCMD_INTSTATUS); 1469 DPRINTF(("%s: intstat 0x%" PRIx32 "\n", DEVNAME(sc), intstat)); 1470 if (intstat) 1471 bwfm_sdio_dev_write(sc, BWFM_SDPCMD_INTSTATUS, intstat); 1472 1473 if (intstat & SDPCMD_INTSTATUS_CHIPACTIVE) 1474 printf("%s: CHIPACTIVE\n", DEVNAME(sc)); 1475 1476 if (intstat & SDPCMD_INTSTATUS_HMB_HOST_INT) { 1477 hostint = bwfm_sdio_dev_read(sc, SDPCMD_TOHOSTMAILBOXDATA); 1478 DPRINTF(("%s: hostint 0x%" PRIx32 "\n", DEVNAME(sc), hostint)); 1479 bwfm_sdio_dev_write(sc, SDPCMD_TOSBMAILBOX, 1480 SDPCMD_TOSBMAILBOX_INT_ACK); 1481 if (hostint & SDPCMD_TOHOSTMAILBOXDATA_NAKHANDLED) 1482 sc->sc_rxskip = false; 1483 if (hostint & SDPCMD_TOHOSTMAILBOXDATA_DEVREADY || 1484 hostint & SDPCMD_TOHOSTMAILBOXDATA_FWREADY) 1485 bwfm_sdio_readshared(sc); 1486 } 1487 1488 if (intstat & SDPCMD_INTSTATUS_HMB_FRAME_IND) { 1489 /* ignore receive indications while recovering */ 1490 if (dorecv && !sc->sc_rxskip) { 1491 DPRINTF(("%s: recv\n", DEVNAME(sc))); 1492 bwfm_sdio_rx_frames(sc); 1493 } 1494 } 1495 1496 if (intstat & SDPCMD_INTSTATUS_HMB_FC_STATE) 1497 dosend = false; 1498 1499 if (intstat & SDPCMD_INTSTATUS_HMB_FC_CHANGE) { 1500 if (dosend) { 1501 intstat = bwfm_sdio_dev_read(sc, BWFM_SDPCMD_INTSTATUS); 1502 DPRINTF(("%s: intstat2 0x%" PRIx32 "\n", DEVNAME(sc), intstat)); 1503 if (intstat & (SDPCMD_INTSTATUS_HMB_FC_STATE | SDPCMD_INTSTATUS_HMB_FC_CHANGE)) 1504 dosend = false; 1505 } 1506 } 1507 1508 if (!dosend && MBUFQ_FIRST(&sc->sc_tx_queue)) printf("%s: flowctl\n", DEVNAME(sc)); 1509 if (dosend && MBUFQ_FIRST(&sc->sc_tx_queue)) { 1510 DPRINTF(("%s: xmit\n", DEVNAME(sc))); 1511 bwfm_sdio_tx_frames(sc); 1512 } 1513 } 1514 1515 static int 1516 bwfm_sdio_tx_ok(struct bwfm_sdio_softc *sc) 1517 { 1518 return (uint8_t)(sc->sc_tx_max_seq - sc->sc_tx_seq) != 0 && 1519 ((uint8_t)(sc->sc_tx_max_seq - sc->sc_tx_seq) & 0x80) == 0; 1520 } 1521 1522 static void 1523 bwfm_sdio_tx_frames(struct bwfm_sdio_softc *sc) 1524 { 1525 struct mbuf *m; 1526 struct ifnet *ifp = sc->sc_sc.sc_ic.ic_ifp; 1527 bool ifstart = false; 1528 int i; 1529 1530 if (!bwfm_sdio_tx_ok(sc)) 1531 return; 1532 1533 i = uimin((uint8_t)(sc->sc_tx_max_seq - sc->sc_tx_seq), 32); 1534 while (i--) { 1535 MBUFQ_DEQUEUE(&sc->sc_tx_queue, m); 1536 if (m == NULL) 1537 break; 1538 1539 if (m->m_type == MT_CONTROL) 1540 bwfm_sdio_tx_ctrlframe(sc, m); 1541 else { 1542 bwfm_sdio_tx_dataframe(sc, m); 1543 if_statinc(ifp, if_opackets); 1544 ifstart = true; 1545 } 1546 1547 m_freem(m); 1548 } 1549 1550 if (ifstart) { 1551 ifp->if_flags &= ~IFF_OACTIVE; 1552 if_schedule_deferred_start(ifp); 1553 } 1554 } 1555 1556 static void 1557 bwfm_sdio_tx_ctrlframe(struct bwfm_sdio_softc *sc, struct mbuf *m) 1558 { 1559 struct bwfm_sdio_hwhdr *hwhdr; 1560 struct bwfm_sdio_swhdr *swhdr; 1561 size_t len, roundto; 1562 1563 len = sizeof(*hwhdr) + sizeof(*swhdr) + m->m_len; 1564 1565 /* Zero-pad to either block-size or 4-byte alignment. */ 1566 if (len > 512 && (len % 512) != 0) 1567 roundto = 512; 1568 else 1569 roundto = 4; 1570 1571 KASSERT(roundup(len, roundto) <= sc->sc_bounce_size); 1572 1573 hwhdr = (void *)sc->sc_bounce_buf; 1574 hwhdr->frmlen = htole16(len); 1575 hwhdr->cksum = htole16(~len); 1576 1577 swhdr = (void *)&hwhdr[1]; 1578 swhdr->seqnr = sc->sc_tx_seq++; 1579 swhdr->chanflag = BWFM_SDIO_SWHDR_CHANNEL_CONTROL; 1580 swhdr->nextlen = 0; 1581 swhdr->dataoff = sizeof(*hwhdr) + sizeof(*swhdr); 1582 swhdr->maxseqnr = 0; 1583 1584 m_copydata(m, 0, m->m_len, &swhdr[1]); 1585 1586 if (roundup(len, roundto) != len) 1587 memset(sc->sc_bounce_buf + len, 0, 1588 roundup(len, roundto) - len); 1589 1590 bwfm_sdio_frame_read_write(sc, sc->sc_bounce_buf, 1591 roundup(len, roundto), 1); 1592 } 1593 1594 static void 1595 bwfm_sdio_tx_dataframe(struct bwfm_sdio_softc *sc, struct mbuf *m) 1596 { 1597 struct bwfm_sdio_hwhdr *hwhdr; 1598 struct bwfm_sdio_swhdr *swhdr; 1599 struct bwfm_proto_bcdc_hdr *bcdc; 1600 size_t len, roundto; 1601 1602 len = sizeof(*hwhdr) + sizeof(*swhdr) + sizeof(*bcdc) 1603 + m->m_pkthdr.len; 1604 1605 /* Zero-pad to either block-size or 4-byte alignment. */ 1606 if (len > 512 && (len % 512) != 0) 1607 roundto = 512; 1608 else 1609 roundto = 4; 1610 1611 KASSERT(roundup(len, roundto) <= sc->sc_bounce_size); 1612 1613 hwhdr = (void *)sc->sc_bounce_buf; 1614 hwhdr->frmlen = htole16(len); 1615 hwhdr->cksum = htole16(~len); 1616 1617 swhdr = (void *)&hwhdr[1]; 1618 swhdr->seqnr = sc->sc_tx_seq++; 1619 swhdr->chanflag = BWFM_SDIO_SWHDR_CHANNEL_DATA; 1620 swhdr->nextlen = 0; 1621 swhdr->dataoff = sizeof(*hwhdr) + sizeof(*swhdr); 1622 swhdr->maxseqnr = 0; 1623 1624 bcdc = (void *)&swhdr[1]; 1625 bcdc->data_offset = 0; 1626 bcdc->priority = WME_AC_BE; 1627 bcdc->flags = BWFM_BCDC_FLAG_VER(BWFM_BCDC_FLAG_PROTO_VER); 1628 bcdc->flags2 = 0; 1629 1630 m_copydata(m, 0, m->m_pkthdr.len, &bcdc[1]); 1631 1632 if (roundup(len, roundto) != len) 1633 memset(sc->sc_bounce_buf + len, 0, 1634 roundup(len, roundto) - len); 1635 1636 bwfm_sdio_frame_read_write(sc, sc->sc_bounce_buf, 1637 roundup(len, roundto), 1); 1638 1639 sc->sc_tx_count--; 1640 } 1641 1642 static int 1643 bwfm_sdio_rxctl(struct bwfm_softc *bwfm, char *buf, size_t *lenp) 1644 { 1645 struct bwfm_sdio_softc *sc = (void *)bwfm; 1646 struct mbuf *m; 1647 int err = 0; 1648 1649 mutex_enter(&sc->sc_lock); 1650 while ((m = bwfm_qget(&sc->sc_rxctl_queue)) == NULL) { 1651 err = cv_timedwait(&sc->sc_rxctl_cv, &sc->sc_lock, 1652 mstohz(5000)); 1653 if (err == EWOULDBLOCK) 1654 break; 1655 } 1656 mutex_exit(&sc->sc_lock); 1657 1658 if (err) 1659 return 1; 1660 1661 if (m->m_len > *lenp) { 1662 m_freem(m); 1663 return 1; 1664 } 1665 1666 *lenp = m->m_len; 1667 m_copydata(m, 0, m->m_len, buf); 1668 m_freem(m); 1669 return 0; 1670 } 1671 1672 static void 1673 bwfm_sdio_rx_frames(struct bwfm_sdio_softc *sc) 1674 { 1675 struct bwfm_sdio_hwhdr *hwhdr; 1676 struct bwfm_sdio_swhdr *swhdr; 1677 struct bwfm_proto_bcdc_hdr *bcdc; 1678 uint16_t *sublen, nextlen = 0; 1679 struct mbuf *m; 1680 size_t flen, off, hoff; 1681 char *data; 1682 int nsub; 1683 size_t subsize; 1684 1685 hwhdr = (struct bwfm_sdio_hwhdr *)sc->sc_bounce_buf; 1686 swhdr = (struct bwfm_sdio_swhdr *)&hwhdr[1]; 1687 data = (char *)&swhdr[1]; 1688 1689 for (;;) { 1690 /* If we know the next size, just read ahead. */ 1691 if (nextlen) { 1692 if (bwfm_sdio_frame_read_write(sc, sc->sc_bounce_buf, 1693 nextlen, 0)) 1694 break; 1695 nextlen = 0; 1696 } else { 1697 if (bwfm_sdio_frame_read_write(sc, sc->sc_bounce_buf, 1698 sizeof(*hwhdr) + sizeof(*swhdr), 0)) 1699 break; 1700 } 1701 1702 hwhdr->frmlen = le16toh(hwhdr->frmlen); 1703 hwhdr->cksum = le16toh(hwhdr->cksum); 1704 1705 if (hwhdr->frmlen == 0 && hwhdr->cksum == 0) { 1706 break; 1707 } 1708 1709 if ((hwhdr->frmlen ^ hwhdr->cksum) != 0xffff) { 1710 printf("%s: checksum error\n", DEVNAME(sc)); 1711 break; 1712 } 1713 1714 if (hwhdr->frmlen < sizeof(*hwhdr) + sizeof(*swhdr)) { 1715 printf("%s: length error\n", DEVNAME(sc)); 1716 break; 1717 } 1718 1719 if (nextlen && hwhdr->frmlen > nextlen) { 1720 printf("%s: read ahead length error (%u > %u)\n", 1721 DEVNAME(sc), hwhdr->frmlen, nextlen); 1722 break; 1723 } 1724 1725 sc->sc_tx_max_seq = swhdr->maxseqnr; 1726 1727 flen = hwhdr->frmlen - (sizeof(*hwhdr) + sizeof(*swhdr)); 1728 if (flen == 0) { 1729 nextlen = swhdr->nextlen << 4; 1730 continue; 1731 } 1732 1733 if (!nextlen) { 1734 KASSERT(roundup(flen, 4) <= sc->sc_bounce_size - 1735 (sizeof(*hwhdr) + sizeof(*swhdr))); 1736 if (bwfm_sdio_frame_read_write(sc, data, 1737 roundup(flen, 4), 0)) { 1738 printf("%s: I/O error roundup(%zu, 4) bytes\n", 1739 DEVNAME(sc), flen); 1740 break; 1741 } 1742 } 1743 1744 if (swhdr->dataoff < (sizeof(*hwhdr) + sizeof(*swhdr))) { 1745 printf("%s: data offset %u in header\n", 1746 DEVNAME(sc), swhdr->dataoff); 1747 break; 1748 } 1749 1750 off = swhdr->dataoff - (sizeof(*hwhdr) + sizeof(*swhdr)); 1751 if (off > flen) { 1752 printf("%s: offset %zu beyond end %zu\n", 1753 DEVNAME(sc), off, flen); 1754 break; 1755 } 1756 1757 switch (swhdr->chanflag & BWFM_SDIO_SWHDR_CHANNEL_MASK) { 1758 case BWFM_SDIO_SWHDR_CHANNEL_CONTROL: 1759 m = bwfm_sdio_newbuf(); 1760 if (m == NULL) 1761 break; 1762 if (flen - off > m->m_len) { 1763 printf("%s: ctl bigger than anticipated\n", 1764 DEVNAME(sc)); 1765 m_freem(m); 1766 break; 1767 } 1768 m->m_len = m->m_pkthdr.len = flen - off; 1769 memcpy(mtod(m, char *), data + off, flen - off); 1770 bwfm_qput(&sc->sc_rxctl_queue, m); 1771 cv_broadcast(&sc->sc_rxctl_cv); 1772 nextlen = swhdr->nextlen << 4; 1773 break; 1774 case BWFM_SDIO_SWHDR_CHANNEL_EVENT: 1775 case BWFM_SDIO_SWHDR_CHANNEL_DATA: 1776 m = bwfm_sdio_newbuf(); 1777 if (m == NULL) 1778 break; 1779 if (flen - off > m->m_len) { 1780 printf("%s: frame bigger than anticipated\n", 1781 DEVNAME(sc)); 1782 m_freem(m); 1783 break; 1784 } 1785 m->m_len = m->m_pkthdr.len = flen - off; 1786 memcpy(mtod(m, char *), data + off, flen - off); 1787 bcdc = mtod(m, struct bwfm_proto_bcdc_hdr *); 1788 hoff = sizeof(*bcdc) + ((size_t)bcdc->data_offset << 2); 1789 if (m->m_len < hoff) { 1790 printf("%s: short bcdc packet %d < %zu\n", 1791 DEVNAME(sc), m->m_len, hoff); 1792 m_freem(m); 1793 break; 1794 } 1795 m_adj(m, hoff); 1796 /* don't pass empty packet to stack */ 1797 if (m->m_len == 0) { 1798 m_freem(m); 1799 break; 1800 } 1801 bwfm_rx(&sc->sc_sc, m); 1802 nextlen = swhdr->nextlen << 4; 1803 break; 1804 case BWFM_SDIO_SWHDR_CHANNEL_GLOM: 1805 if ((flen % sizeof(uint16_t)) != 0) { 1806 printf("%s: odd length (%zu) glom table\n", 1807 DEVNAME(sc), flen); 1808 break; 1809 } 1810 nsub = flen / sizeof(uint16_t); 1811 subsize = nsub * sizeof(uint16_t); 1812 sublen = NULL; 1813 nextlen = 0; 1814 if (subsize > 0) 1815 sublen = kmem_zalloc(subsize, KM_NOSLEEP); 1816 if (sublen != NULL) { 1817 memcpy(sublen, data, subsize); 1818 bwfm_sdio_rx_glom(sc, sublen, nsub, &nextlen); 1819 kmem_free(sublen, subsize); 1820 } 1821 break; 1822 default: 1823 printf("%s: unknown channel\n", DEVNAME(sc)); 1824 break; 1825 } 1826 } 1827 } 1828 1829 static void 1830 bwfm_sdio_rx_glom(struct bwfm_sdio_softc *sc, uint16_t *sublen, int nsub, 1831 uint16_t *nextlen) 1832 { 1833 struct bwfm_sdio_hwhdr hwhdr; 1834 struct bwfm_sdio_swhdr swhdr; 1835 struct bwfm_proto_bcdc_hdr *bcdc; 1836 struct mbuf *m, *m0; 1837 size_t flen, off, hoff; 1838 int i; 1839 1840 if (nsub == 0) 1841 return; 1842 1843 m0 = NULL; 1844 for (i = 0; i < nsub; i++) { 1845 m = bwfm_sdio_newbuf(); 1846 if (m == NULL) { 1847 m_freem(m0); 1848 return; 1849 } 1850 bwfm_qput(&m0, m); 1851 if (le16toh(sublen[i]) > m->m_len) { 1852 m_freem(m0); 1853 printf("%s: header larger than mbuf\n", DEVNAME(sc)); 1854 return; 1855 } 1856 if (bwfm_sdio_frame_read_write(sc, mtod(m, char *), 1857 le16toh(sublen[i]), 0)) { 1858 m_freem(m0); 1859 printf("%s: frame I/O error\n", DEVNAME(sc)); 1860 return; 1861 } 1862 m->m_len = m->m_pkthdr.len = le16toh(sublen[i]); 1863 } 1864 1865 if (m0->m_len >= sizeof(hwhdr) + sizeof(swhdr)) { 1866 m_copydata(m0, 0, sizeof(hwhdr), &hwhdr); 1867 m_copydata(m0, sizeof(hwhdr), sizeof(swhdr), &swhdr); 1868 1869 /* TODO: Verify actual superframe header */ 1870 1871 /* remove superframe header */ 1872 if (m0->m_len >= swhdr.dataoff) 1873 m_adj(m0, swhdr.dataoff); 1874 } 1875 1876 *nextlen = 0; 1877 while ((m = bwfm_qget(&m0)) != NULL) { 1878 if (m->m_len < sizeof(hwhdr) + sizeof(swhdr)) { 1879 printf("%s: tiny mbuf %d < %zu\n", DEVNAME(sc), 1880 m->m_len, sizeof(hwhdr) + sizeof(swhdr)); 1881 goto drop; 1882 } 1883 1884 m_copydata(m, 0, sizeof(hwhdr), &hwhdr); 1885 m_copydata(m, sizeof(hwhdr), sizeof(swhdr), &swhdr); 1886 1887 hwhdr.frmlen = le16toh(hwhdr.frmlen); 1888 hwhdr.cksum = le16toh(hwhdr.cksum); 1889 1890 if (hwhdr.frmlen == 0 && hwhdr.cksum == 0) 1891 goto drop; 1892 1893 if ((hwhdr.frmlen ^ hwhdr.cksum) != 0xffff) { 1894 printf("%s: checksum error\n", DEVNAME(sc)); 1895 goto drop; 1896 } 1897 1898 1899 if (hwhdr.frmlen < sizeof(hwhdr) + sizeof(swhdr)) { 1900 printf("%s: length error\n", DEVNAME(sc)); 1901 goto drop; 1902 } 1903 1904 flen = hwhdr.frmlen - (sizeof(hwhdr) + sizeof(swhdr)); 1905 if (flen == 0) 1906 goto drop; 1907 1908 if (hwhdr.frmlen > m->m_len) { 1909 printf("%s: short mbuf %d < %zu\n", 1910 DEVNAME(sc),m->m_len,flen); 1911 goto drop; 1912 } 1913 1914 if (swhdr.dataoff < (sizeof(hwhdr) + sizeof(swhdr))) { 1915 printf("%s: data offset %u in header\n", 1916 DEVNAME(sc), swhdr.dataoff); 1917 goto drop; 1918 } 1919 1920 off = swhdr.dataoff - (sizeof(hwhdr) + sizeof(swhdr)); 1921 if (off > flen) { 1922 printf("%s: offset %zu beyond end %zu\n", 1923 DEVNAME(sc), off, flen); 1924 goto drop; 1925 } 1926 1927 m_adj(m, (int)hwhdr.frmlen - m->m_len); 1928 *nextlen = swhdr.nextlen << 4; 1929 1930 switch (swhdr.chanflag & BWFM_SDIO_SWHDR_CHANNEL_MASK) { 1931 case BWFM_SDIO_SWHDR_CHANNEL_CONTROL: 1932 printf("%s: control channel not allowed in glom\n", 1933 DEVNAME(sc)); 1934 goto drop; 1935 case BWFM_SDIO_SWHDR_CHANNEL_EVENT: 1936 case BWFM_SDIO_SWHDR_CHANNEL_DATA: 1937 m_adj(m, swhdr.dataoff); 1938 bcdc = mtod(m, struct bwfm_proto_bcdc_hdr *); 1939 hoff = sizeof(*bcdc) + ((size_t)bcdc->data_offset << 2); 1940 if (m->m_len < hoff) { 1941 printf("%s: short bcdc packet %d < %zu\n", 1942 DEVNAME(sc), m->m_len, hoff); 1943 m_freem(m); 1944 break; 1945 } 1946 m_adj(m, hoff); 1947 /* don't pass empty packet to stack */ 1948 if (m->m_len == 0) { 1949 m_freem(m); 1950 break; 1951 } 1952 bwfm_rx(&sc->sc_sc, m); 1953 break; 1954 case BWFM_SDIO_SWHDR_CHANNEL_GLOM: 1955 printf("%s: glom not allowed in glom\n", 1956 DEVNAME(sc)); 1957 goto drop; 1958 default: 1959 printf("%s: unknown channel\n", DEVNAME(sc)); 1960 goto drop; 1961 } 1962 1963 continue; 1964 drop: 1965 printf("rx dropped %p len %d\n",mtod(m, char *),m->m_pkthdr.len); 1966 m_free(m); 1967 break; 1968 } 1969 } 1970 1971 #ifdef BWFM_DEBUG 1972 static void 1973 bwfm_sdio_debug_console(struct bwfm_sdio_softc *sc) 1974 { 1975 struct bwfm_sdio_console c; 1976 uint32_t newidx; 1977 int err; 1978 1979 if (!sc->sc_console_addr) 1980 return; 1981 1982 err = bwfm_sdio_ram_read_write(sc, sc->sc_console_addr, 1983 (char *)&c, sizeof(c), 0); 1984 if (err) 1985 return; 1986 1987 c.log_buf = le32toh(c.log_buf); 1988 c.log_bufsz = le32toh(c.log_bufsz); 1989 c.log_idx = le32toh(c.log_idx); 1990 1991 if (sc->sc_console_buf == NULL) { 1992 sc->sc_console_buf = malloc(c.log_bufsz, M_DEVBUF, 1993 M_WAITOK|M_ZERO); 1994 sc->sc_console_buf_size = c.log_bufsz; 1995 } 1996 1997 newidx = c.log_idx; 1998 if (newidx >= sc->sc_console_buf_size) 1999 return; 2000 2001 err = bwfm_sdio_ram_read_write(sc, c.log_buf, sc->sc_console_buf, 2002 sc->sc_console_buf_size, 0); 2003 if (err) 2004 return; 2005 2006 if (newidx != sc->sc_console_readidx) 2007 DPRINTFN(3, ("BWFM CONSOLE: ")); 2008 while (newidx != sc->sc_console_readidx) { 2009 uint8_t ch = sc->sc_console_buf[sc->sc_console_readidx]; 2010 sc->sc_console_readidx++; 2011 if (sc->sc_console_readidx == sc->sc_console_buf_size) 2012 sc->sc_console_readidx = 0; 2013 if (ch == '\r') 2014 continue; 2015 DPRINTFN(3, ("%c", ch)); 2016 } 2017 } 2018 #endif 2019