Bug Summary

File:dev/sdmmc/if_bwfm_sdio.c
Warning:line 279, column 2
Value stored to 'sf' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

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