File: | dev/pci/if_bwfm_pci.c |
Warning: | line 847, column 4 3rd function call argument is an uninitialized value |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: if_bwfm_pci.c,v 1.75 2022/12/30 14:10:17 kettenis Exp $ */ | |||
2 | /* | |||
3 | * Copyright (c) 2010-2016 Broadcom Corporation | |||
4 | * Copyright (c) 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 | ||||
30 | #if defined(__HAVE_FDT) | |||
31 | #include <machine/fdt.h> | |||
32 | #include <dev/ofw/openfirm.h> | |||
33 | #endif | |||
34 | ||||
35 | #if NBPFILTER1 > 0 | |||
36 | #include <net/bpf.h> | |||
37 | #endif | |||
38 | #include <net/if.h> | |||
39 | #include <net/if_dl.h> | |||
40 | #include <net/if_media.h> | |||
41 | ||||
42 | #include <netinet/in.h> | |||
43 | #include <netinet/if_ether.h> | |||
44 | ||||
45 | #include <net80211/ieee80211_var.h> | |||
46 | ||||
47 | #include <machine/bus.h> | |||
48 | ||||
49 | #include <dev/pci/pcireg.h> | |||
50 | #include <dev/pci/pcivar.h> | |||
51 | #include <dev/pci/pcidevs.h> | |||
52 | ||||
53 | #include <dev/ic/bwfmvar.h> | |||
54 | #include <dev/ic/bwfmreg.h> | |||
55 | #include <dev/pci/if_bwfm_pci.h> | |||
56 | ||||
57 | #define BWFM_DMA_D2H_SCRATCH_BUF_LEN8 8 | |||
58 | #define BWFM_DMA_D2H_RINGUPD_BUF_LEN1024 1024 | |||
59 | #define BWFM_DMA_H2D_IOCTL_BUF_LEN1518 ETHER_MAX_LEN1518 | |||
60 | ||||
61 | #define BWFM_NUM_TX_MSGRINGS2 2 | |||
62 | #define BWFM_NUM_RX_MSGRINGS3 3 | |||
63 | ||||
64 | #define BWFM_NUM_IOCTL_PKTIDS8 8 | |||
65 | #define BWFM_NUM_TX_PKTIDS2048 2048 | |||
66 | #define BWFM_NUM_RX_PKTIDS1024 1024 | |||
67 | ||||
68 | #define BWFM_NUM_IOCTL_DESCS1 1 | |||
69 | #define BWFM_NUM_TX_DESCS1 1 | |||
70 | #define BWFM_NUM_RX_DESCS1 1 | |||
71 | ||||
72 | #ifdef BWFM_DEBUG | |||
73 | #define DPRINTF(x)do { ; } while (0) do { if (bwfm_debug > 0) printf x; } while (0) | |||
74 | #define DPRINTFN(n, x)do { ; } while (0) do { if (bwfm_debug >= (n)) printf x; } while (0) | |||
75 | static int bwfm_debug = 2; | |||
76 | #else | |||
77 | #define DPRINTF(x)do { ; } while (0) do { ; } while (0) | |||
78 | #define DPRINTFN(n, x)do { ; } while (0) do { ; } while (0) | |||
79 | #endif | |||
80 | ||||
81 | #define DEVNAME(sc)((sc)->sc_sc.sc_dev.dv_xname) ((sc)->sc_sc.sc_dev.dv_xname) | |||
82 | ||||
83 | enum ring_status { | |||
84 | RING_CLOSED, | |||
85 | RING_CLOSING, | |||
86 | RING_OPEN, | |||
87 | RING_OPENING, | |||
88 | }; | |||
89 | ||||
90 | struct bwfm_pci_msgring { | |||
91 | uint32_t w_idx_addr; | |||
92 | uint32_t r_idx_addr; | |||
93 | uint32_t w_ptr; | |||
94 | uint32_t r_ptr; | |||
95 | int nitem; | |||
96 | int itemsz; | |||
97 | enum ring_status status; | |||
98 | struct bwfm_pci_dmamem *ring; | |||
99 | struct mbuf *m; | |||
100 | ||||
101 | int fifo; | |||
102 | uint8_t mac[ETHER_ADDR_LEN6]; | |||
103 | }; | |||
104 | ||||
105 | struct bwfm_pci_ioctl { | |||
106 | uint16_t transid; | |||
107 | uint16_t retlen; | |||
108 | int16_t status; | |||
109 | struct mbuf *m; | |||
110 | TAILQ_ENTRY(bwfm_pci_ioctl)struct { struct bwfm_pci_ioctl *tqe_next; struct bwfm_pci_ioctl **tqe_prev; } next; | |||
111 | }; | |||
112 | ||||
113 | struct bwfm_pci_buf { | |||
114 | bus_dmamap_t bb_map; | |||
115 | struct mbuf *bb_m; | |||
116 | }; | |||
117 | ||||
118 | struct bwfm_pci_pkts { | |||
119 | struct bwfm_pci_buf *pkts; | |||
120 | uint32_t npkt; | |||
121 | int last; | |||
122 | }; | |||
123 | ||||
124 | struct bwfm_pci_softc { | |||
125 | struct bwfm_softc sc_sc; | |||
126 | pci_chipset_tag_t sc_pc; | |||
127 | pcitag_t sc_tag; | |||
128 | pcireg_t sc_id; | |||
129 | void *sc_ih; | |||
130 | ||||
131 | int sc_initialized; | |||
132 | ||||
133 | bus_space_tag_t sc_reg_iot; | |||
134 | bus_space_handle_t sc_reg_ioh; | |||
135 | bus_size_t sc_reg_ios; | |||
136 | ||||
137 | bus_space_tag_t sc_tcm_iot; | |||
138 | bus_space_handle_t sc_tcm_ioh; | |||
139 | bus_size_t sc_tcm_ios; | |||
140 | ||||
141 | bus_dma_tag_t sc_dmat; | |||
142 | ||||
143 | uint32_t sc_shared_address; | |||
144 | uint32_t sc_shared_flags; | |||
145 | uint8_t sc_shared_version; | |||
146 | ||||
147 | uint8_t sc_dma_idx_sz; | |||
148 | struct bwfm_pci_dmamem *sc_dma_idx_buf; | |||
149 | size_t sc_dma_idx_bufsz; | |||
150 | ||||
151 | uint16_t sc_max_rxbufpost; | |||
152 | uint32_t sc_rx_dataoffset; | |||
153 | uint32_t sc_htod_mb_data_addr; | |||
154 | uint32_t sc_dtoh_mb_data_addr; | |||
155 | uint32_t sc_ring_info_addr; | |||
156 | ||||
157 | uint32_t sc_console_base_addr; | |||
158 | uint32_t sc_console_buf_addr; | |||
159 | uint32_t sc_console_buf_size; | |||
160 | uint32_t sc_console_readidx; | |||
161 | ||||
162 | uint16_t sc_max_flowrings; | |||
163 | uint16_t sc_max_submissionrings; | |||
164 | uint16_t sc_max_completionrings; | |||
165 | ||||
166 | struct bwfm_pci_msgring sc_ctrl_submit; | |||
167 | struct bwfm_pci_msgring sc_rxpost_submit; | |||
168 | struct bwfm_pci_msgring sc_ctrl_complete; | |||
169 | struct bwfm_pci_msgring sc_tx_complete; | |||
170 | struct bwfm_pci_msgring sc_rx_complete; | |||
171 | struct bwfm_pci_msgring *sc_flowrings; | |||
172 | ||||
173 | struct bwfm_pci_dmamem *sc_scratch_buf; | |||
174 | struct bwfm_pci_dmamem *sc_ringupd_buf; | |||
175 | ||||
176 | TAILQ_HEAD(, bwfm_pci_ioctl)struct { struct bwfm_pci_ioctl *tqh_first; struct bwfm_pci_ioctl **tqh_last; } sc_ioctlq; | |||
177 | uint16_t sc_ioctl_transid; | |||
178 | ||||
179 | struct if_rxring sc_ioctl_ring; | |||
180 | struct if_rxring sc_event_ring; | |||
181 | struct if_rxring sc_rxbuf_ring; | |||
182 | ||||
183 | struct bwfm_pci_pkts sc_ioctl_pkts; | |||
184 | struct bwfm_pci_pkts sc_rx_pkts; | |||
185 | struct bwfm_pci_pkts sc_tx_pkts; | |||
186 | int sc_tx_pkts_full; | |||
187 | ||||
188 | uint8_t sc_mbdata_done; | |||
189 | uint8_t sc_pcireg64; | |||
190 | uint8_t sc_mb_via_ctl; | |||
191 | }; | |||
192 | ||||
193 | struct bwfm_pci_dmamem { | |||
194 | bus_dmamap_t bdm_map; | |||
195 | bus_dma_segment_t bdm_seg; | |||
196 | size_t bdm_size; | |||
197 | caddr_t bdm_kva; | |||
198 | }; | |||
199 | ||||
200 | #define BWFM_PCI_DMA_MAP(_bdm)((_bdm)->bdm_map) ((_bdm)->bdm_map) | |||
201 | #define BWFM_PCI_DMA_LEN(_bdm)((_bdm)->bdm_size) ((_bdm)->bdm_size) | |||
202 | #define BWFM_PCI_DMA_DVA(_bdm)((uint64_t)(_bdm)->bdm_map->dm_segs[0].ds_addr) ((uint64_t)(_bdm)->bdm_map->dm_segs[0].ds_addr) | |||
203 | #define BWFM_PCI_DMA_KVA(_bdm)((void *)(_bdm)->bdm_kva) ((void *)(_bdm)->bdm_kva) | |||
204 | ||||
205 | int bwfm_pci_match(struct device *, void *, void *); | |||
206 | void bwfm_pci_attach(struct device *, struct device *, void *); | |||
207 | int bwfm_pci_detach(struct device *, int); | |||
208 | int bwfm_pci_activate(struct device *, int); | |||
209 | void bwfm_pci_cleanup(struct bwfm_pci_softc *); | |||
210 | ||||
211 | #if defined(__HAVE_FDT) | |||
212 | int bwfm_pci_read_otp(struct bwfm_pci_softc *); | |||
213 | void bwfm_pci_process_otp_tuple(struct bwfm_pci_softc *, uint8_t, | |||
214 | uint8_t, uint8_t *); | |||
215 | #endif | |||
216 | ||||
217 | int bwfm_pci_intr(void *); | |||
218 | void bwfm_pci_intr_enable(struct bwfm_pci_softc *); | |||
219 | void bwfm_pci_intr_disable(struct bwfm_pci_softc *); | |||
220 | uint32_t bwfm_pci_intr_status(struct bwfm_pci_softc *); | |||
221 | void bwfm_pci_intr_ack(struct bwfm_pci_softc *, uint32_t); | |||
222 | uint32_t bwfm_pci_intmask(struct bwfm_pci_softc *); | |||
223 | void bwfm_pci_hostready(struct bwfm_pci_softc *); | |||
224 | int bwfm_pci_load_microcode(struct bwfm_pci_softc *, const u_char *, | |||
225 | size_t, const u_char *, size_t); | |||
226 | void bwfm_pci_select_core(struct bwfm_pci_softc *, int ); | |||
227 | ||||
228 | struct bwfm_pci_dmamem * | |||
229 | bwfm_pci_dmamem_alloc(struct bwfm_pci_softc *, bus_size_t, | |||
230 | bus_size_t); | |||
231 | void bwfm_pci_dmamem_free(struct bwfm_pci_softc *, struct bwfm_pci_dmamem *); | |||
232 | int bwfm_pci_pktid_avail(struct bwfm_pci_softc *, | |||
233 | struct bwfm_pci_pkts *); | |||
234 | int bwfm_pci_pktid_new(struct bwfm_pci_softc *, | |||
235 | struct bwfm_pci_pkts *, struct mbuf *, | |||
236 | uint32_t *, paddr_t *); | |||
237 | struct mbuf * bwfm_pci_pktid_free(struct bwfm_pci_softc *, | |||
238 | struct bwfm_pci_pkts *, uint32_t); | |||
239 | void bwfm_pci_fill_rx_ioctl_ring(struct bwfm_pci_softc *, | |||
240 | struct if_rxring *, uint32_t); | |||
241 | void bwfm_pci_fill_rx_buf_ring(struct bwfm_pci_softc *); | |||
242 | void bwfm_pci_fill_rx_rings(struct bwfm_pci_softc *); | |||
243 | int bwfm_pci_setup_ring(struct bwfm_pci_softc *, struct bwfm_pci_msgring *, | |||
244 | int, size_t, uint32_t, uint32_t, int, uint32_t, uint32_t *); | |||
245 | int bwfm_pci_setup_flowring(struct bwfm_pci_softc *, struct bwfm_pci_msgring *, | |||
246 | int, size_t); | |||
247 | ||||
248 | void bwfm_pci_ring_bell(struct bwfm_pci_softc *, | |||
249 | struct bwfm_pci_msgring *); | |||
250 | void bwfm_pci_ring_update_rptr(struct bwfm_pci_softc *, | |||
251 | struct bwfm_pci_msgring *); | |||
252 | void bwfm_pci_ring_update_wptr(struct bwfm_pci_softc *, | |||
253 | struct bwfm_pci_msgring *); | |||
254 | void bwfm_pci_ring_write_rptr(struct bwfm_pci_softc *, | |||
255 | struct bwfm_pci_msgring *); | |||
256 | void bwfm_pci_ring_write_wptr(struct bwfm_pci_softc *, | |||
257 | struct bwfm_pci_msgring *); | |||
258 | void * bwfm_pci_ring_write_reserve(struct bwfm_pci_softc *, | |||
259 | struct bwfm_pci_msgring *); | |||
260 | void * bwfm_pci_ring_write_reserve_multi(struct bwfm_pci_softc *, | |||
261 | struct bwfm_pci_msgring *, int, int *); | |||
262 | void * bwfm_pci_ring_read_avail(struct bwfm_pci_softc *, | |||
263 | struct bwfm_pci_msgring *, int *); | |||
264 | void bwfm_pci_ring_read_commit(struct bwfm_pci_softc *, | |||
265 | struct bwfm_pci_msgring *, int); | |||
266 | void bwfm_pci_ring_write_commit(struct bwfm_pci_softc *, | |||
267 | struct bwfm_pci_msgring *); | |||
268 | void bwfm_pci_ring_write_cancel(struct bwfm_pci_softc *, | |||
269 | struct bwfm_pci_msgring *, int); | |||
270 | ||||
271 | void bwfm_pci_ring_rx(struct bwfm_pci_softc *, | |||
272 | struct bwfm_pci_msgring *, struct mbuf_list *); | |||
273 | void bwfm_pci_msg_rx(struct bwfm_pci_softc *, void *, | |||
274 | struct mbuf_list *); | |||
275 | ||||
276 | uint32_t bwfm_pci_buscore_read(struct bwfm_softc *, uint32_t); | |||
277 | void bwfm_pci_buscore_write(struct bwfm_softc *, uint32_t, | |||
278 | uint32_t); | |||
279 | int bwfm_pci_buscore_prepare(struct bwfm_softc *); | |||
280 | int bwfm_pci_buscore_reset(struct bwfm_softc *); | |||
281 | void bwfm_pci_buscore_activate(struct bwfm_softc *, uint32_t); | |||
282 | ||||
283 | int bwfm_pci_flowring_lookup(struct bwfm_pci_softc *, | |||
284 | struct mbuf *); | |||
285 | void bwfm_pci_flowring_create(struct bwfm_pci_softc *, | |||
286 | struct mbuf *); | |||
287 | void bwfm_pci_flowring_create_cb(struct bwfm_softc *, void *); | |||
288 | void bwfm_pci_flowring_delete(struct bwfm_pci_softc *, int); | |||
289 | void bwfm_pci_flowring_delete_cb(struct bwfm_softc *, void *); | |||
290 | ||||
291 | int bwfm_pci_preinit(struct bwfm_softc *); | |||
292 | void bwfm_pci_stop(struct bwfm_softc *); | |||
293 | int bwfm_pci_txcheck(struct bwfm_softc *); | |||
294 | int bwfm_pci_txdata(struct bwfm_softc *, struct mbuf *); | |||
295 | ||||
296 | int bwfm_pci_send_mb_data(struct bwfm_pci_softc *, uint32_t); | |||
297 | void bwfm_pci_handle_mb_data(struct bwfm_pci_softc *); | |||
298 | ||||
299 | #ifdef BWFM_DEBUG | |||
300 | void bwfm_pci_debug_console(struct bwfm_pci_softc *); | |||
301 | #endif | |||
302 | ||||
303 | int bwfm_pci_msgbuf_query_dcmd(struct bwfm_softc *, int, | |||
304 | int, char *, size_t *); | |||
305 | int bwfm_pci_msgbuf_set_dcmd(struct bwfm_softc *, int, | |||
306 | int, char *, size_t); | |||
307 | void bwfm_pci_msgbuf_rxioctl(struct bwfm_pci_softc *, | |||
308 | struct msgbuf_ioctl_resp_hdr *); | |||
309 | int bwfm_pci_msgbuf_h2d_mb_write(struct bwfm_pci_softc *, | |||
310 | uint32_t); | |||
311 | ||||
312 | struct bwfm_buscore_ops bwfm_pci_buscore_ops = { | |||
313 | .bc_read = bwfm_pci_buscore_read, | |||
314 | .bc_write = bwfm_pci_buscore_write, | |||
315 | .bc_prepare = bwfm_pci_buscore_prepare, | |||
316 | .bc_reset = bwfm_pci_buscore_reset, | |||
317 | .bc_setup = NULL((void *)0), | |||
318 | .bc_activate = bwfm_pci_buscore_activate, | |||
319 | }; | |||
320 | ||||
321 | struct bwfm_bus_ops bwfm_pci_bus_ops = { | |||
322 | .bs_preinit = bwfm_pci_preinit, | |||
323 | .bs_stop = bwfm_pci_stop, | |||
324 | .bs_txcheck = bwfm_pci_txcheck, | |||
325 | .bs_txdata = bwfm_pci_txdata, | |||
326 | .bs_txctl = NULL((void *)0), | |||
327 | }; | |||
328 | ||||
329 | struct bwfm_proto_ops bwfm_pci_msgbuf_ops = { | |||
330 | .proto_query_dcmd = bwfm_pci_msgbuf_query_dcmd, | |||
331 | .proto_set_dcmd = bwfm_pci_msgbuf_set_dcmd, | |||
332 | .proto_rx = NULL((void *)0), | |||
333 | .proto_rxctl = NULL((void *)0), | |||
334 | }; | |||
335 | ||||
336 | const struct cfattach bwfm_pci_ca = { | |||
337 | sizeof(struct bwfm_pci_softc), | |||
338 | bwfm_pci_match, | |||
339 | bwfm_pci_attach, | |||
340 | bwfm_pci_detach, | |||
341 | bwfm_pci_activate, | |||
342 | }; | |||
343 | ||||
344 | static const struct pci_matchid bwfm_pci_devices[] = { | |||
345 | { PCI_VENDOR_BROADCOM0x14e4, PCI_PRODUCT_BROADCOM_BCM43500x43a3 }, | |||
346 | { PCI_VENDOR_BROADCOM0x14e4, PCI_PRODUCT_BROADCOM_BCM43560x43ec }, | |||
347 | { PCI_VENDOR_BROADCOM0x14e4, PCI_PRODUCT_BROADCOM_BCM436020x43ba }, | |||
348 | { PCI_VENDOR_BROADCOM0x14e4, PCI_PRODUCT_BROADCOM_BCM43710x440d }, | |||
349 | { PCI_VENDOR_BROADCOM0x14e4, PCI_PRODUCT_BROADCOM_BCM43780x4425 }, | |||
350 | { PCI_VENDOR_BROADCOM0x14e4, PCI_PRODUCT_BROADCOM_BCM43870x4433 }, | |||
351 | }; | |||
352 | ||||
353 | int | |||
354 | bwfm_pci_match(struct device *parent, void *match, void *aux) | |||
355 | { | |||
356 | return (pci_matchbyid(aux, bwfm_pci_devices, | |||
357 | nitems(bwfm_pci_devices)(sizeof((bwfm_pci_devices)) / sizeof((bwfm_pci_devices)[0])))); | |||
358 | } | |||
359 | ||||
360 | void | |||
361 | bwfm_pci_attach(struct device *parent, struct device *self, void *aux) | |||
362 | { | |||
363 | struct bwfm_pci_softc *sc = (struct bwfm_pci_softc *)self; | |||
364 | struct pci_attach_args *pa = (struct pci_attach_args *)aux; | |||
365 | const char *intrstr; | |||
366 | pci_intr_handle_t ih; | |||
367 | ||||
368 | if (pci_mapreg_map(pa, PCI_MAPREG_START0x10 + 0x08, | |||
369 | PCI_MAPREG_MEM_TYPE_64BIT0x00000004, 0, &sc->sc_tcm_iot, &sc->sc_tcm_ioh, | |||
370 | NULL((void *)0), &sc->sc_tcm_ios, 0)) { | |||
371 | printf(": can't map bar1\n"); | |||
372 | return; | |||
373 | } | |||
374 | ||||
375 | if (pci_mapreg_map(pa, PCI_MAPREG_START0x10 + 0x00, | |||
376 | PCI_MAPREG_MEM_TYPE_64BIT0x00000004, 0, &sc->sc_reg_iot, &sc->sc_reg_ioh, | |||
377 | NULL((void *)0), &sc->sc_reg_ios, 0)) { | |||
378 | printf(": can't map bar0\n"); | |||
379 | goto bar1; | |||
380 | } | |||
381 | ||||
382 | sc->sc_pc = pa->pa_pc; | |||
383 | sc->sc_tag = pa->pa_tag; | |||
384 | sc->sc_id = pa->pa_id; | |||
385 | sc->sc_dmat = pa->pa_dmat; | |||
386 | ||||
387 | /* Map and establish the interrupt. */ | |||
388 | if (pci_intr_map_msi(pa, &ih) != 0 && pci_intr_map(pa, &ih) != 0) { | |||
389 | printf(": couldn't map interrupt\n"); | |||
390 | goto bar0; | |||
391 | } | |||
392 | intrstr = pci_intr_string(pa->pa_pc, ih); | |||
393 | ||||
394 | sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_NET0x4, | |||
395 | bwfm_pci_intr, sc, DEVNAME(sc)((sc)->sc_sc.sc_dev.dv_xname)); | |||
396 | if (sc->sc_ih == NULL((void *)0)) { | |||
397 | printf(": couldn't establish interrupt"); | |||
398 | if (intrstr != NULL((void *)0)) | |||
399 | printf(" at %s", intrstr); | |||
400 | printf("\n"); | |||
401 | goto bar1; | |||
402 | } | |||
403 | printf(": %s\n", intrstr); | |||
404 | ||||
405 | #if defined(__HAVE_FDT) | |||
406 | sc->sc_sc.sc_node = PCITAG_NODE(pa->pa_tag); | |||
407 | if (sc->sc_sc.sc_node) { | |||
408 | if (OF_getproplen(sc->sc_sc.sc_node, "brcm,cal-blob") > 0) { | |||
409 | sc->sc_sc.sc_calsize = OF_getproplen(sc->sc_sc.sc_node, | |||
410 | "brcm,cal-blob"); | |||
411 | sc->sc_sc.sc_cal = malloc(sc->sc_sc.sc_calsize, | |||
412 | M_DEVBUF2, M_WAITOK0x0001); | |||
413 | OF_getprop(sc->sc_sc.sc_node, "brcm,cal-blob", | |||
414 | sc->sc_sc.sc_cal, sc->sc_sc.sc_calsize); | |||
415 | } | |||
416 | } | |||
417 | #endif | |||
418 | ||||
419 | sc->sc_sc.sc_bus_ops = &bwfm_pci_bus_ops; | |||
420 | sc->sc_sc.sc_proto_ops = &bwfm_pci_msgbuf_ops; | |||
421 | bwfm_attach(&sc->sc_sc); | |||
422 | config_mountroot(self, bwfm_attachhook); | |||
423 | return; | |||
424 | ||||
425 | bar0: | |||
426 | bus_space_unmap(sc->sc_reg_iot, sc->sc_reg_ioh, sc->sc_reg_ios); | |||
427 | bar1: | |||
428 | bus_space_unmap(sc->sc_tcm_iot, sc->sc_tcm_ioh, sc->sc_tcm_ios); | |||
429 | } | |||
430 | ||||
431 | int | |||
432 | bwfm_pci_preinit(struct bwfm_softc *bwfm) | |||
433 | { | |||
434 | struct bwfm_pci_softc *sc = (void *)bwfm; | |||
435 | struct bwfm_pci_ringinfo ringinfo; | |||
436 | const char *chip = NULL((void *)0); | |||
437 | u_char *ucode, *nvram; | |||
438 | size_t size, nvsize, nvlen; | |||
439 | uint32_t d2h_w_idx_ptr, d2h_r_idx_ptr; | |||
440 | uint32_t h2d_w_idx_ptr, h2d_r_idx_ptr; | |||
441 | uint32_t idx_offset, reg; | |||
442 | int i; | |||
443 | ||||
444 | if (sc->sc_initialized) | |||
| ||||
445 | return 0; | |||
446 | ||||
447 | sc->sc_sc.sc_buscore_ops = &bwfm_pci_buscore_ops; | |||
448 | if (bwfm_chip_attach(&sc->sc_sc) != 0) { | |||
449 | printf("%s: cannot attach chip\n", DEVNAME(sc)((sc)->sc_sc.sc_dev.dv_xname)); | |||
450 | return 1; | |||
451 | } | |||
452 | ||||
453 | #if defined(__HAVE_FDT) | |||
454 | if (bwfm_pci_read_otp(sc)) { | |||
455 | printf("%s: cannot read OTP\n", DEVNAME(sc)((sc)->sc_sc.sc_dev.dv_xname)); | |||
456 | return 1; | |||
457 | } | |||
458 | #endif | |||
459 | ||||
460 | bwfm_pci_select_core(sc, BWFM_AGENT_CORE_PCIE20x83C); | |||
461 | bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,((sc->sc_reg_iot)->write_4((sc->sc_reg_ioh), (0x120) , (0x4e0))) | |||
462 | BWFM_PCI_PCIE2REG_CONFIGADDR, 0x4e0)((sc->sc_reg_iot)->write_4((sc->sc_reg_ioh), (0x120) , (0x4e0))); | |||
463 | reg = bus_space_read_4(sc->sc_reg_iot, sc->sc_reg_ioh,((sc->sc_reg_iot)->read_4((sc->sc_reg_ioh), (0x124)) ) | |||
464 | BWFM_PCI_PCIE2REG_CONFIGDATA)((sc->sc_reg_iot)->read_4((sc->sc_reg_ioh), (0x124)) ); | |||
465 | bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,((sc->sc_reg_iot)->write_4((sc->sc_reg_ioh), (0x124) , (reg))) | |||
466 | BWFM_PCI_PCIE2REG_CONFIGDATA, reg)((sc->sc_reg_iot)->write_4((sc->sc_reg_ioh), (0x124) , (reg))); | |||
467 | ||||
468 | switch (bwfm->sc_chip.ch_chip) { | |||
469 | case BRCM_CC_4350_CHIP_ID0x4350: | |||
470 | if (bwfm->sc_chip.ch_chiprev <= 7) | |||
471 | chip = "4350c2"; | |||
472 | else | |||
473 | chip = "4350"; | |||
474 | break; | |||
475 | case BRCM_CC_4355_CHIP_ID0x4355: | |||
476 | chip = "4355c1"; | |||
477 | break; | |||
478 | case BRCM_CC_4356_CHIP_ID0x4356: | |||
479 | chip = "4356"; | |||
480 | break; | |||
481 | case BRCM_CC_4364_CHIP_ID0x4364: | |||
482 | if (bwfm->sc_chip.ch_chiprev <= 3) | |||
483 | chip = "4364b2"; | |||
484 | else | |||
485 | chip = "4364b3"; | |||
486 | break; | |||
487 | case BRCM_CC_43602_CHIP_ID43602: | |||
488 | chip = "43602"; | |||
489 | break; | |||
490 | case BRCM_CC_4371_CHIP_ID0x4371: | |||
491 | chip = "4371"; | |||
492 | break; | |||
493 | case BRCM_CC_4377_CHIP_ID0x4377: | |||
494 | chip = "4377b3"; | |||
495 | break; | |||
496 | case BRCM_CC_4378_CHIP_ID0x4378: | |||
497 | if (bwfm->sc_chip.ch_chiprev <= 3) | |||
498 | chip = "4378b1"; | |||
499 | else | |||
500 | chip = "4378b3"; | |||
501 | break; | |||
502 | case BRCM_CC_4387_CHIP_ID0x4387: | |||
503 | chip = "4387c2"; | |||
504 | break; | |||
505 | default: | |||
506 | printf("%s: unknown firmware for chip %s\n", | |||
507 | DEVNAME(sc)((sc)->sc_sc.sc_dev.dv_xname), bwfm->sc_chip.ch_name); | |||
508 | return 1; | |||
509 | } | |||
510 | ||||
511 | if (bwfm_loadfirmware(bwfm, chip, "-pcie", &ucode, &size, | |||
512 | &nvram, &nvsize, &nvlen) != 0) | |||
513 | return 1; | |||
514 | ||||
515 | /* Retrieve RAM size from firmware. */ | |||
516 | if (size >= BWFM_RAMSIZE0x6c + 8) { | |||
517 | uint32_t *ramsize = (uint32_t *)&ucode[BWFM_RAMSIZE0x6c]; | |||
518 | if (letoh32(ramsize[0])((__uint32_t)(ramsize[0])) == BWFM_RAMSIZE_MAGIC0x534d4152) | |||
519 | bwfm->sc_chip.ch_ramsize = letoh32(ramsize[1])((__uint32_t)(ramsize[1])); | |||
520 | } | |||
521 | ||||
522 | if (bwfm_pci_load_microcode(sc, ucode, size, nvram, nvlen) != 0) { | |||
523 | printf("%s: could not load microcode\n", | |||
524 | DEVNAME(sc)((sc)->sc_sc.sc_dev.dv_xname)); | |||
525 | free(ucode, M_DEVBUF2, size); | |||
526 | free(nvram, M_DEVBUF2, nvsize); | |||
527 | return 1; | |||
528 | } | |||
529 | free(ucode, M_DEVBUF2, size); | |||
530 | free(nvram, M_DEVBUF2, nvsize); | |||
531 | ||||
532 | sc->sc_shared_flags = bus_space_read_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,((sc->sc_tcm_iot)->read_4((sc->sc_tcm_ioh), (sc-> sc_shared_address + 0x000))) | |||
533 | sc->sc_shared_address + BWFM_SHARED_INFO)((sc->sc_tcm_iot)->read_4((sc->sc_tcm_ioh), (sc-> sc_shared_address + 0x000))); | |||
534 | sc->sc_shared_version = sc->sc_shared_flags; | |||
535 | if (sc->sc_shared_version > BWFM_SHARED_INFO_MAX_VERSION7 || | |||
536 | sc->sc_shared_version < BWFM_SHARED_INFO_MIN_VERSION5) { | |||
537 | printf("%s: PCIe version %d unsupported\n", | |||
538 | DEVNAME(sc)((sc)->sc_sc.sc_dev.dv_xname), sc->sc_shared_version); | |||
539 | return 1; | |||
540 | } | |||
541 | ||||
542 | if (sc->sc_shared_version >= 6) { | |||
543 | uint32_t host_cap; | |||
544 | ||||
545 | if ((sc->sc_shared_flags & BWFM_SHARED_INFO_USE_MAILBOX0x2000000) == 0) | |||
546 | sc->sc_mb_via_ctl = 1; | |||
547 | ||||
548 | host_cap = sc->sc_shared_version; | |||
549 | if (sc->sc_shared_flags & BWFM_SHARED_INFO_HOSTRDY_DB10x10000000) | |||
550 | host_cap |= BWFM_SHARED_HOST_CAP_H2D_ENABLE_HOSTRDY0x00000400; | |||
551 | if (sc->sc_shared_flags & BWFM_SHARED_INFO_SHARED_DAR0x80000000) | |||
552 | host_cap |= BWFM_SHARED_HOST_CAP_H2D_DAR0x00010000; | |||
553 | host_cap |= BWFM_SHARED_HOST_CAP_DS_NO_OOB_DW0x00001000; | |||
554 | ||||
555 | bus_space_write_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,((sc->sc_tcm_iot)->write_4((sc->sc_tcm_ioh), (sc-> sc_shared_address + 0x54), (host_cap))) | |||
556 | sc->sc_shared_address + BWFM_SHARED_HOST_CAP, host_cap)((sc->sc_tcm_iot)->write_4((sc->sc_tcm_ioh), (sc-> sc_shared_address + 0x54), (host_cap))); | |||
557 | bus_space_write_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,((sc->sc_tcm_iot)->write_4((sc->sc_tcm_ioh), (sc-> sc_shared_address + 0x70), (0))) | |||
558 | sc->sc_shared_address + BWFM_SHARED_HOST_CAP2, 0)((sc->sc_tcm_iot)->write_4((sc->sc_tcm_ioh), (sc-> sc_shared_address + 0x70), (0))); | |||
559 | } | |||
560 | ||||
561 | sc->sc_dma_idx_sz = 0; | |||
562 | if (sc->sc_shared_flags & BWFM_SHARED_INFO_DMA_INDEX0x10000) { | |||
563 | if (sc->sc_shared_flags & BWFM_SHARED_INFO_DMA_2B_IDX0x100000) | |||
564 | sc->sc_dma_idx_sz = sizeof(uint16_t); | |||
565 | else | |||
566 | sc->sc_dma_idx_sz = sizeof(uint32_t); | |||
567 | } | |||
568 | ||||
569 | /* Maximum RX data buffers in the ring. */ | |||
570 | sc->sc_max_rxbufpost = bus_space_read_2(sc->sc_tcm_iot, sc->sc_tcm_ioh,((sc->sc_tcm_iot)->read_2((sc->sc_tcm_ioh), (sc-> sc_shared_address + 0x22))) | |||
571 | sc->sc_shared_address + BWFM_SHARED_MAX_RXBUFPOST)((sc->sc_tcm_iot)->read_2((sc->sc_tcm_ioh), (sc-> sc_shared_address + 0x22))); | |||
572 | if (sc->sc_max_rxbufpost == 0) | |||
573 | sc->sc_max_rxbufpost = BWFM_SHARED_MAX_RXBUFPOST_DEFAULT255; | |||
574 | ||||
575 | /* Alternative offset of data in a packet */ | |||
576 | sc->sc_rx_dataoffset = bus_space_read_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,((sc->sc_tcm_iot)->read_4((sc->sc_tcm_ioh), (sc-> sc_shared_address + 0x24))) | |||
577 | sc->sc_shared_address + BWFM_SHARED_RX_DATAOFFSET)((sc->sc_tcm_iot)->read_4((sc->sc_tcm_ioh), (sc-> sc_shared_address + 0x24))); | |||
578 | ||||
579 | /* For Power Management */ | |||
580 | sc->sc_htod_mb_data_addr = bus_space_read_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,((sc->sc_tcm_iot)->read_4((sc->sc_tcm_ioh), (sc-> sc_shared_address + 0x28))) | |||
581 | sc->sc_shared_address + BWFM_SHARED_HTOD_MB_DATA_ADDR)((sc->sc_tcm_iot)->read_4((sc->sc_tcm_ioh), (sc-> sc_shared_address + 0x28))); | |||
582 | sc->sc_dtoh_mb_data_addr = bus_space_read_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,((sc->sc_tcm_iot)->read_4((sc->sc_tcm_ioh), (sc-> sc_shared_address + 0x2c))) | |||
583 | sc->sc_shared_address + BWFM_SHARED_DTOH_MB_DATA_ADDR)((sc->sc_tcm_iot)->read_4((sc->sc_tcm_ioh), (sc-> sc_shared_address + 0x2c))); | |||
584 | ||||
585 | /* Ring information */ | |||
586 | sc->sc_ring_info_addr = bus_space_read_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,((sc->sc_tcm_iot)->read_4((sc->sc_tcm_ioh), (sc-> sc_shared_address + 0x30))) | |||
587 | sc->sc_shared_address + BWFM_SHARED_RING_INFO_ADDR)((sc->sc_tcm_iot)->read_4((sc->sc_tcm_ioh), (sc-> sc_shared_address + 0x30))); | |||
588 | ||||
589 | /* Firmware's "dmesg" */ | |||
590 | sc->sc_console_base_addr = bus_space_read_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,((sc->sc_tcm_iot)->read_4((sc->sc_tcm_ioh), (sc-> sc_shared_address + 0x14))) | |||
591 | sc->sc_shared_address + BWFM_SHARED_CONSOLE_ADDR)((sc->sc_tcm_iot)->read_4((sc->sc_tcm_ioh), (sc-> sc_shared_address + 0x14))); | |||
592 | sc->sc_console_buf_addr = bus_space_read_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,((sc->sc_tcm_iot)->read_4((sc->sc_tcm_ioh), (sc-> sc_console_base_addr + 0x08))) | |||
593 | sc->sc_console_base_addr + BWFM_CONSOLE_BUFADDR)((sc->sc_tcm_iot)->read_4((sc->sc_tcm_ioh), (sc-> sc_console_base_addr + 0x08))); | |||
594 | sc->sc_console_buf_size = bus_space_read_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,((sc->sc_tcm_iot)->read_4((sc->sc_tcm_ioh), (sc-> sc_console_base_addr + 0x0c))) | |||
595 | sc->sc_console_base_addr + BWFM_CONSOLE_BUFSIZE)((sc->sc_tcm_iot)->read_4((sc->sc_tcm_ioh), (sc-> sc_console_base_addr + 0x0c))); | |||
596 | ||||
597 | /* Read ring information. */ | |||
598 | bus_space_read_region_1(sc->sc_tcm_iot, sc->sc_tcm_ioh,((sc->sc_tcm_iot)->read_region_1((sc->sc_tcm_ioh), ( sc->sc_ring_info_addr), ((void *)&ringinfo), (sizeof(ringinfo )))) | |||
599 | sc->sc_ring_info_addr, (void *)&ringinfo, sizeof(ringinfo))((sc->sc_tcm_iot)->read_region_1((sc->sc_tcm_ioh), ( sc->sc_ring_info_addr), ((void *)&ringinfo), (sizeof(ringinfo )))); | |||
600 | ||||
601 | if (sc->sc_shared_version >= 6) { | |||
602 | sc->sc_max_submissionrings = le16toh(ringinfo.max_submissionrings)((__uint16_t)(ringinfo.max_submissionrings)); | |||
603 | sc->sc_max_flowrings = le16toh(ringinfo.max_flowrings)((__uint16_t)(ringinfo.max_flowrings)); | |||
604 | sc->sc_max_completionrings = le16toh(ringinfo.max_completionrings)((__uint16_t)(ringinfo.max_completionrings)); | |||
605 | } else { | |||
606 | sc->sc_max_submissionrings = le16toh(ringinfo.max_flowrings)((__uint16_t)(ringinfo.max_flowrings)); | |||
607 | sc->sc_max_flowrings = sc->sc_max_submissionrings - | |||
608 | BWFM_NUM_TX_MSGRINGS2; | |||
609 | sc->sc_max_completionrings = BWFM_NUM_RX_MSGRINGS3; | |||
610 | } | |||
611 | ||||
612 | if (sc->sc_dma_idx_sz == 0) { | |||
613 | d2h_w_idx_ptr = letoh32(ringinfo.d2h_w_idx_ptr)((__uint32_t)(ringinfo.d2h_w_idx_ptr)); | |||
614 | d2h_r_idx_ptr = letoh32(ringinfo.d2h_r_idx_ptr)((__uint32_t)(ringinfo.d2h_r_idx_ptr)); | |||
615 | h2d_w_idx_ptr = letoh32(ringinfo.h2d_w_idx_ptr)((__uint32_t)(ringinfo.h2d_w_idx_ptr)); | |||
616 | h2d_r_idx_ptr = letoh32(ringinfo.h2d_r_idx_ptr)((__uint32_t)(ringinfo.h2d_r_idx_ptr)); | |||
617 | idx_offset = sizeof(uint32_t); | |||
618 | } else { | |||
619 | uint64_t address; | |||
620 | ||||
621 | /* Each TX/RX Ring has a Read and Write Ptr */ | |||
622 | sc->sc_dma_idx_bufsz = (sc->sc_max_submissionrings + | |||
623 | sc->sc_max_completionrings) * sc->sc_dma_idx_sz * 2; | |||
624 | sc->sc_dma_idx_buf = bwfm_pci_dmamem_alloc(sc, | |||
625 | sc->sc_dma_idx_bufsz, 8); | |||
626 | if (sc->sc_dma_idx_buf == NULL((void *)0)) { | |||
627 | /* XXX: Fallback to TCM? */ | |||
628 | printf("%s: cannot allocate idx buf\n", | |||
629 | DEVNAME(sc)((sc)->sc_sc.sc_dev.dv_xname)); | |||
630 | return 1; | |||
631 | } | |||
632 | ||||
633 | idx_offset = sc->sc_dma_idx_sz; | |||
634 | h2d_w_idx_ptr = 0; | |||
635 | address = BWFM_PCI_DMA_DVA(sc->sc_dma_idx_buf)((uint64_t)(sc->sc_dma_idx_buf)->bdm_map->dm_segs[0] .ds_addr); | |||
636 | ringinfo.h2d_w_idx_hostaddr_low = | |||
637 | htole32(address & 0xffffffff)((__uint32_t)(address & 0xffffffff)); | |||
638 | ringinfo.h2d_w_idx_hostaddr_high = | |||
639 | htole32(address >> 32)((__uint32_t)(address >> 32)); | |||
640 | ||||
641 | h2d_r_idx_ptr = h2d_w_idx_ptr + | |||
642 | sc->sc_max_submissionrings * idx_offset; | |||
643 | address += sc->sc_max_submissionrings * idx_offset; | |||
644 | ringinfo.h2d_r_idx_hostaddr_low = | |||
645 | htole32(address & 0xffffffff)((__uint32_t)(address & 0xffffffff)); | |||
646 | ringinfo.h2d_r_idx_hostaddr_high = | |||
647 | htole32(address >> 32)((__uint32_t)(address >> 32)); | |||
648 | ||||
649 | d2h_w_idx_ptr = h2d_r_idx_ptr + | |||
650 | sc->sc_max_submissionrings * idx_offset; | |||
651 | address += sc->sc_max_submissionrings * idx_offset; | |||
652 | ringinfo.d2h_w_idx_hostaddr_low = | |||
653 | htole32(address & 0xffffffff)((__uint32_t)(address & 0xffffffff)); | |||
654 | ringinfo.d2h_w_idx_hostaddr_high = | |||
655 | htole32(address >> 32)((__uint32_t)(address >> 32)); | |||
656 | ||||
657 | d2h_r_idx_ptr = d2h_w_idx_ptr + | |||
658 | sc->sc_max_completionrings * idx_offset; | |||
659 | address += sc->sc_max_completionrings * idx_offset; | |||
660 | ringinfo.d2h_r_idx_hostaddr_low = | |||
661 | htole32(address & 0xffffffff)((__uint32_t)(address & 0xffffffff)); | |||
662 | ringinfo.d2h_r_idx_hostaddr_high = | |||
663 | htole32(address >> 32)((__uint32_t)(address >> 32)); | |||
664 | ||||
665 | bus_space_write_region_1(sc->sc_tcm_iot, sc->sc_tcm_ioh,((sc->sc_tcm_iot)->write_region_1((sc->sc_tcm_ioh), ( sc->sc_ring_info_addr), ((void *)&ringinfo), (sizeof(ringinfo )))) | |||
666 | sc->sc_ring_info_addr, (void *)&ringinfo, sizeof(ringinfo))((sc->sc_tcm_iot)->write_region_1((sc->sc_tcm_ioh), ( sc->sc_ring_info_addr), ((void *)&ringinfo), (sizeof(ringinfo )))); | |||
667 | } | |||
668 | ||||
669 | uint32_t ring_mem_ptr = letoh32(ringinfo.ringmem)((__uint32_t)(ringinfo.ringmem)); | |||
670 | /* TX ctrl ring: Send ctrl buffers, send IOCTLs */ | |||
671 | if (bwfm_pci_setup_ring(sc, &sc->sc_ctrl_submit, 64, 40, | |||
672 | h2d_w_idx_ptr, h2d_r_idx_ptr, 0, idx_offset, | |||
673 | &ring_mem_ptr)) | |||
674 | goto cleanup; | |||
675 | /* TX rxpost ring: Send clean data mbufs for RX */ | |||
676 | if (bwfm_pci_setup_ring(sc, &sc->sc_rxpost_submit, 1024, 32, | |||
677 | h2d_w_idx_ptr, h2d_r_idx_ptr, 1, idx_offset, | |||
678 | &ring_mem_ptr)) | |||
679 | goto cleanup; | |||
680 | /* RX completion rings: recv our filled buffers back */ | |||
681 | if (bwfm_pci_setup_ring(sc, &sc->sc_ctrl_complete, 64, 24, | |||
682 | d2h_w_idx_ptr, d2h_r_idx_ptr, 0, idx_offset, | |||
683 | &ring_mem_ptr)) | |||
684 | goto cleanup; | |||
685 | if (bwfm_pci_setup_ring(sc, &sc->sc_tx_complete, 1024, | |||
686 | sc->sc_shared_version >= 7 ? 24 : 16, | |||
687 | d2h_w_idx_ptr, d2h_r_idx_ptr, 1, idx_offset, | |||
688 | &ring_mem_ptr)) | |||
689 | goto cleanup; | |||
690 | if (bwfm_pci_setup_ring(sc, &sc->sc_rx_complete, 1024, | |||
691 | sc->sc_shared_version >= 7 ? 40 : 32, | |||
692 | d2h_w_idx_ptr, d2h_r_idx_ptr, 2, idx_offset, | |||
693 | &ring_mem_ptr)) | |||
694 | goto cleanup; | |||
695 | ||||
696 | /* Dynamic TX rings for actual data */ | |||
697 | sc->sc_flowrings = malloc(sc->sc_max_flowrings * | |||
698 | sizeof(struct bwfm_pci_msgring), M_DEVBUF2, M_WAITOK0x0001 | M_ZERO0x0008); | |||
699 | for (i = 0; i < sc->sc_max_flowrings; i++) { | |||
700 | struct bwfm_pci_msgring *ring = &sc->sc_flowrings[i]; | |||
701 | ring->w_idx_addr = h2d_w_idx_ptr + (i + 2) * idx_offset; | |||
702 | ring->r_idx_addr = h2d_r_idx_ptr + (i + 2) * idx_offset; | |||
703 | } | |||
704 | ||||
705 | /* Scratch and ring update buffers for firmware */ | |||
706 | if ((sc->sc_scratch_buf = bwfm_pci_dmamem_alloc(sc, | |||
707 | BWFM_DMA_D2H_SCRATCH_BUF_LEN8, 8)) == NULL((void *)0)) | |||
708 | goto cleanup; | |||
709 | bus_space_write_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,((sc->sc_tcm_iot)->write_4((sc->sc_tcm_ioh), (sc-> sc_shared_address + 0x38), (((uint64_t)(sc->sc_scratch_buf )->bdm_map->dm_segs[0].ds_addr) & 0xffffffff))) | |||
710 | sc->sc_shared_address + BWFM_SHARED_DMA_SCRATCH_ADDR_LOW,((sc->sc_tcm_iot)->write_4((sc->sc_tcm_ioh), (sc-> sc_shared_address + 0x38), (((uint64_t)(sc->sc_scratch_buf )->bdm_map->dm_segs[0].ds_addr) & 0xffffffff))) | |||
711 | BWFM_PCI_DMA_DVA(sc->sc_scratch_buf) & 0xffffffff)((sc->sc_tcm_iot)->write_4((sc->sc_tcm_ioh), (sc-> sc_shared_address + 0x38), (((uint64_t)(sc->sc_scratch_buf )->bdm_map->dm_segs[0].ds_addr) & 0xffffffff))); | |||
712 | bus_space_write_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,((sc->sc_tcm_iot)->write_4((sc->sc_tcm_ioh), (sc-> sc_shared_address + 0x3c), (((uint64_t)(sc->sc_scratch_buf )->bdm_map->dm_segs[0].ds_addr) >> 32))) | |||
713 | sc->sc_shared_address + BWFM_SHARED_DMA_SCRATCH_ADDR_HIGH,((sc->sc_tcm_iot)->write_4((sc->sc_tcm_ioh), (sc-> sc_shared_address + 0x3c), (((uint64_t)(sc->sc_scratch_buf )->bdm_map->dm_segs[0].ds_addr) >> 32))) | |||
714 | BWFM_PCI_DMA_DVA(sc->sc_scratch_buf) >> 32)((sc->sc_tcm_iot)->write_4((sc->sc_tcm_ioh), (sc-> sc_shared_address + 0x3c), (((uint64_t)(sc->sc_scratch_buf )->bdm_map->dm_segs[0].ds_addr) >> 32))); | |||
715 | bus_space_write_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,((sc->sc_tcm_iot)->write_4((sc->sc_tcm_ioh), (sc-> sc_shared_address + 0x34), (8))) | |||
716 | sc->sc_shared_address + BWFM_SHARED_DMA_SCRATCH_LEN,((sc->sc_tcm_iot)->write_4((sc->sc_tcm_ioh), (sc-> sc_shared_address + 0x34), (8))) | |||
717 | BWFM_DMA_D2H_SCRATCH_BUF_LEN)((sc->sc_tcm_iot)->write_4((sc->sc_tcm_ioh), (sc-> sc_shared_address + 0x34), (8))); | |||
718 | ||||
719 | if ((sc->sc_ringupd_buf = bwfm_pci_dmamem_alloc(sc, | |||
720 | BWFM_DMA_D2H_RINGUPD_BUF_LEN1024, 8)) == NULL((void *)0)) | |||
721 | goto cleanup; | |||
722 | bus_space_write_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,((sc->sc_tcm_iot)->write_4((sc->sc_tcm_ioh), (sc-> sc_shared_address + 0x44), (((uint64_t)(sc->sc_ringupd_buf )->bdm_map->dm_segs[0].ds_addr) & 0xffffffff))) | |||
723 | sc->sc_shared_address + BWFM_SHARED_DMA_RINGUPD_ADDR_LOW,((sc->sc_tcm_iot)->write_4((sc->sc_tcm_ioh), (sc-> sc_shared_address + 0x44), (((uint64_t)(sc->sc_ringupd_buf )->bdm_map->dm_segs[0].ds_addr) & 0xffffffff))) | |||
724 | BWFM_PCI_DMA_DVA(sc->sc_ringupd_buf) & 0xffffffff)((sc->sc_tcm_iot)->write_4((sc->sc_tcm_ioh), (sc-> sc_shared_address + 0x44), (((uint64_t)(sc->sc_ringupd_buf )->bdm_map->dm_segs[0].ds_addr) & 0xffffffff))); | |||
725 | bus_space_write_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,((sc->sc_tcm_iot)->write_4((sc->sc_tcm_ioh), (sc-> sc_shared_address + 0x48), (((uint64_t)(sc->sc_ringupd_buf )->bdm_map->dm_segs[0].ds_addr) >> 32))) | |||
726 | sc->sc_shared_address + BWFM_SHARED_DMA_RINGUPD_ADDR_HIGH,((sc->sc_tcm_iot)->write_4((sc->sc_tcm_ioh), (sc-> sc_shared_address + 0x48), (((uint64_t)(sc->sc_ringupd_buf )->bdm_map->dm_segs[0].ds_addr) >> 32))) | |||
727 | BWFM_PCI_DMA_DVA(sc->sc_ringupd_buf) >> 32)((sc->sc_tcm_iot)->write_4((sc->sc_tcm_ioh), (sc-> sc_shared_address + 0x48), (((uint64_t)(sc->sc_ringupd_buf )->bdm_map->dm_segs[0].ds_addr) >> 32))); | |||
728 | bus_space_write_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,((sc->sc_tcm_iot)->write_4((sc->sc_tcm_ioh), (sc-> sc_shared_address + 0x40), (1024))) | |||
729 | sc->sc_shared_address + BWFM_SHARED_DMA_RINGUPD_LEN,((sc->sc_tcm_iot)->write_4((sc->sc_tcm_ioh), (sc-> sc_shared_address + 0x40), (1024))) | |||
730 | BWFM_DMA_D2H_RINGUPD_BUF_LEN)((sc->sc_tcm_iot)->write_4((sc->sc_tcm_ioh), (sc-> sc_shared_address + 0x40), (1024))); | |||
731 | ||||
732 | bwfm_pci_select_core(sc, BWFM_AGENT_CORE_PCIE20x83C); | |||
733 | bwfm_pci_intr_enable(sc); | |||
734 | bwfm_pci_hostready(sc); | |||
735 | ||||
736 | /* Maps RX mbufs to a packet id and back. */ | |||
737 | sc->sc_rx_pkts.npkt = BWFM_NUM_RX_PKTIDS1024; | |||
738 | sc->sc_rx_pkts.pkts = malloc(BWFM_NUM_RX_PKTIDS1024 * | |||
739 | sizeof(struct bwfm_pci_buf), M_DEVBUF2, M_WAITOK0x0001 | M_ZERO0x0008); | |||
740 | for (i = 0; i < BWFM_NUM_RX_PKTIDS1024; i++) | |||
741 | bus_dmamap_create(sc->sc_dmat, MSGBUF_MAX_CTL_PKT_SIZE,(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), (8192 ), (1), (8192), (0), (0x0000), (&sc->sc_rx_pkts.pkts[i ].bb_map)) | |||
742 | BWFM_NUM_RX_DESCS, MSGBUF_MAX_CTL_PKT_SIZE, 0, BUS_DMA_WAITOK,(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), (8192 ), (1), (8192), (0), (0x0000), (&sc->sc_rx_pkts.pkts[i ].bb_map)) | |||
743 | &sc->sc_rx_pkts.pkts[i].bb_map)(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), (8192 ), (1), (8192), (0), (0x0000), (&sc->sc_rx_pkts.pkts[i ].bb_map)); | |||
744 | ||||
745 | /* Maps TX mbufs to a packet id and back. */ | |||
746 | sc->sc_tx_pkts.npkt = BWFM_NUM_TX_PKTIDS2048; | |||
747 | sc->sc_tx_pkts.pkts = malloc(BWFM_NUM_TX_PKTIDS2048 | |||
748 | * sizeof(struct bwfm_pci_buf), M_DEVBUF2, M_WAITOK0x0001 | M_ZERO0x0008); | |||
749 | for (i = 0; i < BWFM_NUM_TX_PKTIDS2048; i++) | |||
750 | bus_dmamap_create(sc->sc_dmat, MSGBUF_MAX_PKT_SIZE,(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), (2048 ), (1), (2048), (0), (0x0000), (&sc->sc_tx_pkts.pkts[i ].bb_map)) | |||
751 | BWFM_NUM_TX_DESCS, MSGBUF_MAX_PKT_SIZE, 0, BUS_DMA_WAITOK,(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), (2048 ), (1), (2048), (0), (0x0000), (&sc->sc_tx_pkts.pkts[i ].bb_map)) | |||
752 | &sc->sc_tx_pkts.pkts[i].bb_map)(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), (2048 ), (1), (2048), (0), (0x0000), (&sc->sc_tx_pkts.pkts[i ].bb_map)); | |||
753 | sc->sc_tx_pkts_full = 0; | |||
754 | ||||
755 | /* Maps IOCTL mbufs to a packet id and back. */ | |||
756 | sc->sc_ioctl_pkts.npkt = BWFM_NUM_IOCTL_PKTIDS8; | |||
757 | sc->sc_ioctl_pkts.pkts = malloc(BWFM_NUM_IOCTL_PKTIDS8 | |||
758 | * sizeof(struct bwfm_pci_buf), M_DEVBUF2, M_WAITOK0x0001 | M_ZERO0x0008); | |||
759 | for (i = 0; i < BWFM_NUM_IOCTL_PKTIDS8; i++) | |||
760 | bus_dmamap_create(sc->sc_dmat, MSGBUF_MAX_PKT_SIZE,(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), (2048 ), (1), (2048), (0), (0x0000), (&sc->sc_ioctl_pkts.pkts [i].bb_map)) | |||
761 | BWFM_NUM_IOCTL_DESCS, MSGBUF_MAX_PKT_SIZE, 0, BUS_DMA_WAITOK,(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), (2048 ), (1), (2048), (0), (0x0000), (&sc->sc_ioctl_pkts.pkts [i].bb_map)) | |||
762 | &sc->sc_ioctl_pkts.pkts[i].bb_map)(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), (2048 ), (1), (2048), (0), (0x0000), (&sc->sc_ioctl_pkts.pkts [i].bb_map)); | |||
763 | ||||
764 | /* | |||
765 | * For whatever reason, could also be a bug somewhere in this | |||
766 | * driver, the firmware needs a bunch of RX buffers otherwise | |||
767 | * it won't send any RX complete messages. | |||
768 | */ | |||
769 | if_rxr_init(&sc->sc_rxbuf_ring, min(256, sc->sc_max_rxbufpost), | |||
770 | sc->sc_max_rxbufpost); | |||
771 | if_rxr_init(&sc->sc_ioctl_ring, 8, 8); | |||
772 | if_rxr_init(&sc->sc_event_ring, 8, 8); | |||
773 | bwfm_pci_fill_rx_rings(sc); | |||
774 | ||||
775 | TAILQ_INIT(&sc->sc_ioctlq)do { (&sc->sc_ioctlq)->tqh_first = ((void *)0); (& sc->sc_ioctlq)->tqh_last = &(&sc->sc_ioctlq) ->tqh_first; } while (0); | |||
776 | ||||
777 | #ifdef BWFM_DEBUG | |||
778 | sc->sc_console_readidx = 0; | |||
779 | bwfm_pci_debug_console(sc); | |||
780 | #endif | |||
781 | ||||
782 | sc->sc_initialized = 1; | |||
783 | return 0; | |||
784 | ||||
785 | cleanup: | |||
786 | if (sc->sc_ringupd_buf) | |||
787 | bwfm_pci_dmamem_free(sc, sc->sc_ringupd_buf); | |||
788 | if (sc->sc_scratch_buf) | |||
789 | bwfm_pci_dmamem_free(sc, sc->sc_scratch_buf); | |||
790 | if (sc->sc_rx_complete.ring) | |||
791 | bwfm_pci_dmamem_free(sc, sc->sc_rx_complete.ring); | |||
792 | if (sc->sc_tx_complete.ring) | |||
793 | bwfm_pci_dmamem_free(sc, sc->sc_tx_complete.ring); | |||
794 | if (sc->sc_ctrl_complete.ring) | |||
795 | bwfm_pci_dmamem_free(sc, sc->sc_ctrl_complete.ring); | |||
796 | if (sc->sc_rxpost_submit.ring) | |||
797 | bwfm_pci_dmamem_free(sc, sc->sc_rxpost_submit.ring); | |||
798 | if (sc->sc_ctrl_submit.ring) | |||
799 | bwfm_pci_dmamem_free(sc, sc->sc_ctrl_submit.ring); | |||
800 | if (sc->sc_dma_idx_buf) | |||
801 | bwfm_pci_dmamem_free(sc, sc->sc_dma_idx_buf); | |||
802 | return 1; | |||
803 | } | |||
804 | ||||
805 | int | |||
806 | bwfm_pci_load_microcode(struct bwfm_pci_softc *sc, const u_char *ucode, size_t size, | |||
807 | const u_char *nvram, size_t nvlen) | |||
808 | { | |||
809 | struct bwfm_softc *bwfm = (void *)sc; | |||
810 | struct bwfm_core *core; | |||
811 | struct bwfm_pci_random_seed_footer footer; | |||
812 | uint32_t addr, shared, written; | |||
813 | uint8_t *rndbuf; | |||
814 | int i; | |||
815 | ||||
816 | if (bwfm->sc_chip.ch_chip == BRCM_CC_43602_CHIP_ID43602) { | |||
817 | bwfm_pci_select_core(sc, BWFM_AGENT_CORE_ARM_CR40x83E); | |||
818 | bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,((sc->sc_reg_iot)->write_4((sc->sc_reg_ioh), (0x40), (5))) | |||
819 | BWFM_PCI_ARMCR4REG_BANKIDX, 5)((sc->sc_reg_iot)->write_4((sc->sc_reg_ioh), (0x40), (5))); | |||
820 | bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,((sc->sc_reg_iot)->write_4((sc->sc_reg_ioh), (0x4C), (0))) | |||
821 | BWFM_PCI_ARMCR4REG_BANKPDA, 0)((sc->sc_reg_iot)->write_4((sc->sc_reg_ioh), (0x4C), (0))); | |||
822 | bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,((sc->sc_reg_iot)->write_4((sc->sc_reg_ioh), (0x40), (7))) | |||
823 | BWFM_PCI_ARMCR4REG_BANKIDX, 7)((sc->sc_reg_iot)->write_4((sc->sc_reg_ioh), (0x40), (7))); | |||
824 | bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,((sc->sc_reg_iot)->write_4((sc->sc_reg_ioh), (0x4C), (0))) | |||
825 | BWFM_PCI_ARMCR4REG_BANKPDA, 0)((sc->sc_reg_iot)->write_4((sc->sc_reg_ioh), (0x4C), (0))); | |||
826 | } | |||
827 | ||||
828 | for (i = 0; i < size; i++) | |||
829 | bus_space_write_1(sc->sc_tcm_iot, sc->sc_tcm_ioh,((sc->sc_tcm_iot)->write_1((sc->sc_tcm_ioh), (bwfm-> sc_chip.ch_rambase + i), (ucode[i]))) | |||
830 | bwfm->sc_chip.ch_rambase + i, ucode[i])((sc->sc_tcm_iot)->write_1((sc->sc_tcm_ioh), (bwfm-> sc_chip.ch_rambase + i), (ucode[i]))); | |||
831 | ||||
832 | /* Firmware replaces this with a pointer once up. */ | |||
833 | bus_space_write_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,((sc->sc_tcm_iot)->write_4((sc->sc_tcm_ioh), (bwfm-> sc_chip.ch_rambase + bwfm->sc_chip.ch_ramsize - 4), (0))) | |||
834 | bwfm->sc_chip.ch_rambase + bwfm->sc_chip.ch_ramsize - 4, 0)((sc->sc_tcm_iot)->write_4((sc->sc_tcm_ioh), (bwfm-> sc_chip.ch_rambase + bwfm->sc_chip.ch_ramsize - 4), (0))); | |||
835 | ||||
836 | if (nvram) { | |||
837 | addr = bwfm->sc_chip.ch_rambase + bwfm->sc_chip.ch_ramsize - | |||
838 | nvlen; | |||
839 | for (i = 0; i < nvlen; i++) | |||
840 | bus_space_write_1(sc->sc_tcm_iot, sc->sc_tcm_ioh,((sc->sc_tcm_iot)->write_1((sc->sc_tcm_ioh), (addr + i), (nvram[i]))) | |||
841 | addr + i, nvram[i])((sc->sc_tcm_iot)->write_1((sc->sc_tcm_ioh), (addr + i), (nvram[i]))); | |||
842 | ||||
843 | footer.length = htole32(BWFM_RANDOM_SEED_LENGTH)((__uint32_t)(0x100)); | |||
844 | footer.magic = htole32(BWFM_RANDOM_SEED_MAGIC)((__uint32_t)(0xfeedc0de)); | |||
845 | addr -= sizeof(footer); | |||
846 | for (i = 0; i < sizeof(footer); i++) | |||
847 | bus_space_write_1(sc->sc_tcm_iot, sc->sc_tcm_ioh,((sc->sc_tcm_iot)->write_1((sc->sc_tcm_ioh), (addr + i), (((uint8_t *)&footer)[i]))) | |||
| ||||
848 | addr + i, ((uint8_t *)&footer)[i])((sc->sc_tcm_iot)->write_1((sc->sc_tcm_ioh), (addr + i), (((uint8_t *)&footer)[i]))); | |||
849 | ||||
850 | rndbuf = malloc(BWFM_RANDOM_SEED_LENGTH0x100, M_TEMP127, M_WAITOK0x0001); | |||
851 | arc4random_buf(rndbuf, BWFM_RANDOM_SEED_LENGTH0x100); | |||
852 | addr -= BWFM_RANDOM_SEED_LENGTH0x100; | |||
853 | for (i = 0; i < BWFM_RANDOM_SEED_LENGTH0x100; i++) | |||
854 | bus_space_write_1(sc->sc_tcm_iot, sc->sc_tcm_ioh,((sc->sc_tcm_iot)->write_1((sc->sc_tcm_ioh), (addr + i), (rndbuf[i]))) | |||
855 | addr + i, rndbuf[i])((sc->sc_tcm_iot)->write_1((sc->sc_tcm_ioh), (addr + i), (rndbuf[i]))); | |||
856 | free(rndbuf, M_TEMP127, BWFM_RANDOM_SEED_LENGTH0x100); | |||
857 | } | |||
858 | ||||
859 | written = bus_space_read_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,((sc->sc_tcm_iot)->read_4((sc->sc_tcm_ioh), (bwfm-> sc_chip.ch_rambase + bwfm->sc_chip.ch_ramsize - 4))) | |||
860 | bwfm->sc_chip.ch_rambase + bwfm->sc_chip.ch_ramsize - 4)((sc->sc_tcm_iot)->read_4((sc->sc_tcm_ioh), (bwfm-> sc_chip.ch_rambase + bwfm->sc_chip.ch_ramsize - 4))); | |||
861 | ||||
862 | /* Load reset vector from firmware and kickstart core. */ | |||
863 | if (bwfm->sc_chip.ch_chip == BRCM_CC_43602_CHIP_ID43602) { | |||
864 | core = bwfm_chip_get_core(bwfm, BWFM_AGENT_INTERNAL_MEM0x80E); | |||
865 | bwfm->sc_chip.ch_core_reset(bwfm, core, 0, 0, 0); | |||
866 | } | |||
867 | bwfm_chip_set_active(bwfm, *(uint32_t *)ucode); | |||
868 | ||||
869 | for (i = 0; i < 100; i++) { | |||
870 | delay(50 * 1000)(*delay_func)(50 * 1000); | |||
871 | shared = bus_space_read_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,((sc->sc_tcm_iot)->read_4((sc->sc_tcm_ioh), (bwfm-> sc_chip.ch_rambase + bwfm->sc_chip.ch_ramsize - 4))) | |||
872 | bwfm->sc_chip.ch_rambase + bwfm->sc_chip.ch_ramsize - 4)((sc->sc_tcm_iot)->read_4((sc->sc_tcm_ioh), (bwfm-> sc_chip.ch_rambase + bwfm->sc_chip.ch_ramsize - 4))); | |||
873 | if (shared != written) | |||
874 | break; | |||
875 | } | |||
876 | if (shared == written) { | |||
877 | printf("%s: firmware did not come up\n", DEVNAME(sc)((sc)->sc_sc.sc_dev.dv_xname)); | |||
878 | return 1; | |||
879 | } | |||
880 | if (shared < bwfm->sc_chip.ch_rambase || | |||
881 | shared >= bwfm->sc_chip.ch_rambase + bwfm->sc_chip.ch_ramsize) { | |||
882 | printf("%s: invalid shared RAM address 0x%08x\n", DEVNAME(sc)((sc)->sc_sc.sc_dev.dv_xname), | |||
883 | shared); | |||
884 | return 1; | |||
885 | } | |||
886 | ||||
887 | sc->sc_shared_address = shared; | |||
888 | return 0; | |||
889 | } | |||
890 | ||||
891 | int | |||
892 | bwfm_pci_detach(struct device *self, int flags) | |||
893 | { | |||
894 | struct bwfm_pci_softc *sc = (struct bwfm_pci_softc *)self; | |||
895 | ||||
896 | bwfm_detach(&sc->sc_sc, flags); | |||
897 | bwfm_pci_cleanup(sc); | |||
898 | ||||
899 | return 0; | |||
900 | } | |||
901 | ||||
902 | void | |||
903 | bwfm_pci_cleanup(struct bwfm_pci_softc *sc) | |||
904 | { | |||
905 | int i; | |||
906 | ||||
907 | for (i = 0; i < BWFM_NUM_RX_PKTIDS1024; i++) { | |||
908 | bus_dmamap_destroy(sc->sc_dmat, sc->sc_rx_pkts.pkts[i].bb_map)(*(sc->sc_dmat)->_dmamap_destroy)((sc->sc_dmat), (sc ->sc_rx_pkts.pkts[i].bb_map)); | |||
909 | if (sc->sc_rx_pkts.pkts[i].bb_m) | |||
910 | m_freem(sc->sc_rx_pkts.pkts[i].bb_m); | |||
911 | } | |||
912 | free(sc->sc_rx_pkts.pkts, M_DEVBUF2, BWFM_NUM_RX_PKTIDS1024 * | |||
913 | sizeof(struct bwfm_pci_buf)); | |||
914 | ||||
915 | for (i = 0; i < BWFM_NUM_TX_PKTIDS2048; i++) { | |||
916 | bus_dmamap_destroy(sc->sc_dmat, sc->sc_tx_pkts.pkts[i].bb_map)(*(sc->sc_dmat)->_dmamap_destroy)((sc->sc_dmat), (sc ->sc_tx_pkts.pkts[i].bb_map)); | |||
917 | if (sc->sc_tx_pkts.pkts[i].bb_m) | |||
918 | m_freem(sc->sc_tx_pkts.pkts[i].bb_m); | |||
919 | } | |||
920 | free(sc->sc_tx_pkts.pkts, M_DEVBUF2, BWFM_NUM_TX_PKTIDS2048 * | |||
921 | sizeof(struct bwfm_pci_buf)); | |||
922 | ||||
923 | for (i = 0; i < BWFM_NUM_IOCTL_PKTIDS8; i++) { | |||
924 | bus_dmamap_destroy(sc->sc_dmat, sc->sc_ioctl_pkts.pkts[i].bb_map)(*(sc->sc_dmat)->_dmamap_destroy)((sc->sc_dmat), (sc ->sc_ioctl_pkts.pkts[i].bb_map)); | |||
925 | if (sc->sc_ioctl_pkts.pkts[i].bb_m) | |||
926 | m_freem(sc->sc_ioctl_pkts.pkts[i].bb_m); | |||
927 | } | |||
928 | free(sc->sc_ioctl_pkts.pkts, M_DEVBUF2, BWFM_NUM_IOCTL_PKTIDS8 * | |||
929 | sizeof(struct bwfm_pci_buf)); | |||
930 | ||||
931 | for (i = 0; i < sc->sc_max_flowrings; i++) { | |||
932 | if (sc->sc_flowrings[i].status >= RING_OPEN) | |||
933 | bwfm_pci_dmamem_free(sc, sc->sc_flowrings[i].ring); | |||
934 | } | |||
935 | free(sc->sc_flowrings, M_DEVBUF2, sc->sc_max_flowrings * | |||
936 | sizeof(struct bwfm_pci_msgring)); | |||
937 | ||||
938 | bwfm_pci_dmamem_free(sc, sc->sc_ringupd_buf); | |||
939 | bwfm_pci_dmamem_free(sc, sc->sc_scratch_buf); | |||
940 | bwfm_pci_dmamem_free(sc, sc->sc_rx_complete.ring); | |||
941 | bwfm_pci_dmamem_free(sc, sc->sc_tx_complete.ring); | |||
942 | bwfm_pci_dmamem_free(sc, sc->sc_ctrl_complete.ring); | |||
943 | bwfm_pci_dmamem_free(sc, sc->sc_rxpost_submit.ring); | |||
944 | bwfm_pci_dmamem_free(sc, sc->sc_ctrl_submit.ring); | |||
945 | if (sc->sc_dma_idx_buf) { | |||
946 | bwfm_pci_dmamem_free(sc, sc->sc_dma_idx_buf); | |||
947 | sc->sc_dma_idx_buf = NULL((void *)0); | |||
948 | } | |||
949 | ||||
950 | sc->sc_initialized = 0; | |||
951 | } | |||
952 | ||||
953 | int | |||
954 | bwfm_pci_activate(struct device *self, int act) | |||
955 | { | |||
956 | struct bwfm_pci_softc *sc = (struct bwfm_pci_softc *)self; | |||
957 | struct bwfm_softc *bwfm = (void *)sc; | |||
958 | int error = 0; | |||
959 | ||||
960 | switch (act) { | |||
961 | case DVACT_QUIESCE2: | |||
962 | error = bwfm_activate(bwfm, act); | |||
963 | if (error) | |||
964 | return error; | |||
965 | if (sc->sc_initialized) { | |||
966 | sc->sc_mbdata_done = 0; | |||
967 | error = bwfm_pci_send_mb_data(sc, | |||
968 | BWFM_PCI_H2D_HOST_D3_INFORM0x00000001); | |||
969 | if (error) | |||
970 | return error; | |||
971 | tsleep_nsec(&sc->sc_mbdata_done, PCATCH0x100, | |||
972 | DEVNAME(sc)((sc)->sc_sc.sc_dev.dv_xname), SEC_TO_NSEC(2)); | |||
973 | if (!sc->sc_mbdata_done) | |||
974 | return ETIMEDOUT60; | |||
975 | } | |||
976 | break; | |||
977 | case DVACT_WAKEUP5: | |||
978 | if (sc->sc_initialized) { | |||
979 | /* If device can't be resumed, re-init. */ | |||
980 | if (bwfm_pci_intmask(sc) == 0 || | |||
981 | bwfm_pci_send_mb_data(sc, | |||
982 | BWFM_PCI_H2D_HOST_D0_INFORM0x00000010) != 0) { | |||
983 | bwfm_cleanup(bwfm); | |||
984 | bwfm_pci_cleanup(sc); | |||
985 | } else { | |||
986 | bwfm_pci_select_core(sc, BWFM_AGENT_CORE_PCIE20x83C); | |||
987 | bwfm_pci_intr_enable(sc); | |||
988 | bwfm_pci_hostready(sc); | |||
989 | } | |||
990 | } | |||
991 | error = bwfm_activate(bwfm, act); | |||
992 | if (error) | |||
993 | return error; | |||
994 | break; | |||
995 | default: | |||
996 | break; | |||
997 | } | |||
998 | ||||
999 | return 0; | |||
1000 | } | |||
1001 | ||||
1002 | #if defined(__HAVE_FDT) | |||
1003 | int | |||
1004 | bwfm_pci_read_otp(struct bwfm_pci_softc *sc) | |||
1005 | { | |||
1006 | struct bwfm_softc *bwfm = (void *)sc; | |||
1007 | struct bwfm_core *core; | |||
1008 | uint32_t coreid, base, words; | |||
1009 | uint32_t page, offset, sromctl; | |||
1010 | uint8_t *otp; | |||
1011 | int i; | |||
1012 | ||||
1013 | switch (bwfm->sc_chip.ch_chip) { | |||
1014 | case BRCM_CC_4355_CHIP_ID0x4355: | |||
1015 | coreid = BWFM_AGENT_CORE_CHIPCOMMON0x800; | |||
1016 | base = 0x8c0; | |||
1017 | words = 0xb2; | |||
1018 | break; | |||
1019 | case BRCM_CC_4364_CHIP_ID0x4364: | |||
1020 | coreid = BWFM_AGENT_CORE_CHIPCOMMON0x800; | |||
1021 | base = 0x8c0; | |||
1022 | words = 0x1a0; | |||
1023 | break; | |||
1024 | case BRCM_CC_4377_CHIP_ID0x4377: | |||
1025 | case BRCM_CC_4378_CHIP_ID0x4378: | |||
1026 | coreid = BWFM_AGENT_CORE_GCI0x840; | |||
1027 | base = 0x1120; | |||
1028 | words = 0x170; | |||
1029 | break; | |||
1030 | case BRCM_CC_4387_CHIP_ID0x4387: | |||
1031 | coreid = BWFM_AGENT_CORE_GCI0x840; | |||
1032 | base = 0x113c; | |||
1033 | words = 0x170; | |||
1034 | break; | |||
1035 | default: | |||
1036 | return 0; | |||
1037 | } | |||
1038 | ||||
1039 | core = bwfm_chip_get_core(bwfm, coreid); | |||
1040 | if (core == NULL((void *)0)) | |||
1041 | return 1; | |||
1042 | ||||
1043 | /* Map OTP to shadow area */ | |||
1044 | if (coreid == BWFM_AGENT_CORE_CHIPCOMMON0x800) { | |||
1045 | bwfm_pci_select_core(sc, coreid); | |||
1046 | sromctl = bus_space_read_4(sc->sc_reg_iot, sc->sc_reg_ioh,((sc->sc_reg_iot)->read_4((sc->sc_reg_ioh), (0x00000190 ))) | |||
1047 | BWFM_CHIP_REG_SROMCONTROL)((sc->sc_reg_iot)->read_4((sc->sc_reg_ioh), (0x00000190 ))); | |||
1048 | ||||
1049 | if (!(sromctl & BWFM_CHIP_REG_SROMCONTROL_OTP_PRESENT(1 << 5))) | |||
1050 | return 0; | |||
1051 | ||||
1052 | bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,((sc->sc_reg_iot)->write_4((sc->sc_reg_ioh), (0x00000190 ), (sromctl | (1 << 4)))) | |||
1053 | BWFM_CHIP_REG_SROMCONTROL, sromctl |((sc->sc_reg_iot)->write_4((sc->sc_reg_ioh), (0x00000190 ), (sromctl | (1 << 4)))) | |||
1054 | BWFM_CHIP_REG_SROMCONTROL_OTPSEL)((sc->sc_reg_iot)->write_4((sc->sc_reg_ioh), (0x00000190 ), (sromctl | (1 << 4)))); | |||
1055 | } | |||
1056 | ||||
1057 | /* Map bus window to SROM/OTP shadow area */ | |||
1058 | page = (core->co_base + base) & ~(BWFM_PCI_BAR0_REG_SIZE0x1000 - 1); | |||
1059 | offset = (core->co_base + base) & (BWFM_PCI_BAR0_REG_SIZE0x1000 - 1); | |||
1060 | pci_conf_write(sc->sc_pc, sc->sc_tag, BWFM_PCI_BAR0_WINDOW0x80, page); | |||
1061 | ||||
1062 | otp = mallocarray(words, sizeof(uint16_t), M_TEMP127, M_WAITOK0x0001); | |||
1063 | for (i = 0; i < words; i++) | |||
1064 | ((uint16_t *)otp)[i] = bus_space_read_2(sc->sc_reg_iot,((sc->sc_reg_iot)->read_2((sc->sc_reg_ioh), (offset + i * sizeof(uint16_t)))) | |||
1065 | sc->sc_reg_ioh, offset + i * sizeof(uint16_t))((sc->sc_reg_iot)->read_2((sc->sc_reg_ioh), (offset + i * sizeof(uint16_t)))); | |||
1066 | ||||
1067 | /* Unmap OTP */ | |||
1068 | if (coreid == BWFM_AGENT_CORE_CHIPCOMMON0x800) { | |||
1069 | bwfm_pci_select_core(sc, coreid); | |||
1070 | bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,((sc->sc_reg_iot)->write_4((sc->sc_reg_ioh), (0x00000190 ), (sromctl))) | |||
1071 | BWFM_CHIP_REG_SROMCONTROL, sromctl)((sc->sc_reg_iot)->write_4((sc->sc_reg_ioh), (0x00000190 ), (sromctl))); | |||
1072 | } | |||
1073 | ||||
1074 | for (i = 0; i < (words * sizeof(uint16_t)) - 1; i += otp[i + 1]) { | |||
1075 | if (otp[i + 0] == 0) | |||
1076 | break; | |||
1077 | if (i + otp[i + 1] > words * sizeof(uint16_t)) | |||
1078 | break; | |||
1079 | bwfm_pci_process_otp_tuple(sc, otp[i + 0], otp[i + 1], | |||
1080 | &otp[i + 2]); | |||
1081 | } | |||
1082 | ||||
1083 | free(otp, M_TEMP127, words * sizeof(uint16_t)); | |||
1084 | return 0; | |||
1085 | } | |||
1086 | ||||
1087 | void | |||
1088 | bwfm_pci_process_otp_tuple(struct bwfm_pci_softc *sc, uint8_t type, uint8_t size, | |||
1089 | uint8_t *data) | |||
1090 | { | |||
1091 | struct bwfm_softc *bwfm = (void *)sc; | |||
1092 | char chiprev[8] = "", module[8] = "", modrev[8] = "", vendor[8] = "", chip[8] = ""; | |||
1093 | char board_type[128] = ""; | |||
1094 | int len; | |||
1095 | ||||
1096 | switch (type) { | |||
1097 | case 0x15: /* system vendor OTP */ | |||
1098 | DPRINTF(("%s: system vendor OTP\n", DEVNAME(sc)))do { ; } while (0); | |||
1099 | if (size < sizeof(uint32_t)) | |||
1100 | return; | |||
1101 | if (data[0] != 0x08 || data[1] != 0x00 || | |||
1102 | data[2] != 0x00 || data[3] != 0x00) | |||
1103 | return; | |||
1104 | size -= sizeof(uint32_t); | |||
1105 | data += sizeof(uint32_t); | |||
1106 | while (size) { | |||
1107 | /* reached end */ | |||
1108 | if (data[0] == 0xff) | |||
1109 | break; | |||
1110 | for (len = 0; len < size; len++) | |||
1111 | if (data[len] == 0x00 || data[len] == ' ' || | |||
1112 | data[len] == 0xff) | |||
1113 | break; | |||
1114 | if (len < 3 || len > 9) /* X=abcdef */ | |||
1115 | goto next; | |||
1116 | if (data[1] != '=') | |||
1117 | goto next; | |||
1118 | /* NULL-terminate string */ | |||
1119 | if (data[len] == ' ') | |||
1120 | data[len] = '\0'; | |||
1121 | switch (data[0]) { | |||
1122 | case 's': | |||
1123 | strlcpy(chiprev, &data[2], sizeof(chiprev)); | |||
1124 | break; | |||
1125 | case 'M': | |||
1126 | strlcpy(module, &data[2], sizeof(module)); | |||
1127 | break; | |||
1128 | case 'm': | |||
1129 | strlcpy(modrev, &data[2], sizeof(modrev)); | |||
1130 | break; | |||
1131 | case 'V': | |||
1132 | strlcpy(vendor, &data[2], sizeof(vendor)); | |||
1133 | break; | |||
1134 | } | |||
1135 | next: | |||
1136 | /* skip content */ | |||
1137 | data += len; | |||
1138 | size -= len; | |||
1139 | /* skip spacer tag */ | |||
1140 | if (size) { | |||
1141 | data++; | |||
1142 | size--; | |||
1143 | } | |||
1144 | } | |||
1145 | snprintf(chip, sizeof(chip), | |||
1146 | bwfm->sc_chip.ch_chip > 40000 ? "%05d" : "%04x", | |||
1147 | bwfm->sc_chip.ch_chip); | |||
1148 | if (sc->sc_sc.sc_node) { | |||
1149 | OF_getprop(sc->sc_sc.sc_node, "brcm,board-type", | |||
1150 | board_type, sizeof(board_type)); | |||
1151 | if (strncmp(board_type, "apple,", 6) == 0) { | |||
1152 | strlcpy(sc->sc_sc.sc_fwdir, "apple-bwfm/", | |||
1153 | sizeof(sc->sc_sc.sc_fwdir)); | |||
1154 | } | |||
1155 | } | |||
1156 | strlcpy(sc->sc_sc.sc_board_type, board_type, | |||
1157 | sizeof(sc->sc_sc.sc_board_type)); | |||
1158 | strlcpy(sc->sc_sc.sc_module, module, | |||
1159 | sizeof(sc->sc_sc.sc_module)); | |||
1160 | strlcpy(sc->sc_sc.sc_vendor, vendor, | |||
1161 | sizeof(sc->sc_sc.sc_vendor)); | |||
1162 | strlcpy(sc->sc_sc.sc_modrev, modrev, | |||
1163 | sizeof(sc->sc_sc.sc_modrev)); | |||
1164 | break; | |||
1165 | case 0x80: /* Broadcom CIS */ | |||
1166 | DPRINTF(("%s: Broadcom CIS\n", DEVNAME(sc)))do { ; } while (0); | |||
1167 | break; | |||
1168 | default: | |||
1169 | DPRINTF(("%s: unknown OTP tuple\n", DEVNAME(sc)))do { ; } while (0); | |||
1170 | break; | |||
1171 | } | |||
1172 | } | |||
1173 | #endif | |||
1174 | ||||
1175 | /* DMA code */ | |||
1176 | struct bwfm_pci_dmamem * | |||
1177 | bwfm_pci_dmamem_alloc(struct bwfm_pci_softc *sc, bus_size_t size, bus_size_t align) | |||
1178 | { | |||
1179 | struct bwfm_pci_dmamem *bdm; | |||
1180 | int nsegs; | |||
1181 | ||||
1182 | bdm = malloc(sizeof(*bdm), M_DEVBUF2, M_WAITOK0x0001 | M_ZERO0x0008); | |||
1183 | bdm->bdm_size = size; | |||
1184 | ||||
1185 | if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), (size ), (1), (size), (0), (0x0000 | 0x0002), (&bdm->bdm_map )) | |||
1186 | BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW, &bdm->bdm_map)(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), (size ), (1), (size), (0), (0x0000 | 0x0002), (&bdm->bdm_map )) != 0) | |||
1187 | goto bdmfree; | |||
1188 | ||||
1189 | if (bus_dmamem_alloc(sc->sc_dmat, size, align, 0, &bdm->bdm_seg, 1,(*(sc->sc_dmat)->_dmamem_alloc)((sc->sc_dmat), (size ), (align), (0), (&bdm->bdm_seg), (1), (&nsegs), ( 0x0000)) | |||
1190 | &nsegs, BUS_DMA_WAITOK)(*(sc->sc_dmat)->_dmamem_alloc)((sc->sc_dmat), (size ), (align), (0), (&bdm->bdm_seg), (1), (&nsegs), ( 0x0000)) != 0) | |||
1191 | goto destroy; | |||
1192 | ||||
1193 | if (bus_dmamem_map(sc->sc_dmat, &bdm->bdm_seg, nsegs, size,(*(sc->sc_dmat)->_dmamem_map)((sc->sc_dmat), (&bdm ->bdm_seg), (nsegs), (size), (&bdm->bdm_kva), (0x0000 | 0x0004)) | |||
1194 | &bdm->bdm_kva, BUS_DMA_WAITOK | BUS_DMA_COHERENT)(*(sc->sc_dmat)->_dmamem_map)((sc->sc_dmat), (&bdm ->bdm_seg), (nsegs), (size), (&bdm->bdm_kva), (0x0000 | 0x0004)) != 0) | |||
1195 | goto free; | |||
1196 | ||||
1197 | if (bus_dmamap_load(sc->sc_dmat, bdm->bdm_map, bdm->bdm_kva, size,(*(sc->sc_dmat)->_dmamap_load)((sc->sc_dmat), (bdm-> bdm_map), (bdm->bdm_kva), (size), (((void *)0)), (0x0000)) | |||
1198 | NULL, BUS_DMA_WAITOK)(*(sc->sc_dmat)->_dmamap_load)((sc->sc_dmat), (bdm-> bdm_map), (bdm->bdm_kva), (size), (((void *)0)), (0x0000)) != 0) | |||
1199 | goto unmap; | |||
1200 | ||||
1201 | bzero(bdm->bdm_kva, size)__builtin_bzero((bdm->bdm_kva), (size)); | |||
1202 | ||||
1203 | return (bdm); | |||
1204 | ||||
1205 | unmap: | |||
1206 | bus_dmamem_unmap(sc->sc_dmat, bdm->bdm_kva, size)(*(sc->sc_dmat)->_dmamem_unmap)((sc->sc_dmat), (bdm-> bdm_kva), (size)); | |||
1207 | free: | |||
1208 | bus_dmamem_free(sc->sc_dmat, &bdm->bdm_seg, 1)(*(sc->sc_dmat)->_dmamem_free)((sc->sc_dmat), (& bdm->bdm_seg), (1)); | |||
1209 | destroy: | |||
1210 | bus_dmamap_destroy(sc->sc_dmat, bdm->bdm_map)(*(sc->sc_dmat)->_dmamap_destroy)((sc->sc_dmat), (bdm ->bdm_map)); | |||
1211 | bdmfree: | |||
1212 | free(bdm, M_DEVBUF2, sizeof(*bdm)); | |||
1213 | ||||
1214 | return (NULL((void *)0)); | |||
1215 | } | |||
1216 | ||||
1217 | void | |||
1218 | bwfm_pci_dmamem_free(struct bwfm_pci_softc *sc, struct bwfm_pci_dmamem *bdm) | |||
1219 | { | |||
1220 | bus_dmamem_unmap(sc->sc_dmat, bdm->bdm_kva, bdm->bdm_size)(*(sc->sc_dmat)->_dmamem_unmap)((sc->sc_dmat), (bdm-> bdm_kva), (bdm->bdm_size)); | |||
1221 | bus_dmamem_free(sc->sc_dmat, &bdm->bdm_seg, 1)(*(sc->sc_dmat)->_dmamem_free)((sc->sc_dmat), (& bdm->bdm_seg), (1)); | |||
1222 | bus_dmamap_destroy(sc->sc_dmat, bdm->bdm_map)(*(sc->sc_dmat)->_dmamap_destroy)((sc->sc_dmat), (bdm ->bdm_map)); | |||
1223 | free(bdm, M_DEVBUF2, sizeof(*bdm)); | |||
1224 | } | |||
1225 | ||||
1226 | /* | |||
1227 | * We need a simple mapping from a packet ID to mbufs, because when | |||
1228 | * a transfer completed, we only know the ID so we have to look up | |||
1229 | * the memory for the ID. This simply looks for an empty slot. | |||
1230 | */ | |||
1231 | int | |||
1232 | bwfm_pci_pktid_avail(struct bwfm_pci_softc *sc, struct bwfm_pci_pkts *pkts) | |||
1233 | { | |||
1234 | int i, idx; | |||
1235 | ||||
1236 | idx = pkts->last + 1; | |||
1237 | for (i = 0; i < pkts->npkt; i++) { | |||
1238 | if (idx == pkts->npkt) | |||
1239 | idx = 0; | |||
1240 | if (pkts->pkts[idx].bb_m == NULL((void *)0)) | |||
1241 | return 0; | |||
1242 | idx++; | |||
1243 | } | |||
1244 | return ENOBUFS55; | |||
1245 | } | |||
1246 | ||||
1247 | int | |||
1248 | bwfm_pci_pktid_new(struct bwfm_pci_softc *sc, struct bwfm_pci_pkts *pkts, | |||
1249 | struct mbuf *m, uint32_t *pktid, paddr_t *paddr) | |||
1250 | { | |||
1251 | int i, idx; | |||
1252 | ||||
1253 | idx = pkts->last + 1; | |||
1254 | for (i = 0; i < pkts->npkt; i++) { | |||
1255 | if (idx == pkts->npkt) | |||
1256 | idx = 0; | |||
1257 | if (pkts->pkts[idx].bb_m == NULL((void *)0)) { | |||
1258 | if (bus_dmamap_load_mbuf(sc->sc_dmat,(*(sc->sc_dmat)->_dmamap_load_mbuf)((sc->sc_dmat), ( pkts->pkts[idx].bb_map), (m), (0x0001)) | |||
1259 | pkts->pkts[idx].bb_map, m, BUS_DMA_NOWAIT)(*(sc->sc_dmat)->_dmamap_load_mbuf)((sc->sc_dmat), ( pkts->pkts[idx].bb_map), (m), (0x0001)) != 0) { | |||
1260 | if (m_defrag(m, M_DONTWAIT0x0002)) | |||
1261 | return EFBIG27; | |||
1262 | if (bus_dmamap_load_mbuf(sc->sc_dmat,(*(sc->sc_dmat)->_dmamap_load_mbuf)((sc->sc_dmat), ( pkts->pkts[idx].bb_map), (m), (0x0001)) | |||
1263 | pkts->pkts[idx].bb_map, m, BUS_DMA_NOWAIT)(*(sc->sc_dmat)->_dmamap_load_mbuf)((sc->sc_dmat), ( pkts->pkts[idx].bb_map), (m), (0x0001)) != 0) | |||
1264 | return EFBIG27; | |||
1265 | } | |||
1266 | bus_dmamap_sync(sc->sc_dmat, pkts->pkts[idx].bb_map,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (pkts-> pkts[idx].bb_map), (0), (pkts->pkts[idx].bb_map->dm_mapsize ), (0x01 | 0x04)) | |||
1267 | 0, pkts->pkts[idx].bb_map->dm_mapsize,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (pkts-> pkts[idx].bb_map), (0), (pkts->pkts[idx].bb_map->dm_mapsize ), (0x01 | 0x04)) | |||
1268 | BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (pkts-> pkts[idx].bb_map), (0), (pkts->pkts[idx].bb_map->dm_mapsize ), (0x01 | 0x04)); | |||
1269 | pkts->last = idx; | |||
1270 | pkts->pkts[idx].bb_m = m; | |||
1271 | *pktid = idx; | |||
1272 | *paddr = pkts->pkts[idx].bb_map->dm_segs[0].ds_addr; | |||
1273 | return 0; | |||
1274 | } | |||
1275 | idx++; | |||
1276 | } | |||
1277 | return ENOBUFS55; | |||
1278 | } | |||
1279 | ||||
1280 | struct mbuf * | |||
1281 | bwfm_pci_pktid_free(struct bwfm_pci_softc *sc, struct bwfm_pci_pkts *pkts, | |||
1282 | uint32_t pktid) | |||
1283 | { | |||
1284 | struct mbuf *m; | |||
1285 | ||||
1286 | if (pktid >= pkts->npkt || pkts->pkts[pktid].bb_m == NULL((void *)0)) | |||
1287 | return NULL((void *)0); | |||
1288 | bus_dmamap_sync(sc->sc_dmat, pkts->pkts[pktid].bb_map, 0,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (pkts-> pkts[pktid].bb_map), (0), (pkts->pkts[pktid].bb_map->dm_mapsize ), (0x02 | 0x08)) | |||
1289 | pkts->pkts[pktid].bb_map->dm_mapsize,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (pkts-> pkts[pktid].bb_map), (0), (pkts->pkts[pktid].bb_map->dm_mapsize ), (0x02 | 0x08)) | |||
1290 | BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (pkts-> pkts[pktid].bb_map), (0), (pkts->pkts[pktid].bb_map->dm_mapsize ), (0x02 | 0x08)); | |||
1291 | bus_dmamap_unload(sc->sc_dmat, pkts->pkts[pktid].bb_map)(*(sc->sc_dmat)->_dmamap_unload)((sc->sc_dmat), (pkts ->pkts[pktid].bb_map)); | |||
1292 | m = pkts->pkts[pktid].bb_m; | |||
1293 | pkts->pkts[pktid].bb_m = NULL((void *)0); | |||
1294 | return m; | |||
1295 | } | |||
1296 | ||||
1297 | void | |||
1298 | bwfm_pci_fill_rx_rings(struct bwfm_pci_softc *sc) | |||
1299 | { | |||
1300 | bwfm_pci_fill_rx_buf_ring(sc); | |||
1301 | bwfm_pci_fill_rx_ioctl_ring(sc, &sc->sc_ioctl_ring, | |||
1302 | MSGBUF_TYPE_IOCTLRESP_BUF_POST0xB); | |||
1303 | bwfm_pci_fill_rx_ioctl_ring(sc, &sc->sc_event_ring, | |||
1304 | MSGBUF_TYPE_EVENT_BUF_POST0xD); | |||
1305 | } | |||
1306 | ||||
1307 | void | |||
1308 | bwfm_pci_fill_rx_ioctl_ring(struct bwfm_pci_softc *sc, struct if_rxring *rxring, | |||
1309 | uint32_t msgtype) | |||
1310 | { | |||
1311 | struct msgbuf_rx_ioctl_resp_or_event *req; | |||
1312 | struct mbuf *m; | |||
1313 | uint32_t pktid; | |||
1314 | paddr_t paddr; | |||
1315 | int s, slots; | |||
1316 | ||||
1317 | s = splnet()splraise(0x4); | |||
1318 | for (slots = if_rxr_get(rxring, 8); slots > 0; slots--) { | |||
1319 | if (bwfm_pci_pktid_avail(sc, &sc->sc_rx_pkts)) | |||
1320 | break; | |||
1321 | req = bwfm_pci_ring_write_reserve(sc, &sc->sc_ctrl_submit); | |||
1322 | if (req == NULL((void *)0)) | |||
1323 | break; | |||
1324 | m = MCLGETL(NULL, M_DONTWAIT, MSGBUF_MAX_CTL_PKT_SIZE)m_clget((((void *)0)), (0x0002), (8192)); | |||
1325 | if (m == NULL((void *)0)) { | |||
1326 | bwfm_pci_ring_write_cancel(sc, &sc->sc_ctrl_submit, 1); | |||
1327 | break; | |||
1328 | } | |||
1329 | m->m_lenm_hdr.mh_len = m->m_pkthdrM_dat.MH.MH_pkthdr.len = MSGBUF_MAX_CTL_PKT_SIZE8192; | |||
1330 | if (bwfm_pci_pktid_new(sc, &sc->sc_rx_pkts, m, &pktid, &paddr)) { | |||
1331 | bwfm_pci_ring_write_cancel(sc, &sc->sc_ctrl_submit, 1); | |||
1332 | m_freem(m); | |||
1333 | break; | |||
1334 | } | |||
1335 | memset(req, 0, sizeof(*req))__builtin_memset((req), (0), (sizeof(*req))); | |||
1336 | req->msg.msgtype = msgtype; | |||
1337 | req->msg.request_id = htole32(pktid)((__uint32_t)(pktid)); | |||
1338 | req->host_buf_len = htole16(MSGBUF_MAX_CTL_PKT_SIZE)((__uint16_t)(8192)); | |||
1339 | req->host_buf_addr.high_addr = htole32((uint64_t)paddr >> 32)((__uint32_t)((uint64_t)paddr >> 32)); | |||
1340 | req->host_buf_addr.low_addr = htole32(paddr & 0xffffffff)((__uint32_t)(paddr & 0xffffffff)); | |||
1341 | bwfm_pci_ring_write_commit(sc, &sc->sc_ctrl_submit); | |||
1342 | } | |||
1343 | if_rxr_put(rxring, slots)do { (rxring)->rxr_alive -= (slots); } while (0); | |||
1344 | splx(s)spllower(s); | |||
1345 | } | |||
1346 | ||||
1347 | void | |||
1348 | bwfm_pci_fill_rx_buf_ring(struct bwfm_pci_softc *sc) | |||
1349 | { | |||
1350 | struct msgbuf_rx_bufpost *req; | |||
1351 | struct mbuf *m; | |||
1352 | uint32_t pktid; | |||
1353 | paddr_t paddr; | |||
1354 | int s, slots; | |||
1355 | ||||
1356 | s = splnet()splraise(0x4); | |||
1357 | for (slots = if_rxr_get(&sc->sc_rxbuf_ring, sc->sc_max_rxbufpost); | |||
1358 | slots > 0; slots--) { | |||
1359 | if (bwfm_pci_pktid_avail(sc, &sc->sc_rx_pkts)) | |||
1360 | break; | |||
1361 | req = bwfm_pci_ring_write_reserve(sc, &sc->sc_rxpost_submit); | |||
1362 | if (req == NULL((void *)0)) | |||
1363 | break; | |||
1364 | m = MCLGETL(NULL, M_DONTWAIT, MSGBUF_MAX_PKT_SIZE)m_clget((((void *)0)), (0x0002), (2048)); | |||
1365 | if (m == NULL((void *)0)) { | |||
1366 | bwfm_pci_ring_write_cancel(sc, &sc->sc_rxpost_submit, 1); | |||
1367 | break; | |||
1368 | } | |||
1369 | m->m_lenm_hdr.mh_len = m->m_pkthdrM_dat.MH.MH_pkthdr.len = MSGBUF_MAX_PKT_SIZE2048; | |||
1370 | if (bwfm_pci_pktid_new(sc, &sc->sc_rx_pkts, m, &pktid, &paddr)) { | |||
1371 | bwfm_pci_ring_write_cancel(sc, &sc->sc_rxpost_submit, 1); | |||
1372 | m_freem(m); | |||
1373 | break; | |||
1374 | } | |||
1375 | memset(req, 0, sizeof(*req))__builtin_memset((req), (0), (sizeof(*req))); | |||
1376 | req->msg.msgtype = MSGBUF_TYPE_RXBUF_POST0x11; | |||
1377 | req->msg.request_id = htole32(pktid)((__uint32_t)(pktid)); | |||
1378 | req->data_buf_len = htole16(MSGBUF_MAX_PKT_SIZE)((__uint16_t)(2048)); | |||
1379 | req->data_buf_addr.high_addr = htole32((uint64_t)paddr >> 32)((__uint32_t)((uint64_t)paddr >> 32)); | |||
1380 | req->data_buf_addr.low_addr = htole32(paddr & 0xffffffff)((__uint32_t)(paddr & 0xffffffff)); | |||
1381 | bwfm_pci_ring_write_commit(sc, &sc->sc_rxpost_submit); | |||
1382 | } | |||
1383 | if_rxr_put(&sc->sc_rxbuf_ring, slots)do { (&sc->sc_rxbuf_ring)->rxr_alive -= (slots); } while (0); | |||
1384 | splx(s)spllower(s); | |||
1385 | } | |||
1386 | ||||
1387 | int | |||
1388 | bwfm_pci_setup_ring(struct bwfm_pci_softc *sc, struct bwfm_pci_msgring *ring, | |||
1389 | int nitem, size_t itemsz, uint32_t w_idx, uint32_t r_idx, | |||
1390 | int idx, uint32_t idx_off, uint32_t *ring_mem) | |||
1391 | { | |||
1392 | ring->w_idx_addr = w_idx + idx * idx_off; | |||
1393 | ring->r_idx_addr = r_idx + idx * idx_off; | |||
1394 | ring->w_ptr = 0; | |||
1395 | ring->r_ptr = 0; | |||
1396 | ring->nitem = nitem; | |||
1397 | ring->itemsz = itemsz; | |||
1398 | bwfm_pci_ring_write_rptr(sc, ring); | |||
1399 | bwfm_pci_ring_write_wptr(sc, ring); | |||
1400 | ||||
1401 | ring->ring = bwfm_pci_dmamem_alloc(sc, nitem * itemsz, 8); | |||
1402 | if (ring->ring == NULL((void *)0)) | |||
1403 | return ENOMEM12; | |||
1404 | bus_space_write_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,((sc->sc_tcm_iot)->write_4((sc->sc_tcm_ioh), (*ring_mem + 0x08), (((uint64_t)(ring->ring)->bdm_map->dm_segs [0].ds_addr) & 0xffffffff))) | |||
1405 | *ring_mem + BWFM_RING_MEM_BASE_ADDR_LOW,((sc->sc_tcm_iot)->write_4((sc->sc_tcm_ioh), (*ring_mem + 0x08), (((uint64_t)(ring->ring)->bdm_map->dm_segs [0].ds_addr) & 0xffffffff))) | |||
1406 | BWFM_PCI_DMA_DVA(ring->ring) & 0xffffffff)((sc->sc_tcm_iot)->write_4((sc->sc_tcm_ioh), (*ring_mem + 0x08), (((uint64_t)(ring->ring)->bdm_map->dm_segs [0].ds_addr) & 0xffffffff))); | |||
1407 | bus_space_write_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,((sc->sc_tcm_iot)->write_4((sc->sc_tcm_ioh), (*ring_mem + 0x0c), (((uint64_t)(ring->ring)->bdm_map->dm_segs [0].ds_addr) >> 32))) | |||
1408 | *ring_mem + BWFM_RING_MEM_BASE_ADDR_HIGH,((sc->sc_tcm_iot)->write_4((sc->sc_tcm_ioh), (*ring_mem + 0x0c), (((uint64_t)(ring->ring)->bdm_map->dm_segs [0].ds_addr) >> 32))) | |||
1409 | BWFM_PCI_DMA_DVA(ring->ring) >> 32)((sc->sc_tcm_iot)->write_4((sc->sc_tcm_ioh), (*ring_mem + 0x0c), (((uint64_t)(ring->ring)->bdm_map->dm_segs [0].ds_addr) >> 32))); | |||
1410 | bus_space_write_2(sc->sc_tcm_iot, sc->sc_tcm_ioh,((sc->sc_tcm_iot)->write_2((sc->sc_tcm_ioh), (*ring_mem + 0x04), (nitem))) | |||
1411 | *ring_mem + BWFM_RING_MAX_ITEM, nitem)((sc->sc_tcm_iot)->write_2((sc->sc_tcm_ioh), (*ring_mem + 0x04), (nitem))); | |||
1412 | bus_space_write_2(sc->sc_tcm_iot, sc->sc_tcm_ioh,((sc->sc_tcm_iot)->write_2((sc->sc_tcm_ioh), (*ring_mem + 0x06), (itemsz))) | |||
1413 | *ring_mem + BWFM_RING_LEN_ITEMS, itemsz)((sc->sc_tcm_iot)->write_2((sc->sc_tcm_ioh), (*ring_mem + 0x06), (itemsz))); | |||
1414 | *ring_mem = *ring_mem + BWFM_RING_MEM_SZ16; | |||
1415 | return 0; | |||
1416 | } | |||
1417 | ||||
1418 | int | |||
1419 | bwfm_pci_setup_flowring(struct bwfm_pci_softc *sc, struct bwfm_pci_msgring *ring, | |||
1420 | int nitem, size_t itemsz) | |||
1421 | { | |||
1422 | ring->w_ptr = 0; | |||
1423 | ring->r_ptr = 0; | |||
1424 | ring->nitem = nitem; | |||
1425 | ring->itemsz = itemsz; | |||
1426 | bwfm_pci_ring_write_rptr(sc, ring); | |||
1427 | bwfm_pci_ring_write_wptr(sc, ring); | |||
1428 | ||||
1429 | ring->ring = bwfm_pci_dmamem_alloc(sc, nitem * itemsz, 8); | |||
1430 | if (ring->ring == NULL((void *)0)) | |||
1431 | return ENOMEM12; | |||
1432 | return 0; | |||
1433 | } | |||
1434 | ||||
1435 | /* Ring helpers */ | |||
1436 | void | |||
1437 | bwfm_pci_ring_bell(struct bwfm_pci_softc *sc, | |||
1438 | struct bwfm_pci_msgring *ring) | |||
1439 | { | |||
1440 | if (sc->sc_shared_flags & BWFM_SHARED_INFO_SHARED_DAR0x80000000) | |||
1441 | bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,((sc->sc_reg_iot)->write_4((sc->sc_reg_ioh), (0xA20) , (1))) | |||
1442 | BWFM_PCI_64_PCIE2REG_H2D_MAILBOX_0, 1)((sc->sc_reg_iot)->write_4((sc->sc_reg_ioh), (0xA20) , (1))); | |||
1443 | else | |||
1444 | bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,((sc->sc_reg_iot)->write_4((sc->sc_reg_ioh), (0x140) , (1))) | |||
1445 | BWFM_PCI_PCIE2REG_H2D_MAILBOX_0, 1)((sc->sc_reg_iot)->write_4((sc->sc_reg_ioh), (0x140) , (1))); | |||
1446 | } | |||
1447 | ||||
1448 | void | |||
1449 | bwfm_pci_ring_update_rptr(struct bwfm_pci_softc *sc, | |||
1450 | struct bwfm_pci_msgring *ring) | |||
1451 | { | |||
1452 | if (sc->sc_dma_idx_sz == 0) { | |||
1453 | ring->r_ptr = bus_space_read_2(sc->sc_tcm_iot,((sc->sc_tcm_iot)->read_2((sc->sc_tcm_ioh), (ring-> r_idx_addr))) | |||
1454 | sc->sc_tcm_ioh, ring->r_idx_addr)((sc->sc_tcm_iot)->read_2((sc->sc_tcm_ioh), (ring-> r_idx_addr))); | |||
1455 | } else { | |||
1456 | bus_dmamap_sync(sc->sc_dmat,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (((sc-> sc_dma_idx_buf)->bdm_map)), (ring->r_idx_addr), (sizeof (uint16_t)), (0x02 | 0x08)) | |||
1457 | BWFM_PCI_DMA_MAP(sc->sc_dma_idx_buf), ring->r_idx_addr,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (((sc-> sc_dma_idx_buf)->bdm_map)), (ring->r_idx_addr), (sizeof (uint16_t)), (0x02 | 0x08)) | |||
1458 | sizeof(uint16_t), BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (((sc-> sc_dma_idx_buf)->bdm_map)), (ring->r_idx_addr), (sizeof (uint16_t)), (0x02 | 0x08)); | |||
1459 | ring->r_ptr = *(uint16_t *)(BWFM_PCI_DMA_KVA(sc->sc_dma_idx_buf)((void *)(sc->sc_dma_idx_buf)->bdm_kva) | |||
1460 | + ring->r_idx_addr); | |||
1461 | } | |||
1462 | } | |||
1463 | ||||
1464 | void | |||
1465 | bwfm_pci_ring_update_wptr(struct bwfm_pci_softc *sc, | |||
1466 | struct bwfm_pci_msgring *ring) | |||
1467 | { | |||
1468 | if (sc->sc_dma_idx_sz == 0) { | |||
1469 | ring->w_ptr = bus_space_read_2(sc->sc_tcm_iot,((sc->sc_tcm_iot)->read_2((sc->sc_tcm_ioh), (ring-> w_idx_addr))) | |||
1470 | sc->sc_tcm_ioh, ring->w_idx_addr)((sc->sc_tcm_iot)->read_2((sc->sc_tcm_ioh), (ring-> w_idx_addr))); | |||
1471 | } else { | |||
1472 | bus_dmamap_sync(sc->sc_dmat,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (((sc-> sc_dma_idx_buf)->bdm_map)), (ring->w_idx_addr), (sizeof (uint16_t)), (0x02 | 0x08)) | |||
1473 | BWFM_PCI_DMA_MAP(sc->sc_dma_idx_buf), ring->w_idx_addr,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (((sc-> sc_dma_idx_buf)->bdm_map)), (ring->w_idx_addr), (sizeof (uint16_t)), (0x02 | 0x08)) | |||
1474 | sizeof(uint16_t), BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (((sc-> sc_dma_idx_buf)->bdm_map)), (ring->w_idx_addr), (sizeof (uint16_t)), (0x02 | 0x08)); | |||
1475 | ring->w_ptr = *(uint16_t *)(BWFM_PCI_DMA_KVA(sc->sc_dma_idx_buf)((void *)(sc->sc_dma_idx_buf)->bdm_kva) | |||
1476 | + ring->w_idx_addr); | |||
1477 | } | |||
1478 | } | |||
1479 | ||||
1480 | void | |||
1481 | bwfm_pci_ring_write_rptr(struct bwfm_pci_softc *sc, | |||
1482 | struct bwfm_pci_msgring *ring) | |||
1483 | { | |||
1484 | if (sc->sc_dma_idx_sz == 0) { | |||
1485 | bus_space_write_2(sc->sc_tcm_iot, sc->sc_tcm_ioh,((sc->sc_tcm_iot)->write_2((sc->sc_tcm_ioh), (ring-> r_idx_addr), (ring->r_ptr))) | |||
1486 | ring->r_idx_addr, ring->r_ptr)((sc->sc_tcm_iot)->write_2((sc->sc_tcm_ioh), (ring-> r_idx_addr), (ring->r_ptr))); | |||
1487 | } else { | |||
1488 | *(uint16_t *)(BWFM_PCI_DMA_KVA(sc->sc_dma_idx_buf)((void *)(sc->sc_dma_idx_buf)->bdm_kva) | |||
1489 | + ring->r_idx_addr) = ring->r_ptr; | |||
1490 | bus_dmamap_sync(sc->sc_dmat,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (((sc-> sc_dma_idx_buf)->bdm_map)), (ring->r_idx_addr), (sizeof (uint16_t)), (0x01 | 0x04)) | |||
1491 | BWFM_PCI_DMA_MAP(sc->sc_dma_idx_buf), ring->r_idx_addr,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (((sc-> sc_dma_idx_buf)->bdm_map)), (ring->r_idx_addr), (sizeof (uint16_t)), (0x01 | 0x04)) | |||
1492 | sizeof(uint16_t), BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (((sc-> sc_dma_idx_buf)->bdm_map)), (ring->r_idx_addr), (sizeof (uint16_t)), (0x01 | 0x04)); | |||
1493 | } | |||
1494 | } | |||
1495 | ||||
1496 | void | |||
1497 | bwfm_pci_ring_write_wptr(struct bwfm_pci_softc *sc, | |||
1498 | struct bwfm_pci_msgring *ring) | |||
1499 | { | |||
1500 | if (sc->sc_dma_idx_sz == 0) { | |||
1501 | bus_space_write_2(sc->sc_tcm_iot, sc->sc_tcm_ioh,((sc->sc_tcm_iot)->write_2((sc->sc_tcm_ioh), (ring-> w_idx_addr), (ring->w_ptr))) | |||
1502 | ring->w_idx_addr, ring->w_ptr)((sc->sc_tcm_iot)->write_2((sc->sc_tcm_ioh), (ring-> w_idx_addr), (ring->w_ptr))); | |||
1503 | } else { | |||
1504 | *(uint16_t *)(BWFM_PCI_DMA_KVA(sc->sc_dma_idx_buf)((void *)(sc->sc_dma_idx_buf)->bdm_kva) | |||
1505 | + ring->w_idx_addr) = ring->w_ptr; | |||
1506 | bus_dmamap_sync(sc->sc_dmat,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (((sc-> sc_dma_idx_buf)->bdm_map)), (ring->w_idx_addr), (sizeof (uint16_t)), (0x01 | 0x04)) | |||
1507 | BWFM_PCI_DMA_MAP(sc->sc_dma_idx_buf), ring->w_idx_addr,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (((sc-> sc_dma_idx_buf)->bdm_map)), (ring->w_idx_addr), (sizeof (uint16_t)), (0x01 | 0x04)) | |||
1508 | sizeof(uint16_t), BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (((sc-> sc_dma_idx_buf)->bdm_map)), (ring->w_idx_addr), (sizeof (uint16_t)), (0x01 | 0x04)); | |||
1509 | } | |||
1510 | } | |||
1511 | ||||
1512 | /* | |||
1513 | * Retrieve a free descriptor to put new stuff in, but don't commit | |||
1514 | * to it yet so we can rollback later if any error occurs. | |||
1515 | */ | |||
1516 | void * | |||
1517 | bwfm_pci_ring_write_reserve(struct bwfm_pci_softc *sc, | |||
1518 | struct bwfm_pci_msgring *ring) | |||
1519 | { | |||
1520 | int available; | |||
1521 | char *ret; | |||
1522 | ||||
1523 | bwfm_pci_ring_update_rptr(sc, ring); | |||
1524 | ||||
1525 | if (ring->r_ptr > ring->w_ptr) | |||
1526 | available = ring->r_ptr - ring->w_ptr; | |||
1527 | else | |||
1528 | available = ring->r_ptr + (ring->nitem - ring->w_ptr); | |||
1529 | ||||
1530 | if (available <= 1) | |||
1531 | return NULL((void *)0); | |||
1532 | ||||
1533 | ret = BWFM_PCI_DMA_KVA(ring->ring)((void *)(ring->ring)->bdm_kva) + (ring->w_ptr * ring->itemsz); | |||
1534 | ring->w_ptr += 1; | |||
1535 | if (ring->w_ptr == ring->nitem) | |||
1536 | ring->w_ptr = 0; | |||
1537 | return ret; | |||
1538 | } | |||
1539 | ||||
1540 | void * | |||
1541 | bwfm_pci_ring_write_reserve_multi(struct bwfm_pci_softc *sc, | |||
1542 | struct bwfm_pci_msgring *ring, int count, int *avail) | |||
1543 | { | |||
1544 | int available; | |||
1545 | char *ret; | |||
1546 | ||||
1547 | bwfm_pci_ring_update_rptr(sc, ring); | |||
1548 | ||||
1549 | if (ring->r_ptr > ring->w_ptr) | |||
1550 | available = ring->r_ptr - ring->w_ptr; | |||
1551 | else | |||
1552 | available = ring->r_ptr + (ring->nitem - ring->w_ptr); | |||
1553 | ||||
1554 | if (available <= 1) | |||
1555 | return NULL((void *)0); | |||
1556 | ||||
1557 | ret = BWFM_PCI_DMA_KVA(ring->ring)((void *)(ring->ring)->bdm_kva) + (ring->w_ptr * ring->itemsz); | |||
1558 | *avail = min(count, available - 1); | |||
1559 | if (*avail + ring->w_ptr > ring->nitem) | |||
1560 | *avail = ring->nitem - ring->w_ptr; | |||
1561 | ring->w_ptr += *avail; | |||
1562 | if (ring->w_ptr == ring->nitem) | |||
1563 | ring->w_ptr = 0; | |||
1564 | return ret; | |||
1565 | } | |||
1566 | ||||
1567 | /* | |||
1568 | * Read number of descriptors available (submitted by the firmware) | |||
1569 | * and retrieve pointer to first descriptor. | |||
1570 | */ | |||
1571 | void * | |||
1572 | bwfm_pci_ring_read_avail(struct bwfm_pci_softc *sc, | |||
1573 | struct bwfm_pci_msgring *ring, int *avail) | |||
1574 | { | |||
1575 | bwfm_pci_ring_update_wptr(sc, ring); | |||
1576 | ||||
1577 | if (ring->w_ptr >= ring->r_ptr) | |||
1578 | *avail = ring->w_ptr - ring->r_ptr; | |||
1579 | else | |||
1580 | *avail = ring->nitem - ring->r_ptr; | |||
1581 | ||||
1582 | if (*avail == 0) | |||
1583 | return NULL((void *)0); | |||
1584 | ||||
1585 | bus_dmamap_sync(sc->sc_dmat, BWFM_PCI_DMA_MAP(ring->ring),(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (((ring ->ring)->bdm_map)), (ring->r_ptr * ring->itemsz), (*avail * ring->itemsz), (0x02 | 0x08)) | |||
1586 | ring->r_ptr * ring->itemsz, *avail * ring->itemsz,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (((ring ->ring)->bdm_map)), (ring->r_ptr * ring->itemsz), (*avail * ring->itemsz), (0x02 | 0x08)) | |||
1587 | BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (((ring ->ring)->bdm_map)), (ring->r_ptr * ring->itemsz), (*avail * ring->itemsz), (0x02 | 0x08)); | |||
1588 | return BWFM_PCI_DMA_KVA(ring->ring)((void *)(ring->ring)->bdm_kva) + (ring->r_ptr * ring->itemsz); | |||
1589 | } | |||
1590 | ||||
1591 | /* | |||
1592 | * Let firmware know we read N descriptors. | |||
1593 | */ | |||
1594 | void | |||
1595 | bwfm_pci_ring_read_commit(struct bwfm_pci_softc *sc, | |||
1596 | struct bwfm_pci_msgring *ring, int nitem) | |||
1597 | { | |||
1598 | ring->r_ptr += nitem; | |||
1599 | if (ring->r_ptr == ring->nitem) | |||
1600 | ring->r_ptr = 0; | |||
1601 | bwfm_pci_ring_write_rptr(sc, ring); | |||
1602 | } | |||
1603 | ||||
1604 | /* | |||
1605 | * Let firmware know that we submitted some descriptors. | |||
1606 | */ | |||
1607 | void | |||
1608 | bwfm_pci_ring_write_commit(struct bwfm_pci_softc *sc, | |||
1609 | struct bwfm_pci_msgring *ring) | |||
1610 | { | |||
1611 | bus_dmamap_sync(sc->sc_dmat, BWFM_PCI_DMA_MAP(ring->ring),(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (((ring ->ring)->bdm_map)), (0), (((ring->ring)->bdm_size )), (0x01 | 0x04)) | |||
1612 | 0, BWFM_PCI_DMA_LEN(ring->ring), BUS_DMASYNC_PREREAD |(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (((ring ->ring)->bdm_map)), (0), (((ring->ring)->bdm_size )), (0x01 | 0x04)) | |||
1613 | BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (((ring ->ring)->bdm_map)), (0), (((ring->ring)->bdm_size )), (0x01 | 0x04)); | |||
1614 | bwfm_pci_ring_write_wptr(sc, ring); | |||
1615 | bwfm_pci_ring_bell(sc, ring); | |||
1616 | } | |||
1617 | ||||
1618 | /* | |||
1619 | * Rollback N descriptors in case we don't actually want | |||
1620 | * to commit to it. | |||
1621 | */ | |||
1622 | void | |||
1623 | bwfm_pci_ring_write_cancel(struct bwfm_pci_softc *sc, | |||
1624 | struct bwfm_pci_msgring *ring, int nitem) | |||
1625 | { | |||
1626 | if (ring->w_ptr == 0) | |||
1627 | ring->w_ptr = ring->nitem - nitem; | |||
1628 | else | |||
1629 | ring->w_ptr -= nitem; | |||
1630 | } | |||
1631 | ||||
1632 | /* | |||
1633 | * Foreach written descriptor on the ring, pass the descriptor to | |||
1634 | * a message handler and let the firmware know we handled it. | |||
1635 | */ | |||
1636 | void | |||
1637 | bwfm_pci_ring_rx(struct bwfm_pci_softc *sc, struct bwfm_pci_msgring *ring, | |||
1638 | struct mbuf_list *ml) | |||
1639 | { | |||
1640 | void *buf; | |||
1641 | int avail, processed; | |||
1642 | ||||
1643 | again: | |||
1644 | buf = bwfm_pci_ring_read_avail(sc, ring, &avail); | |||
1645 | if (buf == NULL((void *)0)) | |||
1646 | return; | |||
1647 | ||||
1648 | processed = 0; | |||
1649 | while (avail) { | |||
1650 | bwfm_pci_msg_rx(sc, buf + sc->sc_rx_dataoffset, ml); | |||
1651 | buf += ring->itemsz; | |||
1652 | processed++; | |||
1653 | if (processed == 48) { | |||
1654 | bwfm_pci_ring_read_commit(sc, ring, processed); | |||
1655 | processed = 0; | |||
1656 | } | |||
1657 | avail--; | |||
1658 | } | |||
1659 | if (processed) | |||
1660 | bwfm_pci_ring_read_commit(sc, ring, processed); | |||
1661 | if (ring->r_ptr == 0) | |||
1662 | goto again; | |||
1663 | } | |||
1664 | ||||
1665 | void | |||
1666 | bwfm_pci_msg_rx(struct bwfm_pci_softc *sc, void *buf, struct mbuf_list *ml) | |||
1667 | { | |||
1668 | struct ifnet *ifp = &sc->sc_sc.sc_ic.ic_ific_ac.ac_if; | |||
1669 | struct msgbuf_ioctl_resp_hdr *resp; | |||
1670 | struct msgbuf_tx_status *tx; | |||
1671 | struct msgbuf_rx_complete *rx; | |||
1672 | struct msgbuf_rx_event *event; | |||
1673 | struct msgbuf_d2h_mailbox_data *d2h; | |||
1674 | struct msgbuf_common_hdr *msg; | |||
1675 | struct msgbuf_flowring_create_resp *fcr; | |||
1676 | struct msgbuf_flowring_delete_resp *fdr; | |||
1677 | struct bwfm_cmd_flowring_create fdcmd; | |||
1678 | struct bwfm_pci_msgring *ring; | |||
1679 | struct mbuf *m; | |||
1680 | int flowid; | |||
1681 | ||||
1682 | msg = (struct msgbuf_common_hdr *)buf; | |||
1683 | switch (msg->msgtype) | |||
1684 | { | |||
1685 | case MSGBUF_TYPE_FLOW_RING_CREATE_CMPLT0x4: | |||
1686 | fcr = (struct msgbuf_flowring_create_resp *)buf; | |||
1687 | flowid = letoh16(fcr->compl_hdr.flow_ring_id)((__uint16_t)(fcr->compl_hdr.flow_ring_id)); | |||
1688 | if (flowid < 2) | |||
1689 | break; | |||
1690 | flowid -= 2; | |||
1691 | if (flowid >= sc->sc_max_flowrings) | |||
1692 | break; | |||
1693 | ring = &sc->sc_flowrings[flowid]; | |||
1694 | if (ring->status != RING_OPENING) | |||
1695 | break; | |||
1696 | if (fcr->compl_hdr.status) { | |||
1697 | printf("%s: failed to open flowring %d\n", | |||
1698 | DEVNAME(sc)((sc)->sc_sc.sc_dev.dv_xname), flowid); | |||
1699 | ring->status = RING_CLOSED; | |||
1700 | if (ring->m) { | |||
1701 | m_freem(ring->m); | |||
1702 | ring->m = NULL((void *)0); | |||
1703 | } | |||
1704 | ifq_restart(&ifp->if_snd); | |||
1705 | break; | |||
1706 | } | |||
1707 | ring->status = RING_OPEN; | |||
1708 | if (ring->m != NULL((void *)0)) { | |||
1709 | m = ring->m; | |||
1710 | ring->m = NULL((void *)0); | |||
1711 | if (bwfm_pci_txdata(&sc->sc_sc, m)) | |||
1712 | m_freem(ring->m); | |||
1713 | } | |||
1714 | ifq_restart(&ifp->if_snd); | |||
1715 | break; | |||
1716 | case MSGBUF_TYPE_FLOW_RING_DELETE_CMPLT0x6: | |||
1717 | fdr = (struct msgbuf_flowring_delete_resp *)buf; | |||
1718 | flowid = letoh16(fdr->compl_hdr.flow_ring_id)((__uint16_t)(fdr->compl_hdr.flow_ring_id)); | |||
1719 | if (flowid < 2) | |||
1720 | break; | |||
1721 | flowid -= 2; | |||
1722 | if (flowid >= sc->sc_max_flowrings) | |||
1723 | break; | |||
1724 | ring = &sc->sc_flowrings[flowid]; | |||
1725 | if (ring->status != RING_CLOSING) | |||
1726 | break; | |||
1727 | if (fdr->compl_hdr.status) { | |||
1728 | printf("%s: failed to delete flowring %d\n", | |||
1729 | DEVNAME(sc)((sc)->sc_sc.sc_dev.dv_xname), flowid); | |||
1730 | break; | |||
1731 | } | |||
1732 | fdcmd.flowid = flowid; | |||
1733 | bwfm_do_async(&sc->sc_sc, bwfm_pci_flowring_delete_cb, | |||
1734 | &fdcmd, sizeof(fdcmd)); | |||
1735 | break; | |||
1736 | case MSGBUF_TYPE_IOCTLPTR_REQ_ACK0xA: | |||
1737 | m = bwfm_pci_pktid_free(sc, &sc->sc_ioctl_pkts, | |||
1738 | letoh32(msg->request_id)((__uint32_t)(msg->request_id))); | |||
1739 | if (m == NULL((void *)0)) | |||
1740 | break; | |||
1741 | m_freem(m); | |||
1742 | break; | |||
1743 | case MSGBUF_TYPE_IOCTL_CMPLT0xC: | |||
1744 | resp = (struct msgbuf_ioctl_resp_hdr *)buf; | |||
1745 | bwfm_pci_msgbuf_rxioctl(sc, resp); | |||
1746 | if_rxr_put(&sc->sc_ioctl_ring, 1)do { (&sc->sc_ioctl_ring)->rxr_alive -= (1); } while (0); | |||
1747 | bwfm_pci_fill_rx_rings(sc); | |||
1748 | break; | |||
1749 | case MSGBUF_TYPE_WL_EVENT0xE: | |||
1750 | event = (struct msgbuf_rx_event *)buf; | |||
1751 | m = bwfm_pci_pktid_free(sc, &sc->sc_rx_pkts, | |||
1752 | letoh32(event->msg.request_id)((__uint32_t)(event->msg.request_id))); | |||
1753 | if (m == NULL((void *)0)) | |||
1754 | break; | |||
1755 | m_adj(m, sc->sc_rx_dataoffset); | |||
1756 | m->m_lenm_hdr.mh_len = m->m_pkthdrM_dat.MH.MH_pkthdr.len = letoh16(event->event_data_len)((__uint16_t)(event->event_data_len)); | |||
1757 | bwfm_rx(&sc->sc_sc, m, ml); | |||
1758 | if_rxr_put(&sc->sc_event_ring, 1)do { (&sc->sc_event_ring)->rxr_alive -= (1); } while (0); | |||
1759 | bwfm_pci_fill_rx_rings(sc); | |||
1760 | break; | |||
1761 | case MSGBUF_TYPE_TX_STATUS0x10: | |||
1762 | tx = (struct msgbuf_tx_status *)buf; | |||
1763 | m = bwfm_pci_pktid_free(sc, &sc->sc_tx_pkts, | |||
1764 | letoh32(tx->msg.request_id)((__uint32_t)(tx->msg.request_id)) - 1); | |||
1765 | if (m == NULL((void *)0)) | |||
1766 | break; | |||
1767 | m_freem(m); | |||
1768 | if (sc->sc_tx_pkts_full) { | |||
1769 | sc->sc_tx_pkts_full = 0; | |||
1770 | ifq_restart(&ifp->if_snd); | |||
1771 | } | |||
1772 | break; | |||
1773 | case MSGBUF_TYPE_RX_CMPLT0x12: | |||
1774 | rx = (struct msgbuf_rx_complete *)buf; | |||
1775 | m = bwfm_pci_pktid_free(sc, &sc->sc_rx_pkts, | |||
1776 | letoh32(rx->msg.request_id)((__uint32_t)(rx->msg.request_id))); | |||
1777 | if (m == NULL((void *)0)) | |||
1778 | break; | |||
1779 | if (letoh16(rx->data_offset)((__uint16_t)(rx->data_offset))) | |||
1780 | m_adj(m, letoh16(rx->data_offset)((__uint16_t)(rx->data_offset))); | |||
1781 | else if (sc->sc_rx_dataoffset) | |||
1782 | m_adj(m, sc->sc_rx_dataoffset); | |||
1783 | m->m_lenm_hdr.mh_len = m->m_pkthdrM_dat.MH.MH_pkthdr.len = letoh16(rx->data_len)((__uint16_t)(rx->data_len)); | |||
1784 | bwfm_rx(&sc->sc_sc, m, ml); | |||
1785 | if_rxr_put(&sc->sc_rxbuf_ring, 1)do { (&sc->sc_rxbuf_ring)->rxr_alive -= (1); } while (0); | |||
1786 | bwfm_pci_fill_rx_rings(sc); | |||
1787 | break; | |||
1788 | case MSGBUF_TYPE_D2H_MAILBOX_DATA0x24: | |||
1789 | d2h = (struct msgbuf_d2h_mailbox_data *)buf; | |||
1790 | if (d2h->data & BWFM_PCI_D2H_DEV_D3_ACK0x00000001) { | |||
1791 | sc->sc_mbdata_done = 1; | |||
1792 | wakeup(&sc->sc_mbdata_done); | |||
1793 | } | |||
1794 | break; | |||
1795 | default: | |||
1796 | printf("%s: msgtype 0x%08x\n", __func__, msg->msgtype); | |||
1797 | break; | |||
1798 | } | |||
1799 | } | |||
1800 | ||||
1801 | /* Bus core helpers */ | |||
1802 | void | |||
1803 | bwfm_pci_select_core(struct bwfm_pci_softc *sc, int id) | |||
1804 | { | |||
1805 | struct bwfm_softc *bwfm = (void *)sc; | |||
1806 | struct bwfm_core *core; | |||
1807 | ||||
1808 | core = bwfm_chip_get_core(bwfm, id); | |||
1809 | if (core == NULL((void *)0)) { | |||
1810 | printf("%s: could not find core to select", DEVNAME(sc)((sc)->sc_sc.sc_dev.dv_xname)); | |||
1811 | return; | |||
1812 | } | |||
1813 | ||||
1814 | pci_conf_write(sc->sc_pc, sc->sc_tag, | |||
1815 | BWFM_PCI_BAR0_WINDOW0x80, core->co_base); | |||
1816 | if (pci_conf_read(sc->sc_pc, sc->sc_tag, | |||
1817 | BWFM_PCI_BAR0_WINDOW0x80) != core->co_base) | |||
1818 | pci_conf_write(sc->sc_pc, sc->sc_tag, | |||
1819 | BWFM_PCI_BAR0_WINDOW0x80, core->co_base); | |||
1820 | } | |||
1821 | ||||
1822 | uint32_t | |||
1823 | bwfm_pci_buscore_read(struct bwfm_softc *bwfm, uint32_t reg) | |||
1824 | { | |||
1825 | struct bwfm_pci_softc *sc = (void *)bwfm; | |||
1826 | uint32_t page, offset; | |||
1827 | ||||
1828 | page = reg & ~(BWFM_PCI_BAR0_REG_SIZE0x1000 - 1); | |||
1829 | offset = reg & (BWFM_PCI_BAR0_REG_SIZE0x1000 - 1); | |||
1830 | pci_conf_write(sc->sc_pc, sc->sc_tag, BWFM_PCI_BAR0_WINDOW0x80, page); | |||
1831 | return bus_space_read_4(sc->sc_reg_iot, sc->sc_reg_ioh, offset)((sc->sc_reg_iot)->read_4((sc->sc_reg_ioh), (offset) )); | |||
1832 | } | |||
1833 | ||||
1834 | void | |||
1835 | bwfm_pci_buscore_write(struct bwfm_softc *bwfm, uint32_t reg, uint32_t val) | |||
1836 | { | |||
1837 | struct bwfm_pci_softc *sc = (void *)bwfm; | |||
1838 | uint32_t page, offset; | |||
1839 | ||||
1840 | page = reg & ~(BWFM_PCI_BAR0_REG_SIZE0x1000 - 1); | |||
1841 | offset = reg & (BWFM_PCI_BAR0_REG_SIZE0x1000 - 1); | |||
1842 | pci_conf_write(sc->sc_pc, sc->sc_tag, BWFM_PCI_BAR0_WINDOW0x80, page); | |||
1843 | bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh, offset, val)((sc->sc_reg_iot)->write_4((sc->sc_reg_ioh), (offset ), (val))); | |||
1844 | } | |||
1845 | ||||
1846 | int | |||
1847 | bwfm_pci_buscore_prepare(struct bwfm_softc *bwfm) | |||
1848 | { | |||
1849 | return 0; | |||
1850 | } | |||
1851 | ||||
1852 | int | |||
1853 | bwfm_pci_buscore_reset(struct bwfm_softc *bwfm) | |||
1854 | { | |||
1855 | struct bwfm_pci_softc *sc = (void *)bwfm; | |||
1856 | struct bwfm_core *core; | |||
1857 | uint32_t reg; | |||
1858 | int i; | |||
1859 | ||||
1860 | bwfm_pci_select_core(sc, BWFM_AGENT_CORE_PCIE20x83C); | |||
1861 | reg = pci_conf_read(sc->sc_pc, sc->sc_tag, | |||
1862 | BWFM_PCI_CFGREG_LINK_STATUS_CTRL0x0BC); | |||
1863 | pci_conf_write(sc->sc_pc, sc->sc_tag, BWFM_PCI_CFGREG_LINK_STATUS_CTRL0x0BC, | |||
1864 | reg & ~BWFM_PCI_CFGREG_LINK_STATUS_CTRL_ASPM_ENAB0x3); | |||
1865 | ||||
1866 | bwfm_pci_select_core(sc, BWFM_AGENT_CORE_CHIPCOMMON0x800); | |||
1867 | bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,((sc->sc_reg_iot)->write_4((sc->sc_reg_ioh), (0x00000080 ), (4))) | |||
1868 | BWFM_CHIP_REG_WATCHDOG, 4)((sc->sc_reg_iot)->write_4((sc->sc_reg_ioh), (0x00000080 ), (4))); | |||
1869 | delay(100 * 1000)(*delay_func)(100 * 1000); | |||
1870 | ||||
1871 | bwfm_pci_select_core(sc, BWFM_AGENT_CORE_PCIE20x83C); | |||
1872 | pci_conf_write(sc->sc_pc, sc->sc_tag, | |||
1873 | BWFM_PCI_CFGREG_LINK_STATUS_CTRL0x0BC, reg); | |||
1874 | ||||
1875 | core = bwfm_chip_get_core(bwfm, BWFM_AGENT_CORE_PCIE20x83C); | |||
1876 | if (core->co_rev <= 13) { | |||
1877 | uint16_t cfg_offset[] = { | |||
1878 | BWFM_PCI_CFGREG_STATUS_CMD0x004, | |||
1879 | BWFM_PCI_CFGREG_PM_CSR0x04C, | |||
1880 | BWFM_PCI_CFGREG_MSI_CAP0x058, | |||
1881 | BWFM_PCI_CFGREG_MSI_ADDR_L0x05C, | |||
1882 | BWFM_PCI_CFGREG_MSI_ADDR_H0x060, | |||
1883 | BWFM_PCI_CFGREG_MSI_DATA0x064, | |||
1884 | BWFM_PCI_CFGREG_LINK_STATUS_CTRL20x0DC, | |||
1885 | BWFM_PCI_CFGREG_RBAR_CTRL0x228, | |||
1886 | BWFM_PCI_CFGREG_PML1_SUB_CTRL10x248, | |||
1887 | BWFM_PCI_CFGREG_REG_BAR2_CONFIG0x4E0, | |||
1888 | BWFM_PCI_CFGREG_REG_BAR3_CONFIG0x4F4, | |||
1889 | }; | |||
1890 | ||||
1891 | for (i = 0; i < nitems(cfg_offset)(sizeof((cfg_offset)) / sizeof((cfg_offset)[0])); i++) { | |||
1892 | bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,((sc->sc_reg_iot)->write_4((sc->sc_reg_ioh), (0x120) , (cfg_offset[i]))) | |||
1893 | BWFM_PCI_PCIE2REG_CONFIGADDR, cfg_offset[i])((sc->sc_reg_iot)->write_4((sc->sc_reg_ioh), (0x120) , (cfg_offset[i]))); | |||
1894 | reg = bus_space_read_4(sc->sc_reg_iot, sc->sc_reg_ioh,((sc->sc_reg_iot)->read_4((sc->sc_reg_ioh), (0x124)) ) | |||
1895 | BWFM_PCI_PCIE2REG_CONFIGDATA)((sc->sc_reg_iot)->read_4((sc->sc_reg_ioh), (0x124)) ); | |||
1896 | DPRINTFN(3, ("%s: config offset 0x%04x, value 0x%04x\n",do { ; } while (0) | |||
1897 | DEVNAME(sc), cfg_offset[i], reg))do { ; } while (0); | |||
1898 | bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,((sc->sc_reg_iot)->write_4((sc->sc_reg_ioh), (0x124) , (reg))) | |||
1899 | BWFM_PCI_PCIE2REG_CONFIGDATA, reg)((sc->sc_reg_iot)->write_4((sc->sc_reg_ioh), (0x124) , (reg))); | |||
1900 | } | |||
1901 | } | |||
1902 | if (core->co_rev >= 64) | |||
1903 | sc->sc_pcireg64 = 1; | |||
1904 | ||||
1905 | reg = bwfm_pci_intr_status(sc); | |||
1906 | if (reg != 0xffffffff) | |||
1907 | bwfm_pci_intr_ack(sc, reg); | |||
1908 | ||||
1909 | return 0; | |||
1910 | } | |||
1911 | ||||
1912 | void | |||
1913 | bwfm_pci_buscore_activate(struct bwfm_softc *bwfm, uint32_t rstvec) | |||
1914 | { | |||
1915 | struct bwfm_pci_softc *sc = (void *)bwfm; | |||
1916 | bus_space_write_4(sc->sc_tcm_iot, sc->sc_tcm_ioh, 0, rstvec)((sc->sc_tcm_iot)->write_4((sc->sc_tcm_ioh), (0), (rstvec ))); | |||
1917 | } | |||
1918 | ||||
1919 | static int bwfm_pci_prio2fifo[8] = { | |||
1920 | 0, /* best effort */ | |||
1921 | 1, /* IPTOS_PREC_IMMEDIATE */ | |||
1922 | 1, /* IPTOS_PREC_PRIORITY */ | |||
1923 | 0, /* IPTOS_PREC_FLASH */ | |||
1924 | 2, /* IPTOS_PREC_FLASHOVERRIDE */ | |||
1925 | 2, /* IPTOS_PREC_CRITIC_ECP */ | |||
1926 | 3, /* IPTOS_PREC_INTERNETCONTROL */ | |||
1927 | 3, /* IPTOS_PREC_NETCONTROL */ | |||
1928 | }; | |||
1929 | ||||
1930 | int | |||
1931 | bwfm_pci_flowring_lookup(struct bwfm_pci_softc *sc, struct mbuf *m) | |||
1932 | { | |||
1933 | struct ieee80211com *ic = &sc->sc_sc.sc_ic; | |||
1934 | #ifndef IEEE80211_STA_ONLY | |||
1935 | uint8_t *da = mtod(m, uint8_t *)((uint8_t *)((m)->m_hdr.mh_data)); | |||
1936 | #endif | |||
1937 | int flowid, prio, fifo; | |||
1938 | int i, found; | |||
1939 | ||||
1940 | prio = ieee80211_classify(ic, m); | |||
1941 | fifo = bwfm_pci_prio2fifo[prio]; | |||
1942 | ||||
1943 | switch (ic->ic_opmode) | |||
1944 | { | |||
1945 | case IEEE80211_M_STA: | |||
1946 | flowid = fifo; | |||
1947 | break; | |||
1948 | #ifndef IEEE80211_STA_ONLY | |||
1949 | case IEEE80211_M_HOSTAP: | |||
1950 | if (ETHER_IS_MULTICAST(da)(*(da) & 0x01)) | |||
1951 | da = etherbroadcastaddr; | |||
1952 | flowid = da[5] * 2 + fifo; | |||
1953 | break; | |||
1954 | #endif | |||
1955 | default: | |||
1956 | printf("%s: state not supported\n", DEVNAME(sc)((sc)->sc_sc.sc_dev.dv_xname)); | |||
1957 | return ENOBUFS55; | |||
1958 | } | |||
1959 | ||||
1960 | found = 0; | |||
1961 | flowid = flowid % sc->sc_max_flowrings; | |||
1962 | for (i = 0; i < sc->sc_max_flowrings; i++) { | |||
1963 | if (ic->ic_opmode == IEEE80211_M_STA && | |||
1964 | sc->sc_flowrings[flowid].status >= RING_OPEN && | |||
1965 | sc->sc_flowrings[flowid].fifo == fifo) { | |||
1966 | found = 1; | |||
1967 | break; | |||
1968 | } | |||
1969 | #ifndef IEEE80211_STA_ONLY | |||
1970 | if (ic->ic_opmode == IEEE80211_M_HOSTAP && | |||
1971 | sc->sc_flowrings[flowid].status >= RING_OPEN && | |||
1972 | sc->sc_flowrings[flowid].fifo == fifo && | |||
1973 | !memcmp(sc->sc_flowrings[flowid].mac, da, ETHER_ADDR_LEN)__builtin_memcmp((sc->sc_flowrings[flowid].mac), (da), (6) )) { | |||
1974 | found = 1; | |||
1975 | break; | |||
1976 | } | |||
1977 | #endif | |||
1978 | flowid = (flowid + 1) % sc->sc_max_flowrings; | |||
1979 | } | |||
1980 | ||||
1981 | if (found) | |||
1982 | return flowid; | |||
1983 | ||||
1984 | return -1; | |||
1985 | } | |||
1986 | ||||
1987 | void | |||
1988 | bwfm_pci_flowring_create(struct bwfm_pci_softc *sc, struct mbuf *m) | |||
1989 | { | |||
1990 | struct ieee80211com *ic = &sc->sc_sc.sc_ic; | |||
1991 | struct bwfm_cmd_flowring_create cmd; | |||
1992 | #ifndef IEEE80211_STA_ONLY | |||
1993 | uint8_t *da = mtod(m, uint8_t *)((uint8_t *)((m)->m_hdr.mh_data)); | |||
1994 | #endif | |||
1995 | struct bwfm_pci_msgring *ring; | |||
1996 | int flowid, prio, fifo; | |||
1997 | int i, found; | |||
1998 | ||||
1999 | prio = ieee80211_classify(ic, m); | |||
2000 | fifo = bwfm_pci_prio2fifo[prio]; | |||
2001 | ||||
2002 | switch (ic->ic_opmode) | |||
2003 | { | |||
2004 | case IEEE80211_M_STA: | |||
2005 | flowid = fifo; | |||
2006 | break; | |||
2007 | #ifndef IEEE80211_STA_ONLY | |||
2008 | case IEEE80211_M_HOSTAP: | |||
2009 | if (ETHER_IS_MULTICAST(da)(*(da) & 0x01)) | |||
2010 | da = etherbroadcastaddr; | |||
2011 | flowid = da[5] * 2 + fifo; | |||
2012 | break; | |||
2013 | #endif | |||
2014 | default: | |||
2015 | printf("%s: state not supported\n", DEVNAME(sc)((sc)->sc_sc.sc_dev.dv_xname)); | |||
2016 | return; | |||
2017 | } | |||
2018 | ||||
2019 | found = 0; | |||
2020 | flowid = flowid % sc->sc_max_flowrings; | |||
2021 | for (i = 0; i < sc->sc_max_flowrings; i++) { | |||
2022 | ring = &sc->sc_flowrings[flowid]; | |||
2023 | if (ring->status == RING_CLOSED) { | |||
2024 | ring->status = RING_OPENING; | |||
2025 | found = 1; | |||
2026 | break; | |||
2027 | } | |||
2028 | flowid = (flowid + 1) % sc->sc_max_flowrings; | |||
2029 | } | |||
2030 | ||||
2031 | /* | |||
2032 | * We cannot recover from that so far. Only a stop/init | |||
2033 | * cycle can revive this if it ever happens at all. | |||
2034 | */ | |||
2035 | if (!found) { | |||
2036 | printf("%s: no flowring available\n", DEVNAME(sc)((sc)->sc_sc.sc_dev.dv_xname)); | |||
2037 | return; | |||
2038 | } | |||
2039 | ||||
2040 | cmd.m = m; | |||
2041 | cmd.prio = prio; | |||
2042 | cmd.flowid = flowid; | |||
2043 | bwfm_do_async(&sc->sc_sc, bwfm_pci_flowring_create_cb, &cmd, sizeof(cmd)); | |||
2044 | } | |||
2045 | ||||
2046 | void | |||
2047 | bwfm_pci_flowring_create_cb(struct bwfm_softc *bwfm, void *arg) | |||
2048 | { | |||
2049 | struct bwfm_pci_softc *sc = (void *)bwfm; | |||
2050 | #ifndef IEEE80211_STA_ONLY | |||
2051 | struct ieee80211com *ic = &sc->sc_sc.sc_ic; | |||
2052 | #endif | |||
2053 | struct bwfm_cmd_flowring_create *cmd = arg; | |||
2054 | struct msgbuf_tx_flowring_create_req *req; | |||
2055 | struct bwfm_pci_msgring *ring; | |||
2056 | uint8_t *da, *sa; | |||
2057 | int s; | |||
2058 | ||||
2059 | da = mtod(cmd->m, char *)((char *)((cmd->m)->m_hdr.mh_data)) + 0 * ETHER_ADDR_LEN6; | |||
2060 | sa = mtod(cmd->m, char *)((char *)((cmd->m)->m_hdr.mh_data)) + 1 * ETHER_ADDR_LEN6; | |||
2061 | ||||
2062 | ring = &sc->sc_flowrings[cmd->flowid]; | |||
2063 | if (ring->status != RING_OPENING) { | |||
2064 | printf("%s: flowring not opening\n", DEVNAME(sc)((sc)->sc_sc.sc_dev.dv_xname)); | |||
2065 | return; | |||
2066 | } | |||
2067 | ||||
2068 | if (bwfm_pci_setup_flowring(sc, ring, 512, 48)) { | |||
2069 | printf("%s: cannot setup flowring\n", DEVNAME(sc)((sc)->sc_sc.sc_dev.dv_xname)); | |||
2070 | return; | |||
2071 | } | |||
2072 | ||||
2073 | s = splnet()splraise(0x4); | |||
2074 | req = bwfm_pci_ring_write_reserve(sc, &sc->sc_ctrl_submit); | |||
2075 | if (req == NULL((void *)0)) { | |||
2076 | printf("%s: cannot reserve for flowring\n", DEVNAME(sc)((sc)->sc_sc.sc_dev.dv_xname)); | |||
2077 | splx(s)spllower(s); | |||
2078 | return; | |||
2079 | } | |||
2080 | ||||
2081 | ring->status = RING_OPENING; | |||
2082 | ring->fifo = bwfm_pci_prio2fifo[cmd->prio]; | |||
2083 | ring->m = cmd->m; | |||
2084 | memcpy(ring->mac, da, ETHER_ADDR_LEN)__builtin_memcpy((ring->mac), (da), (6)); | |||
2085 | #ifndef IEEE80211_STA_ONLY | |||
2086 | if (ic->ic_opmode == IEEE80211_M_HOSTAP && ETHER_IS_MULTICAST(da)(*(da) & 0x01)) | |||
2087 | memcpy(ring->mac, etherbroadcastaddr, ETHER_ADDR_LEN)__builtin_memcpy((ring->mac), (etherbroadcastaddr), (6)); | |||
2088 | #endif | |||
2089 | ||||
2090 | req->msg.msgtype = MSGBUF_TYPE_FLOW_RING_CREATE0x3; | |||
2091 | req->msg.ifidx = 0; | |||
2092 | req->msg.request_id = 0; | |||
2093 | req->tid = bwfm_pci_prio2fifo[cmd->prio]; | |||
2094 | req->flow_ring_id = letoh16(cmd->flowid + 2)((__uint16_t)(cmd->flowid + 2)); | |||
2095 | memcpy(req->da, da, ETHER_ADDR_LEN)__builtin_memcpy((req->da), (da), (6)); | |||
2096 | memcpy(req->sa, sa, ETHER_ADDR_LEN)__builtin_memcpy((req->sa), (sa), (6)); | |||
2097 | req->flow_ring_addr.high_addr = | |||
2098 | letoh32(BWFM_PCI_DMA_DVA(ring->ring) >> 32)((__uint32_t)(((uint64_t)(ring->ring)->bdm_map->dm_segs [0].ds_addr) >> 32)); | |||
2099 | req->flow_ring_addr.low_addr = | |||
2100 | letoh32(BWFM_PCI_DMA_DVA(ring->ring) & 0xffffffff)((__uint32_t)(((uint64_t)(ring->ring)->bdm_map->dm_segs [0].ds_addr) & 0xffffffff)); | |||
2101 | req->max_items = letoh16(512)((__uint16_t)(512)); | |||
2102 | req->len_item = letoh16(48)((__uint16_t)(48)); | |||
2103 | ||||
2104 | bwfm_pci_ring_write_commit(sc, &sc->sc_ctrl_submit); | |||
2105 | splx(s)spllower(s); | |||
2106 | } | |||
2107 | ||||
2108 | void | |||
2109 | bwfm_pci_flowring_delete(struct bwfm_pci_softc *sc, int flowid) | |||
2110 | { | |||
2111 | struct msgbuf_tx_flowring_delete_req *req; | |||
2112 | struct bwfm_pci_msgring *ring; | |||
2113 | int s; | |||
2114 | ||||
2115 | ring = &sc->sc_flowrings[flowid]; | |||
2116 | if (ring->status != RING_OPEN) { | |||
2117 | printf("%s: flowring not open\n", DEVNAME(sc)((sc)->sc_sc.sc_dev.dv_xname)); | |||
2118 | return; | |||
2119 | } | |||
2120 | ||||
2121 | s = splnet()splraise(0x4); | |||
2122 | req = bwfm_pci_ring_write_reserve(sc, &sc->sc_ctrl_submit); | |||
2123 | if (req == NULL((void *)0)) { | |||
2124 | printf("%s: cannot reserve for flowring\n", DEVNAME(sc)((sc)->sc_sc.sc_dev.dv_xname)); | |||
2125 | splx(s)spllower(s); | |||
2126 | return; | |||
2127 | } | |||
2128 | ||||
2129 | ring->status = RING_CLOSING; | |||
2130 | ||||
2131 | req->msg.msgtype = MSGBUF_TYPE_FLOW_RING_DELETE0x5; | |||
2132 | req->msg.ifidx = 0; | |||
2133 | req->msg.request_id = 0; | |||
2134 | req->flow_ring_id = letoh16(flowid + 2)((__uint16_t)(flowid + 2)); | |||
2135 | req->reason = 0; | |||
2136 | ||||
2137 | bwfm_pci_ring_write_commit(sc, &sc->sc_ctrl_submit); | |||
2138 | splx(s)spllower(s); | |||
2139 | ||||
2140 | tsleep_nsec(ring, PCATCH0x100, DEVNAME(sc)((sc)->sc_sc.sc_dev.dv_xname), SEC_TO_NSEC(2)); | |||
2141 | if (ring->status != RING_CLOSED) | |||
2142 | printf("%s: flowring not closing\n", DEVNAME(sc)((sc)->sc_sc.sc_dev.dv_xname)); | |||
2143 | } | |||
2144 | ||||
2145 | void | |||
2146 | bwfm_pci_flowring_delete_cb(struct bwfm_softc *bwfm, void *arg) | |||
2147 | { | |||
2148 | struct bwfm_pci_softc *sc = (void *)bwfm; | |||
2149 | struct bwfm_cmd_flowring_create *cmd = arg; | |||
2150 | struct bwfm_pci_msgring *ring; | |||
2151 | ||||
2152 | ring = &sc->sc_flowrings[cmd->flowid]; | |||
2153 | bwfm_pci_dmamem_free(sc, ring->ring); | |||
2154 | ring->status = RING_CLOSED; | |||
2155 | wakeup(ring); | |||
2156 | } | |||
2157 | ||||
2158 | void | |||
2159 | bwfm_pci_stop(struct bwfm_softc *bwfm) | |||
2160 | { | |||
2161 | struct bwfm_pci_softc *sc = (void *)bwfm; | |||
2162 | struct bwfm_pci_msgring *ring; | |||
2163 | int i; | |||
2164 | ||||
2165 | for (i = 0; i < sc->sc_max_flowrings; i++) { | |||
2166 | ring = &sc->sc_flowrings[i]; | |||
2167 | if (ring->status == RING_OPEN) | |||
2168 | bwfm_pci_flowring_delete(sc, i); | |||
2169 | } | |||
2170 | } | |||
2171 | ||||
2172 | int | |||
2173 | bwfm_pci_txcheck(struct bwfm_softc *bwfm) | |||
2174 | { | |||
2175 | struct bwfm_pci_softc *sc = (void *)bwfm; | |||
2176 | struct bwfm_pci_msgring *ring; | |||
2177 | int i; | |||
2178 | ||||
2179 | /* If we are transitioning, we cannot send. */ | |||
2180 | for (i = 0; i < sc->sc_max_flowrings; i++) { | |||
2181 | ring = &sc->sc_flowrings[i]; | |||
2182 | if (ring->status == RING_OPENING) | |||
2183 | return ENOBUFS55; | |||
2184 | } | |||
2185 | ||||
2186 | if (bwfm_pci_pktid_avail(sc, &sc->sc_tx_pkts)) { | |||
2187 | sc->sc_tx_pkts_full = 1; | |||
2188 | return ENOBUFS55; | |||
2189 | } | |||
2190 | ||||
2191 | return 0; | |||
2192 | } | |||
2193 | ||||
2194 | int | |||
2195 | bwfm_pci_txdata(struct bwfm_softc *bwfm, struct mbuf *m) | |||
2196 | { | |||
2197 | struct bwfm_pci_softc *sc = (void *)bwfm; | |||
2198 | struct bwfm_pci_msgring *ring; | |||
2199 | struct msgbuf_tx_msghdr *tx; | |||
2200 | uint32_t pktid; | |||
2201 | paddr_t paddr; | |||
2202 | int flowid, ret; | |||
2203 | ||||
2204 | flowid = bwfm_pci_flowring_lookup(sc, m); | |||
2205 | if (flowid < 0) { | |||
2206 | /* | |||
2207 | * We cannot send the packet right now as there is | |||
2208 | * no flowring yet. The flowring will be created | |||
2209 | * asynchronously. While the ring is transitioning | |||
2210 | * the TX check will tell the upper layers that we | |||
2211 | * cannot send packets right now. When the flowring | |||
2212 | * is created the queue will be restarted and this | |||
2213 | * mbuf will be transmitted. | |||
2214 | */ | |||
2215 | bwfm_pci_flowring_create(sc, m); | |||
2216 | return 0; | |||
2217 | } | |||
2218 | ||||
2219 | ring = &sc->sc_flowrings[flowid]; | |||
2220 | if (ring->status == RING_OPENING || | |||
2221 | ring->status == RING_CLOSING) { | |||
2222 | printf("%s: tried to use a flow that was " | |||
2223 | "transitioning in status %d\n", | |||
2224 | DEVNAME(sc)((sc)->sc_sc.sc_dev.dv_xname), ring->status); | |||
2225 | return ENOBUFS55; | |||
2226 | } | |||
2227 | ||||
2228 | tx = bwfm_pci_ring_write_reserve(sc, ring); | |||
2229 | if (tx == NULL((void *)0)) | |||
2230 | return ENOBUFS55; | |||
2231 | ||||
2232 | memset(tx, 0, sizeof(*tx))__builtin_memset((tx), (0), (sizeof(*tx))); | |||
2233 | tx->msg.msgtype = MSGBUF_TYPE_TX_POST0xF; | |||
2234 | tx->msg.ifidx = 0; | |||
2235 | tx->flags = BWFM_MSGBUF_PKT_FLAGS_FRAME_802_3(1 << 0); | |||
2236 | tx->flags |= ieee80211_classify(&sc->sc_sc.sc_ic, m) << | |||
2237 | BWFM_MSGBUF_PKT_FLAGS_PRIO_SHIFT5; | |||
2238 | tx->seg_cnt = 1; | |||
2239 | memcpy(tx->txhdr, mtod(m, char *), ETHER_HDR_LEN)__builtin_memcpy((tx->txhdr), (((char *)((m)->m_hdr.mh_data ))), (((6 * 2) + 2))); | |||
2240 | ||||
2241 | ret = bwfm_pci_pktid_new(sc, &sc->sc_tx_pkts, m, &pktid, &paddr); | |||
2242 | if (ret) { | |||
2243 | if (ret == ENOBUFS55) { | |||
2244 | printf("%s: no pktid available for TX\n", | |||
2245 | DEVNAME(sc)((sc)->sc_sc.sc_dev.dv_xname)); | |||
2246 | sc->sc_tx_pkts_full = 1; | |||
2247 | } | |||
2248 | bwfm_pci_ring_write_cancel(sc, ring, 1); | |||
2249 | return ret; | |||
2250 | } | |||
2251 | paddr += ETHER_HDR_LEN((6 * 2) + 2); | |||
2252 | ||||
2253 | tx->msg.request_id = htole32(pktid + 1)((__uint32_t)(pktid + 1)); | |||
2254 | tx->data_len = htole16(m->m_len - ETHER_HDR_LEN)((__uint16_t)(m->m_hdr.mh_len - ((6 * 2) + 2))); | |||
2255 | tx->data_buf_addr.high_addr = htole32((uint64_t)paddr >> 32)((__uint32_t)((uint64_t)paddr >> 32)); | |||
2256 | tx->data_buf_addr.low_addr = htole32(paddr & 0xffffffff)((__uint32_t)(paddr & 0xffffffff)); | |||
2257 | ||||
2258 | bwfm_pci_ring_write_commit(sc, ring); | |||
2259 | return 0; | |||
2260 | } | |||
2261 | ||||
2262 | int | |||
2263 | bwfm_pci_send_mb_data(struct bwfm_pci_softc *sc, uint32_t htod_mb_data) | |||
2264 | { | |||
2265 | struct bwfm_softc *bwfm = (void *)sc; | |||
2266 | struct bwfm_core *core; | |||
2267 | uint32_t reg; | |||
2268 | int i; | |||
2269 | ||||
2270 | if (sc->sc_mb_via_ctl) | |||
2271 | return bwfm_pci_msgbuf_h2d_mb_write(sc, htod_mb_data); | |||
2272 | ||||
2273 | for (i = 0; i < 100; i++) { | |||
2274 | reg = bus_space_read_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,((sc->sc_tcm_iot)->read_4((sc->sc_tcm_ioh), (sc-> sc_htod_mb_data_addr))) | |||
2275 | sc->sc_htod_mb_data_addr)((sc->sc_tcm_iot)->read_4((sc->sc_tcm_ioh), (sc-> sc_htod_mb_data_addr))); | |||
2276 | if (reg == 0) | |||
2277 | break; | |||
2278 | delay(10 * 1000)(*delay_func)(10 * 1000); | |||
2279 | } | |||
2280 | if (i == 100) { | |||
2281 | DPRINTF(("%s: MB transaction already pending\n", DEVNAME(sc)))do { ; } while (0); | |||
2282 | return EIO5; | |||
2283 | } | |||
2284 | ||||
2285 | bus_space_write_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,((sc->sc_tcm_iot)->write_4((sc->sc_tcm_ioh), (sc-> sc_htod_mb_data_addr), (htod_mb_data))) | |||
2286 | sc->sc_htod_mb_data_addr, htod_mb_data)((sc->sc_tcm_iot)->write_4((sc->sc_tcm_ioh), (sc-> sc_htod_mb_data_addr), (htod_mb_data))); | |||
2287 | pci_conf_write(sc->sc_pc, sc->sc_tag, BWFM_PCI_REG_SBMBX0x98, 1); | |||
2288 | ||||
2289 | core = bwfm_chip_get_core(bwfm, BWFM_AGENT_CORE_PCIE20x83C); | |||
2290 | if (core->co_rev <= 13) | |||
2291 | pci_conf_write(sc->sc_pc, sc->sc_tag, BWFM_PCI_REG_SBMBX0x98, 1); | |||
2292 | ||||
2293 | return 0; | |||
2294 | } | |||
2295 | ||||
2296 | void | |||
2297 | bwfm_pci_handle_mb_data(struct bwfm_pci_softc *sc) | |||
2298 | { | |||
2299 | uint32_t reg; | |||
2300 | ||||
2301 | reg = bus_space_read_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,((sc->sc_tcm_iot)->read_4((sc->sc_tcm_ioh), (sc-> sc_dtoh_mb_data_addr))) | |||
2302 | sc->sc_dtoh_mb_data_addr)((sc->sc_tcm_iot)->read_4((sc->sc_tcm_ioh), (sc-> sc_dtoh_mb_data_addr))); | |||
2303 | if (reg == 0) | |||
2304 | return; | |||
2305 | ||||
2306 | bus_space_write_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,((sc->sc_tcm_iot)->write_4((sc->sc_tcm_ioh), (sc-> sc_dtoh_mb_data_addr), (0))) | |||
2307 | sc->sc_dtoh_mb_data_addr, 0)((sc->sc_tcm_iot)->write_4((sc->sc_tcm_ioh), (sc-> sc_dtoh_mb_data_addr), (0))); | |||
2308 | ||||
2309 | if (reg & BWFM_PCI_D2H_DEV_D3_ACK0x00000001) { | |||
2310 | sc->sc_mbdata_done = 1; | |||
2311 | wakeup(&sc->sc_mbdata_done); | |||
2312 | } | |||
2313 | ||||
2314 | /* TODO: support more events */ | |||
2315 | if (reg & ~BWFM_PCI_D2H_DEV_D3_ACK0x00000001) | |||
2316 | printf("%s: handle MB data 0x%08x\n", DEVNAME(sc)((sc)->sc_sc.sc_dev.dv_xname), reg); | |||
2317 | } | |||
2318 | ||||
2319 | #ifdef BWFM_DEBUG | |||
2320 | void | |||
2321 | bwfm_pci_debug_console(struct bwfm_pci_softc *sc) | |||
2322 | { | |||
2323 | uint32_t newidx = bus_space_read_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,((sc->sc_tcm_iot)->read_4((sc->sc_tcm_ioh), (sc-> sc_console_base_addr + 0x10))) | |||
2324 | sc->sc_console_base_addr + BWFM_CONSOLE_WRITEIDX)((sc->sc_tcm_iot)->read_4((sc->sc_tcm_ioh), (sc-> sc_console_base_addr + 0x10))); | |||
2325 | ||||
2326 | if (newidx != sc->sc_console_readidx) | |||
2327 | DPRINTFN(3, ("BWFM CONSOLE: "))do { ; } while (0); | |||
2328 | while (newidx != sc->sc_console_readidx) { | |||
2329 | uint8_t ch = bus_space_read_1(sc->sc_tcm_iot, sc->sc_tcm_ioh,((sc->sc_tcm_iot)->read_1((sc->sc_tcm_ioh), (sc-> sc_console_buf_addr + sc->sc_console_readidx))) | |||
2330 | sc->sc_console_buf_addr + sc->sc_console_readidx)((sc->sc_tcm_iot)->read_1((sc->sc_tcm_ioh), (sc-> sc_console_buf_addr + sc->sc_console_readidx))); | |||
2331 | sc->sc_console_readidx++; | |||
2332 | if (sc->sc_console_readidx == sc->sc_console_buf_size) | |||
2333 | sc->sc_console_readidx = 0; | |||
2334 | if (ch == '\r') | |||
2335 | continue; | |||
2336 | DPRINTFN(3, ("%c", ch))do { ; } while (0); | |||
2337 | } | |||
2338 | } | |||
2339 | #endif | |||
2340 | ||||
2341 | int | |||
2342 | bwfm_pci_intr(void *v) | |||
2343 | { | |||
2344 | struct bwfm_pci_softc *sc = (void *)v; | |||
2345 | struct ifnet *ifp = &sc->sc_sc.sc_ic.ic_ific_ac.ac_if; | |||
2346 | struct mbuf_list ml = MBUF_LIST_INITIALIZER(){ ((void *)0), ((void *)0), 0 }; | |||
2347 | uint32_t status, mask; | |||
2348 | ||||
2349 | if (!sc->sc_initialized) | |||
2350 | return 0; | |||
2351 | ||||
2352 | status = bwfm_pci_intr_status(sc); | |||
2353 | /* FIXME: interrupt status seems to be zero? */ | |||
2354 | if (status == 0 && sc->sc_pcireg64) | |||
2355 | status |= BWFM_PCI_64_PCIE2REG_MAILBOXMASK_INT_D2H_DB(1 | 2 | 4 | 8 | 0x10 | 0x20 | 0x40 | 0x80 | 0x100 | 0x200 | 0x400 | 0x800 | 0x1000 | 0x2000 | 0x4000 | 0x8000); | |||
2356 | if (status == 0) | |||
2357 | return 0; | |||
2358 | ||||
2359 | bwfm_pci_intr_disable(sc); | |||
2360 | bwfm_pci_intr_ack(sc, status); | |||
2361 | ||||
2362 | if (!sc->sc_pcireg64 && | |||
2363 | (status & (BWFM_PCI_PCIE2REG_MAILBOXMASK_INT_FN0_00x0100 | | |||
2364 | BWFM_PCI_PCIE2REG_MAILBOXMASK_INT_FN0_10x0200))) | |||
2365 | bwfm_pci_handle_mb_data(sc); | |||
2366 | ||||
2367 | mask = BWFM_PCI_PCIE2REG_MAILBOXMASK_INT_D2H_DB(0x10000 | 0x20000 | 0x40000 | 0x80000 | 0x100000 | 0x200000 | 0x400000 | 0x800000); | |||
2368 | if (sc->sc_pcireg64) | |||
2369 | mask = BWFM_PCI_64_PCIE2REG_MAILBOXMASK_INT_D2H_DB(1 | 2 | 4 | 8 | 0x10 | 0x20 | 0x40 | 0x80 | 0x100 | 0x200 | 0x400 | 0x800 | 0x1000 | 0x2000 | 0x4000 | 0x8000); | |||
2370 | ||||
2371 | if (status & mask) { | |||
2372 | bwfm_pci_ring_rx(sc, &sc->sc_rx_complete, &ml); | |||
2373 | bwfm_pci_ring_rx(sc, &sc->sc_tx_complete, &ml); | |||
2374 | bwfm_pci_ring_rx(sc, &sc->sc_ctrl_complete, &ml); | |||
2375 | ||||
2376 | if (ifiq_input(&ifp->if_rcv, &ml)) | |||
2377 | if_rxr_livelocked(&sc->sc_rxbuf_ring); | |||
2378 | } | |||
2379 | ||||
2380 | #ifdef BWFM_DEBUG | |||
2381 | bwfm_pci_debug_console(sc); | |||
2382 | #endif | |||
2383 | ||||
2384 | bwfm_pci_intr_enable(sc); | |||
2385 | return 1; | |||
2386 | } | |||
2387 | ||||
2388 | void | |||
2389 | bwfm_pci_intr_enable(struct bwfm_pci_softc *sc) | |||
2390 | { | |||
2391 | if (sc->sc_pcireg64) | |||
2392 | bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,((sc->sc_reg_iot)->write_4((sc->sc_reg_ioh), (0xC34) , ((1 | 2 | 4 | 8 | 0x10 | 0x20 | 0x40 | 0x80 | 0x100 | 0x200 | 0x400 | 0x800 | 0x1000 | 0x2000 | 0x4000 | 0x8000)))) | |||
2393 | BWFM_PCI_64_PCIE2REG_MAILBOXMASK,((sc->sc_reg_iot)->write_4((sc->sc_reg_ioh), (0xC34) , ((1 | 2 | 4 | 8 | 0x10 | 0x20 | 0x40 | 0x80 | 0x100 | 0x200 | 0x400 | 0x800 | 0x1000 | 0x2000 | 0x4000 | 0x8000)))) | |||
2394 | BWFM_PCI_64_PCIE2REG_MAILBOXMASK_INT_D2H_DB)((sc->sc_reg_iot)->write_4((sc->sc_reg_ioh), (0xC34) , ((1 | 2 | 4 | 8 | 0x10 | 0x20 | 0x40 | 0x80 | 0x100 | 0x200 | 0x400 | 0x800 | 0x1000 | 0x2000 | 0x4000 | 0x8000)))); | |||
2395 | else | |||
2396 | bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,((sc->sc_reg_iot)->write_4((sc->sc_reg_ioh), (0x4C), (0x0100 | 0x0200 | (0x10000 | 0x20000 | 0x40000 | 0x80000 | 0x100000 | 0x200000 | 0x400000 | 0x800000)))) | |||
2397 | BWFM_PCI_PCIE2REG_MAILBOXMASK,((sc->sc_reg_iot)->write_4((sc->sc_reg_ioh), (0x4C), (0x0100 | 0x0200 | (0x10000 | 0x20000 | 0x40000 | 0x80000 | 0x100000 | 0x200000 | 0x400000 | 0x800000)))) | |||
2398 | BWFM_PCI_PCIE2REG_MAILBOXMASK_INT_FN0_0 |((sc->sc_reg_iot)->write_4((sc->sc_reg_ioh), (0x4C), (0x0100 | 0x0200 | (0x10000 | 0x20000 | 0x40000 | 0x80000 | 0x100000 | 0x200000 | 0x400000 | 0x800000)))) | |||
2399 | BWFM_PCI_PCIE2REG_MAILBOXMASK_INT_FN0_1 |((sc->sc_reg_iot)->write_4((sc->sc_reg_ioh), (0x4C), (0x0100 | 0x0200 | (0x10000 | 0x20000 | 0x40000 | 0x80000 | 0x100000 | 0x200000 | 0x400000 | 0x800000)))) | |||
2400 | BWFM_PCI_PCIE2REG_MAILBOXMASK_INT_D2H_DB)((sc->sc_reg_iot)->write_4((sc->sc_reg_ioh), (0x4C), (0x0100 | 0x0200 | (0x10000 | 0x20000 | 0x40000 | 0x80000 | 0x100000 | 0x200000 | 0x400000 | 0x800000)))); | |||
2401 | } | |||
2402 | ||||
2403 | void | |||
2404 | bwfm_pci_intr_disable(struct bwfm_pci_softc *sc) | |||
2405 | { | |||
2406 | if (sc->sc_pcireg64) | |||
2407 | bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,((sc->sc_reg_iot)->write_4((sc->sc_reg_ioh), (0xC34) , (0))) | |||
2408 | BWFM_PCI_64_PCIE2REG_MAILBOXMASK, 0)((sc->sc_reg_iot)->write_4((sc->sc_reg_ioh), (0xC34) , (0))); | |||
2409 | else | |||
2410 | bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,((sc->sc_reg_iot)->write_4((sc->sc_reg_ioh), (0x4C), (0))) | |||
2411 | BWFM_PCI_PCIE2REG_MAILBOXMASK, 0)((sc->sc_reg_iot)->write_4((sc->sc_reg_ioh), (0x4C), (0))); | |||
2412 | } | |||
2413 | ||||
2414 | uint32_t | |||
2415 | bwfm_pci_intr_status(struct bwfm_pci_softc *sc) | |||
2416 | { | |||
2417 | if (sc->sc_pcireg64) | |||
2418 | return bus_space_read_4(sc->sc_reg_iot, sc->sc_reg_ioh,((sc->sc_reg_iot)->read_4((sc->sc_reg_ioh), (0xC30)) ) | |||
2419 | BWFM_PCI_64_PCIE2REG_MAILBOXINT)((sc->sc_reg_iot)->read_4((sc->sc_reg_ioh), (0xC30)) ); | |||
2420 | else | |||
2421 | return bus_space_read_4(sc->sc_reg_iot, sc->sc_reg_ioh,((sc->sc_reg_iot)->read_4((sc->sc_reg_ioh), (0x48))) | |||
2422 | BWFM_PCI_PCIE2REG_MAILBOXINT)((sc->sc_reg_iot)->read_4((sc->sc_reg_ioh), (0x48))); | |||
2423 | } | |||
2424 | ||||
2425 | void | |||
2426 | bwfm_pci_intr_ack(struct bwfm_pci_softc *sc, uint32_t status) | |||
2427 | { | |||
2428 | if (sc->sc_pcireg64) | |||
2429 | bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,((sc->sc_reg_iot)->write_4((sc->sc_reg_ioh), (0xC30) , (status))) | |||
2430 | BWFM_PCI_64_PCIE2REG_MAILBOXINT, status)((sc->sc_reg_iot)->write_4((sc->sc_reg_ioh), (0xC30) , (status))); | |||
2431 | else | |||
2432 | bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,((sc->sc_reg_iot)->write_4((sc->sc_reg_ioh), (0x48), (status))) | |||
2433 | BWFM_PCI_PCIE2REG_MAILBOXINT, status)((sc->sc_reg_iot)->write_4((sc->sc_reg_ioh), (0x48), (status))); | |||
2434 | } | |||
2435 | ||||
2436 | uint32_t | |||
2437 | bwfm_pci_intmask(struct bwfm_pci_softc *sc) | |||
2438 | { | |||
2439 | if (sc->sc_pcireg64) | |||
2440 | return bus_space_read_4(sc->sc_reg_iot, sc->sc_reg_ioh,((sc->sc_reg_iot)->read_4((sc->sc_reg_ioh), (0xC14)) ) | |||
2441 | BWFM_PCI_64_PCIE2REG_INTMASK)((sc->sc_reg_iot)->read_4((sc->sc_reg_ioh), (0xC14)) ); | |||
2442 | else | |||
2443 | return bus_space_read_4(sc->sc_reg_iot, sc->sc_reg_ioh,((sc->sc_reg_iot)->read_4((sc->sc_reg_ioh), (0x24))) | |||
2444 | BWFM_PCI_PCIE2REG_INTMASK)((sc->sc_reg_iot)->read_4((sc->sc_reg_ioh), (0x24))); | |||
2445 | } | |||
2446 | ||||
2447 | void | |||
2448 | bwfm_pci_hostready(struct bwfm_pci_softc *sc) | |||
2449 | { | |||
2450 | if ((sc->sc_shared_flags & BWFM_SHARED_INFO_HOSTRDY_DB10x10000000) == 0) | |||
2451 | return; | |||
2452 | ||||
2453 | if (sc->sc_shared_flags & BWFM_SHARED_INFO_SHARED_DAR0x80000000) | |||
2454 | bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,((sc->sc_reg_iot)->write_4((sc->sc_reg_ioh), (0xA24) , (1))) | |||
2455 | BWFM_PCI_64_PCIE2REG_H2D_MAILBOX_1, 1)((sc->sc_reg_iot)->write_4((sc->sc_reg_ioh), (0xA24) , (1))); | |||
2456 | else | |||
2457 | bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,((sc->sc_reg_iot)->write_4((sc->sc_reg_ioh), (0x144) , (1))) | |||
2458 | BWFM_PCI_PCIE2REG_H2D_MAILBOX_1, 1)((sc->sc_reg_iot)->write_4((sc->sc_reg_ioh), (0x144) , (1))); | |||
2459 | } | |||
2460 | ||||
2461 | /* Msgbuf protocol implementation */ | |||
2462 | int | |||
2463 | bwfm_pci_msgbuf_query_dcmd(struct bwfm_softc *bwfm, int ifidx, | |||
2464 | int cmd, char *buf, size_t *len) | |||
2465 | { | |||
2466 | struct bwfm_pci_softc *sc = (void *)bwfm; | |||
2467 | struct msgbuf_ioctl_req_hdr *req; | |||
2468 | struct bwfm_pci_ioctl *ctl; | |||
2469 | struct mbuf *m; | |||
2470 | uint32_t pktid; | |||
2471 | paddr_t paddr; | |||
2472 | size_t buflen; | |||
2473 | int s; | |||
2474 | ||||
2475 | buflen = min(*len, BWFM_DMA_H2D_IOCTL_BUF_LEN1518); | |||
2476 | m = MCLGETL(NULL, M_DONTWAIT, buflen)m_clget((((void *)0)), (0x0002), (buflen)); | |||
2477 | if (m == NULL((void *)0)) | |||
2478 | return 1; | |||
2479 | m->m_lenm_hdr.mh_len = m->m_pkthdrM_dat.MH.MH_pkthdr.len = buflen; | |||
2480 | ||||
2481 | if (buf) | |||
2482 | memcpy(mtod(m, char *), buf, buflen)__builtin_memcpy((((char *)((m)->m_hdr.mh_data))), (buf), ( buflen)); | |||
2483 | else | |||
2484 | memset(mtod(m, char *), 0, buflen)__builtin_memset((((char *)((m)->m_hdr.mh_data))), (0), (buflen )); | |||
2485 | ||||
2486 | s = splnet()splraise(0x4); | |||
2487 | req = bwfm_pci_ring_write_reserve(sc, &sc->sc_ctrl_submit); | |||
2488 | if (req == NULL((void *)0)) { | |||
2489 | splx(s)spllower(s); | |||
2490 | m_freem(m); | |||
2491 | return 1; | |||
2492 | } | |||
2493 | ||||
2494 | if (bwfm_pci_pktid_new(sc, &sc->sc_ioctl_pkts, m, &pktid, &paddr)) { | |||
2495 | bwfm_pci_ring_write_cancel(sc, &sc->sc_ctrl_submit, 1); | |||
2496 | splx(s)spllower(s); | |||
2497 | m_freem(m); | |||
2498 | return 1; | |||
2499 | } | |||
2500 | ||||
2501 | ctl = malloc(sizeof(*ctl), M_TEMP127, M_WAITOK0x0001|M_ZERO0x0008); | |||
2502 | ctl->transid = sc->sc_ioctl_transid++; | |||
2503 | TAILQ_INSERT_TAIL(&sc->sc_ioctlq, ctl, next)do { (ctl)->next.tqe_next = ((void *)0); (ctl)->next.tqe_prev = (&sc->sc_ioctlq)->tqh_last; *(&sc->sc_ioctlq )->tqh_last = (ctl); (&sc->sc_ioctlq)->tqh_last = &(ctl)->next.tqe_next; } while (0); | |||
2504 | ||||
2505 | req->msg.msgtype = MSGBUF_TYPE_IOCTLPTR_REQ0x9; | |||
2506 | req->msg.ifidx = 0; | |||
2507 | req->msg.flags = 0; | |||
2508 | req->msg.request_id = htole32(pktid)((__uint32_t)(pktid)); | |||
2509 | req->cmd = htole32(cmd)((__uint32_t)(cmd)); | |||
2510 | req->output_buf_len = htole16(*len)((__uint16_t)(*len)); | |||
2511 | req->trans_id = htole16(ctl->transid)((__uint16_t)(ctl->transid)); | |||
2512 | ||||
2513 | req->input_buf_len = htole16(m->m_len)((__uint16_t)(m->m_hdr.mh_len)); | |||
2514 | req->req_buf_addr.high_addr = htole32((uint64_t)paddr >> 32)((__uint32_t)((uint64_t)paddr >> 32)); | |||
2515 | req->req_buf_addr.low_addr = htole32(paddr & 0xffffffff)((__uint32_t)(paddr & 0xffffffff)); | |||
2516 | ||||
2517 | bwfm_pci_ring_write_commit(sc, &sc->sc_ctrl_submit); | |||
2518 | splx(s)spllower(s); | |||
2519 | ||||
2520 | tsleep_nsec(ctl, PWAIT32, "bwfm", SEC_TO_NSEC(5)); | |||
2521 | TAILQ_REMOVE(&sc->sc_ioctlq, ctl, next)do { if (((ctl)->next.tqe_next) != ((void *)0)) (ctl)-> next.tqe_next->next.tqe_prev = (ctl)->next.tqe_prev; else (&sc->sc_ioctlq)->tqh_last = (ctl)->next.tqe_prev ; *(ctl)->next.tqe_prev = (ctl)->next.tqe_next; ((ctl)-> next.tqe_prev) = ((void *)-1); ((ctl)->next.tqe_next) = (( void *)-1); } while (0); | |||
2522 | ||||
2523 | if (ctl->m == NULL((void *)0)) { | |||
2524 | free(ctl, M_TEMP127, sizeof(*ctl)); | |||
2525 | return 1; | |||
2526 | } | |||
2527 | ||||
2528 | *len = min(ctl->retlen, m->m_lenm_hdr.mh_len); | |||
2529 | *len = min(*len, buflen); | |||
2530 | if (buf) | |||
2531 | m_copydata(ctl->m, 0, *len, buf); | |||
2532 | m_freem(ctl->m); | |||
2533 | ||||
2534 | if (ctl->status < 0) { | |||
2535 | free(ctl, M_TEMP127, sizeof(*ctl)); | |||
2536 | return 1; | |||
2537 | } | |||
2538 | ||||
2539 | free(ctl, M_TEMP127, sizeof(*ctl)); | |||
2540 | return 0; | |||
2541 | } | |||
2542 | ||||
2543 | int | |||
2544 | bwfm_pci_msgbuf_set_dcmd(struct bwfm_softc *bwfm, int ifidx, | |||
2545 | int cmd, char *buf, size_t len) | |||
2546 | { | |||
2547 | return bwfm_pci_msgbuf_query_dcmd(bwfm, ifidx, cmd, buf, &len); | |||
2548 | } | |||
2549 | ||||
2550 | void | |||
2551 | bwfm_pci_msgbuf_rxioctl(struct bwfm_pci_softc *sc, | |||
2552 | struct msgbuf_ioctl_resp_hdr *resp) | |||
2553 | { | |||
2554 | struct bwfm_pci_ioctl *ctl, *tmp; | |||
2555 | struct mbuf *m; | |||
2556 | ||||
2557 | m = bwfm_pci_pktid_free(sc, &sc->sc_rx_pkts, | |||
2558 | letoh32(resp->msg.request_id)((__uint32_t)(resp->msg.request_id))); | |||
2559 | ||||
2560 | TAILQ_FOREACH_SAFE(ctl, &sc->sc_ioctlq, next, tmp)for ((ctl) = ((&sc->sc_ioctlq)->tqh_first); (ctl) != ((void *)0) && ((tmp) = ((ctl)->next.tqe_next), 1 ); (ctl) = (tmp)) { | |||
2561 | if (ctl->transid != letoh16(resp->trans_id)((__uint16_t)(resp->trans_id))) | |||
2562 | continue; | |||
2563 | ctl->m = m; | |||
2564 | ctl->retlen = letoh16(resp->resp_len)((__uint16_t)(resp->resp_len)); | |||
2565 | ctl->status = letoh16(resp->compl_hdr.status)((__uint16_t)(resp->compl_hdr.status)); | |||
2566 | wakeup(ctl); | |||
2567 | return; | |||
2568 | } | |||
2569 | ||||
2570 | m_freem(m); | |||
2571 | } | |||
2572 | ||||
2573 | int | |||
2574 | bwfm_pci_msgbuf_h2d_mb_write(struct bwfm_pci_softc *sc, uint32_t data) | |||
2575 | { | |||
2576 | struct msgbuf_h2d_mailbox_data *req; | |||
2577 | int s; | |||
2578 | ||||
2579 | s = splnet()splraise(0x4); | |||
2580 | req = bwfm_pci_ring_write_reserve(sc, &sc->sc_ctrl_submit); | |||
2581 | if (req == NULL((void *)0)) { | |||
2582 | splx(s)spllower(s); | |||
2583 | return ENOBUFS55; | |||
2584 | } | |||
2585 | ||||
2586 | req->msg.msgtype = MSGBUF_TYPE_H2D_MAILBOX_DATA0x23; | |||
2587 | req->msg.ifidx = -1; | |||
2588 | req->msg.flags = 0; | |||
2589 | req->msg.request_id = 0; | |||
2590 | req->data = data; | |||
2591 | ||||
2592 | bwfm_pci_ring_write_commit(sc, &sc->sc_ctrl_submit); | |||
2593 | splx(s)spllower(s); | |||
2594 | ||||
2595 | return 0; | |||
2596 | } |