1 /* $NetBSD: if_bwfm_sdio.c,v 1.27 2021/08/08 11:11:29 jmcneill 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 struct device_compatible_entry compat_data[] = { 308 { .compat = "brcm,bcm4329-fmac" }, 309 DEVICE_COMPAT_EOL 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_string(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_string(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_compatible_match(phandle, compat_data)) 587 return -1; 588 589 return phandle; 590 } 591 592 static const char * 593 bwfm_fdt_get_model(void) 594 { 595 const char *model; 596 int phandle; 597 598 phandle = OF_finddevice("/"); 599 model = fdtbus_get_string_index(phandle, "compatible", 0); 600 if (model == NULL || 601 (model != NULL && strcmp(model, "netbsd,generic-acpi") == 0)) { 602 model = pmf_get_platform("system-product"); 603 } 604 605 return model; 606 } 607 608 static int 609 bwfm_sdio_detach(device_t self, int flags) 610 { 611 struct bwfm_sdio_softc *sc = (struct bwfm_sdio_softc *)self; 612 613 #ifdef BWFM_DEBUG 614 bwfm_sdio_debug_console(sc); 615 #endif 616 617 if (sc->sc_ih || sc->sc_fdtih) { 618 sdmmc_intr_disable(sc->sc_sf[1]); 619 if (sc->sc_ih) 620 sdmmc_intr_disestablish(sc->sc_ih); 621 if (sc->sc_fdtih) 622 fdtbus_intr_disestablish(sc->sc_phandle, sc->sc_fdtih); 623 } 624 if (sc->sc_bwfm_attached) 625 bwfm_detach(&sc->sc_sc, flags); 626 627 sdmmc_del_task(sc->sc_sf[1]->sc, &sc->sc_task, NULL); 628 629 kmem_free(sc->sc_sf, sc->sc_sf_size); 630 kmem_free(sc->sc_bounce_buf, sc->sc_bounce_size); 631 632 cv_destroy(&sc->sc_rxctl_cv); 633 mutex_destroy(&sc->sc_lock); 634 635 return 0; 636 } 637 638 static void 639 bwfm_sdio_backplane(struct bwfm_sdio_softc *sc, uint32_t addr) 640 { 641 uint32_t bar0 = addr & ~BWFM_SDIO_SB_OFT_ADDR_MASK; 642 643 if (sc->sc_bar0 == bar0) 644 return; 645 646 bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_SBADDRLOW, 647 (bar0 >> 8) & 0xff); 648 bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_SBADDRMID, 649 (bar0 >> 16) & 0xff); 650 bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_SBADDRHIGH, 651 (bar0 >> 24) & 0xff); 652 sc->sc_bar0 = bar0; 653 } 654 655 static uint8_t 656 bwfm_sdio_read_1(struct bwfm_sdio_softc *sc, uint32_t addr) 657 { 658 struct sdmmc_function *sf; 659 uint8_t rv; 660 661 /* 662 * figure out how to read the register based on address range 663 * 0x00 ~ 0x7FF: function 0 CCCR and FBR 664 * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers 665 * The rest: function 1 silicon backplane core registers 666 */ 667 if ((addr & ~0x7ff) == 0) 668 sf = sc->sc_sf[0]; 669 else 670 sf = sc->sc_sf[1]; 671 672 rv = sdmmc_io_read_1(sf, addr); 673 return rv; 674 } 675 676 static uint32_t 677 bwfm_sdio_read_4(struct bwfm_sdio_softc *sc, uint32_t addr) 678 { 679 struct sdmmc_function *sf; 680 uint32_t rv; 681 682 bwfm_sdio_backplane(sc, addr); 683 684 addr &= BWFM_SDIO_SB_OFT_ADDR_MASK; 685 addr |= BWFM_SDIO_SB_ACCESS_2_4B_FLAG; 686 687 /* 688 * figure out how to read the register based on address range 689 * 0x00 ~ 0x7FF: function 0 CCCR and FBR 690 * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers 691 * The rest: function 1 silicon backplane core registers 692 */ 693 if ((addr & ~0x7ff) == 0) 694 sf = sc->sc_sf[0]; 695 else 696 sf = sc->sc_sf[1]; 697 698 rv = sdmmc_io_read_4(sf, addr); 699 return htole32(rv); 700 } 701 702 static void 703 bwfm_sdio_write_1(struct bwfm_sdio_softc *sc, uint32_t addr, uint8_t data) 704 { 705 struct sdmmc_function *sf; 706 707 /* 708 * figure out how to read the register based on address range 709 * 0x00 ~ 0x7FF: function 0 CCCR and FBR 710 * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers 711 * The rest: function 1 silicon backplane core registers 712 */ 713 if ((addr & ~0x7ff) == 0) 714 sf = sc->sc_sf[0]; 715 else 716 sf = sc->sc_sf[1]; 717 718 sdmmc_io_write_1(sf, addr, data); 719 } 720 721 static void 722 bwfm_sdio_write_4(struct bwfm_sdio_softc *sc, uint32_t addr, uint32_t data) 723 { 724 struct sdmmc_function *sf; 725 726 bwfm_sdio_backplane(sc, addr); 727 728 addr &= BWFM_SDIO_SB_OFT_ADDR_MASK; 729 addr |= BWFM_SDIO_SB_ACCESS_2_4B_FLAG; 730 731 /* 732 * figure out how to read the register based on address range 733 * 0x00 ~ 0x7FF: function 0 CCCR and FBR 734 * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers 735 * The rest: function 1 silicon backplane core registers 736 */ 737 if ((addr & ~0x7ff) == 0) 738 sf = sc->sc_sf[0]; 739 else 740 sf = sc->sc_sf[1]; 741 742 sdmmc_io_write_4(sf, addr, htole32(data)); 743 } 744 745 static int 746 bwfm_sdio_buf_read(struct bwfm_sdio_softc *sc, struct sdmmc_function *sf, 747 uint32_t reg, char *data, size_t size) 748 { 749 int err; 750 751 KASSERT(((vaddr_t)data & 0x3) == 0); 752 KASSERT((size & 0x3) == 0); 753 754 if (sf == sc->sc_sf[1]) 755 err = sdmmc_io_read_region_1(sf, reg, data, size); 756 else 757 err = sdmmc_io_read_multi_1(sf, reg, data, size); 758 759 if (err) 760 printf("%s: error %d\n", __func__, err); 761 762 return err; 763 } 764 765 static int 766 bwfm_sdio_buf_write(struct bwfm_sdio_softc *sc, struct sdmmc_function *sf, 767 uint32_t reg, char *data, size_t size) 768 { 769 int err; 770 771 KASSERT(((vaddr_t)data & 0x3) == 0); 772 KASSERT((size & 0x3) == 0); 773 774 err = sdmmc_io_write_region_1(sf, reg, data, size); 775 776 if (err) 777 printf("%s: error %d\n", __func__, err); 778 779 return err; 780 } 781 782 static uint32_t 783 bwfm_sdio_ram_read_write(struct bwfm_sdio_softc *sc, uint32_t reg, 784 char *data, size_t left, int write) 785 { 786 uint32_t sbaddr, sdaddr, off; 787 size_t size; 788 int err; 789 790 err = off = 0; 791 while (left > 0) { 792 sbaddr = reg + off; 793 bwfm_sdio_backplane(sc, sbaddr); 794 795 sdaddr = sbaddr & BWFM_SDIO_SB_OFT_ADDR_MASK; 796 size = ulmin(left, (BWFM_SDIO_SB_OFT_ADDR_PAGE - sdaddr)); 797 sdaddr |= BWFM_SDIO_SB_ACCESS_2_4B_FLAG; 798 799 if (write) { 800 memcpy(sc->sc_bounce_buf, data + off, size); 801 if (roundup(size, 4) != size) 802 memset(sc->sc_bounce_buf + size, 0, 803 roundup(size, 4) - size); 804 err = bwfm_sdio_buf_write(sc, sc->sc_sf[1], sdaddr, 805 sc->sc_bounce_buf, roundup(size, 4)); 806 } else { 807 err = bwfm_sdio_buf_read(sc, sc->sc_sf[1], sdaddr, 808 sc->sc_bounce_buf, roundup(size, 4)); 809 memcpy(data + off, sc->sc_bounce_buf, size); 810 } 811 if (err) 812 break; 813 814 off += size; 815 left -= size; 816 } 817 818 if (err) 819 printf("%s: error %d\n", __func__, err); 820 821 return err; 822 } 823 824 static uint32_t 825 bwfm_sdio_frame_read_write(struct bwfm_sdio_softc *sc, 826 char *data, size_t size, int write) 827 { 828 uint32_t addr; 829 int err; 830 831 addr = sc->sc_cc->co_base; 832 bwfm_sdio_backplane(sc, addr); 833 834 addr &= BWFM_SDIO_SB_OFT_ADDR_MASK; 835 addr |= BWFM_SDIO_SB_ACCESS_2_4B_FLAG; 836 837 if (write) 838 err = bwfm_sdio_buf_write(sc, sc->sc_sf[2], addr, data, size); 839 else 840 err = bwfm_sdio_buf_read(sc, sc->sc_sf[2], addr, data, size); 841 842 if (err) 843 printf("%s: error %d\n", __func__, err); 844 845 return err; 846 } 847 848 static uint32_t 849 bwfm_sdio_dev_read(struct bwfm_sdio_softc *sc, uint32_t reg) 850 { 851 struct bwfm_core *core; 852 uint32_t val; 853 854 core = bwfm_chip_get_core(&sc->sc_sc, BWFM_AGENT_CORE_SDIO_DEV); 855 val = bwfm_sdio_read_4(sc, core->co_base + reg); 856 /* TODO: Workaround for 4335/4339 */ 857 858 return val; 859 } 860 861 static void 862 bwfm_sdio_dev_write(struct bwfm_sdio_softc *sc, uint32_t reg, uint32_t val) 863 { 864 struct bwfm_core *core; 865 866 core = bwfm_chip_get_core(&sc->sc_sc, BWFM_AGENT_CORE_SDIO_DEV); 867 bwfm_sdio_write_4(sc, core->co_base + reg, val); 868 } 869 870 static uint32_t 871 bwfm_sdio_buscore_read(struct bwfm_softc *bwfm, uint32_t reg) 872 { 873 struct bwfm_sdio_softc *sc = (void *)bwfm; 874 uint32_t val; 875 876 mutex_enter(&sc->sc_lock); 877 val = bwfm_sdio_read_4(sc, reg); 878 /* TODO: Workaround for 4335/4339 */ 879 mutex_exit(&sc->sc_lock); 880 881 return val; 882 } 883 884 static void 885 bwfm_sdio_buscore_write(struct bwfm_softc *bwfm, uint32_t reg, uint32_t val) 886 { 887 struct bwfm_sdio_softc *sc = (void *)bwfm; 888 889 mutex_enter(&sc->sc_lock); 890 bwfm_sdio_write_4(sc, reg, val); 891 mutex_exit(&sc->sc_lock); 892 } 893 894 static int 895 bwfm_sdio_buscore_prepare(struct bwfm_softc *bwfm) 896 { 897 struct bwfm_sdio_softc *sc = (void *)bwfm; 898 uint8_t clkval, clkset, clkmask; 899 int i, error = 0; 900 901 mutex_enter(&sc->sc_lock); 902 903 clkset = BWFM_SDIO_FUNC1_CHIPCLKCSR_ALP_AVAIL_REQ | 904 BWFM_SDIO_FUNC1_CHIPCLKCSR_FORCE_HW_CLKREQ_OFF; 905 bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR, clkset); 906 907 clkmask = BWFM_SDIO_FUNC1_CHIPCLKCSR_ALP_AVAIL | 908 BWFM_SDIO_FUNC1_CHIPCLKCSR_HT_AVAIL; 909 clkval = bwfm_sdio_read_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR); 910 911 if ((clkval & ~clkmask) != clkset) { 912 printf("%s: wrote 0x%02x read 0x%02x\n", DEVNAME(sc), 913 clkset, clkval); 914 error = 1; 915 goto done; 916 } 917 918 for (i = 1000; i > 0; i--) { 919 clkval = bwfm_sdio_read_1(sc, 920 BWFM_SDIO_FUNC1_CHIPCLKCSR); 921 if (clkval & clkmask) 922 break; 923 } 924 if (i == 0) { 925 printf("%s: timeout on ALPAV wait, clkval 0x%02x\n", 926 DEVNAME(sc), clkval); 927 error = 1; 928 goto done; 929 } 930 931 clkset = BWFM_SDIO_FUNC1_CHIPCLKCSR_FORCE_HW_CLKREQ_OFF | 932 BWFM_SDIO_FUNC1_CHIPCLKCSR_FORCE_ALP; 933 bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR, clkset); 934 delay(65); 935 936 bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_SDIOPULLUP, 0); 937 938 done: 939 mutex_exit(&sc->sc_lock); 940 941 return error; 942 } 943 944 static void 945 bwfm_sdio_buscore_activate(struct bwfm_softc *bwfm, uint32_t rstvec) 946 { 947 struct bwfm_sdio_softc *sc = (void *)bwfm; 948 struct bwfm_core *core; 949 950 core = bwfm_chip_get_core(&sc->sc_sc, BWFM_AGENT_CORE_SDIO_DEV); 951 bwfm_sdio_buscore_write(&sc->sc_sc, 952 core->co_base + BWFM_SDPCMD_INTSTATUS, 0xFFFFFFFF); 953 954 mutex_enter(&sc->sc_lock); 955 if (rstvec) 956 bwfm_sdio_ram_read_write(sc, 0, (char *)&rstvec, 957 sizeof(rstvec), 1); 958 mutex_exit(&sc->sc_lock); 959 } 960 961 static struct mbuf * 962 bwfm_sdio_newbuf(void) 963 { 964 struct mbuf *m; 965 966 MGETHDR(m, M_DONTWAIT, MT_DATA); 967 if (m == NULL) 968 return NULL; 969 970 MCLGET(m, M_DONTWAIT); 971 if (!(m->m_flags & M_EXT)) { 972 m_freem(m); 973 return NULL; 974 } 975 976 m->m_len = m->m_pkthdr.len = MCLBYTES; 977 return m; 978 } 979 980 static struct mbuf * 981 bwfm_qget(struct mbuf **q) 982 { 983 struct mbuf *m = NULL; 984 985 if (*q != NULL) { 986 m = *q; 987 *q = m->m_next; 988 m->m_next = NULL; 989 } 990 991 return m; 992 } 993 994 static void 995 bwfm_qput(struct mbuf **q, struct mbuf *m) 996 { 997 998 if (*q == NULL) 999 *q = m; 1000 else 1001 m_cat(*q, m); 1002 } 1003 1004 static int 1005 bwfm_sdio_txcheck(struct bwfm_softc *bwfm) 1006 { 1007 struct bwfm_sdio_softc *sc = (void *)bwfm; 1008 int error = 0; 1009 1010 mutex_enter(&sc->sc_lock); 1011 if (sc->sc_tx_count >= 64) 1012 error = ENOBUFS; 1013 mutex_exit(&sc->sc_lock); 1014 1015 return error; 1016 } 1017 1018 1019 static int 1020 bwfm_sdio_txdata(struct bwfm_softc *bwfm, struct mbuf **mp) 1021 { 1022 struct bwfm_sdio_softc *sc = (void *)bwfm; 1023 1024 if (sc->sc_tx_count >= 64) { 1025 printf("%s: tx count limit reached\n",DEVNAME(sc)); 1026 return ENOBUFS; 1027 } 1028 1029 mutex_enter(&sc->sc_lock); 1030 sc->sc_tx_count++; 1031 MBUFQ_ENQUEUE(&sc->sc_tx_queue, *mp); 1032 mutex_exit(&sc->sc_lock); 1033 1034 bwfm_sdio_intr1(sc, "sdio_txdata"); 1035 1036 return 0; 1037 } 1038 1039 static int 1040 bwfm_sdio_txctl(struct bwfm_softc *bwfm, char *buf, size_t len) 1041 { 1042 struct bwfm_sdio_softc *sc = (void *)bwfm; 1043 struct mbuf *m; 1044 1045 KASSERT(len <= MCLBYTES); 1046 1047 MGET(m, M_DONTWAIT, MT_CONTROL); 1048 if (m == NULL) 1049 goto fail; 1050 if (len > MLEN) { 1051 MCLGET(m, M_DONTWAIT); 1052 if (!(m->m_flags & M_EXT)) { 1053 m_freem(m); 1054 goto fail; 1055 } 1056 } 1057 memcpy(mtod(m, char *), buf, len); 1058 m->m_len = len; 1059 1060 mutex_enter(&sc->sc_lock); 1061 MBUFQ_ENQUEUE(&sc->sc_tx_queue, m); 1062 mutex_exit(&sc->sc_lock); 1063 1064 bwfm_sdio_intr1(sc, "sdio_txctl"); 1065 1066 return 0; 1067 1068 fail: 1069 return ENOBUFS; 1070 } 1071 1072 static int 1073 bwfm_nvram_convert(u_char *buf, size_t len, size_t *newlenp) 1074 { 1075 u_char *src, *dst, *end = buf + len; 1076 bool skip = false; 1077 size_t count = 0, pad; 1078 uint32_t token; 1079 1080 for (src = buf, dst = buf; src != end; ++src) { 1081 if (*src == '\n') { 1082 if (count > 0) 1083 *dst++ = '\0'; 1084 count = 0; 1085 skip = false; 1086 continue; 1087 } 1088 if (skip) 1089 continue; 1090 if (*src == '#' && count == 0) { 1091 skip = true; 1092 continue; 1093 } 1094 if (*src == '\r' || *src == ' ') 1095 continue; 1096 *dst++ = *src; 1097 ++count; 1098 } 1099 1100 count = dst - buf; 1101 pad = roundup(count + 1, 4) - count; 1102 1103 if (count + pad + sizeof(token) > len) 1104 return 1; 1105 1106 memset(dst, 0, pad); 1107 count += pad; 1108 dst += pad; 1109 1110 token = (count / 4) & 0xffff; 1111 token |= ~token << 16; 1112 token = htole32(token); 1113 1114 memcpy(dst, &token, sizeof(token)); 1115 count += sizeof(token); 1116 1117 *newlenp = count; 1118 1119 return 0; 1120 } 1121 1122 static int 1123 bwfm_sdio_load_microcode(struct bwfm_sdio_softc *sc, u_char *ucode, size_t size, 1124 u_char *nvram, size_t nvlen) 1125 { 1126 struct bwfm_softc *bwfm = &sc->sc_sc; 1127 char *verify = NULL; 1128 int err = 0; 1129 1130 bwfm_sdio_clkctl(sc, CLK_AVAIL, false); 1131 1132 DPRINTF(("ucode %zu bytes to 0x%08lx\n", size, 1133 (u_long)bwfm->sc_chip.ch_rambase)); 1134 /* Upload firmware */ 1135 err = bwfm_sdio_ram_read_write(sc, bwfm->sc_chip.ch_rambase, 1136 ucode, size, 1); 1137 if (err) 1138 goto out; 1139 1140 /* Verify firmware */ 1141 verify = kmem_zalloc(size, KM_SLEEP); 1142 err = bwfm_sdio_ram_read_write(sc, bwfm->sc_chip.ch_rambase, 1143 verify, size, 0); 1144 if (err || memcmp(verify, ucode, size)) { 1145 printf("%s: firmware verification failed\n", 1146 DEVNAME(sc)); 1147 kmem_free(verify, size); 1148 goto out; 1149 } 1150 kmem_free(verify, size); 1151 1152 DPRINTF(("nvram %zu bytes to 0x%08lx\n", nvlen, 1153 (u_long)bwfm->sc_chip.ch_rambase + bwfm->sc_chip.ch_ramsize 1154 - nvlen)); 1155 /* Upload nvram */ 1156 err = bwfm_sdio_ram_read_write(sc, bwfm->sc_chip.ch_rambase + 1157 bwfm->sc_chip.ch_ramsize - nvlen, nvram, nvlen, 1); 1158 if (err) 1159 goto out; 1160 1161 /* Verify nvram */ 1162 verify = kmem_zalloc(nvlen, KM_SLEEP); 1163 err = bwfm_sdio_ram_read_write(sc, bwfm->sc_chip.ch_rambase + 1164 bwfm->sc_chip.ch_ramsize - nvlen, verify, nvlen, 0); 1165 if (err || memcmp(verify, nvram, nvlen)) { 1166 printf("%s: nvram verification failed\n", 1167 DEVNAME(sc)); 1168 kmem_free(verify, nvlen); 1169 goto out; 1170 } 1171 kmem_free(verify, nvlen); 1172 1173 DPRINTF(("Reset core 0x%08x\n", *(uint32_t *)ucode)); 1174 /* Load reset vector from firmware and kickstart core. */ 1175 bwfm_chip_set_active(bwfm, *(uint32_t *)ucode); 1176 1177 out: 1178 bwfm_sdio_clkctl(sc, CLK_SDONLY, false); 1179 return err; 1180 } 1181 1182 static void 1183 bwfm_sdio_clkctl(struct bwfm_sdio_softc *sc, enum bwfm_sdio_clkstate newstate, 1184 bool pendok) 1185 { 1186 enum bwfm_sdio_clkstate oldstate; 1187 1188 oldstate = sc->sc_clkstate; 1189 if (oldstate == newstate) 1190 return; 1191 1192 switch (newstate) { 1193 case CLK_AVAIL: 1194 if (oldstate == CLK_NONE) 1195 sc->sc_clkstate = CLK_SDONLY; /* XXX */ 1196 bwfm_sdio_htclk(sc, true, pendok); 1197 break; 1198 case CLK_SDONLY: 1199 if (oldstate == CLK_NONE) 1200 sc->sc_clkstate = newstate; 1201 else if (oldstate == CLK_AVAIL) 1202 bwfm_sdio_htclk(sc, false, false); 1203 else 1204 printf("%s: clkctl %d -> %d\n", DEVNAME(sc), 1205 sc->sc_clkstate, newstate); 1206 break; 1207 case CLK_NONE: 1208 if (oldstate == CLK_AVAIL) 1209 bwfm_sdio_htclk(sc, false, false); 1210 sc->sc_clkstate = newstate; 1211 break; 1212 default: 1213 break; 1214 } 1215 1216 DPRINTF(("%s: %d -> %d = %d\n", DEVNAME(sc), oldstate, newstate, 1217 sc->sc_clkstate)); 1218 } 1219 1220 static void 1221 bwfm_sdio_htclk(struct bwfm_sdio_softc *sc, bool on, bool pendok) 1222 { 1223 uint32_t clkctl, devctl, req; 1224 int i; 1225 1226 if (sc->sc_sr_enabled) { 1227 if (on) 1228 sc->sc_clkstate = CLK_AVAIL; 1229 else 1230 sc->sc_clkstate = CLK_SDONLY; 1231 return; 1232 } 1233 1234 if (on) { 1235 if (sc->sc_alp_only) 1236 req = BWFM_SDIO_FUNC1_CHIPCLKCSR_ALP_AVAIL_REQ; 1237 else 1238 req = BWFM_SDIO_FUNC1_CHIPCLKCSR_HT_AVAIL_REQ; 1239 bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR, req); 1240 1241 clkctl = bwfm_sdio_read_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR); 1242 if (!BWFM_SDIO_FUNC1_CHIPCLKCSR_CLKAV(clkctl, sc->sc_alp_only) 1243 && pendok) { 1244 devctl = bwfm_sdio_read_1(sc, BWFM_SDIO_DEVICE_CTL); 1245 devctl |= BWFM_SDIO_DEVICE_CTL_CA_INT_ONLY; 1246 bwfm_sdio_write_1(sc, BWFM_SDIO_DEVICE_CTL, devctl); 1247 sc->sc_clkstate = CLK_PENDING; 1248 return; 1249 } else if (sc->sc_clkstate == CLK_PENDING) { 1250 devctl = bwfm_sdio_read_1(sc, BWFM_SDIO_DEVICE_CTL); 1251 devctl &= ~BWFM_SDIO_DEVICE_CTL_CA_INT_ONLY; 1252 bwfm_sdio_write_1(sc, BWFM_SDIO_DEVICE_CTL, devctl); 1253 } 1254 1255 for (i = 0; i < 50; i++) { 1256 if (BWFM_SDIO_FUNC1_CHIPCLKCSR_CLKAV(clkctl, 1257 sc->sc_alp_only)) 1258 break; 1259 clkctl = bwfm_sdio_read_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR 1260 ); 1261 sdmmc_pause(100000, NULL); 1262 } 1263 if (i >= 50) { 1264 printf("%s: HT avail timeout\n", DEVNAME(sc)); 1265 return; 1266 } 1267 1268 sc->sc_clkstate = CLK_AVAIL; 1269 } else { 1270 if (sc->sc_clkstate == CLK_PENDING) { 1271 devctl = bwfm_sdio_read_1(sc, BWFM_SDIO_DEVICE_CTL); 1272 devctl &= ~BWFM_SDIO_DEVICE_CTL_CA_INT_ONLY; 1273 bwfm_sdio_write_1(sc, BWFM_SDIO_DEVICE_CTL, devctl); 1274 } 1275 sc->sc_clkstate = CLK_SDONLY; 1276 bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR, 0); 1277 } 1278 } 1279 1280 struct bwfm_sdio_dstab { 1281 uint8_t milli; 1282 uint8_t val; 1283 }; 1284 1285 static struct bwfm_sdio_dstab pmu11_1v8[] = { 1286 {32, 0x6}, 1287 {26, 0x7}, 1288 {22, 0x4}, 1289 {16, 0x5}, 1290 {12, 0x2}, 1291 {8, 0x3}, 1292 {4, 0x0}, 1293 {0, 0x1} 1294 }, pmu13_1v8[] = { 1295 {6, 0x7}, 1296 {5, 0x6}, 1297 {4, 0x5}, 1298 {3, 0x4}, 1299 {2, 0x2}, 1300 {1, 0x1}, 1301 {0, 0x0} 1302 }, pmu17_1v8[] = { 1303 {3, 0x3}, 1304 {2, 0x2}, 1305 {1, 0x1}, 1306 {0, 0x0} 1307 }, pmu17_3v3[] = { 1308 {16, 0x7}, 1309 {12, 0x5}, 1310 {8, 0x3}, 1311 {4, 0x1}, 1312 {0, 0x0} 1313 }; 1314 1315 static void 1316 bwfm_sdio_drivestrength(struct bwfm_sdio_softc *sc, unsigned milli) 1317 { 1318 struct bwfm_softc *bwfm = &sc->sc_sc; 1319 struct bwfm_core *core; 1320 struct bwfm_sdio_dstab *tab; 1321 uint32_t tmp, mask; 1322 unsigned i; 1323 1324 if ((bwfm->sc_chip.ch_cc_caps & BWFM_CHIP_REG_CAPABILITIES_PMU) == 0) 1325 return; 1326 1327 switch (bwfm->sc_chip.ch_chip) { 1328 case BRCM_CC_4330_CHIP_ID: 1329 tab = pmu11_1v8; 1330 mask = __BITS(11,13); 1331 break; 1332 case BRCM_CC_4334_CHIP_ID: 1333 tab = pmu17_1v8; 1334 mask = __BITS(11,12); 1335 break; 1336 case BRCM_CC_43143_CHIP_ID: 1337 tab = pmu17_3v3; 1338 mask = __BITS(0,3); 1339 break; 1340 case BRCM_CC_43362_CHIP_ID: 1341 tab = pmu13_1v8; 1342 mask = __BITS(11,13); 1343 break; 1344 default: 1345 return; 1346 } 1347 1348 for (i=0; tab[i].milli != 0; ++i) { 1349 if (milli >= tab[i].milli) 1350 break; 1351 } 1352 if (tab[i].milli == 0) 1353 return; 1354 1355 core = bwfm_chip_get_pmu(&sc->sc_sc); 1356 tmp = bwfm_sdio_read_4(sc, core->co_base + BWFM_CHIP_REG_CHIPCONTROL_ADDR); 1357 tmp &= mask; 1358 tmp |= __SHIFTIN(tab[i].val, mask); 1359 bwfm_sdio_write_4(sc, core->co_base + BWFM_CHIP_REG_CHIPCONTROL_ADDR, tmp); 1360 } 1361 1362 1363 #if notyet 1364 static int 1365 bwfm_sdio_bus_sleep(struct bwfm_sdio_softc *sc, bool sleep, bool pendok) 1366 { 1367 uint32_t clkctl; 1368 1369 if (sc->sleeping == sleep) 1370 return 0; 1371 1372 if (sc->sc_sr_enabled) { 1373 if (sleep) { 1374 clkctl = bwfm_sdio_read_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR); 1375 if ((clkctl & BWFM_SDIO_FUNC1_CHIPCLKCSR_CSR_MASK) == 0) 1376 bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR, BWFM_SDIO_FUNC1_CHIPCLKCSR_ALP_AVAIL_REQ); 1377 } 1378 /* kso_ctrl(sc, sleep) */ 1379 } 1380 1381 if (sleep) { 1382 if (!sc->sc_sr_enabled) 1383 bwfm_sdio_clkctl(sc, CLK_NONE, pendok); 1384 } else { 1385 bwfm_sdio_clkctl(sc, CLK_AVAIL, pendok); 1386 } 1387 1388 sc->sleeping = sleep; 1389 1390 return 0; 1391 } 1392 #endif 1393 1394 static void 1395 bwfm_sdio_readshared(struct bwfm_sdio_softc *sc) 1396 { 1397 struct bwfm_softc *bwfm = &sc->sc_sc; 1398 struct bwfm_sdio_sdpcm sdpcm; 1399 uint32_t addr, shaddr; 1400 int err; 1401 1402 bwfm_sdio_clkctl(sc, CLK_AVAIL, false); 1403 if (sc->sc_clkstate != CLK_AVAIL) 1404 return; 1405 1406 shaddr = bwfm->sc_chip.ch_rambase + bwfm->sc_chip.ch_ramsize - 4; 1407 if (!bwfm->sc_chip.ch_rambase && sc->sc_sr_enabled) 1408 shaddr -= bwfm->sc_chip.ch_srsize; 1409 1410 err = bwfm_sdio_ram_read_write(sc, shaddr, (char *)&addr, 1411 sizeof(addr), 0); 1412 if (err) 1413 return; 1414 1415 addr = le32toh(addr); 1416 if (addr == 0 || ((~addr >> 16) & 0xffff) == (addr & 0xffff)) 1417 return; 1418 1419 err = bwfm_sdio_ram_read_write(sc, addr, (char *)&sdpcm, 1420 sizeof(sdpcm), 0); 1421 if (err) 1422 return; 1423 1424 sc->sc_console_addr = le32toh(sdpcm.console_addr); 1425 } 1426 1427 static int 1428 bwfm_sdio_intr1(void *v, const char *name) 1429 { 1430 struct bwfm_sdio_softc *sc = (void *)v; 1431 1432 DPRINTF(("%s: %s\n", DEVNAME(sc), name)); 1433 1434 sdmmc_add_task(sc->sc_sf[1]->sc, &sc->sc_task); 1435 return 1; 1436 } 1437 1438 static int 1439 bwfm_sdio_intr(void *v) 1440 { 1441 return bwfm_sdio_intr1(v, "sdio_intr"); 1442 } 1443 1444 static void 1445 bwfm_sdio_task(void *v) 1446 { 1447 struct bwfm_sdio_softc *sc = (void *)v; 1448 1449 mutex_enter(&sc->sc_lock); 1450 bwfm_sdio_task1(sc); 1451 #ifdef BWFM_DEBUG 1452 bwfm_sdio_debug_console(sc); 1453 #endif 1454 mutex_exit(&sc->sc_lock); 1455 } 1456 1457 static void 1458 bwfm_sdio_task1(struct bwfm_sdio_softc *sc) 1459 { 1460 uint32_t clkctl, devctl, intstat, hostint; 1461 bool dorecv, dosend; 1462 1463 if (!sc->sc_sr_enabled && sc->sc_clkstate == CLK_PENDING) { 1464 clkctl = bwfm_sdio_read_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR); 1465 if (BWFM_SDIO_FUNC1_CHIPCLKCSR_HTAV(clkctl)) { 1466 devctl = bwfm_sdio_read_1(sc, BWFM_SDIO_DEVICE_CTL); 1467 devctl &= ~BWFM_SDIO_DEVICE_CTL_CA_INT_ONLY; 1468 bwfm_sdio_write_1(sc, BWFM_SDIO_DEVICE_CTL, devctl); 1469 sc->sc_clkstate = CLK_AVAIL; 1470 } 1471 } 1472 1473 dorecv = dosend = sc->sc_clkstate == CLK_AVAIL; 1474 1475 intstat = bwfm_sdio_dev_read(sc, BWFM_SDPCMD_INTSTATUS); 1476 DPRINTF(("%s: intstat 0x%" PRIx32 "\n", DEVNAME(sc), intstat)); 1477 if (intstat) 1478 bwfm_sdio_dev_write(sc, BWFM_SDPCMD_INTSTATUS, intstat); 1479 1480 if (intstat & SDPCMD_INTSTATUS_CHIPACTIVE) 1481 printf("%s: CHIPACTIVE\n", DEVNAME(sc)); 1482 1483 if (intstat & SDPCMD_INTSTATUS_HMB_HOST_INT) { 1484 hostint = bwfm_sdio_dev_read(sc, SDPCMD_TOHOSTMAILBOXDATA); 1485 DPRINTF(("%s: hostint 0x%" PRIx32 "\n", DEVNAME(sc), hostint)); 1486 bwfm_sdio_dev_write(sc, SDPCMD_TOSBMAILBOX, 1487 SDPCMD_TOSBMAILBOX_INT_ACK); 1488 if (hostint & SDPCMD_TOHOSTMAILBOXDATA_FWHALT) 1489 printf("%s: firmware halted\n", DEVNAME(sc)); 1490 if (hostint & SDPCMD_TOHOSTMAILBOXDATA_NAKHANDLED) 1491 sc->sc_rxskip = false; 1492 if (hostint & SDPCMD_TOHOSTMAILBOXDATA_DEVREADY || 1493 hostint & SDPCMD_TOHOSTMAILBOXDATA_FWREADY) 1494 bwfm_sdio_readshared(sc); 1495 } 1496 1497 if (intstat & SDPCMD_INTSTATUS_HMB_FRAME_IND) { 1498 /* ignore receive indications while recovering */ 1499 if (dorecv && !sc->sc_rxskip) { 1500 DPRINTF(("%s: recv\n", DEVNAME(sc))); 1501 bwfm_sdio_rx_frames(sc); 1502 } 1503 } 1504 1505 if (intstat & SDPCMD_INTSTATUS_HMB_FC_STATE) 1506 dosend = false; 1507 1508 if (intstat & SDPCMD_INTSTATUS_HMB_FC_CHANGE) { 1509 if (dosend) { 1510 intstat = bwfm_sdio_dev_read(sc, BWFM_SDPCMD_INTSTATUS); 1511 DPRINTF(("%s: intstat2 0x%" PRIx32 "\n", DEVNAME(sc), intstat)); 1512 if (intstat & (SDPCMD_INTSTATUS_HMB_FC_STATE | SDPCMD_INTSTATUS_HMB_FC_CHANGE)) 1513 dosend = false; 1514 } 1515 } 1516 1517 if (!dosend && MBUFQ_FIRST(&sc->sc_tx_queue)) printf("%s: flowctl\n", DEVNAME(sc)); 1518 if (dosend && MBUFQ_FIRST(&sc->sc_tx_queue)) { 1519 DPRINTF(("%s: xmit\n", DEVNAME(sc))); 1520 bwfm_sdio_tx_frames(sc); 1521 } 1522 } 1523 1524 static int 1525 bwfm_sdio_tx_ok(struct bwfm_sdio_softc *sc) 1526 { 1527 return (uint8_t)(sc->sc_tx_max_seq - sc->sc_tx_seq) != 0 && 1528 ((uint8_t)(sc->sc_tx_max_seq - sc->sc_tx_seq) & 0x80) == 0; 1529 } 1530 1531 static void 1532 bwfm_sdio_tx_frames(struct bwfm_sdio_softc *sc) 1533 { 1534 struct mbuf *m; 1535 struct ifnet *ifp = sc->sc_sc.sc_ic.ic_ifp; 1536 bool ifstart = false; 1537 int i; 1538 1539 if (!bwfm_sdio_tx_ok(sc)) 1540 return; 1541 1542 i = uimin((uint8_t)(sc->sc_tx_max_seq - sc->sc_tx_seq), 32); 1543 while (i--) { 1544 MBUFQ_DEQUEUE(&sc->sc_tx_queue, m); 1545 if (m == NULL) 1546 break; 1547 1548 if (m->m_type == MT_CONTROL) 1549 bwfm_sdio_tx_ctrlframe(sc, m); 1550 else { 1551 bwfm_sdio_tx_dataframe(sc, m); 1552 if_statinc(ifp, if_opackets); 1553 ifstart = true; 1554 } 1555 1556 m_freem(m); 1557 } 1558 1559 if (ifstart) { 1560 ifp->if_flags &= ~IFF_OACTIVE; 1561 if_schedule_deferred_start(ifp); 1562 } 1563 } 1564 1565 static void 1566 bwfm_sdio_tx_ctrlframe(struct bwfm_sdio_softc *sc, struct mbuf *m) 1567 { 1568 struct bwfm_sdio_hwhdr *hwhdr; 1569 struct bwfm_sdio_swhdr *swhdr; 1570 size_t len, roundto; 1571 1572 len = sizeof(*hwhdr) + sizeof(*swhdr) + m->m_len; 1573 1574 /* Zero-pad to either block-size or 4-byte alignment. */ 1575 if (len > 512 && (len % 512) != 0) 1576 roundto = 512; 1577 else 1578 roundto = 4; 1579 1580 KASSERT(roundup(len, roundto) <= sc->sc_bounce_size); 1581 1582 hwhdr = (void *)sc->sc_bounce_buf; 1583 hwhdr->frmlen = htole16(len); 1584 hwhdr->cksum = htole16(~len); 1585 1586 swhdr = (void *)&hwhdr[1]; 1587 swhdr->seqnr = sc->sc_tx_seq++; 1588 swhdr->chanflag = BWFM_SDIO_SWHDR_CHANNEL_CONTROL; 1589 swhdr->nextlen = 0; 1590 swhdr->dataoff = sizeof(*hwhdr) + sizeof(*swhdr); 1591 swhdr->maxseqnr = 0; 1592 1593 m_copydata(m, 0, m->m_len, &swhdr[1]); 1594 1595 if (roundup(len, roundto) != len) 1596 memset(sc->sc_bounce_buf + len, 0, 1597 roundup(len, roundto) - len); 1598 1599 bwfm_sdio_frame_read_write(sc, sc->sc_bounce_buf, 1600 roundup(len, roundto), 1); 1601 } 1602 1603 static void 1604 bwfm_sdio_tx_dataframe(struct bwfm_sdio_softc *sc, struct mbuf *m) 1605 { 1606 struct bwfm_sdio_hwhdr *hwhdr; 1607 struct bwfm_sdio_swhdr *swhdr; 1608 struct bwfm_proto_bcdc_hdr *bcdc; 1609 size_t len, roundto; 1610 1611 len = sizeof(*hwhdr) + sizeof(*swhdr) + sizeof(*bcdc) 1612 + m->m_pkthdr.len; 1613 1614 /* Zero-pad to either block-size or 4-byte alignment. */ 1615 if (len > 512 && (len % 512) != 0) 1616 roundto = 512; 1617 else 1618 roundto = 4; 1619 1620 KASSERT(roundup(len, roundto) <= sc->sc_bounce_size); 1621 1622 hwhdr = (void *)sc->sc_bounce_buf; 1623 hwhdr->frmlen = htole16(len); 1624 hwhdr->cksum = htole16(~len); 1625 1626 swhdr = (void *)&hwhdr[1]; 1627 swhdr->seqnr = sc->sc_tx_seq++; 1628 swhdr->chanflag = BWFM_SDIO_SWHDR_CHANNEL_DATA; 1629 swhdr->nextlen = 0; 1630 swhdr->dataoff = sizeof(*hwhdr) + sizeof(*swhdr); 1631 swhdr->maxseqnr = 0; 1632 1633 bcdc = (void *)&swhdr[1]; 1634 bcdc->data_offset = 0; 1635 bcdc->priority = WME_AC_BE; 1636 bcdc->flags = BWFM_BCDC_FLAG_VER(BWFM_BCDC_FLAG_PROTO_VER); 1637 bcdc->flags2 = 0; 1638 1639 m_copydata(m, 0, m->m_pkthdr.len, &bcdc[1]); 1640 1641 if (roundup(len, roundto) != len) 1642 memset(sc->sc_bounce_buf + len, 0, 1643 roundup(len, roundto) - len); 1644 1645 bwfm_sdio_frame_read_write(sc, sc->sc_bounce_buf, 1646 roundup(len, roundto), 1); 1647 1648 sc->sc_tx_count--; 1649 } 1650 1651 static int 1652 bwfm_sdio_rxctl(struct bwfm_softc *bwfm, char *buf, size_t *lenp) 1653 { 1654 struct bwfm_sdio_softc *sc = (void *)bwfm; 1655 struct mbuf *m; 1656 int err = 0; 1657 1658 mutex_enter(&sc->sc_lock); 1659 while ((m = bwfm_qget(&sc->sc_rxctl_queue)) == NULL) { 1660 err = cv_timedwait(&sc->sc_rxctl_cv, &sc->sc_lock, 1661 mstohz(5000)); 1662 if (err == EWOULDBLOCK) 1663 break; 1664 } 1665 mutex_exit(&sc->sc_lock); 1666 1667 if (err) 1668 return 1; 1669 1670 if (m->m_len > *lenp) { 1671 m_freem(m); 1672 return 1; 1673 } 1674 1675 *lenp = m->m_len; 1676 m_copydata(m, 0, m->m_len, buf); 1677 m_freem(m); 1678 return 0; 1679 } 1680 1681 static void 1682 bwfm_sdio_rx_frames(struct bwfm_sdio_softc *sc) 1683 { 1684 struct bwfm_sdio_hwhdr *hwhdr; 1685 struct bwfm_sdio_swhdr *swhdr; 1686 struct bwfm_proto_bcdc_hdr *bcdc; 1687 uint16_t *sublen, nextlen = 0; 1688 struct mbuf *m; 1689 size_t flen, off, hoff; 1690 char *data; 1691 int nsub; 1692 size_t subsize; 1693 1694 hwhdr = (struct bwfm_sdio_hwhdr *)sc->sc_bounce_buf; 1695 swhdr = (struct bwfm_sdio_swhdr *)&hwhdr[1]; 1696 data = (char *)&swhdr[1]; 1697 1698 for (;;) { 1699 /* If we know the next size, just read ahead. */ 1700 if (nextlen) { 1701 if (bwfm_sdio_frame_read_write(sc, sc->sc_bounce_buf, 1702 nextlen, 0)) 1703 break; 1704 nextlen = 0; 1705 } else { 1706 if (bwfm_sdio_frame_read_write(sc, sc->sc_bounce_buf, 1707 sizeof(*hwhdr) + sizeof(*swhdr), 0)) 1708 break; 1709 } 1710 1711 hwhdr->frmlen = le16toh(hwhdr->frmlen); 1712 hwhdr->cksum = le16toh(hwhdr->cksum); 1713 1714 if (hwhdr->frmlen == 0 && hwhdr->cksum == 0) { 1715 break; 1716 } 1717 1718 if ((hwhdr->frmlen ^ hwhdr->cksum) != 0xffff) { 1719 printf("%s: checksum error\n", DEVNAME(sc)); 1720 break; 1721 } 1722 1723 if (hwhdr->frmlen < sizeof(*hwhdr) + sizeof(*swhdr)) { 1724 printf("%s: length error\n", DEVNAME(sc)); 1725 break; 1726 } 1727 1728 if (nextlen && hwhdr->frmlen > nextlen) { 1729 printf("%s: read ahead length error (%u > %u)\n", 1730 DEVNAME(sc), hwhdr->frmlen, nextlen); 1731 break; 1732 } 1733 1734 sc->sc_tx_max_seq = swhdr->maxseqnr; 1735 1736 flen = hwhdr->frmlen - (sizeof(*hwhdr) + sizeof(*swhdr)); 1737 if (flen == 0) { 1738 DPRINTF(("%s: empty payload (frmlen=%u)\n", 1739 DEVNAME(sc), hwhdr->frmlen)); 1740 nextlen = swhdr->nextlen << 4; 1741 continue; 1742 } 1743 1744 if (!nextlen) { 1745 KASSERT(roundup(flen, 4) <= sc->sc_bounce_size - 1746 (sizeof(*hwhdr) + sizeof(*swhdr))); 1747 if (bwfm_sdio_frame_read_write(sc, data, 1748 roundup(flen, 4), 0)) { 1749 printf("%s: I/O error roundup(%zu, 4) bytes\n", 1750 DEVNAME(sc), flen); 1751 break; 1752 } 1753 } 1754 1755 if (swhdr->dataoff < (sizeof(*hwhdr) + sizeof(*swhdr))) { 1756 printf("%s: data offset %u in header\n", 1757 DEVNAME(sc), swhdr->dataoff); 1758 break; 1759 } 1760 1761 off = swhdr->dataoff - (sizeof(*hwhdr) + sizeof(*swhdr)); 1762 if (off > flen) { 1763 printf("%s: offset %zu beyond end %zu\n", 1764 DEVNAME(sc), off, flen); 1765 break; 1766 } 1767 1768 switch (swhdr->chanflag & BWFM_SDIO_SWHDR_CHANNEL_MASK) { 1769 case BWFM_SDIO_SWHDR_CHANNEL_CONTROL: 1770 m = bwfm_sdio_newbuf(); 1771 if (m == NULL) 1772 break; 1773 if (flen - off > m->m_len) { 1774 printf("%s: ctl bigger than anticipated\n", 1775 DEVNAME(sc)); 1776 m_freem(m); 1777 break; 1778 } 1779 m->m_len = m->m_pkthdr.len = flen - off; 1780 memcpy(mtod(m, char *), data + off, flen - off); 1781 bwfm_qput(&sc->sc_rxctl_queue, m); 1782 cv_broadcast(&sc->sc_rxctl_cv); 1783 nextlen = swhdr->nextlen << 4; 1784 break; 1785 case BWFM_SDIO_SWHDR_CHANNEL_EVENT: 1786 case BWFM_SDIO_SWHDR_CHANNEL_DATA: 1787 m = bwfm_sdio_newbuf(); 1788 if (m == NULL) 1789 break; 1790 if (flen - off > m->m_len) { 1791 printf("%s: frame bigger than anticipated\n", 1792 DEVNAME(sc)); 1793 m_freem(m); 1794 break; 1795 } 1796 m->m_len = m->m_pkthdr.len = flen - off; 1797 memcpy(mtod(m, char *), data + off, flen - off); 1798 bcdc = mtod(m, struct bwfm_proto_bcdc_hdr *); 1799 hoff = sizeof(*bcdc) + ((size_t)bcdc->data_offset << 2); 1800 if (m->m_len < hoff) { 1801 printf("%s: short bcdc packet %d < %zu\n", 1802 DEVNAME(sc), m->m_len, hoff); 1803 m_freem(m); 1804 break; 1805 } 1806 m_adj(m, hoff); 1807 /* don't pass empty packet to stack */ 1808 if (m->m_len > 0) 1809 bwfm_rx(&sc->sc_sc, m); 1810 else 1811 m_freem(m); 1812 nextlen = swhdr->nextlen << 4; 1813 break; 1814 case BWFM_SDIO_SWHDR_CHANNEL_GLOM: 1815 if ((flen % sizeof(uint16_t)) != 0) { 1816 printf("%s: odd length (%zu) glom table\n", 1817 DEVNAME(sc), flen); 1818 break; 1819 } 1820 nsub = flen / sizeof(uint16_t); 1821 subsize = nsub * sizeof(uint16_t); 1822 sublen = NULL; 1823 nextlen = 0; 1824 if (subsize > 0) 1825 sublen = kmem_zalloc(subsize, KM_NOSLEEP); 1826 if (sublen != NULL) { 1827 memcpy(sublen, data, subsize); 1828 bwfm_sdio_rx_glom(sc, sublen, nsub, &nextlen); 1829 kmem_free(sublen, subsize); 1830 } 1831 break; 1832 default: 1833 printf("%s: unknown channel\n", DEVNAME(sc)); 1834 break; 1835 } 1836 } 1837 } 1838 1839 static void 1840 bwfm_sdio_rx_glom(struct bwfm_sdio_softc *sc, uint16_t *sublen, int nsub, 1841 uint16_t *nextlen) 1842 { 1843 struct bwfm_sdio_hwhdr hwhdr; 1844 struct bwfm_sdio_swhdr swhdr; 1845 struct bwfm_proto_bcdc_hdr *bcdc; 1846 struct mbuf *m, *m0; 1847 size_t flen, off, hoff; 1848 int i; 1849 1850 if (nsub == 0) 1851 return; 1852 1853 m0 = NULL; 1854 for (i = 0; i < nsub; i++) { 1855 m = bwfm_sdio_newbuf(); 1856 if (m == NULL) { 1857 m_freem(m0); 1858 return; 1859 } 1860 bwfm_qput(&m0, m); 1861 if (le16toh(sublen[i]) > m->m_len) { 1862 m_freem(m0); 1863 printf("%s: header larger than mbuf\n", DEVNAME(sc)); 1864 return; 1865 } 1866 if (bwfm_sdio_frame_read_write(sc, mtod(m, char *), 1867 le16toh(sublen[i]), 0)) { 1868 m_freem(m0); 1869 printf("%s: frame I/O error\n", DEVNAME(sc)); 1870 return; 1871 } 1872 m->m_len = m->m_pkthdr.len = le16toh(sublen[i]); 1873 } 1874 1875 if (m0->m_len >= sizeof(hwhdr) + sizeof(swhdr)) { 1876 m_copydata(m0, 0, sizeof(hwhdr), &hwhdr); 1877 m_copydata(m0, sizeof(hwhdr), sizeof(swhdr), &swhdr); 1878 1879 /* TODO: Verify actual superframe header */ 1880 1881 /* remove superframe header */ 1882 if (m0->m_len >= swhdr.dataoff) 1883 m_adj(m0, swhdr.dataoff); 1884 } 1885 1886 *nextlen = 0; 1887 while ((m = bwfm_qget(&m0)) != NULL) { 1888 if (m->m_len < sizeof(hwhdr) + sizeof(swhdr)) { 1889 printf("%s: tiny mbuf %d < %zu\n", DEVNAME(sc), 1890 m->m_len, sizeof(hwhdr) + sizeof(swhdr)); 1891 goto drop; 1892 } 1893 1894 m_copydata(m, 0, sizeof(hwhdr), &hwhdr); 1895 m_copydata(m, sizeof(hwhdr), sizeof(swhdr), &swhdr); 1896 1897 hwhdr.frmlen = le16toh(hwhdr.frmlen); 1898 hwhdr.cksum = le16toh(hwhdr.cksum); 1899 1900 if (hwhdr.frmlen == 0 && hwhdr.cksum == 0) 1901 goto drop; 1902 1903 if ((hwhdr.frmlen ^ hwhdr.cksum) != 0xffff) { 1904 printf("%s: checksum error\n", DEVNAME(sc)); 1905 goto drop; 1906 } 1907 1908 1909 if (hwhdr.frmlen < sizeof(hwhdr) + sizeof(swhdr)) { 1910 printf("%s: length error\n", DEVNAME(sc)); 1911 goto drop; 1912 } 1913 1914 flen = hwhdr.frmlen - (sizeof(hwhdr) + sizeof(swhdr)); 1915 if (flen == 0) 1916 goto drop; 1917 1918 if (hwhdr.frmlen > m->m_len) { 1919 printf("%s: short mbuf %d < %zu\n", 1920 DEVNAME(sc),m->m_len,flen); 1921 goto drop; 1922 } 1923 1924 if (swhdr.dataoff < (sizeof(hwhdr) + sizeof(swhdr))) { 1925 printf("%s: data offset %u in header\n", 1926 DEVNAME(sc), swhdr.dataoff); 1927 goto drop; 1928 } 1929 1930 off = swhdr.dataoff - (sizeof(hwhdr) + sizeof(swhdr)); 1931 if (off > flen) { 1932 printf("%s: offset %zu beyond end %zu\n", 1933 DEVNAME(sc), off, flen); 1934 goto drop; 1935 } 1936 1937 m_adj(m, (int)hwhdr.frmlen - m->m_len); 1938 *nextlen = swhdr.nextlen << 4; 1939 1940 switch (swhdr.chanflag & BWFM_SDIO_SWHDR_CHANNEL_MASK) { 1941 case BWFM_SDIO_SWHDR_CHANNEL_CONTROL: 1942 printf("%s: control channel not allowed in glom\n", 1943 DEVNAME(sc)); 1944 goto drop; 1945 case BWFM_SDIO_SWHDR_CHANNEL_EVENT: 1946 case BWFM_SDIO_SWHDR_CHANNEL_DATA: 1947 m_adj(m, swhdr.dataoff); 1948 bcdc = mtod(m, struct bwfm_proto_bcdc_hdr *); 1949 hoff = sizeof(*bcdc) + ((size_t)bcdc->data_offset << 2); 1950 if (m->m_len < hoff) { 1951 printf("%s: short bcdc packet %d < %zu\n", 1952 DEVNAME(sc), m->m_len, hoff); 1953 m_freem(m); 1954 break; 1955 } 1956 m_adj(m, hoff); 1957 /* don't pass empty packet to stack */ 1958 if (m->m_len == 0) { 1959 m_freem(m); 1960 break; 1961 } 1962 bwfm_rx(&sc->sc_sc, m); 1963 break; 1964 case BWFM_SDIO_SWHDR_CHANNEL_GLOM: 1965 printf("%s: glom not allowed in glom\n", 1966 DEVNAME(sc)); 1967 goto drop; 1968 default: 1969 printf("%s: unknown channel\n", DEVNAME(sc)); 1970 goto drop; 1971 } 1972 1973 continue; 1974 drop: 1975 printf("rx dropped %p len %d\n",mtod(m, char *),m->m_pkthdr.len); 1976 m_free(m); 1977 break; 1978 } 1979 } 1980 1981 #ifdef BWFM_DEBUG 1982 static void 1983 bwfm_sdio_debug_console(struct bwfm_sdio_softc *sc) 1984 { 1985 struct bwfm_sdio_console c; 1986 uint32_t newidx; 1987 int err; 1988 1989 if (!sc->sc_console_addr) 1990 return; 1991 1992 err = bwfm_sdio_ram_read_write(sc, sc->sc_console_addr, 1993 (char *)&c, sizeof(c), 0); 1994 if (err) 1995 return; 1996 1997 c.log_buf = le32toh(c.log_buf); 1998 c.log_bufsz = le32toh(c.log_bufsz); 1999 c.log_idx = le32toh(c.log_idx); 2000 2001 if (sc->sc_console_buf == NULL) { 2002 sc->sc_console_buf = malloc(c.log_bufsz, M_DEVBUF, 2003 M_WAITOK|M_ZERO); 2004 sc->sc_console_buf_size = c.log_bufsz; 2005 } 2006 2007 newidx = c.log_idx; 2008 if (newidx >= sc->sc_console_buf_size) 2009 return; 2010 2011 err = bwfm_sdio_ram_read_write(sc, c.log_buf, sc->sc_console_buf, 2012 sc->sc_console_buf_size, 0); 2013 if (err) 2014 return; 2015 2016 if (newidx != sc->sc_console_readidx) 2017 DPRINTFN(3, ("BWFM CONSOLE: ")); 2018 while (newidx != sc->sc_console_readidx) { 2019 uint8_t ch = sc->sc_console_buf[sc->sc_console_readidx]; 2020 sc->sc_console_readidx++; 2021 if (sc->sc_console_readidx == sc->sc_console_buf_size) 2022 sc->sc_console_readidx = 0; 2023 if (ch == '\r') 2024 continue; 2025 DPRINTFN(3, ("%c", ch)); 2026 } 2027 } 2028 #endif 2029