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