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