1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2009-2010 Weongyo Jeong <weongyo@freebsd.org>
5 * Copyright (c) 2016 Landon Fuller <landonf@FreeBSD.org>
6 * Copyright (c) 2017 The FreeBSD Foundation
7 * All rights reserved.
8 *
9 * Portions of this software were developed by Landon Fuller
10 * under sponsorship from the FreeBSD Foundation.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer,
17 * without modification.
18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
20 * redistribution must be conditioned upon including a substantially
21 * similar Disclaimer requirement for further binary redistribution.
22 *
23 * NO WARRANTY
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
27 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
28 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
29 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
32 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
34 * THE POSSIBILITY OF SUCH DAMAGES.
35 */
36
37 #include <sys/cdefs.h>
38 /*
39 * The Broadcom Wireless LAN controller driver.
40 */
41
42 #include "opt_bwn.h"
43 #include "opt_wlan.h"
44
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/kernel.h>
48 #include <sys/gpio.h>
49 #include <sys/malloc.h>
50 #include <sys/module.h>
51 #include <sys/endian.h>
52 #include <sys/errno.h>
53 #include <sys/firmware.h>
54 #include <sys/lock.h>
55 #include <sys/mutex.h>
56 #include <machine/bus.h>
57 #include <machine/resource.h>
58 #include <sys/bus.h>
59 #include <sys/rman.h>
60 #include <sys/socket.h>
61 #include <sys/sockio.h>
62
63 #include <net/ethernet.h>
64 #include <net/if.h>
65 #include <net/if_var.h>
66 #include <net/if_arp.h>
67 #include <net/if_dl.h>
68 #include <net/if_llc.h>
69 #include <net/if_media.h>
70 #include <net/if_types.h>
71
72 #include <net80211/ieee80211_var.h>
73 #include <net80211/ieee80211_radiotap.h>
74 #include <net80211/ieee80211_regdomain.h>
75 #include <net80211/ieee80211_phy.h>
76 #include <net80211/ieee80211_ratectl.h>
77
78 #include <dev/bhnd/bhnd.h>
79 #include <dev/bhnd/bhnd_ids.h>
80
81 #include <dev/bhnd/cores/chipc/chipc.h>
82 #include <dev/bhnd/cores/pmu/bhnd_pmu.h>
83
84 #include <dev/bwn/if_bwnreg.h>
85 #include <dev/bwn/if_bwnvar.h>
86
87 #include <dev/bwn/if_bwn_debug.h>
88 #include <dev/bwn/if_bwn_misc.h>
89 #include <dev/bwn/if_bwn_util.h>
90 #include <dev/bwn/if_bwn_phy_common.h>
91 #include <dev/bwn/if_bwn_phy_g.h>
92 #include <dev/bwn/if_bwn_phy_lp.h>
93 #include <dev/bwn/if_bwn_phy_n.h>
94
95 #include "bhnd_nvram_map.h"
96
97 #include "gpio_if.h"
98
99 static SYSCTL_NODE(_hw, OID_AUTO, bwn, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
100 "Broadcom driver parameters");
101
102 /*
103 * Tunable & sysctl variables.
104 */
105
106 #ifdef BWN_DEBUG
107 static int bwn_debug = 0;
108 SYSCTL_INT(_hw_bwn, OID_AUTO, debug, CTLFLAG_RWTUN, &bwn_debug, 0,
109 "Broadcom debugging printfs");
110 #endif
111
112 static int bwn_bfp = 0; /* use "Bad Frames Preemption" */
113 SYSCTL_INT(_hw_bwn, OID_AUTO, bfp, CTLFLAG_RW, &bwn_bfp, 0,
114 "uses Bad Frames Preemption");
115 static int bwn_bluetooth = 1;
116 SYSCTL_INT(_hw_bwn, OID_AUTO, bluetooth, CTLFLAG_RW, &bwn_bluetooth, 0,
117 "turns on Bluetooth Coexistence");
118 static int bwn_hwpctl = 0;
119 SYSCTL_INT(_hw_bwn, OID_AUTO, hwpctl, CTLFLAG_RW, &bwn_hwpctl, 0,
120 "uses H/W power control");
121 static int bwn_usedma = 1;
122 SYSCTL_INT(_hw_bwn, OID_AUTO, usedma, CTLFLAG_RD, &bwn_usedma, 0,
123 "uses DMA");
124 TUNABLE_INT("hw.bwn.usedma", &bwn_usedma);
125 static int bwn_wme = 1;
126 SYSCTL_INT(_hw_bwn, OID_AUTO, wme, CTLFLAG_RW, &bwn_wme, 0,
127 "uses WME support");
128
129 static void bwn_attach_pre(struct bwn_softc *);
130 static int bwn_attach_post(struct bwn_softc *);
131 static int bwn_retain_bus_providers(struct bwn_softc *sc);
132 static void bwn_release_bus_providers(struct bwn_softc *sc);
133 static void bwn_sprom_bugfixes(device_t);
134 static int bwn_init(struct bwn_softc *);
135 static void bwn_parent(struct ieee80211com *);
136 static void bwn_start(struct bwn_softc *);
137 static int bwn_transmit(struct ieee80211com *, struct mbuf *);
138 static int bwn_attach_core(struct bwn_mac *);
139 static int bwn_phy_getinfo(struct bwn_mac *, int);
140 static int bwn_chiptest(struct bwn_mac *);
141 static int bwn_setup_channels(struct bwn_mac *, int, int);
142 static void bwn_shm_ctlword(struct bwn_mac *, uint16_t,
143 uint16_t);
144 static void bwn_addchannels(struct ieee80211_channel [], int, int *,
145 const struct bwn_channelinfo *, const uint8_t []);
146 static int bwn_raw_xmit(struct ieee80211_node *, struct mbuf *,
147 const struct ieee80211_bpf_params *);
148 static void bwn_updateslot(struct ieee80211com *);
149 static void bwn_update_promisc(struct ieee80211com *);
150 static void bwn_wme_init(struct bwn_mac *);
151 static int bwn_wme_update(struct ieee80211com *);
152 static void bwn_wme_clear(struct bwn_softc *);
153 static void bwn_wme_load(struct bwn_mac *);
154 static void bwn_wme_loadparams(struct bwn_mac *,
155 const struct wmeParams *, uint16_t);
156 static void bwn_scan_start(struct ieee80211com *);
157 static void bwn_scan_end(struct ieee80211com *);
158 static void bwn_set_channel(struct ieee80211com *);
159 static struct ieee80211vap *bwn_vap_create(struct ieee80211com *,
160 const char [IFNAMSIZ], int, enum ieee80211_opmode, int,
161 const uint8_t [IEEE80211_ADDR_LEN],
162 const uint8_t [IEEE80211_ADDR_LEN]);
163 static void bwn_vap_delete(struct ieee80211vap *);
164 static void bwn_stop(struct bwn_softc *);
165 static int bwn_core_forceclk(struct bwn_mac *, bool);
166 static int bwn_core_init(struct bwn_mac *);
167 static void bwn_core_start(struct bwn_mac *);
168 static void bwn_core_exit(struct bwn_mac *);
169 static void bwn_bt_disable(struct bwn_mac *);
170 static int bwn_chip_init(struct bwn_mac *);
171 static void bwn_set_txretry(struct bwn_mac *, int, int);
172 static void bwn_rate_init(struct bwn_mac *);
173 static void bwn_set_phytxctl(struct bwn_mac *);
174 static void bwn_spu_setdelay(struct bwn_mac *, int);
175 static void bwn_bt_enable(struct bwn_mac *);
176 static void bwn_set_macaddr(struct bwn_mac *);
177 static void bwn_crypt_init(struct bwn_mac *);
178 static void bwn_chip_exit(struct bwn_mac *);
179 static int bwn_fw_fillinfo(struct bwn_mac *);
180 static int bwn_fw_loaducode(struct bwn_mac *);
181 static int bwn_gpio_init(struct bwn_mac *);
182 static int bwn_fw_loadinitvals(struct bwn_mac *);
183 static int bwn_phy_init(struct bwn_mac *);
184 static void bwn_set_txantenna(struct bwn_mac *, int);
185 static void bwn_set_opmode(struct bwn_mac *);
186 static void bwn_rate_write(struct bwn_mac *, uint16_t, int);
187 static uint8_t bwn_plcp_getcck(const uint8_t);
188 static uint8_t bwn_plcp_getofdm(const uint8_t);
189 static void bwn_pio_init(struct bwn_mac *);
190 static uint16_t bwn_pio_idx2base(struct bwn_mac *, int);
191 static void bwn_pio_set_txqueue(struct bwn_mac *, struct bwn_pio_txqueue *,
192 int);
193 static void bwn_pio_setupqueue_rx(struct bwn_mac *,
194 struct bwn_pio_rxqueue *, int);
195 static void bwn_destroy_queue_tx(struct bwn_pio_txqueue *);
196 static uint16_t bwn_pio_read_2(struct bwn_mac *, struct bwn_pio_txqueue *,
197 uint16_t);
198 static void bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *);
199 static int bwn_pio_rx(struct bwn_pio_rxqueue *);
200 static uint8_t bwn_pio_rxeof(struct bwn_pio_rxqueue *);
201 static void bwn_pio_handle_txeof(struct bwn_mac *,
202 const struct bwn_txstatus *);
203 static uint16_t bwn_pio_rx_read_2(struct bwn_pio_rxqueue *, uint16_t);
204 static uint32_t bwn_pio_rx_read_4(struct bwn_pio_rxqueue *, uint16_t);
205 static void bwn_pio_rx_write_2(struct bwn_pio_rxqueue *, uint16_t,
206 uint16_t);
207 static void bwn_pio_rx_write_4(struct bwn_pio_rxqueue *, uint16_t,
208 uint32_t);
209 static int bwn_pio_tx_start(struct bwn_mac *, struct ieee80211_node *,
210 struct mbuf **);
211 static struct bwn_pio_txqueue *bwn_pio_select(struct bwn_mac *, uint8_t);
212 static uint32_t bwn_pio_write_multi_4(struct bwn_mac *,
213 struct bwn_pio_txqueue *, uint32_t, const void *, int);
214 static void bwn_pio_write_4(struct bwn_mac *, struct bwn_pio_txqueue *,
215 uint16_t, uint32_t);
216 static uint16_t bwn_pio_write_multi_2(struct bwn_mac *,
217 struct bwn_pio_txqueue *, uint16_t, const void *, int);
218 static uint16_t bwn_pio_write_mbuf_2(struct bwn_mac *,
219 struct bwn_pio_txqueue *, uint16_t, struct mbuf *);
220 static struct bwn_pio_txqueue *bwn_pio_parse_cookie(struct bwn_mac *,
221 uint16_t, struct bwn_pio_txpkt **);
222 static void bwn_dma_init(struct bwn_mac *);
223 static void bwn_dma_rxdirectfifo(struct bwn_mac *, int, uint8_t);
224 static uint16_t bwn_dma_base(int, int);
225 static void bwn_dma_ringfree(struct bwn_dma_ring **);
226 static void bwn_dma_32_getdesc(struct bwn_dma_ring *,
227 int, struct bwn_dmadesc_generic **,
228 struct bwn_dmadesc_meta **);
229 static void bwn_dma_32_setdesc(struct bwn_dma_ring *,
230 struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int,
231 int, int);
232 static void bwn_dma_32_start_transfer(struct bwn_dma_ring *, int);
233 static void bwn_dma_32_suspend(struct bwn_dma_ring *);
234 static void bwn_dma_32_resume(struct bwn_dma_ring *);
235 static int bwn_dma_32_get_curslot(struct bwn_dma_ring *);
236 static void bwn_dma_32_set_curslot(struct bwn_dma_ring *, int);
237 static void bwn_dma_64_getdesc(struct bwn_dma_ring *,
238 int, struct bwn_dmadesc_generic **,
239 struct bwn_dmadesc_meta **);
240 static void bwn_dma_64_setdesc(struct bwn_dma_ring *,
241 struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int,
242 int, int);
243 static void bwn_dma_64_start_transfer(struct bwn_dma_ring *, int);
244 static void bwn_dma_64_suspend(struct bwn_dma_ring *);
245 static void bwn_dma_64_resume(struct bwn_dma_ring *);
246 static int bwn_dma_64_get_curslot(struct bwn_dma_ring *);
247 static void bwn_dma_64_set_curslot(struct bwn_dma_ring *, int);
248 static int bwn_dma_allocringmemory(struct bwn_dma_ring *);
249 static void bwn_dma_setup(struct bwn_dma_ring *);
250 static void bwn_dma_free_ringmemory(struct bwn_dma_ring *);
251 static void bwn_dma_cleanup(struct bwn_dma_ring *);
252 static void bwn_dma_free_descbufs(struct bwn_dma_ring *);
253 static int bwn_dma_tx_reset(struct bwn_mac *, uint16_t, int);
254 static void bwn_dma_rx(struct bwn_dma_ring *);
255 static int bwn_dma_rx_reset(struct bwn_mac *, uint16_t, int);
256 static void bwn_dma_free_descbuf(struct bwn_dma_ring *,
257 struct bwn_dmadesc_meta *);
258 static void bwn_dma_set_redzone(struct bwn_dma_ring *, struct mbuf *);
259 static void bwn_dma_ring_addr(void *, bus_dma_segment_t *, int, int);
260 static int bwn_dma_freeslot(struct bwn_dma_ring *);
261 static int bwn_dma_nextslot(struct bwn_dma_ring *, int);
262 static void bwn_dma_rxeof(struct bwn_dma_ring *, int *);
263 static int bwn_dma_newbuf(struct bwn_dma_ring *,
264 struct bwn_dmadesc_generic *, struct bwn_dmadesc_meta *,
265 int);
266 static void bwn_dma_buf_addr(void *, bus_dma_segment_t *, int,
267 bus_size_t, int);
268 static uint8_t bwn_dma_check_redzone(struct bwn_dma_ring *, struct mbuf *);
269 static void bwn_ratectl_tx_complete(const struct ieee80211_node *,
270 const struct bwn_txstatus *);
271 static void bwn_dma_handle_txeof(struct bwn_mac *,
272 const struct bwn_txstatus *);
273 static int bwn_dma_tx_start(struct bwn_mac *, struct ieee80211_node *,
274 struct mbuf **);
275 static int bwn_dma_getslot(struct bwn_dma_ring *);
276 static struct bwn_dma_ring *bwn_dma_select(struct bwn_mac *,
277 uint8_t);
278 static int bwn_dma_attach(struct bwn_mac *);
279 static struct bwn_dma_ring *bwn_dma_ringsetup(struct bwn_mac *,
280 int, int);
281 static struct bwn_dma_ring *bwn_dma_parse_cookie(struct bwn_mac *,
282 const struct bwn_txstatus *, uint16_t, int *);
283 static void bwn_dma_free(struct bwn_mac *);
284 static int bwn_fw_gets(struct bwn_mac *, enum bwn_fwtype);
285 static int bwn_fw_get(struct bwn_mac *, enum bwn_fwtype,
286 const char *, struct bwn_fwfile *);
287 static void bwn_release_firmware(struct bwn_mac *);
288 static void bwn_do_release_fw(struct bwn_fwfile *);
289 static uint16_t bwn_fwcaps_read(struct bwn_mac *);
290 static int bwn_fwinitvals_write(struct bwn_mac *,
291 const struct bwn_fwinitvals *, size_t, size_t);
292 static uint16_t bwn_ant2phy(int);
293 static void bwn_mac_write_bssid(struct bwn_mac *);
294 static void bwn_mac_setfilter(struct bwn_mac *, uint16_t,
295 const uint8_t *);
296 static void bwn_key_dowrite(struct bwn_mac *, uint8_t, uint8_t,
297 const uint8_t *, size_t, const uint8_t *);
298 static void bwn_key_macwrite(struct bwn_mac *, uint8_t,
299 const uint8_t *);
300 static void bwn_key_write(struct bwn_mac *, uint8_t, uint8_t,
301 const uint8_t *);
302 static void bwn_phy_exit(struct bwn_mac *);
303 static void bwn_core_stop(struct bwn_mac *);
304 static int bwn_switch_band(struct bwn_softc *,
305 struct ieee80211_channel *);
306 static int bwn_phy_reset(struct bwn_mac *);
307 static int bwn_newstate(struct ieee80211vap *, enum ieee80211_state, int);
308 static void bwn_set_pretbtt(struct bwn_mac *);
309 static int bwn_intr(void *);
310 static void bwn_intrtask(void *, int);
311 static void bwn_restart(struct bwn_mac *, const char *);
312 static void bwn_intr_ucode_debug(struct bwn_mac *);
313 static void bwn_intr_tbtt_indication(struct bwn_mac *);
314 static void bwn_intr_atim_end(struct bwn_mac *);
315 static void bwn_intr_beacon(struct bwn_mac *);
316 static void bwn_intr_pmq(struct bwn_mac *);
317 static void bwn_intr_noise(struct bwn_mac *);
318 static void bwn_intr_txeof(struct bwn_mac *);
319 static void bwn_hwreset(void *, int);
320 static void bwn_handle_fwpanic(struct bwn_mac *);
321 static void bwn_load_beacon0(struct bwn_mac *);
322 static void bwn_load_beacon1(struct bwn_mac *);
323 static uint32_t bwn_jssi_read(struct bwn_mac *);
324 static void bwn_noise_gensample(struct bwn_mac *);
325 static void bwn_handle_txeof(struct bwn_mac *,
326 const struct bwn_txstatus *);
327 static void bwn_rxeof(struct bwn_mac *, struct mbuf *, const void *);
328 static void bwn_phy_txpower_check(struct bwn_mac *, uint32_t);
329 static int bwn_tx_start(struct bwn_softc *, struct ieee80211_node *,
330 struct mbuf *);
331 static int bwn_tx_isfull(struct bwn_softc *, struct mbuf *);
332 static int bwn_set_txhdr(struct bwn_mac *,
333 struct ieee80211_node *, struct mbuf *, struct bwn_txhdr *,
334 uint16_t);
335 static void bwn_plcp_genhdr(struct bwn_plcp4 *, const uint16_t,
336 const uint8_t);
337 static uint8_t bwn_antenna_sanitize(struct bwn_mac *, uint8_t);
338 static uint8_t bwn_get_fbrate(uint8_t);
339 static void bwn_txpwr(void *, int);
340 static void bwn_tasks(void *);
341 static void bwn_task_15s(struct bwn_mac *);
342 static void bwn_task_30s(struct bwn_mac *);
343 static void bwn_task_60s(struct bwn_mac *);
344 static int bwn_plcp_get_ofdmrate(struct bwn_mac *, struct bwn_plcp6 *,
345 uint8_t);
346 static int bwn_plcp_get_cckrate(struct bwn_mac *, struct bwn_plcp6 *);
347 static void bwn_rx_radiotap(struct bwn_mac *, struct mbuf *,
348 const struct bwn_rxhdr4 *, struct bwn_plcp6 *, int,
349 int, int);
350 static void bwn_tsf_read(struct bwn_mac *, uint64_t *);
351 static void bwn_set_slot_time(struct bwn_mac *, uint16_t);
352 static void bwn_watchdog(void *);
353 static void bwn_dma_stop(struct bwn_mac *);
354 static void bwn_pio_stop(struct bwn_mac *);
355 static void bwn_dma_ringstop(struct bwn_dma_ring **);
356 static int bwn_led_attach(struct bwn_mac *);
357 static void bwn_led_newstate(struct bwn_mac *, enum ieee80211_state);
358 static void bwn_led_event(struct bwn_mac *, int);
359 static void bwn_led_blink_start(struct bwn_mac *, int, int);
360 static void bwn_led_blink_next(void *);
361 static void bwn_led_blink_end(void *);
362 static void bwn_rfswitch(void *);
363 static void bwn_rf_turnon(struct bwn_mac *);
364 static void bwn_rf_turnoff(struct bwn_mac *);
365 static void bwn_sysctl_node(struct bwn_softc *);
366
367 static const struct bwn_channelinfo bwn_chantable_bg = {
368 .channels = {
369 { 2412, 1, 30 }, { 2417, 2, 30 }, { 2422, 3, 30 },
370 { 2427, 4, 30 }, { 2432, 5, 30 }, { 2437, 6, 30 },
371 { 2442, 7, 30 }, { 2447, 8, 30 }, { 2452, 9, 30 },
372 { 2457, 10, 30 }, { 2462, 11, 30 }, { 2467, 12, 30 },
373 { 2472, 13, 30 }, { 2484, 14, 30 } },
374 .nchannels = 14
375 };
376
377 static const struct bwn_channelinfo bwn_chantable_a = {
378 .channels = {
379 { 5170, 34, 30 }, { 5180, 36, 30 }, { 5190, 38, 30 },
380 { 5200, 40, 30 }, { 5210, 42, 30 }, { 5220, 44, 30 },
381 { 5230, 46, 30 }, { 5240, 48, 30 }, { 5260, 52, 30 },
382 { 5280, 56, 30 }, { 5300, 60, 30 }, { 5320, 64, 30 },
383 { 5500, 100, 30 }, { 5520, 104, 30 }, { 5540, 108, 30 },
384 { 5560, 112, 30 }, { 5580, 116, 30 }, { 5600, 120, 30 },
385 { 5620, 124, 30 }, { 5640, 128, 30 }, { 5660, 132, 30 },
386 { 5680, 136, 30 }, { 5700, 140, 30 }, { 5745, 149, 30 },
387 { 5765, 153, 30 }, { 5785, 157, 30 }, { 5805, 161, 30 },
388 { 5825, 165, 30 }, { 5920, 184, 30 }, { 5940, 188, 30 },
389 { 5960, 192, 30 }, { 5980, 196, 30 }, { 6000, 200, 30 },
390 { 6020, 204, 30 }, { 6040, 208, 30 }, { 6060, 212, 30 },
391 { 6080, 216, 30 } },
392 .nchannels = 37
393 };
394
395 #if 0
396 static const struct bwn_channelinfo bwn_chantable_n = {
397 .channels = {
398 { 5160, 32, 30 }, { 5170, 34, 30 }, { 5180, 36, 30 },
399 { 5190, 38, 30 }, { 5200, 40, 30 }, { 5210, 42, 30 },
400 { 5220, 44, 30 }, { 5230, 46, 30 }, { 5240, 48, 30 },
401 { 5250, 50, 30 }, { 5260, 52, 30 }, { 5270, 54, 30 },
402 { 5280, 56, 30 }, { 5290, 58, 30 }, { 5300, 60, 30 },
403 { 5310, 62, 30 }, { 5320, 64, 30 }, { 5330, 66, 30 },
404 { 5340, 68, 30 }, { 5350, 70, 30 }, { 5360, 72, 30 },
405 { 5370, 74, 30 }, { 5380, 76, 30 }, { 5390, 78, 30 },
406 { 5400, 80, 30 }, { 5410, 82, 30 }, { 5420, 84, 30 },
407 { 5430, 86, 30 }, { 5440, 88, 30 }, { 5450, 90, 30 },
408 { 5460, 92, 30 }, { 5470, 94, 30 }, { 5480, 96, 30 },
409 { 5490, 98, 30 }, { 5500, 100, 30 }, { 5510, 102, 30 },
410 { 5520, 104, 30 }, { 5530, 106, 30 }, { 5540, 108, 30 },
411 { 5550, 110, 30 }, { 5560, 112, 30 }, { 5570, 114, 30 },
412 { 5580, 116, 30 }, { 5590, 118, 30 }, { 5600, 120, 30 },
413 { 5610, 122, 30 }, { 5620, 124, 30 }, { 5630, 126, 30 },
414 { 5640, 128, 30 }, { 5650, 130, 30 }, { 5660, 132, 30 },
415 { 5670, 134, 30 }, { 5680, 136, 30 }, { 5690, 138, 30 },
416 { 5700, 140, 30 }, { 5710, 142, 30 }, { 5720, 144, 30 },
417 { 5725, 145, 30 }, { 5730, 146, 30 }, { 5735, 147, 30 },
418 { 5740, 148, 30 }, { 5745, 149, 30 }, { 5750, 150, 30 },
419 { 5755, 151, 30 }, { 5760, 152, 30 }, { 5765, 153, 30 },
420 { 5770, 154, 30 }, { 5775, 155, 30 }, { 5780, 156, 30 },
421 { 5785, 157, 30 }, { 5790, 158, 30 }, { 5795, 159, 30 },
422 { 5800, 160, 30 }, { 5805, 161, 30 }, { 5810, 162, 30 },
423 { 5815, 163, 30 }, { 5820, 164, 30 }, { 5825, 165, 30 },
424 { 5830, 166, 30 }, { 5840, 168, 30 }, { 5850, 170, 30 },
425 { 5860, 172, 30 }, { 5870, 174, 30 }, { 5880, 176, 30 },
426 { 5890, 178, 30 }, { 5900, 180, 30 }, { 5910, 182, 30 },
427 { 5920, 184, 30 }, { 5930, 186, 30 }, { 5940, 188, 30 },
428 { 5950, 190, 30 }, { 5960, 192, 30 }, { 5970, 194, 30 },
429 { 5980, 196, 30 }, { 5990, 198, 30 }, { 6000, 200, 30 },
430 { 6010, 202, 30 }, { 6020, 204, 30 }, { 6030, 206, 30 },
431 { 6040, 208, 30 }, { 6050, 210, 30 }, { 6060, 212, 30 },
432 { 6070, 214, 30 }, { 6080, 216, 30 }, { 6090, 218, 30 },
433 { 6100, 220, 30 }, { 6110, 222, 30 }, { 6120, 224, 30 },
434 { 6130, 226, 30 }, { 6140, 228, 30 } },
435 .nchannels = 110
436 };
437 #endif
438
439 #define VENDOR_LED_ACT(vendor) \
440 { \
441 .vid = PCI_VENDOR_##vendor, \
442 .led_act = { BWN_VENDOR_LED_ACT_##vendor } \
443 }
444
445 static const struct {
446 uint16_t vid;
447 uint8_t led_act[BWN_LED_MAX];
448 } bwn_vendor_led_act[] = {
449 VENDOR_LED_ACT(HP_COMPAQ),
450 VENDOR_LED_ACT(ASUSTEK)
451 };
452
453 static const uint8_t bwn_default_led_act[BWN_LED_MAX] =
454 { BWN_VENDOR_LED_ACT_DEFAULT };
455
456 #undef VENDOR_LED_ACT
457
458 static const char *bwn_led_vars[] = {
459 BHND_NVAR_LEDBH0,
460 BHND_NVAR_LEDBH1,
461 BHND_NVAR_LEDBH2,
462 BHND_NVAR_LEDBH3
463 };
464
465 static const struct {
466 int on_dur;
467 int off_dur;
468 } bwn_led_duration[109] = {
469 [0] = { 400, 100 },
470 [2] = { 150, 75 },
471 [4] = { 90, 45 },
472 [11] = { 66, 34 },
473 [12] = { 53, 26 },
474 [18] = { 42, 21 },
475 [22] = { 35, 17 },
476 [24] = { 32, 16 },
477 [36] = { 21, 10 },
478 [48] = { 16, 8 },
479 [72] = { 11, 5 },
480 [96] = { 9, 4 },
481 [108] = { 7, 3 }
482 };
483
484 static const uint16_t bwn_wme_shm_offsets[] = {
485 [0] = BWN_WME_BESTEFFORT,
486 [1] = BWN_WME_BACKGROUND,
487 [2] = BWN_WME_VOICE,
488 [3] = BWN_WME_VIDEO,
489 };
490
491 /* Supported D11 core revisions */
492 #define BWN_DEV(_hwrev) {{ \
493 BHND_MATCH_CORE(BHND_MFGID_BCM, BHND_COREID_D11), \
494 BHND_MATCH_CORE_REV(_hwrev), \
495 }}
496 static const struct bhnd_device bwn_devices[] = {
497 BWN_DEV(HWREV_RANGE(5, 16)),
498 BWN_DEV(HWREV_EQ(23)),
499 BHND_DEVICE_END
500 };
501
502 /* D11 quirks when bridged via a PCI host bridge core */
503 static const struct bhnd_device_quirk pci_bridge_quirks[] = {
504 BHND_CORE_QUIRK (HWREV_LTE(10), BWN_QUIRK_UCODE_SLOWCLOCK_WAR),
505 BHND_DEVICE_QUIRK_END
506 };
507
508 /* D11 quirks when bridged via a PCMCIA host bridge core */
509 static const struct bhnd_device_quirk pcmcia_bridge_quirks[] = {
510 BHND_CORE_QUIRK (HWREV_ANY, BWN_QUIRK_NODMA),
511 BHND_DEVICE_QUIRK_END
512 };
513
514 /* Host bridge cores for which D11 quirk flags should be applied */
515 static const struct bhnd_device bridge_devices[] = {
516 BHND_DEVICE(BCM, PCI, NULL, pci_bridge_quirks),
517 BHND_DEVICE(BCM, PCMCIA, NULL, pcmcia_bridge_quirks),
518 BHND_DEVICE_END
519 };
520
521 static int
bwn_probe(device_t dev)522 bwn_probe(device_t dev)
523 {
524 const struct bhnd_device *id;
525
526 id = bhnd_device_lookup(dev, bwn_devices, sizeof(bwn_devices[0]));
527 if (id == NULL)
528 return (ENXIO);
529
530 bhnd_set_default_core_desc(dev);
531 return (BUS_PROBE_DEFAULT);
532 }
533
534 static int
bwn_attach(device_t dev)535 bwn_attach(device_t dev)
536 {
537 struct bwn_mac *mac;
538 struct bwn_softc *sc;
539 device_t parent, hostb;
540 char chip_name[BHND_CHIPID_MAX_NAMELEN];
541 int error;
542
543 sc = device_get_softc(dev);
544 sc->sc_dev = dev;
545 #ifdef BWN_DEBUG
546 sc->sc_debug = bwn_debug;
547 #endif
548
549 mac = NULL;
550
551 /* Determine the driver quirks applicable to this device, including any
552 * quirks specific to the bus host bridge core (if any) */
553 sc->sc_quirks = bhnd_device_quirks(dev, bwn_devices,
554 sizeof(bwn_devices[0]));
555
556 parent = device_get_parent(dev);
557 if ((hostb = bhnd_bus_find_hostb_device(parent)) != NULL) {
558 sc->sc_quirks |= bhnd_device_quirks(hostb, bridge_devices,
559 sizeof(bridge_devices[0]));
560 }
561
562 /* DMA explicitly disabled? */
563 if (!bwn_usedma)
564 sc->sc_quirks |= BWN_QUIRK_NODMA;
565
566 /* Fetch our chip identification and board info */
567 sc->sc_cid = *bhnd_get_chipid(dev);
568 if ((error = bhnd_read_board_info(dev, &sc->sc_board_info))) {
569 device_printf(sc->sc_dev, "couldn't read board info\n");
570 return (error);
571 }
572
573 /* Allocate our D11 register block and PMU state */
574 sc->sc_mem_rid = 0;
575 sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
576 &sc->sc_mem_rid, RF_ACTIVE);
577 if (sc->sc_mem_res == NULL) {
578 device_printf(sc->sc_dev, "couldn't allocate registers\n");
579 return (error);
580 }
581
582 if ((error = bhnd_alloc_pmu(sc->sc_dev))) {
583 bus_release_resource(sc->sc_dev, SYS_RES_MEMORY,
584 sc->sc_mem_rid, sc->sc_mem_res);
585 return (error);
586 }
587
588 /* Retain references to all required bus service providers */
589 if ((error = bwn_retain_bus_providers(sc)))
590 goto fail;
591
592 /* Fetch mask of available antennas */
593 error = bhnd_nvram_getvar_uint8(sc->sc_dev, BHND_NVAR_AA2G,
594 &sc->sc_ant2g);
595 if (error) {
596 device_printf(sc->sc_dev, "error determining 2GHz antenna "
597 "availability from NVRAM: %d\n", error);
598 goto fail;
599 }
600
601 error = bhnd_nvram_getvar_uint8(sc->sc_dev, BHND_NVAR_AA5G,
602 &sc->sc_ant5g);
603 if (error) {
604 device_printf(sc->sc_dev, "error determining 5GHz antenna "
605 "availability from NVRAM: %d\n", error);
606 goto fail;
607 }
608
609 if ((sc->sc_flags & BWN_FLAG_ATTACHED) == 0) {
610 bwn_attach_pre(sc);
611 bwn_sprom_bugfixes(dev);
612 sc->sc_flags |= BWN_FLAG_ATTACHED;
613 }
614
615 mac = malloc(sizeof(*mac), M_DEVBUF, M_WAITOK | M_ZERO);
616 mac->mac_sc = sc;
617 mac->mac_status = BWN_MAC_STATUS_UNINIT;
618 if (bwn_bfp != 0)
619 mac->mac_flags |= BWN_MAC_FLAG_BADFRAME_PREEMP;
620
621 TASK_INIT(&mac->mac_hwreset, 0, bwn_hwreset, mac);
622 NET_TASK_INIT(&mac->mac_intrtask, 0, bwn_intrtask, mac);
623 TASK_INIT(&mac->mac_txpower, 0, bwn_txpwr, mac);
624
625 error = bwn_attach_core(mac);
626 if (error)
627 goto fail;
628 error = bwn_led_attach(mac);
629 if (error)
630 goto fail;
631
632 bhnd_format_chip_id(chip_name, sizeof(chip_name), sc->sc_cid.chip_id);
633 device_printf(sc->sc_dev, "WLAN (%s rev %u sromrev %u) "
634 "PHY (analog %d type %d rev %d) RADIO (manuf %#x ver %#x rev %d)\n",
635 chip_name, bhnd_get_hwrev(sc->sc_dev),
636 sc->sc_board_info.board_srom_rev, mac->mac_phy.analog,
637 mac->mac_phy.type, mac->mac_phy.rev, mac->mac_phy.rf_manuf,
638 mac->mac_phy.rf_ver, mac->mac_phy.rf_rev);
639 if (mac->mac_flags & BWN_MAC_FLAG_DMA)
640 device_printf(sc->sc_dev, "DMA (%d bits)\n", mac->mac_dmatype);
641 else
642 device_printf(sc->sc_dev, "PIO\n");
643
644 #ifdef BWN_GPL_PHY
645 device_printf(sc->sc_dev,
646 "Note: compiled with BWN_GPL_PHY; includes GPLv2 code\n");
647 #endif
648
649 mac->mac_rid_irq = 0;
650 mac->mac_res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
651 &mac->mac_rid_irq, RF_ACTIVE | RF_SHAREABLE);
652
653 if (mac->mac_res_irq == NULL) {
654 device_printf(sc->sc_dev, "couldn't allocate IRQ resource\n");
655 error = ENXIO;
656 goto fail;
657 }
658
659 error = bus_setup_intr(dev, mac->mac_res_irq,
660 INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac,
661 &mac->mac_intrhand);
662 if (error != 0) {
663 device_printf(sc->sc_dev, "couldn't setup interrupt (%d)\n",
664 error);
665 goto fail;
666 }
667
668 TAILQ_INSERT_TAIL(&sc->sc_maclist, mac, mac_list);
669
670 /*
671 * calls attach-post routine
672 */
673 if ((sc->sc_flags & BWN_FLAG_ATTACHED) != 0)
674 bwn_attach_post(sc);
675
676 return (0);
677 fail:
678 if (mac != NULL && mac->mac_res_irq != NULL) {
679 bus_release_resource(dev, SYS_RES_IRQ, mac->mac_rid_irq,
680 mac->mac_res_irq);
681 }
682
683 free(mac, M_DEVBUF);
684 bhnd_release_pmu(dev);
685 bwn_release_bus_providers(sc);
686
687 if (sc->sc_mem_res != NULL) {
688 bus_release_resource(sc->sc_dev, SYS_RES_MEMORY,
689 sc->sc_mem_rid, sc->sc_mem_res);
690 }
691
692 return (error);
693 }
694
695 static int
bwn_retain_bus_providers(struct bwn_softc * sc)696 bwn_retain_bus_providers(struct bwn_softc *sc)
697 {
698 struct chipc_caps *ccaps;
699
700 sc->sc_chipc = bhnd_retain_provider(sc->sc_dev, BHND_SERVICE_CHIPC);
701 if (sc->sc_chipc == NULL) {
702 device_printf(sc->sc_dev, "ChipCommon device not found\n");
703 goto failed;
704 }
705
706 ccaps = BHND_CHIPC_GET_CAPS(sc->sc_chipc);
707
708 sc->sc_gpio = bhnd_retain_provider(sc->sc_dev, BHND_SERVICE_GPIO);
709 if (sc->sc_gpio == NULL) {
710 device_printf(sc->sc_dev, "GPIO device not found\n");
711 goto failed;
712 }
713
714 if (ccaps->pmu) {
715 sc->sc_pmu = bhnd_retain_provider(sc->sc_dev, BHND_SERVICE_PMU);
716 if (sc->sc_pmu == NULL) {
717 device_printf(sc->sc_dev, "PMU device not found\n");
718 goto failed;
719 }
720 }
721
722 return (0);
723
724 failed:
725 bwn_release_bus_providers(sc);
726 return (ENXIO);
727 }
728
729 static void
bwn_release_bus_providers(struct bwn_softc * sc)730 bwn_release_bus_providers(struct bwn_softc *sc)
731 {
732 #define BWN_RELEASE_PROV(_sc, _prov, _service) do { \
733 if ((_sc)-> _prov != NULL) { \
734 bhnd_release_provider((_sc)->sc_dev, (_sc)-> _prov, \
735 (_service)); \
736 (_sc)-> _prov = NULL; \
737 } \
738 } while (0)
739
740 BWN_RELEASE_PROV(sc, sc_chipc, BHND_SERVICE_CHIPC);
741 BWN_RELEASE_PROV(sc, sc_gpio, BHND_SERVICE_GPIO);
742 BWN_RELEASE_PROV(sc, sc_pmu, BHND_SERVICE_PMU);
743
744 #undef BWN_RELEASE_PROV
745 }
746
747 static int
bwn_attach_post(struct bwn_softc * sc)748 bwn_attach_post(struct bwn_softc *sc)
749 {
750 struct ieee80211com *ic;
751 const char *mac_varname;
752 u_int core_unit;
753 int error;
754
755 ic = &sc->sc_ic;
756
757 ic->ic_softc = sc;
758 ic->ic_name = device_get_nameunit(sc->sc_dev);
759 /* XXX not right but it's not used anywhere important */
760 ic->ic_phytype = IEEE80211_T_OFDM;
761 ic->ic_opmode = IEEE80211_M_STA;
762 ic->ic_caps =
763 IEEE80211_C_STA /* station mode supported */
764 | IEEE80211_C_MONITOR /* monitor mode */
765 | IEEE80211_C_AHDEMO /* adhoc demo mode */
766 | IEEE80211_C_SHPREAMBLE /* short preamble supported */
767 | IEEE80211_C_SHSLOT /* short slot time supported */
768 | IEEE80211_C_WME /* WME/WMM supported */
769 | IEEE80211_C_WPA /* capable of WPA1+WPA2 */
770 #if 0
771 | IEEE80211_C_BGSCAN /* capable of bg scanning */
772 #endif
773 | IEEE80211_C_TXPMGT /* capable of txpow mgt */
774 ;
775
776 ic->ic_flags_ext |= IEEE80211_FEXT_SWBMISS; /* s/w bmiss */
777
778 /* Determine the NVRAM variable containing our MAC address */
779 core_unit = bhnd_get_core_unit(sc->sc_dev);
780 mac_varname = NULL;
781 if (sc->sc_board_info.board_srom_rev <= 2) {
782 if (core_unit == 0) {
783 mac_varname = BHND_NVAR_IL0MACADDR;
784 } else if (core_unit == 1) {
785 mac_varname = BHND_NVAR_ET1MACADDR;
786 }
787 } else {
788 if (core_unit == 0) {
789 mac_varname = BHND_NVAR_MACADDR;
790 }
791 }
792
793 if (mac_varname == NULL) {
794 device_printf(sc->sc_dev, "missing MAC address variable for "
795 "D11 core %u", core_unit);
796 return (ENXIO);
797 }
798
799 /* Read the MAC address from NVRAM */
800 error = bhnd_nvram_getvar_array(sc->sc_dev, mac_varname, ic->ic_macaddr,
801 sizeof(ic->ic_macaddr), BHND_NVRAM_TYPE_UINT8_ARRAY);
802 if (error) {
803 device_printf(sc->sc_dev, "error reading %s: %d\n", mac_varname,
804 error);
805 return (error);
806 }
807
808 /* call MI attach routine. */
809 ieee80211_ifattach(ic);
810
811 /* override default methods */
812 ic->ic_raw_xmit = bwn_raw_xmit;
813 ic->ic_updateslot = bwn_updateslot;
814 ic->ic_update_promisc = bwn_update_promisc;
815 ic->ic_wme.wme_update = bwn_wme_update;
816 ic->ic_scan_start = bwn_scan_start;
817 ic->ic_scan_end = bwn_scan_end;
818 ic->ic_set_channel = bwn_set_channel;
819 ic->ic_vap_create = bwn_vap_create;
820 ic->ic_vap_delete = bwn_vap_delete;
821 ic->ic_transmit = bwn_transmit;
822 ic->ic_parent = bwn_parent;
823
824 ieee80211_radiotap_attach(ic,
825 &sc->sc_tx_th.wt_ihdr, sizeof(sc->sc_tx_th),
826 BWN_TX_RADIOTAP_PRESENT,
827 &sc->sc_rx_th.wr_ihdr, sizeof(sc->sc_rx_th),
828 BWN_RX_RADIOTAP_PRESENT);
829
830 bwn_sysctl_node(sc);
831
832 if (bootverbose)
833 ieee80211_announce(ic);
834 return (0);
835 }
836
837 static void
bwn_phy_detach(struct bwn_mac * mac)838 bwn_phy_detach(struct bwn_mac *mac)
839 {
840
841 if (mac->mac_phy.detach != NULL)
842 mac->mac_phy.detach(mac);
843 }
844
845 static int
bwn_detach(device_t dev)846 bwn_detach(device_t dev)
847 {
848 struct bwn_softc *sc = device_get_softc(dev);
849 struct bwn_mac *mac = sc->sc_curmac;
850 struct ieee80211com *ic = &sc->sc_ic;
851
852 sc->sc_flags |= BWN_FLAG_INVALID;
853
854 if (device_is_attached(sc->sc_dev)) {
855 BWN_LOCK(sc);
856 bwn_stop(sc);
857 BWN_UNLOCK(sc);
858 bwn_dma_free(mac);
859 callout_drain(&sc->sc_led_blink_ch);
860 callout_drain(&sc->sc_rfswitch_ch);
861 callout_drain(&sc->sc_task_ch);
862 callout_drain(&sc->sc_watchdog_ch);
863 bwn_phy_detach(mac);
864 ieee80211_draintask(ic, &mac->mac_hwreset);
865 ieee80211_draintask(ic, &mac->mac_txpower);
866 ieee80211_ifdetach(ic);
867 }
868 taskqueue_drain(sc->sc_tq, &mac->mac_intrtask);
869 taskqueue_free(sc->sc_tq);
870
871 if (mac->mac_intrhand != NULL) {
872 bus_teardown_intr(dev, mac->mac_res_irq, mac->mac_intrhand);
873 mac->mac_intrhand = NULL;
874 }
875
876 bhnd_release_pmu(dev);
877 bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_mem_rid,
878 sc->sc_mem_res);
879 bus_release_resource(dev, SYS_RES_IRQ, mac->mac_rid_irq,
880 mac->mac_res_irq);
881 mbufq_drain(&sc->sc_snd);
882 bwn_release_firmware(mac);
883 BWN_LOCK_DESTROY(sc);
884
885 bwn_release_bus_providers(sc);
886
887 return (0);
888 }
889
890 static void
bwn_attach_pre(struct bwn_softc * sc)891 bwn_attach_pre(struct bwn_softc *sc)
892 {
893
894 BWN_LOCK_INIT(sc);
895 TAILQ_INIT(&sc->sc_maclist);
896 callout_init_mtx(&sc->sc_rfswitch_ch, &sc->sc_mtx, 0);
897 callout_init_mtx(&sc->sc_task_ch, &sc->sc_mtx, 0);
898 callout_init_mtx(&sc->sc_watchdog_ch, &sc->sc_mtx, 0);
899 mbufq_init(&sc->sc_snd, ifqmaxlen);
900 sc->sc_tq = taskqueue_create_fast("bwn_taskq", M_NOWAIT,
901 taskqueue_thread_enqueue, &sc->sc_tq);
902 taskqueue_start_threads(&sc->sc_tq, 1, PI_NET,
903 "%s taskq", device_get_nameunit(sc->sc_dev));
904 }
905
906 static void
bwn_sprom_bugfixes(device_t dev)907 bwn_sprom_bugfixes(device_t dev)
908 {
909 struct bwn_softc *sc = device_get_softc(dev);
910
911 #define BWN_ISDEV(_device, _subvendor, _subdevice) \
912 ((sc->sc_board_info.board_devid == PCI_DEVID_##_device) && \
913 (sc->sc_board_info.board_vendor == PCI_VENDOR_##_subvendor) && \
914 (sc->sc_board_info.board_type == _subdevice))
915
916 /* A subset of Apple Airport Extreme (BCM4306 rev 2) devices
917 * were programmed with a missing PACTRL boardflag */
918 if (sc->sc_board_info.board_vendor == PCI_VENDOR_APPLE &&
919 sc->sc_board_info.board_type == 0x4e &&
920 sc->sc_board_info.board_rev > 0x40)
921 sc->sc_board_info.board_flags |= BHND_BFL_PACTRL;
922
923 if (BWN_ISDEV(BCM4318_D11G, ASUSTEK, 0x100f) ||
924 BWN_ISDEV(BCM4306_D11G, DELL, 0x0003) ||
925 BWN_ISDEV(BCM4306_D11G, HP, 0x12f8) ||
926 BWN_ISDEV(BCM4306_D11G, LINKSYS, 0x0013) ||
927 BWN_ISDEV(BCM4306_D11G, LINKSYS, 0x0014) ||
928 BWN_ISDEV(BCM4306_D11G, LINKSYS, 0x0015) ||
929 BWN_ISDEV(BCM4306_D11G, MOTOROLA, 0x7010))
930 sc->sc_board_info.board_flags &= ~BHND_BFL_BTCOEX;
931 #undef BWN_ISDEV
932 }
933
934 static void
bwn_parent(struct ieee80211com * ic)935 bwn_parent(struct ieee80211com *ic)
936 {
937 struct bwn_softc *sc = ic->ic_softc;
938 int startall = 0;
939
940 BWN_LOCK(sc);
941 if (ic->ic_nrunning > 0) {
942 if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0) {
943 bwn_init(sc);
944 startall = 1;
945 } else
946 bwn_update_promisc(ic);
947 } else if (sc->sc_flags & BWN_FLAG_RUNNING)
948 bwn_stop(sc);
949 BWN_UNLOCK(sc);
950
951 if (startall)
952 ieee80211_start_all(ic);
953 }
954
955 static int
bwn_transmit(struct ieee80211com * ic,struct mbuf * m)956 bwn_transmit(struct ieee80211com *ic, struct mbuf *m)
957 {
958 struct bwn_softc *sc = ic->ic_softc;
959 int error;
960
961 BWN_LOCK(sc);
962 if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0) {
963 BWN_UNLOCK(sc);
964 return (ENXIO);
965 }
966 error = mbufq_enqueue(&sc->sc_snd, m);
967 if (error) {
968 BWN_UNLOCK(sc);
969 return (error);
970 }
971 bwn_start(sc);
972 BWN_UNLOCK(sc);
973 return (0);
974 }
975
976 static void
bwn_start(struct bwn_softc * sc)977 bwn_start(struct bwn_softc *sc)
978 {
979 struct bwn_mac *mac = sc->sc_curmac;
980 struct ieee80211_frame *wh;
981 struct ieee80211_node *ni;
982 struct ieee80211_key *k;
983 struct mbuf *m;
984
985 BWN_ASSERT_LOCKED(sc);
986
987 if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0 || mac == NULL ||
988 mac->mac_status < BWN_MAC_STATUS_STARTED)
989 return;
990
991 while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
992 if (bwn_tx_isfull(sc, m))
993 break;
994 ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
995 if (ni == NULL) {
996 device_printf(sc->sc_dev, "unexpected NULL ni\n");
997 m_freem(m);
998 counter_u64_add(sc->sc_ic.ic_oerrors, 1);
999 continue;
1000 }
1001 wh = mtod(m, struct ieee80211_frame *);
1002 if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
1003 k = ieee80211_crypto_encap(ni, m);
1004 if (k == NULL) {
1005 if_inc_counter(ni->ni_vap->iv_ifp,
1006 IFCOUNTER_OERRORS, 1);
1007 ieee80211_free_node(ni);
1008 m_freem(m);
1009 continue;
1010 }
1011 }
1012 wh = NULL; /* Catch any invalid use */
1013 if (bwn_tx_start(sc, ni, m) != 0) {
1014 if (ni != NULL) {
1015 if_inc_counter(ni->ni_vap->iv_ifp,
1016 IFCOUNTER_OERRORS, 1);
1017 ieee80211_free_node(ni);
1018 }
1019 continue;
1020 }
1021 sc->sc_watchdog_timer = 5;
1022 }
1023 }
1024
1025 static int
bwn_tx_isfull(struct bwn_softc * sc,struct mbuf * m)1026 bwn_tx_isfull(struct bwn_softc *sc, struct mbuf *m)
1027 {
1028 struct bwn_dma_ring *dr;
1029 struct bwn_mac *mac = sc->sc_curmac;
1030 struct bwn_pio_txqueue *tq;
1031 int pktlen = roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1032
1033 BWN_ASSERT_LOCKED(sc);
1034
1035 if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
1036 dr = bwn_dma_select(mac, M_WME_GETAC(m));
1037 if (dr->dr_stop == 1 ||
1038 bwn_dma_freeslot(dr) < BWN_TX_SLOTS_PER_FRAME) {
1039 dr->dr_stop = 1;
1040 goto full;
1041 }
1042 } else {
1043 tq = bwn_pio_select(mac, M_WME_GETAC(m));
1044 if (tq->tq_free == 0 || pktlen > tq->tq_size ||
1045 pktlen > (tq->tq_size - tq->tq_used))
1046 goto full;
1047 }
1048 return (0);
1049 full:
1050 mbufq_prepend(&sc->sc_snd, m);
1051 return (1);
1052 }
1053
1054 static int
bwn_tx_start(struct bwn_softc * sc,struct ieee80211_node * ni,struct mbuf * m)1055 bwn_tx_start(struct bwn_softc *sc, struct ieee80211_node *ni, struct mbuf *m)
1056 {
1057 struct bwn_mac *mac = sc->sc_curmac;
1058 int error;
1059
1060 BWN_ASSERT_LOCKED(sc);
1061
1062 if (m->m_pkthdr.len < IEEE80211_MIN_LEN || mac == NULL) {
1063 m_freem(m);
1064 return (ENXIO);
1065 }
1066
1067 error = (mac->mac_flags & BWN_MAC_FLAG_DMA) ?
1068 bwn_dma_tx_start(mac, ni, &m) : bwn_pio_tx_start(mac, ni, &m);
1069 if (error) {
1070 m_freem(m);
1071 return (error);
1072 }
1073 return (0);
1074 }
1075
1076 static int
bwn_pio_tx_start(struct bwn_mac * mac,struct ieee80211_node * ni,struct mbuf ** mp)1077 bwn_pio_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni,
1078 struct mbuf **mp)
1079 {
1080 struct bwn_pio_txpkt *tp;
1081 struct bwn_pio_txqueue *tq;
1082 struct bwn_softc *sc = mac->mac_sc;
1083 struct bwn_txhdr txhdr;
1084 struct mbuf *m, *m_new;
1085 uint32_t ctl32;
1086 int error;
1087 uint16_t ctl16;
1088
1089 BWN_ASSERT_LOCKED(sc);
1090
1091 /* XXX TODO send packets after DTIM */
1092
1093 m = *mp;
1094 tq = bwn_pio_select(mac, M_WME_GETAC(m));
1095 KASSERT(!TAILQ_EMPTY(&tq->tq_pktlist), ("%s: fail", __func__));
1096 tp = TAILQ_FIRST(&tq->tq_pktlist);
1097 tp->tp_ni = ni;
1098 tp->tp_m = m;
1099
1100 error = bwn_set_txhdr(mac, ni, m, &txhdr, BWN_PIO_COOKIE(tq, tp));
1101 if (error) {
1102 device_printf(sc->sc_dev, "tx fail\n");
1103 return (error);
1104 }
1105
1106 TAILQ_REMOVE(&tq->tq_pktlist, tp, tp_list);
1107 tq->tq_used += roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1108 tq->tq_free--;
1109
1110 if (bhnd_get_hwrev(sc->sc_dev) >= 8) {
1111 /*
1112 * XXX please removes m_defrag(9)
1113 */
1114 m_new = m_defrag(*mp, M_NOWAIT);
1115 if (m_new == NULL) {
1116 device_printf(sc->sc_dev,
1117 "%s: can't defrag TX buffer\n",
1118 __func__);
1119 return (ENOBUFS);
1120 }
1121 *mp = m_new;
1122 if (m_new->m_next != NULL)
1123 device_printf(sc->sc_dev,
1124 "TODO: fragmented packets for PIO\n");
1125 tp->tp_m = m_new;
1126
1127 /* send HEADER */
1128 ctl32 = bwn_pio_write_multi_4(mac, tq,
1129 (BWN_PIO_READ_4(mac, tq, BWN_PIO8_TXCTL) |
1130 BWN_PIO8_TXCTL_FRAMEREADY) & ~BWN_PIO8_TXCTL_EOF,
1131 (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1132 /* send BODY */
1133 ctl32 = bwn_pio_write_multi_4(mac, tq, ctl32,
1134 mtod(m_new, const void *), m_new->m_pkthdr.len);
1135 bwn_pio_write_4(mac, tq, BWN_PIO_TXCTL,
1136 ctl32 | BWN_PIO8_TXCTL_EOF);
1137 } else {
1138 ctl16 = bwn_pio_write_multi_2(mac, tq,
1139 (bwn_pio_read_2(mac, tq, BWN_PIO_TXCTL) |
1140 BWN_PIO_TXCTL_FRAMEREADY) & ~BWN_PIO_TXCTL_EOF,
1141 (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1142 ctl16 = bwn_pio_write_mbuf_2(mac, tq, ctl16, m);
1143 BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL,
1144 ctl16 | BWN_PIO_TXCTL_EOF);
1145 }
1146
1147 return (0);
1148 }
1149
1150 static struct bwn_pio_txqueue *
bwn_pio_select(struct bwn_mac * mac,uint8_t prio)1151 bwn_pio_select(struct bwn_mac *mac, uint8_t prio)
1152 {
1153
1154 if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
1155 return (&mac->mac_method.pio.wme[WME_AC_BE]);
1156
1157 switch (prio) {
1158 case 0:
1159 return (&mac->mac_method.pio.wme[WME_AC_BE]);
1160 case 1:
1161 return (&mac->mac_method.pio.wme[WME_AC_BK]);
1162 case 2:
1163 return (&mac->mac_method.pio.wme[WME_AC_VI]);
1164 case 3:
1165 return (&mac->mac_method.pio.wme[WME_AC_VO]);
1166 }
1167 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
1168 return (NULL);
1169 }
1170
1171 static int
bwn_dma_tx_start(struct bwn_mac * mac,struct ieee80211_node * ni,struct mbuf ** mp)1172 bwn_dma_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni,
1173 struct mbuf **mp)
1174 {
1175 #define BWN_GET_TXHDRCACHE(slot) \
1176 &(txhdr_cache[(slot / BWN_TX_SLOTS_PER_FRAME) * BWN_HDRSIZE(mac)])
1177 struct bwn_dma *dma = &mac->mac_method.dma;
1178 struct bwn_dma_ring *dr = bwn_dma_select(mac, M_WME_GETAC(*mp));
1179 struct bwn_dmadesc_generic *desc;
1180 struct bwn_dmadesc_meta *mt;
1181 struct bwn_softc *sc = mac->mac_sc;
1182 struct mbuf *m;
1183 uint8_t *txhdr_cache = (uint8_t *)dr->dr_txhdr_cache;
1184 int error, slot, backup[2] = { dr->dr_curslot, dr->dr_usedslot };
1185
1186 BWN_ASSERT_LOCKED(sc);
1187 KASSERT(!dr->dr_stop, ("%s:%d: fail", __func__, __LINE__));
1188
1189 /* XXX send after DTIM */
1190
1191 m = *mp;
1192 slot = bwn_dma_getslot(dr);
1193 dr->getdesc(dr, slot, &desc, &mt);
1194 KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_HEADER,
1195 ("%s:%d: fail", __func__, __LINE__));
1196
1197 error = bwn_set_txhdr(dr->dr_mac, ni, m,
1198 (struct bwn_txhdr *)BWN_GET_TXHDRCACHE(slot),
1199 BWN_DMA_COOKIE(dr, slot));
1200 if (error)
1201 goto fail;
1202 error = bus_dmamap_load(dr->dr_txring_dtag, mt->mt_dmap,
1203 BWN_GET_TXHDRCACHE(slot), BWN_HDRSIZE(mac), bwn_dma_ring_addr,
1204 &mt->mt_paddr, BUS_DMA_NOWAIT);
1205 if (error) {
1206 device_printf(sc->sc_dev, "%s: can't load TX buffer (1) %d\n",
1207 __func__, error);
1208 goto fail;
1209 }
1210 bus_dmamap_sync(dr->dr_txring_dtag, mt->mt_dmap,
1211 BUS_DMASYNC_PREWRITE);
1212 dr->setdesc(dr, desc, mt->mt_paddr, BWN_HDRSIZE(mac), 1, 0, 0);
1213 bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1214 BUS_DMASYNC_PREWRITE);
1215
1216 slot = bwn_dma_getslot(dr);
1217 dr->getdesc(dr, slot, &desc, &mt);
1218 KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_BODY &&
1219 mt->mt_islast == 1, ("%s:%d: fail", __func__, __LINE__));
1220 mt->mt_m = m;
1221 mt->mt_ni = ni;
1222
1223 error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap, m,
1224 bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1225 if (error && error != EFBIG) {
1226 device_printf(sc->sc_dev, "%s: can't load TX buffer (1) %d\n",
1227 __func__, error);
1228 goto fail;
1229 }
1230 if (error) { /* error == EFBIG */
1231 struct mbuf *m_new;
1232
1233 m_new = m_defrag(m, M_NOWAIT);
1234 if (m_new == NULL) {
1235 device_printf(sc->sc_dev,
1236 "%s: can't defrag TX buffer\n",
1237 __func__);
1238 error = ENOBUFS;
1239 goto fail;
1240 }
1241 *mp = m = m_new;
1242
1243 mt->mt_m = m;
1244 error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap,
1245 m, bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1246 if (error) {
1247 device_printf(sc->sc_dev,
1248 "%s: can't load TX buffer (2) %d\n",
1249 __func__, error);
1250 goto fail;
1251 }
1252 }
1253 bus_dmamap_sync(dma->txbuf_dtag, mt->mt_dmap, BUS_DMASYNC_PREWRITE);
1254 dr->setdesc(dr, desc, mt->mt_paddr, m->m_pkthdr.len, 0, 1, 1);
1255 bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1256 BUS_DMASYNC_PREWRITE);
1257
1258 /* XXX send after DTIM */
1259
1260 dr->start_transfer(dr, bwn_dma_nextslot(dr, slot));
1261 return (0);
1262 fail:
1263 dr->dr_curslot = backup[0];
1264 dr->dr_usedslot = backup[1];
1265 return (error);
1266 #undef BWN_GET_TXHDRCACHE
1267 }
1268
1269 static void
bwn_watchdog(void * arg)1270 bwn_watchdog(void *arg)
1271 {
1272 struct bwn_softc *sc = arg;
1273
1274 if (sc->sc_watchdog_timer != 0 && --sc->sc_watchdog_timer == 0) {
1275 device_printf(sc->sc_dev, "device timeout\n");
1276 counter_u64_add(sc->sc_ic.ic_oerrors, 1);
1277 }
1278 callout_schedule(&sc->sc_watchdog_ch, hz);
1279 }
1280
1281 static int
bwn_attach_core(struct bwn_mac * mac)1282 bwn_attach_core(struct bwn_mac *mac)
1283 {
1284 struct bwn_softc *sc = mac->mac_sc;
1285 int error, have_bg = 0, have_a = 0;
1286 uint16_t iost;
1287
1288 KASSERT(bhnd_get_hwrev(sc->sc_dev) >= 5,
1289 ("unsupported revision %d", bhnd_get_hwrev(sc->sc_dev)));
1290
1291 if ((error = bwn_core_forceclk(mac, true)))
1292 return (error);
1293
1294 if ((error = bhnd_read_iost(sc->sc_dev, &iost))) {
1295 device_printf(sc->sc_dev, "error reading I/O status flags: "
1296 "%d\n", error);
1297 return (error);
1298 }
1299
1300 have_a = (iost & BWN_IOST_HAVE_5GHZ) ? 1 : 0;
1301 have_bg = (iost & BWN_IOST_HAVE_2GHZ) ? 1 : 0;
1302 if (iost & BWN_IOST_DUALPHY) {
1303 have_bg = 1;
1304 have_a = 1;
1305 }
1306
1307 #if 0
1308 device_printf(sc->sc_dev, "%s: iost=0x%04hx, have_a=%d, have_bg=%d,"
1309 " deviceid=0x%04x, siba_deviceid=0x%04x\n",
1310 __func__,
1311 iost,
1312 have_a,
1313 have_bg,
1314 sc->sc_board_info.board_devid,
1315 sc->sc_cid.chip_id);
1316 #endif
1317
1318 /*
1319 * Guess at whether it has A-PHY or G-PHY.
1320 * This is just used for resetting the core to probe things;
1321 * we will re-guess once it's all up and working.
1322 */
1323 error = bwn_reset_core(mac, have_bg);
1324 if (error)
1325 goto fail;
1326
1327 /*
1328 * Determine the DMA engine type
1329 */
1330 if (iost & BHND_IOST_DMA64) {
1331 mac->mac_dmatype = BHND_DMA_ADDR_64BIT;
1332 } else {
1333 uint32_t tmp;
1334 uint16_t base;
1335
1336 base = bwn_dma_base(0, 0);
1337 BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL,
1338 BWN_DMA32_TXADDREXT_MASK);
1339 tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
1340 if (tmp & BWN_DMA32_TXADDREXT_MASK) {
1341 mac->mac_dmatype = BHND_DMA_ADDR_32BIT;
1342 } else {
1343 mac->mac_dmatype = BHND_DMA_ADDR_30BIT;
1344 }
1345 }
1346
1347 /*
1348 * Get the PHY version.
1349 */
1350 error = bwn_phy_getinfo(mac, have_bg);
1351 if (error)
1352 goto fail;
1353
1354 /*
1355 * This is the whitelist of devices which we "believe"
1356 * the SPROM PHY config from. The rest are "guessed".
1357 */
1358 if (sc->sc_board_info.board_devid != PCI_DEVID_BCM4311_D11DUAL &&
1359 sc->sc_board_info.board_devid != PCI_DEVID_BCM4328_D11G &&
1360 sc->sc_board_info.board_devid != PCI_DEVID_BCM4318_D11DUAL &&
1361 sc->sc_board_info.board_devid != PCI_DEVID_BCM4306_D11DUAL &&
1362 sc->sc_board_info.board_devid != PCI_DEVID_BCM4321_D11N &&
1363 sc->sc_board_info.board_devid != PCI_DEVID_BCM4322_D11N) {
1364 have_a = have_bg = 0;
1365 if (mac->mac_phy.type == BWN_PHYTYPE_A)
1366 have_a = 1;
1367 else if (mac->mac_phy.type == BWN_PHYTYPE_G ||
1368 mac->mac_phy.type == BWN_PHYTYPE_N ||
1369 mac->mac_phy.type == BWN_PHYTYPE_LP)
1370 have_bg = 1;
1371 else
1372 KASSERT(0 == 1, ("%s: unknown phy type (%d)", __func__,
1373 mac->mac_phy.type));
1374 }
1375
1376 /*
1377 * XXX The PHY-G support doesn't do 5GHz operation.
1378 */
1379 if (mac->mac_phy.type != BWN_PHYTYPE_LP &&
1380 mac->mac_phy.type != BWN_PHYTYPE_N) {
1381 device_printf(sc->sc_dev,
1382 "%s: forcing 2GHz only; no dual-band support for PHY\n",
1383 __func__);
1384 have_a = 0;
1385 have_bg = 1;
1386 }
1387
1388 mac->mac_phy.phy_n = NULL;
1389
1390 if (mac->mac_phy.type == BWN_PHYTYPE_G) {
1391 mac->mac_phy.attach = bwn_phy_g_attach;
1392 mac->mac_phy.detach = bwn_phy_g_detach;
1393 mac->mac_phy.prepare_hw = bwn_phy_g_prepare_hw;
1394 mac->mac_phy.init_pre = bwn_phy_g_init_pre;
1395 mac->mac_phy.init = bwn_phy_g_init;
1396 mac->mac_phy.exit = bwn_phy_g_exit;
1397 mac->mac_phy.phy_read = bwn_phy_g_read;
1398 mac->mac_phy.phy_write = bwn_phy_g_write;
1399 mac->mac_phy.rf_read = bwn_phy_g_rf_read;
1400 mac->mac_phy.rf_write = bwn_phy_g_rf_write;
1401 mac->mac_phy.use_hwpctl = bwn_phy_g_hwpctl;
1402 mac->mac_phy.rf_onoff = bwn_phy_g_rf_onoff;
1403 mac->mac_phy.switch_analog = bwn_phy_switch_analog;
1404 mac->mac_phy.switch_channel = bwn_phy_g_switch_channel;
1405 mac->mac_phy.get_default_chan = bwn_phy_g_get_default_chan;
1406 mac->mac_phy.set_antenna = bwn_phy_g_set_antenna;
1407 mac->mac_phy.set_im = bwn_phy_g_im;
1408 mac->mac_phy.recalc_txpwr = bwn_phy_g_recalc_txpwr;
1409 mac->mac_phy.set_txpwr = bwn_phy_g_set_txpwr;
1410 mac->mac_phy.task_15s = bwn_phy_g_task_15s;
1411 mac->mac_phy.task_60s = bwn_phy_g_task_60s;
1412 } else if (mac->mac_phy.type == BWN_PHYTYPE_LP) {
1413 mac->mac_phy.init_pre = bwn_phy_lp_init_pre;
1414 mac->mac_phy.init = bwn_phy_lp_init;
1415 mac->mac_phy.phy_read = bwn_phy_lp_read;
1416 mac->mac_phy.phy_write = bwn_phy_lp_write;
1417 mac->mac_phy.phy_maskset = bwn_phy_lp_maskset;
1418 mac->mac_phy.rf_read = bwn_phy_lp_rf_read;
1419 mac->mac_phy.rf_write = bwn_phy_lp_rf_write;
1420 mac->mac_phy.rf_onoff = bwn_phy_lp_rf_onoff;
1421 mac->mac_phy.switch_analog = bwn_phy_lp_switch_analog;
1422 mac->mac_phy.switch_channel = bwn_phy_lp_switch_channel;
1423 mac->mac_phy.get_default_chan = bwn_phy_lp_get_default_chan;
1424 mac->mac_phy.set_antenna = bwn_phy_lp_set_antenna;
1425 mac->mac_phy.task_60s = bwn_phy_lp_task_60s;
1426 } else if (mac->mac_phy.type == BWN_PHYTYPE_N) {
1427 mac->mac_phy.attach = bwn_phy_n_attach;
1428 mac->mac_phy.detach = bwn_phy_n_detach;
1429 mac->mac_phy.prepare_hw = bwn_phy_n_prepare_hw;
1430 mac->mac_phy.init_pre = bwn_phy_n_init_pre;
1431 mac->mac_phy.init = bwn_phy_n_init;
1432 mac->mac_phy.exit = bwn_phy_n_exit;
1433 mac->mac_phy.phy_read = bwn_phy_n_read;
1434 mac->mac_phy.phy_write = bwn_phy_n_write;
1435 mac->mac_phy.rf_read = bwn_phy_n_rf_read;
1436 mac->mac_phy.rf_write = bwn_phy_n_rf_write;
1437 mac->mac_phy.use_hwpctl = bwn_phy_n_hwpctl;
1438 mac->mac_phy.rf_onoff = bwn_phy_n_rf_onoff;
1439 mac->mac_phy.switch_analog = bwn_phy_n_switch_analog;
1440 mac->mac_phy.switch_channel = bwn_phy_n_switch_channel;
1441 mac->mac_phy.get_default_chan = bwn_phy_n_get_default_chan;
1442 mac->mac_phy.set_antenna = bwn_phy_n_set_antenna;
1443 mac->mac_phy.set_im = bwn_phy_n_im;
1444 mac->mac_phy.recalc_txpwr = bwn_phy_n_recalc_txpwr;
1445 mac->mac_phy.set_txpwr = bwn_phy_n_set_txpwr;
1446 mac->mac_phy.task_15s = bwn_phy_n_task_15s;
1447 mac->mac_phy.task_60s = bwn_phy_n_task_60s;
1448 } else {
1449 device_printf(sc->sc_dev, "unsupported PHY type (%d)\n",
1450 mac->mac_phy.type);
1451 error = ENXIO;
1452 goto fail;
1453 }
1454
1455 mac->mac_phy.gmode = have_bg;
1456 if (mac->mac_phy.attach != NULL) {
1457 error = mac->mac_phy.attach(mac);
1458 if (error) {
1459 device_printf(sc->sc_dev, "failed\n");
1460 goto fail;
1461 }
1462 }
1463
1464 error = bwn_reset_core(mac, have_bg);
1465 if (error)
1466 goto fail;
1467
1468 error = bwn_chiptest(mac);
1469 if (error)
1470 goto fail;
1471 error = bwn_setup_channels(mac, have_bg, have_a);
1472 if (error) {
1473 device_printf(sc->sc_dev, "failed to setup channels\n");
1474 goto fail;
1475 }
1476
1477 if (sc->sc_curmac == NULL)
1478 sc->sc_curmac = mac;
1479
1480 error = bwn_dma_attach(mac);
1481 if (error != 0) {
1482 device_printf(sc->sc_dev, "failed to initialize DMA\n");
1483 goto fail;
1484 }
1485
1486 mac->mac_phy.switch_analog(mac, 0);
1487
1488 fail:
1489 bhnd_suspend_hw(sc->sc_dev, 0);
1490 bwn_release_firmware(mac);
1491 return (error);
1492 }
1493
1494 /*
1495 * Reset
1496 */
1497 int
bwn_reset_core(struct bwn_mac * mac,int g_mode)1498 bwn_reset_core(struct bwn_mac *mac, int g_mode)
1499 {
1500 struct bwn_softc *sc;
1501 uint32_t ctl;
1502 uint16_t ioctl, ioctl_mask;
1503 int error;
1504
1505 sc = mac->mac_sc;
1506
1507 DPRINTF(sc, BWN_DEBUG_RESET, "%s: g_mode=%d\n", __func__, g_mode);
1508
1509 /* Reset core */
1510 ioctl = (BWN_IOCTL_PHYCLOCK_ENABLE | BWN_IOCTL_PHYRESET);
1511 if (g_mode)
1512 ioctl |= BWN_IOCTL_SUPPORT_G;
1513
1514 /* XXX N-PHY only; and hard-code to 20MHz for now */
1515 if (mac->mac_phy.type == BWN_PHYTYPE_N)
1516 ioctl |= BWN_IOCTL_PHY_BANDWIDTH_20MHZ;
1517
1518 if ((error = bhnd_reset_hw(sc->sc_dev, ioctl, ioctl))) {
1519 device_printf(sc->sc_dev, "core reset failed: %d", error);
1520 return (error);
1521 }
1522
1523 DELAY(2000);
1524
1525 /* Take PHY out of reset */
1526 ioctl = BHND_IOCTL_CLK_FORCE;
1527 ioctl_mask = BHND_IOCTL_CLK_FORCE |
1528 BWN_IOCTL_PHYRESET |
1529 BWN_IOCTL_PHYCLOCK_ENABLE;
1530
1531 if ((error = bhnd_write_ioctl(sc->sc_dev, ioctl, ioctl_mask))) {
1532 device_printf(sc->sc_dev, "failed to set core ioctl flags: "
1533 "%d\n", error);
1534 return (error);
1535 }
1536
1537 DELAY(2000);
1538
1539 ioctl = BWN_IOCTL_PHYCLOCK_ENABLE;
1540 if ((error = bhnd_write_ioctl(sc->sc_dev, ioctl, ioctl_mask))) {
1541 device_printf(sc->sc_dev, "failed to set core ioctl flags: "
1542 "%d\n", error);
1543 return (error);
1544 }
1545
1546 DELAY(2000);
1547
1548 if (mac->mac_phy.switch_analog != NULL)
1549 mac->mac_phy.switch_analog(mac, 1);
1550
1551 ctl = BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GMODE;
1552 if (g_mode)
1553 ctl |= BWN_MACCTL_GMODE;
1554 BWN_WRITE_4(mac, BWN_MACCTL, ctl | BWN_MACCTL_IHR_ON);
1555
1556 return (0);
1557 }
1558
1559 static int
bwn_phy_getinfo(struct bwn_mac * mac,int gmode)1560 bwn_phy_getinfo(struct bwn_mac *mac, int gmode)
1561 {
1562 struct bwn_phy *phy = &mac->mac_phy;
1563 struct bwn_softc *sc = mac->mac_sc;
1564 uint32_t tmp;
1565
1566 /* PHY */
1567 tmp = BWN_READ_2(mac, BWN_PHYVER);
1568 phy->gmode = gmode;
1569 phy->rf_on = 1;
1570 phy->analog = (tmp & BWN_PHYVER_ANALOG) >> 12;
1571 phy->type = (tmp & BWN_PHYVER_TYPE) >> 8;
1572 phy->rev = (tmp & BWN_PHYVER_VERSION);
1573 if ((phy->type == BWN_PHYTYPE_A && phy->rev >= 4) ||
1574 (phy->type == BWN_PHYTYPE_B && phy->rev != 2 &&
1575 phy->rev != 4 && phy->rev != 6 && phy->rev != 7) ||
1576 (phy->type == BWN_PHYTYPE_G && phy->rev > 9) ||
1577 (phy->type == BWN_PHYTYPE_N && phy->rev > 6) ||
1578 (phy->type == BWN_PHYTYPE_LP && phy->rev > 2))
1579 goto unsupphy;
1580
1581 /* RADIO */
1582 BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1583 tmp = BWN_READ_2(mac, BWN_RFDATALO);
1584 BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1585 tmp |= (uint32_t)BWN_READ_2(mac, BWN_RFDATAHI) << 16;
1586
1587 phy->rf_rev = (tmp & 0xf0000000) >> 28;
1588 phy->rf_ver = (tmp & 0x0ffff000) >> 12;
1589 phy->rf_manuf = (tmp & 0x00000fff);
1590
1591 /*
1592 * For now, just always do full init (ie, what bwn has traditionally
1593 * done)
1594 */
1595 phy->phy_do_full_init = 1;
1596
1597 if (phy->rf_manuf != 0x17f) /* 0x17f is broadcom */
1598 goto unsupradio;
1599 if ((phy->type == BWN_PHYTYPE_A && (phy->rf_ver != 0x2060 ||
1600 phy->rf_rev != 1 || phy->rf_manuf != 0x17f)) ||
1601 (phy->type == BWN_PHYTYPE_B && (phy->rf_ver & 0xfff0) != 0x2050) ||
1602 (phy->type == BWN_PHYTYPE_G && phy->rf_ver != 0x2050) ||
1603 (phy->type == BWN_PHYTYPE_N &&
1604 phy->rf_ver != 0x2055 && phy->rf_ver != 0x2056) ||
1605 (phy->type == BWN_PHYTYPE_LP &&
1606 phy->rf_ver != 0x2062 && phy->rf_ver != 0x2063))
1607 goto unsupradio;
1608
1609 return (0);
1610 unsupphy:
1611 device_printf(sc->sc_dev, "unsupported PHY (type %#x, rev %#x, "
1612 "analog %#x)\n",
1613 phy->type, phy->rev, phy->analog);
1614 return (ENXIO);
1615 unsupradio:
1616 device_printf(sc->sc_dev, "unsupported radio (manuf %#x, ver %#x, "
1617 "rev %#x)\n",
1618 phy->rf_manuf, phy->rf_ver, phy->rf_rev);
1619 return (ENXIO);
1620 }
1621
1622 static int
bwn_chiptest(struct bwn_mac * mac)1623 bwn_chiptest(struct bwn_mac *mac)
1624 {
1625 #define TESTVAL0 0x55aaaa55
1626 #define TESTVAL1 0xaa5555aa
1627 struct bwn_softc *sc = mac->mac_sc;
1628 uint32_t v, backup;
1629
1630 BWN_LOCK(sc);
1631
1632 backup = bwn_shm_read_4(mac, BWN_SHARED, 0);
1633
1634 bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL0);
1635 if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL0)
1636 goto error;
1637 bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL1);
1638 if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL1)
1639 goto error;
1640
1641 bwn_shm_write_4(mac, BWN_SHARED, 0, backup);
1642
1643 if ((bhnd_get_hwrev(sc->sc_dev) >= 3) &&
1644 (bhnd_get_hwrev(sc->sc_dev) <= 10)) {
1645 BWN_WRITE_2(mac, BWN_TSF_CFP_START, 0xaaaa);
1646 BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0xccccbbbb);
1647 if (BWN_READ_2(mac, BWN_TSF_CFP_START_LOW) != 0xbbbb)
1648 goto error;
1649 if (BWN_READ_2(mac, BWN_TSF_CFP_START_HIGH) != 0xcccc)
1650 goto error;
1651 }
1652 BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0);
1653
1654 v = BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_GMODE;
1655 if (v != (BWN_MACCTL_GMODE | BWN_MACCTL_IHR_ON))
1656 goto error;
1657
1658 BWN_UNLOCK(sc);
1659 return (0);
1660 error:
1661 BWN_UNLOCK(sc);
1662 device_printf(sc->sc_dev, "failed to validate the chipaccess\n");
1663 return (ENODEV);
1664 }
1665
1666 static int
bwn_setup_channels(struct bwn_mac * mac,int have_bg,int have_a)1667 bwn_setup_channels(struct bwn_mac *mac, int have_bg, int have_a)
1668 {
1669 struct bwn_softc *sc = mac->mac_sc;
1670 struct ieee80211com *ic = &sc->sc_ic;
1671 uint8_t bands[IEEE80211_MODE_BYTES];
1672
1673 memset(ic->ic_channels, 0, sizeof(ic->ic_channels));
1674 ic->ic_nchans = 0;
1675
1676 DPRINTF(sc, BWN_DEBUG_EEPROM, "%s: called; bg=%d, a=%d\n",
1677 __func__,
1678 have_bg,
1679 have_a);
1680
1681 if (have_bg) {
1682 memset(bands, 0, sizeof(bands));
1683 setbit(bands, IEEE80211_MODE_11B);
1684 setbit(bands, IEEE80211_MODE_11G);
1685 bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1686 &ic->ic_nchans, &bwn_chantable_bg, bands);
1687 }
1688
1689 if (have_a) {
1690 memset(bands, 0, sizeof(bands));
1691 setbit(bands, IEEE80211_MODE_11A);
1692 bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1693 &ic->ic_nchans, &bwn_chantable_a, bands);
1694 }
1695
1696 mac->mac_phy.supports_2ghz = have_bg;
1697 mac->mac_phy.supports_5ghz = have_a;
1698
1699 return (ic->ic_nchans == 0 ? ENXIO : 0);
1700 }
1701
1702 uint32_t
bwn_shm_read_4(struct bwn_mac * mac,uint16_t way,uint16_t offset)1703 bwn_shm_read_4(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1704 {
1705 uint32_t ret;
1706
1707 BWN_ASSERT_LOCKED(mac->mac_sc);
1708
1709 if (way == BWN_SHARED) {
1710 KASSERT((offset & 0x0001) == 0,
1711 ("%s:%d warn", __func__, __LINE__));
1712 if (offset & 0x0003) {
1713 bwn_shm_ctlword(mac, way, offset >> 2);
1714 ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1715 ret <<= 16;
1716 bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1717 ret |= BWN_READ_2(mac, BWN_SHM_DATA);
1718 goto out;
1719 }
1720 offset >>= 2;
1721 }
1722 bwn_shm_ctlword(mac, way, offset);
1723 ret = BWN_READ_4(mac, BWN_SHM_DATA);
1724 out:
1725 return (ret);
1726 }
1727
1728 uint16_t
bwn_shm_read_2(struct bwn_mac * mac,uint16_t way,uint16_t offset)1729 bwn_shm_read_2(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1730 {
1731 uint16_t ret;
1732
1733 BWN_ASSERT_LOCKED(mac->mac_sc);
1734
1735 if (way == BWN_SHARED) {
1736 KASSERT((offset & 0x0001) == 0,
1737 ("%s:%d warn", __func__, __LINE__));
1738 if (offset & 0x0003) {
1739 bwn_shm_ctlword(mac, way, offset >> 2);
1740 ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1741 goto out;
1742 }
1743 offset >>= 2;
1744 }
1745 bwn_shm_ctlword(mac, way, offset);
1746 ret = BWN_READ_2(mac, BWN_SHM_DATA);
1747 out:
1748
1749 return (ret);
1750 }
1751
1752 static void
bwn_shm_ctlword(struct bwn_mac * mac,uint16_t way,uint16_t offset)1753 bwn_shm_ctlword(struct bwn_mac *mac, uint16_t way,
1754 uint16_t offset)
1755 {
1756 uint32_t control;
1757
1758 control = way;
1759 control <<= 16;
1760 control |= offset;
1761 BWN_WRITE_4(mac, BWN_SHM_CONTROL, control);
1762 }
1763
1764 void
bwn_shm_write_4(struct bwn_mac * mac,uint16_t way,uint16_t offset,uint32_t value)1765 bwn_shm_write_4(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1766 uint32_t value)
1767 {
1768 BWN_ASSERT_LOCKED(mac->mac_sc);
1769
1770 if (way == BWN_SHARED) {
1771 KASSERT((offset & 0x0001) == 0,
1772 ("%s:%d warn", __func__, __LINE__));
1773 if (offset & 0x0003) {
1774 bwn_shm_ctlword(mac, way, offset >> 2);
1775 BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED,
1776 (value >> 16) & 0xffff);
1777 bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1778 BWN_WRITE_2(mac, BWN_SHM_DATA, value & 0xffff);
1779 return;
1780 }
1781 offset >>= 2;
1782 }
1783 bwn_shm_ctlword(mac, way, offset);
1784 BWN_WRITE_4(mac, BWN_SHM_DATA, value);
1785 }
1786
1787 void
bwn_shm_write_2(struct bwn_mac * mac,uint16_t way,uint16_t offset,uint16_t value)1788 bwn_shm_write_2(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1789 uint16_t value)
1790 {
1791 BWN_ASSERT_LOCKED(mac->mac_sc);
1792
1793 if (way == BWN_SHARED) {
1794 KASSERT((offset & 0x0001) == 0,
1795 ("%s:%d warn", __func__, __LINE__));
1796 if (offset & 0x0003) {
1797 bwn_shm_ctlword(mac, way, offset >> 2);
1798 BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED, value);
1799 return;
1800 }
1801 offset >>= 2;
1802 }
1803 bwn_shm_ctlword(mac, way, offset);
1804 BWN_WRITE_2(mac, BWN_SHM_DATA, value);
1805 }
1806
1807 static void
bwn_addchannels(struct ieee80211_channel chans[],int maxchans,int * nchans,const struct bwn_channelinfo * ci,const uint8_t bands[])1808 bwn_addchannels(struct ieee80211_channel chans[], int maxchans, int *nchans,
1809 const struct bwn_channelinfo *ci, const uint8_t bands[])
1810 {
1811 int i, error;
1812
1813 for (i = 0, error = 0; i < ci->nchannels && error == 0; i++) {
1814 const struct bwn_channel *hc = &ci->channels[i];
1815
1816 error = ieee80211_add_channel(chans, maxchans, nchans,
1817 hc->ieee, hc->freq, hc->maxTxPow, 0, bands);
1818 }
1819 }
1820
1821 static int
bwn_raw_xmit(struct ieee80211_node * ni,struct mbuf * m,const struct ieee80211_bpf_params * params)1822 bwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
1823 const struct ieee80211_bpf_params *params)
1824 {
1825 struct ieee80211com *ic = ni->ni_ic;
1826 struct bwn_softc *sc = ic->ic_softc;
1827 struct bwn_mac *mac = sc->sc_curmac;
1828 int error;
1829
1830 if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0 ||
1831 mac->mac_status < BWN_MAC_STATUS_STARTED) {
1832 m_freem(m);
1833 return (ENETDOWN);
1834 }
1835
1836 BWN_LOCK(sc);
1837 if (bwn_tx_isfull(sc, m)) {
1838 m_freem(m);
1839 BWN_UNLOCK(sc);
1840 return (ENOBUFS);
1841 }
1842
1843 error = bwn_tx_start(sc, ni, m);
1844 if (error == 0)
1845 sc->sc_watchdog_timer = 5;
1846 BWN_UNLOCK(sc);
1847 return (error);
1848 }
1849
1850 /*
1851 * Callback from the 802.11 layer to update the slot time
1852 * based on the current setting. We use it to notify the
1853 * firmware of ERP changes and the f/w takes care of things
1854 * like slot time and preamble.
1855 */
1856 static void
bwn_updateslot(struct ieee80211com * ic)1857 bwn_updateslot(struct ieee80211com *ic)
1858 {
1859 struct bwn_softc *sc = ic->ic_softc;
1860 struct bwn_mac *mac;
1861
1862 BWN_LOCK(sc);
1863 if (sc->sc_flags & BWN_FLAG_RUNNING) {
1864 mac = (struct bwn_mac *)sc->sc_curmac;
1865 bwn_set_slot_time(mac, IEEE80211_GET_SLOTTIME(ic));
1866 }
1867 BWN_UNLOCK(sc);
1868 }
1869
1870 /*
1871 * Callback from the 802.11 layer after a promiscuous mode change.
1872 * Note this interface does not check the operating mode as this
1873 * is an internal callback and we are expected to honor the current
1874 * state (e.g. this is used for setting the interface in promiscuous
1875 * mode when operating in hostap mode to do ACS).
1876 */
1877 static void
bwn_update_promisc(struct ieee80211com * ic)1878 bwn_update_promisc(struct ieee80211com *ic)
1879 {
1880 struct bwn_softc *sc = ic->ic_softc;
1881 struct bwn_mac *mac = sc->sc_curmac;
1882
1883 BWN_LOCK(sc);
1884 mac = sc->sc_curmac;
1885 if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
1886 if (ic->ic_promisc > 0)
1887 sc->sc_filters |= BWN_MACCTL_PROMISC;
1888 else
1889 sc->sc_filters &= ~BWN_MACCTL_PROMISC;
1890 bwn_set_opmode(mac);
1891 }
1892 BWN_UNLOCK(sc);
1893 }
1894
1895 /*
1896 * Callback from the 802.11 layer to update WME parameters.
1897 */
1898 static int
bwn_wme_update(struct ieee80211com * ic)1899 bwn_wme_update(struct ieee80211com *ic)
1900 {
1901 struct bwn_softc *sc = ic->ic_softc;
1902 struct bwn_mac *mac = sc->sc_curmac;
1903 struct chanAccParams chp;
1904 struct wmeParams *wmep;
1905 int i;
1906
1907 ieee80211_wme_ic_getparams(ic, &chp);
1908
1909 BWN_LOCK(sc);
1910 mac = sc->sc_curmac;
1911 if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
1912 bwn_mac_suspend(mac);
1913 for (i = 0; i < N(sc->sc_wmeParams); i++) {
1914 wmep = &chp.cap_wmeParams[i];
1915 bwn_wme_loadparams(mac, wmep, bwn_wme_shm_offsets[i]);
1916 }
1917 bwn_mac_enable(mac);
1918 }
1919 BWN_UNLOCK(sc);
1920 return (0);
1921 }
1922
1923 static void
bwn_scan_start(struct ieee80211com * ic)1924 bwn_scan_start(struct ieee80211com *ic)
1925 {
1926 struct bwn_softc *sc = ic->ic_softc;
1927 struct bwn_mac *mac;
1928
1929 BWN_LOCK(sc);
1930 mac = sc->sc_curmac;
1931 if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
1932 sc->sc_filters |= BWN_MACCTL_BEACON_PROMISC;
1933 bwn_set_opmode(mac);
1934 /* disable CFP update during scan */
1935 bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_SKIP_CFP_UPDATE);
1936 }
1937 BWN_UNLOCK(sc);
1938 }
1939
1940 static void
bwn_scan_end(struct ieee80211com * ic)1941 bwn_scan_end(struct ieee80211com *ic)
1942 {
1943 struct bwn_softc *sc = ic->ic_softc;
1944 struct bwn_mac *mac;
1945
1946 BWN_LOCK(sc);
1947 mac = sc->sc_curmac;
1948 if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
1949 sc->sc_filters &= ~BWN_MACCTL_BEACON_PROMISC;
1950 bwn_set_opmode(mac);
1951 bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_SKIP_CFP_UPDATE);
1952 }
1953 BWN_UNLOCK(sc);
1954 }
1955
1956 static void
bwn_set_channel(struct ieee80211com * ic)1957 bwn_set_channel(struct ieee80211com *ic)
1958 {
1959 struct bwn_softc *sc = ic->ic_softc;
1960 struct bwn_mac *mac = sc->sc_curmac;
1961 struct bwn_phy *phy = &mac->mac_phy;
1962 int chan, error;
1963
1964 BWN_LOCK(sc);
1965
1966 error = bwn_switch_band(sc, ic->ic_curchan);
1967 if (error)
1968 goto fail;
1969 bwn_mac_suspend(mac);
1970 bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
1971 chan = ieee80211_chan2ieee(ic, ic->ic_curchan);
1972 if (chan != phy->chan)
1973 bwn_switch_channel(mac, chan);
1974
1975 /* TX power level */
1976 if (ic->ic_curchan->ic_maxpower != 0 &&
1977 ic->ic_curchan->ic_maxpower != phy->txpower) {
1978 phy->txpower = ic->ic_curchan->ic_maxpower / 2;
1979 bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME |
1980 BWN_TXPWR_IGNORE_TSSI);
1981 }
1982
1983 bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
1984 if (phy->set_antenna)
1985 phy->set_antenna(mac, BWN_ANT_DEFAULT);
1986
1987 if (sc->sc_rf_enabled != phy->rf_on) {
1988 if (sc->sc_rf_enabled) {
1989 bwn_rf_turnon(mac);
1990 if (!(mac->mac_flags & BWN_MAC_FLAG_RADIO_ON))
1991 device_printf(sc->sc_dev,
1992 "please turn on the RF switch\n");
1993 } else
1994 bwn_rf_turnoff(mac);
1995 }
1996
1997 bwn_mac_enable(mac);
1998
1999 fail:
2000 BWN_UNLOCK(sc);
2001 }
2002
2003 static struct ieee80211vap *
bwn_vap_create(struct ieee80211com * ic,const char name[IFNAMSIZ],int unit,enum ieee80211_opmode opmode,int flags,const uint8_t bssid[IEEE80211_ADDR_LEN],const uint8_t mac[IEEE80211_ADDR_LEN])2004 bwn_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
2005 enum ieee80211_opmode opmode, int flags,
2006 const uint8_t bssid[IEEE80211_ADDR_LEN],
2007 const uint8_t mac[IEEE80211_ADDR_LEN])
2008 {
2009 struct ieee80211vap *vap;
2010 struct bwn_vap *bvp;
2011
2012 switch (opmode) {
2013 case IEEE80211_M_HOSTAP:
2014 case IEEE80211_M_MBSS:
2015 case IEEE80211_M_STA:
2016 case IEEE80211_M_WDS:
2017 case IEEE80211_M_MONITOR:
2018 case IEEE80211_M_IBSS:
2019 case IEEE80211_M_AHDEMO:
2020 break;
2021 default:
2022 return (NULL);
2023 }
2024
2025 bvp = malloc(sizeof(struct bwn_vap), M_80211_VAP, M_WAITOK | M_ZERO);
2026 vap = &bvp->bv_vap;
2027 ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid);
2028 /* override with driver methods */
2029 bvp->bv_newstate = vap->iv_newstate;
2030 vap->iv_newstate = bwn_newstate;
2031
2032 /* override max aid so sta's cannot assoc when we're out of sta id's */
2033 vap->iv_max_aid = BWN_STAID_MAX;
2034
2035 ieee80211_ratectl_init(vap);
2036
2037 /* complete setup */
2038 ieee80211_vap_attach(vap, ieee80211_media_change,
2039 ieee80211_media_status, mac);
2040 return (vap);
2041 }
2042
2043 static void
bwn_vap_delete(struct ieee80211vap * vap)2044 bwn_vap_delete(struct ieee80211vap *vap)
2045 {
2046 struct bwn_vap *bvp = BWN_VAP(vap);
2047
2048 ieee80211_ratectl_deinit(vap);
2049 ieee80211_vap_detach(vap);
2050 free(bvp, M_80211_VAP);
2051 }
2052
2053 static int
bwn_init(struct bwn_softc * sc)2054 bwn_init(struct bwn_softc *sc)
2055 {
2056 struct bwn_mac *mac;
2057 int error;
2058
2059 BWN_ASSERT_LOCKED(sc);
2060
2061 DPRINTF(sc, BWN_DEBUG_RESET, "%s: called\n", __func__);
2062
2063 bzero(sc->sc_bssid, IEEE80211_ADDR_LEN);
2064 sc->sc_flags |= BWN_FLAG_NEED_BEACON_TP;
2065 sc->sc_filters = 0;
2066 bwn_wme_clear(sc);
2067 sc->sc_beacons[0] = sc->sc_beacons[1] = 0;
2068 sc->sc_rf_enabled = 1;
2069
2070 mac = sc->sc_curmac;
2071 if (mac->mac_status == BWN_MAC_STATUS_UNINIT) {
2072 error = bwn_core_init(mac);
2073 if (error != 0)
2074 return (error);
2075 }
2076 if (mac->mac_status == BWN_MAC_STATUS_INITED)
2077 bwn_core_start(mac);
2078
2079 bwn_set_opmode(mac);
2080 bwn_set_pretbtt(mac);
2081 bwn_spu_setdelay(mac, 0);
2082 bwn_set_macaddr(mac);
2083
2084 sc->sc_flags |= BWN_FLAG_RUNNING;
2085 callout_reset(&sc->sc_rfswitch_ch, hz, bwn_rfswitch, sc);
2086 callout_reset(&sc->sc_watchdog_ch, hz, bwn_watchdog, sc);
2087
2088 return (0);
2089 }
2090
2091 static void
bwn_stop(struct bwn_softc * sc)2092 bwn_stop(struct bwn_softc *sc)
2093 {
2094 struct bwn_mac *mac = sc->sc_curmac;
2095
2096 BWN_ASSERT_LOCKED(sc);
2097
2098 DPRINTF(sc, BWN_DEBUG_RESET, "%s: called\n", __func__);
2099
2100 if (mac->mac_status >= BWN_MAC_STATUS_INITED) {
2101 /* XXX FIXME opmode not based on VAP */
2102 bwn_set_opmode(mac);
2103 bwn_set_macaddr(mac);
2104 }
2105
2106 if (mac->mac_status >= BWN_MAC_STATUS_STARTED)
2107 bwn_core_stop(mac);
2108
2109 callout_stop(&sc->sc_led_blink_ch);
2110 sc->sc_led_blinking = 0;
2111
2112 bwn_core_exit(mac);
2113 sc->sc_rf_enabled = 0;
2114
2115 sc->sc_flags &= ~BWN_FLAG_RUNNING;
2116 }
2117
2118 static void
bwn_wme_clear(struct bwn_softc * sc)2119 bwn_wme_clear(struct bwn_softc *sc)
2120 {
2121 struct wmeParams *p;
2122 unsigned int i;
2123
2124 KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
2125 ("%s:%d: fail", __func__, __LINE__));
2126
2127 for (i = 0; i < N(sc->sc_wmeParams); i++) {
2128 p = &(sc->sc_wmeParams[i]);
2129
2130 switch (bwn_wme_shm_offsets[i]) {
2131 case BWN_WME_VOICE:
2132 p->wmep_txopLimit = 0;
2133 p->wmep_aifsn = 2;
2134 /* XXX FIXME: log2(cwmin) */
2135 p->wmep_logcwmin =
2136 _IEEE80211_MASKSHIFT(0x0001, WME_PARAM_LOGCWMIN);
2137 p->wmep_logcwmax =
2138 _IEEE80211_MASKSHIFT(0x0001, WME_PARAM_LOGCWMAX);
2139 break;
2140 case BWN_WME_VIDEO:
2141 p->wmep_txopLimit = 0;
2142 p->wmep_aifsn = 2;
2143 /* XXX FIXME: log2(cwmin) */
2144 p->wmep_logcwmin =
2145 _IEEE80211_MASKSHIFT(0x0001, WME_PARAM_LOGCWMIN);
2146 p->wmep_logcwmax =
2147 _IEEE80211_MASKSHIFT(0x0001, WME_PARAM_LOGCWMAX);
2148 break;
2149 case BWN_WME_BESTEFFORT:
2150 p->wmep_txopLimit = 0;
2151 p->wmep_aifsn = 3;
2152 /* XXX FIXME: log2(cwmin) */
2153 p->wmep_logcwmin =
2154 _IEEE80211_MASKSHIFT(0x0001, WME_PARAM_LOGCWMIN);
2155 p->wmep_logcwmax =
2156 _IEEE80211_MASKSHIFT(0x03ff, WME_PARAM_LOGCWMAX);
2157 break;
2158 case BWN_WME_BACKGROUND:
2159 p->wmep_txopLimit = 0;
2160 p->wmep_aifsn = 7;
2161 /* XXX FIXME: log2(cwmin) */
2162 p->wmep_logcwmin =
2163 _IEEE80211_MASKSHIFT(0x0001, WME_PARAM_LOGCWMIN);
2164 p->wmep_logcwmax =
2165 _IEEE80211_MASKSHIFT(0x03ff, WME_PARAM_LOGCWMAX);
2166 break;
2167 default:
2168 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
2169 }
2170 }
2171 }
2172
2173 static int
bwn_core_forceclk(struct bwn_mac * mac,bool force)2174 bwn_core_forceclk(struct bwn_mac *mac, bool force)
2175 {
2176 struct bwn_softc *sc;
2177 bhnd_clock clock;
2178 int error;
2179
2180 sc = mac->mac_sc;
2181
2182 /* On PMU equipped devices, we do not need to force the HT clock */
2183 if (sc->sc_pmu != NULL)
2184 return (0);
2185
2186 /* Issue a PMU clock request */
2187 if (force)
2188 clock = BHND_CLOCK_HT;
2189 else
2190 clock = BHND_CLOCK_DYN;
2191
2192 if ((error = bhnd_request_clock(sc->sc_dev, clock))) {
2193 device_printf(sc->sc_dev, "%d clock request failed: %d\n",
2194 clock, error);
2195 return (error);
2196 }
2197
2198 return (0);
2199 }
2200
2201 static int
bwn_core_init(struct bwn_mac * mac)2202 bwn_core_init(struct bwn_mac *mac)
2203 {
2204 struct bwn_softc *sc = mac->mac_sc;
2205 uint64_t hf;
2206 int error;
2207
2208 KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
2209 ("%s:%d: fail", __func__, __LINE__));
2210
2211 DPRINTF(mac->mac_sc, BWN_DEBUG_RESET, "%s: called\n", __func__);
2212
2213 if ((error = bwn_core_forceclk(mac, true)))
2214 return (error);
2215
2216 if (bhnd_is_hw_suspended(sc->sc_dev)) {
2217 if ((error = bwn_reset_core(mac, mac->mac_phy.gmode)))
2218 goto fail0;
2219 }
2220
2221 mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
2222 mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
2223 mac->mac_phy.hwpctl = (bwn_hwpctl) ? 1 : 0;
2224 BWN_GETTIME(mac->mac_phy.nexttime);
2225 mac->mac_phy.txerrors = BWN_TXERROR_MAX;
2226 bzero(&mac->mac_stats, sizeof(mac->mac_stats));
2227 mac->mac_stats.link_noise = -95;
2228 mac->mac_reason_intr = 0;
2229 bzero(mac->mac_reason, sizeof(mac->mac_reason));
2230 mac->mac_intr_mask = BWN_INTR_MASKTEMPLATE;
2231 #ifdef BWN_DEBUG
2232 if (sc->sc_debug & BWN_DEBUG_XMIT)
2233 mac->mac_intr_mask &= ~BWN_INTR_PHY_TXERR;
2234 #endif
2235 mac->mac_suspended = 1;
2236 mac->mac_task_state = 0;
2237 memset(&mac->mac_noise, 0, sizeof(mac->mac_noise));
2238
2239 mac->mac_phy.init_pre(mac);
2240
2241 bwn_bt_disable(mac);
2242 if (mac->mac_phy.prepare_hw) {
2243 error = mac->mac_phy.prepare_hw(mac);
2244 if (error)
2245 goto fail0;
2246 }
2247 DPRINTF(mac->mac_sc, BWN_DEBUG_RESET, "%s: chip_init\n", __func__);
2248 error = bwn_chip_init(mac);
2249 if (error)
2250 goto fail0;
2251 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_COREREV,
2252 bhnd_get_hwrev(sc->sc_dev));
2253 hf = bwn_hf_read(mac);
2254 if (mac->mac_phy.type == BWN_PHYTYPE_G) {
2255 hf |= BWN_HF_GPHY_SYM_WORKAROUND;
2256 if (sc->sc_board_info.board_flags & BHND_BFL_PACTRL)
2257 hf |= BWN_HF_PAGAINBOOST_OFDM_ON;
2258 if (mac->mac_phy.rev == 1)
2259 hf |= BWN_HF_GPHY_DC_CANCELFILTER;
2260 }
2261 if (mac->mac_phy.rf_ver == 0x2050) {
2262 if (mac->mac_phy.rf_rev < 6)
2263 hf |= BWN_HF_FORCE_VCO_RECALC;
2264 if (mac->mac_phy.rf_rev == 6)
2265 hf |= BWN_HF_4318_TSSI;
2266 }
2267 if (sc->sc_board_info.board_flags & BHND_BFL_NOPLLDOWN)
2268 hf |= BWN_HF_SLOWCLOCK_REQ_OFF;
2269 if (sc->sc_quirks & BWN_QUIRK_UCODE_SLOWCLOCK_WAR)
2270 hf |= BWN_HF_PCI_SLOWCLOCK_WORKAROUND;
2271 hf &= ~BWN_HF_SKIP_CFP_UPDATE;
2272 bwn_hf_write(mac, hf);
2273
2274 /* Tell the firmware about the MAC capabilities */
2275 if (bhnd_get_hwrev(sc->sc_dev) >= 13) {
2276 uint32_t cap;
2277 cap = BWN_READ_4(mac, BWN_MAC_HW_CAP);
2278 DPRINTF(sc, BWN_DEBUG_RESET,
2279 "%s: hw capabilities: 0x%08x\n",
2280 __func__, cap);
2281 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_MACHW_L,
2282 cap & 0xffff);
2283 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_MACHW_H,
2284 (cap >> 16) & 0xffff);
2285 }
2286
2287 bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
2288 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SHORT_RETRY_FALLBACK, 3);
2289 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_LONG_RETRY_FALLBACK, 2);
2290 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_MAXTIME, 1);
2291
2292 bwn_rate_init(mac);
2293 bwn_set_phytxctl(mac);
2294
2295 bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MIN,
2296 (mac->mac_phy.type == BWN_PHYTYPE_B) ? 0x1f : 0xf);
2297 bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MAX, 0x3ff);
2298
2299 if (sc->sc_quirks & BWN_QUIRK_NODMA)
2300 bwn_pio_init(mac);
2301 else
2302 bwn_dma_init(mac);
2303 bwn_wme_init(mac);
2304 bwn_spu_setdelay(mac, 1);
2305 bwn_bt_enable(mac);
2306
2307 DPRINTF(mac->mac_sc, BWN_DEBUG_RESET, "%s: powerup\n", __func__);
2308 if (sc->sc_board_info.board_flags & BHND_BFL_NOPLLDOWN)
2309 bwn_core_forceclk(mac, true);
2310 else
2311 bwn_core_forceclk(mac, false);
2312
2313 bwn_set_macaddr(mac);
2314 bwn_crypt_init(mac);
2315
2316 /* XXX LED initializatin */
2317
2318 mac->mac_status = BWN_MAC_STATUS_INITED;
2319
2320 DPRINTF(mac->mac_sc, BWN_DEBUG_RESET, "%s: done\n", __func__);
2321 return (error);
2322
2323 fail0:
2324 bhnd_suspend_hw(sc->sc_dev, 0);
2325 KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
2326 ("%s:%d: fail", __func__, __LINE__));
2327 DPRINTF(mac->mac_sc, BWN_DEBUG_RESET, "%s: fail\n", __func__);
2328 return (error);
2329 }
2330
2331 static void
bwn_core_start(struct bwn_mac * mac)2332 bwn_core_start(struct bwn_mac *mac)
2333 {
2334 struct bwn_softc *sc = mac->mac_sc;
2335 uint32_t tmp;
2336
2337 KASSERT(mac->mac_status == BWN_MAC_STATUS_INITED,
2338 ("%s:%d: fail", __func__, __LINE__));
2339
2340 if (bhnd_get_hwrev(sc->sc_dev) < 5)
2341 return;
2342
2343 while (1) {
2344 tmp = BWN_READ_4(mac, BWN_XMITSTAT_0);
2345 if (!(tmp & 0x00000001))
2346 break;
2347 tmp = BWN_READ_4(mac, BWN_XMITSTAT_1);
2348 }
2349
2350 bwn_mac_enable(mac);
2351 BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
2352 callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
2353
2354 mac->mac_status = BWN_MAC_STATUS_STARTED;
2355 }
2356
2357 static void
bwn_core_exit(struct bwn_mac * mac)2358 bwn_core_exit(struct bwn_mac *mac)
2359 {
2360 struct bwn_softc *sc = mac->mac_sc;
2361 uint32_t macctl;
2362
2363 BWN_ASSERT_LOCKED(mac->mac_sc);
2364
2365 KASSERT(mac->mac_status <= BWN_MAC_STATUS_INITED,
2366 ("%s:%d: fail", __func__, __LINE__));
2367
2368 if (mac->mac_status != BWN_MAC_STATUS_INITED)
2369 return;
2370 mac->mac_status = BWN_MAC_STATUS_UNINIT;
2371
2372 macctl = BWN_READ_4(mac, BWN_MACCTL);
2373 macctl &= ~BWN_MACCTL_MCODE_RUN;
2374 macctl |= BWN_MACCTL_MCODE_JMP0;
2375 BWN_WRITE_4(mac, BWN_MACCTL, macctl);
2376
2377 bwn_dma_stop(mac);
2378 bwn_pio_stop(mac);
2379 bwn_chip_exit(mac);
2380 mac->mac_phy.switch_analog(mac, 0);
2381 bhnd_suspend_hw(sc->sc_dev, 0);
2382 }
2383
2384 static void
bwn_bt_disable(struct bwn_mac * mac)2385 bwn_bt_disable(struct bwn_mac *mac)
2386 {
2387 struct bwn_softc *sc = mac->mac_sc;
2388
2389 (void)sc;
2390 /* XXX do nothing yet */
2391 }
2392
2393 static int
bwn_chip_init(struct bwn_mac * mac)2394 bwn_chip_init(struct bwn_mac *mac)
2395 {
2396 struct bwn_softc *sc = mac->mac_sc;
2397 struct bwn_phy *phy = &mac->mac_phy;
2398 uint32_t macctl;
2399 u_int delay;
2400 int error;
2401
2402 macctl = BWN_MACCTL_IHR_ON | BWN_MACCTL_SHM_ON | BWN_MACCTL_STA;
2403 if (phy->gmode)
2404 macctl |= BWN_MACCTL_GMODE;
2405 BWN_WRITE_4(mac, BWN_MACCTL, macctl);
2406
2407 error = bwn_fw_fillinfo(mac);
2408 if (error)
2409 return (error);
2410 error = bwn_fw_loaducode(mac);
2411 if (error)
2412 return (error);
2413
2414 error = bwn_gpio_init(mac);
2415 if (error)
2416 return (error);
2417
2418 error = bwn_fw_loadinitvals(mac);
2419 if (error)
2420 return (error);
2421
2422 phy->switch_analog(mac, 1);
2423 error = bwn_phy_init(mac);
2424 if (error)
2425 return (error);
2426
2427 if (phy->set_im)
2428 phy->set_im(mac, BWN_IMMODE_NONE);
2429 if (phy->set_antenna)
2430 phy->set_antenna(mac, BWN_ANT_DEFAULT);
2431 bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
2432
2433 if (phy->type == BWN_PHYTYPE_B)
2434 BWN_WRITE_2(mac, 0x005e, BWN_READ_2(mac, 0x005e) | 0x0004);
2435 BWN_WRITE_4(mac, 0x0100, 0x01000000);
2436 if (bhnd_get_hwrev(sc->sc_dev) < 5)
2437 BWN_WRITE_4(mac, 0x010c, 0x01000000);
2438
2439 BWN_WRITE_4(mac, BWN_MACCTL,
2440 BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_STA);
2441 BWN_WRITE_4(mac, BWN_MACCTL,
2442 BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_STA);
2443 bwn_shm_write_2(mac, BWN_SHARED, 0x0074, 0x0000);
2444
2445 bwn_set_opmode(mac);
2446 if (bhnd_get_hwrev(sc->sc_dev) < 3) {
2447 BWN_WRITE_2(mac, 0x060e, 0x0000);
2448 BWN_WRITE_2(mac, 0x0610, 0x8000);
2449 BWN_WRITE_2(mac, 0x0604, 0x0000);
2450 BWN_WRITE_2(mac, 0x0606, 0x0200);
2451 } else {
2452 BWN_WRITE_4(mac, 0x0188, 0x80000000);
2453 BWN_WRITE_4(mac, 0x018c, 0x02000000);
2454 }
2455 BWN_WRITE_4(mac, BWN_INTR_REASON, 0x00004000);
2456 BWN_WRITE_4(mac, BWN_DMA0_INTR_MASK, 0x0001dc00);
2457 BWN_WRITE_4(mac, BWN_DMA1_INTR_MASK, 0x0000dc00);
2458 BWN_WRITE_4(mac, BWN_DMA2_INTR_MASK, 0x0000dc00);
2459 BWN_WRITE_4(mac, BWN_DMA3_INTR_MASK, 0x0001dc00);
2460 BWN_WRITE_4(mac, BWN_DMA4_INTR_MASK, 0x0000dc00);
2461 BWN_WRITE_4(mac, BWN_DMA5_INTR_MASK, 0x0000dc00);
2462
2463 bwn_mac_phy_clock_set(mac, true);
2464
2465 /* Provide the HT clock transition latency to the MAC core */
2466 error = bhnd_get_clock_latency(sc->sc_dev, BHND_CLOCK_HT, &delay);
2467 if (error) {
2468 device_printf(sc->sc_dev, "failed to fetch HT clock latency: "
2469 "%d\n", error);
2470 return (error);
2471 }
2472
2473 if (delay > UINT16_MAX) {
2474 device_printf(sc->sc_dev, "invalid HT clock latency: %u\n",
2475 delay);
2476 return (ENXIO);
2477 }
2478
2479 BWN_WRITE_2(mac, BWN_POWERUP_DELAY, delay);
2480 return (0);
2481 }
2482
2483 /* read hostflags */
2484 uint64_t
bwn_hf_read(struct bwn_mac * mac)2485 bwn_hf_read(struct bwn_mac *mac)
2486 {
2487 uint64_t ret;
2488
2489 ret = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFHI);
2490 ret <<= 16;
2491 ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFMI);
2492 ret <<= 16;
2493 ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO);
2494 return (ret);
2495 }
2496
2497 void
bwn_hf_write(struct bwn_mac * mac,uint64_t value)2498 bwn_hf_write(struct bwn_mac *mac, uint64_t value)
2499 {
2500
2501 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFLO,
2502 (value & 0x00000000ffffull));
2503 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFMI,
2504 (value & 0x0000ffff0000ull) >> 16);
2505 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFHI,
2506 (value & 0xffff00000000ULL) >> 32);
2507 }
2508
2509 static void
bwn_set_txretry(struct bwn_mac * mac,int s,int l)2510 bwn_set_txretry(struct bwn_mac *mac, int s, int l)
2511 {
2512
2513 bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_SHORT_RETRY, MIN(s, 0xf));
2514 bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_LONG_RETRY, MIN(l, 0xf));
2515 }
2516
2517 static void
bwn_rate_init(struct bwn_mac * mac)2518 bwn_rate_init(struct bwn_mac *mac)
2519 {
2520
2521 switch (mac->mac_phy.type) {
2522 case BWN_PHYTYPE_A:
2523 case BWN_PHYTYPE_G:
2524 case BWN_PHYTYPE_LP:
2525 case BWN_PHYTYPE_N:
2526 bwn_rate_write(mac, BWN_OFDM_RATE_6MB, 1);
2527 bwn_rate_write(mac, BWN_OFDM_RATE_12MB, 1);
2528 bwn_rate_write(mac, BWN_OFDM_RATE_18MB, 1);
2529 bwn_rate_write(mac, BWN_OFDM_RATE_24MB, 1);
2530 bwn_rate_write(mac, BWN_OFDM_RATE_36MB, 1);
2531 bwn_rate_write(mac, BWN_OFDM_RATE_48MB, 1);
2532 bwn_rate_write(mac, BWN_OFDM_RATE_54MB, 1);
2533 if (mac->mac_phy.type == BWN_PHYTYPE_A)
2534 break;
2535 /* FALLTHROUGH */
2536 case BWN_PHYTYPE_B:
2537 bwn_rate_write(mac, BWN_CCK_RATE_1MB, 0);
2538 bwn_rate_write(mac, BWN_CCK_RATE_2MB, 0);
2539 bwn_rate_write(mac, BWN_CCK_RATE_5MB, 0);
2540 bwn_rate_write(mac, BWN_CCK_RATE_11MB, 0);
2541 break;
2542 default:
2543 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
2544 }
2545 }
2546
2547 static void
bwn_rate_write(struct bwn_mac * mac,uint16_t rate,int ofdm)2548 bwn_rate_write(struct bwn_mac *mac, uint16_t rate, int ofdm)
2549 {
2550 uint16_t offset;
2551
2552 if (ofdm) {
2553 offset = 0x480;
2554 offset += (bwn_plcp_getofdm(rate) & 0x000f) * 2;
2555 } else {
2556 offset = 0x4c0;
2557 offset += (bwn_plcp_getcck(rate) & 0x000f) * 2;
2558 }
2559 bwn_shm_write_2(mac, BWN_SHARED, offset + 0x20,
2560 bwn_shm_read_2(mac, BWN_SHARED, offset));
2561 }
2562
2563 static uint8_t
bwn_plcp_getcck(const uint8_t bitrate)2564 bwn_plcp_getcck(const uint8_t bitrate)
2565 {
2566
2567 switch (bitrate) {
2568 case BWN_CCK_RATE_1MB:
2569 return (0x0a);
2570 case BWN_CCK_RATE_2MB:
2571 return (0x14);
2572 case BWN_CCK_RATE_5MB:
2573 return (0x37);
2574 case BWN_CCK_RATE_11MB:
2575 return (0x6e);
2576 }
2577 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
2578 return (0);
2579 }
2580
2581 static uint8_t
bwn_plcp_getofdm(const uint8_t bitrate)2582 bwn_plcp_getofdm(const uint8_t bitrate)
2583 {
2584
2585 switch (bitrate) {
2586 case BWN_OFDM_RATE_6MB:
2587 return (0xb);
2588 case BWN_OFDM_RATE_9MB:
2589 return (0xf);
2590 case BWN_OFDM_RATE_12MB:
2591 return (0xa);
2592 case BWN_OFDM_RATE_18MB:
2593 return (0xe);
2594 case BWN_OFDM_RATE_24MB:
2595 return (0x9);
2596 case BWN_OFDM_RATE_36MB:
2597 return (0xd);
2598 case BWN_OFDM_RATE_48MB:
2599 return (0x8);
2600 case BWN_OFDM_RATE_54MB:
2601 return (0xc);
2602 }
2603 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
2604 return (0);
2605 }
2606
2607 static void
bwn_set_phytxctl(struct bwn_mac * mac)2608 bwn_set_phytxctl(struct bwn_mac *mac)
2609 {
2610 uint16_t ctl;
2611
2612 ctl = (BWN_TX_PHY_ENC_CCK | BWN_TX_PHY_ANT01AUTO |
2613 BWN_TX_PHY_TXPWR);
2614 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_BEACON_PHYCTL, ctl);
2615 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, ctl);
2616 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, ctl);
2617 }
2618
2619 static void
bwn_pio_init(struct bwn_mac * mac)2620 bwn_pio_init(struct bwn_mac *mac)
2621 {
2622 struct bwn_pio *pio = &mac->mac_method.pio;
2623
2624 BWN_WRITE_4(mac, BWN_MACCTL, BWN_READ_4(mac, BWN_MACCTL)
2625 & ~BWN_MACCTL_BIGENDIAN);
2626 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RX_PADOFFSET, 0);
2627
2628 bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BK], 0);
2629 bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BE], 1);
2630 bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VI], 2);
2631 bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VO], 3);
2632 bwn_pio_set_txqueue(mac, &pio->mcast, 4);
2633 bwn_pio_setupqueue_rx(mac, &pio->rx, 0);
2634 }
2635
2636 static void
bwn_pio_set_txqueue(struct bwn_mac * mac,struct bwn_pio_txqueue * tq,int index)2637 bwn_pio_set_txqueue(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
2638 int index)
2639 {
2640 struct bwn_pio_txpkt *tp;
2641 struct bwn_softc *sc = mac->mac_sc;
2642 unsigned int i;
2643
2644 tq->tq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_TXQOFFSET(mac);
2645 tq->tq_index = index;
2646
2647 tq->tq_free = BWN_PIO_MAX_TXPACKETS;
2648 if (bhnd_get_hwrev(sc->sc_dev) >= 8)
2649 tq->tq_size = 1920;
2650 else {
2651 tq->tq_size = bwn_pio_read_2(mac, tq, BWN_PIO_TXQBUFSIZE);
2652 tq->tq_size -= 80;
2653 }
2654
2655 TAILQ_INIT(&tq->tq_pktlist);
2656 for (i = 0; i < N(tq->tq_pkts); i++) {
2657 tp = &(tq->tq_pkts[i]);
2658 tp->tp_index = i;
2659 tp->tp_queue = tq;
2660 TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
2661 }
2662 }
2663
2664 static uint16_t
bwn_pio_idx2base(struct bwn_mac * mac,int index)2665 bwn_pio_idx2base(struct bwn_mac *mac, int index)
2666 {
2667 struct bwn_softc *sc = mac->mac_sc;
2668 static const uint16_t bases[] = {
2669 BWN_PIO_BASE0,
2670 BWN_PIO_BASE1,
2671 BWN_PIO_BASE2,
2672 BWN_PIO_BASE3,
2673 BWN_PIO_BASE4,
2674 BWN_PIO_BASE5,
2675 BWN_PIO_BASE6,
2676 BWN_PIO_BASE7,
2677 };
2678 static const uint16_t bases_rev11[] = {
2679 BWN_PIO11_BASE0,
2680 BWN_PIO11_BASE1,
2681 BWN_PIO11_BASE2,
2682 BWN_PIO11_BASE3,
2683 BWN_PIO11_BASE4,
2684 BWN_PIO11_BASE5,
2685 };
2686
2687 if (bhnd_get_hwrev(sc->sc_dev) >= 11) {
2688 if (index >= N(bases_rev11))
2689 device_printf(sc->sc_dev, "%s: warning\n", __func__);
2690 return (bases_rev11[index]);
2691 }
2692 if (index >= N(bases))
2693 device_printf(sc->sc_dev, "%s: warning\n", __func__);
2694 return (bases[index]);
2695 }
2696
2697 static void
bwn_pio_setupqueue_rx(struct bwn_mac * mac,struct bwn_pio_rxqueue * prq,int index)2698 bwn_pio_setupqueue_rx(struct bwn_mac *mac, struct bwn_pio_rxqueue *prq,
2699 int index)
2700 {
2701 struct bwn_softc *sc = mac->mac_sc;
2702
2703 prq->prq_mac = mac;
2704 prq->prq_rev = bhnd_get_hwrev(sc->sc_dev);
2705 prq->prq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_RXQOFFSET(mac);
2706 bwn_dma_rxdirectfifo(mac, index, 1);
2707 }
2708
2709 static void
bwn_destroy_pioqueue_tx(struct bwn_pio_txqueue * tq)2710 bwn_destroy_pioqueue_tx(struct bwn_pio_txqueue *tq)
2711 {
2712 if (tq == NULL)
2713 return;
2714 bwn_pio_cancel_tx_packets(tq);
2715 }
2716
2717 static void
bwn_destroy_queue_tx(struct bwn_pio_txqueue * pio)2718 bwn_destroy_queue_tx(struct bwn_pio_txqueue *pio)
2719 {
2720
2721 bwn_destroy_pioqueue_tx(pio);
2722 }
2723
2724 static uint16_t
bwn_pio_read_2(struct bwn_mac * mac,struct bwn_pio_txqueue * tq,uint16_t offset)2725 bwn_pio_read_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
2726 uint16_t offset)
2727 {
2728
2729 return (BWN_READ_2(mac, tq->tq_base + offset));
2730 }
2731
2732 static void
bwn_dma_rxdirectfifo(struct bwn_mac * mac,int idx,uint8_t enable)2733 bwn_dma_rxdirectfifo(struct bwn_mac *mac, int idx, uint8_t enable)
2734 {
2735 uint32_t ctl;
2736 uint16_t base;
2737
2738 base = bwn_dma_base(mac->mac_dmatype, idx);
2739 if (mac->mac_dmatype == BHND_DMA_ADDR_64BIT) {
2740 ctl = BWN_READ_4(mac, base + BWN_DMA64_RXCTL);
2741 ctl &= ~BWN_DMA64_RXDIRECTFIFO;
2742 if (enable)
2743 ctl |= BWN_DMA64_RXDIRECTFIFO;
2744 BWN_WRITE_4(mac, base + BWN_DMA64_RXCTL, ctl);
2745 } else {
2746 ctl = BWN_READ_4(mac, base + BWN_DMA32_RXCTL);
2747 ctl &= ~BWN_DMA32_RXDIRECTFIFO;
2748 if (enable)
2749 ctl |= BWN_DMA32_RXDIRECTFIFO;
2750 BWN_WRITE_4(mac, base + BWN_DMA32_RXCTL, ctl);
2751 }
2752 }
2753
2754 static void
bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue * tq)2755 bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *tq)
2756 {
2757 struct bwn_pio_txpkt *tp;
2758 unsigned int i;
2759
2760 for (i = 0; i < N(tq->tq_pkts); i++) {
2761 tp = &(tq->tq_pkts[i]);
2762 if (tp->tp_m) {
2763 m_freem(tp->tp_m);
2764 tp->tp_m = NULL;
2765 }
2766 }
2767 }
2768
2769 static uint16_t
bwn_dma_base(int type,int controller_idx)2770 bwn_dma_base(int type, int controller_idx)
2771 {
2772 static const uint16_t map64[] = {
2773 BWN_DMA64_BASE0,
2774 BWN_DMA64_BASE1,
2775 BWN_DMA64_BASE2,
2776 BWN_DMA64_BASE3,
2777 BWN_DMA64_BASE4,
2778 BWN_DMA64_BASE5,
2779 };
2780 static const uint16_t map32[] = {
2781 BWN_DMA32_BASE0,
2782 BWN_DMA32_BASE1,
2783 BWN_DMA32_BASE2,
2784 BWN_DMA32_BASE3,
2785 BWN_DMA32_BASE4,
2786 BWN_DMA32_BASE5,
2787 };
2788
2789 if (type == BHND_DMA_ADDR_64BIT) {
2790 KASSERT(controller_idx >= 0 && controller_idx < N(map64),
2791 ("%s:%d: fail", __func__, __LINE__));
2792 return (map64[controller_idx]);
2793 }
2794 KASSERT(controller_idx >= 0 && controller_idx < N(map32),
2795 ("%s:%d: fail", __func__, __LINE__));
2796 return (map32[controller_idx]);
2797 }
2798
2799 static void
bwn_dma_init(struct bwn_mac * mac)2800 bwn_dma_init(struct bwn_mac *mac)
2801 {
2802 struct bwn_dma *dma = &mac->mac_method.dma;
2803
2804 /* setup TX DMA channels. */
2805 bwn_dma_setup(dma->wme[WME_AC_BK]);
2806 bwn_dma_setup(dma->wme[WME_AC_BE]);
2807 bwn_dma_setup(dma->wme[WME_AC_VI]);
2808 bwn_dma_setup(dma->wme[WME_AC_VO]);
2809 bwn_dma_setup(dma->mcast);
2810 /* setup RX DMA channel. */
2811 bwn_dma_setup(dma->rx);
2812 }
2813
2814 static struct bwn_dma_ring *
bwn_dma_ringsetup(struct bwn_mac * mac,int controller_index,int for_tx)2815 bwn_dma_ringsetup(struct bwn_mac *mac, int controller_index,
2816 int for_tx)
2817 {
2818 struct bwn_dma *dma = &mac->mac_method.dma;
2819 struct bwn_dma_ring *dr;
2820 struct bwn_dmadesc_generic *desc;
2821 struct bwn_dmadesc_meta *mt;
2822 struct bwn_softc *sc = mac->mac_sc;
2823 int error, i;
2824
2825 dr = malloc(sizeof(*dr), M_DEVBUF, M_NOWAIT | M_ZERO);
2826 if (dr == NULL)
2827 goto out;
2828 dr->dr_numslots = BWN_RXRING_SLOTS;
2829 if (for_tx)
2830 dr->dr_numslots = BWN_TXRING_SLOTS;
2831
2832 dr->dr_meta = malloc(dr->dr_numslots * sizeof(struct bwn_dmadesc_meta),
2833 M_DEVBUF, M_NOWAIT | M_ZERO);
2834 if (dr->dr_meta == NULL)
2835 goto fail0;
2836
2837 dr->dr_type = mac->mac_dmatype;
2838 dr->dr_mac = mac;
2839 dr->dr_base = bwn_dma_base(dr->dr_type, controller_index);
2840 dr->dr_index = controller_index;
2841 if (dr->dr_type == BHND_DMA_ADDR_64BIT) {
2842 dr->getdesc = bwn_dma_64_getdesc;
2843 dr->setdesc = bwn_dma_64_setdesc;
2844 dr->start_transfer = bwn_dma_64_start_transfer;
2845 dr->suspend = bwn_dma_64_suspend;
2846 dr->resume = bwn_dma_64_resume;
2847 dr->get_curslot = bwn_dma_64_get_curslot;
2848 dr->set_curslot = bwn_dma_64_set_curslot;
2849 } else {
2850 dr->getdesc = bwn_dma_32_getdesc;
2851 dr->setdesc = bwn_dma_32_setdesc;
2852 dr->start_transfer = bwn_dma_32_start_transfer;
2853 dr->suspend = bwn_dma_32_suspend;
2854 dr->resume = bwn_dma_32_resume;
2855 dr->get_curslot = bwn_dma_32_get_curslot;
2856 dr->set_curslot = bwn_dma_32_set_curslot;
2857 }
2858 if (for_tx) {
2859 dr->dr_tx = 1;
2860 dr->dr_curslot = -1;
2861 } else {
2862 if (dr->dr_index == 0) {
2863 switch (mac->mac_fw.fw_hdr_format) {
2864 case BWN_FW_HDR_351:
2865 case BWN_FW_HDR_410:
2866 dr->dr_rx_bufsize =
2867 BWN_DMA0_RX_BUFFERSIZE_FW351;
2868 dr->dr_frameoffset =
2869 BWN_DMA0_RX_FRAMEOFFSET_FW351;
2870 break;
2871 case BWN_FW_HDR_598:
2872 dr->dr_rx_bufsize =
2873 BWN_DMA0_RX_BUFFERSIZE_FW598;
2874 dr->dr_frameoffset =
2875 BWN_DMA0_RX_FRAMEOFFSET_FW598;
2876 break;
2877 }
2878 } else
2879 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
2880 }
2881
2882 error = bwn_dma_allocringmemory(dr);
2883 if (error)
2884 goto fail2;
2885
2886 if (for_tx) {
2887 /*
2888 * Assumption: BWN_TXRING_SLOTS can be divided by
2889 * BWN_TX_SLOTS_PER_FRAME
2890 */
2891 KASSERT(BWN_TXRING_SLOTS % BWN_TX_SLOTS_PER_FRAME == 0,
2892 ("%s:%d: fail", __func__, __LINE__));
2893
2894 dr->dr_txhdr_cache = contigmalloc(
2895 (dr->dr_numslots / BWN_TX_SLOTS_PER_FRAME) *
2896 BWN_MAXTXHDRSIZE, M_DEVBUF, M_ZERO,
2897 0, BUS_SPACE_MAXADDR, 8, 0);
2898 if (dr->dr_txhdr_cache == NULL) {
2899 device_printf(sc->sc_dev,
2900 "can't allocate TX header DMA memory\n");
2901 goto fail1;
2902 }
2903
2904 /*
2905 * Create TX ring DMA stuffs
2906 */
2907 error = bus_dma_tag_create(dma->parent_dtag,
2908 BWN_ALIGN, 0,
2909 BUS_SPACE_MAXADDR,
2910 BUS_SPACE_MAXADDR,
2911 NULL, NULL,
2912 BWN_HDRSIZE(mac),
2913 1,
2914 BUS_SPACE_MAXSIZE_32BIT,
2915 0,
2916 NULL, NULL,
2917 &dr->dr_txring_dtag);
2918 if (error) {
2919 device_printf(sc->sc_dev,
2920 "can't create TX ring DMA tag: TODO frees\n");
2921 goto fail2;
2922 }
2923
2924 for (i = 0; i < dr->dr_numslots; i += 2) {
2925 dr->getdesc(dr, i, &desc, &mt);
2926
2927 mt->mt_txtype = BWN_DMADESC_METATYPE_HEADER;
2928 mt->mt_m = NULL;
2929 mt->mt_ni = NULL;
2930 mt->mt_islast = 0;
2931 error = bus_dmamap_create(dr->dr_txring_dtag, 0,
2932 &mt->mt_dmap);
2933 if (error) {
2934 device_printf(sc->sc_dev,
2935 "can't create RX buf DMA map\n");
2936 goto fail2;
2937 }
2938
2939 dr->getdesc(dr, i + 1, &desc, &mt);
2940
2941 mt->mt_txtype = BWN_DMADESC_METATYPE_BODY;
2942 mt->mt_m = NULL;
2943 mt->mt_ni = NULL;
2944 mt->mt_islast = 1;
2945 error = bus_dmamap_create(dma->txbuf_dtag, 0,
2946 &mt->mt_dmap);
2947 if (error) {
2948 device_printf(sc->sc_dev,
2949 "can't create RX buf DMA map\n");
2950 goto fail2;
2951 }
2952 }
2953 } else {
2954 error = bus_dmamap_create(dma->rxbuf_dtag, 0,
2955 &dr->dr_spare_dmap);
2956 if (error) {
2957 device_printf(sc->sc_dev,
2958 "can't create RX buf DMA map\n");
2959 goto out; /* XXX wrong! */
2960 }
2961
2962 for (i = 0; i < dr->dr_numslots; i++) {
2963 dr->getdesc(dr, i, &desc, &mt);
2964
2965 error = bus_dmamap_create(dma->rxbuf_dtag, 0,
2966 &mt->mt_dmap);
2967 if (error) {
2968 device_printf(sc->sc_dev,
2969 "can't create RX buf DMA map\n");
2970 goto out; /* XXX wrong! */
2971 }
2972 error = bwn_dma_newbuf(dr, desc, mt, 1);
2973 if (error) {
2974 device_printf(sc->sc_dev,
2975 "failed to allocate RX buf\n");
2976 goto out; /* XXX wrong! */
2977 }
2978 }
2979
2980 bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
2981 BUS_DMASYNC_PREWRITE);
2982
2983 dr->dr_usedslot = dr->dr_numslots;
2984 }
2985
2986 out:
2987 return (dr);
2988
2989 fail2:
2990 free(dr->dr_txhdr_cache, M_DEVBUF);
2991 fail1:
2992 free(dr->dr_meta, M_DEVBUF);
2993 fail0:
2994 free(dr, M_DEVBUF);
2995 return (NULL);
2996 }
2997
2998 static void
bwn_dma_ringfree(struct bwn_dma_ring ** dr)2999 bwn_dma_ringfree(struct bwn_dma_ring **dr)
3000 {
3001
3002 if (dr == NULL)
3003 return;
3004
3005 bwn_dma_free_descbufs(*dr);
3006 bwn_dma_free_ringmemory(*dr);
3007
3008 free((*dr)->dr_txhdr_cache, M_DEVBUF);
3009 free((*dr)->dr_meta, M_DEVBUF);
3010 free(*dr, M_DEVBUF);
3011
3012 *dr = NULL;
3013 }
3014
3015 static void
bwn_dma_32_getdesc(struct bwn_dma_ring * dr,int slot,struct bwn_dmadesc_generic ** gdesc,struct bwn_dmadesc_meta ** meta)3016 bwn_dma_32_getdesc(struct bwn_dma_ring *dr, int slot,
3017 struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
3018 {
3019 struct bwn_dmadesc32 *desc;
3020
3021 *meta = &(dr->dr_meta[slot]);
3022 desc = dr->dr_ring_descbase;
3023 desc = &(desc[slot]);
3024
3025 *gdesc = (struct bwn_dmadesc_generic *)desc;
3026 }
3027
3028 static void
bwn_dma_32_setdesc(struct bwn_dma_ring * dr,struct bwn_dmadesc_generic * desc,bus_addr_t dmaaddr,uint16_t bufsize,int start,int end,int irq)3029 bwn_dma_32_setdesc(struct bwn_dma_ring *dr,
3030 struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
3031 int start, int end, int irq)
3032 {
3033 struct bwn_dmadesc32 *descbase;
3034 struct bwn_dma *dma;
3035 struct bhnd_dma_translation *dt;
3036 uint32_t addr, addrext, ctl;
3037 int slot;
3038
3039 descbase = dr->dr_ring_descbase;
3040 dma = &dr->dr_mac->mac_method.dma;
3041 dt = &dma->translation;
3042
3043 slot = (int)(&(desc->dma.dma32) - descbase);
3044 KASSERT(slot >= 0 && slot < dr->dr_numslots,
3045 ("%s:%d: fail", __func__, __LINE__));
3046
3047 addr = (dmaaddr & dt->addr_mask) | dt->base_addr;
3048 addrext = ((dmaaddr & dt->addrext_mask) >> dma->addrext_shift);
3049 ctl = bufsize & BWN_DMA32_DCTL_BYTECNT;
3050 if (slot == dr->dr_numslots - 1)
3051 ctl |= BWN_DMA32_DCTL_DTABLEEND;
3052 if (start)
3053 ctl |= BWN_DMA32_DCTL_FRAMESTART;
3054 if (end)
3055 ctl |= BWN_DMA32_DCTL_FRAMEEND;
3056 if (irq)
3057 ctl |= BWN_DMA32_DCTL_IRQ;
3058 ctl |= (addrext << BWN_DMA32_DCTL_ADDREXT_SHIFT)
3059 & BWN_DMA32_DCTL_ADDREXT_MASK;
3060
3061 desc->dma.dma32.control = htole32(ctl);
3062 desc->dma.dma32.address = htole32(addr);
3063 }
3064
3065 static void
bwn_dma_32_start_transfer(struct bwn_dma_ring * dr,int slot)3066 bwn_dma_32_start_transfer(struct bwn_dma_ring *dr, int slot)
3067 {
3068
3069 BWN_DMA_WRITE(dr, BWN_DMA32_TXINDEX,
3070 (uint32_t)(slot * sizeof(struct bwn_dmadesc32)));
3071 }
3072
3073 static void
bwn_dma_32_suspend(struct bwn_dma_ring * dr)3074 bwn_dma_32_suspend(struct bwn_dma_ring *dr)
3075 {
3076
3077 BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
3078 BWN_DMA_READ(dr, BWN_DMA32_TXCTL) | BWN_DMA32_TXSUSPEND);
3079 }
3080
3081 static void
bwn_dma_32_resume(struct bwn_dma_ring * dr)3082 bwn_dma_32_resume(struct bwn_dma_ring *dr)
3083 {
3084
3085 BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
3086 BWN_DMA_READ(dr, BWN_DMA32_TXCTL) & ~BWN_DMA32_TXSUSPEND);
3087 }
3088
3089 static int
bwn_dma_32_get_curslot(struct bwn_dma_ring * dr)3090 bwn_dma_32_get_curslot(struct bwn_dma_ring *dr)
3091 {
3092 uint32_t val;
3093
3094 val = BWN_DMA_READ(dr, BWN_DMA32_RXSTATUS);
3095 val &= BWN_DMA32_RXDPTR;
3096
3097 return (val / sizeof(struct bwn_dmadesc32));
3098 }
3099
3100 static void
bwn_dma_32_set_curslot(struct bwn_dma_ring * dr,int slot)3101 bwn_dma_32_set_curslot(struct bwn_dma_ring *dr, int slot)
3102 {
3103
3104 BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX,
3105 (uint32_t) (slot * sizeof(struct bwn_dmadesc32)));
3106 }
3107
3108 static void
bwn_dma_64_getdesc(struct bwn_dma_ring * dr,int slot,struct bwn_dmadesc_generic ** gdesc,struct bwn_dmadesc_meta ** meta)3109 bwn_dma_64_getdesc(struct bwn_dma_ring *dr, int slot,
3110 struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
3111 {
3112 struct bwn_dmadesc64 *desc;
3113
3114 *meta = &(dr->dr_meta[slot]);
3115 desc = dr->dr_ring_descbase;
3116 desc = &(desc[slot]);
3117
3118 *gdesc = (struct bwn_dmadesc_generic *)desc;
3119 }
3120
3121 static void
bwn_dma_64_setdesc(struct bwn_dma_ring * dr,struct bwn_dmadesc_generic * desc,bus_addr_t dmaaddr,uint16_t bufsize,int start,int end,int irq)3122 bwn_dma_64_setdesc(struct bwn_dma_ring *dr,
3123 struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
3124 int start, int end, int irq)
3125 {
3126 struct bwn_dmadesc64 *descbase;
3127 struct bwn_dma *dma;
3128 struct bhnd_dma_translation *dt;
3129 bhnd_addr_t addr;
3130 uint32_t addrhi, addrlo;
3131 uint32_t addrext;
3132 uint32_t ctl0, ctl1;
3133 int slot;
3134
3135 descbase = dr->dr_ring_descbase;
3136 dma = &dr->dr_mac->mac_method.dma;
3137 dt = &dma->translation;
3138
3139 slot = (int)(&(desc->dma.dma64) - descbase);
3140 KASSERT(slot >= 0 && slot < dr->dr_numslots,
3141 ("%s:%d: fail", __func__, __LINE__));
3142
3143 addr = (dmaaddr & dt->addr_mask) | dt->base_addr;
3144 addrhi = (addr >> 32);
3145 addrlo = (addr & UINT32_MAX);
3146 addrext = ((dmaaddr & dt->addrext_mask) >> dma->addrext_shift);
3147
3148 ctl0 = 0;
3149 if (slot == dr->dr_numslots - 1)
3150 ctl0 |= BWN_DMA64_DCTL0_DTABLEEND;
3151 if (start)
3152 ctl0 |= BWN_DMA64_DCTL0_FRAMESTART;
3153 if (end)
3154 ctl0 |= BWN_DMA64_DCTL0_FRAMEEND;
3155 if (irq)
3156 ctl0 |= BWN_DMA64_DCTL0_IRQ;
3157
3158 ctl1 = 0;
3159 ctl1 |= bufsize & BWN_DMA64_DCTL1_BYTECNT;
3160 ctl1 |= (addrext << BWN_DMA64_DCTL1_ADDREXT_SHIFT)
3161 & BWN_DMA64_DCTL1_ADDREXT_MASK;
3162
3163 desc->dma.dma64.control0 = htole32(ctl0);
3164 desc->dma.dma64.control1 = htole32(ctl1);
3165 desc->dma.dma64.address_low = htole32(addrlo);
3166 desc->dma.dma64.address_high = htole32(addrhi);
3167 }
3168
3169 static void
bwn_dma_64_start_transfer(struct bwn_dma_ring * dr,int slot)3170 bwn_dma_64_start_transfer(struct bwn_dma_ring *dr, int slot)
3171 {
3172
3173 BWN_DMA_WRITE(dr, BWN_DMA64_TXINDEX,
3174 (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
3175 }
3176
3177 static void
bwn_dma_64_suspend(struct bwn_dma_ring * dr)3178 bwn_dma_64_suspend(struct bwn_dma_ring *dr)
3179 {
3180
3181 BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
3182 BWN_DMA_READ(dr, BWN_DMA64_TXCTL) | BWN_DMA64_TXSUSPEND);
3183 }
3184
3185 static void
bwn_dma_64_resume(struct bwn_dma_ring * dr)3186 bwn_dma_64_resume(struct bwn_dma_ring *dr)
3187 {
3188
3189 BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
3190 BWN_DMA_READ(dr, BWN_DMA64_TXCTL) & ~BWN_DMA64_TXSUSPEND);
3191 }
3192
3193 static int
bwn_dma_64_get_curslot(struct bwn_dma_ring * dr)3194 bwn_dma_64_get_curslot(struct bwn_dma_ring *dr)
3195 {
3196 uint32_t val;
3197
3198 val = BWN_DMA_READ(dr, BWN_DMA64_RXSTATUS);
3199 val &= BWN_DMA64_RXSTATDPTR;
3200
3201 return (val / sizeof(struct bwn_dmadesc64));
3202 }
3203
3204 static void
bwn_dma_64_set_curslot(struct bwn_dma_ring * dr,int slot)3205 bwn_dma_64_set_curslot(struct bwn_dma_ring *dr, int slot)
3206 {
3207
3208 BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX,
3209 (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
3210 }
3211
3212 static int
bwn_dma_allocringmemory(struct bwn_dma_ring * dr)3213 bwn_dma_allocringmemory(struct bwn_dma_ring *dr)
3214 {
3215 struct bwn_mac *mac = dr->dr_mac;
3216 struct bwn_dma *dma = &mac->mac_method.dma;
3217 struct bwn_softc *sc = mac->mac_sc;
3218 int error;
3219
3220 error = bus_dma_tag_create(dma->parent_dtag,
3221 BWN_ALIGN, 0,
3222 BUS_SPACE_MAXADDR,
3223 BUS_SPACE_MAXADDR,
3224 NULL, NULL,
3225 BWN_DMA_RINGMEMSIZE,
3226 1,
3227 BUS_SPACE_MAXSIZE_32BIT,
3228 0,
3229 NULL, NULL,
3230 &dr->dr_ring_dtag);
3231 if (error) {
3232 device_printf(sc->sc_dev,
3233 "can't create TX ring DMA tag: TODO frees\n");
3234 return (-1);
3235 }
3236
3237 error = bus_dmamem_alloc(dr->dr_ring_dtag,
3238 &dr->dr_ring_descbase, BUS_DMA_WAITOK | BUS_DMA_ZERO,
3239 &dr->dr_ring_dmap);
3240 if (error) {
3241 device_printf(sc->sc_dev,
3242 "can't allocate DMA mem: TODO frees\n");
3243 return (-1);
3244 }
3245 error = bus_dmamap_load(dr->dr_ring_dtag, dr->dr_ring_dmap,
3246 dr->dr_ring_descbase, BWN_DMA_RINGMEMSIZE,
3247 bwn_dma_ring_addr, &dr->dr_ring_dmabase, BUS_DMA_NOWAIT);
3248 if (error) {
3249 device_printf(sc->sc_dev,
3250 "can't load DMA mem: TODO free\n");
3251 return (-1);
3252 }
3253
3254 return (0);
3255 }
3256
3257 static void
bwn_dma_setup(struct bwn_dma_ring * dr)3258 bwn_dma_setup(struct bwn_dma_ring *dr)
3259 {
3260 struct bwn_mac *mac;
3261 struct bwn_dma *dma;
3262 struct bhnd_dma_translation *dt;
3263 bhnd_addr_t addr, paddr;
3264 uint32_t addrhi, addrlo, addrext, value;
3265
3266 mac = dr->dr_mac;
3267 dma = &mac->mac_method.dma;
3268 dt = &dma->translation;
3269
3270 paddr = dr->dr_ring_dmabase;
3271 addr = (paddr & dt->addr_mask) | dt->base_addr;
3272 addrhi = (addr >> 32);
3273 addrlo = (addr & UINT32_MAX);
3274 addrext = ((paddr & dt->addrext_mask) >> dma->addrext_shift);
3275
3276 if (dr->dr_tx) {
3277 dr->dr_curslot = -1;
3278
3279 if (dr->dr_type == BHND_DMA_ADDR_64BIT) {
3280 value = BWN_DMA64_TXENABLE;
3281 value |= BWN_DMA64_TXPARITY_DISABLE;
3282 value |= (addrext << BWN_DMA64_TXADDREXT_SHIFT)
3283 & BWN_DMA64_TXADDREXT_MASK;
3284 BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL, value);
3285 BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO, addrlo);
3286 BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI, addrhi);
3287 } else {
3288 value = BWN_DMA32_TXENABLE;
3289 value |= BWN_DMA32_TXPARITY_DISABLE;
3290 value |= (addrext << BWN_DMA32_TXADDREXT_SHIFT)
3291 & BWN_DMA32_TXADDREXT_MASK;
3292 BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL, value);
3293 BWN_DMA_WRITE(dr, BWN_DMA32_TXRING, addrlo);
3294 }
3295 return;
3296 }
3297
3298 /*
3299 * set for RX
3300 */
3301 dr->dr_usedslot = dr->dr_numslots;
3302
3303 if (dr->dr_type == BHND_DMA_ADDR_64BIT) {
3304 value = (dr->dr_frameoffset << BWN_DMA64_RXFROFF_SHIFT);
3305 value |= BWN_DMA64_RXENABLE;
3306 value |= BWN_DMA64_RXPARITY_DISABLE;
3307 value |= (addrext << BWN_DMA64_RXADDREXT_SHIFT)
3308 & BWN_DMA64_RXADDREXT_MASK;
3309 BWN_DMA_WRITE(dr, BWN_DMA64_RXCTL, value);
3310 BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, addrlo);
3311 BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI, addrhi);
3312 BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX, dr->dr_numslots *
3313 sizeof(struct bwn_dmadesc64));
3314 } else {
3315 value = (dr->dr_frameoffset << BWN_DMA32_RXFROFF_SHIFT);
3316 value |= BWN_DMA32_RXENABLE;
3317 value |= BWN_DMA32_RXPARITY_DISABLE;
3318 value |= (addrext << BWN_DMA32_RXADDREXT_SHIFT)
3319 & BWN_DMA32_RXADDREXT_MASK;
3320 BWN_DMA_WRITE(dr, BWN_DMA32_RXCTL, value);
3321 BWN_DMA_WRITE(dr, BWN_DMA32_RXRING, addrlo);
3322 BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX, dr->dr_numslots *
3323 sizeof(struct bwn_dmadesc32));
3324 }
3325 }
3326
3327 static void
bwn_dma_free_ringmemory(struct bwn_dma_ring * dr)3328 bwn_dma_free_ringmemory(struct bwn_dma_ring *dr)
3329 {
3330
3331 bus_dmamap_unload(dr->dr_ring_dtag, dr->dr_ring_dmap);
3332 bus_dmamem_free(dr->dr_ring_dtag, dr->dr_ring_descbase,
3333 dr->dr_ring_dmap);
3334 }
3335
3336 static void
bwn_dma_cleanup(struct bwn_dma_ring * dr)3337 bwn_dma_cleanup(struct bwn_dma_ring *dr)
3338 {
3339
3340 if (dr->dr_tx) {
3341 bwn_dma_tx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
3342 if (dr->dr_type == BHND_DMA_ADDR_64BIT) {
3343 BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO, 0);
3344 BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI, 0);
3345 } else
3346 BWN_DMA_WRITE(dr, BWN_DMA32_TXRING, 0);
3347 } else {
3348 bwn_dma_rx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
3349 if (dr->dr_type == BHND_DMA_ADDR_64BIT) {
3350 BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, 0);
3351 BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI, 0);
3352 } else
3353 BWN_DMA_WRITE(dr, BWN_DMA32_RXRING, 0);
3354 }
3355 }
3356
3357 static void
bwn_dma_free_descbufs(struct bwn_dma_ring * dr)3358 bwn_dma_free_descbufs(struct bwn_dma_ring *dr)
3359 {
3360 struct bwn_dmadesc_generic *desc;
3361 struct bwn_dmadesc_meta *meta;
3362 struct bwn_mac *mac = dr->dr_mac;
3363 struct bwn_dma *dma = &mac->mac_method.dma;
3364 struct bwn_softc *sc = mac->mac_sc;
3365 int i;
3366
3367 if (!dr->dr_usedslot)
3368 return;
3369 for (i = 0; i < dr->dr_numslots; i++) {
3370 dr->getdesc(dr, i, &desc, &meta);
3371
3372 if (meta->mt_m == NULL) {
3373 if (!dr->dr_tx)
3374 device_printf(sc->sc_dev, "%s: not TX?\n",
3375 __func__);
3376 continue;
3377 }
3378 if (dr->dr_tx) {
3379 if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
3380 bus_dmamap_unload(dr->dr_txring_dtag,
3381 meta->mt_dmap);
3382 else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
3383 bus_dmamap_unload(dma->txbuf_dtag,
3384 meta->mt_dmap);
3385 } else
3386 bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
3387 bwn_dma_free_descbuf(dr, meta);
3388 }
3389 }
3390
3391 static int
bwn_dma_tx_reset(struct bwn_mac * mac,uint16_t base,int type)3392 bwn_dma_tx_reset(struct bwn_mac *mac, uint16_t base,
3393 int type)
3394 {
3395 struct bwn_softc *sc = mac->mac_sc;
3396 uint32_t value;
3397 int i;
3398 uint16_t offset;
3399
3400 for (i = 0; i < 10; i++) {
3401 offset = (type == BHND_DMA_ADDR_64BIT) ? BWN_DMA64_TXSTATUS :
3402 BWN_DMA32_TXSTATUS;
3403 value = BWN_READ_4(mac, base + offset);
3404 if (type == BHND_DMA_ADDR_64BIT) {
3405 value &= BWN_DMA64_TXSTAT;
3406 if (value == BWN_DMA64_TXSTAT_DISABLED ||
3407 value == BWN_DMA64_TXSTAT_IDLEWAIT ||
3408 value == BWN_DMA64_TXSTAT_STOPPED)
3409 break;
3410 } else {
3411 value &= BWN_DMA32_TXSTATE;
3412 if (value == BWN_DMA32_TXSTAT_DISABLED ||
3413 value == BWN_DMA32_TXSTAT_IDLEWAIT ||
3414 value == BWN_DMA32_TXSTAT_STOPPED)
3415 break;
3416 }
3417 DELAY(1000);
3418 }
3419 offset = (type == BHND_DMA_ADDR_64BIT) ? BWN_DMA64_TXCTL :
3420 BWN_DMA32_TXCTL;
3421 BWN_WRITE_4(mac, base + offset, 0);
3422 for (i = 0; i < 10; i++) {
3423 offset = (type == BHND_DMA_ADDR_64BIT) ? BWN_DMA64_TXSTATUS :
3424 BWN_DMA32_TXSTATUS;
3425 value = BWN_READ_4(mac, base + offset);
3426 if (type == BHND_DMA_ADDR_64BIT) {
3427 value &= BWN_DMA64_TXSTAT;
3428 if (value == BWN_DMA64_TXSTAT_DISABLED) {
3429 i = -1;
3430 break;
3431 }
3432 } else {
3433 value &= BWN_DMA32_TXSTATE;
3434 if (value == BWN_DMA32_TXSTAT_DISABLED) {
3435 i = -1;
3436 break;
3437 }
3438 }
3439 DELAY(1000);
3440 }
3441 if (i != -1) {
3442 device_printf(sc->sc_dev, "%s: timed out\n", __func__);
3443 return (ENODEV);
3444 }
3445 DELAY(1000);
3446
3447 return (0);
3448 }
3449
3450 static int
bwn_dma_rx_reset(struct bwn_mac * mac,uint16_t base,int type)3451 bwn_dma_rx_reset(struct bwn_mac *mac, uint16_t base,
3452 int type)
3453 {
3454 struct bwn_softc *sc = mac->mac_sc;
3455 uint32_t value;
3456 int i;
3457 uint16_t offset;
3458
3459 offset = (type == BHND_DMA_ADDR_64BIT) ? BWN_DMA64_RXCTL :
3460 BWN_DMA32_RXCTL;
3461 BWN_WRITE_4(mac, base + offset, 0);
3462 for (i = 0; i < 10; i++) {
3463 offset = (type == BHND_DMA_ADDR_64BIT) ? BWN_DMA64_RXSTATUS :
3464 BWN_DMA32_RXSTATUS;
3465 value = BWN_READ_4(mac, base + offset);
3466 if (type == BHND_DMA_ADDR_64BIT) {
3467 value &= BWN_DMA64_RXSTAT;
3468 if (value == BWN_DMA64_RXSTAT_DISABLED) {
3469 i = -1;
3470 break;
3471 }
3472 } else {
3473 value &= BWN_DMA32_RXSTATE;
3474 if (value == BWN_DMA32_RXSTAT_DISABLED) {
3475 i = -1;
3476 break;
3477 }
3478 }
3479 DELAY(1000);
3480 }
3481 if (i != -1) {
3482 device_printf(sc->sc_dev, "%s: timed out\n", __func__);
3483 return (ENODEV);
3484 }
3485
3486 return (0);
3487 }
3488
3489 static void
bwn_dma_free_descbuf(struct bwn_dma_ring * dr,struct bwn_dmadesc_meta * meta)3490 bwn_dma_free_descbuf(struct bwn_dma_ring *dr,
3491 struct bwn_dmadesc_meta *meta)
3492 {
3493
3494 if (meta->mt_m != NULL) {
3495 m_freem(meta->mt_m);
3496 meta->mt_m = NULL;
3497 }
3498 if (meta->mt_ni != NULL) {
3499 ieee80211_free_node(meta->mt_ni);
3500 meta->mt_ni = NULL;
3501 }
3502 }
3503
3504 static void
bwn_dma_set_redzone(struct bwn_dma_ring * dr,struct mbuf * m)3505 bwn_dma_set_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
3506 {
3507 struct bwn_rxhdr4 *rxhdr;
3508 unsigned char *frame;
3509
3510 rxhdr = mtod(m, struct bwn_rxhdr4 *);
3511 rxhdr->frame_len = 0;
3512
3513 KASSERT(dr->dr_rx_bufsize >= dr->dr_frameoffset +
3514 sizeof(struct bwn_plcp6) + 2,
3515 ("%s:%d: fail", __func__, __LINE__));
3516 frame = mtod(m, char *) + dr->dr_frameoffset;
3517 memset(frame, 0xff, sizeof(struct bwn_plcp6) + 2 /* padding */);
3518 }
3519
3520 static uint8_t
bwn_dma_check_redzone(struct bwn_dma_ring * dr,struct mbuf * m)3521 bwn_dma_check_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
3522 {
3523 unsigned char *f = mtod(m, char *) + dr->dr_frameoffset;
3524
3525 return ((f[0] & f[1] & f[2] & f[3] & f[4] & f[5] & f[6] & f[7])
3526 == 0xff);
3527 }
3528
3529 static void
bwn_wme_init(struct bwn_mac * mac)3530 bwn_wme_init(struct bwn_mac *mac)
3531 {
3532
3533 bwn_wme_load(mac);
3534
3535 /* enable WME support. */
3536 bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_EDCF);
3537 BWN_WRITE_2(mac, BWN_IFSCTL, BWN_READ_2(mac, BWN_IFSCTL) |
3538 BWN_IFSCTL_USE_EDCF);
3539 }
3540
3541 static void
bwn_spu_setdelay(struct bwn_mac * mac,int idle)3542 bwn_spu_setdelay(struct bwn_mac *mac, int idle)
3543 {
3544 struct bwn_softc *sc = mac->mac_sc;
3545 struct ieee80211com *ic = &sc->sc_ic;
3546 uint16_t delay; /* microsec */
3547
3548 delay = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 3700 : 1050;
3549 if (ic->ic_opmode == IEEE80211_M_IBSS || idle)
3550 delay = 500;
3551 if ((mac->mac_phy.rf_ver == 0x2050) && (mac->mac_phy.rf_rev == 8))
3552 delay = max(delay, (uint16_t)2400);
3553
3554 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SPU_WAKEUP, delay);
3555 }
3556
3557 static void
bwn_bt_enable(struct bwn_mac * mac)3558 bwn_bt_enable(struct bwn_mac *mac)
3559 {
3560 struct bwn_softc *sc = mac->mac_sc;
3561 uint64_t hf;
3562
3563 if (bwn_bluetooth == 0)
3564 return;
3565 if ((sc->sc_board_info.board_flags & BHND_BFL_BTCOEX) == 0)
3566 return;
3567 if (mac->mac_phy.type != BWN_PHYTYPE_B && !mac->mac_phy.gmode)
3568 return;
3569
3570 hf = bwn_hf_read(mac);
3571 if (sc->sc_board_info.board_flags & BHND_BFL_BTC2WIRE_ALTGPIO)
3572 hf |= BWN_HF_BT_COEXISTALT;
3573 else
3574 hf |= BWN_HF_BT_COEXIST;
3575 bwn_hf_write(mac, hf);
3576 }
3577
3578 static void
bwn_set_macaddr(struct bwn_mac * mac)3579 bwn_set_macaddr(struct bwn_mac *mac)
3580 {
3581
3582 bwn_mac_write_bssid(mac);
3583 bwn_mac_setfilter(mac, BWN_MACFILTER_SELF,
3584 mac->mac_sc->sc_ic.ic_macaddr);
3585 }
3586
3587 static void
bwn_clear_keys(struct bwn_mac * mac)3588 bwn_clear_keys(struct bwn_mac *mac)
3589 {
3590 int i;
3591
3592 for (i = 0; i < mac->mac_max_nr_keys; i++) {
3593 KASSERT(i >= 0 && i < mac->mac_max_nr_keys,
3594 ("%s:%d: fail", __func__, __LINE__));
3595
3596 bwn_key_dowrite(mac, i, BWN_SEC_ALGO_NONE,
3597 NULL, BWN_SEC_KEYSIZE, NULL);
3598 if ((i <= 3) && !BWN_SEC_NEWAPI(mac)) {
3599 bwn_key_dowrite(mac, i + 4, BWN_SEC_ALGO_NONE,
3600 NULL, BWN_SEC_KEYSIZE, NULL);
3601 }
3602 mac->mac_key[i].keyconf = NULL;
3603 }
3604 }
3605
3606 static void
bwn_crypt_init(struct bwn_mac * mac)3607 bwn_crypt_init(struct bwn_mac *mac)
3608 {
3609 struct bwn_softc *sc = mac->mac_sc;
3610
3611 mac->mac_max_nr_keys = (bhnd_get_hwrev(sc->sc_dev) >= 5) ? 58 : 20;
3612 KASSERT(mac->mac_max_nr_keys <= N(mac->mac_key),
3613 ("%s:%d: fail", __func__, __LINE__));
3614 mac->mac_ktp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_KEY_TABLEP);
3615 mac->mac_ktp *= 2;
3616 if (bhnd_get_hwrev(sc->sc_dev) >= 5)
3617 BWN_WRITE_2(mac, BWN_RCMTA_COUNT, mac->mac_max_nr_keys - 8);
3618 bwn_clear_keys(mac);
3619 }
3620
3621 static void
bwn_chip_exit(struct bwn_mac * mac)3622 bwn_chip_exit(struct bwn_mac *mac)
3623 {
3624 bwn_phy_exit(mac);
3625 }
3626
3627 static int
bwn_fw_fillinfo(struct bwn_mac * mac)3628 bwn_fw_fillinfo(struct bwn_mac *mac)
3629 {
3630 int error;
3631
3632 error = bwn_fw_gets(mac, BWN_FWTYPE_DEFAULT);
3633 if (error == 0)
3634 return (0);
3635 error = bwn_fw_gets(mac, BWN_FWTYPE_OPENSOURCE);
3636 if (error == 0)
3637 return (0);
3638 return (error);
3639 }
3640
3641 /**
3642 * Request that the GPIO controller tristate all pins set in @p mask, granting
3643 * the MAC core control over the pins.
3644 *
3645 * @param mac bwn MAC state.
3646 * @param pins If the bit position for a pin number is set to one, tristate the
3647 * pin.
3648 */
3649 int
bwn_gpio_control(struct bwn_mac * mac,uint32_t pins)3650 bwn_gpio_control(struct bwn_mac *mac, uint32_t pins)
3651 {
3652 struct bwn_softc *sc;
3653 uint32_t flags[32];
3654 int error;
3655
3656 sc = mac->mac_sc;
3657
3658 /* Determine desired pin flags */
3659 for (size_t pin = 0; pin < nitems(flags); pin++) {
3660 uint32_t pinbit = (1 << pin);
3661
3662 if (pins & pinbit) {
3663 /* Tristate output */
3664 flags[pin] = GPIO_PIN_OUTPUT|GPIO_PIN_TRISTATE;
3665 } else {
3666 /* Leave unmodified */
3667 flags[pin] = 0;
3668 }
3669 }
3670
3671 /* Configure all pins */
3672 error = GPIO_PIN_CONFIG_32(sc->sc_gpio, 0, nitems(flags), flags);
3673 if (error) {
3674 device_printf(sc->sc_dev, "error configuring %s pin flags: "
3675 "%d\n", device_get_nameunit(sc->sc_gpio), error);
3676 return (error);
3677 }
3678
3679 return (0);
3680 }
3681
3682 static int
bwn_gpio_init(struct bwn_mac * mac)3683 bwn_gpio_init(struct bwn_mac *mac)
3684 {
3685 struct bwn_softc *sc;
3686 uint32_t pins;
3687
3688 sc = mac->mac_sc;
3689
3690 pins = 0xF;
3691
3692 BWN_WRITE_4(mac, BWN_MACCTL,
3693 BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GPOUT_MASK);
3694 BWN_WRITE_2(mac, BWN_GPIO_MASK,
3695 BWN_READ_2(mac, BWN_GPIO_MASK) | pins);
3696
3697 if (sc->sc_board_info.board_flags & BHND_BFL_PACTRL) {
3698 /* MAC core is responsible for toggling PAREF via gpio9 */
3699 BWN_WRITE_2(mac, BWN_GPIO_MASK,
3700 BWN_READ_2(mac, BWN_GPIO_MASK) | BHND_GPIO_BOARD_PACTRL);
3701
3702 pins |= BHND_GPIO_BOARD_PACTRL;
3703 }
3704
3705 return (bwn_gpio_control(mac, pins));
3706 }
3707
3708 static int
bwn_fw_loadinitvals(struct bwn_mac * mac)3709 bwn_fw_loadinitvals(struct bwn_mac *mac)
3710 {
3711 #define GETFWOFFSET(fwp, offset) \
3712 ((const struct bwn_fwinitvals *)((const char *)fwp.fw->data + offset))
3713 const size_t hdr_len = sizeof(struct bwn_fwhdr);
3714 const struct bwn_fwhdr *hdr;
3715 struct bwn_fw *fw = &mac->mac_fw;
3716 int error;
3717
3718 hdr = (const struct bwn_fwhdr *)(fw->initvals.fw->data);
3719 error = bwn_fwinitvals_write(mac, GETFWOFFSET(fw->initvals, hdr_len),
3720 be32toh(hdr->size), fw->initvals.fw->datasize - hdr_len);
3721 if (error)
3722 return (error);
3723 if (fw->initvals_band.fw) {
3724 hdr = (const struct bwn_fwhdr *)(fw->initvals_band.fw->data);
3725 error = bwn_fwinitvals_write(mac,
3726 GETFWOFFSET(fw->initvals_band, hdr_len),
3727 be32toh(hdr->size),
3728 fw->initvals_band.fw->datasize - hdr_len);
3729 }
3730 return (error);
3731 #undef GETFWOFFSET
3732 }
3733
3734 static int
bwn_phy_init(struct bwn_mac * mac)3735 bwn_phy_init(struct bwn_mac *mac)
3736 {
3737 struct bwn_softc *sc = mac->mac_sc;
3738 int error;
3739
3740 mac->mac_phy.chan = mac->mac_phy.get_default_chan(mac);
3741 mac->mac_phy.rf_onoff(mac, 1);
3742 error = mac->mac_phy.init(mac);
3743 if (error) {
3744 device_printf(sc->sc_dev, "PHY init failed\n");
3745 goto fail0;
3746 }
3747 error = bwn_switch_channel(mac,
3748 mac->mac_phy.get_default_chan(mac));
3749 if (error) {
3750 device_printf(sc->sc_dev,
3751 "failed to switch default channel\n");
3752 goto fail1;
3753 }
3754 return (0);
3755 fail1:
3756 if (mac->mac_phy.exit)
3757 mac->mac_phy.exit(mac);
3758 fail0:
3759 mac->mac_phy.rf_onoff(mac, 0);
3760
3761 return (error);
3762 }
3763
3764 static void
bwn_set_txantenna(struct bwn_mac * mac,int antenna)3765 bwn_set_txantenna(struct bwn_mac *mac, int antenna)
3766 {
3767 uint16_t ant;
3768 uint16_t tmp;
3769
3770 ant = bwn_ant2phy(antenna);
3771
3772 /* For ACK/CTS */
3773 tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL);
3774 tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
3775 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, tmp);
3776 /* For Probe Resposes */
3777 tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL);
3778 tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
3779 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, tmp);
3780 }
3781
3782 static void
bwn_set_opmode(struct bwn_mac * mac)3783 bwn_set_opmode(struct bwn_mac *mac)
3784 {
3785 struct bwn_softc *sc = mac->mac_sc;
3786 struct ieee80211com *ic = &sc->sc_ic;
3787 uint32_t ctl;
3788 uint16_t cfp_pretbtt;
3789
3790 ctl = BWN_READ_4(mac, BWN_MACCTL);
3791 ctl &= ~(BWN_MACCTL_HOSTAP | BWN_MACCTL_PASS_CTL |
3792 BWN_MACCTL_PASS_BADPLCP | BWN_MACCTL_PASS_BADFCS |
3793 BWN_MACCTL_PROMISC | BWN_MACCTL_BEACON_PROMISC);
3794 ctl |= BWN_MACCTL_STA;
3795
3796 if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
3797 ic->ic_opmode == IEEE80211_M_MBSS)
3798 ctl |= BWN_MACCTL_HOSTAP;
3799 else if (ic->ic_opmode == IEEE80211_M_IBSS)
3800 ctl &= ~BWN_MACCTL_STA;
3801 ctl |= sc->sc_filters;
3802
3803 if (bhnd_get_hwrev(sc->sc_dev) <= 4)
3804 ctl |= BWN_MACCTL_PROMISC;
3805
3806 BWN_WRITE_4(mac, BWN_MACCTL, ctl);
3807
3808 cfp_pretbtt = 2;
3809 if ((ctl & BWN_MACCTL_STA) && !(ctl & BWN_MACCTL_HOSTAP)) {
3810 if (sc->sc_cid.chip_id == BHND_CHIPID_BCM4306 &&
3811 sc->sc_cid.chip_rev == 3)
3812 cfp_pretbtt = 100;
3813 else
3814 cfp_pretbtt = 50;
3815 }
3816 BWN_WRITE_2(mac, 0x612, cfp_pretbtt);
3817 }
3818
3819 static void
bwn_dma_ring_addr(void * arg,bus_dma_segment_t * seg,int nseg,int error)3820 bwn_dma_ring_addr(void *arg, bus_dma_segment_t *seg, int nseg, int error)
3821 {
3822 if (!error) {
3823 KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
3824 *((bus_addr_t *)arg) = seg->ds_addr;
3825 }
3826 }
3827
3828 void
bwn_dummy_transmission(struct bwn_mac * mac,int ofdm,int paon)3829 bwn_dummy_transmission(struct bwn_mac *mac, int ofdm, int paon)
3830 {
3831 struct bwn_phy *phy = &mac->mac_phy;
3832 struct bwn_softc *sc = mac->mac_sc;
3833 unsigned int i, max_loop;
3834 uint16_t value;
3835 uint32_t buffer[5] = {
3836 0x00000000, 0x00d40000, 0x00000000, 0x01000000, 0x00000000
3837 };
3838
3839 if (ofdm) {
3840 max_loop = 0x1e;
3841 buffer[0] = 0x000201cc;
3842 } else {
3843 max_loop = 0xfa;
3844 buffer[0] = 0x000b846e;
3845 }
3846
3847 BWN_ASSERT_LOCKED(mac->mac_sc);
3848
3849 for (i = 0; i < 5; i++)
3850 bwn_ram_write(mac, i * 4, buffer[i]);
3851
3852 BWN_WRITE_2(mac, 0x0568, 0x0000);
3853 BWN_WRITE_2(mac, 0x07c0,
3854 (bhnd_get_hwrev(sc->sc_dev) < 11) ? 0x0000 : 0x0100);
3855
3856 value = (ofdm ? 0x41 : 0x40);
3857 BWN_WRITE_2(mac, 0x050c, value);
3858
3859 if (phy->type == BWN_PHYTYPE_N || phy->type == BWN_PHYTYPE_LP ||
3860 phy->type == BWN_PHYTYPE_LCN)
3861 BWN_WRITE_2(mac, 0x0514, 0x1a02);
3862 BWN_WRITE_2(mac, 0x0508, 0x0000);
3863 BWN_WRITE_2(mac, 0x050a, 0x0000);
3864 BWN_WRITE_2(mac, 0x054c, 0x0000);
3865 BWN_WRITE_2(mac, 0x056a, 0x0014);
3866 BWN_WRITE_2(mac, 0x0568, 0x0826);
3867 BWN_WRITE_2(mac, 0x0500, 0x0000);
3868
3869 /* XXX TODO: n phy pa override? */
3870
3871 switch (phy->type) {
3872 case BWN_PHYTYPE_N:
3873 case BWN_PHYTYPE_LCN:
3874 BWN_WRITE_2(mac, 0x0502, 0x00d0);
3875 break;
3876 case BWN_PHYTYPE_LP:
3877 BWN_WRITE_2(mac, 0x0502, 0x0050);
3878 break;
3879 default:
3880 BWN_WRITE_2(mac, 0x0502, 0x0030);
3881 break;
3882 }
3883
3884 /* flush */
3885 BWN_READ_2(mac, 0x0502);
3886
3887 if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
3888 BWN_RF_WRITE(mac, 0x0051, 0x0017);
3889 for (i = 0x00; i < max_loop; i++) {
3890 value = BWN_READ_2(mac, 0x050e);
3891 if (value & 0x0080)
3892 break;
3893 DELAY(10);
3894 }
3895 for (i = 0x00; i < 0x0a; i++) {
3896 value = BWN_READ_2(mac, 0x050e);
3897 if (value & 0x0400)
3898 break;
3899 DELAY(10);
3900 }
3901 for (i = 0x00; i < 0x19; i++) {
3902 value = BWN_READ_2(mac, 0x0690);
3903 if (!(value & 0x0100))
3904 break;
3905 DELAY(10);
3906 }
3907 if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
3908 BWN_RF_WRITE(mac, 0x0051, 0x0037);
3909 }
3910
3911 void
bwn_ram_write(struct bwn_mac * mac,uint16_t offset,uint32_t val)3912 bwn_ram_write(struct bwn_mac *mac, uint16_t offset, uint32_t val)
3913 {
3914 uint32_t macctl;
3915
3916 KASSERT(offset % 4 == 0, ("%s:%d: fail", __func__, __LINE__));
3917
3918 macctl = BWN_READ_4(mac, BWN_MACCTL);
3919 if (macctl & BWN_MACCTL_BIGENDIAN)
3920 printf("TODO: need swap\n");
3921
3922 BWN_WRITE_4(mac, BWN_RAM_CONTROL, offset);
3923 BWN_BARRIER(mac, BWN_RAM_CONTROL, 4, BUS_SPACE_BARRIER_WRITE);
3924 BWN_WRITE_4(mac, BWN_RAM_DATA, val);
3925 }
3926
3927 void
bwn_mac_suspend(struct bwn_mac * mac)3928 bwn_mac_suspend(struct bwn_mac *mac)
3929 {
3930 struct bwn_softc *sc = mac->mac_sc;
3931 int i;
3932 uint32_t tmp;
3933
3934 KASSERT(mac->mac_suspended >= 0,
3935 ("%s:%d: fail", __func__, __LINE__));
3936
3937 DPRINTF(mac->mac_sc, BWN_DEBUG_RESET, "%s: suspended=%d\n",
3938 __func__, mac->mac_suspended);
3939
3940 if (mac->mac_suspended == 0) {
3941 bwn_psctl(mac, BWN_PS_AWAKE);
3942 BWN_WRITE_4(mac, BWN_MACCTL,
3943 BWN_READ_4(mac, BWN_MACCTL)
3944 & ~BWN_MACCTL_ON);
3945 BWN_READ_4(mac, BWN_MACCTL);
3946 for (i = 35; i; i--) {
3947 tmp = BWN_READ_4(mac, BWN_INTR_REASON);
3948 if (tmp & BWN_INTR_MAC_SUSPENDED)
3949 goto out;
3950 DELAY(10);
3951 }
3952 for (i = 40; i; i--) {
3953 tmp = BWN_READ_4(mac, BWN_INTR_REASON);
3954 if (tmp & BWN_INTR_MAC_SUSPENDED)
3955 goto out;
3956 DELAY(1000);
3957 }
3958 device_printf(sc->sc_dev, "MAC suspend failed\n");
3959 }
3960 out:
3961 mac->mac_suspended++;
3962 }
3963
3964 void
bwn_mac_enable(struct bwn_mac * mac)3965 bwn_mac_enable(struct bwn_mac *mac)
3966 {
3967 struct bwn_softc *sc = mac->mac_sc;
3968 uint16_t state;
3969
3970 DPRINTF(mac->mac_sc, BWN_DEBUG_RESET, "%s: suspended=%d\n",
3971 __func__, mac->mac_suspended);
3972
3973 state = bwn_shm_read_2(mac, BWN_SHARED,
3974 BWN_SHARED_UCODESTAT);
3975 if (state != BWN_SHARED_UCODESTAT_SUSPEND &&
3976 state != BWN_SHARED_UCODESTAT_SLEEP) {
3977 DPRINTF(sc, BWN_DEBUG_FW,
3978 "%s: warn: firmware state (%d)\n",
3979 __func__, state);
3980 }
3981
3982 mac->mac_suspended--;
3983 KASSERT(mac->mac_suspended >= 0,
3984 ("%s:%d: fail", __func__, __LINE__));
3985 if (mac->mac_suspended == 0) {
3986 BWN_WRITE_4(mac, BWN_MACCTL,
3987 BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_ON);
3988 BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_MAC_SUSPENDED);
3989 BWN_READ_4(mac, BWN_MACCTL);
3990 BWN_READ_4(mac, BWN_INTR_REASON);
3991 bwn_psctl(mac, 0);
3992 }
3993 }
3994
3995 void
bwn_psctl(struct bwn_mac * mac,uint32_t flags)3996 bwn_psctl(struct bwn_mac *mac, uint32_t flags)
3997 {
3998 struct bwn_softc *sc = mac->mac_sc;
3999 int i;
4000 uint16_t ucstat;
4001
4002 KASSERT(!((flags & BWN_PS_ON) && (flags & BWN_PS_OFF)),
4003 ("%s:%d: fail", __func__, __LINE__));
4004 KASSERT(!((flags & BWN_PS_AWAKE) && (flags & BWN_PS_ASLEEP)),
4005 ("%s:%d: fail", __func__, __LINE__));
4006
4007 /* XXX forcibly awake and hwps-off */
4008
4009 BWN_WRITE_4(mac, BWN_MACCTL,
4010 (BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_AWAKE) &
4011 ~BWN_MACCTL_HWPS);
4012 BWN_READ_4(mac, BWN_MACCTL);
4013 if (bhnd_get_hwrev(sc->sc_dev) >= 5) {
4014 for (i = 0; i < 100; i++) {
4015 ucstat = bwn_shm_read_2(mac, BWN_SHARED,
4016 BWN_SHARED_UCODESTAT);
4017 if (ucstat != BWN_SHARED_UCODESTAT_SLEEP)
4018 break;
4019 DELAY(10);
4020 }
4021 }
4022 DPRINTF(mac->mac_sc, BWN_DEBUG_RESET, "%s: ucstat=%d\n", __func__,
4023 ucstat);
4024 }
4025
4026 static int
bwn_fw_gets(struct bwn_mac * mac,enum bwn_fwtype type)4027 bwn_fw_gets(struct bwn_mac *mac, enum bwn_fwtype type)
4028 {
4029 struct bwn_softc *sc = mac->mac_sc;
4030 struct bwn_fw *fw = &mac->mac_fw;
4031 const uint8_t rev = bhnd_get_hwrev(sc->sc_dev);
4032 const char *filename;
4033 uint16_t iost;
4034 int error;
4035
4036 /* microcode */
4037 filename = NULL;
4038 switch (rev) {
4039 case 42:
4040 if (mac->mac_phy.type == BWN_PHYTYPE_AC)
4041 filename = "ucode42";
4042 break;
4043 case 40:
4044 if (mac->mac_phy.type == BWN_PHYTYPE_AC)
4045 filename = "ucode40";
4046 break;
4047 case 33:
4048 if (mac->mac_phy.type == BWN_PHYTYPE_LCN40)
4049 filename = "ucode33_lcn40";
4050 break;
4051 case 30:
4052 if (mac->mac_phy.type == BWN_PHYTYPE_N)
4053 filename = "ucode30_mimo";
4054 break;
4055 case 29:
4056 if (mac->mac_phy.type == BWN_PHYTYPE_HT)
4057 filename = "ucode29_mimo";
4058 break;
4059 case 26:
4060 if (mac->mac_phy.type == BWN_PHYTYPE_HT)
4061 filename = "ucode26_mimo";
4062 break;
4063 case 28:
4064 case 25:
4065 if (mac->mac_phy.type == BWN_PHYTYPE_N)
4066 filename = "ucode25_mimo";
4067 else if (mac->mac_phy.type == BWN_PHYTYPE_LCN)
4068 filename = "ucode25_lcn";
4069 break;
4070 case 24:
4071 if (mac->mac_phy.type == BWN_PHYTYPE_LCN)
4072 filename = "ucode24_lcn";
4073 break;
4074 case 23:
4075 if (mac->mac_phy.type == BWN_PHYTYPE_N)
4076 filename = "ucode16_mimo";
4077 break;
4078 case 16:
4079 case 17:
4080 case 18:
4081 case 19:
4082 if (mac->mac_phy.type == BWN_PHYTYPE_N)
4083 filename = "ucode16_mimo";
4084 else if (mac->mac_phy.type == BWN_PHYTYPE_LP)
4085 filename = "ucode16_lp";
4086 break;
4087 case 15:
4088 filename = "ucode15";
4089 break;
4090 case 14:
4091 filename = "ucode14";
4092 break;
4093 case 13:
4094 filename = "ucode13";
4095 break;
4096 case 12:
4097 case 11:
4098 filename = "ucode11";
4099 break;
4100 case 10:
4101 case 9:
4102 case 8:
4103 case 7:
4104 case 6:
4105 case 5:
4106 filename = "ucode5";
4107 break;
4108 default:
4109 device_printf(sc->sc_dev, "no ucode for rev %d\n", rev);
4110 bwn_release_firmware(mac);
4111 return (EOPNOTSUPP);
4112 }
4113
4114 device_printf(sc->sc_dev, "ucode fw: %s\n", filename);
4115 error = bwn_fw_get(mac, type, filename, &fw->ucode);
4116 if (error) {
4117 bwn_release_firmware(mac);
4118 return (error);
4119 }
4120
4121 /* PCM */
4122 KASSERT(fw->no_pcmfile == 0, ("%s:%d fail", __func__, __LINE__));
4123 if (rev >= 5 && rev <= 10) {
4124 error = bwn_fw_get(mac, type, "pcm5", &fw->pcm);
4125 if (error == ENOENT)
4126 fw->no_pcmfile = 1;
4127 else if (error) {
4128 bwn_release_firmware(mac);
4129 return (error);
4130 }
4131 } else if (rev < 11) {
4132 device_printf(sc->sc_dev, "no PCM for rev %d\n", rev);
4133 bwn_release_firmware(mac);
4134 return (EOPNOTSUPP);
4135 }
4136
4137 /* initvals */
4138 error = bhnd_read_iost(sc->sc_dev, &iost);
4139 if (error)
4140 goto fail1;
4141
4142 switch (mac->mac_phy.type) {
4143 case BWN_PHYTYPE_A:
4144 if (rev < 5 || rev > 10)
4145 goto fail1;
4146 if (iost & BWN_IOST_HAVE_2GHZ)
4147 filename = "a0g1initvals5";
4148 else
4149 filename = "a0g0initvals5";
4150 break;
4151 case BWN_PHYTYPE_G:
4152 if (rev >= 5 && rev <= 10)
4153 filename = "b0g0initvals5";
4154 else if (rev >= 13)
4155 filename = "b0g0initvals13";
4156 else
4157 goto fail1;
4158 break;
4159 case BWN_PHYTYPE_LP:
4160 if (rev == 13)
4161 filename = "lp0initvals13";
4162 else if (rev == 14)
4163 filename = "lp0initvals14";
4164 else if (rev >= 15)
4165 filename = "lp0initvals15";
4166 else
4167 goto fail1;
4168 break;
4169 case BWN_PHYTYPE_N:
4170 if (rev == 30)
4171 filename = "n16initvals30";
4172 else if (rev == 28 || rev == 25)
4173 filename = "n0initvals25";
4174 else if (rev == 24)
4175 filename = "n0initvals24";
4176 else if (rev == 23)
4177 filename = "n0initvals16";
4178 else if (rev >= 16 && rev <= 18)
4179 filename = "n0initvals16";
4180 else if (rev >= 11 && rev <= 12)
4181 filename = "n0initvals11";
4182 else
4183 goto fail1;
4184 break;
4185 default:
4186 goto fail1;
4187 }
4188 error = bwn_fw_get(mac, type, filename, &fw->initvals);
4189 if (error) {
4190 bwn_release_firmware(mac);
4191 return (error);
4192 }
4193
4194 /* bandswitch initvals */
4195 switch (mac->mac_phy.type) {
4196 case BWN_PHYTYPE_A:
4197 if (rev >= 5 && rev <= 10) {
4198 if (iost & BWN_IOST_HAVE_2GHZ)
4199 filename = "a0g1bsinitvals5";
4200 else
4201 filename = "a0g0bsinitvals5";
4202 } else if (rev >= 11)
4203 filename = NULL;
4204 else
4205 goto fail1;
4206 break;
4207 case BWN_PHYTYPE_G:
4208 if (rev >= 5 && rev <= 10)
4209 filename = "b0g0bsinitvals5";
4210 else if (rev >= 11)
4211 filename = NULL;
4212 else
4213 goto fail1;
4214 break;
4215 case BWN_PHYTYPE_LP:
4216 if (rev == 13)
4217 filename = "lp0bsinitvals13";
4218 else if (rev == 14)
4219 filename = "lp0bsinitvals14";
4220 else if (rev >= 15)
4221 filename = "lp0bsinitvals15";
4222 else
4223 goto fail1;
4224 break;
4225 case BWN_PHYTYPE_N:
4226 if (rev == 30)
4227 filename = "n16bsinitvals30";
4228 else if (rev == 28 || rev == 25)
4229 filename = "n0bsinitvals25";
4230 else if (rev == 24)
4231 filename = "n0bsinitvals24";
4232 else if (rev == 23)
4233 filename = "n0bsinitvals16";
4234 else if (rev >= 16 && rev <= 18)
4235 filename = "n0bsinitvals16";
4236 else if (rev >= 11 && rev <= 12)
4237 filename = "n0bsinitvals11";
4238 else
4239 goto fail1;
4240 break;
4241 default:
4242 device_printf(sc->sc_dev, "unknown phy (%d)\n",
4243 mac->mac_phy.type);
4244 goto fail1;
4245 }
4246 error = bwn_fw_get(mac, type, filename, &fw->initvals_band);
4247 if (error) {
4248 bwn_release_firmware(mac);
4249 return (error);
4250 }
4251 return (0);
4252 fail1:
4253 device_printf(sc->sc_dev, "no INITVALS for rev %d, phy.type %d\n",
4254 rev, mac->mac_phy.type);
4255 bwn_release_firmware(mac);
4256 return (EOPNOTSUPP);
4257 }
4258
4259 static int
bwn_fw_get(struct bwn_mac * mac,enum bwn_fwtype type,const char * name,struct bwn_fwfile * bfw)4260 bwn_fw_get(struct bwn_mac *mac, enum bwn_fwtype type,
4261 const char *name, struct bwn_fwfile *bfw)
4262 {
4263 const struct bwn_fwhdr *hdr;
4264 struct bwn_softc *sc = mac->mac_sc;
4265 const struct firmware *fw;
4266 char namebuf[64];
4267
4268 if (name == NULL) {
4269 bwn_do_release_fw(bfw);
4270 return (0);
4271 }
4272 if (bfw->filename != NULL) {
4273 if (bfw->type == type && (strcmp(bfw->filename, name) == 0))
4274 return (0);
4275 bwn_do_release_fw(bfw);
4276 }
4277
4278 snprintf(namebuf, sizeof(namebuf), "bwn%s_v4_%s%s",
4279 (type == BWN_FWTYPE_OPENSOURCE) ? "-open" : "",
4280 (mac->mac_phy.type == BWN_PHYTYPE_LP) ? "lp_" : "", name);
4281 /* XXX Sleeping on "fwload" with the non-sleepable locks held */
4282 fw = firmware_get(namebuf);
4283 if (fw == NULL) {
4284 device_printf(sc->sc_dev, "the fw file(%s) not found\n",
4285 namebuf);
4286 return (ENOENT);
4287 }
4288 if (fw->datasize < sizeof(struct bwn_fwhdr))
4289 goto fail;
4290 hdr = (const struct bwn_fwhdr *)(fw->data);
4291 switch (hdr->type) {
4292 case BWN_FWTYPE_UCODE:
4293 case BWN_FWTYPE_PCM:
4294 if (be32toh(hdr->size) !=
4295 (fw->datasize - sizeof(struct bwn_fwhdr)))
4296 goto fail;
4297 /* FALLTHROUGH */
4298 case BWN_FWTYPE_IV:
4299 if (hdr->ver != 1)
4300 goto fail;
4301 break;
4302 default:
4303 goto fail;
4304 }
4305 bfw->filename = name;
4306 bfw->fw = fw;
4307 bfw->type = type;
4308 return (0);
4309 fail:
4310 device_printf(sc->sc_dev, "the fw file(%s) format error\n", namebuf);
4311 if (fw != NULL)
4312 firmware_put(fw, FIRMWARE_UNLOAD);
4313 return (EPROTO);
4314 }
4315
4316 static void
bwn_release_firmware(struct bwn_mac * mac)4317 bwn_release_firmware(struct bwn_mac *mac)
4318 {
4319
4320 bwn_do_release_fw(&mac->mac_fw.ucode);
4321 bwn_do_release_fw(&mac->mac_fw.pcm);
4322 bwn_do_release_fw(&mac->mac_fw.initvals);
4323 bwn_do_release_fw(&mac->mac_fw.initvals_band);
4324 }
4325
4326 static void
bwn_do_release_fw(struct bwn_fwfile * bfw)4327 bwn_do_release_fw(struct bwn_fwfile *bfw)
4328 {
4329
4330 if (bfw->fw != NULL)
4331 firmware_put(bfw->fw, FIRMWARE_UNLOAD);
4332 bfw->fw = NULL;
4333 bfw->filename = NULL;
4334 }
4335
4336 static int
bwn_fw_loaducode(struct bwn_mac * mac)4337 bwn_fw_loaducode(struct bwn_mac *mac)
4338 {
4339 #define GETFWOFFSET(fwp, offset) \
4340 ((const uint32_t *)((const char *)fwp.fw->data + offset))
4341 #define GETFWSIZE(fwp, offset) \
4342 ((fwp.fw->datasize - offset) / sizeof(uint32_t))
4343 struct bwn_softc *sc = mac->mac_sc;
4344 const uint32_t *data;
4345 unsigned int i;
4346 uint32_t ctl;
4347 uint16_t date, fwcaps, time;
4348 int error = 0;
4349
4350 ctl = BWN_READ_4(mac, BWN_MACCTL);
4351 ctl |= BWN_MACCTL_MCODE_JMP0;
4352 KASSERT(!(ctl & BWN_MACCTL_MCODE_RUN), ("%s:%d: fail", __func__,
4353 __LINE__));
4354 BWN_WRITE_4(mac, BWN_MACCTL, ctl);
4355 for (i = 0; i < 64; i++)
4356 bwn_shm_write_2(mac, BWN_SCRATCH, i, 0);
4357 for (i = 0; i < 4096; i += 2)
4358 bwn_shm_write_2(mac, BWN_SHARED, i, 0);
4359
4360 data = GETFWOFFSET(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
4361 bwn_shm_ctlword(mac, BWN_UCODE | BWN_SHARED_AUTOINC, 0x0000);
4362 for (i = 0; i < GETFWSIZE(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
4363 i++) {
4364 BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
4365 DELAY(10);
4366 }
4367
4368 if (mac->mac_fw.pcm.fw) {
4369 data = GETFWOFFSET(mac->mac_fw.pcm, sizeof(struct bwn_fwhdr));
4370 bwn_shm_ctlword(mac, BWN_HW, 0x01ea);
4371 BWN_WRITE_4(mac, BWN_SHM_DATA, 0x00004000);
4372 bwn_shm_ctlword(mac, BWN_HW, 0x01eb);
4373 for (i = 0; i < GETFWSIZE(mac->mac_fw.pcm,
4374 sizeof(struct bwn_fwhdr)); i++) {
4375 BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
4376 DELAY(10);
4377 }
4378 }
4379
4380 BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_ALL);
4381 BWN_WRITE_4(mac, BWN_MACCTL,
4382 (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_JMP0) |
4383 BWN_MACCTL_MCODE_RUN);
4384
4385 for (i = 0; i < 21; i++) {
4386 if (BWN_READ_4(mac, BWN_INTR_REASON) == BWN_INTR_MAC_SUSPENDED)
4387 break;
4388 if (i >= 20) {
4389 device_printf(sc->sc_dev, "ucode timeout\n");
4390 error = ENXIO;
4391 goto error;
4392 }
4393 DELAY(50000);
4394 }
4395 BWN_READ_4(mac, BWN_INTR_REASON);
4396
4397 mac->mac_fw.rev = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_REV);
4398 if (mac->mac_fw.rev <= 0x128) {
4399 device_printf(sc->sc_dev, "the firmware is too old\n");
4400 error = EOPNOTSUPP;
4401 goto error;
4402 }
4403
4404 /*
4405 * Determine firmware header version; needed for TX/RX packet
4406 * handling.
4407 */
4408 if (mac->mac_fw.rev >= 598)
4409 mac->mac_fw.fw_hdr_format = BWN_FW_HDR_598;
4410 else if (mac->mac_fw.rev >= 410)
4411 mac->mac_fw.fw_hdr_format = BWN_FW_HDR_410;
4412 else
4413 mac->mac_fw.fw_hdr_format = BWN_FW_HDR_351;
4414
4415 /*
4416 * We don't support rev 598 or later; that requires
4417 * another round of changes to the TX/RX descriptor
4418 * and status layout.
4419 *
4420 * So, complain this is the case and exit out, rather
4421 * than attaching and then failing.
4422 */
4423 #if 0
4424 if (mac->mac_fw.fw_hdr_format == BWN_FW_HDR_598) {
4425 device_printf(sc->sc_dev,
4426 "firmware is too new (>=598); not supported\n");
4427 error = EOPNOTSUPP;
4428 goto error;
4429 }
4430 #endif
4431
4432 mac->mac_fw.patch = bwn_shm_read_2(mac, BWN_SHARED,
4433 BWN_SHARED_UCODE_PATCH);
4434 date = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_DATE);
4435 mac->mac_fw.opensource = (date == 0xffff);
4436 if (bwn_wme != 0)
4437 mac->mac_flags |= BWN_MAC_FLAG_WME;
4438 mac->mac_flags |= BWN_MAC_FLAG_HWCRYPTO;
4439
4440 time = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_TIME);
4441 if (mac->mac_fw.opensource == 0) {
4442 device_printf(sc->sc_dev,
4443 "firmware version (rev %u patch %u date %#x time %#x)\n",
4444 mac->mac_fw.rev, mac->mac_fw.patch, date, time);
4445 if (mac->mac_fw.no_pcmfile)
4446 device_printf(sc->sc_dev,
4447 "no HW crypto acceleration due to pcm5\n");
4448 } else {
4449 mac->mac_fw.patch = time;
4450 fwcaps = bwn_fwcaps_read(mac);
4451 if (!(fwcaps & BWN_FWCAPS_HWCRYPTO) || mac->mac_fw.no_pcmfile) {
4452 device_printf(sc->sc_dev,
4453 "disabling HW crypto acceleration\n");
4454 mac->mac_flags &= ~BWN_MAC_FLAG_HWCRYPTO;
4455 }
4456 if (!(fwcaps & BWN_FWCAPS_WME)) {
4457 device_printf(sc->sc_dev, "disabling WME support\n");
4458 mac->mac_flags &= ~BWN_MAC_FLAG_WME;
4459 }
4460 }
4461
4462 if (BWN_ISOLDFMT(mac))
4463 device_printf(sc->sc_dev, "using old firmware image\n");
4464
4465 return (0);
4466
4467 error:
4468 BWN_WRITE_4(mac, BWN_MACCTL,
4469 (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_RUN) |
4470 BWN_MACCTL_MCODE_JMP0);
4471
4472 return (error);
4473 #undef GETFWSIZE
4474 #undef GETFWOFFSET
4475 }
4476
4477 /* OpenFirmware only */
4478 static uint16_t
bwn_fwcaps_read(struct bwn_mac * mac)4479 bwn_fwcaps_read(struct bwn_mac *mac)
4480 {
4481
4482 KASSERT(mac->mac_fw.opensource == 1,
4483 ("%s:%d: fail", __func__, __LINE__));
4484 return (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_FWCAPS));
4485 }
4486
4487 static int
bwn_fwinitvals_write(struct bwn_mac * mac,const struct bwn_fwinitvals * ivals,size_t count,size_t array_size)4488 bwn_fwinitvals_write(struct bwn_mac *mac, const struct bwn_fwinitvals *ivals,
4489 size_t count, size_t array_size)
4490 {
4491 #define GET_NEXTIV16(iv) \
4492 ((const struct bwn_fwinitvals *)((const uint8_t *)(iv) + \
4493 sizeof(uint16_t) + sizeof(uint16_t)))
4494 #define GET_NEXTIV32(iv) \
4495 ((const struct bwn_fwinitvals *)((const uint8_t *)(iv) + \
4496 sizeof(uint16_t) + sizeof(uint32_t)))
4497 struct bwn_softc *sc = mac->mac_sc;
4498 const struct bwn_fwinitvals *iv;
4499 uint16_t offset;
4500 size_t i;
4501 uint8_t bit32;
4502
4503 KASSERT(sizeof(struct bwn_fwinitvals) == 6,
4504 ("%s:%d: fail", __func__, __LINE__));
4505 iv = ivals;
4506 for (i = 0; i < count; i++) {
4507 if (array_size < sizeof(iv->offset_size))
4508 goto fail;
4509 array_size -= sizeof(iv->offset_size);
4510 offset = be16toh(iv->offset_size);
4511 bit32 = (offset & BWN_FWINITVALS_32BIT) ? 1 : 0;
4512 offset &= BWN_FWINITVALS_OFFSET_MASK;
4513 if (offset >= 0x1000)
4514 goto fail;
4515 if (bit32) {
4516 if (array_size < sizeof(iv->data.d32))
4517 goto fail;
4518 array_size -= sizeof(iv->data.d32);
4519 BWN_WRITE_4(mac, offset, be32toh(iv->data.d32));
4520 iv = GET_NEXTIV32(iv);
4521 } else {
4522 if (array_size < sizeof(iv->data.d16))
4523 goto fail;
4524 array_size -= sizeof(iv->data.d16);
4525 BWN_WRITE_2(mac, offset, be16toh(iv->data.d16));
4526
4527 iv = GET_NEXTIV16(iv);
4528 }
4529 }
4530 if (array_size != 0)
4531 goto fail;
4532 return (0);
4533 fail:
4534 device_printf(sc->sc_dev, "initvals: invalid format\n");
4535 return (EPROTO);
4536 #undef GET_NEXTIV16
4537 #undef GET_NEXTIV32
4538 }
4539
4540 int
bwn_switch_channel(struct bwn_mac * mac,int chan)4541 bwn_switch_channel(struct bwn_mac *mac, int chan)
4542 {
4543 struct bwn_phy *phy = &(mac->mac_phy);
4544 struct bwn_softc *sc = mac->mac_sc;
4545 struct ieee80211com *ic = &sc->sc_ic;
4546 uint16_t channelcookie, savedcookie;
4547 int error;
4548
4549 if (chan == 0xffff)
4550 chan = phy->get_default_chan(mac);
4551
4552 channelcookie = chan;
4553 if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan))
4554 channelcookie |= 0x100;
4555 savedcookie = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_CHAN);
4556 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, channelcookie);
4557 error = phy->switch_channel(mac, chan);
4558 if (error)
4559 goto fail;
4560
4561 mac->mac_phy.chan = chan;
4562 DELAY(8000);
4563 return (0);
4564 fail:
4565 device_printf(sc->sc_dev, "failed to switch channel\n");
4566 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, savedcookie);
4567 return (error);
4568 }
4569
4570 static uint16_t
bwn_ant2phy(int antenna)4571 bwn_ant2phy(int antenna)
4572 {
4573
4574 switch (antenna) {
4575 case BWN_ANT0:
4576 return (BWN_TX_PHY_ANT0);
4577 case BWN_ANT1:
4578 return (BWN_TX_PHY_ANT1);
4579 case BWN_ANT2:
4580 return (BWN_TX_PHY_ANT2);
4581 case BWN_ANT3:
4582 return (BWN_TX_PHY_ANT3);
4583 case BWN_ANTAUTO:
4584 return (BWN_TX_PHY_ANT01AUTO);
4585 }
4586 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
4587 return (0);
4588 }
4589
4590 static void
bwn_wme_load(struct bwn_mac * mac)4591 bwn_wme_load(struct bwn_mac *mac)
4592 {
4593 struct bwn_softc *sc = mac->mac_sc;
4594 int i;
4595
4596 KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
4597 ("%s:%d: fail", __func__, __LINE__));
4598
4599 bwn_mac_suspend(mac);
4600 for (i = 0; i < N(sc->sc_wmeParams); i++)
4601 bwn_wme_loadparams(mac, &(sc->sc_wmeParams[i]),
4602 bwn_wme_shm_offsets[i]);
4603 bwn_mac_enable(mac);
4604 }
4605
4606 static void
bwn_wme_loadparams(struct bwn_mac * mac,const struct wmeParams * p,uint16_t shm_offset)4607 bwn_wme_loadparams(struct bwn_mac *mac,
4608 const struct wmeParams *p, uint16_t shm_offset)
4609 {
4610 struct bwn_softc *sc = mac->mac_sc;
4611 uint16_t params[BWN_NR_WMEPARAMS];
4612 int slot, tmp;
4613 unsigned int i;
4614
4615 slot = BWN_READ_2(mac, BWN_RNG) &
4616 _IEEE80211_SHIFTMASK(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
4617
4618 memset(¶ms, 0, sizeof(params));
4619
4620 DPRINTF(sc, BWN_DEBUG_WME, "wmep_txopLimit %d wmep_logcwmin %d "
4621 "wmep_logcwmax %d wmep_aifsn %d\n", p->wmep_txopLimit,
4622 p->wmep_logcwmin, p->wmep_logcwmax, p->wmep_aifsn);
4623
4624 params[BWN_WMEPARAM_TXOP] = p->wmep_txopLimit * 32;
4625 params[BWN_WMEPARAM_CWMIN] =
4626 _IEEE80211_SHIFTMASK(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
4627 params[BWN_WMEPARAM_CWMAX] =
4628 _IEEE80211_SHIFTMASK(p->wmep_logcwmax, WME_PARAM_LOGCWMAX);
4629 params[BWN_WMEPARAM_CWCUR] =
4630 _IEEE80211_SHIFTMASK(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
4631 params[BWN_WMEPARAM_AIFS] = p->wmep_aifsn;
4632 params[BWN_WMEPARAM_BSLOTS] = slot;
4633 params[BWN_WMEPARAM_REGGAP] = slot + p->wmep_aifsn;
4634
4635 for (i = 0; i < N(params); i++) {
4636 if (i == BWN_WMEPARAM_STATUS) {
4637 tmp = bwn_shm_read_2(mac, BWN_SHARED,
4638 shm_offset + (i * 2));
4639 tmp |= 0x100;
4640 bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
4641 tmp);
4642 } else {
4643 bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
4644 params[i]);
4645 }
4646 }
4647 }
4648
4649 static void
bwn_mac_write_bssid(struct bwn_mac * mac)4650 bwn_mac_write_bssid(struct bwn_mac *mac)
4651 {
4652 struct bwn_softc *sc = mac->mac_sc;
4653 uint32_t tmp;
4654 int i;
4655 uint8_t mac_bssid[IEEE80211_ADDR_LEN * 2];
4656
4657 bwn_mac_setfilter(mac, BWN_MACFILTER_BSSID, sc->sc_bssid);
4658 memcpy(mac_bssid, sc->sc_ic.ic_macaddr, IEEE80211_ADDR_LEN);
4659 memcpy(mac_bssid + IEEE80211_ADDR_LEN, sc->sc_bssid,
4660 IEEE80211_ADDR_LEN);
4661
4662 for (i = 0; i < N(mac_bssid); i += sizeof(uint32_t)) {
4663 tmp = (uint32_t) (mac_bssid[i + 0]);
4664 tmp |= (uint32_t) (mac_bssid[i + 1]) << 8;
4665 tmp |= (uint32_t) (mac_bssid[i + 2]) << 16;
4666 tmp |= (uint32_t) (mac_bssid[i + 3]) << 24;
4667 bwn_ram_write(mac, 0x20 + i, tmp);
4668 }
4669 }
4670
4671 static void
bwn_mac_setfilter(struct bwn_mac * mac,uint16_t offset,const uint8_t * macaddr)4672 bwn_mac_setfilter(struct bwn_mac *mac, uint16_t offset,
4673 const uint8_t *macaddr)
4674 {
4675 static const uint8_t zero[IEEE80211_ADDR_LEN] = { 0 };
4676 uint16_t data;
4677
4678 if (!mac)
4679 macaddr = zero;
4680
4681 offset |= 0x0020;
4682 BWN_WRITE_2(mac, BWN_MACFILTER_CONTROL, offset);
4683
4684 data = macaddr[0];
4685 data |= macaddr[1] << 8;
4686 BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
4687 data = macaddr[2];
4688 data |= macaddr[3] << 8;
4689 BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
4690 data = macaddr[4];
4691 data |= macaddr[5] << 8;
4692 BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
4693 }
4694
4695 static void
bwn_key_dowrite(struct bwn_mac * mac,uint8_t index,uint8_t algorithm,const uint8_t * key,size_t key_len,const uint8_t * mac_addr)4696 bwn_key_dowrite(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
4697 const uint8_t *key, size_t key_len, const uint8_t *mac_addr)
4698 {
4699 uint8_t buf[BWN_SEC_KEYSIZE] = { 0, };
4700 uint8_t per_sta_keys_start = 8;
4701
4702 if (BWN_SEC_NEWAPI(mac))
4703 per_sta_keys_start = 4;
4704
4705 KASSERT(index < mac->mac_max_nr_keys,
4706 ("%s:%d: fail", __func__, __LINE__));
4707 KASSERT(key_len <= BWN_SEC_KEYSIZE,
4708 ("%s:%d: fail", __func__, __LINE__));
4709
4710 if (index >= per_sta_keys_start)
4711 bwn_key_macwrite(mac, index, NULL);
4712 if (key)
4713 memcpy(buf, key, key_len);
4714 bwn_key_write(mac, index, algorithm, buf);
4715 if (index >= per_sta_keys_start)
4716 bwn_key_macwrite(mac, index, mac_addr);
4717
4718 mac->mac_key[index].algorithm = algorithm;
4719 }
4720
4721 static void
bwn_key_macwrite(struct bwn_mac * mac,uint8_t index,const uint8_t * addr)4722 bwn_key_macwrite(struct bwn_mac *mac, uint8_t index, const uint8_t *addr)
4723 {
4724 struct bwn_softc *sc = mac->mac_sc;
4725 uint32_t addrtmp[2] = { 0, 0 };
4726 uint8_t start = 8;
4727
4728 if (BWN_SEC_NEWAPI(mac))
4729 start = 4;
4730
4731 KASSERT(index >= start,
4732 ("%s:%d: fail", __func__, __LINE__));
4733 index -= start;
4734
4735 if (addr) {
4736 addrtmp[0] = addr[0];
4737 addrtmp[0] |= ((uint32_t) (addr[1]) << 8);
4738 addrtmp[0] |= ((uint32_t) (addr[2]) << 16);
4739 addrtmp[0] |= ((uint32_t) (addr[3]) << 24);
4740 addrtmp[1] = addr[4];
4741 addrtmp[1] |= ((uint32_t) (addr[5]) << 8);
4742 }
4743
4744 if (bhnd_get_hwrev(sc->sc_dev) >= 5) {
4745 bwn_shm_write_4(mac, BWN_RCMTA, (index * 2) + 0, addrtmp[0]);
4746 bwn_shm_write_2(mac, BWN_RCMTA, (index * 2) + 1, addrtmp[1]);
4747 } else {
4748 if (index >= 8) {
4749 bwn_shm_write_4(mac, BWN_SHARED,
4750 BWN_SHARED_PSM + (index * 6) + 0, addrtmp[0]);
4751 bwn_shm_write_2(mac, BWN_SHARED,
4752 BWN_SHARED_PSM + (index * 6) + 4, addrtmp[1]);
4753 }
4754 }
4755 }
4756
4757 static void
bwn_key_write(struct bwn_mac * mac,uint8_t index,uint8_t algorithm,const uint8_t * key)4758 bwn_key_write(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
4759 const uint8_t *key)
4760 {
4761 unsigned int i;
4762 uint32_t offset;
4763 uint16_t kidx, value;
4764
4765 kidx = BWN_SEC_KEY2FW(mac, index);
4766 bwn_shm_write_2(mac, BWN_SHARED,
4767 BWN_SHARED_KEYIDX_BLOCK + (kidx * 2), (kidx << 4) | algorithm);
4768
4769 offset = mac->mac_ktp + (index * BWN_SEC_KEYSIZE);
4770 for (i = 0; i < BWN_SEC_KEYSIZE; i += 2) {
4771 value = key[i];
4772 value |= (uint16_t)(key[i + 1]) << 8;
4773 bwn_shm_write_2(mac, BWN_SHARED, offset + i, value);
4774 }
4775 }
4776
4777 static void
bwn_phy_exit(struct bwn_mac * mac)4778 bwn_phy_exit(struct bwn_mac *mac)
4779 {
4780
4781 mac->mac_phy.rf_onoff(mac, 0);
4782 if (mac->mac_phy.exit != NULL)
4783 mac->mac_phy.exit(mac);
4784 }
4785
4786 static void
bwn_dma_free(struct bwn_mac * mac)4787 bwn_dma_free(struct bwn_mac *mac)
4788 {
4789 struct bwn_dma *dma;
4790
4791 if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
4792 return;
4793 dma = &mac->mac_method.dma;
4794
4795 bwn_dma_ringfree(&dma->rx);
4796 bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
4797 bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
4798 bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
4799 bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
4800 bwn_dma_ringfree(&dma->mcast);
4801 }
4802
4803 static void
bwn_core_stop(struct bwn_mac * mac)4804 bwn_core_stop(struct bwn_mac *mac)
4805 {
4806 struct bwn_softc *sc = mac->mac_sc;
4807
4808 BWN_ASSERT_LOCKED(sc);
4809
4810 if (mac->mac_status < BWN_MAC_STATUS_STARTED)
4811 return;
4812
4813 callout_stop(&sc->sc_rfswitch_ch);
4814 callout_stop(&sc->sc_task_ch);
4815 callout_stop(&sc->sc_watchdog_ch);
4816 sc->sc_watchdog_timer = 0;
4817 BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
4818 BWN_READ_4(mac, BWN_INTR_MASK);
4819 bwn_mac_suspend(mac);
4820
4821 mac->mac_status = BWN_MAC_STATUS_INITED;
4822 }
4823
4824 static int
bwn_switch_band(struct bwn_softc * sc,struct ieee80211_channel * chan)4825 bwn_switch_band(struct bwn_softc *sc, struct ieee80211_channel *chan)
4826 {
4827 struct bwn_mac *up_dev = NULL;
4828 struct bwn_mac *down_dev;
4829 struct bwn_mac *mac;
4830 int err, status;
4831 uint8_t gmode;
4832
4833 BWN_ASSERT_LOCKED(sc);
4834
4835 TAILQ_FOREACH(mac, &sc->sc_maclist, mac_list) {
4836 if (IEEE80211_IS_CHAN_2GHZ(chan) &&
4837 mac->mac_phy.supports_2ghz) {
4838 up_dev = mac;
4839 gmode = 1;
4840 } else if (IEEE80211_IS_CHAN_5GHZ(chan) &&
4841 mac->mac_phy.supports_5ghz) {
4842 up_dev = mac;
4843 gmode = 0;
4844 } else {
4845 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
4846 return (EINVAL);
4847 }
4848 if (up_dev != NULL)
4849 break;
4850 }
4851 if (up_dev == NULL) {
4852 device_printf(sc->sc_dev, "Could not find a device\n");
4853 return (ENODEV);
4854 }
4855 if (up_dev == sc->sc_curmac && sc->sc_curmac->mac_phy.gmode == gmode)
4856 return (0);
4857
4858 DPRINTF(sc, BWN_DEBUG_RF | BWN_DEBUG_PHY | BWN_DEBUG_RESET,
4859 "switching to %s-GHz band\n",
4860 IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
4861
4862 down_dev = sc->sc_curmac;
4863 status = down_dev->mac_status;
4864 if (status >= BWN_MAC_STATUS_STARTED)
4865 bwn_core_stop(down_dev);
4866 if (status >= BWN_MAC_STATUS_INITED)
4867 bwn_core_exit(down_dev);
4868
4869 if (down_dev != up_dev) {
4870 err = bwn_phy_reset(down_dev);
4871 if (err)
4872 goto fail;
4873 }
4874
4875 up_dev->mac_phy.gmode = gmode;
4876 if (status >= BWN_MAC_STATUS_INITED) {
4877 err = bwn_core_init(up_dev);
4878 if (err) {
4879 device_printf(sc->sc_dev,
4880 "fatal: failed to initialize for %s-GHz\n",
4881 IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
4882 goto fail;
4883 }
4884 }
4885 if (status >= BWN_MAC_STATUS_STARTED)
4886 bwn_core_start(up_dev);
4887 KASSERT(up_dev->mac_status == status, ("%s: fail", __func__));
4888 sc->sc_curmac = up_dev;
4889
4890 return (0);
4891 fail:
4892 sc->sc_curmac = NULL;
4893 return (err);
4894 }
4895
4896 static void
bwn_rf_turnon(struct bwn_mac * mac)4897 bwn_rf_turnon(struct bwn_mac *mac)
4898 {
4899
4900 DPRINTF(mac->mac_sc, BWN_DEBUG_RESET, "%s: called\n", __func__);
4901
4902 bwn_mac_suspend(mac);
4903 mac->mac_phy.rf_onoff(mac, 1);
4904 mac->mac_phy.rf_on = 1;
4905 bwn_mac_enable(mac);
4906 }
4907
4908 static void
bwn_rf_turnoff(struct bwn_mac * mac)4909 bwn_rf_turnoff(struct bwn_mac *mac)
4910 {
4911
4912 DPRINTF(mac->mac_sc, BWN_DEBUG_RESET, "%s: called\n", __func__);
4913
4914 bwn_mac_suspend(mac);
4915 mac->mac_phy.rf_onoff(mac, 0);
4916 mac->mac_phy.rf_on = 0;
4917 bwn_mac_enable(mac);
4918 }
4919
4920 /*
4921 * PHY reset.
4922 */
4923 static int
bwn_phy_reset(struct bwn_mac * mac)4924 bwn_phy_reset(struct bwn_mac *mac)
4925 {
4926 struct bwn_softc *sc;
4927 uint16_t iost, mask;
4928 int error;
4929
4930 sc = mac->mac_sc;
4931
4932 iost = BWN_IOCTL_PHYRESET | BHND_IOCTL_CLK_FORCE;
4933 mask = iost | BWN_IOCTL_SUPPORT_G;
4934
4935 if ((error = bhnd_write_ioctl(sc->sc_dev, iost, mask)))
4936 return (error);
4937
4938 DELAY(1000);
4939
4940 iost &= ~BHND_IOCTL_CLK_FORCE;
4941
4942 if ((error = bhnd_write_ioctl(sc->sc_dev, iost, mask)))
4943 return (error);
4944
4945 DELAY(1000);
4946
4947 return (0);
4948 }
4949
4950 static int
bwn_newstate(struct ieee80211vap * vap,enum ieee80211_state nstate,int arg)4951 bwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
4952 {
4953 struct bwn_vap *bvp = BWN_VAP(vap);
4954 struct ieee80211com *ic= vap->iv_ic;
4955 enum ieee80211_state ostate = vap->iv_state;
4956 struct bwn_softc *sc = ic->ic_softc;
4957 struct bwn_mac *mac = sc->sc_curmac;
4958 int error;
4959
4960 DPRINTF(sc, BWN_DEBUG_STATE, "%s: %s -> %s\n", __func__,
4961 ieee80211_state_name[vap->iv_state],
4962 ieee80211_state_name[nstate]);
4963
4964 error = bvp->bv_newstate(vap, nstate, arg);
4965 if (error != 0)
4966 return (error);
4967
4968 BWN_LOCK(sc);
4969
4970 bwn_led_newstate(mac, nstate);
4971
4972 /*
4973 * Clear the BSSID when we stop a STA
4974 */
4975 if (vap->iv_opmode == IEEE80211_M_STA) {
4976 if (ostate == IEEE80211_S_RUN && nstate != IEEE80211_S_RUN) {
4977 /*
4978 * Clear out the BSSID. If we reassociate to
4979 * the same AP, this will reinialize things
4980 * correctly...
4981 */
4982 if (ic->ic_opmode == IEEE80211_M_STA &&
4983 (sc->sc_flags & BWN_FLAG_INVALID) == 0) {
4984 memset(sc->sc_bssid, 0, IEEE80211_ADDR_LEN);
4985 bwn_set_macaddr(mac);
4986 }
4987 }
4988 }
4989
4990 if (vap->iv_opmode == IEEE80211_M_MONITOR ||
4991 vap->iv_opmode == IEEE80211_M_AHDEMO) {
4992 /* XXX nothing to do? */
4993 } else if (nstate == IEEE80211_S_RUN) {
4994 memcpy(sc->sc_bssid, vap->iv_bss->ni_bssid, IEEE80211_ADDR_LEN);
4995 bwn_set_opmode(mac);
4996 bwn_set_pretbtt(mac);
4997 bwn_spu_setdelay(mac, 0);
4998 bwn_set_macaddr(mac);
4999 }
5000
5001 BWN_UNLOCK(sc);
5002
5003 return (error);
5004 }
5005
5006 static void
bwn_set_pretbtt(struct bwn_mac * mac)5007 bwn_set_pretbtt(struct bwn_mac *mac)
5008 {
5009 struct bwn_softc *sc = mac->mac_sc;
5010 struct ieee80211com *ic = &sc->sc_ic;
5011 uint16_t pretbtt;
5012
5013 if (ic->ic_opmode == IEEE80211_M_IBSS)
5014 pretbtt = 2;
5015 else
5016 pretbtt = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 120 : 250;
5017 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PRETBTT, pretbtt);
5018 BWN_WRITE_2(mac, BWN_TSF_CFP_PRETBTT, pretbtt);
5019 }
5020
5021 static int
bwn_intr(void * arg)5022 bwn_intr(void *arg)
5023 {
5024 struct bwn_mac *mac = arg;
5025 struct bwn_softc *sc = mac->mac_sc;
5026 uint32_t reason;
5027
5028 if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
5029 (sc->sc_flags & BWN_FLAG_INVALID))
5030 return (FILTER_STRAY);
5031
5032 DPRINTF(sc, BWN_DEBUG_INTR, "%s: called\n", __func__);
5033
5034 reason = BWN_READ_4(mac, BWN_INTR_REASON);
5035 if (reason == 0xffffffff) /* shared IRQ */
5036 return (FILTER_STRAY);
5037 reason &= mac->mac_intr_mask;
5038 if (reason == 0)
5039 return (FILTER_HANDLED);
5040 DPRINTF(sc, BWN_DEBUG_INTR, "%s: reason=0x%08x\n", __func__, reason);
5041
5042 mac->mac_reason[0] = BWN_READ_4(mac, BWN_DMA0_REASON) & 0x0001dc00;
5043 mac->mac_reason[1] = BWN_READ_4(mac, BWN_DMA1_REASON) & 0x0000dc00;
5044 mac->mac_reason[2] = BWN_READ_4(mac, BWN_DMA2_REASON) & 0x0000dc00;
5045 mac->mac_reason[3] = BWN_READ_4(mac, BWN_DMA3_REASON) & 0x0001dc00;
5046 mac->mac_reason[4] = BWN_READ_4(mac, BWN_DMA4_REASON) & 0x0000dc00;
5047 BWN_WRITE_4(mac, BWN_INTR_REASON, reason);
5048 BWN_WRITE_4(mac, BWN_DMA0_REASON, mac->mac_reason[0]);
5049 BWN_WRITE_4(mac, BWN_DMA1_REASON, mac->mac_reason[1]);
5050 BWN_WRITE_4(mac, BWN_DMA2_REASON, mac->mac_reason[2]);
5051 BWN_WRITE_4(mac, BWN_DMA3_REASON, mac->mac_reason[3]);
5052 BWN_WRITE_4(mac, BWN_DMA4_REASON, mac->mac_reason[4]);
5053
5054 /* Disable interrupts. */
5055 BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
5056
5057 mac->mac_reason_intr = reason;
5058
5059 BWN_BARRIER(mac, 0, 0, BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE);
5060
5061 taskqueue_enqueue(sc->sc_tq, &mac->mac_intrtask);
5062 return (FILTER_HANDLED);
5063 }
5064
5065 static void
bwn_intrtask(void * arg,int npending)5066 bwn_intrtask(void *arg, int npending)
5067 {
5068 struct bwn_mac *mac = arg;
5069 struct bwn_softc *sc = mac->mac_sc;
5070 uint32_t merged = 0;
5071 int i, tx = 0, rx = 0;
5072
5073 BWN_LOCK(sc);
5074 if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
5075 (sc->sc_flags & BWN_FLAG_INVALID)) {
5076 BWN_UNLOCK(sc);
5077 return;
5078 }
5079
5080 for (i = 0; i < N(mac->mac_reason); i++)
5081 merged |= mac->mac_reason[i];
5082
5083 if (mac->mac_reason_intr & BWN_INTR_MAC_TXERR)
5084 device_printf(sc->sc_dev, "MAC trans error\n");
5085
5086 if (mac->mac_reason_intr & BWN_INTR_PHY_TXERR) {
5087 DPRINTF(sc, BWN_DEBUG_INTR, "%s: PHY trans error\n", __func__);
5088 mac->mac_phy.txerrors--;
5089 if (mac->mac_phy.txerrors == 0) {
5090 mac->mac_phy.txerrors = BWN_TXERROR_MAX;
5091 bwn_restart(mac, "PHY TX errors");
5092 }
5093 }
5094
5095 if (merged & (BWN_DMAINTR_FATALMASK | BWN_DMAINTR_NONFATALMASK)) {
5096 if (merged & BWN_DMAINTR_FATALMASK) {
5097 device_printf(sc->sc_dev,
5098 "Fatal DMA error: %#x %#x %#x %#x %#x %#x\n",
5099 mac->mac_reason[0], mac->mac_reason[1],
5100 mac->mac_reason[2], mac->mac_reason[3],
5101 mac->mac_reason[4], mac->mac_reason[5]);
5102 bwn_restart(mac, "DMA error");
5103 BWN_UNLOCK(sc);
5104 return;
5105 }
5106 if (merged & BWN_DMAINTR_NONFATALMASK) {
5107 device_printf(sc->sc_dev,
5108 "DMA error: %#x %#x %#x %#x %#x %#x\n",
5109 mac->mac_reason[0], mac->mac_reason[1],
5110 mac->mac_reason[2], mac->mac_reason[3],
5111 mac->mac_reason[4], mac->mac_reason[5]);
5112 }
5113 }
5114
5115 if (mac->mac_reason_intr & BWN_INTR_UCODE_DEBUG)
5116 bwn_intr_ucode_debug(mac);
5117 if (mac->mac_reason_intr & BWN_INTR_TBTT_INDI)
5118 bwn_intr_tbtt_indication(mac);
5119 if (mac->mac_reason_intr & BWN_INTR_ATIM_END)
5120 bwn_intr_atim_end(mac);
5121 if (mac->mac_reason_intr & BWN_INTR_BEACON)
5122 bwn_intr_beacon(mac);
5123 if (mac->mac_reason_intr & BWN_INTR_PMQ)
5124 bwn_intr_pmq(mac);
5125 if (mac->mac_reason_intr & BWN_INTR_NOISESAMPLE_OK)
5126 bwn_intr_noise(mac);
5127
5128 if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
5129 if (mac->mac_reason[0] & BWN_DMAINTR_RX_DONE) {
5130 bwn_dma_rx(mac->mac_method.dma.rx);
5131 rx = 1;
5132 }
5133 } else
5134 rx = bwn_pio_rx(&mac->mac_method.pio.rx);
5135
5136 KASSERT(!(mac->mac_reason[1] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
5137 KASSERT(!(mac->mac_reason[2] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
5138 KASSERT(!(mac->mac_reason[3] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
5139 KASSERT(!(mac->mac_reason[4] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
5140 KASSERT(!(mac->mac_reason[5] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
5141
5142 if (mac->mac_reason_intr & BWN_INTR_TX_OK) {
5143 bwn_intr_txeof(mac);
5144 tx = 1;
5145 }
5146
5147 BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
5148
5149 if (sc->sc_blink_led != NULL && sc->sc_led_blink) {
5150 int evt = BWN_LED_EVENT_NONE;
5151
5152 if (tx && rx) {
5153 if (sc->sc_rx_rate > sc->sc_tx_rate)
5154 evt = BWN_LED_EVENT_RX;
5155 else
5156 evt = BWN_LED_EVENT_TX;
5157 } else if (tx) {
5158 evt = BWN_LED_EVENT_TX;
5159 } else if (rx) {
5160 evt = BWN_LED_EVENT_RX;
5161 } else if (rx == 0) {
5162 evt = BWN_LED_EVENT_POLL;
5163 }
5164
5165 if (evt != BWN_LED_EVENT_NONE)
5166 bwn_led_event(mac, evt);
5167 }
5168
5169 if (mbufq_first(&sc->sc_snd) != NULL)
5170 bwn_start(sc);
5171
5172 BWN_BARRIER(mac, 0, 0, BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE);
5173
5174 BWN_UNLOCK(sc);
5175 }
5176
5177 static void
bwn_restart(struct bwn_mac * mac,const char * msg)5178 bwn_restart(struct bwn_mac *mac, const char *msg)
5179 {
5180 struct bwn_softc *sc = mac->mac_sc;
5181 struct ieee80211com *ic = &sc->sc_ic;
5182
5183 if (mac->mac_status < BWN_MAC_STATUS_INITED)
5184 return;
5185
5186 device_printf(sc->sc_dev, "HW reset: %s\n", msg);
5187 ieee80211_runtask(ic, &mac->mac_hwreset);
5188 }
5189
5190 static void
bwn_intr_ucode_debug(struct bwn_mac * mac)5191 bwn_intr_ucode_debug(struct bwn_mac *mac)
5192 {
5193 struct bwn_softc *sc = mac->mac_sc;
5194 uint16_t reason;
5195
5196 if (mac->mac_fw.opensource == 0)
5197 return;
5198
5199 reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG);
5200 switch (reason) {
5201 case BWN_DEBUGINTR_PANIC:
5202 bwn_handle_fwpanic(mac);
5203 break;
5204 case BWN_DEBUGINTR_DUMP_SHM:
5205 device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_SHM\n");
5206 break;
5207 case BWN_DEBUGINTR_DUMP_REGS:
5208 device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_REGS\n");
5209 break;
5210 case BWN_DEBUGINTR_MARKER:
5211 device_printf(sc->sc_dev, "BWN_DEBUGINTR_MARKER\n");
5212 break;
5213 default:
5214 device_printf(sc->sc_dev,
5215 "ucode debug unknown reason: %#x\n", reason);
5216 }
5217
5218 bwn_shm_write_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG,
5219 BWN_DEBUGINTR_ACK);
5220 }
5221
5222 static void
bwn_intr_tbtt_indication(struct bwn_mac * mac)5223 bwn_intr_tbtt_indication(struct bwn_mac *mac)
5224 {
5225 struct bwn_softc *sc = mac->mac_sc;
5226 struct ieee80211com *ic = &sc->sc_ic;
5227
5228 if (ic->ic_opmode != IEEE80211_M_HOSTAP)
5229 bwn_psctl(mac, 0);
5230 if (ic->ic_opmode == IEEE80211_M_IBSS)
5231 mac->mac_flags |= BWN_MAC_FLAG_DFQVALID;
5232 }
5233
5234 static void
bwn_intr_atim_end(struct bwn_mac * mac)5235 bwn_intr_atim_end(struct bwn_mac *mac)
5236 {
5237
5238 if (mac->mac_flags & BWN_MAC_FLAG_DFQVALID) {
5239 BWN_WRITE_4(mac, BWN_MACCMD,
5240 BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_DFQ_VALID);
5241 mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
5242 }
5243 }
5244
5245 static void
bwn_intr_beacon(struct bwn_mac * mac)5246 bwn_intr_beacon(struct bwn_mac *mac)
5247 {
5248 struct bwn_softc *sc = mac->mac_sc;
5249 struct ieee80211com *ic = &sc->sc_ic;
5250 uint32_t cmd, beacon0, beacon1;
5251
5252 if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
5253 ic->ic_opmode == IEEE80211_M_MBSS)
5254 return;
5255
5256 mac->mac_intr_mask &= ~BWN_INTR_BEACON;
5257
5258 cmd = BWN_READ_4(mac, BWN_MACCMD);
5259 beacon0 = (cmd & BWN_MACCMD_BEACON0_VALID);
5260 beacon1 = (cmd & BWN_MACCMD_BEACON1_VALID);
5261
5262 if (beacon0 && beacon1) {
5263 BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_BEACON);
5264 mac->mac_intr_mask |= BWN_INTR_BEACON;
5265 return;
5266 }
5267
5268 if (sc->sc_flags & BWN_FLAG_NEED_BEACON_TP) {
5269 sc->sc_flags &= ~BWN_FLAG_NEED_BEACON_TP;
5270 bwn_load_beacon0(mac);
5271 bwn_load_beacon1(mac);
5272 cmd = BWN_READ_4(mac, BWN_MACCMD);
5273 cmd |= BWN_MACCMD_BEACON0_VALID;
5274 BWN_WRITE_4(mac, BWN_MACCMD, cmd);
5275 } else {
5276 if (!beacon0) {
5277 bwn_load_beacon0(mac);
5278 cmd = BWN_READ_4(mac, BWN_MACCMD);
5279 cmd |= BWN_MACCMD_BEACON0_VALID;
5280 BWN_WRITE_4(mac, BWN_MACCMD, cmd);
5281 } else if (!beacon1) {
5282 bwn_load_beacon1(mac);
5283 cmd = BWN_READ_4(mac, BWN_MACCMD);
5284 cmd |= BWN_MACCMD_BEACON1_VALID;
5285 BWN_WRITE_4(mac, BWN_MACCMD, cmd);
5286 }
5287 }
5288 }
5289
5290 static void
bwn_intr_pmq(struct bwn_mac * mac)5291 bwn_intr_pmq(struct bwn_mac *mac)
5292 {
5293 uint32_t tmp;
5294
5295 while (1) {
5296 tmp = BWN_READ_4(mac, BWN_PS_STATUS);
5297 if (!(tmp & 0x00000008))
5298 break;
5299 }
5300 BWN_WRITE_2(mac, BWN_PS_STATUS, 0x0002);
5301 }
5302
5303 static void
bwn_intr_noise(struct bwn_mac * mac)5304 bwn_intr_noise(struct bwn_mac *mac)
5305 {
5306 struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5307 uint16_t tmp;
5308 uint8_t noise[4];
5309 uint8_t i, j;
5310 int32_t average;
5311
5312 if (mac->mac_phy.type != BWN_PHYTYPE_G)
5313 return;
5314
5315 KASSERT(mac->mac_noise.noi_running, ("%s: fail", __func__));
5316 *((uint32_t *)noise) = htole32(bwn_jssi_read(mac));
5317 if (noise[0] == 0x7f || noise[1] == 0x7f || noise[2] == 0x7f ||
5318 noise[3] == 0x7f)
5319 goto new;
5320
5321 KASSERT(mac->mac_noise.noi_nsamples < 8,
5322 ("%s:%d: fail", __func__, __LINE__));
5323 i = mac->mac_noise.noi_nsamples;
5324 noise[0] = MIN(MAX(noise[0], 0), N(pg->pg_nrssi_lt) - 1);
5325 noise[1] = MIN(MAX(noise[1], 0), N(pg->pg_nrssi_lt) - 1);
5326 noise[2] = MIN(MAX(noise[2], 0), N(pg->pg_nrssi_lt) - 1);
5327 noise[3] = MIN(MAX(noise[3], 0), N(pg->pg_nrssi_lt) - 1);
5328 mac->mac_noise.noi_samples[i][0] = pg->pg_nrssi_lt[noise[0]];
5329 mac->mac_noise.noi_samples[i][1] = pg->pg_nrssi_lt[noise[1]];
5330 mac->mac_noise.noi_samples[i][2] = pg->pg_nrssi_lt[noise[2]];
5331 mac->mac_noise.noi_samples[i][3] = pg->pg_nrssi_lt[noise[3]];
5332 mac->mac_noise.noi_nsamples++;
5333 if (mac->mac_noise.noi_nsamples == 8) {
5334 average = 0;
5335 for (i = 0; i < 8; i++) {
5336 for (j = 0; j < 4; j++)
5337 average += mac->mac_noise.noi_samples[i][j];
5338 }
5339 average = (((average / 32) * 125) + 64) / 128;
5340 tmp = (bwn_shm_read_2(mac, BWN_SHARED, 0x40c) / 128) & 0x1f;
5341 if (tmp >= 8)
5342 average += 2;
5343 else
5344 average -= 25;
5345 average -= (tmp == 8) ? 72 : 48;
5346
5347 mac->mac_stats.link_noise = average;
5348 mac->mac_noise.noi_running = 0;
5349 return;
5350 }
5351 new:
5352 bwn_noise_gensample(mac);
5353 }
5354
5355 static int
bwn_pio_rx(struct bwn_pio_rxqueue * prq)5356 bwn_pio_rx(struct bwn_pio_rxqueue *prq)
5357 {
5358 struct bwn_mac *mac = prq->prq_mac;
5359 struct bwn_softc *sc = mac->mac_sc;
5360 unsigned int i;
5361
5362 BWN_ASSERT_LOCKED(sc);
5363
5364 if (mac->mac_status < BWN_MAC_STATUS_STARTED)
5365 return (0);
5366
5367 for (i = 0; i < 5000; i++) {
5368 if (bwn_pio_rxeof(prq) == 0)
5369 break;
5370 }
5371 if (i >= 5000)
5372 device_printf(sc->sc_dev, "too many RX frames in PIO mode\n");
5373 return ((i > 0) ? 1 : 0);
5374 }
5375
5376 static void
bwn_dma_rx(struct bwn_dma_ring * dr)5377 bwn_dma_rx(struct bwn_dma_ring *dr)
5378 {
5379 int slot, curslot;
5380
5381 KASSERT(!dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
5382 curslot = dr->get_curslot(dr);
5383 KASSERT(curslot >= 0 && curslot < dr->dr_numslots,
5384 ("%s:%d: fail", __func__, __LINE__));
5385
5386 slot = dr->dr_curslot;
5387 for (; slot != curslot; slot = bwn_dma_nextslot(dr, slot))
5388 bwn_dma_rxeof(dr, &slot);
5389
5390 bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
5391 BUS_DMASYNC_PREWRITE);
5392
5393 dr->set_curslot(dr, slot);
5394 dr->dr_curslot = slot;
5395 }
5396
5397 static void
bwn_intr_txeof(struct bwn_mac * mac)5398 bwn_intr_txeof(struct bwn_mac *mac)
5399 {
5400 struct bwn_txstatus stat;
5401 uint32_t stat0, stat1;
5402 uint16_t tmp;
5403
5404 BWN_ASSERT_LOCKED(mac->mac_sc);
5405
5406 while (1) {
5407 stat0 = BWN_READ_4(mac, BWN_XMITSTAT_0);
5408 if (!(stat0 & 0x00000001))
5409 break;
5410 stat1 = BWN_READ_4(mac, BWN_XMITSTAT_1);
5411
5412 DPRINTF(mac->mac_sc, BWN_DEBUG_XMIT,
5413 "%s: stat0=0x%08x, stat1=0x%08x\n",
5414 __func__,
5415 stat0,
5416 stat1);
5417
5418 stat.cookie = (stat0 >> 16);
5419 stat.seq = (stat1 & 0x0000ffff);
5420 stat.phy_stat = ((stat1 & 0x00ff0000) >> 16);
5421 tmp = (stat0 & 0x0000ffff);
5422 stat.framecnt = ((tmp & 0xf000) >> 12);
5423 stat.rtscnt = ((tmp & 0x0f00) >> 8);
5424 stat.sreason = ((tmp & 0x001c) >> 2);
5425 stat.pm = (tmp & 0x0080) ? 1 : 0;
5426 stat.im = (tmp & 0x0040) ? 1 : 0;
5427 stat.ampdu = (tmp & 0x0020) ? 1 : 0;
5428 stat.ack = (tmp & 0x0002) ? 1 : 0;
5429
5430 DPRINTF(mac->mac_sc, BWN_DEBUG_XMIT,
5431 "%s: cookie=%d, seq=%d, phystat=0x%02x, framecnt=%d, "
5432 "rtscnt=%d, sreason=%d, pm=%d, im=%d, ampdu=%d, ack=%d\n",
5433 __func__,
5434 stat.cookie,
5435 stat.seq,
5436 stat.phy_stat,
5437 stat.framecnt,
5438 stat.rtscnt,
5439 stat.sreason,
5440 stat.pm,
5441 stat.im,
5442 stat.ampdu,
5443 stat.ack);
5444
5445 bwn_handle_txeof(mac, &stat);
5446 }
5447 }
5448
5449 static void
bwn_hwreset(void * arg,int npending)5450 bwn_hwreset(void *arg, int npending)
5451 {
5452 struct bwn_mac *mac = arg;
5453 struct bwn_softc *sc = mac->mac_sc;
5454 int error = 0;
5455 int prev_status;
5456
5457 BWN_LOCK(sc);
5458
5459 prev_status = mac->mac_status;
5460 if (prev_status >= BWN_MAC_STATUS_STARTED)
5461 bwn_core_stop(mac);
5462 if (prev_status >= BWN_MAC_STATUS_INITED)
5463 bwn_core_exit(mac);
5464
5465 if (prev_status >= BWN_MAC_STATUS_INITED) {
5466 error = bwn_core_init(mac);
5467 if (error)
5468 goto out;
5469 }
5470 if (prev_status >= BWN_MAC_STATUS_STARTED)
5471 bwn_core_start(mac);
5472 out:
5473 if (error) {
5474 device_printf(sc->sc_dev, "%s: failed (%d)\n", __func__, error);
5475 sc->sc_curmac = NULL;
5476 }
5477 BWN_UNLOCK(sc);
5478 }
5479
5480 static void
bwn_handle_fwpanic(struct bwn_mac * mac)5481 bwn_handle_fwpanic(struct bwn_mac *mac)
5482 {
5483 struct bwn_softc *sc = mac->mac_sc;
5484 uint16_t reason;
5485
5486 reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_FWPANIC_REASON_REG);
5487 device_printf(sc->sc_dev,"fw panic (%u)\n", reason);
5488
5489 if (reason == BWN_FWPANIC_RESTART)
5490 bwn_restart(mac, "ucode panic");
5491 }
5492
5493 static void
bwn_load_beacon0(struct bwn_mac * mac)5494 bwn_load_beacon0(struct bwn_mac *mac)
5495 {
5496
5497 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5498 }
5499
5500 static void
bwn_load_beacon1(struct bwn_mac * mac)5501 bwn_load_beacon1(struct bwn_mac *mac)
5502 {
5503
5504 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5505 }
5506
5507 static uint32_t
bwn_jssi_read(struct bwn_mac * mac)5508 bwn_jssi_read(struct bwn_mac *mac)
5509 {
5510 uint32_t val = 0;
5511
5512 val = bwn_shm_read_2(mac, BWN_SHARED, 0x08a);
5513 val <<= 16;
5514 val |= bwn_shm_read_2(mac, BWN_SHARED, 0x088);
5515
5516 return (val);
5517 }
5518
5519 static void
bwn_noise_gensample(struct bwn_mac * mac)5520 bwn_noise_gensample(struct bwn_mac *mac)
5521 {
5522 uint32_t jssi = 0x7f7f7f7f;
5523
5524 bwn_shm_write_2(mac, BWN_SHARED, 0x088, (jssi & 0x0000ffff));
5525 bwn_shm_write_2(mac, BWN_SHARED, 0x08a, (jssi & 0xffff0000) >> 16);
5526 BWN_WRITE_4(mac, BWN_MACCMD,
5527 BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_BGNOISE);
5528 }
5529
5530 static int
bwn_dma_freeslot(struct bwn_dma_ring * dr)5531 bwn_dma_freeslot(struct bwn_dma_ring *dr)
5532 {
5533 BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
5534
5535 return (dr->dr_numslots - dr->dr_usedslot);
5536 }
5537
5538 static int
bwn_dma_nextslot(struct bwn_dma_ring * dr,int slot)5539 bwn_dma_nextslot(struct bwn_dma_ring *dr, int slot)
5540 {
5541 BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
5542
5543 KASSERT(slot >= -1 && slot <= dr->dr_numslots - 1,
5544 ("%s:%d: fail", __func__, __LINE__));
5545 if (slot == dr->dr_numslots - 1)
5546 return (0);
5547 return (slot + 1);
5548 }
5549
5550 static void
bwn_dma_rxeof(struct bwn_dma_ring * dr,int * slot)5551 bwn_dma_rxeof(struct bwn_dma_ring *dr, int *slot)
5552 {
5553 struct bwn_mac *mac = dr->dr_mac;
5554 struct bwn_softc *sc = mac->mac_sc;
5555 struct bwn_dma *dma = &mac->mac_method.dma;
5556 struct bwn_dmadesc_generic *desc;
5557 struct bwn_dmadesc_meta *meta;
5558 struct bwn_rxhdr4 *rxhdr;
5559 struct mbuf *m;
5560 uint32_t macstat;
5561 int32_t tmp;
5562 int cnt = 0;
5563 uint16_t len;
5564
5565 dr->getdesc(dr, *slot, &desc, &meta);
5566
5567 bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap, BUS_DMASYNC_POSTREAD);
5568 m = meta->mt_m;
5569
5570 if (bwn_dma_newbuf(dr, desc, meta, 0)) {
5571 counter_u64_add(sc->sc_ic.ic_ierrors, 1);
5572 return;
5573 }
5574
5575 rxhdr = mtod(m, struct bwn_rxhdr4 *);
5576 len = le16toh(rxhdr->frame_len);
5577 if (len <= 0) {
5578 counter_u64_add(sc->sc_ic.ic_ierrors, 1);
5579 return;
5580 }
5581 if (bwn_dma_check_redzone(dr, m)) {
5582 device_printf(sc->sc_dev, "redzone error.\n");
5583 bwn_dma_set_redzone(dr, m);
5584 bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
5585 BUS_DMASYNC_PREWRITE);
5586 return;
5587 }
5588 if (len > dr->dr_rx_bufsize) {
5589 tmp = len;
5590 while (1) {
5591 dr->getdesc(dr, *slot, &desc, &meta);
5592 bwn_dma_set_redzone(dr, meta->mt_m);
5593 bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
5594 BUS_DMASYNC_PREWRITE);
5595 *slot = bwn_dma_nextslot(dr, *slot);
5596 cnt++;
5597 tmp -= dr->dr_rx_bufsize;
5598 if (tmp <= 0)
5599 break;
5600 }
5601 device_printf(sc->sc_dev, "too small buffer "
5602 "(len %u buffer %u dropped %d)\n",
5603 len, dr->dr_rx_bufsize, cnt);
5604 return;
5605 }
5606
5607 switch (mac->mac_fw.fw_hdr_format) {
5608 case BWN_FW_HDR_351:
5609 case BWN_FW_HDR_410:
5610 macstat = le32toh(rxhdr->ps4.r351.mac_status);
5611 break;
5612 case BWN_FW_HDR_598:
5613 macstat = le32toh(rxhdr->ps4.r598.mac_status);
5614 break;
5615 }
5616
5617 if (macstat & BWN_RX_MAC_FCSERR) {
5618 if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
5619 device_printf(sc->sc_dev, "RX drop\n");
5620 return;
5621 }
5622 }
5623
5624 m->m_len = m->m_pkthdr.len = len + dr->dr_frameoffset;
5625 m_adj(m, dr->dr_frameoffset);
5626
5627 bwn_rxeof(dr->dr_mac, m, rxhdr);
5628 }
5629
5630 static void
bwn_handle_txeof(struct bwn_mac * mac,const struct bwn_txstatus * status)5631 bwn_handle_txeof(struct bwn_mac *mac, const struct bwn_txstatus *status)
5632 {
5633 struct bwn_softc *sc = mac->mac_sc;
5634 struct bwn_stats *stats = &mac->mac_stats;
5635
5636 BWN_ASSERT_LOCKED(mac->mac_sc);
5637
5638 if (status->im)
5639 device_printf(sc->sc_dev, "TODO: STATUS IM\n");
5640 if (status->ampdu)
5641 device_printf(sc->sc_dev, "TODO: STATUS AMPDU\n");
5642 if (status->rtscnt) {
5643 if (status->rtscnt == 0xf)
5644 stats->rtsfail++;
5645 else
5646 stats->rts++;
5647 }
5648
5649 if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
5650 bwn_dma_handle_txeof(mac, status);
5651 } else {
5652 bwn_pio_handle_txeof(mac, status);
5653 }
5654
5655 bwn_phy_txpower_check(mac, 0);
5656 }
5657
5658 static uint8_t
bwn_pio_rxeof(struct bwn_pio_rxqueue * prq)5659 bwn_pio_rxeof(struct bwn_pio_rxqueue *prq)
5660 {
5661 struct bwn_mac *mac = prq->prq_mac;
5662 struct bwn_softc *sc = mac->mac_sc;
5663 struct bwn_rxhdr4 rxhdr;
5664 struct mbuf *m;
5665 uint32_t ctl32, macstat, v32;
5666 unsigned int i, padding;
5667 uint16_t ctl16, len, totlen, v16;
5668 unsigned char *mp;
5669 char *data;
5670
5671 memset(&rxhdr, 0, sizeof(rxhdr));
5672
5673 if (prq->prq_rev >= 8) {
5674 ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
5675 if (!(ctl32 & BWN_PIO8_RXCTL_FRAMEREADY))
5676 return (0);
5677 bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
5678 BWN_PIO8_RXCTL_FRAMEREADY);
5679 for (i = 0; i < 10; i++) {
5680 ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
5681 if (ctl32 & BWN_PIO8_RXCTL_DATAREADY)
5682 goto ready;
5683 DELAY(10);
5684 }
5685 } else {
5686 ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
5687 if (!(ctl16 & BWN_PIO_RXCTL_FRAMEREADY))
5688 return (0);
5689 bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL,
5690 BWN_PIO_RXCTL_FRAMEREADY);
5691 for (i = 0; i < 10; i++) {
5692 ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
5693 if (ctl16 & BWN_PIO_RXCTL_DATAREADY)
5694 goto ready;
5695 DELAY(10);
5696 }
5697 }
5698 device_printf(sc->sc_dev, "%s: timed out\n", __func__);
5699 return (1);
5700 ready:
5701 if (prq->prq_rev >= 8) {
5702 bus_read_multi_4(sc->sc_mem_res,
5703 prq->prq_base + BWN_PIO8_RXDATA, (void *)&rxhdr,
5704 sizeof(rxhdr));
5705 } else {
5706 bus_read_multi_2(sc->sc_mem_res,
5707 prq->prq_base + BWN_PIO_RXDATA, (void *)&rxhdr,
5708 sizeof(rxhdr));
5709 }
5710 len = le16toh(rxhdr.frame_len);
5711 if (len > 0x700) {
5712 device_printf(sc->sc_dev, "%s: len is too big\n", __func__);
5713 goto error;
5714 }
5715 if (len == 0) {
5716 device_printf(sc->sc_dev, "%s: len is 0\n", __func__);
5717 goto error;
5718 }
5719
5720 switch (mac->mac_fw.fw_hdr_format) {
5721 case BWN_FW_HDR_351:
5722 case BWN_FW_HDR_410:
5723 macstat = le32toh(rxhdr.ps4.r351.mac_status);
5724 break;
5725 case BWN_FW_HDR_598:
5726 macstat = le32toh(rxhdr.ps4.r598.mac_status);
5727 break;
5728 }
5729
5730 if (macstat & BWN_RX_MAC_FCSERR) {
5731 if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
5732 device_printf(sc->sc_dev, "%s: FCS error", __func__);
5733 goto error;
5734 }
5735 }
5736
5737 padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
5738 totlen = len + padding;
5739 KASSERT(totlen <= MCLBYTES, ("too big..\n"));
5740 m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
5741 if (m == NULL) {
5742 device_printf(sc->sc_dev, "%s: out of memory", __func__);
5743 goto error;
5744 }
5745 mp = mtod(m, unsigned char *);
5746 if (prq->prq_rev >= 8) {
5747 bus_read_multi_4(sc->sc_mem_res,
5748 prq->prq_base + BWN_PIO8_RXDATA, (void *)mp, (totlen & ~3));
5749 if (totlen & 3) {
5750 v32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXDATA);
5751 data = &(mp[totlen - 1]);
5752 switch (totlen & 3) {
5753 case 3:
5754 *data = (v32 >> 16);
5755 data--;
5756 case 2:
5757 *data = (v32 >> 8);
5758 data--;
5759 case 1:
5760 *data = v32;
5761 }
5762 }
5763 } else {
5764 bus_read_multi_2(sc->sc_mem_res,
5765 prq->prq_base + BWN_PIO_RXDATA, (void *)mp, (totlen & ~1));
5766 if (totlen & 1) {
5767 v16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXDATA);
5768 mp[totlen - 1] = v16;
5769 }
5770 }
5771
5772 m->m_len = m->m_pkthdr.len = totlen;
5773
5774 bwn_rxeof(prq->prq_mac, m, &rxhdr);
5775
5776 return (1);
5777 error:
5778 if (prq->prq_rev >= 8)
5779 bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
5780 BWN_PIO8_RXCTL_DATAREADY);
5781 else
5782 bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL, BWN_PIO_RXCTL_DATAREADY);
5783 return (1);
5784 }
5785
5786 static int
bwn_dma_newbuf(struct bwn_dma_ring * dr,struct bwn_dmadesc_generic * desc,struct bwn_dmadesc_meta * meta,int init)5787 bwn_dma_newbuf(struct bwn_dma_ring *dr, struct bwn_dmadesc_generic *desc,
5788 struct bwn_dmadesc_meta *meta, int init)
5789 {
5790 struct bwn_mac *mac = dr->dr_mac;
5791 struct bwn_dma *dma = &mac->mac_method.dma;
5792 struct bwn_rxhdr4 *hdr;
5793 bus_dmamap_t map;
5794 bus_addr_t paddr;
5795 struct mbuf *m;
5796 int error;
5797
5798 m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
5799 if (m == NULL) {
5800 error = ENOBUFS;
5801
5802 /*
5803 * If the NIC is up and running, we need to:
5804 * - Clear RX buffer's header.
5805 * - Restore RX descriptor settings.
5806 */
5807 if (init)
5808 return (error);
5809 else
5810 goto back;
5811 }
5812 m->m_len = m->m_pkthdr.len = MCLBYTES;
5813
5814 bwn_dma_set_redzone(dr, m);
5815
5816 /*
5817 * Try to load RX buf into temporary DMA map
5818 */
5819 error = bus_dmamap_load_mbuf(dma->rxbuf_dtag, dr->dr_spare_dmap, m,
5820 bwn_dma_buf_addr, &paddr, BUS_DMA_NOWAIT);
5821 if (error) {
5822 m_freem(m);
5823
5824 /*
5825 * See the comment above
5826 */
5827 if (init)
5828 return (error);
5829 else
5830 goto back;
5831 }
5832
5833 if (!init)
5834 bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
5835 meta->mt_m = m;
5836 meta->mt_paddr = paddr;
5837
5838 /*
5839 * Swap RX buf's DMA map with the loaded temporary one
5840 */
5841 map = meta->mt_dmap;
5842 meta->mt_dmap = dr->dr_spare_dmap;
5843 dr->dr_spare_dmap = map;
5844
5845 back:
5846 /*
5847 * Clear RX buf header
5848 */
5849 hdr = mtod(meta->mt_m, struct bwn_rxhdr4 *);
5850 bzero(hdr, sizeof(*hdr));
5851 bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
5852 BUS_DMASYNC_PREWRITE);
5853
5854 /*
5855 * Setup RX buf descriptor
5856 */
5857 dr->setdesc(dr, desc, meta->mt_paddr, meta->mt_m->m_len -
5858 sizeof(*hdr), 0, 0, 0);
5859 return (error);
5860 }
5861
5862 static void
bwn_dma_buf_addr(void * arg,bus_dma_segment_t * seg,int nseg,bus_size_t mapsz __unused,int error)5863 bwn_dma_buf_addr(void *arg, bus_dma_segment_t *seg, int nseg,
5864 bus_size_t mapsz __unused, int error)
5865 {
5866
5867 if (!error) {
5868 KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
5869 *((bus_addr_t *)arg) = seg->ds_addr;
5870 }
5871 }
5872
5873 static int
bwn_hwrate2ieeerate(int rate)5874 bwn_hwrate2ieeerate(int rate)
5875 {
5876
5877 switch (rate) {
5878 case BWN_CCK_RATE_1MB:
5879 return (2);
5880 case BWN_CCK_RATE_2MB:
5881 return (4);
5882 case BWN_CCK_RATE_5MB:
5883 return (11);
5884 case BWN_CCK_RATE_11MB:
5885 return (22);
5886 case BWN_OFDM_RATE_6MB:
5887 return (12);
5888 case BWN_OFDM_RATE_9MB:
5889 return (18);
5890 case BWN_OFDM_RATE_12MB:
5891 return (24);
5892 case BWN_OFDM_RATE_18MB:
5893 return (36);
5894 case BWN_OFDM_RATE_24MB:
5895 return (48);
5896 case BWN_OFDM_RATE_36MB:
5897 return (72);
5898 case BWN_OFDM_RATE_48MB:
5899 return (96);
5900 case BWN_OFDM_RATE_54MB:
5901 return (108);
5902 default:
5903 printf("Ooops\n");
5904 return (0);
5905 }
5906 }
5907
5908 /*
5909 * Post process the RX provided RSSI.
5910 *
5911 * Valid for A, B, G, LP PHYs.
5912 */
5913 static int8_t
bwn_rx_rssi_calc(struct bwn_mac * mac,uint8_t in_rssi,int ofdm,int adjust_2053,int adjust_2050)5914 bwn_rx_rssi_calc(struct bwn_mac *mac, uint8_t in_rssi,
5915 int ofdm, int adjust_2053, int adjust_2050)
5916 {
5917 struct bwn_phy *phy = &mac->mac_phy;
5918 struct bwn_phy_g *gphy = &phy->phy_g;
5919 int tmp;
5920
5921 switch (phy->rf_ver) {
5922 case 0x2050:
5923 if (ofdm) {
5924 tmp = in_rssi;
5925 if (tmp > 127)
5926 tmp -= 256;
5927 tmp = tmp * 73 / 64;
5928 if (adjust_2050)
5929 tmp += 25;
5930 else
5931 tmp -= 3;
5932 } else {
5933 if (mac->mac_sc->sc_board_info.board_flags
5934 & BHND_BFL_ADCDIV) {
5935 if (in_rssi > 63)
5936 in_rssi = 63;
5937 tmp = gphy->pg_nrssi_lt[in_rssi];
5938 tmp = (31 - tmp) * -131 / 128 - 57;
5939 } else {
5940 tmp = in_rssi;
5941 tmp = (31 - tmp) * -149 / 128 - 68;
5942 }
5943 if (phy->type == BWN_PHYTYPE_G && adjust_2050)
5944 tmp += 25;
5945 }
5946 break;
5947 case 0x2060:
5948 if (in_rssi > 127)
5949 tmp = in_rssi - 256;
5950 else
5951 tmp = in_rssi;
5952 break;
5953 default:
5954 tmp = in_rssi;
5955 tmp = (tmp - 11) * 103 / 64;
5956 if (adjust_2053)
5957 tmp -= 109;
5958 else
5959 tmp -= 83;
5960 }
5961
5962 return (tmp);
5963 }
5964
5965 static void
bwn_rxeof(struct bwn_mac * mac,struct mbuf * m,const void * _rxhdr)5966 bwn_rxeof(struct bwn_mac *mac, struct mbuf *m, const void *_rxhdr)
5967 {
5968 const struct bwn_rxhdr4 *rxhdr = _rxhdr;
5969 struct bwn_plcp6 *plcp;
5970 struct bwn_softc *sc = mac->mac_sc;
5971 struct ieee80211_frame_min *wh;
5972 struct ieee80211_node *ni;
5973 struct ieee80211com *ic = &sc->sc_ic;
5974 uint32_t macstat;
5975 int padding, rate, rssi = 0, noise = 0;
5976 uint16_t phytype, phystat0, phystat3, chanstat;
5977 unsigned char *mp = mtod(m, unsigned char *);
5978
5979 BWN_ASSERT_LOCKED(sc);
5980
5981 phystat0 = le16toh(rxhdr->phy_status0);
5982
5983 /*
5984 * XXX Note: phy_status3 doesn't exist for HT-PHY; it's only
5985 * used for LP-PHY.
5986 */
5987 phystat3 = le16toh(rxhdr->ps3.lp.phy_status3);
5988
5989 switch (mac->mac_fw.fw_hdr_format) {
5990 case BWN_FW_HDR_351:
5991 case BWN_FW_HDR_410:
5992 macstat = le32toh(rxhdr->ps4.r351.mac_status);
5993 chanstat = le16toh(rxhdr->ps4.r351.channel);
5994 break;
5995 case BWN_FW_HDR_598:
5996 macstat = le32toh(rxhdr->ps4.r598.mac_status);
5997 chanstat = le16toh(rxhdr->ps4.r598.channel);
5998 break;
5999 }
6000
6001 phytype = chanstat & BWN_RX_CHAN_PHYTYPE;
6002
6003 if (macstat & BWN_RX_MAC_FCSERR)
6004 device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_FCS_CRC\n");
6005 if (phystat0 & (BWN_RX_PHYST0_PLCPHCF | BWN_RX_PHYST0_PLCPFV))
6006 device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_PLCP_CRC\n");
6007 if (macstat & BWN_RX_MAC_DECERR)
6008 goto drop;
6009
6010 padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
6011 if (m->m_pkthdr.len < (sizeof(struct bwn_plcp6) + padding)) {
6012 device_printf(sc->sc_dev, "frame too short (length=%d)\n",
6013 m->m_pkthdr.len);
6014 goto drop;
6015 }
6016 plcp = (struct bwn_plcp6 *)(mp + padding);
6017 m_adj(m, sizeof(struct bwn_plcp6) + padding);
6018 if (m->m_pkthdr.len < IEEE80211_MIN_LEN) {
6019 device_printf(sc->sc_dev, "frame too short (length=%d)\n",
6020 m->m_pkthdr.len);
6021 goto drop;
6022 }
6023 wh = mtod(m, struct ieee80211_frame_min *);
6024
6025 if (macstat & BWN_RX_MAC_DEC) {
6026 DPRINTF(sc, BWN_DEBUG_HWCRYPTO,
6027 "RX decryption attempted (old %d keyidx %#x)\n",
6028 BWN_ISOLDFMT(mac),
6029 (macstat & BWN_RX_MAC_KEYIDX) >> BWN_RX_MAC_KEYIDX_SHIFT);
6030 }
6031
6032 if (phystat0 & BWN_RX_PHYST0_OFDM)
6033 rate = bwn_plcp_get_ofdmrate(mac, plcp,
6034 phytype == BWN_PHYTYPE_A);
6035 else
6036 rate = bwn_plcp_get_cckrate(mac, plcp);
6037 if (rate == -1) {
6038 if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADPLCP))
6039 goto drop;
6040 }
6041 sc->sc_rx_rate = bwn_hwrate2ieeerate(rate);
6042
6043 /* rssi/noise */
6044 switch (phytype) {
6045 case BWN_PHYTYPE_A:
6046 case BWN_PHYTYPE_B:
6047 case BWN_PHYTYPE_G:
6048 case BWN_PHYTYPE_LP:
6049 rssi = bwn_rx_rssi_calc(mac, rxhdr->phy.abg.rssi,
6050 !! (phystat0 & BWN_RX_PHYST0_OFDM),
6051 !! (phystat0 & BWN_RX_PHYST0_GAINCTL),
6052 !! (phystat3 & BWN_RX_PHYST3_TRSTATE));
6053 break;
6054 case BWN_PHYTYPE_N:
6055 /* Broadcom has code for min/avg, but always used max */
6056 if (rxhdr->phy.n.power0 == 16 || rxhdr->phy.n.power0 == 32)
6057 rssi = max(rxhdr->phy.n.power1, rxhdr->ps2.n.power2);
6058 else
6059 rssi = max(rxhdr->phy.n.power0, rxhdr->phy.n.power1);
6060 #if 0
6061 DPRINTF(mac->mac_sc, BWN_DEBUG_RECV,
6062 "%s: power0=%d, power1=%d, power2=%d\n",
6063 __func__,
6064 rxhdr->phy.n.power0,
6065 rxhdr->phy.n.power1,
6066 rxhdr->ps2.n.power2);
6067 #endif
6068 break;
6069 default:
6070 /* XXX TODO: implement rssi for other PHYs */
6071 break;
6072 }
6073
6074 /*
6075 * RSSI here is absolute, not relative to the noise floor.
6076 */
6077 noise = mac->mac_stats.link_noise;
6078 rssi = rssi - noise;
6079
6080 /* RX radio tap */
6081 if (ieee80211_radiotap_active(ic))
6082 bwn_rx_radiotap(mac, m, rxhdr, plcp, rate, rssi, noise);
6083 m_adj(m, -IEEE80211_CRC_LEN);
6084
6085 BWN_UNLOCK(sc);
6086
6087 ni = ieee80211_find_rxnode(ic, wh);
6088 if (ni != NULL) {
6089 ieee80211_input(ni, m, rssi, noise);
6090 ieee80211_free_node(ni);
6091 } else
6092 ieee80211_input_all(ic, m, rssi, noise);
6093
6094 BWN_LOCK(sc);
6095 return;
6096 drop:
6097 device_printf(sc->sc_dev, "%s: dropped\n", __func__);
6098 }
6099
6100 static void
bwn_ratectl_tx_complete(const struct ieee80211_node * ni,const struct bwn_txstatus * status)6101 bwn_ratectl_tx_complete(const struct ieee80211_node *ni,
6102 const struct bwn_txstatus *status)
6103 {
6104 struct ieee80211_ratectl_tx_status txs;
6105 int retrycnt = 0;
6106
6107 /*
6108 * If we don't get an ACK, then we should log the
6109 * full framecnt. That may be 0 if it's a PHY
6110 * failure, so ensure that gets logged as some
6111 * retry attempt.
6112 */
6113 txs.flags = IEEE80211_RATECTL_STATUS_LONG_RETRY;
6114 if (status->ack) {
6115 txs.status = IEEE80211_RATECTL_TX_SUCCESS;
6116 retrycnt = status->framecnt - 1;
6117 } else {
6118 txs.status = IEEE80211_RATECTL_TX_FAIL_UNSPECIFIED;
6119 retrycnt = status->framecnt;
6120 if (retrycnt == 0)
6121 retrycnt = 1;
6122 }
6123 txs.long_retries = retrycnt;
6124 ieee80211_ratectl_tx_complete(ni, &txs);
6125 }
6126
6127 static void
bwn_dma_handle_txeof(struct bwn_mac * mac,const struct bwn_txstatus * status)6128 bwn_dma_handle_txeof(struct bwn_mac *mac,
6129 const struct bwn_txstatus *status)
6130 {
6131 struct bwn_dma *dma = &mac->mac_method.dma;
6132 struct bwn_dma_ring *dr;
6133 struct bwn_dmadesc_generic *desc;
6134 struct bwn_dmadesc_meta *meta;
6135 struct bwn_softc *sc = mac->mac_sc;
6136 int slot;
6137
6138 BWN_ASSERT_LOCKED(sc);
6139
6140 dr = bwn_dma_parse_cookie(mac, status, status->cookie, &slot);
6141 if (dr == NULL) {
6142 device_printf(sc->sc_dev, "failed to parse cookie\n");
6143 return;
6144 }
6145 KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
6146
6147 while (1) {
6148 KASSERT(slot >= 0 && slot < dr->dr_numslots,
6149 ("%s:%d: fail", __func__, __LINE__));
6150 dr->getdesc(dr, slot, &desc, &meta);
6151
6152 if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
6153 bus_dmamap_unload(dr->dr_txring_dtag, meta->mt_dmap);
6154 else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
6155 bus_dmamap_unload(dma->txbuf_dtag, meta->mt_dmap);
6156
6157 if (meta->mt_islast) {
6158 KASSERT(meta->mt_m != NULL,
6159 ("%s:%d: fail", __func__, __LINE__));
6160
6161 bwn_ratectl_tx_complete(meta->mt_ni, status);
6162 ieee80211_tx_complete(meta->mt_ni, meta->mt_m, 0);
6163 meta->mt_ni = NULL;
6164 meta->mt_m = NULL;
6165 } else
6166 KASSERT(meta->mt_m == NULL,
6167 ("%s:%d: fail", __func__, __LINE__));
6168
6169 dr->dr_usedslot--;
6170 if (meta->mt_islast)
6171 break;
6172 slot = bwn_dma_nextslot(dr, slot);
6173 }
6174 sc->sc_watchdog_timer = 0;
6175 if (dr->dr_stop) {
6176 KASSERT(bwn_dma_freeslot(dr) >= BWN_TX_SLOTS_PER_FRAME,
6177 ("%s:%d: fail", __func__, __LINE__));
6178 dr->dr_stop = 0;
6179 }
6180 }
6181
6182 static void
bwn_pio_handle_txeof(struct bwn_mac * mac,const struct bwn_txstatus * status)6183 bwn_pio_handle_txeof(struct bwn_mac *mac,
6184 const struct bwn_txstatus *status)
6185 {
6186 struct bwn_pio_txqueue *tq;
6187 struct bwn_pio_txpkt *tp = NULL;
6188 struct bwn_softc *sc = mac->mac_sc;
6189
6190 BWN_ASSERT_LOCKED(sc);
6191
6192 tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
6193 if (tq == NULL)
6194 return;
6195
6196 tq->tq_used -= roundup(tp->tp_m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
6197 tq->tq_free++;
6198
6199 if (tp->tp_ni != NULL) {
6200 /*
6201 * Do any tx complete callback. Note this must
6202 * be done before releasing the node reference.
6203 */
6204 bwn_ratectl_tx_complete(tp->tp_ni, status);
6205 }
6206 ieee80211_tx_complete(tp->tp_ni, tp->tp_m, 0);
6207 tp->tp_ni = NULL;
6208 tp->tp_m = NULL;
6209 TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
6210
6211 sc->sc_watchdog_timer = 0;
6212 }
6213
6214 static void
bwn_phy_txpower_check(struct bwn_mac * mac,uint32_t flags)6215 bwn_phy_txpower_check(struct bwn_mac *mac, uint32_t flags)
6216 {
6217 struct bwn_softc *sc = mac->mac_sc;
6218 struct bwn_phy *phy = &mac->mac_phy;
6219 struct ieee80211com *ic = &sc->sc_ic;
6220 unsigned long now;
6221 bwn_txpwr_result_t result;
6222
6223 BWN_GETTIME(now);
6224
6225 if (!(flags & BWN_TXPWR_IGNORE_TIME) && ieee80211_time_before(now, phy->nexttime))
6226 return;
6227 phy->nexttime = now + 2 * 1000;
6228
6229 if (sc->sc_board_info.board_vendor == PCI_VENDOR_BROADCOM &&
6230 sc->sc_board_info.board_type == BHND_BOARD_BU4306)
6231 return;
6232
6233 if (phy->recalc_txpwr != NULL) {
6234 result = phy->recalc_txpwr(mac,
6235 (flags & BWN_TXPWR_IGNORE_TSSI) ? 1 : 0);
6236 if (result == BWN_TXPWR_RES_DONE)
6237 return;
6238 KASSERT(result == BWN_TXPWR_RES_NEED_ADJUST,
6239 ("%s: fail", __func__));
6240 KASSERT(phy->set_txpwr != NULL, ("%s: fail", __func__));
6241
6242 ieee80211_runtask(ic, &mac->mac_txpower);
6243 }
6244 }
6245
6246 static uint16_t
bwn_pio_rx_read_2(struct bwn_pio_rxqueue * prq,uint16_t offset)6247 bwn_pio_rx_read_2(struct bwn_pio_rxqueue *prq, uint16_t offset)
6248 {
6249
6250 return (BWN_READ_2(prq->prq_mac, prq->prq_base + offset));
6251 }
6252
6253 static uint32_t
bwn_pio_rx_read_4(struct bwn_pio_rxqueue * prq,uint16_t offset)6254 bwn_pio_rx_read_4(struct bwn_pio_rxqueue *prq, uint16_t offset)
6255 {
6256
6257 return (BWN_READ_4(prq->prq_mac, prq->prq_base + offset));
6258 }
6259
6260 static void
bwn_pio_rx_write_2(struct bwn_pio_rxqueue * prq,uint16_t offset,uint16_t value)6261 bwn_pio_rx_write_2(struct bwn_pio_rxqueue *prq, uint16_t offset, uint16_t value)
6262 {
6263
6264 BWN_WRITE_2(prq->prq_mac, prq->prq_base + offset, value);
6265 }
6266
6267 static void
bwn_pio_rx_write_4(struct bwn_pio_rxqueue * prq,uint16_t offset,uint32_t value)6268 bwn_pio_rx_write_4(struct bwn_pio_rxqueue *prq, uint16_t offset, uint32_t value)
6269 {
6270
6271 BWN_WRITE_4(prq->prq_mac, prq->prq_base + offset, value);
6272 }
6273
6274 static int
bwn_ieeerate2hwrate(struct bwn_softc * sc,int rate)6275 bwn_ieeerate2hwrate(struct bwn_softc *sc, int rate)
6276 {
6277
6278 switch (rate) {
6279 /* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
6280 case 12:
6281 return (BWN_OFDM_RATE_6MB);
6282 case 18:
6283 return (BWN_OFDM_RATE_9MB);
6284 case 24:
6285 return (BWN_OFDM_RATE_12MB);
6286 case 36:
6287 return (BWN_OFDM_RATE_18MB);
6288 case 48:
6289 return (BWN_OFDM_RATE_24MB);
6290 case 72:
6291 return (BWN_OFDM_RATE_36MB);
6292 case 96:
6293 return (BWN_OFDM_RATE_48MB);
6294 case 108:
6295 return (BWN_OFDM_RATE_54MB);
6296 /* CCK rates (NB: not IEEE std, device-specific) */
6297 case 2:
6298 return (BWN_CCK_RATE_1MB);
6299 case 4:
6300 return (BWN_CCK_RATE_2MB);
6301 case 11:
6302 return (BWN_CCK_RATE_5MB);
6303 case 22:
6304 return (BWN_CCK_RATE_11MB);
6305 }
6306
6307 device_printf(sc->sc_dev, "unsupported rate %d\n", rate);
6308 return (BWN_CCK_RATE_1MB);
6309 }
6310
6311 static uint16_t
bwn_set_txhdr_phyctl1(struct bwn_mac * mac,uint8_t bitrate)6312 bwn_set_txhdr_phyctl1(struct bwn_mac *mac, uint8_t bitrate)
6313 {
6314 struct bwn_phy *phy = &mac->mac_phy;
6315 uint16_t control = 0;
6316 uint16_t bw;
6317
6318 /* XXX TODO: this is for LP phy, what about N-PHY, etc? */
6319 bw = BWN_TXH_PHY1_BW_20;
6320
6321 if (BWN_ISCCKRATE(bitrate) && phy->type != BWN_PHYTYPE_LP) {
6322 control = bw;
6323 } else {
6324 control = bw;
6325 /* Figure out coding rate and modulation */
6326 /* XXX TODO: table-ize, for MCS transmit */
6327 /* Note: this is BWN_*_RATE values */
6328 switch (bitrate) {
6329 case BWN_CCK_RATE_1MB:
6330 control |= 0;
6331 break;
6332 case BWN_CCK_RATE_2MB:
6333 control |= 1;
6334 break;
6335 case BWN_CCK_RATE_5MB:
6336 control |= 2;
6337 break;
6338 case BWN_CCK_RATE_11MB:
6339 control |= 3;
6340 break;
6341 case BWN_OFDM_RATE_6MB:
6342 control |= BWN_TXH_PHY1_CRATE_1_2;
6343 control |= BWN_TXH_PHY1_MODUL_BPSK;
6344 break;
6345 case BWN_OFDM_RATE_9MB:
6346 control |= BWN_TXH_PHY1_CRATE_3_4;
6347 control |= BWN_TXH_PHY1_MODUL_BPSK;
6348 break;
6349 case BWN_OFDM_RATE_12MB:
6350 control |= BWN_TXH_PHY1_CRATE_1_2;
6351 control |= BWN_TXH_PHY1_MODUL_QPSK;
6352 break;
6353 case BWN_OFDM_RATE_18MB:
6354 control |= BWN_TXH_PHY1_CRATE_3_4;
6355 control |= BWN_TXH_PHY1_MODUL_QPSK;
6356 break;
6357 case BWN_OFDM_RATE_24MB:
6358 control |= BWN_TXH_PHY1_CRATE_1_2;
6359 control |= BWN_TXH_PHY1_MODUL_QAM16;
6360 break;
6361 case BWN_OFDM_RATE_36MB:
6362 control |= BWN_TXH_PHY1_CRATE_3_4;
6363 control |= BWN_TXH_PHY1_MODUL_QAM16;
6364 break;
6365 case BWN_OFDM_RATE_48MB:
6366 control |= BWN_TXH_PHY1_CRATE_1_2;
6367 control |= BWN_TXH_PHY1_MODUL_QAM64;
6368 break;
6369 case BWN_OFDM_RATE_54MB:
6370 control |= BWN_TXH_PHY1_CRATE_3_4;
6371 control |= BWN_TXH_PHY1_MODUL_QAM64;
6372 break;
6373 default:
6374 break;
6375 }
6376 control |= BWN_TXH_PHY1_MODE_SISO;
6377 }
6378
6379 return control;
6380 }
6381
6382 static int
bwn_set_txhdr(struct bwn_mac * mac,struct ieee80211_node * ni,struct mbuf * m,struct bwn_txhdr * txhdr,uint16_t cookie)6383 bwn_set_txhdr(struct bwn_mac *mac, struct ieee80211_node *ni,
6384 struct mbuf *m, struct bwn_txhdr *txhdr, uint16_t cookie)
6385 {
6386 const struct bwn_phy *phy = &mac->mac_phy;
6387 struct bwn_softc *sc = mac->mac_sc;
6388 struct ieee80211_frame *wh;
6389 struct ieee80211_frame *protwh;
6390 const struct ieee80211_txparam *tp = ni->ni_txparms;
6391 struct ieee80211vap *vap = ni->ni_vap;
6392 struct ieee80211com *ic = &sc->sc_ic;
6393 struct mbuf *mprot;
6394 uint8_t *prot_ptr;
6395 unsigned int len;
6396 uint32_t macctl = 0;
6397 int rts_rate, rts_rate_fb, ismcast, isshort, type;
6398 uint16_t phyctl = 0;
6399 uint8_t rate, rate_fb;
6400 int fill_phy_ctl1 = 0;
6401
6402 wh = mtod(m, struct ieee80211_frame *);
6403 memset(txhdr, 0, sizeof(*txhdr));
6404
6405 type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
6406 ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
6407 isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0;
6408
6409 if ((phy->type == BWN_PHYTYPE_N) || (phy->type == BWN_PHYTYPE_LP)
6410 || (phy->type == BWN_PHYTYPE_HT))
6411 fill_phy_ctl1 = 1;
6412
6413 /*
6414 * Find TX rate
6415 */
6416 if (type != IEEE80211_FC0_TYPE_DATA || (m->m_flags & M_EAPOL))
6417 rate = rate_fb = tp->mgmtrate;
6418 else if (ismcast)
6419 rate = rate_fb = tp->mcastrate;
6420 else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
6421 rate = rate_fb = tp->ucastrate;
6422 else {
6423 ieee80211_ratectl_rate(ni, NULL, 0);
6424 rate = ieee80211_node_get_txrate_dot11rate(ni);
6425 /* TODO: assign rate_fb the previous rate, if available */
6426 rate_fb = rate;
6427 }
6428
6429 sc->sc_tx_rate = rate;
6430
6431 /* Note: this maps the select ieee80211 rate to hardware rate */
6432 rate = bwn_ieeerate2hwrate(sc, rate);
6433 rate_fb = bwn_ieeerate2hwrate(sc, rate_fb);
6434
6435 txhdr->phyrate = (BWN_ISOFDMRATE(rate)) ? bwn_plcp_getofdm(rate) :
6436 bwn_plcp_getcck(rate);
6437 bcopy(wh->i_fc, txhdr->macfc, sizeof(txhdr->macfc));
6438 bcopy(wh->i_addr1, txhdr->addr1, IEEE80211_ADDR_LEN);
6439
6440 /* XXX rate/rate_fb is the hardware rate */
6441 if ((rate_fb == rate) ||
6442 (*(u_int16_t *)wh->i_dur & htole16(0x8000)) ||
6443 (*(u_int16_t *)wh->i_dur == htole16(0)))
6444 txhdr->dur_fb = *(u_int16_t *)wh->i_dur;
6445 else
6446 txhdr->dur_fb = ieee80211_compute_duration(ic->ic_rt,
6447 m->m_pkthdr.len, rate, isshort);
6448
6449 /* XXX TX encryption */
6450
6451 switch (mac->mac_fw.fw_hdr_format) {
6452 case BWN_FW_HDR_351:
6453 bwn_plcp_genhdr((struct bwn_plcp4 *)(&txhdr->body.r351.plcp),
6454 m->m_pkthdr.len + IEEE80211_CRC_LEN, rate);
6455 break;
6456 case BWN_FW_HDR_410:
6457 bwn_plcp_genhdr((struct bwn_plcp4 *)(&txhdr->body.r410.plcp),
6458 m->m_pkthdr.len + IEEE80211_CRC_LEN, rate);
6459 break;
6460 case BWN_FW_HDR_598:
6461 bwn_plcp_genhdr((struct bwn_plcp4 *)(&txhdr->body.r598.plcp),
6462 m->m_pkthdr.len + IEEE80211_CRC_LEN, rate);
6463 break;
6464 }
6465
6466 bwn_plcp_genhdr((struct bwn_plcp4 *)(&txhdr->plcp_fb),
6467 m->m_pkthdr.len + IEEE80211_CRC_LEN, rate_fb);
6468
6469 txhdr->eftypes |= (BWN_ISOFDMRATE(rate_fb)) ? BWN_TX_EFT_FB_OFDM :
6470 BWN_TX_EFT_FB_CCK;
6471 txhdr->chan = phy->chan;
6472 phyctl |= (BWN_ISOFDMRATE(rate)) ? BWN_TX_PHY_ENC_OFDM :
6473 BWN_TX_PHY_ENC_CCK;
6474 /* XXX preamble? obey net80211 */
6475 if (isshort && (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
6476 rate == BWN_CCK_RATE_11MB))
6477 phyctl |= BWN_TX_PHY_SHORTPRMBL;
6478
6479 if (! phy->gmode)
6480 macctl |= BWN_TX_MAC_5GHZ;
6481
6482 /* XXX TX antenna selection */
6483
6484 switch (bwn_antenna_sanitize(mac, 0)) {
6485 case 0:
6486 phyctl |= BWN_TX_PHY_ANT01AUTO;
6487 break;
6488 case 1:
6489 phyctl |= BWN_TX_PHY_ANT0;
6490 break;
6491 case 2:
6492 phyctl |= BWN_TX_PHY_ANT1;
6493 break;
6494 case 3:
6495 phyctl |= BWN_TX_PHY_ANT2;
6496 break;
6497 case 4:
6498 phyctl |= BWN_TX_PHY_ANT3;
6499 break;
6500 default:
6501 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
6502 }
6503
6504 if (!ismcast)
6505 macctl |= BWN_TX_MAC_ACK;
6506
6507 macctl |= (BWN_TX_MAC_HWSEQ | BWN_TX_MAC_START_MSDU);
6508 if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
6509 m->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold)
6510 macctl |= BWN_TX_MAC_LONGFRAME;
6511
6512 if ((ic->ic_flags & IEEE80211_F_USEPROT) &&
6513 ic->ic_protmode != IEEE80211_PROT_NONE) {
6514 /* Note: don't fall back to CCK rates for 5G */
6515 if (phy->gmode)
6516 rts_rate = BWN_CCK_RATE_1MB;
6517 else
6518 rts_rate = BWN_OFDM_RATE_6MB;
6519 rts_rate_fb = bwn_get_fbrate(rts_rate);
6520
6521 /* XXX 'rate' here is hardware rate now, not the net80211 rate */
6522 mprot = ieee80211_alloc_prot(ni, m, rate, ic->ic_protmode);
6523 if (mprot == NULL) {
6524 if_inc_counter(vap->iv_ifp, IFCOUNTER_OERRORS, 1);
6525 device_printf(sc->sc_dev,
6526 "could not allocate mbuf for protection mode %d\n",
6527 ic->ic_protmode);
6528 return (ENOBUFS);
6529 }
6530
6531 switch (mac->mac_fw.fw_hdr_format) {
6532 case BWN_FW_HDR_351:
6533 prot_ptr = txhdr->body.r351.rts_frame;
6534 break;
6535 case BWN_FW_HDR_410:
6536 prot_ptr = txhdr->body.r410.rts_frame;
6537 break;
6538 case BWN_FW_HDR_598:
6539 prot_ptr = txhdr->body.r598.rts_frame;
6540 break;
6541 }
6542
6543 bcopy(mtod(mprot, uint8_t *), prot_ptr, mprot->m_pkthdr.len);
6544 m_freem(mprot);
6545
6546 if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) {
6547 macctl |= BWN_TX_MAC_SEND_CTSTOSELF;
6548 len = sizeof(struct ieee80211_frame_cts);
6549 } else {
6550 macctl |= BWN_TX_MAC_SEND_RTSCTS;
6551 len = sizeof(struct ieee80211_frame_rts);
6552 }
6553 len += IEEE80211_CRC_LEN;
6554
6555 switch (mac->mac_fw.fw_hdr_format) {
6556 case BWN_FW_HDR_351:
6557 bwn_plcp_genhdr((struct bwn_plcp4 *)
6558 &txhdr->body.r351.rts_plcp, len, rts_rate);
6559 break;
6560 case BWN_FW_HDR_410:
6561 bwn_plcp_genhdr((struct bwn_plcp4 *)
6562 &txhdr->body.r410.rts_plcp, len, rts_rate);
6563 break;
6564 case BWN_FW_HDR_598:
6565 bwn_plcp_genhdr((struct bwn_plcp4 *)
6566 &txhdr->body.r598.rts_plcp, len, rts_rate);
6567 break;
6568 }
6569
6570 bwn_plcp_genhdr((struct bwn_plcp4 *)&txhdr->rts_plcp_fb, len,
6571 rts_rate_fb);
6572
6573 switch (mac->mac_fw.fw_hdr_format) {
6574 case BWN_FW_HDR_351:
6575 protwh = (struct ieee80211_frame *)
6576 &txhdr->body.r351.rts_frame;
6577 break;
6578 case BWN_FW_HDR_410:
6579 protwh = (struct ieee80211_frame *)
6580 &txhdr->body.r410.rts_frame;
6581 break;
6582 case BWN_FW_HDR_598:
6583 protwh = (struct ieee80211_frame *)
6584 &txhdr->body.r598.rts_frame;
6585 break;
6586 }
6587
6588 txhdr->rts_dur_fb = *(u_int16_t *)protwh->i_dur;
6589
6590 if (BWN_ISOFDMRATE(rts_rate)) {
6591 txhdr->eftypes |= BWN_TX_EFT_RTS_OFDM;
6592 txhdr->phyrate_rts = bwn_plcp_getofdm(rts_rate);
6593 } else {
6594 txhdr->eftypes |= BWN_TX_EFT_RTS_CCK;
6595 txhdr->phyrate_rts = bwn_plcp_getcck(rts_rate);
6596 }
6597 txhdr->eftypes |= (BWN_ISOFDMRATE(rts_rate_fb)) ?
6598 BWN_TX_EFT_RTS_FBOFDM : BWN_TX_EFT_RTS_FBCCK;
6599
6600 if (fill_phy_ctl1) {
6601 txhdr->phyctl_1rts = htole16(bwn_set_txhdr_phyctl1(mac, rts_rate));
6602 txhdr->phyctl_1rtsfb = htole16(bwn_set_txhdr_phyctl1(mac, rts_rate_fb));
6603 }
6604 }
6605
6606 if (fill_phy_ctl1) {
6607 txhdr->phyctl_1 = htole16(bwn_set_txhdr_phyctl1(mac, rate));
6608 txhdr->phyctl_1fb = htole16(bwn_set_txhdr_phyctl1(mac, rate_fb));
6609 }
6610
6611 switch (mac->mac_fw.fw_hdr_format) {
6612 case BWN_FW_HDR_351:
6613 txhdr->body.r351.cookie = htole16(cookie);
6614 break;
6615 case BWN_FW_HDR_410:
6616 txhdr->body.r410.cookie = htole16(cookie);
6617 break;
6618 case BWN_FW_HDR_598:
6619 txhdr->body.r598.cookie = htole16(cookie);
6620 break;
6621 }
6622
6623 txhdr->macctl = htole32(macctl);
6624 txhdr->phyctl = htole16(phyctl);
6625
6626 /*
6627 * TX radio tap
6628 */
6629 if (ieee80211_radiotap_active_vap(vap)) {
6630 sc->sc_tx_th.wt_flags = 0;
6631 if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED)
6632 sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP;
6633 if (isshort &&
6634 (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
6635 rate == BWN_CCK_RATE_11MB))
6636 sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
6637 sc->sc_tx_th.wt_rate = rate;
6638
6639 ieee80211_radiotap_tx(vap, m);
6640 }
6641
6642 return (0);
6643 }
6644
6645 static void
bwn_plcp_genhdr(struct bwn_plcp4 * plcp,const uint16_t octets,const uint8_t rate)6646 bwn_plcp_genhdr(struct bwn_plcp4 *plcp, const uint16_t octets,
6647 const uint8_t rate)
6648 {
6649 uint32_t d, plen;
6650 uint8_t *raw = plcp->o.raw;
6651
6652 if (BWN_ISOFDMRATE(rate)) {
6653 d = bwn_plcp_getofdm(rate);
6654 KASSERT(!(octets & 0xf000),
6655 ("%s:%d: fail", __func__, __LINE__));
6656 d |= (octets << 5);
6657 plcp->o.data = htole32(d);
6658 } else {
6659 plen = octets * 16 / rate;
6660 if ((octets * 16 % rate) > 0) {
6661 plen++;
6662 if ((rate == BWN_CCK_RATE_11MB)
6663 && ((octets * 8 % 11) < 4)) {
6664 raw[1] = 0x84;
6665 } else
6666 raw[1] = 0x04;
6667 } else
6668 raw[1] = 0x04;
6669 plcp->o.data |= htole32(plen << 16);
6670 raw[0] = bwn_plcp_getcck(rate);
6671 }
6672 }
6673
6674 static uint8_t
bwn_antenna_sanitize(struct bwn_mac * mac,uint8_t n)6675 bwn_antenna_sanitize(struct bwn_mac *mac, uint8_t n)
6676 {
6677 struct bwn_softc *sc = mac->mac_sc;
6678 uint8_t mask;
6679
6680 if (n == 0)
6681 return (0);
6682 if (mac->mac_phy.gmode)
6683 mask = sc->sc_ant2g;
6684 else
6685 mask = sc->sc_ant5g;
6686 if (!(mask & (1 << (n - 1))))
6687 return (0);
6688 return (n);
6689 }
6690
6691 /*
6692 * Return a fallback rate for the given rate.
6693 *
6694 * Note: Don't fall back from OFDM to CCK.
6695 */
6696 static uint8_t
bwn_get_fbrate(uint8_t bitrate)6697 bwn_get_fbrate(uint8_t bitrate)
6698 {
6699 switch (bitrate) {
6700 /* CCK */
6701 case BWN_CCK_RATE_1MB:
6702 return (BWN_CCK_RATE_1MB);
6703 case BWN_CCK_RATE_2MB:
6704 return (BWN_CCK_RATE_1MB);
6705 case BWN_CCK_RATE_5MB:
6706 return (BWN_CCK_RATE_2MB);
6707 case BWN_CCK_RATE_11MB:
6708 return (BWN_CCK_RATE_5MB);
6709
6710 /* OFDM */
6711 case BWN_OFDM_RATE_6MB:
6712 return (BWN_OFDM_RATE_6MB);
6713 case BWN_OFDM_RATE_9MB:
6714 return (BWN_OFDM_RATE_6MB);
6715 case BWN_OFDM_RATE_12MB:
6716 return (BWN_OFDM_RATE_9MB);
6717 case BWN_OFDM_RATE_18MB:
6718 return (BWN_OFDM_RATE_12MB);
6719 case BWN_OFDM_RATE_24MB:
6720 return (BWN_OFDM_RATE_18MB);
6721 case BWN_OFDM_RATE_36MB:
6722 return (BWN_OFDM_RATE_24MB);
6723 case BWN_OFDM_RATE_48MB:
6724 return (BWN_OFDM_RATE_36MB);
6725 case BWN_OFDM_RATE_54MB:
6726 return (BWN_OFDM_RATE_48MB);
6727 }
6728 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
6729 return (0);
6730 }
6731
6732 static uint32_t
bwn_pio_write_multi_4(struct bwn_mac * mac,struct bwn_pio_txqueue * tq,uint32_t ctl,const void * _data,int len)6733 bwn_pio_write_multi_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
6734 uint32_t ctl, const void *_data, int len)
6735 {
6736 struct bwn_softc *sc = mac->mac_sc;
6737 uint32_t value = 0;
6738 const uint8_t *data = _data;
6739
6740 ctl |= BWN_PIO8_TXCTL_0_7 | BWN_PIO8_TXCTL_8_15 |
6741 BWN_PIO8_TXCTL_16_23 | BWN_PIO8_TXCTL_24_31;
6742 bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
6743
6744 bus_write_multi_4(sc->sc_mem_res, tq->tq_base + BWN_PIO8_TXDATA,
6745 __DECONST(void *, data), (len & ~3));
6746 if (len & 3) {
6747 ctl &= ~(BWN_PIO8_TXCTL_8_15 | BWN_PIO8_TXCTL_16_23 |
6748 BWN_PIO8_TXCTL_24_31);
6749 data = &(data[len - 1]);
6750 switch (len & 3) {
6751 case 3:
6752 ctl |= BWN_PIO8_TXCTL_16_23;
6753 value |= (uint32_t)(*data) << 16;
6754 data--;
6755 case 2:
6756 ctl |= BWN_PIO8_TXCTL_8_15;
6757 value |= (uint32_t)(*data) << 8;
6758 data--;
6759 case 1:
6760 value |= (uint32_t)(*data);
6761 }
6762 bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
6763 bwn_pio_write_4(mac, tq, BWN_PIO8_TXDATA, value);
6764 }
6765
6766 return (ctl);
6767 }
6768
6769 static void
bwn_pio_write_4(struct bwn_mac * mac,struct bwn_pio_txqueue * tq,uint16_t offset,uint32_t value)6770 bwn_pio_write_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
6771 uint16_t offset, uint32_t value)
6772 {
6773
6774 BWN_WRITE_4(mac, tq->tq_base + offset, value);
6775 }
6776
6777 static uint16_t
bwn_pio_write_multi_2(struct bwn_mac * mac,struct bwn_pio_txqueue * tq,uint16_t ctl,const void * _data,int len)6778 bwn_pio_write_multi_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
6779 uint16_t ctl, const void *_data, int len)
6780 {
6781 struct bwn_softc *sc = mac->mac_sc;
6782 const uint8_t *data = _data;
6783
6784 ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
6785 BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
6786
6787 bus_write_multi_2(sc->sc_mem_res, tq->tq_base + BWN_PIO_TXDATA,
6788 __DECONST(void *, data), (len & ~1));
6789 if (len & 1) {
6790 ctl &= ~BWN_PIO_TXCTL_WRITEHI;
6791 BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
6792 BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data[len - 1]);
6793 }
6794
6795 return (ctl);
6796 }
6797
6798 static uint16_t
bwn_pio_write_mbuf_2(struct bwn_mac * mac,struct bwn_pio_txqueue * tq,uint16_t ctl,struct mbuf * m0)6799 bwn_pio_write_mbuf_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
6800 uint16_t ctl, struct mbuf *m0)
6801 {
6802 int i, j = 0;
6803 uint16_t data = 0;
6804 const uint8_t *buf;
6805 struct mbuf *m = m0;
6806
6807 ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
6808 BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
6809
6810 for (; m != NULL; m = m->m_next) {
6811 buf = mtod(m, const uint8_t *);
6812 for (i = 0; i < m->m_len; i++) {
6813 if (!((j++) % 2))
6814 data |= buf[i];
6815 else {
6816 data |= (buf[i] << 8);
6817 BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
6818 data = 0;
6819 }
6820 }
6821 }
6822 if (m0->m_pkthdr.len % 2) {
6823 ctl &= ~BWN_PIO_TXCTL_WRITEHI;
6824 BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
6825 BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
6826 }
6827
6828 return (ctl);
6829 }
6830
6831 static void
bwn_set_slot_time(struct bwn_mac * mac,uint16_t time)6832 bwn_set_slot_time(struct bwn_mac *mac, uint16_t time)
6833 {
6834
6835 /* XXX should exit if 5GHz band .. */
6836 if (mac->mac_phy.type != BWN_PHYTYPE_G)
6837 return;
6838
6839 BWN_WRITE_2(mac, 0x684, 510 + time);
6840 /* Disabled in Linux b43, can adversely effect performance */
6841 #if 0
6842 bwn_shm_write_2(mac, BWN_SHARED, 0x0010, time);
6843 #endif
6844 }
6845
6846 static struct bwn_dma_ring *
bwn_dma_select(struct bwn_mac * mac,uint8_t prio)6847 bwn_dma_select(struct bwn_mac *mac, uint8_t prio)
6848 {
6849
6850 if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
6851 return (mac->mac_method.dma.wme[WME_AC_BE]);
6852
6853 switch (prio) {
6854 case 3:
6855 return (mac->mac_method.dma.wme[WME_AC_VO]);
6856 case 2:
6857 return (mac->mac_method.dma.wme[WME_AC_VI]);
6858 case 0:
6859 return (mac->mac_method.dma.wme[WME_AC_BE]);
6860 case 1:
6861 return (mac->mac_method.dma.wme[WME_AC_BK]);
6862 }
6863 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
6864 return (NULL);
6865 }
6866
6867 static int
bwn_dma_getslot(struct bwn_dma_ring * dr)6868 bwn_dma_getslot(struct bwn_dma_ring *dr)
6869 {
6870 int slot;
6871
6872 BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
6873
6874 KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
6875 KASSERT(!(dr->dr_stop), ("%s:%d: fail", __func__, __LINE__));
6876 KASSERT(bwn_dma_freeslot(dr) != 0, ("%s:%d: fail", __func__, __LINE__));
6877
6878 slot = bwn_dma_nextslot(dr, dr->dr_curslot);
6879 KASSERT(!(slot & ~0x0fff), ("%s:%d: fail", __func__, __LINE__));
6880 dr->dr_curslot = slot;
6881 dr->dr_usedslot++;
6882
6883 return (slot);
6884 }
6885
6886 static struct bwn_pio_txqueue *
bwn_pio_parse_cookie(struct bwn_mac * mac,uint16_t cookie,struct bwn_pio_txpkt ** pack)6887 bwn_pio_parse_cookie(struct bwn_mac *mac, uint16_t cookie,
6888 struct bwn_pio_txpkt **pack)
6889 {
6890 struct bwn_pio *pio = &mac->mac_method.pio;
6891 struct bwn_pio_txqueue *tq = NULL;
6892 unsigned int index;
6893
6894 switch (cookie & 0xf000) {
6895 case 0x1000:
6896 tq = &pio->wme[WME_AC_BK];
6897 break;
6898 case 0x2000:
6899 tq = &pio->wme[WME_AC_BE];
6900 break;
6901 case 0x3000:
6902 tq = &pio->wme[WME_AC_VI];
6903 break;
6904 case 0x4000:
6905 tq = &pio->wme[WME_AC_VO];
6906 break;
6907 case 0x5000:
6908 tq = &pio->mcast;
6909 break;
6910 }
6911 KASSERT(tq != NULL, ("%s:%d: fail", __func__, __LINE__));
6912 if (tq == NULL)
6913 return (NULL);
6914 index = (cookie & 0x0fff);
6915 KASSERT(index < N(tq->tq_pkts), ("%s:%d: fail", __func__, __LINE__));
6916 if (index >= N(tq->tq_pkts))
6917 return (NULL);
6918 *pack = &tq->tq_pkts[index];
6919 KASSERT(*pack != NULL, ("%s:%d: fail", __func__, __LINE__));
6920 return (tq);
6921 }
6922
6923 static void
bwn_txpwr(void * arg,int npending)6924 bwn_txpwr(void *arg, int npending)
6925 {
6926 struct bwn_mac *mac = arg;
6927 struct bwn_softc *sc;
6928
6929 if (mac == NULL)
6930 return;
6931
6932 sc = mac->mac_sc;
6933
6934 BWN_LOCK(sc);
6935 if (mac->mac_status >= BWN_MAC_STATUS_STARTED &&
6936 mac->mac_phy.set_txpwr != NULL)
6937 mac->mac_phy.set_txpwr(mac);
6938 BWN_UNLOCK(sc);
6939 }
6940
6941 static void
bwn_task_15s(struct bwn_mac * mac)6942 bwn_task_15s(struct bwn_mac *mac)
6943 {
6944 uint16_t reg;
6945
6946 if (mac->mac_fw.opensource) {
6947 reg = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG);
6948 if (reg) {
6949 bwn_restart(mac, "fw watchdog");
6950 return;
6951 }
6952 bwn_shm_write_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG, 1);
6953 }
6954 if (mac->mac_phy.task_15s)
6955 mac->mac_phy.task_15s(mac);
6956
6957 mac->mac_phy.txerrors = BWN_TXERROR_MAX;
6958 }
6959
6960 static void
bwn_task_30s(struct bwn_mac * mac)6961 bwn_task_30s(struct bwn_mac *mac)
6962 {
6963
6964 if (mac->mac_phy.type != BWN_PHYTYPE_G || mac->mac_noise.noi_running)
6965 return;
6966 mac->mac_noise.noi_running = 1;
6967 mac->mac_noise.noi_nsamples = 0;
6968
6969 bwn_noise_gensample(mac);
6970 }
6971
6972 static void
bwn_task_60s(struct bwn_mac * mac)6973 bwn_task_60s(struct bwn_mac *mac)
6974 {
6975
6976 if (mac->mac_phy.task_60s)
6977 mac->mac_phy.task_60s(mac);
6978 bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME);
6979 }
6980
6981 static void
bwn_tasks(void * arg)6982 bwn_tasks(void *arg)
6983 {
6984 struct bwn_mac *mac = arg;
6985 struct bwn_softc *sc = mac->mac_sc;
6986
6987 BWN_ASSERT_LOCKED(sc);
6988 if (mac->mac_status != BWN_MAC_STATUS_STARTED)
6989 return;
6990
6991 if (mac->mac_task_state % 4 == 0)
6992 bwn_task_60s(mac);
6993 if (mac->mac_task_state % 2 == 0)
6994 bwn_task_30s(mac);
6995 bwn_task_15s(mac);
6996
6997 mac->mac_task_state++;
6998 callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
6999 }
7000
7001 static int
bwn_plcp_get_ofdmrate(struct bwn_mac * mac,struct bwn_plcp6 * plcp,uint8_t a)7002 bwn_plcp_get_ofdmrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp, uint8_t a)
7003 {
7004 struct bwn_softc *sc = mac->mac_sc;
7005
7006 KASSERT(a == 0, ("not support APHY\n"));
7007
7008 switch (plcp->o.raw[0] & 0xf) {
7009 case 0xb:
7010 return (BWN_OFDM_RATE_6MB);
7011 case 0xf:
7012 return (BWN_OFDM_RATE_9MB);
7013 case 0xa:
7014 return (BWN_OFDM_RATE_12MB);
7015 case 0xe:
7016 return (BWN_OFDM_RATE_18MB);
7017 case 0x9:
7018 return (BWN_OFDM_RATE_24MB);
7019 case 0xd:
7020 return (BWN_OFDM_RATE_36MB);
7021 case 0x8:
7022 return (BWN_OFDM_RATE_48MB);
7023 case 0xc:
7024 return (BWN_OFDM_RATE_54MB);
7025 }
7026 device_printf(sc->sc_dev, "incorrect OFDM rate %d\n",
7027 plcp->o.raw[0] & 0xf);
7028 return (-1);
7029 }
7030
7031 static int
bwn_plcp_get_cckrate(struct bwn_mac * mac,struct bwn_plcp6 * plcp)7032 bwn_plcp_get_cckrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp)
7033 {
7034 struct bwn_softc *sc = mac->mac_sc;
7035
7036 switch (plcp->o.raw[0]) {
7037 case 0x0a:
7038 return (BWN_CCK_RATE_1MB);
7039 case 0x14:
7040 return (BWN_CCK_RATE_2MB);
7041 case 0x37:
7042 return (BWN_CCK_RATE_5MB);
7043 case 0x6e:
7044 return (BWN_CCK_RATE_11MB);
7045 }
7046 device_printf(sc->sc_dev, "incorrect CCK rate %d\n", plcp->o.raw[0]);
7047 return (-1);
7048 }
7049
7050 static void
bwn_rx_radiotap(struct bwn_mac * mac,struct mbuf * m,const struct bwn_rxhdr4 * rxhdr,struct bwn_plcp6 * plcp,int rate,int rssi,int noise)7051 bwn_rx_radiotap(struct bwn_mac *mac, struct mbuf *m,
7052 const struct bwn_rxhdr4 *rxhdr, struct bwn_plcp6 *plcp, int rate,
7053 int rssi, int noise)
7054 {
7055 struct bwn_softc *sc = mac->mac_sc;
7056 const struct ieee80211_frame_min *wh;
7057 uint64_t tsf;
7058 uint16_t low_mactime_now;
7059 uint16_t mt;
7060
7061 if (htole16(rxhdr->phy_status0) & BWN_RX_PHYST0_SHORTPRMBL)
7062 sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
7063
7064 wh = mtod(m, const struct ieee80211_frame_min *);
7065 if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED)
7066 sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_WEP;
7067
7068 bwn_tsf_read(mac, &tsf);
7069 low_mactime_now = tsf;
7070 tsf = tsf & ~0xffffULL;
7071
7072 switch (mac->mac_fw.fw_hdr_format) {
7073 case BWN_FW_HDR_351:
7074 case BWN_FW_HDR_410:
7075 mt = le16toh(rxhdr->ps4.r351.mac_time);
7076 break;
7077 case BWN_FW_HDR_598:
7078 mt = le16toh(rxhdr->ps4.r598.mac_time);
7079 break;
7080 }
7081
7082 tsf += mt;
7083 if (low_mactime_now < mt)
7084 tsf -= 0x10000;
7085
7086 sc->sc_rx_th.wr_tsf = tsf;
7087 sc->sc_rx_th.wr_rate = rate;
7088 sc->sc_rx_th.wr_antsignal = rssi;
7089 sc->sc_rx_th.wr_antnoise = noise;
7090 }
7091
7092 static void
bwn_tsf_read(struct bwn_mac * mac,uint64_t * tsf)7093 bwn_tsf_read(struct bwn_mac *mac, uint64_t *tsf)
7094 {
7095 uint32_t low, high;
7096
7097 KASSERT(bhnd_get_hwrev(mac->mac_sc->sc_dev) >= 3,
7098 ("%s:%d: fail", __func__, __LINE__));
7099
7100 low = BWN_READ_4(mac, BWN_REV3PLUS_TSF_LOW);
7101 high = BWN_READ_4(mac, BWN_REV3PLUS_TSF_HIGH);
7102 *tsf = high;
7103 *tsf <<= 32;
7104 *tsf |= low;
7105 }
7106
7107 static int
bwn_dma_attach(struct bwn_mac * mac)7108 bwn_dma_attach(struct bwn_mac *mac)
7109 {
7110 struct bwn_dma *dma;
7111 struct bwn_softc *sc;
7112 struct bhnd_dma_translation *dt, dma_translation;
7113 bhnd_addr_t addrext_req;
7114 bus_dma_tag_t dmat;
7115 bus_addr_t lowaddr;
7116 u_int addrext_shift, addr_width;
7117 int error;
7118
7119 dma = &mac->mac_method.dma;
7120 sc = mac->mac_sc;
7121 dt = NULL;
7122
7123 if (sc->sc_quirks & BWN_QUIRK_NODMA)
7124 return (0);
7125
7126 KASSERT(bhnd_get_hwrev(sc->sc_dev) >= 5, ("%s: fail", __func__));
7127
7128 /* Use the DMA engine's maximum host address width to determine the
7129 * addrext constraints, and supported device address width. */
7130 switch (mac->mac_dmatype) {
7131 case BHND_DMA_ADDR_30BIT:
7132 /* 32-bit engine without addrext support */
7133 addrext_req = 0x0;
7134 addrext_shift = 0;
7135
7136 /* We can address the full 32-bit device address space */
7137 addr_width = BHND_DMA_ADDR_32BIT;
7138 break;
7139
7140 case BHND_DMA_ADDR_32BIT:
7141 /* 32-bit engine with addrext support */
7142 addrext_req = BWN_DMA32_ADDREXT_MASK;
7143 addrext_shift = BWN_DMA32_ADDREXT_SHIFT;
7144 addr_width = BHND_DMA_ADDR_32BIT;
7145 break;
7146
7147 case BHND_DMA_ADDR_64BIT:
7148 /* 64-bit engine with addrext support */
7149 addrext_req = BWN_DMA64_ADDREXT_MASK;
7150 addrext_shift = BWN_DMA64_ADDREXT_SHIFT;
7151 addr_width = BHND_DMA_ADDR_64BIT;
7152 break;
7153
7154 default:
7155 device_printf(sc->sc_dev, "unsupported DMA address width: %d\n",
7156 mac->mac_dmatype);
7157 return (ENXIO);
7158 }
7159
7160 /* Fetch our device->host DMA translation and tag */
7161 error = bhnd_get_dma_translation(sc->sc_dev, addr_width, 0, &dmat,
7162 &dma_translation);
7163 if (error) {
7164 device_printf(sc->sc_dev, "error fetching DMA translation: "
7165 "%d\n", error);
7166 return (error);
7167 }
7168
7169 /* Verify that our DMA engine's addrext constraints are compatible with
7170 * our DMA translation */
7171 if (addrext_req != 0x0 &&
7172 (dma_translation.addrext_mask & addrext_req) != addrext_req)
7173 {
7174 device_printf(sc->sc_dev, "bus addrext mask %#jx incompatible "
7175 "with device addrext mask %#jx, disabling extended address "
7176 "support\n", (uintmax_t)dma_translation.addrext_mask,
7177 (uintmax_t)addrext_req);
7178
7179 addrext_req = 0x0;
7180 addrext_shift = 0;
7181 }
7182
7183 /* Apply our addrext translation constraint */
7184 dma_translation.addrext_mask = addrext_req;
7185
7186 /* Initialize our DMA engine configuration */
7187 mac->mac_flags |= BWN_MAC_FLAG_DMA;
7188
7189 dma->addrext_shift = addrext_shift;
7190 dma->translation = dma_translation;
7191
7192 dt = &dma->translation;
7193
7194 /* Dermine our translation's maximum supported address */
7195 lowaddr = MIN((dt->addr_mask | dt->addrext_mask), BUS_SPACE_MAXADDR);
7196
7197 /*
7198 * Create top level DMA tag
7199 */
7200 error = bus_dma_tag_create(dmat, /* parent */
7201 BWN_ALIGN, 0, /* alignment, bounds */
7202 lowaddr, /* lowaddr */
7203 BUS_SPACE_MAXADDR, /* highaddr */
7204 NULL, NULL, /* filter, filterarg */
7205 BUS_SPACE_MAXSIZE, /* maxsize */
7206 BUS_SPACE_UNRESTRICTED, /* nsegments */
7207 BUS_SPACE_MAXSIZE, /* maxsegsize */
7208 0, /* flags */
7209 NULL, NULL, /* lockfunc, lockarg */
7210 &dma->parent_dtag);
7211 if (error) {
7212 device_printf(sc->sc_dev, "can't create parent DMA tag\n");
7213 return (error);
7214 }
7215
7216 /*
7217 * Create TX/RX mbuf DMA tag
7218 */
7219 error = bus_dma_tag_create(dma->parent_dtag,
7220 1,
7221 0,
7222 BUS_SPACE_MAXADDR,
7223 BUS_SPACE_MAXADDR,
7224 NULL, NULL,
7225 MCLBYTES,
7226 1,
7227 BUS_SPACE_MAXSIZE_32BIT,
7228 0,
7229 NULL, NULL,
7230 &dma->rxbuf_dtag);
7231 if (error) {
7232 device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
7233 goto fail0;
7234 }
7235 error = bus_dma_tag_create(dma->parent_dtag,
7236 1,
7237 0,
7238 BUS_SPACE_MAXADDR,
7239 BUS_SPACE_MAXADDR,
7240 NULL, NULL,
7241 MCLBYTES,
7242 1,
7243 BUS_SPACE_MAXSIZE_32BIT,
7244 0,
7245 NULL, NULL,
7246 &dma->txbuf_dtag);
7247 if (error) {
7248 device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
7249 goto fail1;
7250 }
7251
7252 dma->wme[WME_AC_BK] = bwn_dma_ringsetup(mac, 0, 1);
7253 if (!dma->wme[WME_AC_BK])
7254 goto fail2;
7255
7256 dma->wme[WME_AC_BE] = bwn_dma_ringsetup(mac, 1, 1);
7257 if (!dma->wme[WME_AC_BE])
7258 goto fail3;
7259
7260 dma->wme[WME_AC_VI] = bwn_dma_ringsetup(mac, 2, 1);
7261 if (!dma->wme[WME_AC_VI])
7262 goto fail4;
7263
7264 dma->wme[WME_AC_VO] = bwn_dma_ringsetup(mac, 3, 1);
7265 if (!dma->wme[WME_AC_VO])
7266 goto fail5;
7267
7268 dma->mcast = bwn_dma_ringsetup(mac, 4, 1);
7269 if (!dma->mcast)
7270 goto fail6;
7271 dma->rx = bwn_dma_ringsetup(mac, 0, 0);
7272 if (!dma->rx)
7273 goto fail7;
7274
7275 return (error);
7276
7277 fail7: bwn_dma_ringfree(&dma->mcast);
7278 fail6: bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
7279 fail5: bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
7280 fail4: bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
7281 fail3: bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
7282 fail2: bus_dma_tag_destroy(dma->txbuf_dtag);
7283 fail1: bus_dma_tag_destroy(dma->rxbuf_dtag);
7284 fail0: bus_dma_tag_destroy(dma->parent_dtag);
7285 return (error);
7286 }
7287
7288 static struct bwn_dma_ring *
bwn_dma_parse_cookie(struct bwn_mac * mac,const struct bwn_txstatus * status,uint16_t cookie,int * slot)7289 bwn_dma_parse_cookie(struct bwn_mac *mac, const struct bwn_txstatus *status,
7290 uint16_t cookie, int *slot)
7291 {
7292 struct bwn_dma *dma = &mac->mac_method.dma;
7293 struct bwn_dma_ring *dr;
7294 struct bwn_softc *sc = mac->mac_sc;
7295
7296 BWN_ASSERT_LOCKED(mac->mac_sc);
7297
7298 switch (cookie & 0xf000) {
7299 case 0x1000:
7300 dr = dma->wme[WME_AC_BK];
7301 break;
7302 case 0x2000:
7303 dr = dma->wme[WME_AC_BE];
7304 break;
7305 case 0x3000:
7306 dr = dma->wme[WME_AC_VI];
7307 break;
7308 case 0x4000:
7309 dr = dma->wme[WME_AC_VO];
7310 break;
7311 case 0x5000:
7312 dr = dma->mcast;
7313 break;
7314 default:
7315 dr = NULL;
7316 KASSERT(0 == 1,
7317 ("invalid cookie value %d", cookie & 0xf000));
7318 }
7319 *slot = (cookie & 0x0fff);
7320 if (*slot < 0 || *slot >= dr->dr_numslots) {
7321 /*
7322 * XXX FIXME: sometimes H/W returns TX DONE events duplicately
7323 * that it occurs events which have same H/W sequence numbers.
7324 * When it's occurred just prints a WARNING msgs and ignores.
7325 */
7326 KASSERT(status->seq == dma->lastseq,
7327 ("%s:%d: fail", __func__, __LINE__));
7328 device_printf(sc->sc_dev,
7329 "out of slot ranges (0 < %d < %d)\n", *slot,
7330 dr->dr_numslots);
7331 return (NULL);
7332 }
7333 dma->lastseq = status->seq;
7334 return (dr);
7335 }
7336
7337 static void
bwn_dma_stop(struct bwn_mac * mac)7338 bwn_dma_stop(struct bwn_mac *mac)
7339 {
7340 struct bwn_dma *dma;
7341
7342 if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
7343 return;
7344 dma = &mac->mac_method.dma;
7345
7346 bwn_dma_ringstop(&dma->rx);
7347 bwn_dma_ringstop(&dma->wme[WME_AC_BK]);
7348 bwn_dma_ringstop(&dma->wme[WME_AC_BE]);
7349 bwn_dma_ringstop(&dma->wme[WME_AC_VI]);
7350 bwn_dma_ringstop(&dma->wme[WME_AC_VO]);
7351 bwn_dma_ringstop(&dma->mcast);
7352 }
7353
7354 static void
bwn_dma_ringstop(struct bwn_dma_ring ** dr)7355 bwn_dma_ringstop(struct bwn_dma_ring **dr)
7356 {
7357
7358 if (dr == NULL)
7359 return;
7360
7361 bwn_dma_cleanup(*dr);
7362 }
7363
7364 static void
bwn_pio_stop(struct bwn_mac * mac)7365 bwn_pio_stop(struct bwn_mac *mac)
7366 {
7367 struct bwn_pio *pio;
7368
7369 if (mac->mac_flags & BWN_MAC_FLAG_DMA)
7370 return;
7371 pio = &mac->mac_method.pio;
7372
7373 bwn_destroy_queue_tx(&pio->mcast);
7374 bwn_destroy_queue_tx(&pio->wme[WME_AC_VO]);
7375 bwn_destroy_queue_tx(&pio->wme[WME_AC_VI]);
7376 bwn_destroy_queue_tx(&pio->wme[WME_AC_BE]);
7377 bwn_destroy_queue_tx(&pio->wme[WME_AC_BK]);
7378 }
7379
7380 static int
bwn_led_attach(struct bwn_mac * mac)7381 bwn_led_attach(struct bwn_mac *mac)
7382 {
7383 struct bwn_softc *sc = mac->mac_sc;
7384 const uint8_t *led_act = NULL;
7385 int error;
7386 int i;
7387
7388 sc->sc_led_idle = (2350 * hz) / 1000;
7389 sc->sc_led_blink = 1;
7390
7391 for (i = 0; i < N(bwn_vendor_led_act); ++i) {
7392 if (sc->sc_board_info.board_vendor ==
7393 bwn_vendor_led_act[i].vid) {
7394 led_act = bwn_vendor_led_act[i].led_act;
7395 break;
7396 }
7397 }
7398 if (led_act == NULL)
7399 led_act = bwn_default_led_act;
7400
7401 _Static_assert(nitems(bwn_led_vars) == BWN_LED_MAX,
7402 "invalid NVRAM variable name array");
7403
7404 for (i = 0; i < BWN_LED_MAX; ++i) {
7405 struct bwn_led *led;
7406 uint8_t val;
7407
7408 led = &sc->sc_leds[i];
7409
7410 KASSERT(i < nitems(bwn_led_vars), ("unknown LED index"));
7411 error = bhnd_nvram_getvar_uint8(sc->sc_dev, bwn_led_vars[i],
7412 &val);
7413 if (error) {
7414 if (error != ENOENT) {
7415 device_printf(sc->sc_dev, "NVRAM variable %s "
7416 "unreadable: %d", bwn_led_vars[i], error);
7417 return (error);
7418 }
7419
7420 /* Not found; use default */
7421 led->led_act = led_act[i];
7422 } else {
7423 if (val & BWN_LED_ACT_LOW)
7424 led->led_flags |= BWN_LED_F_ACTLOW;
7425 led->led_act = val & BWN_LED_ACT_MASK;
7426 }
7427 led->led_mask = (1 << i);
7428
7429 if (led->led_act == BWN_LED_ACT_BLINK_SLOW ||
7430 led->led_act == BWN_LED_ACT_BLINK_POLL ||
7431 led->led_act == BWN_LED_ACT_BLINK) {
7432 led->led_flags |= BWN_LED_F_BLINK;
7433 if (led->led_act == BWN_LED_ACT_BLINK_POLL)
7434 led->led_flags |= BWN_LED_F_POLLABLE;
7435 else if (led->led_act == BWN_LED_ACT_BLINK_SLOW)
7436 led->led_flags |= BWN_LED_F_SLOW;
7437
7438 if (sc->sc_blink_led == NULL) {
7439 sc->sc_blink_led = led;
7440 if (led->led_flags & BWN_LED_F_SLOW)
7441 BWN_LED_SLOWDOWN(sc->sc_led_idle);
7442 }
7443 }
7444
7445 DPRINTF(sc, BWN_DEBUG_LED,
7446 "%dth led, act %d, lowact %d\n", i,
7447 led->led_act, led->led_flags & BWN_LED_F_ACTLOW);
7448 }
7449 callout_init_mtx(&sc->sc_led_blink_ch, &sc->sc_mtx, 0);
7450
7451 return (0);
7452 }
7453
7454 static __inline uint16_t
bwn_led_onoff(const struct bwn_led * led,uint16_t val,int on)7455 bwn_led_onoff(const struct bwn_led *led, uint16_t val, int on)
7456 {
7457
7458 if (led->led_flags & BWN_LED_F_ACTLOW)
7459 on = !on;
7460 if (on)
7461 val |= led->led_mask;
7462 else
7463 val &= ~led->led_mask;
7464 return val;
7465 }
7466
7467 static void
bwn_led_newstate(struct bwn_mac * mac,enum ieee80211_state nstate)7468 bwn_led_newstate(struct bwn_mac *mac, enum ieee80211_state nstate)
7469 {
7470 struct bwn_softc *sc = mac->mac_sc;
7471 struct ieee80211com *ic = &sc->sc_ic;
7472 uint16_t val;
7473 int i;
7474
7475 if (nstate == IEEE80211_S_INIT) {
7476 callout_stop(&sc->sc_led_blink_ch);
7477 sc->sc_led_blinking = 0;
7478 }
7479
7480 if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0)
7481 return;
7482
7483 val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
7484 for (i = 0; i < BWN_LED_MAX; ++i) {
7485 struct bwn_led *led = &sc->sc_leds[i];
7486 int on;
7487
7488 if (led->led_act == BWN_LED_ACT_UNKN ||
7489 led->led_act == BWN_LED_ACT_NULL)
7490 continue;
7491
7492 if ((led->led_flags & BWN_LED_F_BLINK) &&
7493 nstate != IEEE80211_S_INIT)
7494 continue;
7495
7496 switch (led->led_act) {
7497 case BWN_LED_ACT_ON: /* Always on */
7498 on = 1;
7499 break;
7500 case BWN_LED_ACT_OFF: /* Always off */
7501 case BWN_LED_ACT_5GHZ: /* TODO: 11A */
7502 on = 0;
7503 break;
7504 default:
7505 on = 1;
7506 switch (nstate) {
7507 case IEEE80211_S_INIT:
7508 on = 0;
7509 break;
7510 case IEEE80211_S_RUN:
7511 if (led->led_act == BWN_LED_ACT_11G &&
7512 ic->ic_curmode != IEEE80211_MODE_11G)
7513 on = 0;
7514 break;
7515 default:
7516 if (led->led_act == BWN_LED_ACT_ASSOC)
7517 on = 0;
7518 break;
7519 }
7520 break;
7521 }
7522
7523 val = bwn_led_onoff(led, val, on);
7524 }
7525 BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
7526 }
7527
7528 static void
bwn_led_event(struct bwn_mac * mac,int event)7529 bwn_led_event(struct bwn_mac *mac, int event)
7530 {
7531 struct bwn_softc *sc = mac->mac_sc;
7532 struct bwn_led *led = sc->sc_blink_led;
7533 int rate;
7534
7535 if (event == BWN_LED_EVENT_POLL) {
7536 if ((led->led_flags & BWN_LED_F_POLLABLE) == 0)
7537 return;
7538 if (ticks - sc->sc_led_ticks < sc->sc_led_idle)
7539 return;
7540 }
7541
7542 sc->sc_led_ticks = ticks;
7543 if (sc->sc_led_blinking)
7544 return;
7545
7546 switch (event) {
7547 case BWN_LED_EVENT_RX:
7548 rate = sc->sc_rx_rate;
7549 break;
7550 case BWN_LED_EVENT_TX:
7551 rate = sc->sc_tx_rate;
7552 break;
7553 case BWN_LED_EVENT_POLL:
7554 rate = 0;
7555 break;
7556 default:
7557 panic("unknown LED event %d\n", event);
7558 break;
7559 }
7560 bwn_led_blink_start(mac, bwn_led_duration[rate].on_dur,
7561 bwn_led_duration[rate].off_dur);
7562 }
7563
7564 static void
bwn_led_blink_start(struct bwn_mac * mac,int on_dur,int off_dur)7565 bwn_led_blink_start(struct bwn_mac *mac, int on_dur, int off_dur)
7566 {
7567 struct bwn_softc *sc = mac->mac_sc;
7568 struct bwn_led *led = sc->sc_blink_led;
7569 uint16_t val;
7570
7571 val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
7572 val = bwn_led_onoff(led, val, 1);
7573 BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
7574
7575 if (led->led_flags & BWN_LED_F_SLOW) {
7576 BWN_LED_SLOWDOWN(on_dur);
7577 BWN_LED_SLOWDOWN(off_dur);
7578 }
7579
7580 sc->sc_led_blinking = 1;
7581 sc->sc_led_blink_offdur = off_dur;
7582
7583 callout_reset(&sc->sc_led_blink_ch, on_dur, bwn_led_blink_next, mac);
7584 }
7585
7586 static void
bwn_led_blink_next(void * arg)7587 bwn_led_blink_next(void *arg)
7588 {
7589 struct bwn_mac *mac = arg;
7590 struct bwn_softc *sc = mac->mac_sc;
7591 uint16_t val;
7592
7593 val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
7594 val = bwn_led_onoff(sc->sc_blink_led, val, 0);
7595 BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
7596
7597 callout_reset(&sc->sc_led_blink_ch, sc->sc_led_blink_offdur,
7598 bwn_led_blink_end, mac);
7599 }
7600
7601 static void
bwn_led_blink_end(void * arg)7602 bwn_led_blink_end(void *arg)
7603 {
7604 struct bwn_mac *mac = arg;
7605 struct bwn_softc *sc = mac->mac_sc;
7606
7607 sc->sc_led_blinking = 0;
7608 }
7609
7610 static int
bwn_suspend(device_t dev)7611 bwn_suspend(device_t dev)
7612 {
7613 struct bwn_softc *sc = device_get_softc(dev);
7614
7615 BWN_LOCK(sc);
7616 bwn_stop(sc);
7617 BWN_UNLOCK(sc);
7618 return (0);
7619 }
7620
7621 static int
bwn_resume(device_t dev)7622 bwn_resume(device_t dev)
7623 {
7624 struct bwn_softc *sc = device_get_softc(dev);
7625 int error = EDOOFUS;
7626
7627 BWN_LOCK(sc);
7628 if (sc->sc_ic.ic_nrunning > 0)
7629 error = bwn_init(sc);
7630 BWN_UNLOCK(sc);
7631 if (error == 0)
7632 ieee80211_start_all(&sc->sc_ic);
7633 return (0);
7634 }
7635
7636 static void
bwn_rfswitch(void * arg)7637 bwn_rfswitch(void *arg)
7638 {
7639 struct bwn_softc *sc = arg;
7640 struct bwn_mac *mac = sc->sc_curmac;
7641 int cur = 0, prev = 0;
7642
7643 KASSERT(mac->mac_status >= BWN_MAC_STATUS_STARTED,
7644 ("%s: invalid MAC status %d", __func__, mac->mac_status));
7645
7646 if (mac->mac_phy.rev >= 3 || mac->mac_phy.type == BWN_PHYTYPE_LP
7647 || mac->mac_phy.type == BWN_PHYTYPE_N) {
7648 if (!(BWN_READ_4(mac, BWN_RF_HWENABLED_HI)
7649 & BWN_RF_HWENABLED_HI_MASK))
7650 cur = 1;
7651 } else {
7652 if (BWN_READ_2(mac, BWN_RF_HWENABLED_LO)
7653 & BWN_RF_HWENABLED_LO_MASK)
7654 cur = 1;
7655 }
7656
7657 if (mac->mac_flags & BWN_MAC_FLAG_RADIO_ON)
7658 prev = 1;
7659
7660 DPRINTF(sc, BWN_DEBUG_RESET, "%s: called; cur=%d, prev=%d\n",
7661 __func__, cur, prev);
7662
7663 if (cur != prev) {
7664 if (cur)
7665 mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
7666 else
7667 mac->mac_flags &= ~BWN_MAC_FLAG_RADIO_ON;
7668
7669 device_printf(sc->sc_dev,
7670 "status of RF switch is changed to %s\n",
7671 cur ? "ON" : "OFF");
7672 if (cur != mac->mac_phy.rf_on) {
7673 if (cur)
7674 bwn_rf_turnon(mac);
7675 else
7676 bwn_rf_turnoff(mac);
7677 }
7678 }
7679
7680 callout_schedule(&sc->sc_rfswitch_ch, hz);
7681 }
7682
7683 static void
bwn_sysctl_node(struct bwn_softc * sc)7684 bwn_sysctl_node(struct bwn_softc *sc)
7685 {
7686 device_t dev = sc->sc_dev;
7687 struct bwn_mac *mac;
7688 struct bwn_stats *stats;
7689
7690 /* XXX assume that count of MAC is only 1. */
7691
7692 if ((mac = sc->sc_curmac) == NULL)
7693 return;
7694 stats = &mac->mac_stats;
7695
7696 SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
7697 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
7698 "linknoise", CTLFLAG_RW, &stats->rts, 0, "Noise level");
7699 SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
7700 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
7701 "rts", CTLFLAG_RW, &stats->rts, 0, "RTS");
7702 SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
7703 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
7704 "rtsfail", CTLFLAG_RW, &stats->rtsfail, 0, "RTS failed to send");
7705
7706 #ifdef BWN_DEBUG
7707 SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
7708 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
7709 "debug", CTLFLAG_RW, &sc->sc_debug, 0, "Debug flags");
7710 #endif
7711 }
7712
7713 static device_method_t bwn_methods[] = {
7714 /* Device interface */
7715 DEVMETHOD(device_probe, bwn_probe),
7716 DEVMETHOD(device_attach, bwn_attach),
7717 DEVMETHOD(device_detach, bwn_detach),
7718 DEVMETHOD(device_suspend, bwn_suspend),
7719 DEVMETHOD(device_resume, bwn_resume),
7720 DEVMETHOD_END
7721 };
7722
7723 static driver_t bwn_driver = {
7724 "bwn",
7725 bwn_methods,
7726 sizeof(struct bwn_softc)
7727 };
7728
7729 DRIVER_MODULE(bwn, bhnd, bwn_driver, 0, 0);
7730 MODULE_DEPEND(bwn, bhnd, 1, 1, 1);
7731 MODULE_DEPEND(bwn, gpiobus, 1, 1, 1);
7732 MODULE_DEPEND(bwn, wlan, 1, 1, 1); /* 802.11 media layer */
7733 MODULE_DEPEND(bwn, firmware, 1, 1, 1); /* firmware support */
7734 MODULE_DEPEND(bwn, wlan_amrr, 1, 1, 1);
7735 MODULE_VERSION(bwn, 1);
7736