xref: /openbsd-src/sys/dev/sdmmc/if_bwfm_sdio.c (revision f1dd7b858388b4a23f4f67a4957ec5ff656ebbe8)
1 /* $OpenBSD: if_bwfm_sdio.c,v 1.39 2021/02/26 00:07:41 patrick 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/sdmmcvar.h>
49 
50 #include <dev/ic/bwfmvar.h>
51 #include <dev/ic/bwfmreg.h>
52 #include <dev/sdmmc/if_bwfm_sdio.h>
53 
54 #define BWFM_SDIO_CCCR_BRCM_CARDCAP			0xf0
55 #define  BWFM_SDIO_CCCR_BRCM_CARDCAP_CMD14_SUPPORT	0x02
56 #define  BWFM_SDIO_CCCR_BRCM_CARDCAP_CMD14_EXT		0x04
57 #define  BWFM_SDIO_CCCR_BRCM_CARDCAP_CMD_NODEC		0x08
58 #define BWFM_SDIO_CCCR_BRCM_CARDCTRL			0xf1
59 #define  BWFM_SDIO_CCCR_BRCM_CARDCTRL_WLANRESET		0x02
60 #define BWFM_SDIO_CCCR_BRCM_SEPINT			0xf2
61 
62 /* #define BWFM_DEBUG */
63 #ifdef BWFM_DEBUG
64 #define DPRINTF(x)	do { if (bwfm_debug > 0) printf x; } while (0)
65 #define DPRINTFN(n, x)	do { if (bwfm_debug >= (n)) printf x; } while (0)
66 static int bwfm_debug = 1;
67 #else
68 #define DPRINTF(x)	do { ; } while (0)
69 #define DPRINTFN(n, x)	do { ; } while (0)
70 #endif
71 
72 #undef DEVNAME
73 #define DEVNAME(sc)	((sc)->sc_sc.sc_dev.dv_xname)
74 
75 enum bwfm_sdio_clkstate {
76 	CLK_NONE,
77 	CLK_SDONLY,
78 	CLK_PENDING,
79 	CLK_AVAIL,
80 };
81 
82 struct bwfm_sdio_softc {
83 	struct bwfm_softc	  sc_sc;
84 	struct sdmmc_function	**sc_sf;
85 	struct rwlock		 *sc_lock;
86 	void			 *sc_ih;
87 	int			  sc_node;
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 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 != 0x02d0)
212 		return 0;
213 
214 	/* Look for supported chips. */
215 	switch (cis->product) {
216 	case 0x4324:
217 	case 0x4330:
218 	case 0x4334:
219 	case 0x4329:
220 	case 0x4335:
221 	case 0x4339:
222 	case 0x4345:
223 	case 0x4354:
224 	case 0x4356:
225 	case 0x4359:
226 	case 0xa887:	/* BCM43143 */
227 	case 0xa94c:	/* BCM43340 */
228 	case 0xa94d:	/* BCM43341 */
229 	case 0xa962:	/* BCM43362 */
230 	case 0xa9a6:	/* BCM43430 */
231 	case 0xa9bf:	/* 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_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_4330_CHIP_ID:
364 		chip = "4330";
365 		break;
366 	case BRCM_CC_4334_CHIP_ID:
367 		chip = "4334";
368 		break;
369 	case BRCM_CC_4345_CHIP_ID:
370 		if (bwfm->sc_chip.ch_chiprev == 9)
371 			chip = "43456";
372 		else
373 			chip = "43455";
374 		break;
375 	case BRCM_CC_43340_CHIP_ID:
376 	case BRCM_CC_43341_CHIP_ID:
377 		chip = "43340";
378 		break;
379 	case BRCM_CC_4335_CHIP_ID:
380 		if (bwfm->sc_chip.ch_chiprev < 2)
381 			chip = "4335";
382 		else
383 			chip = "4339";
384 		break;
385 	case BRCM_CC_4339_CHIP_ID:
386 		chip = "4339";
387 		break;
388 	case BRCM_CC_43430_CHIP_ID:
389 		if (bwfm->sc_chip.ch_chiprev == 0)
390 			chip = "43430a0";
391 		else
392 			chip = "43430";
393 		break;
394 	case BRCM_CC_4356_CHIP_ID:
395 		chip = "4356";
396 		break;
397 	case BRCM_CC_4359_CHIP_ID:
398 		chip = "4359";
399 		break;
400 	default:
401 		printf("%s: unknown firmware for chip %s\n",
402 		    DEVNAME(sc), bwfm->sc_chip.ch_name);
403 		goto err;
404 	}
405 
406 	if (bwfm_loadfirmware(bwfm, chip, "-sdio", &ucode, &size,
407 	    &nvram, &nvsize, &nvlen) != 0)
408 		goto err;
409 
410 	sc->sc_alp_only = 1;
411 	if (bwfm_sdio_load_microcode(sc, ucode, size,
412 	    nvram, nvlen) != 0) {
413 		printf("%s: could not load microcode\n",
414 		    DEVNAME(sc));
415 		free(ucode, M_DEVBUF, size);
416 		free(nvram, M_DEVBUF, nvsize);
417 		goto err;
418 	}
419 	sc->sc_alp_only = 0;
420 	free(ucode, M_DEVBUF, size);
421 	free(nvram, M_DEVBUF, nvsize);
422 
423 	bwfm_sdio_clkctl(sc, CLK_AVAIL, 0);
424 	if (sc->sc_clkstate != CLK_AVAIL)
425 		goto err;
426 
427 	clk = bwfm_sdio_read_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR);
428 	bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR,
429 	    clk | BWFM_SDIO_FUNC1_CHIPCLKCSR_FORCE_HT);
430 
431 	bwfm_sdio_dev_write(sc, SDPCMD_TOSBMAILBOXDATA,
432 	    SDPCM_PROT_VERSION << SDPCM_PROT_VERSION_SHIFT);
433 	if (sdmmc_io_function_enable(sc->sc_sf[2]) != 0) {
434 		printf("%s: cannot enable function 2\n", DEVNAME(sc));
435 		goto err;
436 	}
437 
438 	bwfm_sdio_dev_write(sc, SDPCMD_HOSTINTMASK,
439 	    SDPCMD_INTSTATUS_HMB_SW_MASK|SDPCMD_INTSTATUS_CHIPACTIVE);
440 	bwfm_sdio_write_1(sc, BWFM_SDIO_WATERMARK, 8);
441 
442 	if (bwfm_chip_sr_capable(bwfm)) {
443 		reg = bwfm_sdio_read_1(sc, BWFM_SDIO_FUNC1_WAKEUPCTRL);
444 		reg |= BWFM_SDIO_FUNC1_WAKEUPCTRL_HTWAIT;
445 		bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_WAKEUPCTRL, reg);
446 		bwfm_sdio_write_1(sc, BWFM_SDIO_CCCR_CARDCAP,
447 		    BWFM_SDIO_CCCR_CARDCAP_CMD14_SUPPORT |
448 		    BWFM_SDIO_CCCR_CARDCAP_CMD14_EXT);
449 		bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR,
450 		    BWFM_SDIO_FUNC1_CHIPCLKCSR_FORCE_HT);
451 		sc->sc_sr_enabled = 1;
452 	} else {
453 		bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR, clk);
454 	}
455 
456 #if defined(__HAVE_FDT)
457 	if (sc->sc_node) {
458 		sc->sc_ih = fdt_intr_establish(sc->sc_node,
459 		    IPL_NET, bwfm_sdio_oob_intr, sc, DEVNAME(sc));
460 		if (sc->sc_ih != NULL) {
461 			bwfm_sdio_write_1(sc, BWFM_SDIO_CCCR_SEPINT,
462 			    BWFM_SDIO_CCCR_SEPINT_MASK |
463 			    BWFM_SDIO_CCCR_SEPINT_OE |
464 			    BWFM_SDIO_CCCR_SEPINT_ACT_HI);
465 			sc->sc_oob = 1;
466 		}
467 	}
468 	if (sc->sc_ih == NULL)
469 #endif
470 	sc->sc_ih = sdmmc_intr_establish(bwfm->sc_dev.dv_parent,
471 	    bwfm_sdio_intr, sc, DEVNAME(sc));
472 	if (sc->sc_ih == NULL) {
473 		printf("%s: can't establish interrupt\n", DEVNAME(sc));
474 		bwfm_sdio_clkctl(sc, CLK_NONE, 0);
475 		goto err;
476 	}
477 	sdmmc_intr_enable(sc->sc_sf[1]);
478 	rw_exit(sc->sc_lock);
479 
480 	sc->sc_initialized = 1;
481 	return 0;
482 
483 err:
484 	rw_exit(sc->sc_lock);
485 	return 1;
486 }
487 
488 int
489 bwfm_sdio_load_microcode(struct bwfm_sdio_softc *sc, u_char *ucode, size_t size,
490     u_char *nvram, size_t nvlen)
491 {
492 	struct bwfm_softc *bwfm = (void *)sc;
493 	char *verify = NULL;
494 	int err = 0;
495 
496 	bwfm_sdio_clkctl(sc, CLK_AVAIL, 0);
497 
498 	/* Upload firmware */
499 	err = bwfm_sdio_ram_read_write(sc, bwfm->sc_chip.ch_rambase,
500 	    ucode, size, 1);
501 	if (err)
502 		goto out;
503 
504 	/* Verify firmware */
505 	verify = malloc(size, M_TEMP, M_WAITOK | M_ZERO);
506 	err = bwfm_sdio_ram_read_write(sc, bwfm->sc_chip.ch_rambase,
507 	    verify, size, 0);
508 	if (err || memcmp(verify, ucode, size)) {
509 		printf("%s: firmware verification failed\n",
510 		    DEVNAME(sc));
511 		free(verify, M_TEMP, size);
512 		goto out;
513 	}
514 	free(verify, M_TEMP, size);
515 
516 	/* Upload nvram */
517 	err = bwfm_sdio_ram_read_write(sc, bwfm->sc_chip.ch_rambase +
518 	    bwfm->sc_chip.ch_ramsize - nvlen, nvram, nvlen, 1);
519 	if (err)
520 		goto out;
521 
522 	/* Verify nvram */
523 	verify = malloc(nvlen, M_TEMP, M_WAITOK | M_ZERO);
524 	err = bwfm_sdio_ram_read_write(sc, bwfm->sc_chip.ch_rambase +
525 	    bwfm->sc_chip.ch_ramsize - nvlen, verify, nvlen, 0);
526 	if (err || memcmp(verify, nvram, nvlen)) {
527 		printf("%s: nvram verification failed\n",
528 		    DEVNAME(sc));
529 		free(verify, M_TEMP, nvlen);
530 		goto out;
531 	}
532 	free(verify, M_TEMP, nvlen);
533 
534 	/* Load reset vector from firmware and kickstart core. */
535 	bwfm_chip_set_active(bwfm, *(uint32_t *)ucode);
536 
537 out:
538 	bwfm_sdio_clkctl(sc, CLK_SDONLY, 0);
539 	return err;
540 }
541 
542 void
543 bwfm_sdio_clkctl(struct bwfm_sdio_softc *sc, enum bwfm_sdio_clkstate newstate,
544     int pendok)
545 {
546 	enum bwfm_sdio_clkstate oldstate;
547 
548 	oldstate = sc->sc_clkstate;
549 	if (sc->sc_clkstate == newstate)
550 		return;
551 
552 	switch (newstate) {
553 	case CLK_AVAIL:
554 		if (sc->sc_clkstate == CLK_NONE)
555 			sc->sc_clkstate = CLK_SDONLY;
556 		bwfm_sdio_htclk(sc, 1, pendok);
557 		break;
558 	case CLK_SDONLY:
559 		if (sc->sc_clkstate == CLK_NONE)
560 			sc->sc_clkstate = CLK_SDONLY;
561 		else if (sc->sc_clkstate == CLK_AVAIL)
562 			bwfm_sdio_htclk(sc, 0, 0);
563 		else
564 			printf("%s: request for %d -> %d\n",
565 			    DEVNAME(sc), sc->sc_clkstate, newstate);
566 		break;
567 	case CLK_NONE:
568 		if (sc->sc_clkstate == CLK_AVAIL)
569 			bwfm_sdio_htclk(sc, 0, 0);
570 		sc->sc_clkstate = CLK_NONE;
571 		break;
572 	default:
573 		break;
574 	}
575 
576 	DPRINTF(("%s: %d -> %d = %d\n", DEVNAME(sc), oldstate, newstate,
577 	    sc->sc_clkstate));
578 }
579 
580 void
581 bwfm_sdio_htclk(struct bwfm_sdio_softc *sc, int on, int pendok)
582 {
583 	uint32_t clkctl, devctl, req;
584 	int i;
585 
586 	if (sc->sc_sr_enabled) {
587 		if (on)
588 			sc->sc_clkstate = CLK_AVAIL;
589 		else
590 			sc->sc_clkstate = CLK_SDONLY;
591 		return;
592 	}
593 
594 	if (on) {
595 		if (sc->sc_alp_only)
596 			req = BWFM_SDIO_FUNC1_CHIPCLKCSR_ALP_AVAIL_REQ;
597 		else
598 			req = BWFM_SDIO_FUNC1_CHIPCLKCSR_HT_AVAIL_REQ;
599 		bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR, req);
600 
601 		clkctl = bwfm_sdio_read_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR);
602 		if (!BWFM_SDIO_FUNC1_CHIPCLKCSR_CLKAV(clkctl, sc->sc_alp_only)
603 		    && pendok) {
604 			devctl = bwfm_sdio_read_1(sc, BWFM_SDIO_DEVICE_CTL);
605 			devctl |= BWFM_SDIO_DEVICE_CTL_CA_INT_ONLY;
606 			bwfm_sdio_write_1(sc, BWFM_SDIO_DEVICE_CTL, devctl);
607 			sc->sc_clkstate = CLK_PENDING;
608 			return;
609 		} else if (sc->sc_clkstate == CLK_PENDING) {
610 			devctl = bwfm_sdio_read_1(sc, BWFM_SDIO_DEVICE_CTL);
611 			devctl &= ~BWFM_SDIO_DEVICE_CTL_CA_INT_ONLY;
612 			bwfm_sdio_write_1(sc, BWFM_SDIO_DEVICE_CTL, devctl);
613 		}
614 
615 		for (i = 0; i < 5000; i++) {
616 			if (BWFM_SDIO_FUNC1_CHIPCLKCSR_CLKAV(clkctl,
617 			    sc->sc_alp_only))
618 				break;
619 			clkctl = bwfm_sdio_read_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR);
620 			delay(1000);
621 		}
622 		if (!BWFM_SDIO_FUNC1_CHIPCLKCSR_CLKAV(clkctl, sc->sc_alp_only)) {
623 			printf("%s: HT avail timeout\n", DEVNAME(sc));
624 			return;
625 		}
626 
627 		sc->sc_clkstate = CLK_AVAIL;
628 	} else {
629 		if (sc->sc_clkstate == CLK_PENDING) {
630 			devctl = bwfm_sdio_read_1(sc, BWFM_SDIO_DEVICE_CTL);
631 			devctl &= ~BWFM_SDIO_DEVICE_CTL_CA_INT_ONLY;
632 			bwfm_sdio_write_1(sc, BWFM_SDIO_DEVICE_CTL, devctl);
633 		}
634 		sc->sc_clkstate = CLK_SDONLY;
635 		bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR, 0);
636 	}
637 }
638 
639 void
640 bwfm_sdio_readshared(struct bwfm_sdio_softc *sc)
641 {
642 	struct bwfm_softc *bwfm = (void *)sc;
643 	struct bwfm_sdio_sdpcm sdpcm;
644 	uint32_t addr, shaddr;
645 	int err;
646 
647 	shaddr = bwfm->sc_chip.ch_rambase + bwfm->sc_chip.ch_ramsize - 4;
648 	if (!bwfm->sc_chip.ch_rambase && bwfm_chip_sr_capable(bwfm))
649 		shaddr -= bwfm->sc_chip.ch_srsize;
650 
651 	err = bwfm_sdio_ram_read_write(sc, shaddr, (char *)&addr,
652 	    sizeof(addr), 0);
653 	if (err)
654 		return;
655 
656 	addr = letoh32(addr);
657 	if (addr == 0 || ((~addr >> 16) & 0xffff) == (addr & 0xffff))
658 		return;
659 
660 	err = bwfm_sdio_ram_read_write(sc, addr, (char *)&sdpcm,
661 	    sizeof(sdpcm), 0);
662 	if (err)
663 		return;
664 
665 	sc->sc_console_addr = letoh32(sdpcm.console_addr);
666 }
667 
668 int
669 bwfm_sdio_intr(void *v)
670 {
671 	bwfm_sdio_task(v);
672 	return 1;
673 }
674 
675 #if defined(__HAVE_FDT)
676 int
677 bwfm_sdio_oob_intr(void *v)
678 {
679 	struct bwfm_sdio_softc *sc = (void *)v;
680 	if (!sc->sc_oob)
681 		return 0;
682 	fdt_intr_disable(sc->sc_ih);
683 	task_add(systq, &sc->sc_task);
684 	return 1;
685 }
686 #endif
687 
688 void
689 bwfm_sdio_task(void *v)
690 {
691 	struct bwfm_sdio_softc *sc = (void *)v;
692 	uint32_t clkctl, devctl, intstat, hostint;
693 
694 	rw_enter_write(sc->sc_lock);
695 
696 	if (!sc->sc_sr_enabled && sc->sc_clkstate == CLK_PENDING) {
697 		clkctl = bwfm_sdio_read_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR);
698 		if (BWFM_SDIO_FUNC1_CHIPCLKCSR_HTAV(clkctl)) {
699 			devctl = bwfm_sdio_read_1(sc, BWFM_SDIO_DEVICE_CTL);
700 			devctl &= ~BWFM_SDIO_DEVICE_CTL_CA_INT_ONLY;
701 			bwfm_sdio_write_1(sc, BWFM_SDIO_DEVICE_CTL, devctl);
702 			sc->sc_clkstate = CLK_AVAIL;
703 		}
704 	}
705 
706 	intstat = bwfm_sdio_dev_read(sc, BWFM_SDPCMD_INTSTATUS);
707 	intstat &= (SDPCMD_INTSTATUS_HMB_SW_MASK|SDPCMD_INTSTATUS_CHIPACTIVE);
708 	/* XXX fc state */
709 	if (intstat)
710 		bwfm_sdio_dev_write(sc, BWFM_SDPCMD_INTSTATUS, intstat);
711 
712 	if (intstat & SDPCMD_INTSTATUS_HMB_HOST_INT) {
713 		hostint = bwfm_sdio_dev_read(sc, SDPCMD_TOHOSTMAILBOXDATA);
714 		bwfm_sdio_dev_write(sc, SDPCMD_TOSBMAILBOX,
715 		    SDPCMD_TOSBMAILBOX_INT_ACK);
716 		if (hostint & SDPCMD_TOHOSTMAILBOXDATA_NAKHANDLED)
717 			intstat |= SDPCMD_INTSTATUS_HMB_FRAME_IND;
718 		if (hostint & SDPCMD_TOHOSTMAILBOXDATA_DEVREADY ||
719 		    hostint & SDPCMD_TOHOSTMAILBOXDATA_FWREADY)
720 			bwfm_sdio_readshared(sc);
721 	}
722 
723 	/* FIXME: Might stall if we don't when not set. */
724 	if (1 || intstat & SDPCMD_INTSTATUS_HMB_FRAME_IND) {
725 		bwfm_sdio_rx_frames(sc);
726 	}
727 
728 	if (!ml_empty(&sc->sc_tx_queue)) {
729 		bwfm_sdio_tx_frames(sc);
730 	}
731 
732 #ifdef BWFM_DEBUG
733 	bwfm_sdio_debug_console(sc);
734 #endif
735 
736 	rw_exit(sc->sc_lock);
737 
738 #if defined(__HAVE_FDT)
739 	if (sc->sc_oob)
740 		fdt_intr_enable(sc->sc_ih);
741 #endif
742 }
743 
744 int
745 bwfm_sdio_detach(struct device *self, int flags)
746 {
747 	struct bwfm_sdio_softc *sc = (struct bwfm_sdio_softc *)self;
748 
749 	bwfm_detach(&sc->sc_sc, flags);
750 
751 	dma_free(sc->sc_bounce_buf, sc->sc_bounce_size);
752 	free(sc->sc_sf, M_DEVBUF, 0);
753 
754 	return 0;
755 }
756 
757 void
758 bwfm_sdio_backplane(struct bwfm_sdio_softc *sc, uint32_t bar0)
759 {
760 	if (sc->sc_bar0 == bar0)
761 		return;
762 
763 	bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_SBADDRLOW,
764 	    (bar0 >>  8) & 0x80);
765 	bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_SBADDRMID,
766 	    (bar0 >> 16) & 0xff);
767 	bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_SBADDRHIGH,
768 	    (bar0 >> 24) & 0xff);
769 	sc->sc_bar0 = bar0;
770 }
771 
772 uint8_t
773 bwfm_sdio_read_1(struct bwfm_sdio_softc *sc, uint32_t addr)
774 {
775 	struct sdmmc_function *sf;
776 	uint8_t rv;
777 
778 	/*
779 	 * figure out how to read the register based on address range
780 	 * 0x00 ~ 0x7FF: function 0 CCCR and FBR
781 	 * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers
782 	 * The rest: function 1 silicon backplane core registers
783 	 */
784 	if ((addr & ~0x7ff) == 0)
785 		sf = sc->sc_sf[0];
786 	else
787 		sf = sc->sc_sf[1];
788 
789 	rv = sdmmc_io_read_1(sf, addr);
790 	return rv;
791 }
792 
793 uint32_t
794 bwfm_sdio_read_4(struct bwfm_sdio_softc *sc, uint32_t addr)
795 {
796 	struct sdmmc_function *sf;
797 	uint32_t bar0 = addr & ~BWFM_SDIO_SB_OFT_ADDR_MASK;
798 	uint32_t rv;
799 
800 	bwfm_sdio_backplane(sc, bar0);
801 
802 	addr &= BWFM_SDIO_SB_OFT_ADDR_MASK;
803 	addr |= BWFM_SDIO_SB_ACCESS_2_4B_FLAG;
804 
805 	/*
806 	 * figure out how to read the register based on address range
807 	 * 0x00 ~ 0x7FF: function 0 CCCR and FBR
808 	 * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers
809 	 * The rest: function 1 silicon backplane core registers
810 	 */
811 	if ((addr & ~0x7ff) == 0)
812 		sf = sc->sc_sf[0];
813 	else
814 		sf = sc->sc_sf[1];
815 
816 	rv = sdmmc_io_read_4(sf, addr);
817 	return rv;
818 }
819 
820 void
821 bwfm_sdio_write_1(struct bwfm_sdio_softc *sc, uint32_t addr, uint8_t data)
822 {
823 	struct sdmmc_function *sf;
824 
825 	/*
826 	 * figure out how to read the register based on address range
827 	 * 0x00 ~ 0x7FF: function 0 CCCR and FBR
828 	 * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers
829 	 * The rest: function 1 silicon backplane core registers
830 	 */
831 	if ((addr & ~0x7ff) == 0)
832 		sf = sc->sc_sf[0];
833 	else
834 		sf = sc->sc_sf[1];
835 
836 	sdmmc_io_write_1(sf, addr, data);
837 }
838 
839 void
840 bwfm_sdio_write_4(struct bwfm_sdio_softc *sc, uint32_t addr, uint32_t data)
841 {
842 	struct sdmmc_function *sf;
843 	uint32_t bar0 = addr & ~BWFM_SDIO_SB_OFT_ADDR_MASK;
844 
845 	bwfm_sdio_backplane(sc, bar0);
846 
847 	addr &= BWFM_SDIO_SB_OFT_ADDR_MASK;
848 	addr |= BWFM_SDIO_SB_ACCESS_2_4B_FLAG;
849 
850 	/*
851 	 * figure out how to read the register based on address range
852 	 * 0x00 ~ 0x7FF: function 0 CCCR and FBR
853 	 * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers
854 	 * The rest: function 1 silicon backplane core registers
855 	 */
856 	if ((addr & ~0x7ff) == 0)
857 		sf = sc->sc_sf[0];
858 	else
859 		sf = sc->sc_sf[1];
860 
861 	sdmmc_io_write_4(sf, addr, data);
862 }
863 
864 int
865 bwfm_sdio_buf_read(struct bwfm_sdio_softc *sc, struct sdmmc_function *sf,
866     uint32_t reg, char *data, size_t size)
867 {
868 	int err;
869 
870 	KASSERT(((vaddr_t)data & 0x3) == 0);
871 	KASSERT((size & 0x3) == 0);
872 
873 	if (sf == sc->sc_sf[1])
874 		err = sdmmc_io_read_region_1(sf, reg, data, size);
875 	else
876 		err = sdmmc_io_read_multi_1(sf, reg, data, size);
877 
878 	if (err)
879 		printf("%s: error %d\n", __func__, err);
880 
881 	return err;
882 }
883 
884 int
885 bwfm_sdio_buf_write(struct bwfm_sdio_softc *sc, struct sdmmc_function *sf,
886     uint32_t reg, char *data, size_t size)
887 {
888 	int err;
889 
890 	KASSERT(((vaddr_t)data & 0x3) == 0);
891 	KASSERT((size & 0x3) == 0);
892 
893 	err = sdmmc_io_write_region_1(sf, reg, data, size);
894 
895 	if (err)
896 		printf("%s: error %d\n", __func__, err);
897 
898 	return err;
899 }
900 
901 uint32_t
902 bwfm_sdio_ram_read_write(struct bwfm_sdio_softc *sc, uint32_t reg,
903     char *data, size_t left, int write)
904 {
905 	uint32_t sbaddr, sdaddr, off;
906 	size_t size;
907 	int err;
908 
909 	err = off = 0;
910 	while (left > 0) {
911 		sbaddr = reg + off;
912 		bwfm_sdio_backplane(sc, sbaddr);
913 
914 		sdaddr = sbaddr & BWFM_SDIO_SB_OFT_ADDR_MASK;
915 		size = min(left, (BWFM_SDIO_SB_OFT_ADDR_PAGE - sdaddr));
916 		sdaddr |= BWFM_SDIO_SB_ACCESS_2_4B_FLAG;
917 
918 		if (write) {
919 			memcpy(sc->sc_bounce_buf, data + off, size);
920 			if (roundup(size, 4) != size)
921 				memset(sc->sc_bounce_buf + size, 0,
922 				    roundup(size, 4) - size);
923 			err = bwfm_sdio_buf_write(sc, sc->sc_sf[1], sdaddr,
924 			    sc->sc_bounce_buf, roundup(size, 4));
925 		} else {
926 			err = bwfm_sdio_buf_read(sc, sc->sc_sf[1], sdaddr,
927 			    sc->sc_bounce_buf, roundup(size, 4));
928 			memcpy(data + off, sc->sc_bounce_buf, size);
929 		}
930 		if (err)
931 			break;
932 
933 		off += size;
934 		left -= size;
935 	}
936 
937 	return err;
938 }
939 
940 uint32_t
941 bwfm_sdio_frame_read_write(struct bwfm_sdio_softc *sc,
942     char *data, size_t size, int write)
943 {
944 	uint32_t addr;
945 	int err;
946 
947 	addr = sc->sc_cc->co_base;
948 	bwfm_sdio_backplane(sc, addr);
949 
950 	addr &= BWFM_SDIO_SB_OFT_ADDR_MASK;
951 	addr |= BWFM_SDIO_SB_ACCESS_2_4B_FLAG;
952 
953 	if (write)
954 		err = bwfm_sdio_buf_write(sc, sc->sc_sf[2], addr, data, size);
955 	else
956 		err = bwfm_sdio_buf_read(sc, sc->sc_sf[2], addr, data, size);
957 
958 	return err;
959 }
960 
961 uint32_t
962 bwfm_sdio_dev_read(struct bwfm_sdio_softc *sc, uint32_t reg)
963 {
964 	struct bwfm_core *core;
965 	core = bwfm_chip_get_core(&sc->sc_sc, BWFM_AGENT_CORE_SDIO_DEV);
966 	return bwfm_sdio_read_4(sc, core->co_base + reg);
967 }
968 
969 void
970 bwfm_sdio_dev_write(struct bwfm_sdio_softc *sc, uint32_t reg, uint32_t val)
971 {
972 	struct bwfm_core *core;
973 	core = bwfm_chip_get_core(&sc->sc_sc, BWFM_AGENT_CORE_SDIO_DEV);
974 	bwfm_sdio_write_4(sc, core->co_base + reg, val);
975 }
976 
977 uint32_t
978 bwfm_sdio_buscore_read(struct bwfm_softc *bwfm, uint32_t reg)
979 {
980 	struct bwfm_sdio_softc *sc = (void *)bwfm;
981 	return bwfm_sdio_read_4(sc, reg);
982 }
983 
984 void
985 bwfm_sdio_buscore_write(struct bwfm_softc *bwfm, uint32_t reg, uint32_t val)
986 {
987 	struct bwfm_sdio_softc *sc = (void *)bwfm;
988 	bwfm_sdio_write_4(sc, reg, val);
989 }
990 
991 int
992 bwfm_sdio_buscore_prepare(struct bwfm_softc *bwfm)
993 {
994 	struct bwfm_sdio_softc *sc = (void *)bwfm;
995 	uint8_t clkval, clkset, clkmask;
996 	int i;
997 
998 	clkset = BWFM_SDIO_FUNC1_CHIPCLKCSR_ALP_AVAIL_REQ |
999 	    BWFM_SDIO_FUNC1_CHIPCLKCSR_FORCE_HW_CLKREQ_OFF;
1000 	bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR, clkset);
1001 
1002 	clkmask = BWFM_SDIO_FUNC1_CHIPCLKCSR_ALP_AVAIL |
1003 	    BWFM_SDIO_FUNC1_CHIPCLKCSR_HT_AVAIL;
1004 	clkval = bwfm_sdio_read_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR);
1005 
1006 	if ((clkval & ~clkmask) != clkset) {
1007 		printf("%s: wrote 0x%02x read 0x%02x\n", DEVNAME(sc),
1008 		    clkset, clkval);
1009 		return 1;
1010 	}
1011 
1012 	for (i = 1000; i > 0; i--) {
1013 		clkval = bwfm_sdio_read_1(sc,
1014 		    BWFM_SDIO_FUNC1_CHIPCLKCSR);
1015 		if (clkval & clkmask)
1016 			break;
1017 	}
1018 	if (i == 0) {
1019 		printf("%s: timeout on ALPAV wait, clkval 0x%02x\n",
1020 		    DEVNAME(sc), clkval);
1021 		return 1;
1022 	}
1023 
1024 	clkset = BWFM_SDIO_FUNC1_CHIPCLKCSR_FORCE_HW_CLKREQ_OFF |
1025 	    BWFM_SDIO_FUNC1_CHIPCLKCSR_FORCE_ALP;
1026 	bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR, clkset);
1027 	delay(65);
1028 
1029 	bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_SDIOPULLUP, 0);
1030 
1031 	return 0;
1032 }
1033 
1034 void
1035 bwfm_sdio_buscore_activate(struct bwfm_softc *bwfm, uint32_t rstvec)
1036 {
1037 	struct bwfm_sdio_softc *sc = (void *)bwfm;
1038 
1039 	bwfm_sdio_dev_write(sc, BWFM_SDPCMD_INTSTATUS, 0xFFFFFFFF);
1040 
1041 	if (rstvec)
1042 		bwfm_sdio_ram_read_write(sc, 0, (char *)&rstvec,
1043 		    sizeof(rstvec), 1);
1044 }
1045 
1046 struct mbuf *
1047 bwfm_sdio_newbuf(void)
1048 {
1049 	struct mbuf *m;
1050 
1051 	MGETHDR(m, M_DONTWAIT, MT_DATA);
1052 	if (m == NULL)
1053 		return (NULL);
1054 
1055 	MCLGET(m, M_DONTWAIT);
1056 	if (!(m->m_flags & M_EXT)) {
1057 		m_freem(m);
1058 		return (NULL);
1059 	}
1060 
1061 	m->m_len = m->m_pkthdr.len = MCLBYTES;
1062 
1063 	return (m);
1064 }
1065 
1066 int
1067 bwfm_sdio_tx_ok(struct bwfm_sdio_softc *sc)
1068 {
1069 	return (uint8_t)(sc->sc_tx_max_seq - sc->sc_tx_seq) != 0 &&
1070 	    ((uint8_t)(sc->sc_tx_max_seq - sc->sc_tx_seq) & 0x80) == 0;
1071 }
1072 
1073 void
1074 bwfm_sdio_tx_frames(struct bwfm_sdio_softc *sc)
1075 {
1076 	struct ifnet *ifp = &sc->sc_sc.sc_ic.ic_if;
1077 	struct mbuf *m;
1078 	int i;
1079 
1080 	if (!bwfm_sdio_tx_ok(sc))
1081 		return;
1082 
1083 	i = min((uint8_t)(sc->sc_tx_max_seq - sc->sc_tx_seq), 32);
1084 	while (i--) {
1085 		m = ml_dequeue(&sc->sc_tx_queue);
1086 		if (m == NULL)
1087 			break;
1088 
1089 		if (m->m_type == MT_CONTROL)
1090 			bwfm_sdio_tx_ctrlframe(sc, m);
1091 		else
1092 			bwfm_sdio_tx_dataframe(sc, m);
1093 
1094 		m_freem(m);
1095 	}
1096 
1097 	if (sc->sc_tx_count < 64)
1098 		ifq_restart(&ifp->if_snd);
1099 }
1100 
1101 void
1102 bwfm_sdio_tx_ctrlframe(struct bwfm_sdio_softc *sc, struct mbuf *m)
1103 {
1104 	struct bwfm_sdio_hwhdr *hwhdr;
1105 	struct bwfm_sdio_swhdr *swhdr;
1106 	size_t len, roundto;
1107 
1108 	len = sizeof(*hwhdr) + sizeof(*swhdr) + m->m_len;
1109 
1110 	/* Zero-pad to either block-size or 4-byte alignment. */
1111 	if (len > 512 && (len % 512) != 0)
1112 		roundto = 512;
1113 	else
1114 		roundto = 4;
1115 
1116 	KASSERT(roundup(len, roundto) <= sc->sc_bounce_size);
1117 
1118 	hwhdr = (void *)sc->sc_bounce_buf;
1119 	hwhdr->frmlen = htole16(len);
1120 	hwhdr->cksum = htole16(~len);
1121 
1122 	swhdr = (void *)&hwhdr[1];
1123 	swhdr->seqnr = sc->sc_tx_seq++;
1124 	swhdr->chanflag = BWFM_SDIO_SWHDR_CHANNEL_CONTROL;
1125 	swhdr->nextlen = 0;
1126 	swhdr->dataoff = sizeof(*hwhdr) + sizeof(*swhdr);
1127 	swhdr->maxseqnr = 0;
1128 
1129 	m_copydata(m, 0, m->m_len, (caddr_t)&swhdr[1]);
1130 
1131 	if (roundup(len, roundto) != len)
1132 		memset(sc->sc_bounce_buf + len, 0,
1133 		    roundup(len, roundto) - len);
1134 
1135 	bwfm_sdio_frame_read_write(sc, sc->sc_bounce_buf,
1136 	    roundup(len, roundto), 1);
1137 }
1138 
1139 void
1140 bwfm_sdio_tx_dataframe(struct bwfm_sdio_softc *sc, struct mbuf *m)
1141 {
1142 	struct bwfm_sdio_hwhdr *hwhdr;
1143 	struct bwfm_sdio_swhdr *swhdr;
1144 	struct bwfm_proto_bcdc_hdr *bcdc;
1145 	size_t len, roundto;
1146 
1147 	len = sizeof(*hwhdr) + sizeof(*swhdr) + sizeof(*bcdc)
1148 	    + m->m_pkthdr.len;
1149 
1150 	/* Zero-pad to either block-size or 4-byte alignment. */
1151 	if (len > 512 && (len % 512) != 0)
1152 		roundto = 512;
1153 	else
1154 		roundto = 4;
1155 
1156 	KASSERT(roundup(len, roundto) <= sc->sc_bounce_size);
1157 
1158 	hwhdr = (void *)sc->sc_bounce_buf;
1159 	hwhdr->frmlen = htole16(len);
1160 	hwhdr->cksum = htole16(~len);
1161 
1162 	swhdr = (void *)&hwhdr[1];
1163 	swhdr->seqnr = sc->sc_tx_seq++;
1164 	swhdr->chanflag = BWFM_SDIO_SWHDR_CHANNEL_DATA;
1165 	swhdr->nextlen = 0;
1166 	swhdr->dataoff = sizeof(*hwhdr) + sizeof(*swhdr);
1167 	swhdr->maxseqnr = 0;
1168 
1169 	bcdc = (void *)&swhdr[1];
1170 	bcdc->data_offset = 0;
1171 	bcdc->priority = ieee80211_classify(&sc->sc_sc.sc_ic, m);
1172 	bcdc->flags = BWFM_BCDC_FLAG_VER(BWFM_BCDC_FLAG_PROTO_VER);
1173 	bcdc->flags2 = 0;
1174 
1175 	m_copydata(m, 0, m->m_pkthdr.len, (caddr_t)&bcdc[1]);
1176 
1177 	if (roundup(len, roundto) != len)
1178 		memset(sc->sc_bounce_buf + len, 0,
1179 		    roundup(len, roundto) - len);
1180 
1181 	bwfm_sdio_frame_read_write(sc, sc->sc_bounce_buf,
1182 	    roundup(len, roundto), 1);
1183 
1184 	sc->sc_tx_count--;
1185 }
1186 
1187 void
1188 bwfm_sdio_rx_frames(struct bwfm_sdio_softc *sc)
1189 {
1190 	struct ifnet *ifp = &sc->sc_sc.sc_ic.ic_if;
1191 	struct mbuf_list ml = MBUF_LIST_INITIALIZER();
1192 	struct bwfm_sdio_hwhdr *hwhdr;
1193 	struct bwfm_sdio_swhdr *swhdr;
1194 	uint16_t *sublen, nextlen = 0;
1195 	struct mbuf *m;
1196 	size_t flen;
1197 	char *data;
1198 	off_t off;
1199 	int nsub;
1200 
1201 	hwhdr = (struct bwfm_sdio_hwhdr *)sc->sc_bounce_buf;
1202 	swhdr = (struct bwfm_sdio_swhdr *)&hwhdr[1];
1203 	data = (char *)&swhdr[1];
1204 
1205 	for (;;) {
1206 		/* If we know the next size, just read ahead. */
1207 		if (nextlen) {
1208 			if (bwfm_sdio_frame_read_write(sc, sc->sc_bounce_buf,
1209 			    nextlen, 0))
1210 				break;
1211 		} else {
1212 			if (bwfm_sdio_frame_read_write(sc, sc->sc_bounce_buf,
1213 			    sizeof(*hwhdr) + sizeof(*swhdr), 0))
1214 				break;
1215 		}
1216 
1217 		hwhdr->frmlen = letoh16(hwhdr->frmlen);
1218 		hwhdr->cksum = letoh16(hwhdr->cksum);
1219 
1220 		if (hwhdr->frmlen == 0 && hwhdr->cksum == 0)
1221 			break;
1222 
1223 		if ((hwhdr->frmlen ^ hwhdr->cksum) != 0xffff) {
1224 			printf("%s: checksum error\n", DEVNAME(sc));
1225 			break;
1226 		}
1227 
1228 		if (hwhdr->frmlen < sizeof(*hwhdr) + sizeof(*swhdr)) {
1229 			printf("%s: length error\n", DEVNAME(sc));
1230 			break;
1231 		}
1232 
1233 		if (nextlen && hwhdr->frmlen > nextlen) {
1234 			printf("%s: read ahead length error (%u > %u)\n",
1235 			    DEVNAME(sc), hwhdr->frmlen, nextlen);
1236 			break;
1237 		}
1238 
1239 		sc->sc_tx_max_seq = swhdr->maxseqnr;
1240 
1241 		flen = hwhdr->frmlen - (sizeof(*hwhdr) + sizeof(*swhdr));
1242 		if (flen == 0) {
1243 			nextlen = swhdr->nextlen << 4;
1244 			continue;
1245 		}
1246 
1247 		if (!nextlen) {
1248 			KASSERT(roundup(flen, 4) <= sc->sc_bounce_size -
1249 			    (sizeof(*hwhdr) + sizeof(*swhdr)));
1250 			if (bwfm_sdio_frame_read_write(sc, data,
1251 			    roundup(flen, 4), 0))
1252 				break;
1253 		}
1254 
1255 		if (swhdr->dataoff < (sizeof(*hwhdr) + sizeof(*swhdr)))
1256 			break;
1257 
1258 		off = swhdr->dataoff - (sizeof(*hwhdr) + sizeof(*swhdr));
1259 		if (off > flen)
1260 			break;
1261 
1262 		switch (swhdr->chanflag & BWFM_SDIO_SWHDR_CHANNEL_MASK) {
1263 		case BWFM_SDIO_SWHDR_CHANNEL_CONTROL:
1264 			sc->sc_sc.sc_proto_ops->proto_rxctl(&sc->sc_sc,
1265 			    data + off, flen - off);
1266 			nextlen = swhdr->nextlen << 4;
1267 			break;
1268 		case BWFM_SDIO_SWHDR_CHANNEL_EVENT:
1269 		case BWFM_SDIO_SWHDR_CHANNEL_DATA:
1270 			m = bwfm_sdio_newbuf();
1271 			if (m == NULL)
1272 				break;
1273 			if (flen - off > m->m_len) {
1274 				printf("%s: frame bigger than anticipated\n",
1275 				    DEVNAME(sc));
1276 				m_freem(m);
1277 				break;
1278 			}
1279 			m->m_len = m->m_pkthdr.len = flen - off;
1280 			memcpy(mtod(m, char *), data + off, flen - off);
1281 			sc->sc_sc.sc_proto_ops->proto_rx(&sc->sc_sc, m, &ml);
1282 			nextlen = swhdr->nextlen << 4;
1283 			break;
1284 		case BWFM_SDIO_SWHDR_CHANNEL_GLOM:
1285 			if ((flen % sizeof(uint16_t)) != 0)
1286 				break;
1287 			nsub = flen / sizeof(uint16_t);
1288 			sublen = mallocarray(nsub, sizeof(uint16_t),
1289 			    M_DEVBUF, M_WAITOK | M_ZERO);
1290 			memcpy(sublen, data, nsub * sizeof(uint16_t));
1291 			bwfm_sdio_rx_glom(sc, sublen, nsub, &nextlen, &ml);
1292 			free(sublen, M_DEVBUF, nsub * sizeof(uint16_t));
1293 			break;
1294 		default:
1295 			printf("%s: unknown channel\n", DEVNAME(sc));
1296 			break;
1297 		}
1298 	}
1299 
1300 	if_input(ifp, &ml);
1301 }
1302 
1303 void
1304 bwfm_sdio_rx_glom(struct bwfm_sdio_softc *sc, uint16_t *sublen, int nsub,
1305     uint16_t *nextlen, struct mbuf_list *ml)
1306 {
1307 	struct bwfm_sdio_hwhdr hwhdr;
1308 	struct bwfm_sdio_swhdr swhdr;
1309 	struct mbuf_list glom, drop;
1310 	struct mbuf *m;
1311 	size_t flen;
1312 	off_t off;
1313 	int i;
1314 
1315 	ml_init(&glom);
1316 	ml_init(&drop);
1317 
1318 	if (nsub == 0)
1319 		return;
1320 
1321 	for (i = 0; i < nsub; i++) {
1322 		m = bwfm_sdio_newbuf();
1323 		if (m == NULL) {
1324 			ml_purge(&glom);
1325 			return;
1326 		}
1327 		ml_enqueue(&glom, m);
1328 		if (letoh16(sublen[i]) > m->m_len) {
1329 			ml_purge(&glom);
1330 			return;
1331 		}
1332 		if (bwfm_sdio_frame_read_write(sc, mtod(m, char *),
1333 		    letoh16(sublen[i]), 0)) {
1334 			ml_purge(&glom);
1335 			return;
1336 		}
1337 		m->m_len = m->m_pkthdr.len = letoh16(sublen[i]);
1338 	}
1339 
1340 	/* TODO: Verify actual superframe header */
1341 	m = MBUF_LIST_FIRST(&glom);
1342 	if (m->m_len >= sizeof(hwhdr) + sizeof(swhdr)) {
1343 		m_copydata(m, 0, sizeof(hwhdr), (caddr_t)&hwhdr);
1344 		m_copydata(m, sizeof(hwhdr), sizeof(swhdr), (caddr_t)&swhdr);
1345 		*nextlen = swhdr.nextlen << 4;
1346 		m_adj(m, sizeof(struct bwfm_sdio_hwhdr) +
1347 		    sizeof(struct bwfm_sdio_swhdr));
1348 	}
1349 
1350 	while ((m = ml_dequeue(&glom)) != NULL) {
1351 		if (m->m_len < sizeof(hwhdr) + sizeof(swhdr))
1352 			goto drop;
1353 
1354 		m_copydata(m, 0, sizeof(hwhdr), (caddr_t)&hwhdr);
1355 		m_copydata(m, sizeof(hwhdr), sizeof(swhdr), (caddr_t)&swhdr);
1356 
1357 		hwhdr.frmlen = letoh16(hwhdr.frmlen);
1358 		hwhdr.cksum = letoh16(hwhdr.cksum);
1359 
1360 		if (hwhdr.frmlen == 0 && hwhdr.cksum == 0)
1361 			goto drop;
1362 
1363 		if ((hwhdr.frmlen ^ hwhdr.cksum) != 0xffff) {
1364 			printf("%s: checksum error\n", DEVNAME(sc));
1365 			goto drop;
1366 		}
1367 
1368 		if (hwhdr.frmlen < sizeof(hwhdr) + sizeof(swhdr)) {
1369 			printf("%s: length error\n", DEVNAME(sc));
1370 			goto drop;
1371 		}
1372 
1373 		flen = hwhdr.frmlen - (sizeof(hwhdr) + sizeof(swhdr));
1374 		if (flen == 0)
1375 			goto drop;
1376 		if (m->m_len < flen)
1377 			goto drop;
1378 
1379 		if (swhdr.dataoff < (sizeof(hwhdr) + sizeof(swhdr)))
1380 			goto drop;
1381 
1382 		off = swhdr.dataoff - (sizeof(hwhdr) + sizeof(swhdr));
1383 		if (off > flen)
1384 			goto drop;
1385 
1386 		switch (swhdr.chanflag & BWFM_SDIO_SWHDR_CHANNEL_MASK) {
1387 		case BWFM_SDIO_SWHDR_CHANNEL_CONTROL:
1388 			printf("%s: control channel not allowed in glom\n",
1389 			    DEVNAME(sc));
1390 			goto drop;
1391 		case BWFM_SDIO_SWHDR_CHANNEL_EVENT:
1392 		case BWFM_SDIO_SWHDR_CHANNEL_DATA:
1393 			m_adj(m, swhdr.dataoff);
1394 			sc->sc_sc.sc_proto_ops->proto_rx(&sc->sc_sc, m, ml);
1395 			break;
1396 		case BWFM_SDIO_SWHDR_CHANNEL_GLOM:
1397 			printf("%s: glom not allowed in glom\n",
1398 			    DEVNAME(sc));
1399 			goto drop;
1400 		default:
1401 			printf("%s: unknown channel\n", DEVNAME(sc));
1402 			goto drop;
1403 		}
1404 
1405 		continue;
1406 drop:
1407 		ml_enqueue(&drop, m);
1408 	}
1409 
1410 	ml_purge(&drop);
1411 }
1412 
1413 int
1414 bwfm_sdio_txcheck(struct bwfm_softc *bwfm)
1415 {
1416 	struct bwfm_sdio_softc *sc = (void *)bwfm;
1417 
1418 	if (sc->sc_tx_count >= 64)
1419 		return ENOBUFS;
1420 
1421 	return 0;
1422 }
1423 
1424 int
1425 bwfm_sdio_txdata(struct bwfm_softc *bwfm, struct mbuf *m)
1426 {
1427 	struct bwfm_sdio_softc *sc = (void *)bwfm;
1428 
1429 	if (sc->sc_tx_count >= 64)
1430 		return ENOBUFS;
1431 
1432 	sc->sc_tx_count++;
1433 	ml_enqueue(&sc->sc_tx_queue, m);
1434 	task_add(systq, &sc->sc_task);
1435 	return 0;
1436 }
1437 
1438 int
1439 bwfm_sdio_txctl(struct bwfm_softc *bwfm, void *arg)
1440 {
1441 	struct bwfm_sdio_softc *sc = (void *)bwfm;
1442 	struct bwfm_proto_bcdc_ctl *ctl = arg;
1443 	struct mbuf *m;
1444 
1445 	KASSERT(ctl->len <= MCLBYTES);
1446 
1447 	MGET(m, M_DONTWAIT, MT_CONTROL);
1448 	if (m == NULL)
1449 		goto fail;
1450 	if (ctl->len > MLEN) {
1451 		MCLGET(m, M_DONTWAIT);
1452 		if (!(m->m_flags & M_EXT)) {
1453 			m_freem(m);
1454 			goto fail;
1455 		}
1456 	}
1457 	memcpy(mtod(m, char *), ctl->buf, ctl->len);
1458 	m->m_len = ctl->len;
1459 
1460 	TAILQ_INSERT_TAIL(&sc->sc_sc.sc_bcdc_rxctlq, ctl, next);
1461 	ml_enqueue(&sc->sc_tx_queue, m);
1462 	task_add(systq, &sc->sc_task);
1463 	return 0;
1464 
1465 fail:
1466 	free(ctl->buf, M_TEMP, ctl->len);
1467 	free(ctl, M_TEMP, sizeof(*ctl));
1468 	return 1;
1469 }
1470 
1471 #ifdef BWFM_DEBUG
1472 void
1473 bwfm_sdio_debug_console(struct bwfm_sdio_softc *sc)
1474 {
1475 	struct bwfm_sdio_console c;
1476 	uint32_t newidx;
1477 	int err;
1478 
1479 	if (!sc->sc_console_addr)
1480 		return;
1481 
1482 	err = bwfm_sdio_ram_read_write(sc, sc->sc_console_addr,
1483 	    (char *)&c, sizeof(c), 0);
1484 	if (err)
1485 		return;
1486 
1487 	c.log_buf = letoh32(c.log_buf);
1488 	c.log_bufsz = letoh32(c.log_bufsz);
1489 	c.log_idx = letoh32(c.log_idx);
1490 
1491 	if (sc->sc_console_buf == NULL) {
1492 		sc->sc_console_buf = malloc(c.log_bufsz, M_DEVBUF,
1493 		    M_WAITOK|M_ZERO);
1494 		sc->sc_console_buf_size = c.log_bufsz;
1495 	}
1496 
1497 	newidx = c.log_idx;
1498 	if (newidx >= sc->sc_console_buf_size)
1499 		return;
1500 
1501 	err = bwfm_sdio_ram_read_write(sc, c.log_buf, sc->sc_console_buf,
1502 	    sc->sc_console_buf_size, 0);
1503 	if (err)
1504 		return;
1505 
1506 	if (newidx != sc->sc_console_readidx)
1507 		DPRINTFN(3, ("BWFM CONSOLE: "));
1508 	while (newidx != sc->sc_console_readidx) {
1509 		uint8_t ch = sc->sc_console_buf[sc->sc_console_readidx];
1510 		sc->sc_console_readidx++;
1511 		if (sc->sc_console_readidx == sc->sc_console_buf_size)
1512 			sc->sc_console_readidx = 0;
1513 		if (ch == '\r')
1514 			continue;
1515 		DPRINTFN(3, ("%c", ch));
1516 	}
1517 }
1518 #endif
1519