xref: /openbsd/sys/dev/sdmmc/if_bwfm_sdio.c (revision 3bef86f7)
1 /* $OpenBSD: if_bwfm_sdio.c,v 1.44 2022/04/06 18:59:30 naddy Exp $ */
2 /*
3  * Copyright (c) 2010-2016 Broadcom Corporation
4  * Copyright (c) 2016,2017 Patrick Wildt <patrick@blueri.se>
5  *
6  * Permission to use, copy, modify, and/or distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include "bpfilter.h"
20 
21 #include <sys/param.h>
22 #include <sys/systm.h>
23 #include <sys/buf.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/pool.h>
30 
31 #if defined(__HAVE_FDT)
32 #include <machine/fdt.h>
33 #include <dev/ofw/openfirm.h>
34 #endif
35 
36 #if NBPFILTER > 0
37 #include <net/bpf.h>
38 #endif
39 #include <net/if.h>
40 #include <net/if_dl.h>
41 #include <net/if_media.h>
42 
43 #include <netinet/in.h>
44 #include <netinet/if_ether.h>
45 
46 #include <net80211/ieee80211_var.h>
47 
48 #include <dev/sdmmc/sdmmcdevs.h>
49 #include <dev/sdmmc/sdmmcvar.h>
50 
51 #include <dev/ic/bwfmvar.h>
52 #include <dev/ic/bwfmreg.h>
53 #include <dev/sdmmc/if_bwfm_sdio.h>
54 
55 #define BWFM_SDIO_CCCR_BRCM_CARDCAP			0xf0
56 #define  BWFM_SDIO_CCCR_BRCM_CARDCAP_CMD14_SUPPORT	0x02
57 #define  BWFM_SDIO_CCCR_BRCM_CARDCAP_CMD14_EXT		0x04
58 #define  BWFM_SDIO_CCCR_BRCM_CARDCAP_CMD_NODEC		0x08
59 #define BWFM_SDIO_CCCR_BRCM_CARDCTRL			0xf1
60 #define  BWFM_SDIO_CCCR_BRCM_CARDCTRL_WLANRESET		0x02
61 #define BWFM_SDIO_CCCR_BRCM_SEPINT			0xf2
62 
63 /* #define BWFM_DEBUG */
64 #ifdef BWFM_DEBUG
65 #define DPRINTF(x)	do { if (bwfm_debug > 0) printf x; } while (0)
66 #define DPRINTFN(n, x)	do { if (bwfm_debug >= (n)) printf x; } while (0)
67 static int bwfm_debug = 1;
68 #else
69 #define DPRINTF(x)	do { ; } while (0)
70 #define DPRINTFN(n, x)	do { ; } while (0)
71 #endif
72 
73 #undef DEVNAME
74 #define DEVNAME(sc)	((sc)->sc_sc.sc_dev.dv_xname)
75 
76 enum bwfm_sdio_clkstate {
77 	CLK_NONE,
78 	CLK_SDONLY,
79 	CLK_PENDING,
80 	CLK_AVAIL,
81 };
82 
83 struct bwfm_sdio_softc {
84 	struct bwfm_softc	  sc_sc;
85 	struct sdmmc_function	**sc_sf;
86 	struct rwlock		 *sc_lock;
87 	void			 *sc_ih;
88 	int			  sc_oob;
89 
90 	int			  sc_initialized;
91 
92 	uint32_t		  sc_bar0;
93 	int			  sc_clkstate;
94 	int			  sc_alp_only;
95 	int			  sc_sr_enabled;
96 	uint32_t		  sc_console_addr;
97 
98 	char			 *sc_bounce_buf;
99 	size_t			  sc_bounce_size;
100 
101 	char			 *sc_console_buf;
102 	size_t			  sc_console_buf_size;
103 	uint32_t		  sc_console_readidx;
104 
105 	struct bwfm_core	 *sc_cc;
106 
107 	uint8_t			  sc_tx_seq;
108 	uint8_t			  sc_tx_max_seq;
109 	struct mbuf_list	  sc_tx_queue;
110 	int			  sc_tx_count;
111 
112 	struct task		  sc_task;
113 };
114 
115 int		 bwfm_sdio_match(struct device *, void *, void *);
116 void		 bwfm_sdio_attach(struct device *, struct device *, void *);
117 int		 bwfm_sdio_preinit(struct bwfm_softc *);
118 int		 bwfm_sdio_detach(struct device *, int);
119 
120 int		 bwfm_sdio_intr(void *);
121 int		 bwfm_sdio_oob_intr(void *);
122 void		 bwfm_sdio_task(void *);
123 int		 bwfm_sdio_load_microcode(struct bwfm_sdio_softc *,
124 		    u_char *, size_t, u_char *, size_t);
125 
126 void		 bwfm_sdio_clkctl(struct bwfm_sdio_softc *,
127 		    enum bwfm_sdio_clkstate, int);
128 void		 bwfm_sdio_htclk(struct bwfm_sdio_softc *, int, int);
129 void		 bwfm_sdio_readshared(struct bwfm_sdio_softc *);
130 
131 void		 bwfm_sdio_backplane(struct bwfm_sdio_softc *, uint32_t);
132 uint8_t		 bwfm_sdio_read_1(struct bwfm_sdio_softc *, uint32_t);
133 uint32_t	 bwfm_sdio_read_4(struct bwfm_sdio_softc *, uint32_t);
134 void		 bwfm_sdio_write_1(struct bwfm_sdio_softc *, uint32_t,
135 		    uint8_t);
136 void		 bwfm_sdio_write_4(struct bwfm_sdio_softc *, uint32_t,
137 		    uint32_t);
138 int		 bwfm_sdio_buf_read(struct bwfm_sdio_softc *,
139 		    struct sdmmc_function *, uint32_t, char *, size_t);
140 int		 bwfm_sdio_buf_write(struct bwfm_sdio_softc *,
141 		    struct sdmmc_function *, uint32_t, char *, size_t);
142 uint32_t	 bwfm_sdio_ram_read_write(struct bwfm_sdio_softc *,
143 		    uint32_t, char *, size_t, int);
144 uint32_t	 bwfm_sdio_frame_read_write(struct bwfm_sdio_softc *,
145 		    char *, size_t, int);
146 
147 uint32_t	 bwfm_sdio_dev_read(struct bwfm_sdio_softc *, uint32_t);
148 void		 bwfm_sdio_dev_write(struct bwfm_sdio_softc *, uint32_t,
149 		    uint32_t);
150 
151 uint32_t	 bwfm_sdio_buscore_read(struct bwfm_softc *, uint32_t);
152 void		 bwfm_sdio_buscore_write(struct bwfm_softc *, uint32_t,
153 		    uint32_t);
154 int		 bwfm_sdio_buscore_prepare(struct bwfm_softc *);
155 void		 bwfm_sdio_buscore_activate(struct bwfm_softc *, uint32_t);
156 
157 struct mbuf *	 bwfm_sdio_newbuf(void);
158 int		 bwfm_sdio_tx_ok(struct bwfm_sdio_softc *);
159 void		 bwfm_sdio_tx_frames(struct bwfm_sdio_softc *);
160 void		 bwfm_sdio_tx_ctrlframe(struct bwfm_sdio_softc *, struct mbuf *);
161 void		 bwfm_sdio_tx_dataframe(struct bwfm_sdio_softc *, struct mbuf *);
162 void		 bwfm_sdio_rx_frames(struct bwfm_sdio_softc *);
163 void		 bwfm_sdio_rx_glom(struct bwfm_sdio_softc *, uint16_t *, int,
164 		    uint16_t *, struct mbuf_list *);
165 
166 int		 bwfm_sdio_txcheck(struct bwfm_softc *);
167 int		 bwfm_sdio_txdata(struct bwfm_softc *, struct mbuf *);
168 int		 bwfm_sdio_txctl(struct bwfm_softc *, void *);
169 
170 #ifdef BWFM_DEBUG
171 void		 bwfm_sdio_debug_console(struct bwfm_sdio_softc *);
172 #endif
173 
174 struct bwfm_bus_ops bwfm_sdio_bus_ops = {
175 	.bs_preinit = bwfm_sdio_preinit,
176 	.bs_stop = NULL,
177 	.bs_txcheck = bwfm_sdio_txcheck,
178 	.bs_txdata = bwfm_sdio_txdata,
179 	.bs_txctl = bwfm_sdio_txctl,
180 };
181 
182 struct bwfm_buscore_ops bwfm_sdio_buscore_ops = {
183 	.bc_read = bwfm_sdio_buscore_read,
184 	.bc_write = bwfm_sdio_buscore_write,
185 	.bc_prepare = bwfm_sdio_buscore_prepare,
186 	.bc_reset = NULL,
187 	.bc_setup = NULL,
188 	.bc_activate = bwfm_sdio_buscore_activate,
189 };
190 
191 const struct cfattach bwfm_sdio_ca = {
192 	sizeof(struct bwfm_sdio_softc),
193 	bwfm_sdio_match,
194 	bwfm_sdio_attach,
195 	bwfm_sdio_detach,
196 };
197 
198 int
199 bwfm_sdio_match(struct device *parent, void *match, void *aux)
200 {
201 	struct sdmmc_attach_args *saa = aux;
202 	struct sdmmc_function *sf = saa->sf;
203 	struct sdmmc_cis *cis;
204 
205 	/* Not SDIO. */
206 	if (sf == NULL)
207 		return 0;
208 
209 	/* Look for Broadcom. */
210 	cis = &sf->sc->sc_fn0->cis;
211 	if (cis->manufacturer != SDMMC_VENDOR_BROADCOM)
212 		return 0;
213 
214 	/* Look for supported chips. */
215 	switch (cis->product) {
216 	case SDMMC_PRODUCT_BROADCOM_BCM4324:
217 	case SDMMC_PRODUCT_BROADCOM_BCM4329:
218 	case SDMMC_PRODUCT_BROADCOM_BCM4330:
219 	case SDMMC_PRODUCT_BROADCOM_BCM4334:
220 	case SDMMC_PRODUCT_BROADCOM_BCM4335:
221 	case SDMMC_PRODUCT_BROADCOM_BCM4339:
222 	case SDMMC_PRODUCT_BROADCOM_BCM4345:
223 	case SDMMC_PRODUCT_BROADCOM_BCM4354:
224 	case SDMMC_PRODUCT_BROADCOM_BCM4356:
225 	case SDMMC_PRODUCT_BROADCOM_BCM4359:
226 	case SDMMC_PRODUCT_BROADCOM_BCM43143:
227 	case SDMMC_PRODUCT_BROADCOM_BCM43340:
228 	case SDMMC_PRODUCT_BROADCOM_BCM43341:
229 	case SDMMC_PRODUCT_BROADCOM_BCM43362:
230 	case SDMMC_PRODUCT_BROADCOM_BCM43430:
231 	case SDMMC_PRODUCT_BROADCOM_BCM43364:
232 		break;
233 	default:
234 		return 0;
235 	}
236 
237 	/* We need both functions, but ... */
238 	if (sf->sc->sc_function_count <= 1)
239 		return 0;
240 
241 	/* ... only attach for one. */
242 	if (sf->number != 1)
243 		return 0;
244 
245 	return 1;
246 }
247 
248 void
249 bwfm_sdio_attach(struct device *parent, struct device *self, void *aux)
250 {
251 	struct bwfm_sdio_softc *sc = (struct bwfm_sdio_softc *)self;
252 	struct sdmmc_attach_args *saa = aux;
253 	struct sdmmc_function *sf = saa->sf;
254 	struct bwfm_core *core;
255 	uint32_t reg;
256 
257 	printf("\n");
258 
259 #if defined(__HAVE_FDT)
260 	if (sf->cookie)
261 		sc->sc_sc.sc_node = *(int *)sf->cookie;
262 #endif
263 
264 	task_set(&sc->sc_task, bwfm_sdio_task, sc);
265 	ml_init(&sc->sc_tx_queue);
266 	sc->sc_bounce_size = 64 * 1024;
267 	sc->sc_bounce_buf = dma_alloc(sc->sc_bounce_size, PR_WAITOK);
268 	sc->sc_tx_seq = 0xff;
269 
270 	rw_assert_wrlock(&sf->sc->sc_lock);
271 	sc->sc_lock = &sf->sc->sc_lock;
272 
273 	sc->sc_sf = mallocarray(sf->sc->sc_function_count + 1,
274 	    sizeof(struct sdmmc_function *), M_DEVBUF, M_WAITOK);
275 
276 	/* Copy all function pointers. */
277 	SIMPLEQ_FOREACH(sf, &saa->sf->sc->sf_head, sf_list) {
278 		sc->sc_sf[sf->number] = sf;
279 	}
280 	sf = saa->sf;
281 
282 	sdmmc_io_set_blocklen(sc->sc_sf[1], 64);
283 	sdmmc_io_set_blocklen(sc->sc_sf[2], 512);
284 
285 	/* Enable Function 1. */
286 	if (sdmmc_io_function_enable(sc->sc_sf[1]) != 0) {
287 		printf("%s: cannot enable function 1\n", DEVNAME(sc));
288 		goto err;
289 	}
290 
291 	DPRINTF(("%s: F1 signature read @0x18000000=%x\n", DEVNAME(sc),
292 	    bwfm_sdio_read_4(sc, 0x18000000)));
293 
294 	/* Force PLL off */
295 	bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR,
296 	    BWFM_SDIO_FUNC1_CHIPCLKCSR_FORCE_HW_CLKREQ_OFF |
297 	    BWFM_SDIO_FUNC1_CHIPCLKCSR_ALP_AVAIL_REQ);
298 
299 	sc->sc_sc.sc_buscore_ops = &bwfm_sdio_buscore_ops;
300 	if (bwfm_chip_attach(&sc->sc_sc) != 0) {
301 		printf("%s: cannot attach chip\n", DEVNAME(sc));
302 		goto err;
303 	}
304 
305 	sc->sc_cc = bwfm_chip_get_core(&sc->sc_sc, BWFM_AGENT_CORE_CHIPCOMMON);
306 	if (sc->sc_cc == NULL) {
307 		printf("%s: cannot find chipcommon core\n", DEVNAME(sc));
308 		goto err;
309 	}
310 
311 	core = bwfm_chip_get_core(&sc->sc_sc, BWFM_AGENT_CORE_SDIO_DEV);
312 	if (core->co_rev >= 12) {
313 		reg = bwfm_sdio_read_1(sc, BWFM_SDIO_FUNC1_SLEEPCSR);
314 		if (!(reg & BWFM_SDIO_FUNC1_SLEEPCSR_KSO)) {
315 			reg |= BWFM_SDIO_FUNC1_SLEEPCSR_KSO;
316 			bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_SLEEPCSR, reg);
317 		}
318 	}
319 
320 	/* TODO: drive strength */
321 
322 	bwfm_sdio_write_1(sc, BWFM_SDIO_CCCR_BRCM_CARDCTRL,
323 	    bwfm_sdio_read_1(sc, BWFM_SDIO_CCCR_BRCM_CARDCTRL) |
324 	    BWFM_SDIO_CCCR_BRCM_CARDCTRL_WLANRESET);
325 
326 	core = bwfm_chip_get_pmu(&sc->sc_sc);
327 	bwfm_sdio_write_4(sc, core->co_base + BWFM_CHIP_REG_PMUCONTROL,
328 	    bwfm_sdio_read_4(sc, core->co_base + BWFM_CHIP_REG_PMUCONTROL) |
329 	    (BWFM_CHIP_REG_PMUCONTROL_RES_RELOAD <<
330 	     BWFM_CHIP_REG_PMUCONTROL_RES_SHIFT));
331 
332 	sdmmc_io_function_disable(sc->sc_sf[2]);
333 
334 	bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR, 0);
335 	sc->sc_clkstate = CLK_SDONLY;
336 
337 	sc->sc_sc.sc_bus_ops = &bwfm_sdio_bus_ops;
338 	sc->sc_sc.sc_proto_ops = &bwfm_proto_bcdc_ops;
339 	bwfm_attach(&sc->sc_sc);
340 	config_mountroot(self, bwfm_attachhook);
341 	return;
342 
343 err:
344 	free(sc->sc_sf, M_DEVBUF, 0);
345 }
346 
347 int
348 bwfm_sdio_preinit(struct bwfm_softc *bwfm)
349 {
350 	struct bwfm_sdio_softc *sc = (void *)bwfm;
351 	const char *chip = NULL;
352 	uint32_t clk, reg;
353 	u_char *ucode, *nvram;
354 	size_t size = 0, nvsize, nvlen = 0;
355 
356 	if (sc->sc_initialized)
357 		return 0;
358 
359 	rw_enter_write(sc->sc_lock);
360 
361 	switch (bwfm->sc_chip.ch_chip)
362 	{
363 	case BRCM_CC_43241_CHIP_ID:
364 		if (bwfm->sc_chip.ch_chiprev <= 4)
365 			chip = "43241b0";
366 		else if (bwfm->sc_chip.ch_chiprev == 5)
367 			chip = "43241b4";
368 		else
369 			chip = "43241b5";
370 		break;
371 	case BRCM_CC_4330_CHIP_ID:
372 		chip = "4330";
373 		break;
374 	case BRCM_CC_4334_CHIP_ID:
375 		chip = "4334";
376 		break;
377 	case BRCM_CC_4345_CHIP_ID:
378 		if (bwfm->sc_chip.ch_chiprev == 9)
379 			chip = "43456";
380 		else
381 			chip = "43455";
382 		break;
383 	case BRCM_CC_43340_CHIP_ID:
384 	case BRCM_CC_43341_CHIP_ID:
385 		chip = "43340";
386 		break;
387 	case BRCM_CC_4335_CHIP_ID:
388 		if (bwfm->sc_chip.ch_chiprev < 2)
389 			chip = "4335";
390 		else
391 			chip = "4339";
392 		break;
393 	case BRCM_CC_4339_CHIP_ID:
394 		chip = "4339";
395 		break;
396 	case BRCM_CC_43430_CHIP_ID:
397 		if (bwfm->sc_chip.ch_chiprev == 0)
398 			chip = "43430a0";
399 		else if (bwfm->sc_chip.ch_chiprev == 2)
400 			chip = "43436";
401 		else
402 			chip = "43430";
403 		break;
404 	case BRCM_CC_4356_CHIP_ID:
405 		chip = "4356";
406 		break;
407 	case BRCM_CC_4359_CHIP_ID:
408 		chip = "4359";
409 		break;
410 	default:
411 		printf("%s: unknown firmware for chip %s\n",
412 		    DEVNAME(sc), bwfm->sc_chip.ch_name);
413 		goto err;
414 	}
415 
416 	if (bwfm_loadfirmware(bwfm, chip, "-sdio", &ucode, &size,
417 	    &nvram, &nvsize, &nvlen) != 0)
418 		goto err;
419 
420 	sc->sc_alp_only = 1;
421 	if (bwfm_sdio_load_microcode(sc, ucode, size,
422 	    nvram, nvlen) != 0) {
423 		printf("%s: could not load microcode\n",
424 		    DEVNAME(sc));
425 		free(ucode, M_DEVBUF, size);
426 		free(nvram, M_DEVBUF, nvsize);
427 		goto err;
428 	}
429 	sc->sc_alp_only = 0;
430 	free(ucode, M_DEVBUF, size);
431 	free(nvram, M_DEVBUF, nvsize);
432 
433 	bwfm_sdio_clkctl(sc, CLK_AVAIL, 0);
434 	if (sc->sc_clkstate != CLK_AVAIL)
435 		goto err;
436 
437 	clk = bwfm_sdio_read_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR);
438 	bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR,
439 	    clk | BWFM_SDIO_FUNC1_CHIPCLKCSR_FORCE_HT);
440 
441 	bwfm_sdio_dev_write(sc, SDPCMD_TOSBMAILBOXDATA,
442 	    SDPCM_PROT_VERSION << SDPCM_PROT_VERSION_SHIFT);
443 	if (sdmmc_io_function_enable(sc->sc_sf[2]) != 0) {
444 		printf("%s: cannot enable function 2\n", DEVNAME(sc));
445 		goto err;
446 	}
447 
448 	bwfm_sdio_dev_write(sc, SDPCMD_HOSTINTMASK,
449 	    SDPCMD_INTSTATUS_HMB_SW_MASK|SDPCMD_INTSTATUS_CHIPACTIVE);
450 	bwfm_sdio_write_1(sc, BWFM_SDIO_WATERMARK, 8);
451 
452 	if (bwfm_chip_sr_capable(bwfm)) {
453 		reg = bwfm_sdio_read_1(sc, BWFM_SDIO_FUNC1_WAKEUPCTRL);
454 		reg |= BWFM_SDIO_FUNC1_WAKEUPCTRL_HTWAIT;
455 		bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_WAKEUPCTRL, reg);
456 		bwfm_sdio_write_1(sc, BWFM_SDIO_CCCR_CARDCAP,
457 		    BWFM_SDIO_CCCR_CARDCAP_CMD14_SUPPORT |
458 		    BWFM_SDIO_CCCR_CARDCAP_CMD14_EXT);
459 		bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR,
460 		    BWFM_SDIO_FUNC1_CHIPCLKCSR_FORCE_HT);
461 		sc->sc_sr_enabled = 1;
462 	} else {
463 		bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR, clk);
464 	}
465 
466 #if defined(__HAVE_FDT)
467 	if (sc->sc_sc.sc_node) {
468 		sc->sc_ih = fdt_intr_establish(sc->sc_sc.sc_node,
469 		    IPL_NET, bwfm_sdio_oob_intr, sc, DEVNAME(sc));
470 		if (sc->sc_ih != NULL) {
471 			bwfm_sdio_write_1(sc, BWFM_SDIO_CCCR_SEPINT,
472 			    BWFM_SDIO_CCCR_SEPINT_MASK |
473 			    BWFM_SDIO_CCCR_SEPINT_OE |
474 			    BWFM_SDIO_CCCR_SEPINT_ACT_HI);
475 			sc->sc_oob = 1;
476 		}
477 	}
478 	if (sc->sc_ih == NULL)
479 #endif
480 	sc->sc_ih = sdmmc_intr_establish(bwfm->sc_dev.dv_parent,
481 	    bwfm_sdio_intr, sc, DEVNAME(sc));
482 	if (sc->sc_ih == NULL) {
483 		printf("%s: can't establish interrupt\n", DEVNAME(sc));
484 		bwfm_sdio_clkctl(sc, CLK_NONE, 0);
485 		goto err;
486 	}
487 	sdmmc_intr_enable(sc->sc_sf[1]);
488 	rw_exit(sc->sc_lock);
489 
490 	sc->sc_initialized = 1;
491 	return 0;
492 
493 err:
494 	rw_exit(sc->sc_lock);
495 	return 1;
496 }
497 
498 int
499 bwfm_sdio_load_microcode(struct bwfm_sdio_softc *sc, u_char *ucode, size_t size,
500     u_char *nvram, size_t nvlen)
501 {
502 	struct bwfm_softc *bwfm = (void *)sc;
503 	char *verify = NULL;
504 	int err = 0;
505 
506 	bwfm_sdio_clkctl(sc, CLK_AVAIL, 0);
507 
508 	/* Upload firmware */
509 	err = bwfm_sdio_ram_read_write(sc, bwfm->sc_chip.ch_rambase,
510 	    ucode, size, 1);
511 	if (err)
512 		goto out;
513 
514 	/* Verify firmware */
515 	verify = malloc(size, M_TEMP, M_WAITOK | M_ZERO);
516 	err = bwfm_sdio_ram_read_write(sc, bwfm->sc_chip.ch_rambase,
517 	    verify, size, 0);
518 	if (err || memcmp(verify, ucode, size)) {
519 		printf("%s: firmware verification failed\n",
520 		    DEVNAME(sc));
521 		free(verify, M_TEMP, size);
522 		goto out;
523 	}
524 	free(verify, M_TEMP, size);
525 
526 	/* Upload nvram */
527 	err = bwfm_sdio_ram_read_write(sc, bwfm->sc_chip.ch_rambase +
528 	    bwfm->sc_chip.ch_ramsize - nvlen, nvram, nvlen, 1);
529 	if (err)
530 		goto out;
531 
532 	/* Verify nvram */
533 	verify = malloc(nvlen, M_TEMP, M_WAITOK | M_ZERO);
534 	err = bwfm_sdio_ram_read_write(sc, bwfm->sc_chip.ch_rambase +
535 	    bwfm->sc_chip.ch_ramsize - nvlen, verify, nvlen, 0);
536 	if (err || memcmp(verify, nvram, nvlen)) {
537 		printf("%s: nvram verification failed\n",
538 		    DEVNAME(sc));
539 		free(verify, M_TEMP, nvlen);
540 		goto out;
541 	}
542 	free(verify, M_TEMP, nvlen);
543 
544 	/* Load reset vector from firmware and kickstart core. */
545 	bwfm_chip_set_active(bwfm, *(uint32_t *)ucode);
546 
547 out:
548 	bwfm_sdio_clkctl(sc, CLK_SDONLY, 0);
549 	return err;
550 }
551 
552 void
553 bwfm_sdio_clkctl(struct bwfm_sdio_softc *sc, enum bwfm_sdio_clkstate newstate,
554     int pendok)
555 {
556 	enum bwfm_sdio_clkstate oldstate;
557 
558 	oldstate = sc->sc_clkstate;
559 	if (sc->sc_clkstate == newstate)
560 		return;
561 
562 	switch (newstate) {
563 	case CLK_AVAIL:
564 		if (sc->sc_clkstate == CLK_NONE)
565 			sc->sc_clkstate = CLK_SDONLY;
566 		bwfm_sdio_htclk(sc, 1, pendok);
567 		break;
568 	case CLK_SDONLY:
569 		if (sc->sc_clkstate == CLK_NONE)
570 			sc->sc_clkstate = CLK_SDONLY;
571 		else if (sc->sc_clkstate == CLK_AVAIL)
572 			bwfm_sdio_htclk(sc, 0, 0);
573 		else
574 			printf("%s: request for %d -> %d\n",
575 			    DEVNAME(sc), sc->sc_clkstate, newstate);
576 		break;
577 	case CLK_NONE:
578 		if (sc->sc_clkstate == CLK_AVAIL)
579 			bwfm_sdio_htclk(sc, 0, 0);
580 		sc->sc_clkstate = CLK_NONE;
581 		break;
582 	default:
583 		break;
584 	}
585 
586 	DPRINTF(("%s: %d -> %d = %d\n", DEVNAME(sc), oldstate, newstate,
587 	    sc->sc_clkstate));
588 }
589 
590 void
591 bwfm_sdio_htclk(struct bwfm_sdio_softc *sc, int on, int pendok)
592 {
593 	uint32_t clkctl, devctl, req;
594 	int i;
595 
596 	if (sc->sc_sr_enabled) {
597 		if (on)
598 			sc->sc_clkstate = CLK_AVAIL;
599 		else
600 			sc->sc_clkstate = CLK_SDONLY;
601 		return;
602 	}
603 
604 	if (on) {
605 		if (sc->sc_alp_only)
606 			req = BWFM_SDIO_FUNC1_CHIPCLKCSR_ALP_AVAIL_REQ;
607 		else
608 			req = BWFM_SDIO_FUNC1_CHIPCLKCSR_HT_AVAIL_REQ;
609 		bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR, req);
610 
611 		clkctl = bwfm_sdio_read_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR);
612 		if (!BWFM_SDIO_FUNC1_CHIPCLKCSR_CLKAV(clkctl, sc->sc_alp_only)
613 		    && pendok) {
614 			devctl = bwfm_sdio_read_1(sc, BWFM_SDIO_DEVICE_CTL);
615 			devctl |= BWFM_SDIO_DEVICE_CTL_CA_INT_ONLY;
616 			bwfm_sdio_write_1(sc, BWFM_SDIO_DEVICE_CTL, devctl);
617 			sc->sc_clkstate = CLK_PENDING;
618 			return;
619 		} else if (sc->sc_clkstate == CLK_PENDING) {
620 			devctl = bwfm_sdio_read_1(sc, BWFM_SDIO_DEVICE_CTL);
621 			devctl &= ~BWFM_SDIO_DEVICE_CTL_CA_INT_ONLY;
622 			bwfm_sdio_write_1(sc, BWFM_SDIO_DEVICE_CTL, devctl);
623 		}
624 
625 		for (i = 0; i < 5000; i++) {
626 			if (BWFM_SDIO_FUNC1_CHIPCLKCSR_CLKAV(clkctl,
627 			    sc->sc_alp_only))
628 				break;
629 			clkctl = bwfm_sdio_read_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR);
630 			delay(1000);
631 		}
632 		if (!BWFM_SDIO_FUNC1_CHIPCLKCSR_CLKAV(clkctl, sc->sc_alp_only)) {
633 			printf("%s: HT avail timeout\n", DEVNAME(sc));
634 			return;
635 		}
636 
637 		sc->sc_clkstate = CLK_AVAIL;
638 	} else {
639 		if (sc->sc_clkstate == CLK_PENDING) {
640 			devctl = bwfm_sdio_read_1(sc, BWFM_SDIO_DEVICE_CTL);
641 			devctl &= ~BWFM_SDIO_DEVICE_CTL_CA_INT_ONLY;
642 			bwfm_sdio_write_1(sc, BWFM_SDIO_DEVICE_CTL, devctl);
643 		}
644 		sc->sc_clkstate = CLK_SDONLY;
645 		bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR, 0);
646 	}
647 }
648 
649 void
650 bwfm_sdio_readshared(struct bwfm_sdio_softc *sc)
651 {
652 	struct bwfm_softc *bwfm = (void *)sc;
653 	struct bwfm_sdio_sdpcm sdpcm;
654 	uint32_t addr, shaddr;
655 	int err;
656 
657 	shaddr = bwfm->sc_chip.ch_rambase + bwfm->sc_chip.ch_ramsize - 4;
658 	if (!bwfm->sc_chip.ch_rambase && bwfm_chip_sr_capable(bwfm))
659 		shaddr -= bwfm->sc_chip.ch_srsize;
660 
661 	err = bwfm_sdio_ram_read_write(sc, shaddr, (char *)&addr,
662 	    sizeof(addr), 0);
663 	if (err)
664 		return;
665 
666 	addr = letoh32(addr);
667 	if (addr == 0 || ((~addr >> 16) & 0xffff) == (addr & 0xffff))
668 		return;
669 
670 	err = bwfm_sdio_ram_read_write(sc, addr, (char *)&sdpcm,
671 	    sizeof(sdpcm), 0);
672 	if (err)
673 		return;
674 
675 	sc->sc_console_addr = letoh32(sdpcm.console_addr);
676 }
677 
678 int
679 bwfm_sdio_intr(void *v)
680 {
681 	bwfm_sdio_task(v);
682 	return 1;
683 }
684 
685 #if defined(__HAVE_FDT)
686 int
687 bwfm_sdio_oob_intr(void *v)
688 {
689 	struct bwfm_sdio_softc *sc = (void *)v;
690 	if (!sc->sc_oob)
691 		return 0;
692 	fdt_intr_disable(sc->sc_ih);
693 	task_add(systq, &sc->sc_task);
694 	return 1;
695 }
696 #endif
697 
698 void
699 bwfm_sdio_task(void *v)
700 {
701 	struct bwfm_sdio_softc *sc = (void *)v;
702 	uint32_t clkctl, devctl, intstat, hostint;
703 
704 	rw_enter_write(sc->sc_lock);
705 
706 	if (!sc->sc_sr_enabled && sc->sc_clkstate == CLK_PENDING) {
707 		clkctl = bwfm_sdio_read_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR);
708 		if (BWFM_SDIO_FUNC1_CHIPCLKCSR_HTAV(clkctl)) {
709 			devctl = bwfm_sdio_read_1(sc, BWFM_SDIO_DEVICE_CTL);
710 			devctl &= ~BWFM_SDIO_DEVICE_CTL_CA_INT_ONLY;
711 			bwfm_sdio_write_1(sc, BWFM_SDIO_DEVICE_CTL, devctl);
712 			sc->sc_clkstate = CLK_AVAIL;
713 		}
714 	}
715 
716 	intstat = bwfm_sdio_dev_read(sc, BWFM_SDPCMD_INTSTATUS);
717 	intstat &= (SDPCMD_INTSTATUS_HMB_SW_MASK|SDPCMD_INTSTATUS_CHIPACTIVE);
718 	/* XXX fc state */
719 	if (intstat)
720 		bwfm_sdio_dev_write(sc, BWFM_SDPCMD_INTSTATUS, intstat);
721 
722 	if (intstat & SDPCMD_INTSTATUS_HMB_HOST_INT) {
723 		hostint = bwfm_sdio_dev_read(sc, SDPCMD_TOHOSTMAILBOXDATA);
724 		bwfm_sdio_dev_write(sc, SDPCMD_TOSBMAILBOX,
725 		    SDPCMD_TOSBMAILBOX_INT_ACK);
726 		if (hostint & SDPCMD_TOHOSTMAILBOXDATA_NAKHANDLED)
727 			intstat |= SDPCMD_INTSTATUS_HMB_FRAME_IND;
728 		if (hostint & SDPCMD_TOHOSTMAILBOXDATA_DEVREADY ||
729 		    hostint & SDPCMD_TOHOSTMAILBOXDATA_FWREADY)
730 			bwfm_sdio_readshared(sc);
731 	}
732 
733 	/* FIXME: Might stall if we don't when not set. */
734 	if (1 || intstat & SDPCMD_INTSTATUS_HMB_FRAME_IND) {
735 		bwfm_sdio_rx_frames(sc);
736 	}
737 
738 	if (!ml_empty(&sc->sc_tx_queue)) {
739 		bwfm_sdio_tx_frames(sc);
740 	}
741 
742 #ifdef BWFM_DEBUG
743 	bwfm_sdio_debug_console(sc);
744 #endif
745 
746 	rw_exit(sc->sc_lock);
747 
748 #if defined(__HAVE_FDT)
749 	if (sc->sc_oob)
750 		fdt_intr_enable(sc->sc_ih);
751 #endif
752 }
753 
754 int
755 bwfm_sdio_detach(struct device *self, int flags)
756 {
757 	struct bwfm_sdio_softc *sc = (struct bwfm_sdio_softc *)self;
758 
759 	bwfm_detach(&sc->sc_sc, flags);
760 
761 	dma_free(sc->sc_bounce_buf, sc->sc_bounce_size);
762 	free(sc->sc_sf, M_DEVBUF, 0);
763 
764 	return 0;
765 }
766 
767 void
768 bwfm_sdio_backplane(struct bwfm_sdio_softc *sc, uint32_t bar0)
769 {
770 	if (sc->sc_bar0 == bar0)
771 		return;
772 
773 	bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_SBADDRLOW,
774 	    (bar0 >>  8) & 0x80);
775 	bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_SBADDRMID,
776 	    (bar0 >> 16) & 0xff);
777 	bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_SBADDRHIGH,
778 	    (bar0 >> 24) & 0xff);
779 	sc->sc_bar0 = bar0;
780 }
781 
782 uint8_t
783 bwfm_sdio_read_1(struct bwfm_sdio_softc *sc, uint32_t addr)
784 {
785 	struct sdmmc_function *sf;
786 	uint8_t rv;
787 
788 	/*
789 	 * figure out how to read the register based on address range
790 	 * 0x00 ~ 0x7FF: function 0 CCCR and FBR
791 	 * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers
792 	 * The rest: function 1 silicon backplane core registers
793 	 */
794 	if ((addr & ~0x7ff) == 0)
795 		sf = sc->sc_sf[0];
796 	else
797 		sf = sc->sc_sf[1];
798 
799 	rv = sdmmc_io_read_1(sf, addr);
800 	return rv;
801 }
802 
803 uint32_t
804 bwfm_sdio_read_4(struct bwfm_sdio_softc *sc, uint32_t addr)
805 {
806 	struct sdmmc_function *sf;
807 	uint32_t bar0 = addr & ~BWFM_SDIO_SB_OFT_ADDR_MASK;
808 	uint32_t rv;
809 
810 	bwfm_sdio_backplane(sc, bar0);
811 
812 	addr &= BWFM_SDIO_SB_OFT_ADDR_MASK;
813 	addr |= BWFM_SDIO_SB_ACCESS_2_4B_FLAG;
814 
815 	/*
816 	 * figure out how to read the register based on address range
817 	 * 0x00 ~ 0x7FF: function 0 CCCR and FBR
818 	 * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers
819 	 * The rest: function 1 silicon backplane core registers
820 	 */
821 	if ((addr & ~0x7ff) == 0)
822 		sf = sc->sc_sf[0];
823 	else
824 		sf = sc->sc_sf[1];
825 
826 	rv = sdmmc_io_read_4(sf, addr);
827 	return rv;
828 }
829 
830 void
831 bwfm_sdio_write_1(struct bwfm_sdio_softc *sc, uint32_t addr, uint8_t data)
832 {
833 	struct sdmmc_function *sf;
834 
835 	/*
836 	 * figure out how to read the register based on address range
837 	 * 0x00 ~ 0x7FF: function 0 CCCR and FBR
838 	 * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers
839 	 * The rest: function 1 silicon backplane core registers
840 	 */
841 	if ((addr & ~0x7ff) == 0)
842 		sf = sc->sc_sf[0];
843 	else
844 		sf = sc->sc_sf[1];
845 
846 	sdmmc_io_write_1(sf, addr, data);
847 }
848 
849 void
850 bwfm_sdio_write_4(struct bwfm_sdio_softc *sc, uint32_t addr, uint32_t data)
851 {
852 	struct sdmmc_function *sf;
853 	uint32_t bar0 = addr & ~BWFM_SDIO_SB_OFT_ADDR_MASK;
854 
855 	bwfm_sdio_backplane(sc, bar0);
856 
857 	addr &= BWFM_SDIO_SB_OFT_ADDR_MASK;
858 	addr |= BWFM_SDIO_SB_ACCESS_2_4B_FLAG;
859 
860 	/*
861 	 * figure out how to read the register based on address range
862 	 * 0x00 ~ 0x7FF: function 0 CCCR and FBR
863 	 * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers
864 	 * The rest: function 1 silicon backplane core registers
865 	 */
866 	if ((addr & ~0x7ff) == 0)
867 		sf = sc->sc_sf[0];
868 	else
869 		sf = sc->sc_sf[1];
870 
871 	sdmmc_io_write_4(sf, addr, data);
872 }
873 
874 int
875 bwfm_sdio_buf_read(struct bwfm_sdio_softc *sc, struct sdmmc_function *sf,
876     uint32_t reg, char *data, size_t size)
877 {
878 	int err;
879 
880 	KASSERT(((vaddr_t)data & 0x3) == 0);
881 	KASSERT((size & 0x3) == 0);
882 
883 	if (sf == sc->sc_sf[1])
884 		err = sdmmc_io_read_region_1(sf, reg, data, size);
885 	else
886 		err = sdmmc_io_read_multi_1(sf, reg, data, size);
887 
888 	if (err)
889 		printf("%s: error %d\n", __func__, err);
890 
891 	return err;
892 }
893 
894 int
895 bwfm_sdio_buf_write(struct bwfm_sdio_softc *sc, struct sdmmc_function *sf,
896     uint32_t reg, char *data, size_t size)
897 {
898 	int err;
899 
900 	KASSERT(((vaddr_t)data & 0x3) == 0);
901 	KASSERT((size & 0x3) == 0);
902 
903 	err = sdmmc_io_write_region_1(sf, reg, data, size);
904 
905 	if (err)
906 		printf("%s: error %d\n", __func__, err);
907 
908 	return err;
909 }
910 
911 uint32_t
912 bwfm_sdio_ram_read_write(struct bwfm_sdio_softc *sc, uint32_t reg,
913     char *data, size_t left, int write)
914 {
915 	uint32_t sbaddr, sdaddr, off;
916 	size_t size;
917 	int err;
918 
919 	err = off = 0;
920 	while (left > 0) {
921 		sbaddr = reg + off;
922 		bwfm_sdio_backplane(sc, sbaddr);
923 
924 		sdaddr = sbaddr & BWFM_SDIO_SB_OFT_ADDR_MASK;
925 		size = min(left, (BWFM_SDIO_SB_OFT_ADDR_PAGE - sdaddr));
926 		sdaddr |= BWFM_SDIO_SB_ACCESS_2_4B_FLAG;
927 
928 		if (write) {
929 			memcpy(sc->sc_bounce_buf, data + off, size);
930 			if (roundup(size, 4) != size)
931 				memset(sc->sc_bounce_buf + size, 0,
932 				    roundup(size, 4) - size);
933 			err = bwfm_sdio_buf_write(sc, sc->sc_sf[1], sdaddr,
934 			    sc->sc_bounce_buf, roundup(size, 4));
935 		} else {
936 			err = bwfm_sdio_buf_read(sc, sc->sc_sf[1], sdaddr,
937 			    sc->sc_bounce_buf, roundup(size, 4));
938 			memcpy(data + off, sc->sc_bounce_buf, size);
939 		}
940 		if (err)
941 			break;
942 
943 		off += size;
944 		left -= size;
945 	}
946 
947 	return err;
948 }
949 
950 uint32_t
951 bwfm_sdio_frame_read_write(struct bwfm_sdio_softc *sc,
952     char *data, size_t size, int write)
953 {
954 	uint32_t addr;
955 	int err;
956 
957 	addr = sc->sc_cc->co_base;
958 	bwfm_sdio_backplane(sc, addr);
959 
960 	addr &= BWFM_SDIO_SB_OFT_ADDR_MASK;
961 	addr |= BWFM_SDIO_SB_ACCESS_2_4B_FLAG;
962 
963 	if (write)
964 		err = bwfm_sdio_buf_write(sc, sc->sc_sf[2], addr, data, size);
965 	else
966 		err = bwfm_sdio_buf_read(sc, sc->sc_sf[2], addr, data, size);
967 
968 	return err;
969 }
970 
971 uint32_t
972 bwfm_sdio_dev_read(struct bwfm_sdio_softc *sc, uint32_t reg)
973 {
974 	struct bwfm_core *core;
975 	core = bwfm_chip_get_core(&sc->sc_sc, BWFM_AGENT_CORE_SDIO_DEV);
976 	return bwfm_sdio_read_4(sc, core->co_base + reg);
977 }
978 
979 void
980 bwfm_sdio_dev_write(struct bwfm_sdio_softc *sc, uint32_t reg, uint32_t val)
981 {
982 	struct bwfm_core *core;
983 	core = bwfm_chip_get_core(&sc->sc_sc, BWFM_AGENT_CORE_SDIO_DEV);
984 	bwfm_sdio_write_4(sc, core->co_base + reg, val);
985 }
986 
987 uint32_t
988 bwfm_sdio_buscore_read(struct bwfm_softc *bwfm, uint32_t reg)
989 {
990 	struct bwfm_sdio_softc *sc = (void *)bwfm;
991 	return bwfm_sdio_read_4(sc, reg);
992 }
993 
994 void
995 bwfm_sdio_buscore_write(struct bwfm_softc *bwfm, uint32_t reg, uint32_t val)
996 {
997 	struct bwfm_sdio_softc *sc = (void *)bwfm;
998 	bwfm_sdio_write_4(sc, reg, val);
999 }
1000 
1001 int
1002 bwfm_sdio_buscore_prepare(struct bwfm_softc *bwfm)
1003 {
1004 	struct bwfm_sdio_softc *sc = (void *)bwfm;
1005 	uint8_t clkval, clkset, clkmask;
1006 	int i;
1007 
1008 	clkset = BWFM_SDIO_FUNC1_CHIPCLKCSR_ALP_AVAIL_REQ |
1009 	    BWFM_SDIO_FUNC1_CHIPCLKCSR_FORCE_HW_CLKREQ_OFF;
1010 	bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR, clkset);
1011 
1012 	clkmask = BWFM_SDIO_FUNC1_CHIPCLKCSR_ALP_AVAIL |
1013 	    BWFM_SDIO_FUNC1_CHIPCLKCSR_HT_AVAIL;
1014 	clkval = bwfm_sdio_read_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR);
1015 
1016 	if ((clkval & ~clkmask) != clkset) {
1017 		printf("%s: wrote 0x%02x read 0x%02x\n", DEVNAME(sc),
1018 		    clkset, clkval);
1019 		return 1;
1020 	}
1021 
1022 	for (i = 1000; i > 0; i--) {
1023 		clkval = bwfm_sdio_read_1(sc,
1024 		    BWFM_SDIO_FUNC1_CHIPCLKCSR);
1025 		if (clkval & clkmask)
1026 			break;
1027 	}
1028 	if (i == 0) {
1029 		printf("%s: timeout on ALPAV wait, clkval 0x%02x\n",
1030 		    DEVNAME(sc), clkval);
1031 		return 1;
1032 	}
1033 
1034 	clkset = BWFM_SDIO_FUNC1_CHIPCLKCSR_FORCE_HW_CLKREQ_OFF |
1035 	    BWFM_SDIO_FUNC1_CHIPCLKCSR_FORCE_ALP;
1036 	bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR, clkset);
1037 	delay(65);
1038 
1039 	bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_SDIOPULLUP, 0);
1040 
1041 	return 0;
1042 }
1043 
1044 void
1045 bwfm_sdio_buscore_activate(struct bwfm_softc *bwfm, uint32_t rstvec)
1046 {
1047 	struct bwfm_sdio_softc *sc = (void *)bwfm;
1048 
1049 	bwfm_sdio_dev_write(sc, BWFM_SDPCMD_INTSTATUS, 0xFFFFFFFF);
1050 
1051 	if (rstvec)
1052 		bwfm_sdio_ram_read_write(sc, 0, (char *)&rstvec,
1053 		    sizeof(rstvec), 1);
1054 }
1055 
1056 struct mbuf *
1057 bwfm_sdio_newbuf(void)
1058 {
1059 	struct mbuf *m;
1060 
1061 	MGETHDR(m, M_DONTWAIT, MT_DATA);
1062 	if (m == NULL)
1063 		return (NULL);
1064 
1065 	MCLGET(m, M_DONTWAIT);
1066 	if (!(m->m_flags & M_EXT)) {
1067 		m_freem(m);
1068 		return (NULL);
1069 	}
1070 
1071 	m->m_len = m->m_pkthdr.len = MCLBYTES;
1072 
1073 	return (m);
1074 }
1075 
1076 int
1077 bwfm_sdio_tx_ok(struct bwfm_sdio_softc *sc)
1078 {
1079 	return (uint8_t)(sc->sc_tx_max_seq - sc->sc_tx_seq) != 0 &&
1080 	    ((uint8_t)(sc->sc_tx_max_seq - sc->sc_tx_seq) & 0x80) == 0;
1081 }
1082 
1083 void
1084 bwfm_sdio_tx_frames(struct bwfm_sdio_softc *sc)
1085 {
1086 	struct ifnet *ifp = &sc->sc_sc.sc_ic.ic_if;
1087 	struct mbuf *m;
1088 	int i;
1089 
1090 	if (!bwfm_sdio_tx_ok(sc))
1091 		return;
1092 
1093 	i = min((uint8_t)(sc->sc_tx_max_seq - sc->sc_tx_seq), 32);
1094 	while (i--) {
1095 		m = ml_dequeue(&sc->sc_tx_queue);
1096 		if (m == NULL)
1097 			break;
1098 
1099 		if (m->m_type == MT_CONTROL)
1100 			bwfm_sdio_tx_ctrlframe(sc, m);
1101 		else
1102 			bwfm_sdio_tx_dataframe(sc, m);
1103 
1104 		m_freem(m);
1105 	}
1106 
1107 	if (sc->sc_tx_count < 64)
1108 		ifq_restart(&ifp->if_snd);
1109 }
1110 
1111 void
1112 bwfm_sdio_tx_ctrlframe(struct bwfm_sdio_softc *sc, struct mbuf *m)
1113 {
1114 	struct bwfm_sdio_hwhdr *hwhdr;
1115 	struct bwfm_sdio_swhdr *swhdr;
1116 	size_t len, roundto;
1117 
1118 	len = sizeof(*hwhdr) + sizeof(*swhdr) + m->m_len;
1119 
1120 	/* Zero-pad to either block-size or 4-byte alignment. */
1121 	if (len > 512 && (len % 512) != 0)
1122 		roundto = 512;
1123 	else
1124 		roundto = 4;
1125 
1126 	KASSERT(roundup(len, roundto) <= sc->sc_bounce_size);
1127 
1128 	hwhdr = (void *)sc->sc_bounce_buf;
1129 	hwhdr->frmlen = htole16(len);
1130 	hwhdr->cksum = htole16(~len);
1131 
1132 	swhdr = (void *)&hwhdr[1];
1133 	swhdr->seqnr = sc->sc_tx_seq++;
1134 	swhdr->chanflag = BWFM_SDIO_SWHDR_CHANNEL_CONTROL;
1135 	swhdr->nextlen = 0;
1136 	swhdr->dataoff = sizeof(*hwhdr) + sizeof(*swhdr);
1137 	swhdr->maxseqnr = 0;
1138 
1139 	m_copydata(m, 0, m->m_len, (caddr_t)&swhdr[1]);
1140 
1141 	if (roundup(len, roundto) != len)
1142 		memset(sc->sc_bounce_buf + len, 0,
1143 		    roundup(len, roundto) - len);
1144 
1145 	bwfm_sdio_frame_read_write(sc, sc->sc_bounce_buf,
1146 	    roundup(len, roundto), 1);
1147 }
1148 
1149 void
1150 bwfm_sdio_tx_dataframe(struct bwfm_sdio_softc *sc, struct mbuf *m)
1151 {
1152 	struct bwfm_sdio_hwhdr *hwhdr;
1153 	struct bwfm_sdio_swhdr *swhdr;
1154 	struct bwfm_proto_bcdc_hdr *bcdc;
1155 	size_t len, roundto;
1156 
1157 	len = sizeof(*hwhdr) + sizeof(*swhdr) + sizeof(*bcdc)
1158 	    + m->m_pkthdr.len;
1159 
1160 	/* Zero-pad to either block-size or 4-byte alignment. */
1161 	if (len > 512 && (len % 512) != 0)
1162 		roundto = 512;
1163 	else
1164 		roundto = 4;
1165 
1166 	KASSERT(roundup(len, roundto) <= sc->sc_bounce_size);
1167 
1168 	hwhdr = (void *)sc->sc_bounce_buf;
1169 	hwhdr->frmlen = htole16(len);
1170 	hwhdr->cksum = htole16(~len);
1171 
1172 	swhdr = (void *)&hwhdr[1];
1173 	swhdr->seqnr = sc->sc_tx_seq++;
1174 	swhdr->chanflag = BWFM_SDIO_SWHDR_CHANNEL_DATA;
1175 	swhdr->nextlen = 0;
1176 	swhdr->dataoff = sizeof(*hwhdr) + sizeof(*swhdr);
1177 	swhdr->maxseqnr = 0;
1178 
1179 	bcdc = (void *)&swhdr[1];
1180 	bcdc->data_offset = 0;
1181 	bcdc->priority = ieee80211_classify(&sc->sc_sc.sc_ic, m);
1182 	bcdc->flags = BWFM_BCDC_FLAG_VER(BWFM_BCDC_FLAG_PROTO_VER);
1183 	bcdc->flags2 = 0;
1184 
1185 	m_copydata(m, 0, m->m_pkthdr.len, (caddr_t)&bcdc[1]);
1186 
1187 	if (roundup(len, roundto) != len)
1188 		memset(sc->sc_bounce_buf + len, 0,
1189 		    roundup(len, roundto) - len);
1190 
1191 	bwfm_sdio_frame_read_write(sc, sc->sc_bounce_buf,
1192 	    roundup(len, roundto), 1);
1193 
1194 	sc->sc_tx_count--;
1195 }
1196 
1197 void
1198 bwfm_sdio_rx_frames(struct bwfm_sdio_softc *sc)
1199 {
1200 	struct ifnet *ifp = &sc->sc_sc.sc_ic.ic_if;
1201 	struct mbuf_list ml = MBUF_LIST_INITIALIZER();
1202 	struct bwfm_sdio_hwhdr *hwhdr;
1203 	struct bwfm_sdio_swhdr *swhdr;
1204 	uint16_t *sublen, nextlen = 0;
1205 	struct mbuf *m;
1206 	size_t flen;
1207 	char *data;
1208 	off_t off;
1209 	int nsub;
1210 
1211 	hwhdr = (struct bwfm_sdio_hwhdr *)sc->sc_bounce_buf;
1212 	swhdr = (struct bwfm_sdio_swhdr *)&hwhdr[1];
1213 	data = (char *)&swhdr[1];
1214 
1215 	for (;;) {
1216 		/* If we know the next size, just read ahead. */
1217 		if (nextlen) {
1218 			if (bwfm_sdio_frame_read_write(sc, sc->sc_bounce_buf,
1219 			    nextlen, 0))
1220 				break;
1221 		} else {
1222 			if (bwfm_sdio_frame_read_write(sc, sc->sc_bounce_buf,
1223 			    sizeof(*hwhdr) + sizeof(*swhdr), 0))
1224 				break;
1225 		}
1226 
1227 		hwhdr->frmlen = letoh16(hwhdr->frmlen);
1228 		hwhdr->cksum = letoh16(hwhdr->cksum);
1229 
1230 		if (hwhdr->frmlen == 0 && hwhdr->cksum == 0)
1231 			break;
1232 
1233 		if ((hwhdr->frmlen ^ hwhdr->cksum) != 0xffff) {
1234 			printf("%s: checksum error\n", DEVNAME(sc));
1235 			break;
1236 		}
1237 
1238 		if (hwhdr->frmlen < sizeof(*hwhdr) + sizeof(*swhdr)) {
1239 			printf("%s: length error\n", DEVNAME(sc));
1240 			break;
1241 		}
1242 
1243 		if (nextlen && hwhdr->frmlen > nextlen) {
1244 			printf("%s: read ahead length error (%u > %u)\n",
1245 			    DEVNAME(sc), hwhdr->frmlen, nextlen);
1246 			break;
1247 		}
1248 
1249 		sc->sc_tx_max_seq = swhdr->maxseqnr;
1250 
1251 		flen = hwhdr->frmlen - (sizeof(*hwhdr) + sizeof(*swhdr));
1252 		if (flen == 0) {
1253 			nextlen = swhdr->nextlen << 4;
1254 			continue;
1255 		}
1256 
1257 		if (!nextlen) {
1258 			KASSERT(roundup(flen, 4) <= sc->sc_bounce_size -
1259 			    (sizeof(*hwhdr) + sizeof(*swhdr)));
1260 			if (bwfm_sdio_frame_read_write(sc, data,
1261 			    roundup(flen, 4), 0))
1262 				break;
1263 		}
1264 
1265 		if (swhdr->dataoff < (sizeof(*hwhdr) + sizeof(*swhdr)))
1266 			break;
1267 
1268 		off = swhdr->dataoff - (sizeof(*hwhdr) + sizeof(*swhdr));
1269 		if (off > flen)
1270 			break;
1271 
1272 		switch (swhdr->chanflag & BWFM_SDIO_SWHDR_CHANNEL_MASK) {
1273 		case BWFM_SDIO_SWHDR_CHANNEL_CONTROL:
1274 			sc->sc_sc.sc_proto_ops->proto_rxctl(&sc->sc_sc,
1275 			    data + off, flen - off);
1276 			nextlen = swhdr->nextlen << 4;
1277 			break;
1278 		case BWFM_SDIO_SWHDR_CHANNEL_EVENT:
1279 		case BWFM_SDIO_SWHDR_CHANNEL_DATA:
1280 			m = bwfm_sdio_newbuf();
1281 			if (m == NULL)
1282 				break;
1283 			if (flen - off > m->m_len) {
1284 				printf("%s: frame bigger than anticipated\n",
1285 				    DEVNAME(sc));
1286 				m_freem(m);
1287 				break;
1288 			}
1289 			m->m_len = m->m_pkthdr.len = flen - off;
1290 			memcpy(mtod(m, char *), data + off, flen - off);
1291 			sc->sc_sc.sc_proto_ops->proto_rx(&sc->sc_sc, m, &ml);
1292 			nextlen = swhdr->nextlen << 4;
1293 			break;
1294 		case BWFM_SDIO_SWHDR_CHANNEL_GLOM:
1295 			if ((flen % sizeof(uint16_t)) != 0)
1296 				break;
1297 			nsub = flen / sizeof(uint16_t);
1298 			sublen = mallocarray(nsub, sizeof(uint16_t),
1299 			    M_DEVBUF, M_WAITOK | M_ZERO);
1300 			memcpy(sublen, data, nsub * sizeof(uint16_t));
1301 			bwfm_sdio_rx_glom(sc, sublen, nsub, &nextlen, &ml);
1302 			free(sublen, M_DEVBUF, nsub * sizeof(uint16_t));
1303 			break;
1304 		default:
1305 			printf("%s: unknown channel\n", DEVNAME(sc));
1306 			break;
1307 		}
1308 	}
1309 
1310 	if_input(ifp, &ml);
1311 }
1312 
1313 void
1314 bwfm_sdio_rx_glom(struct bwfm_sdio_softc *sc, uint16_t *sublen, int nsub,
1315     uint16_t *nextlen, struct mbuf_list *ml)
1316 {
1317 	struct bwfm_sdio_hwhdr hwhdr;
1318 	struct bwfm_sdio_swhdr swhdr;
1319 	struct mbuf_list glom, drop;
1320 	struct mbuf *m;
1321 	size_t flen;
1322 	off_t off;
1323 	int i;
1324 
1325 	ml_init(&glom);
1326 	ml_init(&drop);
1327 
1328 	if (nsub == 0)
1329 		return;
1330 
1331 	for (i = 0; i < nsub; i++) {
1332 		m = bwfm_sdio_newbuf();
1333 		if (m == NULL) {
1334 			ml_purge(&glom);
1335 			return;
1336 		}
1337 		ml_enqueue(&glom, m);
1338 		if (letoh16(sublen[i]) > m->m_len) {
1339 			ml_purge(&glom);
1340 			return;
1341 		}
1342 		if (bwfm_sdio_frame_read_write(sc, mtod(m, char *),
1343 		    letoh16(sublen[i]), 0)) {
1344 			ml_purge(&glom);
1345 			return;
1346 		}
1347 		m->m_len = m->m_pkthdr.len = letoh16(sublen[i]);
1348 	}
1349 
1350 	/* TODO: Verify actual superframe header */
1351 	m = MBUF_LIST_FIRST(&glom);
1352 	if (m->m_len >= sizeof(hwhdr) + sizeof(swhdr)) {
1353 		m_copydata(m, 0, sizeof(hwhdr), (caddr_t)&hwhdr);
1354 		m_copydata(m, sizeof(hwhdr), sizeof(swhdr), (caddr_t)&swhdr);
1355 		*nextlen = swhdr.nextlen << 4;
1356 		m_adj(m, sizeof(struct bwfm_sdio_hwhdr) +
1357 		    sizeof(struct bwfm_sdio_swhdr));
1358 	}
1359 
1360 	while ((m = ml_dequeue(&glom)) != NULL) {
1361 		if (m->m_len < sizeof(hwhdr) + sizeof(swhdr))
1362 			goto drop;
1363 
1364 		m_copydata(m, 0, sizeof(hwhdr), (caddr_t)&hwhdr);
1365 		m_copydata(m, sizeof(hwhdr), sizeof(swhdr), (caddr_t)&swhdr);
1366 
1367 		hwhdr.frmlen = letoh16(hwhdr.frmlen);
1368 		hwhdr.cksum = letoh16(hwhdr.cksum);
1369 
1370 		if (hwhdr.frmlen == 0 && hwhdr.cksum == 0)
1371 			goto drop;
1372 
1373 		if ((hwhdr.frmlen ^ hwhdr.cksum) != 0xffff) {
1374 			printf("%s: checksum error\n", DEVNAME(sc));
1375 			goto drop;
1376 		}
1377 
1378 		if (hwhdr.frmlen < sizeof(hwhdr) + sizeof(swhdr)) {
1379 			printf("%s: length error\n", DEVNAME(sc));
1380 			goto drop;
1381 		}
1382 
1383 		flen = hwhdr.frmlen - (sizeof(hwhdr) + sizeof(swhdr));
1384 		if (flen == 0)
1385 			goto drop;
1386 		if (m->m_len < flen)
1387 			goto drop;
1388 
1389 		if (swhdr.dataoff < (sizeof(hwhdr) + sizeof(swhdr)))
1390 			goto drop;
1391 
1392 		off = swhdr.dataoff - (sizeof(hwhdr) + sizeof(swhdr));
1393 		if (off > flen)
1394 			goto drop;
1395 
1396 		switch (swhdr.chanflag & BWFM_SDIO_SWHDR_CHANNEL_MASK) {
1397 		case BWFM_SDIO_SWHDR_CHANNEL_CONTROL:
1398 			printf("%s: control channel not allowed in glom\n",
1399 			    DEVNAME(sc));
1400 			goto drop;
1401 		case BWFM_SDIO_SWHDR_CHANNEL_EVENT:
1402 		case BWFM_SDIO_SWHDR_CHANNEL_DATA:
1403 			m_adj(m, swhdr.dataoff);
1404 			sc->sc_sc.sc_proto_ops->proto_rx(&sc->sc_sc, m, ml);
1405 			break;
1406 		case BWFM_SDIO_SWHDR_CHANNEL_GLOM:
1407 			printf("%s: glom not allowed in glom\n",
1408 			    DEVNAME(sc));
1409 			goto drop;
1410 		default:
1411 			printf("%s: unknown channel\n", DEVNAME(sc));
1412 			goto drop;
1413 		}
1414 
1415 		continue;
1416 drop:
1417 		ml_enqueue(&drop, m);
1418 	}
1419 
1420 	ml_purge(&drop);
1421 }
1422 
1423 int
1424 bwfm_sdio_txcheck(struct bwfm_softc *bwfm)
1425 {
1426 	struct bwfm_sdio_softc *sc = (void *)bwfm;
1427 
1428 	if (sc->sc_tx_count >= 64)
1429 		return ENOBUFS;
1430 
1431 	return 0;
1432 }
1433 
1434 int
1435 bwfm_sdio_txdata(struct bwfm_softc *bwfm, struct mbuf *m)
1436 {
1437 	struct bwfm_sdio_softc *sc = (void *)bwfm;
1438 
1439 	if (sc->sc_tx_count >= 64)
1440 		return ENOBUFS;
1441 
1442 	sc->sc_tx_count++;
1443 	ml_enqueue(&sc->sc_tx_queue, m);
1444 	task_add(systq, &sc->sc_task);
1445 	return 0;
1446 }
1447 
1448 int
1449 bwfm_sdio_txctl(struct bwfm_softc *bwfm, void *arg)
1450 {
1451 	struct bwfm_sdio_softc *sc = (void *)bwfm;
1452 	struct bwfm_proto_bcdc_ctl *ctl = arg;
1453 	struct mbuf *m;
1454 
1455 	KASSERT(ctl->len <= MCLBYTES);
1456 
1457 	MGET(m, M_DONTWAIT, MT_CONTROL);
1458 	if (m == NULL)
1459 		goto fail;
1460 	if (ctl->len > MLEN) {
1461 		MCLGET(m, M_DONTWAIT);
1462 		if (!(m->m_flags & M_EXT)) {
1463 			m_freem(m);
1464 			goto fail;
1465 		}
1466 	}
1467 	memcpy(mtod(m, char *), ctl->buf, ctl->len);
1468 	m->m_len = ctl->len;
1469 
1470 	TAILQ_INSERT_TAIL(&sc->sc_sc.sc_bcdc_rxctlq, ctl, next);
1471 	ml_enqueue(&sc->sc_tx_queue, m);
1472 	task_add(systq, &sc->sc_task);
1473 	return 0;
1474 
1475 fail:
1476 	free(ctl->buf, M_TEMP, ctl->len);
1477 	free(ctl, M_TEMP, sizeof(*ctl));
1478 	return 1;
1479 }
1480 
1481 #ifdef BWFM_DEBUG
1482 void
1483 bwfm_sdio_debug_console(struct bwfm_sdio_softc *sc)
1484 {
1485 	struct bwfm_sdio_console c;
1486 	uint32_t newidx;
1487 	int err;
1488 
1489 	if (!sc->sc_console_addr)
1490 		return;
1491 
1492 	err = bwfm_sdio_ram_read_write(sc, sc->sc_console_addr,
1493 	    (char *)&c, sizeof(c), 0);
1494 	if (err)
1495 		return;
1496 
1497 	c.log_buf = letoh32(c.log_buf);
1498 	c.log_bufsz = letoh32(c.log_bufsz);
1499 	c.log_idx = letoh32(c.log_idx);
1500 
1501 	if (sc->sc_console_buf == NULL) {
1502 		sc->sc_console_buf = malloc(c.log_bufsz, M_DEVBUF,
1503 		    M_WAITOK|M_ZERO);
1504 		sc->sc_console_buf_size = c.log_bufsz;
1505 	}
1506 
1507 	newidx = c.log_idx;
1508 	if (newidx >= sc->sc_console_buf_size)
1509 		return;
1510 
1511 	err = bwfm_sdio_ram_read_write(sc, c.log_buf, sc->sc_console_buf,
1512 	    sc->sc_console_buf_size, 0);
1513 	if (err)
1514 		return;
1515 
1516 	if (newidx != sc->sc_console_readidx)
1517 		DPRINTFN(3, ("BWFM CONSOLE: "));
1518 	while (newidx != sc->sc_console_readidx) {
1519 		uint8_t ch = sc->sc_console_buf[sc->sc_console_readidx];
1520 		sc->sc_console_readidx++;
1521 		if (sc->sc_console_readidx == sc->sc_console_buf_size)
1522 			sc->sc_console_readidx = 0;
1523 		if (ch == '\r')
1524 			continue;
1525 		DPRINTFN(3, ("%c", ch));
1526 	}
1527 }
1528 #endif
1529