Bug Summary

File:dev/sdmmc/if_bwfm_sdio.c
Warning:line 727, column 4
Value stored to 'intstat' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

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