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