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