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