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