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