Deleted Added
full compact
if_bwn.c (300019) if_bwn.c (300075)
1/*-
2 * Copyright (c) 2009-2010 Weongyo Jeong <weongyo@freebsd.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer,
10 * without modification.
11 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13 * redistribution must be conditioned upon including a substantially
14 * similar Disclaimer requirement for further binary redistribution.
15 *
16 * NO WARRANTY
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
20 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
22 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27 * THE POSSIBILITY OF SUCH DAMAGES.
28 */
29
30#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2009-2010 Weongyo Jeong <weongyo@freebsd.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer,
10 * without modification.
11 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13 * redistribution must be conditioned upon including a substantially
14 * similar Disclaimer requirement for further binary redistribution.
15 *
16 * NO WARRANTY
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
20 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
22 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27 * THE POSSIBILITY OF SUCH DAMAGES.
28 */
29
30#include <sys/cdefs.h>
31__FBSDID("$FreeBSD: head/sys/dev/bwn/if_bwn.c 300019 2016-05-17 07:12:00Z adrian $");
31__FBSDID("$FreeBSD: head/sys/dev/bwn/if_bwn.c 300075 2016-05-17 20:18:23Z adrian $");
32
33/*
34 * The Broadcom Wireless LAN controller driver.
35 */
36
37#include "opt_bwn.h"
38#include "opt_wlan.h"
39
40#include <sys/param.h>
41#include <sys/systm.h>
42#include <sys/kernel.h>
43#include <sys/malloc.h>
44#include <sys/module.h>
45#include <sys/endian.h>
46#include <sys/errno.h>
47#include <sys/firmware.h>
48#include <sys/lock.h>
49#include <sys/mutex.h>
50#include <machine/bus.h>
51#include <machine/resource.h>
52#include <sys/bus.h>
53#include <sys/rman.h>
54#include <sys/socket.h>
55#include <sys/sockio.h>
56
57#include <net/ethernet.h>
58#include <net/if.h>
59#include <net/if_var.h>
60#include <net/if_arp.h>
61#include <net/if_dl.h>
62#include <net/if_llc.h>
63#include <net/if_media.h>
64#include <net/if_types.h>
65
66#include <dev/pci/pcivar.h>
67#include <dev/pci/pcireg.h>
68#include <dev/siba/siba_ids.h>
69#include <dev/siba/sibareg.h>
70#include <dev/siba/sibavar.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/bwn/if_bwnreg.h>
79#include <dev/bwn/if_bwnvar.h>
80
81#include <dev/bwn/if_bwn_debug.h>
82#include <dev/bwn/if_bwn_misc.h>
83#include <dev/bwn/if_bwn_util.h>
84#include <dev/bwn/if_bwn_phy_common.h>
85#include <dev/bwn/if_bwn_phy_g.h>
86#include <dev/bwn/if_bwn_phy_lp.h>
87#include <dev/bwn/if_bwn_phy_n.h>
88
89static SYSCTL_NODE(_hw, OID_AUTO, bwn, CTLFLAG_RD, 0,
90 "Broadcom driver parameters");
91
92/*
93 * Tunable & sysctl variables.
94 */
95
96#ifdef BWN_DEBUG
97static int bwn_debug = 0;
98SYSCTL_INT(_hw_bwn, OID_AUTO, debug, CTLFLAG_RWTUN, &bwn_debug, 0,
99 "Broadcom debugging printfs");
100#endif
101
102static int bwn_bfp = 0; /* use "Bad Frames Preemption" */
103SYSCTL_INT(_hw_bwn, OID_AUTO, bfp, CTLFLAG_RW, &bwn_bfp, 0,
104 "uses Bad Frames Preemption");
105static int bwn_bluetooth = 1;
106SYSCTL_INT(_hw_bwn, OID_AUTO, bluetooth, CTLFLAG_RW, &bwn_bluetooth, 0,
107 "turns on Bluetooth Coexistence");
108static int bwn_hwpctl = 0;
109SYSCTL_INT(_hw_bwn, OID_AUTO, hwpctl, CTLFLAG_RW, &bwn_hwpctl, 0,
110 "uses H/W power control");
111static int bwn_msi_disable = 0; /* MSI disabled */
112TUNABLE_INT("hw.bwn.msi_disable", &bwn_msi_disable);
113static int bwn_usedma = 1;
114SYSCTL_INT(_hw_bwn, OID_AUTO, usedma, CTLFLAG_RD, &bwn_usedma, 0,
115 "uses DMA");
116TUNABLE_INT("hw.bwn.usedma", &bwn_usedma);
117static int bwn_wme = 1;
118SYSCTL_INT(_hw_bwn, OID_AUTO, wme, CTLFLAG_RW, &bwn_wme, 0,
119 "uses WME support");
120
121static void bwn_attach_pre(struct bwn_softc *);
122static int bwn_attach_post(struct bwn_softc *);
123static void bwn_sprom_bugfixes(device_t);
124static int bwn_init(struct bwn_softc *);
125static void bwn_parent(struct ieee80211com *);
126static void bwn_start(struct bwn_softc *);
127static int bwn_transmit(struct ieee80211com *, struct mbuf *);
128static int bwn_attach_core(struct bwn_mac *);
129static int bwn_phy_getinfo(struct bwn_mac *, int);
130static int bwn_chiptest(struct bwn_mac *);
131static int bwn_setup_channels(struct bwn_mac *, int, int);
132static void bwn_shm_ctlword(struct bwn_mac *, uint16_t,
133 uint16_t);
134static void bwn_addchannels(struct ieee80211_channel [], int, int *,
135 const struct bwn_channelinfo *, const uint8_t []);
136static int bwn_raw_xmit(struct ieee80211_node *, struct mbuf *,
137 const struct ieee80211_bpf_params *);
138static void bwn_updateslot(struct ieee80211com *);
139static void bwn_update_promisc(struct ieee80211com *);
140static void bwn_wme_init(struct bwn_mac *);
141static int bwn_wme_update(struct ieee80211com *);
142static void bwn_wme_clear(struct bwn_softc *);
143static void bwn_wme_load(struct bwn_mac *);
144static void bwn_wme_loadparams(struct bwn_mac *,
145 const struct wmeParams *, uint16_t);
146static void bwn_scan_start(struct ieee80211com *);
147static void bwn_scan_end(struct ieee80211com *);
148static void bwn_set_channel(struct ieee80211com *);
149static struct ieee80211vap *bwn_vap_create(struct ieee80211com *,
150 const char [IFNAMSIZ], int, enum ieee80211_opmode, int,
151 const uint8_t [IEEE80211_ADDR_LEN],
152 const uint8_t [IEEE80211_ADDR_LEN]);
153static void bwn_vap_delete(struct ieee80211vap *);
154static void bwn_stop(struct bwn_softc *);
155static int bwn_core_init(struct bwn_mac *);
156static void bwn_core_start(struct bwn_mac *);
157static void bwn_core_exit(struct bwn_mac *);
158static void bwn_bt_disable(struct bwn_mac *);
159static int bwn_chip_init(struct bwn_mac *);
160static void bwn_set_txretry(struct bwn_mac *, int, int);
161static void bwn_rate_init(struct bwn_mac *);
162static void bwn_set_phytxctl(struct bwn_mac *);
163static void bwn_spu_setdelay(struct bwn_mac *, int);
164static void bwn_bt_enable(struct bwn_mac *);
165static void bwn_set_macaddr(struct bwn_mac *);
166static void bwn_crypt_init(struct bwn_mac *);
167static void bwn_chip_exit(struct bwn_mac *);
168static int bwn_fw_fillinfo(struct bwn_mac *);
169static int bwn_fw_loaducode(struct bwn_mac *);
170static int bwn_gpio_init(struct bwn_mac *);
171static int bwn_fw_loadinitvals(struct bwn_mac *);
172static int bwn_phy_init(struct bwn_mac *);
173static void bwn_set_txantenna(struct bwn_mac *, int);
174static void bwn_set_opmode(struct bwn_mac *);
175static void bwn_rate_write(struct bwn_mac *, uint16_t, int);
176static uint8_t bwn_plcp_getcck(const uint8_t);
177static uint8_t bwn_plcp_getofdm(const uint8_t);
178static void bwn_pio_init(struct bwn_mac *);
179static uint16_t bwn_pio_idx2base(struct bwn_mac *, int);
180static void bwn_pio_set_txqueue(struct bwn_mac *, struct bwn_pio_txqueue *,
181 int);
182static void bwn_pio_setupqueue_rx(struct bwn_mac *,
183 struct bwn_pio_rxqueue *, int);
184static void bwn_destroy_queue_tx(struct bwn_pio_txqueue *);
185static uint16_t bwn_pio_read_2(struct bwn_mac *, struct bwn_pio_txqueue *,
186 uint16_t);
187static void bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *);
188static int bwn_pio_rx(struct bwn_pio_rxqueue *);
189static uint8_t bwn_pio_rxeof(struct bwn_pio_rxqueue *);
190static void bwn_pio_handle_txeof(struct bwn_mac *,
191 const struct bwn_txstatus *);
192static uint16_t bwn_pio_rx_read_2(struct bwn_pio_rxqueue *, uint16_t);
193static uint32_t bwn_pio_rx_read_4(struct bwn_pio_rxqueue *, uint16_t);
194static void bwn_pio_rx_write_2(struct bwn_pio_rxqueue *, uint16_t,
195 uint16_t);
196static void bwn_pio_rx_write_4(struct bwn_pio_rxqueue *, uint16_t,
197 uint32_t);
198static int bwn_pio_tx_start(struct bwn_mac *, struct ieee80211_node *,
199 struct mbuf *);
200static struct bwn_pio_txqueue *bwn_pio_select(struct bwn_mac *, uint8_t);
201static uint32_t bwn_pio_write_multi_4(struct bwn_mac *,
202 struct bwn_pio_txqueue *, uint32_t, const void *, int);
203static void bwn_pio_write_4(struct bwn_mac *, struct bwn_pio_txqueue *,
204 uint16_t, uint32_t);
205static uint16_t bwn_pio_write_multi_2(struct bwn_mac *,
206 struct bwn_pio_txqueue *, uint16_t, const void *, int);
207static uint16_t bwn_pio_write_mbuf_2(struct bwn_mac *,
208 struct bwn_pio_txqueue *, uint16_t, struct mbuf *);
209static struct bwn_pio_txqueue *bwn_pio_parse_cookie(struct bwn_mac *,
210 uint16_t, struct bwn_pio_txpkt **);
211static void bwn_dma_init(struct bwn_mac *);
212static void bwn_dma_rxdirectfifo(struct bwn_mac *, int, uint8_t);
213static int bwn_dma_mask2type(uint64_t);
214static uint64_t bwn_dma_mask(struct bwn_mac *);
215static uint16_t bwn_dma_base(int, int);
216static void bwn_dma_ringfree(struct bwn_dma_ring **);
217static void bwn_dma_32_getdesc(struct bwn_dma_ring *,
218 int, struct bwn_dmadesc_generic **,
219 struct bwn_dmadesc_meta **);
220static void bwn_dma_32_setdesc(struct bwn_dma_ring *,
221 struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int,
222 int, int);
223static void bwn_dma_32_start_transfer(struct bwn_dma_ring *, int);
224static void bwn_dma_32_suspend(struct bwn_dma_ring *);
225static void bwn_dma_32_resume(struct bwn_dma_ring *);
226static int bwn_dma_32_get_curslot(struct bwn_dma_ring *);
227static void bwn_dma_32_set_curslot(struct bwn_dma_ring *, int);
228static void bwn_dma_64_getdesc(struct bwn_dma_ring *,
229 int, struct bwn_dmadesc_generic **,
230 struct bwn_dmadesc_meta **);
231static void bwn_dma_64_setdesc(struct bwn_dma_ring *,
232 struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int,
233 int, int);
234static void bwn_dma_64_start_transfer(struct bwn_dma_ring *, int);
235static void bwn_dma_64_suspend(struct bwn_dma_ring *);
236static void bwn_dma_64_resume(struct bwn_dma_ring *);
237static int bwn_dma_64_get_curslot(struct bwn_dma_ring *);
238static void bwn_dma_64_set_curslot(struct bwn_dma_ring *, int);
239static int bwn_dma_allocringmemory(struct bwn_dma_ring *);
240static void bwn_dma_setup(struct bwn_dma_ring *);
241static void bwn_dma_free_ringmemory(struct bwn_dma_ring *);
242static void bwn_dma_cleanup(struct bwn_dma_ring *);
243static void bwn_dma_free_descbufs(struct bwn_dma_ring *);
244static int bwn_dma_tx_reset(struct bwn_mac *, uint16_t, int);
245static void bwn_dma_rx(struct bwn_dma_ring *);
246static int bwn_dma_rx_reset(struct bwn_mac *, uint16_t, int);
247static void bwn_dma_free_descbuf(struct bwn_dma_ring *,
248 struct bwn_dmadesc_meta *);
249static void bwn_dma_set_redzone(struct bwn_dma_ring *, struct mbuf *);
250static int bwn_dma_gettype(struct bwn_mac *);
251static void bwn_dma_ring_addr(void *, bus_dma_segment_t *, int, int);
252static int bwn_dma_freeslot(struct bwn_dma_ring *);
253static int bwn_dma_nextslot(struct bwn_dma_ring *, int);
254static void bwn_dma_rxeof(struct bwn_dma_ring *, int *);
255static int bwn_dma_newbuf(struct bwn_dma_ring *,
256 struct bwn_dmadesc_generic *, struct bwn_dmadesc_meta *,
257 int);
258static void bwn_dma_buf_addr(void *, bus_dma_segment_t *, int,
259 bus_size_t, int);
260static uint8_t bwn_dma_check_redzone(struct bwn_dma_ring *, struct mbuf *);
261static void bwn_dma_handle_txeof(struct bwn_mac *,
262 const struct bwn_txstatus *);
263static int bwn_dma_tx_start(struct bwn_mac *, struct ieee80211_node *,
264 struct mbuf *);
265static int bwn_dma_getslot(struct bwn_dma_ring *);
266static struct bwn_dma_ring *bwn_dma_select(struct bwn_mac *,
267 uint8_t);
268static int bwn_dma_attach(struct bwn_mac *);
269static struct bwn_dma_ring *bwn_dma_ringsetup(struct bwn_mac *,
270 int, int, int);
271static struct bwn_dma_ring *bwn_dma_parse_cookie(struct bwn_mac *,
272 const struct bwn_txstatus *, uint16_t, int *);
273static void bwn_dma_free(struct bwn_mac *);
274static int bwn_fw_gets(struct bwn_mac *, enum bwn_fwtype);
275static int bwn_fw_get(struct bwn_mac *, enum bwn_fwtype,
276 const char *, struct bwn_fwfile *);
277static void bwn_release_firmware(struct bwn_mac *);
278static void bwn_do_release_fw(struct bwn_fwfile *);
279static uint16_t bwn_fwcaps_read(struct bwn_mac *);
280static int bwn_fwinitvals_write(struct bwn_mac *,
281 const struct bwn_fwinitvals *, size_t, size_t);
282static uint16_t bwn_ant2phy(int);
283static void bwn_mac_write_bssid(struct bwn_mac *);
284static void bwn_mac_setfilter(struct bwn_mac *, uint16_t,
285 const uint8_t *);
286static void bwn_key_dowrite(struct bwn_mac *, uint8_t, uint8_t,
287 const uint8_t *, size_t, const uint8_t *);
288static void bwn_key_macwrite(struct bwn_mac *, uint8_t,
289 const uint8_t *);
290static void bwn_key_write(struct bwn_mac *, uint8_t, uint8_t,
291 const uint8_t *);
292static void bwn_phy_exit(struct bwn_mac *);
293static void bwn_core_stop(struct bwn_mac *);
294static int bwn_switch_band(struct bwn_softc *,
295 struct ieee80211_channel *);
296static void bwn_phy_reset(struct bwn_mac *);
297static int bwn_newstate(struct ieee80211vap *, enum ieee80211_state, int);
298static void bwn_set_pretbtt(struct bwn_mac *);
299static int bwn_intr(void *);
300static void bwn_intrtask(void *, int);
301static void bwn_restart(struct bwn_mac *, const char *);
302static void bwn_intr_ucode_debug(struct bwn_mac *);
303static void bwn_intr_tbtt_indication(struct bwn_mac *);
304static void bwn_intr_atim_end(struct bwn_mac *);
305static void bwn_intr_beacon(struct bwn_mac *);
306static void bwn_intr_pmq(struct bwn_mac *);
307static void bwn_intr_noise(struct bwn_mac *);
308static void bwn_intr_txeof(struct bwn_mac *);
309static void bwn_hwreset(void *, int);
310static void bwn_handle_fwpanic(struct bwn_mac *);
311static void bwn_load_beacon0(struct bwn_mac *);
312static void bwn_load_beacon1(struct bwn_mac *);
313static uint32_t bwn_jssi_read(struct bwn_mac *);
314static void bwn_noise_gensample(struct bwn_mac *);
315static void bwn_handle_txeof(struct bwn_mac *,
316 const struct bwn_txstatus *);
317static void bwn_rxeof(struct bwn_mac *, struct mbuf *, const void *);
318static void bwn_phy_txpower_check(struct bwn_mac *, uint32_t);
319static int bwn_tx_start(struct bwn_softc *, struct ieee80211_node *,
320 struct mbuf *);
321static int bwn_tx_isfull(struct bwn_softc *, struct mbuf *);
322static int bwn_set_txhdr(struct bwn_mac *,
323 struct ieee80211_node *, struct mbuf *, struct bwn_txhdr *,
324 uint16_t);
325static void bwn_plcp_genhdr(struct bwn_plcp4 *, const uint16_t,
326 const uint8_t);
327static uint8_t bwn_antenna_sanitize(struct bwn_mac *, uint8_t);
328static uint8_t bwn_get_fbrate(uint8_t);
329static void bwn_txpwr(void *, int);
330static void bwn_tasks(void *);
331static void bwn_task_15s(struct bwn_mac *);
332static void bwn_task_30s(struct bwn_mac *);
333static void bwn_task_60s(struct bwn_mac *);
334static int bwn_plcp_get_ofdmrate(struct bwn_mac *, struct bwn_plcp6 *,
335 uint8_t);
336static int bwn_plcp_get_cckrate(struct bwn_mac *, struct bwn_plcp6 *);
337static void bwn_rx_radiotap(struct bwn_mac *, struct mbuf *,
338 const struct bwn_rxhdr4 *, struct bwn_plcp6 *, int,
339 int, int);
340static void bwn_tsf_read(struct bwn_mac *, uint64_t *);
341static void bwn_set_slot_time(struct bwn_mac *, uint16_t);
342static void bwn_watchdog(void *);
343static void bwn_dma_stop(struct bwn_mac *);
344static void bwn_pio_stop(struct bwn_mac *);
345static void bwn_dma_ringstop(struct bwn_dma_ring **);
346static void bwn_led_attach(struct bwn_mac *);
347static void bwn_led_newstate(struct bwn_mac *, enum ieee80211_state);
348static void bwn_led_event(struct bwn_mac *, int);
349static void bwn_led_blink_start(struct bwn_mac *, int, int);
350static void bwn_led_blink_next(void *);
351static void bwn_led_blink_end(void *);
352static void bwn_rfswitch(void *);
353static void bwn_rf_turnon(struct bwn_mac *);
354static void bwn_rf_turnoff(struct bwn_mac *);
355static void bwn_sysctl_node(struct bwn_softc *);
356
357static struct resource_spec bwn_res_spec_legacy[] = {
358 { SYS_RES_IRQ, 0, RF_ACTIVE | RF_SHAREABLE },
359 { -1, 0, 0 }
360};
361
362static struct resource_spec bwn_res_spec_msi[] = {
363 { SYS_RES_IRQ, 1, RF_ACTIVE },
364 { -1, 0, 0 }
365};
366
367static 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
377static 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
396static 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
445static const struct {
446 uint16_t vid;
447 uint8_t led_act[BWN_LED_MAX];
448} bwn_vendor_led_act[] = {
449 VENDOR_LED_ACT(COMPAQ),
450 VENDOR_LED_ACT(ASUSTEK)
451};
452
453static const uint8_t bwn_default_led_act[BWN_LED_MAX] =
454 { BWN_VENDOR_LED_ACT_DEFAULT };
455
456#undef VENDOR_LED_ACT
457
458static const struct {
459 int on_dur;
460 int off_dur;
461} bwn_led_duration[109] = {
462 [0] = { 400, 100 },
463 [2] = { 150, 75 },
464 [4] = { 90, 45 },
465 [11] = { 66, 34 },
466 [12] = { 53, 26 },
467 [18] = { 42, 21 },
468 [22] = { 35, 17 },
469 [24] = { 32, 16 },
470 [36] = { 21, 10 },
471 [48] = { 16, 8 },
472 [72] = { 11, 5 },
473 [96] = { 9, 4 },
474 [108] = { 7, 3 }
475};
476
477static const uint16_t bwn_wme_shm_offsets[] = {
478 [0] = BWN_WME_BESTEFFORT,
479 [1] = BWN_WME_BACKGROUND,
480 [2] = BWN_WME_VOICE,
481 [3] = BWN_WME_VIDEO,
482};
483
484static const struct siba_devid bwn_devs[] = {
485 SIBA_DEV(BROADCOM, 80211, 5, "Revision 5"),
486 SIBA_DEV(BROADCOM, 80211, 6, "Revision 6"),
487 SIBA_DEV(BROADCOM, 80211, 7, "Revision 7"),
488 SIBA_DEV(BROADCOM, 80211, 9, "Revision 9"),
489 SIBA_DEV(BROADCOM, 80211, 10, "Revision 10"),
490 SIBA_DEV(BROADCOM, 80211, 11, "Revision 11"),
491 SIBA_DEV(BROADCOM, 80211, 12, "Revision 12"),
492 SIBA_DEV(BROADCOM, 80211, 13, "Revision 13"),
493 SIBA_DEV(BROADCOM, 80211, 15, "Revision 15"),
494 SIBA_DEV(BROADCOM, 80211, 16, "Revision 16")
495};
496
497static int
498bwn_probe(device_t dev)
499{
500 int i;
501
502 for (i = 0; i < nitems(bwn_devs); i++) {
503 if (siba_get_vendor(dev) == bwn_devs[i].sd_vendor &&
504 siba_get_device(dev) == bwn_devs[i].sd_device &&
505 siba_get_revid(dev) == bwn_devs[i].sd_rev)
506 return (BUS_PROBE_DEFAULT);
507 }
508
509 return (ENXIO);
510}
511
512static int
513bwn_attach(device_t dev)
514{
515 struct bwn_mac *mac;
516 struct bwn_softc *sc = device_get_softc(dev);
517 int error, i, msic, reg;
518
519 sc->sc_dev = dev;
520#ifdef BWN_DEBUG
521 sc->sc_debug = bwn_debug;
522#endif
523
524 if ((sc->sc_flags & BWN_FLAG_ATTACHED) == 0) {
525 bwn_attach_pre(sc);
526 bwn_sprom_bugfixes(dev);
527 sc->sc_flags |= BWN_FLAG_ATTACHED;
528 }
529
530 if (!TAILQ_EMPTY(&sc->sc_maclist)) {
531 if (siba_get_pci_device(dev) != 0x4313 &&
532 siba_get_pci_device(dev) != 0x431a &&
533 siba_get_pci_device(dev) != 0x4321) {
534 device_printf(sc->sc_dev,
535 "skip 802.11 cores\n");
536 return (ENODEV);
537 }
538 }
539
540 mac = malloc(sizeof(*mac), M_DEVBUF, M_WAITOK | M_ZERO);
541 mac->mac_sc = sc;
542 mac->mac_status = BWN_MAC_STATUS_UNINIT;
543 if (bwn_bfp != 0)
544 mac->mac_flags |= BWN_MAC_FLAG_BADFRAME_PREEMP;
545
546 TASK_INIT(&mac->mac_hwreset, 0, bwn_hwreset, mac);
547 TASK_INIT(&mac->mac_intrtask, 0, bwn_intrtask, mac);
548 TASK_INIT(&mac->mac_txpower, 0, bwn_txpwr, mac);
549
550 error = bwn_attach_core(mac);
551 if (error)
552 goto fail0;
553 bwn_led_attach(mac);
554
555 device_printf(sc->sc_dev, "WLAN (chipid %#x rev %u) "
556 "PHY (analog %d type %d rev %d) RADIO (manuf %#x ver %#x rev %d)\n",
557 siba_get_chipid(sc->sc_dev), siba_get_revid(sc->sc_dev),
558 mac->mac_phy.analog, mac->mac_phy.type, mac->mac_phy.rev,
559 mac->mac_phy.rf_manuf, mac->mac_phy.rf_ver,
560 mac->mac_phy.rf_rev);
561 if (mac->mac_flags & BWN_MAC_FLAG_DMA)
562 device_printf(sc->sc_dev, "DMA (%d bits)\n",
563 mac->mac_method.dma.dmatype);
564 else
565 device_printf(sc->sc_dev, "PIO\n");
566
567 /*
568 * setup PCI resources and interrupt.
569 */
570 if (pci_find_cap(dev, PCIY_EXPRESS, &reg) == 0) {
571 msic = pci_msi_count(dev);
572 if (bootverbose)
573 device_printf(sc->sc_dev, "MSI count : %d\n", msic);
574 } else
575 msic = 0;
576
577 mac->mac_intr_spec = bwn_res_spec_legacy;
578 if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0) {
579 if (pci_alloc_msi(dev, &msic) == 0) {
580 device_printf(sc->sc_dev,
581 "Using %d MSI messages\n", msic);
582 mac->mac_intr_spec = bwn_res_spec_msi;
583 mac->mac_msi = 1;
584 }
585 }
586
587 error = bus_alloc_resources(dev, mac->mac_intr_spec,
588 mac->mac_res_irq);
589 if (error) {
590 device_printf(sc->sc_dev,
591 "couldn't allocate IRQ resources (%d)\n", error);
592 goto fail1;
593 }
594
595 if (mac->mac_msi == 0)
596 error = bus_setup_intr(dev, mac->mac_res_irq[0],
597 INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac,
598 &mac->mac_intrhand[0]);
599 else {
600 for (i = 0; i < BWN_MSI_MESSAGES; i++) {
601 error = bus_setup_intr(dev, mac->mac_res_irq[i],
602 INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac,
603 &mac->mac_intrhand[i]);
604 if (error != 0) {
605 device_printf(sc->sc_dev,
606 "couldn't setup interrupt (%d)\n", error);
607 break;
608 }
609 }
610 }
611
612 TAILQ_INSERT_TAIL(&sc->sc_maclist, mac, mac_list);
613
614 /*
615 * calls attach-post routine
616 */
617 if ((sc->sc_flags & BWN_FLAG_ATTACHED) != 0)
618 bwn_attach_post(sc);
619
620 return (0);
621fail1:
622 if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0)
623 pci_release_msi(dev);
624fail0:
625 free(mac, M_DEVBUF);
626 return (error);
627}
628
629static int
630bwn_is_valid_ether_addr(uint8_t *addr)
631{
632 char zero_addr[6] = { 0, 0, 0, 0, 0, 0 };
633
634 if ((addr[0] & 1) || (!bcmp(addr, zero_addr, ETHER_ADDR_LEN)))
635 return (FALSE);
636
637 return (TRUE);
638}
639
640static int
641bwn_attach_post(struct bwn_softc *sc)
642{
643 struct ieee80211com *ic = &sc->sc_ic;
644
645 ic->ic_softc = sc;
646 ic->ic_name = device_get_nameunit(sc->sc_dev);
647 /* XXX not right but it's not used anywhere important */
648 ic->ic_phytype = IEEE80211_T_OFDM;
649 ic->ic_opmode = IEEE80211_M_STA;
650 ic->ic_caps =
651 IEEE80211_C_STA /* station mode supported */
652 | IEEE80211_C_MONITOR /* monitor mode */
653 | IEEE80211_C_AHDEMO /* adhoc demo mode */
654 | IEEE80211_C_SHPREAMBLE /* short preamble supported */
655 | IEEE80211_C_SHSLOT /* short slot time supported */
656 | IEEE80211_C_WME /* WME/WMM supported */
657 | IEEE80211_C_WPA /* capable of WPA1+WPA2 */
658#if 0
659 | IEEE80211_C_BGSCAN /* capable of bg scanning */
660#endif
661 | IEEE80211_C_TXPMGT /* capable of txpow mgt */
662 ;
663
664 ic->ic_flags_ext |= IEEE80211_FEXT_SWBMISS; /* s/w bmiss */
665
666 IEEE80211_ADDR_COPY(ic->ic_macaddr,
667 bwn_is_valid_ether_addr(siba_sprom_get_mac_80211a(sc->sc_dev)) ?
668 siba_sprom_get_mac_80211a(sc->sc_dev) :
669 siba_sprom_get_mac_80211bg(sc->sc_dev));
670
671 /* call MI attach routine. */
672 ieee80211_ifattach(ic);
673
674 ic->ic_headroom = sizeof(struct bwn_txhdr);
675
676 /* override default methods */
677 ic->ic_raw_xmit = bwn_raw_xmit;
678 ic->ic_updateslot = bwn_updateslot;
679 ic->ic_update_promisc = bwn_update_promisc;
680 ic->ic_wme.wme_update = bwn_wme_update;
681 ic->ic_scan_start = bwn_scan_start;
682 ic->ic_scan_end = bwn_scan_end;
683 ic->ic_set_channel = bwn_set_channel;
684 ic->ic_vap_create = bwn_vap_create;
685 ic->ic_vap_delete = bwn_vap_delete;
686 ic->ic_transmit = bwn_transmit;
687 ic->ic_parent = bwn_parent;
688
689 ieee80211_radiotap_attach(ic,
690 &sc->sc_tx_th.wt_ihdr, sizeof(sc->sc_tx_th),
691 BWN_TX_RADIOTAP_PRESENT,
692 &sc->sc_rx_th.wr_ihdr, sizeof(sc->sc_rx_th),
693 BWN_RX_RADIOTAP_PRESENT);
694
695 bwn_sysctl_node(sc);
696
697 if (bootverbose)
698 ieee80211_announce(ic);
699 return (0);
700}
701
702static void
703bwn_phy_detach(struct bwn_mac *mac)
704{
705
706 if (mac->mac_phy.detach != NULL)
707 mac->mac_phy.detach(mac);
708}
709
710static int
711bwn_detach(device_t dev)
712{
713 struct bwn_softc *sc = device_get_softc(dev);
714 struct bwn_mac *mac = sc->sc_curmac;
715 struct ieee80211com *ic = &sc->sc_ic;
716 int i;
717
718 sc->sc_flags |= BWN_FLAG_INVALID;
719
720 if (device_is_attached(sc->sc_dev)) {
721 BWN_LOCK(sc);
722 bwn_stop(sc);
723 BWN_UNLOCK(sc);
724 bwn_dma_free(mac);
725 callout_drain(&sc->sc_led_blink_ch);
726 callout_drain(&sc->sc_rfswitch_ch);
727 callout_drain(&sc->sc_task_ch);
728 callout_drain(&sc->sc_watchdog_ch);
729 bwn_phy_detach(mac);
730 ieee80211_draintask(ic, &mac->mac_hwreset);
731 ieee80211_draintask(ic, &mac->mac_txpower);
732 ieee80211_ifdetach(ic);
733 }
734 taskqueue_drain(sc->sc_tq, &mac->mac_intrtask);
735 taskqueue_free(sc->sc_tq);
736
737 for (i = 0; i < BWN_MSI_MESSAGES; i++) {
738 if (mac->mac_intrhand[i] != NULL) {
739 bus_teardown_intr(dev, mac->mac_res_irq[i],
740 mac->mac_intrhand[i]);
741 mac->mac_intrhand[i] = NULL;
742 }
743 }
744 bus_release_resources(dev, mac->mac_intr_spec, mac->mac_res_irq);
745 if (mac->mac_msi != 0)
746 pci_release_msi(dev);
747 mbufq_drain(&sc->sc_snd);
748 BWN_LOCK_DESTROY(sc);
749 return (0);
750}
751
752static void
753bwn_attach_pre(struct bwn_softc *sc)
754{
755
756 BWN_LOCK_INIT(sc);
757 TAILQ_INIT(&sc->sc_maclist);
758 callout_init_mtx(&sc->sc_rfswitch_ch, &sc->sc_mtx, 0);
759 callout_init_mtx(&sc->sc_task_ch, &sc->sc_mtx, 0);
760 callout_init_mtx(&sc->sc_watchdog_ch, &sc->sc_mtx, 0);
761 mbufq_init(&sc->sc_snd, ifqmaxlen);
762 sc->sc_tq = taskqueue_create_fast("bwn_taskq", M_NOWAIT,
763 taskqueue_thread_enqueue, &sc->sc_tq);
764 taskqueue_start_threads(&sc->sc_tq, 1, PI_NET,
765 "%s taskq", device_get_nameunit(sc->sc_dev));
766}
767
768static void
769bwn_sprom_bugfixes(device_t dev)
770{
771#define BWN_ISDEV(_vendor, _device, _subvendor, _subdevice) \
772 ((siba_get_pci_vendor(dev) == PCI_VENDOR_##_vendor) && \
773 (siba_get_pci_device(dev) == _device) && \
774 (siba_get_pci_subvendor(dev) == PCI_VENDOR_##_subvendor) && \
775 (siba_get_pci_subdevice(dev) == _subdevice))
776
777 if (siba_get_pci_subvendor(dev) == PCI_VENDOR_APPLE &&
778 siba_get_pci_subdevice(dev) == 0x4e &&
779 siba_get_pci_revid(dev) > 0x40)
780 siba_sprom_set_bf_lo(dev,
781 siba_sprom_get_bf_lo(dev) | BWN_BFL_PACTRL);
782 if (siba_get_pci_subvendor(dev) == SIBA_BOARDVENDOR_DELL &&
783 siba_get_chipid(dev) == 0x4301 && siba_get_pci_revid(dev) == 0x74)
784 siba_sprom_set_bf_lo(dev,
785 siba_sprom_get_bf_lo(dev) | BWN_BFL_BTCOEXIST);
786 if (siba_get_type(dev) == SIBA_TYPE_PCI) {
787 if (BWN_ISDEV(BROADCOM, 0x4318, ASUSTEK, 0x100f) ||
788 BWN_ISDEV(BROADCOM, 0x4320, DELL, 0x0003) ||
789 BWN_ISDEV(BROADCOM, 0x4320, HP, 0x12f8) ||
790 BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0013) ||
791 BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0014) ||
792 BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0015) ||
793 BWN_ISDEV(BROADCOM, 0x4320, MOTOROLA, 0x7010))
794 siba_sprom_set_bf_lo(dev,
795 siba_sprom_get_bf_lo(dev) & ~BWN_BFL_BTCOEXIST);
796 }
797#undef BWN_ISDEV
798}
799
800static void
801bwn_parent(struct ieee80211com *ic)
802{
803 struct bwn_softc *sc = ic->ic_softc;
804 int startall = 0;
805
806 BWN_LOCK(sc);
807 if (ic->ic_nrunning > 0) {
808 if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0) {
809 bwn_init(sc);
810 startall = 1;
811 } else
812 bwn_update_promisc(ic);
813 } else if (sc->sc_flags & BWN_FLAG_RUNNING)
814 bwn_stop(sc);
815 BWN_UNLOCK(sc);
816
817 if (startall)
818 ieee80211_start_all(ic);
819}
820
821static int
822bwn_transmit(struct ieee80211com *ic, struct mbuf *m)
823{
824 struct bwn_softc *sc = ic->ic_softc;
825 int error;
826
827 BWN_LOCK(sc);
828 if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0) {
829 BWN_UNLOCK(sc);
830 return (ENXIO);
831 }
832 error = mbufq_enqueue(&sc->sc_snd, m);
833 if (error) {
834 BWN_UNLOCK(sc);
835 return (error);
836 }
837 bwn_start(sc);
838 BWN_UNLOCK(sc);
839 return (0);
840}
841
842static void
843bwn_start(struct bwn_softc *sc)
844{
845 struct bwn_mac *mac = sc->sc_curmac;
846 struct ieee80211_frame *wh;
847 struct ieee80211_node *ni;
848 struct ieee80211_key *k;
849 struct mbuf *m;
850
851 BWN_ASSERT_LOCKED(sc);
852
853 if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0 || mac == NULL ||
854 mac->mac_status < BWN_MAC_STATUS_STARTED)
855 return;
856
857 while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
858 if (bwn_tx_isfull(sc, m))
859 break;
860 ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
861 if (ni == NULL) {
862 device_printf(sc->sc_dev, "unexpected NULL ni\n");
863 m_freem(m);
864 counter_u64_add(sc->sc_ic.ic_oerrors, 1);
865 continue;
866 }
867 wh = mtod(m, struct ieee80211_frame *);
868 if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
869 k = ieee80211_crypto_encap(ni, m);
870 if (k == NULL) {
871 if_inc_counter(ni->ni_vap->iv_ifp,
872 IFCOUNTER_OERRORS, 1);
873 ieee80211_free_node(ni);
874 m_freem(m);
875 continue;
876 }
877 }
878 wh = NULL; /* Catch any invalid use */
879 if (bwn_tx_start(sc, ni, m) != 0) {
880 if (ni != NULL) {
881 if_inc_counter(ni->ni_vap->iv_ifp,
882 IFCOUNTER_OERRORS, 1);
883 ieee80211_free_node(ni);
884 }
885 continue;
886 }
887 sc->sc_watchdog_timer = 5;
888 }
889}
890
891static int
892bwn_tx_isfull(struct bwn_softc *sc, struct mbuf *m)
893{
894 struct bwn_dma_ring *dr;
895 struct bwn_mac *mac = sc->sc_curmac;
896 struct bwn_pio_txqueue *tq;
897 int pktlen = roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
898
899 BWN_ASSERT_LOCKED(sc);
900
901 if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
902 dr = bwn_dma_select(mac, M_WME_GETAC(m));
903 if (dr->dr_stop == 1 ||
904 bwn_dma_freeslot(dr) < BWN_TX_SLOTS_PER_FRAME) {
905 dr->dr_stop = 1;
906 goto full;
907 }
908 } else {
909 tq = bwn_pio_select(mac, M_WME_GETAC(m));
910 if (tq->tq_free == 0 || pktlen > tq->tq_size ||
911 pktlen > (tq->tq_size - tq->tq_used))
912 goto full;
913 }
914 return (0);
915full:
916 mbufq_prepend(&sc->sc_snd, m);
917 return (1);
918}
919
920static int
921bwn_tx_start(struct bwn_softc *sc, struct ieee80211_node *ni, struct mbuf *m)
922{
923 struct bwn_mac *mac = sc->sc_curmac;
924 int error;
925
926 BWN_ASSERT_LOCKED(sc);
927
928 if (m->m_pkthdr.len < IEEE80211_MIN_LEN || mac == NULL) {
929 m_freem(m);
930 return (ENXIO);
931 }
932
933 error = (mac->mac_flags & BWN_MAC_FLAG_DMA) ?
934 bwn_dma_tx_start(mac, ni, m) : bwn_pio_tx_start(mac, ni, m);
935 if (error) {
936 m_freem(m);
937 return (error);
938 }
939 return (0);
940}
941
942static int
943bwn_pio_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
944{
945 struct bwn_pio_txpkt *tp;
946 struct bwn_pio_txqueue *tq = bwn_pio_select(mac, M_WME_GETAC(m));
947 struct bwn_softc *sc = mac->mac_sc;
948 struct bwn_txhdr txhdr;
949 struct mbuf *m_new;
950 uint32_t ctl32;
951 int error;
952 uint16_t ctl16;
953
954 BWN_ASSERT_LOCKED(sc);
955
956 /* XXX TODO send packets after DTIM */
957
958 KASSERT(!TAILQ_EMPTY(&tq->tq_pktlist), ("%s: fail", __func__));
959 tp = TAILQ_FIRST(&tq->tq_pktlist);
960 tp->tp_ni = ni;
961 tp->tp_m = m;
962
963 error = bwn_set_txhdr(mac, ni, m, &txhdr, BWN_PIO_COOKIE(tq, tp));
964 if (error) {
965 device_printf(sc->sc_dev, "tx fail\n");
966 return (error);
967 }
968
969 TAILQ_REMOVE(&tq->tq_pktlist, tp, tp_list);
970 tq->tq_used += roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
971 tq->tq_free--;
972
973 if (siba_get_revid(sc->sc_dev) >= 8) {
974 /*
975 * XXX please removes m_defrag(9)
976 */
977 m_new = m_defrag(m, M_NOWAIT);
978 if (m_new == NULL) {
979 device_printf(sc->sc_dev,
980 "%s: can't defrag TX buffer\n",
981 __func__);
982 return (ENOBUFS);
983 }
984 if (m_new->m_next != NULL)
985 device_printf(sc->sc_dev,
986 "TODO: fragmented packets for PIO\n");
987 tp->tp_m = m_new;
988
989 /* send HEADER */
990 ctl32 = bwn_pio_write_multi_4(mac, tq,
991 (BWN_PIO_READ_4(mac, tq, BWN_PIO8_TXCTL) |
992 BWN_PIO8_TXCTL_FRAMEREADY) & ~BWN_PIO8_TXCTL_EOF,
993 (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
994 /* send BODY */
995 ctl32 = bwn_pio_write_multi_4(mac, tq, ctl32,
996 mtod(m_new, const void *), m_new->m_pkthdr.len);
997 bwn_pio_write_4(mac, tq, BWN_PIO_TXCTL,
998 ctl32 | BWN_PIO8_TXCTL_EOF);
999 } else {
1000 ctl16 = bwn_pio_write_multi_2(mac, tq,
1001 (bwn_pio_read_2(mac, tq, BWN_PIO_TXCTL) |
1002 BWN_PIO_TXCTL_FRAMEREADY) & ~BWN_PIO_TXCTL_EOF,
1003 (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1004 ctl16 = bwn_pio_write_mbuf_2(mac, tq, ctl16, m);
1005 BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL,
1006 ctl16 | BWN_PIO_TXCTL_EOF);
1007 }
1008
1009 return (0);
1010}
1011
1012static struct bwn_pio_txqueue *
1013bwn_pio_select(struct bwn_mac *mac, uint8_t prio)
1014{
1015
1016 if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
1017 return (&mac->mac_method.pio.wme[WME_AC_BE]);
1018
1019 switch (prio) {
1020 case 0:
1021 return (&mac->mac_method.pio.wme[WME_AC_BE]);
1022 case 1:
1023 return (&mac->mac_method.pio.wme[WME_AC_BK]);
1024 case 2:
1025 return (&mac->mac_method.pio.wme[WME_AC_VI]);
1026 case 3:
1027 return (&mac->mac_method.pio.wme[WME_AC_VO]);
1028 }
1029 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
1030 return (NULL);
1031}
1032
1033static int
1034bwn_dma_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1035{
1036#define BWN_GET_TXHDRCACHE(slot) \
1037 &(txhdr_cache[(slot / BWN_TX_SLOTS_PER_FRAME) * BWN_HDRSIZE(mac)])
1038 struct bwn_dma *dma = &mac->mac_method.dma;
1039 struct bwn_dma_ring *dr = bwn_dma_select(mac, M_WME_GETAC(m));
1040 struct bwn_dmadesc_generic *desc;
1041 struct bwn_dmadesc_meta *mt;
1042 struct bwn_softc *sc = mac->mac_sc;
1043 uint8_t *txhdr_cache = (uint8_t *)dr->dr_txhdr_cache;
1044 int error, slot, backup[2] = { dr->dr_curslot, dr->dr_usedslot };
1045
1046 BWN_ASSERT_LOCKED(sc);
1047 KASSERT(!dr->dr_stop, ("%s:%d: fail", __func__, __LINE__));
1048
1049 /* XXX send after DTIM */
1050
1051 slot = bwn_dma_getslot(dr);
1052 dr->getdesc(dr, slot, &desc, &mt);
1053 KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_HEADER,
1054 ("%s:%d: fail", __func__, __LINE__));
1055
1056 error = bwn_set_txhdr(dr->dr_mac, ni, m,
1057 (struct bwn_txhdr *)BWN_GET_TXHDRCACHE(slot),
1058 BWN_DMA_COOKIE(dr, slot));
1059 if (error)
1060 goto fail;
1061 error = bus_dmamap_load(dr->dr_txring_dtag, mt->mt_dmap,
1062 BWN_GET_TXHDRCACHE(slot), BWN_HDRSIZE(mac), bwn_dma_ring_addr,
1063 &mt->mt_paddr, BUS_DMA_NOWAIT);
1064 if (error) {
1065 device_printf(sc->sc_dev, "%s: can't load TX buffer (1) %d\n",
1066 __func__, error);
1067 goto fail;
1068 }
1069 bus_dmamap_sync(dr->dr_txring_dtag, mt->mt_dmap,
1070 BUS_DMASYNC_PREWRITE);
1071 dr->setdesc(dr, desc, mt->mt_paddr, BWN_HDRSIZE(mac), 1, 0, 0);
1072 bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1073 BUS_DMASYNC_PREWRITE);
1074
1075 slot = bwn_dma_getslot(dr);
1076 dr->getdesc(dr, slot, &desc, &mt);
1077 KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_BODY &&
1078 mt->mt_islast == 1, ("%s:%d: fail", __func__, __LINE__));
1079 mt->mt_m = m;
1080 mt->mt_ni = ni;
1081
1082 error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap, m,
1083 bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1084 if (error && error != EFBIG) {
1085 device_printf(sc->sc_dev, "%s: can't load TX buffer (1) %d\n",
1086 __func__, error);
1087 goto fail;
1088 }
1089 if (error) { /* error == EFBIG */
1090 struct mbuf *m_new;
1091
1092 m_new = m_defrag(m, M_NOWAIT);
1093 if (m_new == NULL) {
1094 device_printf(sc->sc_dev,
1095 "%s: can't defrag TX buffer\n",
1096 __func__);
1097 error = ENOBUFS;
1098 goto fail;
1099 } else {
1100 m = m_new;
1101 }
1102
1103 mt->mt_m = m;
1104 error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap,
1105 m, bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1106 if (error) {
1107 device_printf(sc->sc_dev,
1108 "%s: can't load TX buffer (2) %d\n",
1109 __func__, error);
1110 goto fail;
1111 }
1112 }
1113 bus_dmamap_sync(dma->txbuf_dtag, mt->mt_dmap, BUS_DMASYNC_PREWRITE);
1114 dr->setdesc(dr, desc, mt->mt_paddr, m->m_pkthdr.len, 0, 1, 1);
1115 bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1116 BUS_DMASYNC_PREWRITE);
1117
1118 /* XXX send after DTIM */
1119
1120 dr->start_transfer(dr, bwn_dma_nextslot(dr, slot));
1121 return (0);
1122fail:
1123 dr->dr_curslot = backup[0];
1124 dr->dr_usedslot = backup[1];
1125 return (error);
1126#undef BWN_GET_TXHDRCACHE
1127}
1128
1129static void
1130bwn_watchdog(void *arg)
1131{
1132 struct bwn_softc *sc = arg;
1133
1134 if (sc->sc_watchdog_timer != 0 && --sc->sc_watchdog_timer == 0) {
1135 device_printf(sc->sc_dev, "device timeout\n");
1136 counter_u64_add(sc->sc_ic.ic_oerrors, 1);
1137 }
1138 callout_schedule(&sc->sc_watchdog_ch, hz);
1139}
1140
1141static int
1142bwn_attach_core(struct bwn_mac *mac)
1143{
1144 struct bwn_softc *sc = mac->mac_sc;
1145 int error, have_bg = 0, have_a = 0;
1146 uint32_t high;
1147
1148 KASSERT(siba_get_revid(sc->sc_dev) >= 5,
1149 ("unsupported revision %d", siba_get_revid(sc->sc_dev)));
1150
1151 siba_powerup(sc->sc_dev, 0);
1152
1153 high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH);
1154
1155 /*
1156 * Guess at whether it has A-PHY or G-PHY.
1157 * This is just used for resetting the core to probe things;
1158 * we will re-guess once it's all up and working.
1159 *
1160 * XXX TODO: there's the TGSHIGH DUALPHY flag based on
1161 * the PHY revision.
1162 */
1163 bwn_reset_core(mac, !!(high & BWN_TGSHIGH_HAVE_2GHZ));
1164
1165 /*
1166 * Get the PHY version.
1167 */
1168 error = bwn_phy_getinfo(mac, high);
1169 if (error)
1170 goto fail;
1171
1172 /* XXX TODO need bhnd */
1173 if (bwn_is_bus_siba(mac)) {
1174 have_a = (high & BWN_TGSHIGH_HAVE_5GHZ) ? 1 : 0;
1175 have_bg = (high & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1176 if (high & BWN_TGSHIGH_DUALPHY) {
1177 have_bg = 1;
1178 have_a = 1;
1179 }
1180 } else {
1181 device_printf(sc->sc_dev, "%s: not siba; bailing\n", __func__);
1182 error = ENXIO;
1183 goto fail;
1184 }
1185
1186#if 0
1187 device_printf(sc->sc_dev, "%s: high=0x%08x, have_a=%d, have_bg=%d,"
1188 " deviceid=0x%04x, siba_deviceid=0x%04x\n",
1189 __func__,
1190 high,
1191 have_a,
1192 have_bg,
1193 siba_get_pci_device(sc->sc_dev),
1194 siba_get_chipid(sc->sc_dev));
1195#endif
1196
1197 if (siba_get_pci_device(sc->sc_dev) != 0x4312 &&
1198 siba_get_pci_device(sc->sc_dev) != 0x4319 &&
1199 siba_get_pci_device(sc->sc_dev) != 0x4324 &&
1200 siba_get_pci_device(sc->sc_dev) != 0x4328) {
1201 have_a = have_bg = 0;
1202 if (mac->mac_phy.type == BWN_PHYTYPE_A)
1203 have_a = 1;
1204 else if (mac->mac_phy.type == BWN_PHYTYPE_G ||
1205 mac->mac_phy.type == BWN_PHYTYPE_N ||
1206 mac->mac_phy.type == BWN_PHYTYPE_LP)
1207 have_bg = 1;
1208 else
1209 KASSERT(0 == 1, ("%s: unknown phy type (%d)", __func__,
1210 mac->mac_phy.type));
1211 }
1212
1213 /*
1214 * XXX turns off PHY A because it's not supported.
1215 * Implement PHY-A support so we can use it for PHY-G
1216 * dual-band support.
1217 */
1218 if (mac->mac_phy.type != BWN_PHYTYPE_LP &&
1219 mac->mac_phy.type != BWN_PHYTYPE_N) {
1220 device_printf(sc->sc_dev,
1221 "%s: forcing 2GHz only; missing PHY-A support\n",
1222 __func__);
1223 have_a = 0;
1224 have_bg = 1;
1225 }
1226
1227 mac->mac_phy.phy_n = NULL;
1228
1229 if (mac->mac_phy.type == BWN_PHYTYPE_G) {
1230 mac->mac_phy.attach = bwn_phy_g_attach;
1231 mac->mac_phy.detach = bwn_phy_g_detach;
1232 mac->mac_phy.prepare_hw = bwn_phy_g_prepare_hw;
1233 mac->mac_phy.init_pre = bwn_phy_g_init_pre;
1234 mac->mac_phy.init = bwn_phy_g_init;
1235 mac->mac_phy.exit = bwn_phy_g_exit;
1236 mac->mac_phy.phy_read = bwn_phy_g_read;
1237 mac->mac_phy.phy_write = bwn_phy_g_write;
1238 mac->mac_phy.rf_read = bwn_phy_g_rf_read;
1239 mac->mac_phy.rf_write = bwn_phy_g_rf_write;
1240 mac->mac_phy.use_hwpctl = bwn_phy_g_hwpctl;
1241 mac->mac_phy.rf_onoff = bwn_phy_g_rf_onoff;
1242 mac->mac_phy.switch_analog = bwn_phy_switch_analog;
1243 mac->mac_phy.switch_channel = bwn_phy_g_switch_channel;
1244 mac->mac_phy.get_default_chan = bwn_phy_g_get_default_chan;
1245 mac->mac_phy.set_antenna = bwn_phy_g_set_antenna;
1246 mac->mac_phy.set_im = bwn_phy_g_im;
1247 mac->mac_phy.recalc_txpwr = bwn_phy_g_recalc_txpwr;
1248 mac->mac_phy.set_txpwr = bwn_phy_g_set_txpwr;
1249 mac->mac_phy.task_15s = bwn_phy_g_task_15s;
1250 mac->mac_phy.task_60s = bwn_phy_g_task_60s;
1251 } else if (mac->mac_phy.type == BWN_PHYTYPE_LP) {
1252 mac->mac_phy.init_pre = bwn_phy_lp_init_pre;
1253 mac->mac_phy.init = bwn_phy_lp_init;
1254 mac->mac_phy.phy_read = bwn_phy_lp_read;
1255 mac->mac_phy.phy_write = bwn_phy_lp_write;
1256 mac->mac_phy.phy_maskset = bwn_phy_lp_maskset;
1257 mac->mac_phy.rf_read = bwn_phy_lp_rf_read;
1258 mac->mac_phy.rf_write = bwn_phy_lp_rf_write;
1259 mac->mac_phy.rf_onoff = bwn_phy_lp_rf_onoff;
1260 mac->mac_phy.switch_analog = bwn_phy_lp_switch_analog;
1261 mac->mac_phy.switch_channel = bwn_phy_lp_switch_channel;
1262 mac->mac_phy.get_default_chan = bwn_phy_lp_get_default_chan;
1263 mac->mac_phy.set_antenna = bwn_phy_lp_set_antenna;
1264 mac->mac_phy.task_60s = bwn_phy_lp_task_60s;
1265 } else if (mac->mac_phy.type == BWN_PHYTYPE_N) {
1266 mac->mac_phy.attach = bwn_phy_n_attach;
1267 mac->mac_phy.detach = bwn_phy_n_detach;
1268 mac->mac_phy.prepare_hw = bwn_phy_n_prepare_hw;
1269 mac->mac_phy.init_pre = bwn_phy_n_init_pre;
1270 mac->mac_phy.init = bwn_phy_n_init;
1271 mac->mac_phy.exit = bwn_phy_n_exit;
1272 mac->mac_phy.phy_read = bwn_phy_n_read;
1273 mac->mac_phy.phy_write = bwn_phy_n_write;
1274 mac->mac_phy.rf_read = bwn_phy_n_rf_read;
1275 mac->mac_phy.rf_write = bwn_phy_n_rf_write;
1276 mac->mac_phy.use_hwpctl = bwn_phy_n_hwpctl;
1277 mac->mac_phy.rf_onoff = bwn_phy_n_rf_onoff;
1278 mac->mac_phy.switch_analog = bwn_phy_n_switch_analog;
1279 mac->mac_phy.switch_channel = bwn_phy_n_switch_channel;
1280 mac->mac_phy.get_default_chan = bwn_phy_n_get_default_chan;
1281 mac->mac_phy.set_antenna = bwn_phy_n_set_antenna;
1282 mac->mac_phy.set_im = bwn_phy_n_im;
1283 mac->mac_phy.recalc_txpwr = bwn_phy_n_recalc_txpwr;
1284 mac->mac_phy.set_txpwr = bwn_phy_n_set_txpwr;
1285 mac->mac_phy.task_15s = bwn_phy_n_task_15s;
1286 mac->mac_phy.task_60s = bwn_phy_n_task_60s;
1287 } else {
1288 device_printf(sc->sc_dev, "unsupported PHY type (%d)\n",
1289 mac->mac_phy.type);
1290 error = ENXIO;
1291 goto fail;
1292 }
1293
1294 mac->mac_phy.gmode = have_bg;
1295 if (mac->mac_phy.attach != NULL) {
1296 error = mac->mac_phy.attach(mac);
1297 if (error) {
1298 device_printf(sc->sc_dev, "failed\n");
1299 goto fail;
1300 }
1301 }
1302
1303 bwn_reset_core(mac, have_bg);
1304
1305 error = bwn_chiptest(mac);
1306 if (error)
1307 goto fail;
1308 error = bwn_setup_channels(mac, have_bg, have_a);
1309 if (error) {
1310 device_printf(sc->sc_dev, "failed to setup channels\n");
1311 goto fail;
1312 }
1313
1314 if (sc->sc_curmac == NULL)
1315 sc->sc_curmac = mac;
1316
1317 error = bwn_dma_attach(mac);
1318 if (error != 0) {
1319 device_printf(sc->sc_dev, "failed to initialize DMA\n");
1320 goto fail;
1321 }
1322
1323 mac->mac_phy.switch_analog(mac, 0);
1324
1325 siba_dev_down(sc->sc_dev, 0);
1326fail:
1327 siba_powerdown(sc->sc_dev);
1328 return (error);
1329}
1330
1331/*
1332 * Reset - SIBA.
1333 *
1334 * XXX TODO: implement BCMA version!
1335 */
1336void
1337bwn_reset_core(struct bwn_mac *mac, int g_mode)
1338{
1339 struct bwn_softc *sc = mac->mac_sc;
1340 uint32_t low, ctl;
1341 uint32_t flags = 0;
1342
1343 DPRINTF(sc, BWN_DEBUG_RESET, "%s: g_mode=%d\n", __func__, g_mode);
1344
1345 flags |= (BWN_TGSLOW_PHYCLOCK_ENABLE | BWN_TGSLOW_PHYRESET);
1346 if (g_mode)
1347 flags |= BWN_TGSLOW_SUPPORT_G;
1348
1349 /* XXX N-PHY only; and hard-code to 20MHz for now */
1350 if (mac->mac_phy.type == BWN_PHYTYPE_N)
1351 flags |= BWN_TGSLOW_PHY_BANDWIDTH_20MHZ;
1352
1353 siba_dev_up(sc->sc_dev, flags);
1354 DELAY(2000);
1355
1356 /* Take PHY out of reset */
1357 low = (siba_read_4(sc->sc_dev, SIBA_TGSLOW) | SIBA_TGSLOW_FGC) &
1358 ~BWN_TGSLOW_PHYRESET;
1359 siba_write_4(sc->sc_dev, SIBA_TGSLOW, low);
1360 siba_read_4(sc->sc_dev, SIBA_TGSLOW);
1361 DELAY(1000);
1362 siba_write_4(sc->sc_dev, SIBA_TGSLOW, low & ~SIBA_TGSLOW_FGC);
1363 siba_read_4(sc->sc_dev, SIBA_TGSLOW);
1364 DELAY(1000);
1365
1366 if (mac->mac_phy.switch_analog != NULL)
1367 mac->mac_phy.switch_analog(mac, 1);
1368
1369 ctl = BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GMODE;
1370 if (g_mode)
1371 ctl |= BWN_MACCTL_GMODE;
1372 BWN_WRITE_4(mac, BWN_MACCTL, ctl | BWN_MACCTL_IHR_ON);
1373}
1374
1375static int
1376bwn_phy_getinfo(struct bwn_mac *mac, int tgshigh)
1377{
1378 struct bwn_phy *phy = &mac->mac_phy;
1379 struct bwn_softc *sc = mac->mac_sc;
1380 uint32_t tmp;
1381
1382 /* PHY */
1383 tmp = BWN_READ_2(mac, BWN_PHYVER);
1384 phy->gmode = !! (tgshigh & BWN_TGSHIGH_HAVE_2GHZ);
1385 phy->rf_on = 1;
1386 phy->analog = (tmp & BWN_PHYVER_ANALOG) >> 12;
1387 phy->type = (tmp & BWN_PHYVER_TYPE) >> 8;
1388 phy->rev = (tmp & BWN_PHYVER_VERSION);
1389 if ((phy->type == BWN_PHYTYPE_A && phy->rev >= 4) ||
1390 (phy->type == BWN_PHYTYPE_B && phy->rev != 2 &&
1391 phy->rev != 4 && phy->rev != 6 && phy->rev != 7) ||
1392 (phy->type == BWN_PHYTYPE_G && phy->rev > 9) ||
1393 (phy->type == BWN_PHYTYPE_N && phy->rev > 4) ||
1394 (phy->type == BWN_PHYTYPE_LP && phy->rev > 2))
1395 goto unsupphy;
1396
1397 /* RADIO */
1398 if (siba_get_chipid(sc->sc_dev) == 0x4317) {
1399 if (siba_get_chiprev(sc->sc_dev) == 0)
1400 tmp = 0x3205017f;
1401 else if (siba_get_chiprev(sc->sc_dev) == 1)
1402 tmp = 0x4205017f;
1403 else
1404 tmp = 0x5205017f;
1405 } else {
1406 BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1407 tmp = BWN_READ_2(mac, BWN_RFDATALO);
1408 BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1409 tmp |= (uint32_t)BWN_READ_2(mac, BWN_RFDATAHI) << 16;
1410 }
1411 phy->rf_rev = (tmp & 0xf0000000) >> 28;
1412 phy->rf_ver = (tmp & 0x0ffff000) >> 12;
1413 phy->rf_manuf = (tmp & 0x00000fff);
1414
1415 /*
1416 * For now, just always do full init (ie, what bwn has traditionally
1417 * done)
1418 */
1419 phy->phy_do_full_init = 1;
1420
1421 if (phy->rf_manuf != 0x17f) /* 0x17f is broadcom */
1422 goto unsupradio;
1423 if ((phy->type == BWN_PHYTYPE_A && (phy->rf_ver != 0x2060 ||
1424 phy->rf_rev != 1 || phy->rf_manuf != 0x17f)) ||
1425 (phy->type == BWN_PHYTYPE_B && (phy->rf_ver & 0xfff0) != 0x2050) ||
1426 (phy->type == BWN_PHYTYPE_G && phy->rf_ver != 0x2050) ||
1427 (phy->type == BWN_PHYTYPE_N &&
1428 phy->rf_ver != 0x2055 && phy->rf_ver != 0x2056) ||
1429 (phy->type == BWN_PHYTYPE_LP &&
1430 phy->rf_ver != 0x2062 && phy->rf_ver != 0x2063))
1431 goto unsupradio;
1432
1433 return (0);
1434unsupphy:
1435 device_printf(sc->sc_dev, "unsupported PHY (type %#x, rev %#x, "
1436 "analog %#x)\n",
1437 phy->type, phy->rev, phy->analog);
1438 return (ENXIO);
1439unsupradio:
1440 device_printf(sc->sc_dev, "unsupported radio (manuf %#x, ver %#x, "
1441 "rev %#x)\n",
1442 phy->rf_manuf, phy->rf_ver, phy->rf_rev);
1443 return (ENXIO);
1444}
1445
1446static int
1447bwn_chiptest(struct bwn_mac *mac)
1448{
1449#define TESTVAL0 0x55aaaa55
1450#define TESTVAL1 0xaa5555aa
1451 struct bwn_softc *sc = mac->mac_sc;
1452 uint32_t v, backup;
1453
1454 BWN_LOCK(sc);
1455
1456 backup = bwn_shm_read_4(mac, BWN_SHARED, 0);
1457
1458 bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL0);
1459 if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL0)
1460 goto error;
1461 bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL1);
1462 if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL1)
1463 goto error;
1464
1465 bwn_shm_write_4(mac, BWN_SHARED, 0, backup);
1466
1467 if ((siba_get_revid(sc->sc_dev) >= 3) &&
1468 (siba_get_revid(sc->sc_dev) <= 10)) {
1469 BWN_WRITE_2(mac, BWN_TSF_CFP_START, 0xaaaa);
1470 BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0xccccbbbb);
1471 if (BWN_READ_2(mac, BWN_TSF_CFP_START_LOW) != 0xbbbb)
1472 goto error;
1473 if (BWN_READ_2(mac, BWN_TSF_CFP_START_HIGH) != 0xcccc)
1474 goto error;
1475 }
1476 BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0);
1477
1478 v = BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_GMODE;
1479 if (v != (BWN_MACCTL_GMODE | BWN_MACCTL_IHR_ON))
1480 goto error;
1481
1482 BWN_UNLOCK(sc);
1483 return (0);
1484error:
1485 BWN_UNLOCK(sc);
1486 device_printf(sc->sc_dev, "failed to validate the chipaccess\n");
1487 return (ENODEV);
1488}
1489
1490static int
1491bwn_setup_channels(struct bwn_mac *mac, int have_bg, int have_a)
1492{
1493 struct bwn_softc *sc = mac->mac_sc;
1494 struct ieee80211com *ic = &sc->sc_ic;
1495 uint8_t bands[howmany(IEEE80211_MODE_MAX, 8)];
1496
1497 memset(ic->ic_channels, 0, sizeof(ic->ic_channels));
1498 ic->ic_nchans = 0;
1499
1500 DPRINTF(sc, BWN_DEBUG_EEPROM, "%s: called; bg=%d, a=%d\n",
1501 __func__,
1502 have_bg,
1503 have_a);
1504
1505 if (have_bg) {
1506 memset(bands, 0, sizeof(bands));
1507 setbit(bands, IEEE80211_MODE_11B);
1508 setbit(bands, IEEE80211_MODE_11G);
1509 bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1510 &ic->ic_nchans, &bwn_chantable_bg, bands);
1511 }
1512
1513 if (have_a) {
1514 memset(bands, 0, sizeof(bands));
1515 setbit(bands, IEEE80211_MODE_11A);
1516 bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1517 &ic->ic_nchans, &bwn_chantable_a, bands);
1518 }
1519
1520 mac->mac_phy.supports_2ghz = have_bg;
1521 mac->mac_phy.supports_5ghz = have_a;
1522
1523 return (ic->ic_nchans == 0 ? ENXIO : 0);
1524}
1525
1526uint32_t
1527bwn_shm_read_4(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1528{
1529 uint32_t ret;
1530
1531 BWN_ASSERT_LOCKED(mac->mac_sc);
1532
1533 if (way == BWN_SHARED) {
1534 KASSERT((offset & 0x0001) == 0,
1535 ("%s:%d warn", __func__, __LINE__));
1536 if (offset & 0x0003) {
1537 bwn_shm_ctlword(mac, way, offset >> 2);
1538 ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1539 ret <<= 16;
1540 bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1541 ret |= BWN_READ_2(mac, BWN_SHM_DATA);
1542 goto out;
1543 }
1544 offset >>= 2;
1545 }
1546 bwn_shm_ctlword(mac, way, offset);
1547 ret = BWN_READ_4(mac, BWN_SHM_DATA);
1548out:
1549 return (ret);
1550}
1551
1552uint16_t
1553bwn_shm_read_2(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1554{
1555 uint16_t ret;
1556
1557 BWN_ASSERT_LOCKED(mac->mac_sc);
1558
1559 if (way == BWN_SHARED) {
1560 KASSERT((offset & 0x0001) == 0,
1561 ("%s:%d warn", __func__, __LINE__));
1562 if (offset & 0x0003) {
1563 bwn_shm_ctlword(mac, way, offset >> 2);
1564 ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1565 goto out;
1566 }
1567 offset >>= 2;
1568 }
1569 bwn_shm_ctlword(mac, way, offset);
1570 ret = BWN_READ_2(mac, BWN_SHM_DATA);
1571out:
1572
1573 return (ret);
1574}
1575
1576static void
1577bwn_shm_ctlword(struct bwn_mac *mac, uint16_t way,
1578 uint16_t offset)
1579{
1580 uint32_t control;
1581
1582 control = way;
1583 control <<= 16;
1584 control |= offset;
1585 BWN_WRITE_4(mac, BWN_SHM_CONTROL, control);
1586}
1587
1588void
1589bwn_shm_write_4(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1590 uint32_t value)
1591{
1592 BWN_ASSERT_LOCKED(mac->mac_sc);
1593
1594 if (way == BWN_SHARED) {
1595 KASSERT((offset & 0x0001) == 0,
1596 ("%s:%d warn", __func__, __LINE__));
1597 if (offset & 0x0003) {
1598 bwn_shm_ctlword(mac, way, offset >> 2);
1599 BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED,
1600 (value >> 16) & 0xffff);
1601 bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1602 BWN_WRITE_2(mac, BWN_SHM_DATA, value & 0xffff);
1603 return;
1604 }
1605 offset >>= 2;
1606 }
1607 bwn_shm_ctlword(mac, way, offset);
1608 BWN_WRITE_4(mac, BWN_SHM_DATA, value);
1609}
1610
1611void
1612bwn_shm_write_2(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1613 uint16_t value)
1614{
1615 BWN_ASSERT_LOCKED(mac->mac_sc);
1616
1617 if (way == BWN_SHARED) {
1618 KASSERT((offset & 0x0001) == 0,
1619 ("%s:%d warn", __func__, __LINE__));
1620 if (offset & 0x0003) {
1621 bwn_shm_ctlword(mac, way, offset >> 2);
1622 BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED, value);
1623 return;
1624 }
1625 offset >>= 2;
1626 }
1627 bwn_shm_ctlword(mac, way, offset);
1628 BWN_WRITE_2(mac, BWN_SHM_DATA, value);
1629}
1630
1631static void
1632bwn_addchannels(struct ieee80211_channel chans[], int maxchans, int *nchans,
1633 const struct bwn_channelinfo *ci, const uint8_t bands[])
1634{
1635 int i, error;
1636
1637 for (i = 0, error = 0; i < ci->nchannels && error == 0; i++) {
1638 const struct bwn_channel *hc = &ci->channels[i];
1639
1640 error = ieee80211_add_channel(chans, maxchans, nchans,
1641 hc->ieee, hc->freq, hc->maxTxPow, 0, bands);
1642 }
1643}
1644
1645static int
1646bwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
1647 const struct ieee80211_bpf_params *params)
1648{
1649 struct ieee80211com *ic = ni->ni_ic;
1650 struct bwn_softc *sc = ic->ic_softc;
1651 struct bwn_mac *mac = sc->sc_curmac;
1652 int error;
1653
1654 if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0 ||
1655 mac->mac_status < BWN_MAC_STATUS_STARTED) {
1656 m_freem(m);
1657 return (ENETDOWN);
1658 }
1659
1660 BWN_LOCK(sc);
1661 if (bwn_tx_isfull(sc, m)) {
1662 m_freem(m);
1663 BWN_UNLOCK(sc);
1664 return (ENOBUFS);
1665 }
1666
1667 error = bwn_tx_start(sc, ni, m);
1668 if (error == 0)
1669 sc->sc_watchdog_timer = 5;
1670 BWN_UNLOCK(sc);
1671 return (error);
1672}
1673
1674/*
1675 * Callback from the 802.11 layer to update the slot time
1676 * based on the current setting. We use it to notify the
1677 * firmware of ERP changes and the f/w takes care of things
1678 * like slot time and preamble.
1679 */
1680static void
1681bwn_updateslot(struct ieee80211com *ic)
1682{
1683 struct bwn_softc *sc = ic->ic_softc;
1684 struct bwn_mac *mac;
1685
1686 BWN_LOCK(sc);
1687 if (sc->sc_flags & BWN_FLAG_RUNNING) {
1688 mac = (struct bwn_mac *)sc->sc_curmac;
1689 bwn_set_slot_time(mac, IEEE80211_GET_SLOTTIME(ic));
1690 }
1691 BWN_UNLOCK(sc);
1692}
1693
1694/*
1695 * Callback from the 802.11 layer after a promiscuous mode change.
1696 * Note this interface does not check the operating mode as this
1697 * is an internal callback and we are expected to honor the current
1698 * state (e.g. this is used for setting the interface in promiscuous
1699 * mode when operating in hostap mode to do ACS).
1700 */
1701static void
1702bwn_update_promisc(struct ieee80211com *ic)
1703{
1704 struct bwn_softc *sc = ic->ic_softc;
1705 struct bwn_mac *mac = sc->sc_curmac;
1706
1707 BWN_LOCK(sc);
1708 mac = sc->sc_curmac;
1709 if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
1710 if (ic->ic_promisc > 0)
1711 sc->sc_filters |= BWN_MACCTL_PROMISC;
1712 else
1713 sc->sc_filters &= ~BWN_MACCTL_PROMISC;
1714 bwn_set_opmode(mac);
1715 }
1716 BWN_UNLOCK(sc);
1717}
1718
1719/*
1720 * Callback from the 802.11 layer to update WME parameters.
1721 */
1722static int
1723bwn_wme_update(struct ieee80211com *ic)
1724{
1725 struct bwn_softc *sc = ic->ic_softc;
1726 struct bwn_mac *mac = sc->sc_curmac;
1727 struct wmeParams *wmep;
1728 int i;
1729
1730 BWN_LOCK(sc);
1731 mac = sc->sc_curmac;
1732 if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
1733 bwn_mac_suspend(mac);
1734 for (i = 0; i < N(sc->sc_wmeParams); i++) {
1735 wmep = &ic->ic_wme.wme_chanParams.cap_wmeParams[i];
1736 bwn_wme_loadparams(mac, wmep, bwn_wme_shm_offsets[i]);
1737 }
1738 bwn_mac_enable(mac);
1739 }
1740 BWN_UNLOCK(sc);
1741 return (0);
1742}
1743
1744static void
1745bwn_scan_start(struct ieee80211com *ic)
1746{
1747 struct bwn_softc *sc = ic->ic_softc;
1748 struct bwn_mac *mac;
1749
1750 BWN_LOCK(sc);
1751 mac = sc->sc_curmac;
1752 if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
1753 sc->sc_filters |= BWN_MACCTL_BEACON_PROMISC;
1754 bwn_set_opmode(mac);
1755 /* disable CFP update during scan */
1756 bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_SKIP_CFP_UPDATE);
1757 }
1758 BWN_UNLOCK(sc);
1759}
1760
1761static void
1762bwn_scan_end(struct ieee80211com *ic)
1763{
1764 struct bwn_softc *sc = ic->ic_softc;
1765 struct bwn_mac *mac;
1766
1767 BWN_LOCK(sc);
1768 mac = sc->sc_curmac;
1769 if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
1770 sc->sc_filters &= ~BWN_MACCTL_BEACON_PROMISC;
1771 bwn_set_opmode(mac);
1772 bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_SKIP_CFP_UPDATE);
1773 }
1774 BWN_UNLOCK(sc);
1775}
1776
1777static void
1778bwn_set_channel(struct ieee80211com *ic)
1779{
1780 struct bwn_softc *sc = ic->ic_softc;
1781 struct bwn_mac *mac = sc->sc_curmac;
1782 struct bwn_phy *phy = &mac->mac_phy;
1783 int chan, error;
1784
1785 BWN_LOCK(sc);
1786
1787 error = bwn_switch_band(sc, ic->ic_curchan);
1788 if (error)
1789 goto fail;
1790 bwn_mac_suspend(mac);
1791 bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
1792 chan = ieee80211_chan2ieee(ic, ic->ic_curchan);
1793 if (chan != phy->chan)
1794 bwn_switch_channel(mac, chan);
1795
1796 /* TX power level */
1797 if (ic->ic_curchan->ic_maxpower != 0 &&
1798 ic->ic_curchan->ic_maxpower != phy->txpower) {
1799 phy->txpower = ic->ic_curchan->ic_maxpower / 2;
1800 bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME |
1801 BWN_TXPWR_IGNORE_TSSI);
1802 }
1803
1804 bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
1805 if (phy->set_antenna)
1806 phy->set_antenna(mac, BWN_ANT_DEFAULT);
1807
1808 if (sc->sc_rf_enabled != phy->rf_on) {
1809 if (sc->sc_rf_enabled) {
1810 bwn_rf_turnon(mac);
1811 if (!(mac->mac_flags & BWN_MAC_FLAG_RADIO_ON))
1812 device_printf(sc->sc_dev,
1813 "please turn on the RF switch\n");
1814 } else
1815 bwn_rf_turnoff(mac);
1816 }
1817
1818 bwn_mac_enable(mac);
1819
1820fail:
1821 /*
1822 * Setup radio tap channel freq and flags
1823 */
1824 sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq =
1825 htole16(ic->ic_curchan->ic_freq);
1826 sc->sc_tx_th.wt_chan_flags = sc->sc_rx_th.wr_chan_flags =
1827 htole16(ic->ic_curchan->ic_flags & 0xffff);
1828
1829 BWN_UNLOCK(sc);
1830}
1831
1832static struct ieee80211vap *
1833bwn_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
1834 enum ieee80211_opmode opmode, int flags,
1835 const uint8_t bssid[IEEE80211_ADDR_LEN],
1836 const uint8_t mac[IEEE80211_ADDR_LEN])
1837{
1838 struct ieee80211vap *vap;
1839 struct bwn_vap *bvp;
1840
1841 switch (opmode) {
1842 case IEEE80211_M_HOSTAP:
1843 case IEEE80211_M_MBSS:
1844 case IEEE80211_M_STA:
1845 case IEEE80211_M_WDS:
1846 case IEEE80211_M_MONITOR:
1847 case IEEE80211_M_IBSS:
1848 case IEEE80211_M_AHDEMO:
1849 break;
1850 default:
1851 return (NULL);
1852 }
1853
1854 bvp = malloc(sizeof(struct bwn_vap), M_80211_VAP, M_WAITOK | M_ZERO);
1855 vap = &bvp->bv_vap;
1856 ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid);
1857 /* override with driver methods */
1858 bvp->bv_newstate = vap->iv_newstate;
1859 vap->iv_newstate = bwn_newstate;
1860
1861 /* override max aid so sta's cannot assoc when we're out of sta id's */
1862 vap->iv_max_aid = BWN_STAID_MAX;
1863
1864 ieee80211_ratectl_init(vap);
1865
1866 /* complete setup */
1867 ieee80211_vap_attach(vap, ieee80211_media_change,
1868 ieee80211_media_status, mac);
1869 return (vap);
1870}
1871
1872static void
1873bwn_vap_delete(struct ieee80211vap *vap)
1874{
1875 struct bwn_vap *bvp = BWN_VAP(vap);
1876
1877 ieee80211_ratectl_deinit(vap);
1878 ieee80211_vap_detach(vap);
1879 free(bvp, M_80211_VAP);
1880}
1881
1882static int
1883bwn_init(struct bwn_softc *sc)
1884{
1885 struct bwn_mac *mac;
1886 int error;
1887
1888 BWN_ASSERT_LOCKED(sc);
1889
1890 DPRINTF(sc, BWN_DEBUG_RESET, "%s: called\n", __func__);
1891
1892 bzero(sc->sc_bssid, IEEE80211_ADDR_LEN);
1893 sc->sc_flags |= BWN_FLAG_NEED_BEACON_TP;
1894 sc->sc_filters = 0;
1895 bwn_wme_clear(sc);
1896 sc->sc_beacons[0] = sc->sc_beacons[1] = 0;
1897 sc->sc_rf_enabled = 1;
1898
1899 mac = sc->sc_curmac;
1900 if (mac->mac_status == BWN_MAC_STATUS_UNINIT) {
1901 error = bwn_core_init(mac);
1902 if (error != 0)
1903 return (error);
1904 }
1905 if (mac->mac_status == BWN_MAC_STATUS_INITED)
1906 bwn_core_start(mac);
1907
1908 bwn_set_opmode(mac);
1909 bwn_set_pretbtt(mac);
1910 bwn_spu_setdelay(mac, 0);
1911 bwn_set_macaddr(mac);
1912
1913 sc->sc_flags |= BWN_FLAG_RUNNING;
1914 callout_reset(&sc->sc_rfswitch_ch, hz, bwn_rfswitch, sc);
1915 callout_reset(&sc->sc_watchdog_ch, hz, bwn_watchdog, sc);
1916
1917 return (0);
1918}
1919
1920static void
1921bwn_stop(struct bwn_softc *sc)
1922{
1923 struct bwn_mac *mac = sc->sc_curmac;
1924
1925 BWN_ASSERT_LOCKED(sc);
1926
1927 DPRINTF(sc, BWN_DEBUG_RESET, "%s: called\n", __func__);
1928
1929 if (mac->mac_status >= BWN_MAC_STATUS_INITED) {
1930 /* XXX FIXME opmode not based on VAP */
1931 bwn_set_opmode(mac);
1932 bwn_set_macaddr(mac);
1933 }
1934
1935 if (mac->mac_status >= BWN_MAC_STATUS_STARTED)
1936 bwn_core_stop(mac);
1937
1938 callout_stop(&sc->sc_led_blink_ch);
1939 sc->sc_led_blinking = 0;
1940
1941 bwn_core_exit(mac);
1942 sc->sc_rf_enabled = 0;
1943
1944 sc->sc_flags &= ~BWN_FLAG_RUNNING;
1945}
1946
1947static void
1948bwn_wme_clear(struct bwn_softc *sc)
1949{
1950#define MS(_v, _f) (((_v) & _f) >> _f##_S)
1951 struct wmeParams *p;
1952 unsigned int i;
1953
1954 KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
1955 ("%s:%d: fail", __func__, __LINE__));
1956
1957 for (i = 0; i < N(sc->sc_wmeParams); i++) {
1958 p = &(sc->sc_wmeParams[i]);
1959
1960 switch (bwn_wme_shm_offsets[i]) {
1961 case BWN_WME_VOICE:
1962 p->wmep_txopLimit = 0;
1963 p->wmep_aifsn = 2;
1964 /* XXX FIXME: log2(cwmin) */
1965 p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
1966 p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
1967 break;
1968 case BWN_WME_VIDEO:
1969 p->wmep_txopLimit = 0;
1970 p->wmep_aifsn = 2;
1971 /* XXX FIXME: log2(cwmin) */
1972 p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
1973 p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
1974 break;
1975 case BWN_WME_BESTEFFORT:
1976 p->wmep_txopLimit = 0;
1977 p->wmep_aifsn = 3;
1978 /* XXX FIXME: log2(cwmin) */
1979 p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
1980 p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
1981 break;
1982 case BWN_WME_BACKGROUND:
1983 p->wmep_txopLimit = 0;
1984 p->wmep_aifsn = 7;
1985 /* XXX FIXME: log2(cwmin) */
1986 p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
1987 p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
1988 break;
1989 default:
1990 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
1991 }
1992 }
1993}
1994
1995static int
1996bwn_core_init(struct bwn_mac *mac)
1997{
1998 struct bwn_softc *sc = mac->mac_sc;
1999 uint64_t hf;
2000 int error;
2001
2002 KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
2003 ("%s:%d: fail", __func__, __LINE__));
2004
2005 siba_powerup(sc->sc_dev, 0);
2006 if (!siba_dev_isup(sc->sc_dev))
2007 bwn_reset_core(mac, mac->mac_phy.gmode);
2008
2009 mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
2010 mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
2011 mac->mac_phy.hwpctl = (bwn_hwpctl) ? 1 : 0;
2012 BWN_GETTIME(mac->mac_phy.nexttime);
2013 mac->mac_phy.txerrors = BWN_TXERROR_MAX;
2014 bzero(&mac->mac_stats, sizeof(mac->mac_stats));
2015 mac->mac_stats.link_noise = -95;
2016 mac->mac_reason_intr = 0;
2017 bzero(mac->mac_reason, sizeof(mac->mac_reason));
2018 mac->mac_intr_mask = BWN_INTR_MASKTEMPLATE;
2019#ifdef BWN_DEBUG
2020 if (sc->sc_debug & BWN_DEBUG_XMIT)
2021 mac->mac_intr_mask &= ~BWN_INTR_PHY_TXERR;
2022#endif
2023 mac->mac_suspended = 1;
2024 mac->mac_task_state = 0;
2025 memset(&mac->mac_noise, 0, sizeof(mac->mac_noise));
2026
2027 mac->mac_phy.init_pre(mac);
2028
2029 siba_pcicore_intr(sc->sc_dev);
2030
2031 siba_fix_imcfglobug(sc->sc_dev);
2032 bwn_bt_disable(mac);
2033 if (mac->mac_phy.prepare_hw) {
2034 error = mac->mac_phy.prepare_hw(mac);
2035 if (error)
2036 goto fail0;
2037 }
2038 error = bwn_chip_init(mac);
2039 if (error)
2040 goto fail0;
2041 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_COREREV,
2042 siba_get_revid(sc->sc_dev));
2043 hf = bwn_hf_read(mac);
2044 if (mac->mac_phy.type == BWN_PHYTYPE_G) {
2045 hf |= BWN_HF_GPHY_SYM_WORKAROUND;
2046 if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
2047 hf |= BWN_HF_PAGAINBOOST_OFDM_ON;
2048 if (mac->mac_phy.rev == 1)
2049 hf |= BWN_HF_GPHY_DC_CANCELFILTER;
2050 }
2051 if (mac->mac_phy.rf_ver == 0x2050) {
2052 if (mac->mac_phy.rf_rev < 6)
2053 hf |= BWN_HF_FORCE_VCO_RECALC;
2054 if (mac->mac_phy.rf_rev == 6)
2055 hf |= BWN_HF_4318_TSSI;
2056 }
2057 if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW)
2058 hf |= BWN_HF_SLOWCLOCK_REQ_OFF;
2059 if ((siba_get_type(sc->sc_dev) == SIBA_TYPE_PCI) &&
2060 (siba_get_pcicore_revid(sc->sc_dev) <= 10))
2061 hf |= BWN_HF_PCI_SLOWCLOCK_WORKAROUND;
2062 hf &= ~BWN_HF_SKIP_CFP_UPDATE;
2063 bwn_hf_write(mac, hf);
2064
2065 bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
2066 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SHORT_RETRY_FALLBACK, 3);
2067 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_LONG_RETRY_FALLBACK, 2);
2068 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_MAXTIME, 1);
2069
2070 bwn_rate_init(mac);
2071 bwn_set_phytxctl(mac);
2072
2073 bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MIN,
2074 (mac->mac_phy.type == BWN_PHYTYPE_B) ? 0x1f : 0xf);
2075 bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MAX, 0x3ff);
2076
2077 if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
2078 bwn_pio_init(mac);
2079 else
2080 bwn_dma_init(mac);
2081 bwn_wme_init(mac);
2082 bwn_spu_setdelay(mac, 1);
2083 bwn_bt_enable(mac);
2084
2085 siba_powerup(sc->sc_dev,
2086 !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW));
2087 bwn_set_macaddr(mac);
2088 bwn_crypt_init(mac);
2089
2090 /* XXX LED initializatin */
2091
2092 mac->mac_status = BWN_MAC_STATUS_INITED;
2093
2094 return (error);
2095
2096fail0:
2097 siba_powerdown(sc->sc_dev);
2098 KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
2099 ("%s:%d: fail", __func__, __LINE__));
2100 return (error);
2101}
2102
2103static void
2104bwn_core_start(struct bwn_mac *mac)
2105{
2106 struct bwn_softc *sc = mac->mac_sc;
2107 uint32_t tmp;
2108
2109 KASSERT(mac->mac_status == BWN_MAC_STATUS_INITED,
2110 ("%s:%d: fail", __func__, __LINE__));
2111
2112 if (siba_get_revid(sc->sc_dev) < 5)
2113 return;
2114
2115 while (1) {
2116 tmp = BWN_READ_4(mac, BWN_XMITSTAT_0);
2117 if (!(tmp & 0x00000001))
2118 break;
2119 tmp = BWN_READ_4(mac, BWN_XMITSTAT_1);
2120 }
2121
2122 bwn_mac_enable(mac);
2123 BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
2124 callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
2125
2126 mac->mac_status = BWN_MAC_STATUS_STARTED;
2127}
2128
2129static void
2130bwn_core_exit(struct bwn_mac *mac)
2131{
2132 struct bwn_softc *sc = mac->mac_sc;
2133 uint32_t macctl;
2134
2135 BWN_ASSERT_LOCKED(mac->mac_sc);
2136
2137 KASSERT(mac->mac_status <= BWN_MAC_STATUS_INITED,
2138 ("%s:%d: fail", __func__, __LINE__));
2139
2140 if (mac->mac_status != BWN_MAC_STATUS_INITED)
2141 return;
2142 mac->mac_status = BWN_MAC_STATUS_UNINIT;
2143
2144 macctl = BWN_READ_4(mac, BWN_MACCTL);
2145 macctl &= ~BWN_MACCTL_MCODE_RUN;
2146 macctl |= BWN_MACCTL_MCODE_JMP0;
2147 BWN_WRITE_4(mac, BWN_MACCTL, macctl);
2148
2149 bwn_dma_stop(mac);
2150 bwn_pio_stop(mac);
2151 bwn_chip_exit(mac);
2152 mac->mac_phy.switch_analog(mac, 0);
2153 siba_dev_down(sc->sc_dev, 0);
2154 siba_powerdown(sc->sc_dev);
2155}
2156
2157static void
2158bwn_bt_disable(struct bwn_mac *mac)
2159{
2160 struct bwn_softc *sc = mac->mac_sc;
2161
2162 (void)sc;
2163 /* XXX do nothing yet */
2164}
2165
2166static int
2167bwn_chip_init(struct bwn_mac *mac)
2168{
2169 struct bwn_softc *sc = mac->mac_sc;
2170 struct bwn_phy *phy = &mac->mac_phy;
2171 uint32_t macctl;
2172 int error;
2173
2174 macctl = BWN_MACCTL_IHR_ON | BWN_MACCTL_SHM_ON | BWN_MACCTL_STA;
2175 if (phy->gmode)
2176 macctl |= BWN_MACCTL_GMODE;
2177 BWN_WRITE_4(mac, BWN_MACCTL, macctl);
2178
2179 error = bwn_fw_fillinfo(mac);
2180 if (error)
2181 return (error);
2182 error = bwn_fw_loaducode(mac);
2183 if (error)
2184 return (error);
2185
2186 error = bwn_gpio_init(mac);
2187 if (error)
2188 return (error);
2189
2190 error = bwn_fw_loadinitvals(mac);
2191 if (error) {
2192 siba_gpio_set(sc->sc_dev, 0);
2193 return (error);
2194 }
2195 phy->switch_analog(mac, 1);
2196 error = bwn_phy_init(mac);
2197 if (error) {
2198 siba_gpio_set(sc->sc_dev, 0);
2199 return (error);
2200 }
2201 if (phy->set_im)
2202 phy->set_im(mac, BWN_IMMODE_NONE);
2203 if (phy->set_antenna)
2204 phy->set_antenna(mac, BWN_ANT_DEFAULT);
2205 bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
2206
2207 if (phy->type == BWN_PHYTYPE_B)
2208 BWN_WRITE_2(mac, 0x005e, BWN_READ_2(mac, 0x005e) | 0x0004);
2209 BWN_WRITE_4(mac, 0x0100, 0x01000000);
2210 if (siba_get_revid(sc->sc_dev) < 5)
2211 BWN_WRITE_4(mac, 0x010c, 0x01000000);
2212
2213 BWN_WRITE_4(mac, BWN_MACCTL,
2214 BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_STA);
2215 BWN_WRITE_4(mac, BWN_MACCTL,
2216 BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_STA);
2217 bwn_shm_write_2(mac, BWN_SHARED, 0x0074, 0x0000);
2218
2219 bwn_set_opmode(mac);
2220 if (siba_get_revid(sc->sc_dev) < 3) {
2221 BWN_WRITE_2(mac, 0x060e, 0x0000);
2222 BWN_WRITE_2(mac, 0x0610, 0x8000);
2223 BWN_WRITE_2(mac, 0x0604, 0x0000);
2224 BWN_WRITE_2(mac, 0x0606, 0x0200);
2225 } else {
2226 BWN_WRITE_4(mac, 0x0188, 0x80000000);
2227 BWN_WRITE_4(mac, 0x018c, 0x02000000);
2228 }
2229 BWN_WRITE_4(mac, BWN_INTR_REASON, 0x00004000);
2230 BWN_WRITE_4(mac, BWN_DMA0_INTR_MASK, 0x0001dc00);
2231 BWN_WRITE_4(mac, BWN_DMA1_INTR_MASK, 0x0000dc00);
2232 BWN_WRITE_4(mac, BWN_DMA2_INTR_MASK, 0x0000dc00);
2233 BWN_WRITE_4(mac, BWN_DMA3_INTR_MASK, 0x0001dc00);
2234 BWN_WRITE_4(mac, BWN_DMA4_INTR_MASK, 0x0000dc00);
2235 BWN_WRITE_4(mac, BWN_DMA5_INTR_MASK, 0x0000dc00);
2236
2237 bwn_mac_phy_clock_set(mac, true);
2238
2239 /* SIBA powerup */
2240 /* XXX TODO: BCMA powerup */
2241 BWN_WRITE_2(mac, BWN_POWERUP_DELAY, siba_get_cc_powerdelay(sc->sc_dev));
2242 return (error);
2243}
2244
2245/* read hostflags */
2246uint64_t
2247bwn_hf_read(struct bwn_mac *mac)
2248{
2249 uint64_t ret;
2250
2251 ret = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFHI);
2252 ret <<= 16;
2253 ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFMI);
2254 ret <<= 16;
2255 ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO);
2256 return (ret);
2257}
2258
2259void
2260bwn_hf_write(struct bwn_mac *mac, uint64_t value)
2261{
2262
2263 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFLO,
2264 (value & 0x00000000ffffull));
2265 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFMI,
2266 (value & 0x0000ffff0000ull) >> 16);
2267 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFHI,
2268 (value & 0xffff00000000ULL) >> 32);
2269}
2270
2271static void
2272bwn_set_txretry(struct bwn_mac *mac, int s, int l)
2273{
2274
2275 bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_SHORT_RETRY, MIN(s, 0xf));
2276 bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_LONG_RETRY, MIN(l, 0xf));
2277}
2278
2279static void
2280bwn_rate_init(struct bwn_mac *mac)
2281{
2282
2283 switch (mac->mac_phy.type) {
2284 case BWN_PHYTYPE_A:
2285 case BWN_PHYTYPE_G:
2286 case BWN_PHYTYPE_LP:
2287 case BWN_PHYTYPE_N:
2288 bwn_rate_write(mac, BWN_OFDM_RATE_6MB, 1);
2289 bwn_rate_write(mac, BWN_OFDM_RATE_12MB, 1);
2290 bwn_rate_write(mac, BWN_OFDM_RATE_18MB, 1);
2291 bwn_rate_write(mac, BWN_OFDM_RATE_24MB, 1);
2292 bwn_rate_write(mac, BWN_OFDM_RATE_36MB, 1);
2293 bwn_rate_write(mac, BWN_OFDM_RATE_48MB, 1);
2294 bwn_rate_write(mac, BWN_OFDM_RATE_54MB, 1);
2295 if (mac->mac_phy.type == BWN_PHYTYPE_A)
2296 break;
2297 /* FALLTHROUGH */
2298 case BWN_PHYTYPE_B:
2299 bwn_rate_write(mac, BWN_CCK_RATE_1MB, 0);
2300 bwn_rate_write(mac, BWN_CCK_RATE_2MB, 0);
2301 bwn_rate_write(mac, BWN_CCK_RATE_5MB, 0);
2302 bwn_rate_write(mac, BWN_CCK_RATE_11MB, 0);
2303 break;
2304 default:
2305 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
2306 }
2307}
2308
2309static void
2310bwn_rate_write(struct bwn_mac *mac, uint16_t rate, int ofdm)
2311{
2312 uint16_t offset;
2313
2314 if (ofdm) {
2315 offset = 0x480;
2316 offset += (bwn_plcp_getofdm(rate) & 0x000f) * 2;
2317 } else {
2318 offset = 0x4c0;
2319 offset += (bwn_plcp_getcck(rate) & 0x000f) * 2;
2320 }
2321 bwn_shm_write_2(mac, BWN_SHARED, offset + 0x20,
2322 bwn_shm_read_2(mac, BWN_SHARED, offset));
2323}
2324
2325static uint8_t
2326bwn_plcp_getcck(const uint8_t bitrate)
2327{
2328
2329 switch (bitrate) {
2330 case BWN_CCK_RATE_1MB:
2331 return (0x0a);
2332 case BWN_CCK_RATE_2MB:
2333 return (0x14);
2334 case BWN_CCK_RATE_5MB:
2335 return (0x37);
2336 case BWN_CCK_RATE_11MB:
2337 return (0x6e);
2338 }
2339 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
2340 return (0);
2341}
2342
2343static uint8_t
2344bwn_plcp_getofdm(const uint8_t bitrate)
2345{
2346
2347 switch (bitrate) {
2348 case BWN_OFDM_RATE_6MB:
2349 return (0xb);
2350 case BWN_OFDM_RATE_9MB:
2351 return (0xf);
2352 case BWN_OFDM_RATE_12MB:
2353 return (0xa);
2354 case BWN_OFDM_RATE_18MB:
2355 return (0xe);
2356 case BWN_OFDM_RATE_24MB:
2357 return (0x9);
2358 case BWN_OFDM_RATE_36MB:
2359 return (0xd);
2360 case BWN_OFDM_RATE_48MB:
2361 return (0x8);
2362 case BWN_OFDM_RATE_54MB:
2363 return (0xc);
2364 }
2365 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
2366 return (0);
2367}
2368
2369static void
2370bwn_set_phytxctl(struct bwn_mac *mac)
2371{
2372 uint16_t ctl;
2373
2374 ctl = (BWN_TX_PHY_ENC_CCK | BWN_TX_PHY_ANT01AUTO |
2375 BWN_TX_PHY_TXPWR);
2376 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_BEACON_PHYCTL, ctl);
2377 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, ctl);
2378 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, ctl);
2379}
2380
2381static void
2382bwn_pio_init(struct bwn_mac *mac)
2383{
2384 struct bwn_pio *pio = &mac->mac_method.pio;
2385
2386 BWN_WRITE_4(mac, BWN_MACCTL, BWN_READ_4(mac, BWN_MACCTL)
2387 & ~BWN_MACCTL_BIGENDIAN);
2388 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RX_PADOFFSET, 0);
2389
2390 bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BK], 0);
2391 bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BE], 1);
2392 bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VI], 2);
2393 bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VO], 3);
2394 bwn_pio_set_txqueue(mac, &pio->mcast, 4);
2395 bwn_pio_setupqueue_rx(mac, &pio->rx, 0);
2396}
2397
2398static void
2399bwn_pio_set_txqueue(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
2400 int index)
2401{
2402 struct bwn_pio_txpkt *tp;
2403 struct bwn_softc *sc = mac->mac_sc;
2404 unsigned int i;
2405
2406 tq->tq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_TXQOFFSET(mac);
2407 tq->tq_index = index;
2408
2409 tq->tq_free = BWN_PIO_MAX_TXPACKETS;
2410 if (siba_get_revid(sc->sc_dev) >= 8)
2411 tq->tq_size = 1920;
2412 else {
2413 tq->tq_size = bwn_pio_read_2(mac, tq, BWN_PIO_TXQBUFSIZE);
2414 tq->tq_size -= 80;
2415 }
2416
2417 TAILQ_INIT(&tq->tq_pktlist);
2418 for (i = 0; i < N(tq->tq_pkts); i++) {
2419 tp = &(tq->tq_pkts[i]);
2420 tp->tp_index = i;
2421 tp->tp_queue = tq;
2422 TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
2423 }
2424}
2425
2426static uint16_t
2427bwn_pio_idx2base(struct bwn_mac *mac, int index)
2428{
2429 struct bwn_softc *sc = mac->mac_sc;
2430 static const uint16_t bases[] = {
2431 BWN_PIO_BASE0,
2432 BWN_PIO_BASE1,
2433 BWN_PIO_BASE2,
2434 BWN_PIO_BASE3,
2435 BWN_PIO_BASE4,
2436 BWN_PIO_BASE5,
2437 BWN_PIO_BASE6,
2438 BWN_PIO_BASE7,
2439 };
2440 static const uint16_t bases_rev11[] = {
2441 BWN_PIO11_BASE0,
2442 BWN_PIO11_BASE1,
2443 BWN_PIO11_BASE2,
2444 BWN_PIO11_BASE3,
2445 BWN_PIO11_BASE4,
2446 BWN_PIO11_BASE5,
2447 };
2448
2449 if (siba_get_revid(sc->sc_dev) >= 11) {
2450 if (index >= N(bases_rev11))
2451 device_printf(sc->sc_dev, "%s: warning\n", __func__);
2452 return (bases_rev11[index]);
2453 }
2454 if (index >= N(bases))
2455 device_printf(sc->sc_dev, "%s: warning\n", __func__);
2456 return (bases[index]);
2457}
2458
2459static void
2460bwn_pio_setupqueue_rx(struct bwn_mac *mac, struct bwn_pio_rxqueue *prq,
2461 int index)
2462{
2463 struct bwn_softc *sc = mac->mac_sc;
2464
2465 prq->prq_mac = mac;
2466 prq->prq_rev = siba_get_revid(sc->sc_dev);
2467 prq->prq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_RXQOFFSET(mac);
2468 bwn_dma_rxdirectfifo(mac, index, 1);
2469}
2470
2471static void
2472bwn_destroy_pioqueue_tx(struct bwn_pio_txqueue *tq)
2473{
2474 if (tq == NULL)
2475 return;
2476 bwn_pio_cancel_tx_packets(tq);
2477}
2478
2479static void
2480bwn_destroy_queue_tx(struct bwn_pio_txqueue *pio)
2481{
2482
2483 bwn_destroy_pioqueue_tx(pio);
2484}
2485
2486static uint16_t
2487bwn_pio_read_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
2488 uint16_t offset)
2489{
2490
2491 return (BWN_READ_2(mac, tq->tq_base + offset));
2492}
2493
2494static void
2495bwn_dma_rxdirectfifo(struct bwn_mac *mac, int idx, uint8_t enable)
2496{
2497 uint32_t ctl;
2498 int type;
2499 uint16_t base;
2500
2501 type = bwn_dma_mask2type(bwn_dma_mask(mac));
2502 base = bwn_dma_base(type, idx);
2503 if (type == BWN_DMA_64BIT) {
2504 ctl = BWN_READ_4(mac, base + BWN_DMA64_RXCTL);
2505 ctl &= ~BWN_DMA64_RXDIRECTFIFO;
2506 if (enable)
2507 ctl |= BWN_DMA64_RXDIRECTFIFO;
2508 BWN_WRITE_4(mac, base + BWN_DMA64_RXCTL, ctl);
2509 } else {
2510 ctl = BWN_READ_4(mac, base + BWN_DMA32_RXCTL);
2511 ctl &= ~BWN_DMA32_RXDIRECTFIFO;
2512 if (enable)
2513 ctl |= BWN_DMA32_RXDIRECTFIFO;
2514 BWN_WRITE_4(mac, base + BWN_DMA32_RXCTL, ctl);
2515 }
2516}
2517
2518static uint64_t
2519bwn_dma_mask(struct bwn_mac *mac)
2520{
2521 uint32_t tmp;
2522 uint16_t base;
2523
2524 tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
2525 if (tmp & SIBA_TGSHIGH_DMA64)
2526 return (BWN_DMA_BIT_MASK(64));
2527 base = bwn_dma_base(0, 0);
2528 BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
2529 tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
2530 if (tmp & BWN_DMA32_TXADDREXT_MASK)
2531 return (BWN_DMA_BIT_MASK(32));
2532
2533 return (BWN_DMA_BIT_MASK(30));
2534}
2535
2536static int
2537bwn_dma_mask2type(uint64_t dmamask)
2538{
2539
2540 if (dmamask == BWN_DMA_BIT_MASK(30))
2541 return (BWN_DMA_30BIT);
2542 if (dmamask == BWN_DMA_BIT_MASK(32))
2543 return (BWN_DMA_32BIT);
2544 if (dmamask == BWN_DMA_BIT_MASK(64))
2545 return (BWN_DMA_64BIT);
2546 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
2547 return (BWN_DMA_30BIT);
2548}
2549
2550static void
2551bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *tq)
2552{
2553 struct bwn_pio_txpkt *tp;
2554 unsigned int i;
2555
2556 for (i = 0; i < N(tq->tq_pkts); i++) {
2557 tp = &(tq->tq_pkts[i]);
2558 if (tp->tp_m) {
2559 m_freem(tp->tp_m);
2560 tp->tp_m = NULL;
2561 }
2562 }
2563}
2564
2565static uint16_t
2566bwn_dma_base(int type, int controller_idx)
2567{
2568 static const uint16_t map64[] = {
2569 BWN_DMA64_BASE0,
2570 BWN_DMA64_BASE1,
2571 BWN_DMA64_BASE2,
2572 BWN_DMA64_BASE3,
2573 BWN_DMA64_BASE4,
2574 BWN_DMA64_BASE5,
2575 };
2576 static const uint16_t map32[] = {
2577 BWN_DMA32_BASE0,
2578 BWN_DMA32_BASE1,
2579 BWN_DMA32_BASE2,
2580 BWN_DMA32_BASE3,
2581 BWN_DMA32_BASE4,
2582 BWN_DMA32_BASE5,
2583 };
2584
2585 if (type == BWN_DMA_64BIT) {
2586 KASSERT(controller_idx >= 0 && controller_idx < N(map64),
2587 ("%s:%d: fail", __func__, __LINE__));
2588 return (map64[controller_idx]);
2589 }
2590 KASSERT(controller_idx >= 0 && controller_idx < N(map32),
2591 ("%s:%d: fail", __func__, __LINE__));
2592 return (map32[controller_idx]);
2593}
2594
2595static void
2596bwn_dma_init(struct bwn_mac *mac)
2597{
2598 struct bwn_dma *dma = &mac->mac_method.dma;
2599
2600 /* setup TX DMA channels. */
2601 bwn_dma_setup(dma->wme[WME_AC_BK]);
2602 bwn_dma_setup(dma->wme[WME_AC_BE]);
2603 bwn_dma_setup(dma->wme[WME_AC_VI]);
2604 bwn_dma_setup(dma->wme[WME_AC_VO]);
2605 bwn_dma_setup(dma->mcast);
2606 /* setup RX DMA channel. */
2607 bwn_dma_setup(dma->rx);
2608}
2609
2610static struct bwn_dma_ring *
2611bwn_dma_ringsetup(struct bwn_mac *mac, int controller_index,
2612 int for_tx, int type)
2613{
2614 struct bwn_dma *dma = &mac->mac_method.dma;
2615 struct bwn_dma_ring *dr;
2616 struct bwn_dmadesc_generic *desc;
2617 struct bwn_dmadesc_meta *mt;
2618 struct bwn_softc *sc = mac->mac_sc;
2619 int error, i;
2620
2621 dr = malloc(sizeof(*dr), M_DEVBUF, M_NOWAIT | M_ZERO);
2622 if (dr == NULL)
2623 goto out;
2624 dr->dr_numslots = BWN_RXRING_SLOTS;
2625 if (for_tx)
2626 dr->dr_numslots = BWN_TXRING_SLOTS;
2627
2628 dr->dr_meta = malloc(dr->dr_numslots * sizeof(struct bwn_dmadesc_meta),
2629 M_DEVBUF, M_NOWAIT | M_ZERO);
2630 if (dr->dr_meta == NULL)
2631 goto fail0;
2632
2633 dr->dr_type = type;
2634 dr->dr_mac = mac;
2635 dr->dr_base = bwn_dma_base(type, controller_index);
2636 dr->dr_index = controller_index;
2637 if (type == BWN_DMA_64BIT) {
2638 dr->getdesc = bwn_dma_64_getdesc;
2639 dr->setdesc = bwn_dma_64_setdesc;
2640 dr->start_transfer = bwn_dma_64_start_transfer;
2641 dr->suspend = bwn_dma_64_suspend;
2642 dr->resume = bwn_dma_64_resume;
2643 dr->get_curslot = bwn_dma_64_get_curslot;
2644 dr->set_curslot = bwn_dma_64_set_curslot;
2645 } else {
2646 dr->getdesc = bwn_dma_32_getdesc;
2647 dr->setdesc = bwn_dma_32_setdesc;
2648 dr->start_transfer = bwn_dma_32_start_transfer;
2649 dr->suspend = bwn_dma_32_suspend;
2650 dr->resume = bwn_dma_32_resume;
2651 dr->get_curslot = bwn_dma_32_get_curslot;
2652 dr->set_curslot = bwn_dma_32_set_curslot;
2653 }
2654 if (for_tx) {
2655 dr->dr_tx = 1;
2656 dr->dr_curslot = -1;
2657 } else {
2658 if (dr->dr_index == 0) {
32
33/*
34 * The Broadcom Wireless LAN controller driver.
35 */
36
37#include "opt_bwn.h"
38#include "opt_wlan.h"
39
40#include <sys/param.h>
41#include <sys/systm.h>
42#include <sys/kernel.h>
43#include <sys/malloc.h>
44#include <sys/module.h>
45#include <sys/endian.h>
46#include <sys/errno.h>
47#include <sys/firmware.h>
48#include <sys/lock.h>
49#include <sys/mutex.h>
50#include <machine/bus.h>
51#include <machine/resource.h>
52#include <sys/bus.h>
53#include <sys/rman.h>
54#include <sys/socket.h>
55#include <sys/sockio.h>
56
57#include <net/ethernet.h>
58#include <net/if.h>
59#include <net/if_var.h>
60#include <net/if_arp.h>
61#include <net/if_dl.h>
62#include <net/if_llc.h>
63#include <net/if_media.h>
64#include <net/if_types.h>
65
66#include <dev/pci/pcivar.h>
67#include <dev/pci/pcireg.h>
68#include <dev/siba/siba_ids.h>
69#include <dev/siba/sibareg.h>
70#include <dev/siba/sibavar.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/bwn/if_bwnreg.h>
79#include <dev/bwn/if_bwnvar.h>
80
81#include <dev/bwn/if_bwn_debug.h>
82#include <dev/bwn/if_bwn_misc.h>
83#include <dev/bwn/if_bwn_util.h>
84#include <dev/bwn/if_bwn_phy_common.h>
85#include <dev/bwn/if_bwn_phy_g.h>
86#include <dev/bwn/if_bwn_phy_lp.h>
87#include <dev/bwn/if_bwn_phy_n.h>
88
89static SYSCTL_NODE(_hw, OID_AUTO, bwn, CTLFLAG_RD, 0,
90 "Broadcom driver parameters");
91
92/*
93 * Tunable & sysctl variables.
94 */
95
96#ifdef BWN_DEBUG
97static int bwn_debug = 0;
98SYSCTL_INT(_hw_bwn, OID_AUTO, debug, CTLFLAG_RWTUN, &bwn_debug, 0,
99 "Broadcom debugging printfs");
100#endif
101
102static int bwn_bfp = 0; /* use "Bad Frames Preemption" */
103SYSCTL_INT(_hw_bwn, OID_AUTO, bfp, CTLFLAG_RW, &bwn_bfp, 0,
104 "uses Bad Frames Preemption");
105static int bwn_bluetooth = 1;
106SYSCTL_INT(_hw_bwn, OID_AUTO, bluetooth, CTLFLAG_RW, &bwn_bluetooth, 0,
107 "turns on Bluetooth Coexistence");
108static int bwn_hwpctl = 0;
109SYSCTL_INT(_hw_bwn, OID_AUTO, hwpctl, CTLFLAG_RW, &bwn_hwpctl, 0,
110 "uses H/W power control");
111static int bwn_msi_disable = 0; /* MSI disabled */
112TUNABLE_INT("hw.bwn.msi_disable", &bwn_msi_disable);
113static int bwn_usedma = 1;
114SYSCTL_INT(_hw_bwn, OID_AUTO, usedma, CTLFLAG_RD, &bwn_usedma, 0,
115 "uses DMA");
116TUNABLE_INT("hw.bwn.usedma", &bwn_usedma);
117static int bwn_wme = 1;
118SYSCTL_INT(_hw_bwn, OID_AUTO, wme, CTLFLAG_RW, &bwn_wme, 0,
119 "uses WME support");
120
121static void bwn_attach_pre(struct bwn_softc *);
122static int bwn_attach_post(struct bwn_softc *);
123static void bwn_sprom_bugfixes(device_t);
124static int bwn_init(struct bwn_softc *);
125static void bwn_parent(struct ieee80211com *);
126static void bwn_start(struct bwn_softc *);
127static int bwn_transmit(struct ieee80211com *, struct mbuf *);
128static int bwn_attach_core(struct bwn_mac *);
129static int bwn_phy_getinfo(struct bwn_mac *, int);
130static int bwn_chiptest(struct bwn_mac *);
131static int bwn_setup_channels(struct bwn_mac *, int, int);
132static void bwn_shm_ctlword(struct bwn_mac *, uint16_t,
133 uint16_t);
134static void bwn_addchannels(struct ieee80211_channel [], int, int *,
135 const struct bwn_channelinfo *, const uint8_t []);
136static int bwn_raw_xmit(struct ieee80211_node *, struct mbuf *,
137 const struct ieee80211_bpf_params *);
138static void bwn_updateslot(struct ieee80211com *);
139static void bwn_update_promisc(struct ieee80211com *);
140static void bwn_wme_init(struct bwn_mac *);
141static int bwn_wme_update(struct ieee80211com *);
142static void bwn_wme_clear(struct bwn_softc *);
143static void bwn_wme_load(struct bwn_mac *);
144static void bwn_wme_loadparams(struct bwn_mac *,
145 const struct wmeParams *, uint16_t);
146static void bwn_scan_start(struct ieee80211com *);
147static void bwn_scan_end(struct ieee80211com *);
148static void bwn_set_channel(struct ieee80211com *);
149static struct ieee80211vap *bwn_vap_create(struct ieee80211com *,
150 const char [IFNAMSIZ], int, enum ieee80211_opmode, int,
151 const uint8_t [IEEE80211_ADDR_LEN],
152 const uint8_t [IEEE80211_ADDR_LEN]);
153static void bwn_vap_delete(struct ieee80211vap *);
154static void bwn_stop(struct bwn_softc *);
155static int bwn_core_init(struct bwn_mac *);
156static void bwn_core_start(struct bwn_mac *);
157static void bwn_core_exit(struct bwn_mac *);
158static void bwn_bt_disable(struct bwn_mac *);
159static int bwn_chip_init(struct bwn_mac *);
160static void bwn_set_txretry(struct bwn_mac *, int, int);
161static void bwn_rate_init(struct bwn_mac *);
162static void bwn_set_phytxctl(struct bwn_mac *);
163static void bwn_spu_setdelay(struct bwn_mac *, int);
164static void bwn_bt_enable(struct bwn_mac *);
165static void bwn_set_macaddr(struct bwn_mac *);
166static void bwn_crypt_init(struct bwn_mac *);
167static void bwn_chip_exit(struct bwn_mac *);
168static int bwn_fw_fillinfo(struct bwn_mac *);
169static int bwn_fw_loaducode(struct bwn_mac *);
170static int bwn_gpio_init(struct bwn_mac *);
171static int bwn_fw_loadinitvals(struct bwn_mac *);
172static int bwn_phy_init(struct bwn_mac *);
173static void bwn_set_txantenna(struct bwn_mac *, int);
174static void bwn_set_opmode(struct bwn_mac *);
175static void bwn_rate_write(struct bwn_mac *, uint16_t, int);
176static uint8_t bwn_plcp_getcck(const uint8_t);
177static uint8_t bwn_plcp_getofdm(const uint8_t);
178static void bwn_pio_init(struct bwn_mac *);
179static uint16_t bwn_pio_idx2base(struct bwn_mac *, int);
180static void bwn_pio_set_txqueue(struct bwn_mac *, struct bwn_pio_txqueue *,
181 int);
182static void bwn_pio_setupqueue_rx(struct bwn_mac *,
183 struct bwn_pio_rxqueue *, int);
184static void bwn_destroy_queue_tx(struct bwn_pio_txqueue *);
185static uint16_t bwn_pio_read_2(struct bwn_mac *, struct bwn_pio_txqueue *,
186 uint16_t);
187static void bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *);
188static int bwn_pio_rx(struct bwn_pio_rxqueue *);
189static uint8_t bwn_pio_rxeof(struct bwn_pio_rxqueue *);
190static void bwn_pio_handle_txeof(struct bwn_mac *,
191 const struct bwn_txstatus *);
192static uint16_t bwn_pio_rx_read_2(struct bwn_pio_rxqueue *, uint16_t);
193static uint32_t bwn_pio_rx_read_4(struct bwn_pio_rxqueue *, uint16_t);
194static void bwn_pio_rx_write_2(struct bwn_pio_rxqueue *, uint16_t,
195 uint16_t);
196static void bwn_pio_rx_write_4(struct bwn_pio_rxqueue *, uint16_t,
197 uint32_t);
198static int bwn_pio_tx_start(struct bwn_mac *, struct ieee80211_node *,
199 struct mbuf *);
200static struct bwn_pio_txqueue *bwn_pio_select(struct bwn_mac *, uint8_t);
201static uint32_t bwn_pio_write_multi_4(struct bwn_mac *,
202 struct bwn_pio_txqueue *, uint32_t, const void *, int);
203static void bwn_pio_write_4(struct bwn_mac *, struct bwn_pio_txqueue *,
204 uint16_t, uint32_t);
205static uint16_t bwn_pio_write_multi_2(struct bwn_mac *,
206 struct bwn_pio_txqueue *, uint16_t, const void *, int);
207static uint16_t bwn_pio_write_mbuf_2(struct bwn_mac *,
208 struct bwn_pio_txqueue *, uint16_t, struct mbuf *);
209static struct bwn_pio_txqueue *bwn_pio_parse_cookie(struct bwn_mac *,
210 uint16_t, struct bwn_pio_txpkt **);
211static void bwn_dma_init(struct bwn_mac *);
212static void bwn_dma_rxdirectfifo(struct bwn_mac *, int, uint8_t);
213static int bwn_dma_mask2type(uint64_t);
214static uint64_t bwn_dma_mask(struct bwn_mac *);
215static uint16_t bwn_dma_base(int, int);
216static void bwn_dma_ringfree(struct bwn_dma_ring **);
217static void bwn_dma_32_getdesc(struct bwn_dma_ring *,
218 int, struct bwn_dmadesc_generic **,
219 struct bwn_dmadesc_meta **);
220static void bwn_dma_32_setdesc(struct bwn_dma_ring *,
221 struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int,
222 int, int);
223static void bwn_dma_32_start_transfer(struct bwn_dma_ring *, int);
224static void bwn_dma_32_suspend(struct bwn_dma_ring *);
225static void bwn_dma_32_resume(struct bwn_dma_ring *);
226static int bwn_dma_32_get_curslot(struct bwn_dma_ring *);
227static void bwn_dma_32_set_curslot(struct bwn_dma_ring *, int);
228static void bwn_dma_64_getdesc(struct bwn_dma_ring *,
229 int, struct bwn_dmadesc_generic **,
230 struct bwn_dmadesc_meta **);
231static void bwn_dma_64_setdesc(struct bwn_dma_ring *,
232 struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int,
233 int, int);
234static void bwn_dma_64_start_transfer(struct bwn_dma_ring *, int);
235static void bwn_dma_64_suspend(struct bwn_dma_ring *);
236static void bwn_dma_64_resume(struct bwn_dma_ring *);
237static int bwn_dma_64_get_curslot(struct bwn_dma_ring *);
238static void bwn_dma_64_set_curslot(struct bwn_dma_ring *, int);
239static int bwn_dma_allocringmemory(struct bwn_dma_ring *);
240static void bwn_dma_setup(struct bwn_dma_ring *);
241static void bwn_dma_free_ringmemory(struct bwn_dma_ring *);
242static void bwn_dma_cleanup(struct bwn_dma_ring *);
243static void bwn_dma_free_descbufs(struct bwn_dma_ring *);
244static int bwn_dma_tx_reset(struct bwn_mac *, uint16_t, int);
245static void bwn_dma_rx(struct bwn_dma_ring *);
246static int bwn_dma_rx_reset(struct bwn_mac *, uint16_t, int);
247static void bwn_dma_free_descbuf(struct bwn_dma_ring *,
248 struct bwn_dmadesc_meta *);
249static void bwn_dma_set_redzone(struct bwn_dma_ring *, struct mbuf *);
250static int bwn_dma_gettype(struct bwn_mac *);
251static void bwn_dma_ring_addr(void *, bus_dma_segment_t *, int, int);
252static int bwn_dma_freeslot(struct bwn_dma_ring *);
253static int bwn_dma_nextslot(struct bwn_dma_ring *, int);
254static void bwn_dma_rxeof(struct bwn_dma_ring *, int *);
255static int bwn_dma_newbuf(struct bwn_dma_ring *,
256 struct bwn_dmadesc_generic *, struct bwn_dmadesc_meta *,
257 int);
258static void bwn_dma_buf_addr(void *, bus_dma_segment_t *, int,
259 bus_size_t, int);
260static uint8_t bwn_dma_check_redzone(struct bwn_dma_ring *, struct mbuf *);
261static void bwn_dma_handle_txeof(struct bwn_mac *,
262 const struct bwn_txstatus *);
263static int bwn_dma_tx_start(struct bwn_mac *, struct ieee80211_node *,
264 struct mbuf *);
265static int bwn_dma_getslot(struct bwn_dma_ring *);
266static struct bwn_dma_ring *bwn_dma_select(struct bwn_mac *,
267 uint8_t);
268static int bwn_dma_attach(struct bwn_mac *);
269static struct bwn_dma_ring *bwn_dma_ringsetup(struct bwn_mac *,
270 int, int, int);
271static struct bwn_dma_ring *bwn_dma_parse_cookie(struct bwn_mac *,
272 const struct bwn_txstatus *, uint16_t, int *);
273static void bwn_dma_free(struct bwn_mac *);
274static int bwn_fw_gets(struct bwn_mac *, enum bwn_fwtype);
275static int bwn_fw_get(struct bwn_mac *, enum bwn_fwtype,
276 const char *, struct bwn_fwfile *);
277static void bwn_release_firmware(struct bwn_mac *);
278static void bwn_do_release_fw(struct bwn_fwfile *);
279static uint16_t bwn_fwcaps_read(struct bwn_mac *);
280static int bwn_fwinitvals_write(struct bwn_mac *,
281 const struct bwn_fwinitvals *, size_t, size_t);
282static uint16_t bwn_ant2phy(int);
283static void bwn_mac_write_bssid(struct bwn_mac *);
284static void bwn_mac_setfilter(struct bwn_mac *, uint16_t,
285 const uint8_t *);
286static void bwn_key_dowrite(struct bwn_mac *, uint8_t, uint8_t,
287 const uint8_t *, size_t, const uint8_t *);
288static void bwn_key_macwrite(struct bwn_mac *, uint8_t,
289 const uint8_t *);
290static void bwn_key_write(struct bwn_mac *, uint8_t, uint8_t,
291 const uint8_t *);
292static void bwn_phy_exit(struct bwn_mac *);
293static void bwn_core_stop(struct bwn_mac *);
294static int bwn_switch_band(struct bwn_softc *,
295 struct ieee80211_channel *);
296static void bwn_phy_reset(struct bwn_mac *);
297static int bwn_newstate(struct ieee80211vap *, enum ieee80211_state, int);
298static void bwn_set_pretbtt(struct bwn_mac *);
299static int bwn_intr(void *);
300static void bwn_intrtask(void *, int);
301static void bwn_restart(struct bwn_mac *, const char *);
302static void bwn_intr_ucode_debug(struct bwn_mac *);
303static void bwn_intr_tbtt_indication(struct bwn_mac *);
304static void bwn_intr_atim_end(struct bwn_mac *);
305static void bwn_intr_beacon(struct bwn_mac *);
306static void bwn_intr_pmq(struct bwn_mac *);
307static void bwn_intr_noise(struct bwn_mac *);
308static void bwn_intr_txeof(struct bwn_mac *);
309static void bwn_hwreset(void *, int);
310static void bwn_handle_fwpanic(struct bwn_mac *);
311static void bwn_load_beacon0(struct bwn_mac *);
312static void bwn_load_beacon1(struct bwn_mac *);
313static uint32_t bwn_jssi_read(struct bwn_mac *);
314static void bwn_noise_gensample(struct bwn_mac *);
315static void bwn_handle_txeof(struct bwn_mac *,
316 const struct bwn_txstatus *);
317static void bwn_rxeof(struct bwn_mac *, struct mbuf *, const void *);
318static void bwn_phy_txpower_check(struct bwn_mac *, uint32_t);
319static int bwn_tx_start(struct bwn_softc *, struct ieee80211_node *,
320 struct mbuf *);
321static int bwn_tx_isfull(struct bwn_softc *, struct mbuf *);
322static int bwn_set_txhdr(struct bwn_mac *,
323 struct ieee80211_node *, struct mbuf *, struct bwn_txhdr *,
324 uint16_t);
325static void bwn_plcp_genhdr(struct bwn_plcp4 *, const uint16_t,
326 const uint8_t);
327static uint8_t bwn_antenna_sanitize(struct bwn_mac *, uint8_t);
328static uint8_t bwn_get_fbrate(uint8_t);
329static void bwn_txpwr(void *, int);
330static void bwn_tasks(void *);
331static void bwn_task_15s(struct bwn_mac *);
332static void bwn_task_30s(struct bwn_mac *);
333static void bwn_task_60s(struct bwn_mac *);
334static int bwn_plcp_get_ofdmrate(struct bwn_mac *, struct bwn_plcp6 *,
335 uint8_t);
336static int bwn_plcp_get_cckrate(struct bwn_mac *, struct bwn_plcp6 *);
337static void bwn_rx_radiotap(struct bwn_mac *, struct mbuf *,
338 const struct bwn_rxhdr4 *, struct bwn_plcp6 *, int,
339 int, int);
340static void bwn_tsf_read(struct bwn_mac *, uint64_t *);
341static void bwn_set_slot_time(struct bwn_mac *, uint16_t);
342static void bwn_watchdog(void *);
343static void bwn_dma_stop(struct bwn_mac *);
344static void bwn_pio_stop(struct bwn_mac *);
345static void bwn_dma_ringstop(struct bwn_dma_ring **);
346static void bwn_led_attach(struct bwn_mac *);
347static void bwn_led_newstate(struct bwn_mac *, enum ieee80211_state);
348static void bwn_led_event(struct bwn_mac *, int);
349static void bwn_led_blink_start(struct bwn_mac *, int, int);
350static void bwn_led_blink_next(void *);
351static void bwn_led_blink_end(void *);
352static void bwn_rfswitch(void *);
353static void bwn_rf_turnon(struct bwn_mac *);
354static void bwn_rf_turnoff(struct bwn_mac *);
355static void bwn_sysctl_node(struct bwn_softc *);
356
357static struct resource_spec bwn_res_spec_legacy[] = {
358 { SYS_RES_IRQ, 0, RF_ACTIVE | RF_SHAREABLE },
359 { -1, 0, 0 }
360};
361
362static struct resource_spec bwn_res_spec_msi[] = {
363 { SYS_RES_IRQ, 1, RF_ACTIVE },
364 { -1, 0, 0 }
365};
366
367static 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
377static 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
396static 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
445static const struct {
446 uint16_t vid;
447 uint8_t led_act[BWN_LED_MAX];
448} bwn_vendor_led_act[] = {
449 VENDOR_LED_ACT(COMPAQ),
450 VENDOR_LED_ACT(ASUSTEK)
451};
452
453static const uint8_t bwn_default_led_act[BWN_LED_MAX] =
454 { BWN_VENDOR_LED_ACT_DEFAULT };
455
456#undef VENDOR_LED_ACT
457
458static const struct {
459 int on_dur;
460 int off_dur;
461} bwn_led_duration[109] = {
462 [0] = { 400, 100 },
463 [2] = { 150, 75 },
464 [4] = { 90, 45 },
465 [11] = { 66, 34 },
466 [12] = { 53, 26 },
467 [18] = { 42, 21 },
468 [22] = { 35, 17 },
469 [24] = { 32, 16 },
470 [36] = { 21, 10 },
471 [48] = { 16, 8 },
472 [72] = { 11, 5 },
473 [96] = { 9, 4 },
474 [108] = { 7, 3 }
475};
476
477static const uint16_t bwn_wme_shm_offsets[] = {
478 [0] = BWN_WME_BESTEFFORT,
479 [1] = BWN_WME_BACKGROUND,
480 [2] = BWN_WME_VOICE,
481 [3] = BWN_WME_VIDEO,
482};
483
484static const struct siba_devid bwn_devs[] = {
485 SIBA_DEV(BROADCOM, 80211, 5, "Revision 5"),
486 SIBA_DEV(BROADCOM, 80211, 6, "Revision 6"),
487 SIBA_DEV(BROADCOM, 80211, 7, "Revision 7"),
488 SIBA_DEV(BROADCOM, 80211, 9, "Revision 9"),
489 SIBA_DEV(BROADCOM, 80211, 10, "Revision 10"),
490 SIBA_DEV(BROADCOM, 80211, 11, "Revision 11"),
491 SIBA_DEV(BROADCOM, 80211, 12, "Revision 12"),
492 SIBA_DEV(BROADCOM, 80211, 13, "Revision 13"),
493 SIBA_DEV(BROADCOM, 80211, 15, "Revision 15"),
494 SIBA_DEV(BROADCOM, 80211, 16, "Revision 16")
495};
496
497static int
498bwn_probe(device_t dev)
499{
500 int i;
501
502 for (i = 0; i < nitems(bwn_devs); i++) {
503 if (siba_get_vendor(dev) == bwn_devs[i].sd_vendor &&
504 siba_get_device(dev) == bwn_devs[i].sd_device &&
505 siba_get_revid(dev) == bwn_devs[i].sd_rev)
506 return (BUS_PROBE_DEFAULT);
507 }
508
509 return (ENXIO);
510}
511
512static int
513bwn_attach(device_t dev)
514{
515 struct bwn_mac *mac;
516 struct bwn_softc *sc = device_get_softc(dev);
517 int error, i, msic, reg;
518
519 sc->sc_dev = dev;
520#ifdef BWN_DEBUG
521 sc->sc_debug = bwn_debug;
522#endif
523
524 if ((sc->sc_flags & BWN_FLAG_ATTACHED) == 0) {
525 bwn_attach_pre(sc);
526 bwn_sprom_bugfixes(dev);
527 sc->sc_flags |= BWN_FLAG_ATTACHED;
528 }
529
530 if (!TAILQ_EMPTY(&sc->sc_maclist)) {
531 if (siba_get_pci_device(dev) != 0x4313 &&
532 siba_get_pci_device(dev) != 0x431a &&
533 siba_get_pci_device(dev) != 0x4321) {
534 device_printf(sc->sc_dev,
535 "skip 802.11 cores\n");
536 return (ENODEV);
537 }
538 }
539
540 mac = malloc(sizeof(*mac), M_DEVBUF, M_WAITOK | M_ZERO);
541 mac->mac_sc = sc;
542 mac->mac_status = BWN_MAC_STATUS_UNINIT;
543 if (bwn_bfp != 0)
544 mac->mac_flags |= BWN_MAC_FLAG_BADFRAME_PREEMP;
545
546 TASK_INIT(&mac->mac_hwreset, 0, bwn_hwreset, mac);
547 TASK_INIT(&mac->mac_intrtask, 0, bwn_intrtask, mac);
548 TASK_INIT(&mac->mac_txpower, 0, bwn_txpwr, mac);
549
550 error = bwn_attach_core(mac);
551 if (error)
552 goto fail0;
553 bwn_led_attach(mac);
554
555 device_printf(sc->sc_dev, "WLAN (chipid %#x rev %u) "
556 "PHY (analog %d type %d rev %d) RADIO (manuf %#x ver %#x rev %d)\n",
557 siba_get_chipid(sc->sc_dev), siba_get_revid(sc->sc_dev),
558 mac->mac_phy.analog, mac->mac_phy.type, mac->mac_phy.rev,
559 mac->mac_phy.rf_manuf, mac->mac_phy.rf_ver,
560 mac->mac_phy.rf_rev);
561 if (mac->mac_flags & BWN_MAC_FLAG_DMA)
562 device_printf(sc->sc_dev, "DMA (%d bits)\n",
563 mac->mac_method.dma.dmatype);
564 else
565 device_printf(sc->sc_dev, "PIO\n");
566
567 /*
568 * setup PCI resources and interrupt.
569 */
570 if (pci_find_cap(dev, PCIY_EXPRESS, &reg) == 0) {
571 msic = pci_msi_count(dev);
572 if (bootverbose)
573 device_printf(sc->sc_dev, "MSI count : %d\n", msic);
574 } else
575 msic = 0;
576
577 mac->mac_intr_spec = bwn_res_spec_legacy;
578 if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0) {
579 if (pci_alloc_msi(dev, &msic) == 0) {
580 device_printf(sc->sc_dev,
581 "Using %d MSI messages\n", msic);
582 mac->mac_intr_spec = bwn_res_spec_msi;
583 mac->mac_msi = 1;
584 }
585 }
586
587 error = bus_alloc_resources(dev, mac->mac_intr_spec,
588 mac->mac_res_irq);
589 if (error) {
590 device_printf(sc->sc_dev,
591 "couldn't allocate IRQ resources (%d)\n", error);
592 goto fail1;
593 }
594
595 if (mac->mac_msi == 0)
596 error = bus_setup_intr(dev, mac->mac_res_irq[0],
597 INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac,
598 &mac->mac_intrhand[0]);
599 else {
600 for (i = 0; i < BWN_MSI_MESSAGES; i++) {
601 error = bus_setup_intr(dev, mac->mac_res_irq[i],
602 INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac,
603 &mac->mac_intrhand[i]);
604 if (error != 0) {
605 device_printf(sc->sc_dev,
606 "couldn't setup interrupt (%d)\n", error);
607 break;
608 }
609 }
610 }
611
612 TAILQ_INSERT_TAIL(&sc->sc_maclist, mac, mac_list);
613
614 /*
615 * calls attach-post routine
616 */
617 if ((sc->sc_flags & BWN_FLAG_ATTACHED) != 0)
618 bwn_attach_post(sc);
619
620 return (0);
621fail1:
622 if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0)
623 pci_release_msi(dev);
624fail0:
625 free(mac, M_DEVBUF);
626 return (error);
627}
628
629static int
630bwn_is_valid_ether_addr(uint8_t *addr)
631{
632 char zero_addr[6] = { 0, 0, 0, 0, 0, 0 };
633
634 if ((addr[0] & 1) || (!bcmp(addr, zero_addr, ETHER_ADDR_LEN)))
635 return (FALSE);
636
637 return (TRUE);
638}
639
640static int
641bwn_attach_post(struct bwn_softc *sc)
642{
643 struct ieee80211com *ic = &sc->sc_ic;
644
645 ic->ic_softc = sc;
646 ic->ic_name = device_get_nameunit(sc->sc_dev);
647 /* XXX not right but it's not used anywhere important */
648 ic->ic_phytype = IEEE80211_T_OFDM;
649 ic->ic_opmode = IEEE80211_M_STA;
650 ic->ic_caps =
651 IEEE80211_C_STA /* station mode supported */
652 | IEEE80211_C_MONITOR /* monitor mode */
653 | IEEE80211_C_AHDEMO /* adhoc demo mode */
654 | IEEE80211_C_SHPREAMBLE /* short preamble supported */
655 | IEEE80211_C_SHSLOT /* short slot time supported */
656 | IEEE80211_C_WME /* WME/WMM supported */
657 | IEEE80211_C_WPA /* capable of WPA1+WPA2 */
658#if 0
659 | IEEE80211_C_BGSCAN /* capable of bg scanning */
660#endif
661 | IEEE80211_C_TXPMGT /* capable of txpow mgt */
662 ;
663
664 ic->ic_flags_ext |= IEEE80211_FEXT_SWBMISS; /* s/w bmiss */
665
666 IEEE80211_ADDR_COPY(ic->ic_macaddr,
667 bwn_is_valid_ether_addr(siba_sprom_get_mac_80211a(sc->sc_dev)) ?
668 siba_sprom_get_mac_80211a(sc->sc_dev) :
669 siba_sprom_get_mac_80211bg(sc->sc_dev));
670
671 /* call MI attach routine. */
672 ieee80211_ifattach(ic);
673
674 ic->ic_headroom = sizeof(struct bwn_txhdr);
675
676 /* override default methods */
677 ic->ic_raw_xmit = bwn_raw_xmit;
678 ic->ic_updateslot = bwn_updateslot;
679 ic->ic_update_promisc = bwn_update_promisc;
680 ic->ic_wme.wme_update = bwn_wme_update;
681 ic->ic_scan_start = bwn_scan_start;
682 ic->ic_scan_end = bwn_scan_end;
683 ic->ic_set_channel = bwn_set_channel;
684 ic->ic_vap_create = bwn_vap_create;
685 ic->ic_vap_delete = bwn_vap_delete;
686 ic->ic_transmit = bwn_transmit;
687 ic->ic_parent = bwn_parent;
688
689 ieee80211_radiotap_attach(ic,
690 &sc->sc_tx_th.wt_ihdr, sizeof(sc->sc_tx_th),
691 BWN_TX_RADIOTAP_PRESENT,
692 &sc->sc_rx_th.wr_ihdr, sizeof(sc->sc_rx_th),
693 BWN_RX_RADIOTAP_PRESENT);
694
695 bwn_sysctl_node(sc);
696
697 if (bootverbose)
698 ieee80211_announce(ic);
699 return (0);
700}
701
702static void
703bwn_phy_detach(struct bwn_mac *mac)
704{
705
706 if (mac->mac_phy.detach != NULL)
707 mac->mac_phy.detach(mac);
708}
709
710static int
711bwn_detach(device_t dev)
712{
713 struct bwn_softc *sc = device_get_softc(dev);
714 struct bwn_mac *mac = sc->sc_curmac;
715 struct ieee80211com *ic = &sc->sc_ic;
716 int i;
717
718 sc->sc_flags |= BWN_FLAG_INVALID;
719
720 if (device_is_attached(sc->sc_dev)) {
721 BWN_LOCK(sc);
722 bwn_stop(sc);
723 BWN_UNLOCK(sc);
724 bwn_dma_free(mac);
725 callout_drain(&sc->sc_led_blink_ch);
726 callout_drain(&sc->sc_rfswitch_ch);
727 callout_drain(&sc->sc_task_ch);
728 callout_drain(&sc->sc_watchdog_ch);
729 bwn_phy_detach(mac);
730 ieee80211_draintask(ic, &mac->mac_hwreset);
731 ieee80211_draintask(ic, &mac->mac_txpower);
732 ieee80211_ifdetach(ic);
733 }
734 taskqueue_drain(sc->sc_tq, &mac->mac_intrtask);
735 taskqueue_free(sc->sc_tq);
736
737 for (i = 0; i < BWN_MSI_MESSAGES; i++) {
738 if (mac->mac_intrhand[i] != NULL) {
739 bus_teardown_intr(dev, mac->mac_res_irq[i],
740 mac->mac_intrhand[i]);
741 mac->mac_intrhand[i] = NULL;
742 }
743 }
744 bus_release_resources(dev, mac->mac_intr_spec, mac->mac_res_irq);
745 if (mac->mac_msi != 0)
746 pci_release_msi(dev);
747 mbufq_drain(&sc->sc_snd);
748 BWN_LOCK_DESTROY(sc);
749 return (0);
750}
751
752static void
753bwn_attach_pre(struct bwn_softc *sc)
754{
755
756 BWN_LOCK_INIT(sc);
757 TAILQ_INIT(&sc->sc_maclist);
758 callout_init_mtx(&sc->sc_rfswitch_ch, &sc->sc_mtx, 0);
759 callout_init_mtx(&sc->sc_task_ch, &sc->sc_mtx, 0);
760 callout_init_mtx(&sc->sc_watchdog_ch, &sc->sc_mtx, 0);
761 mbufq_init(&sc->sc_snd, ifqmaxlen);
762 sc->sc_tq = taskqueue_create_fast("bwn_taskq", M_NOWAIT,
763 taskqueue_thread_enqueue, &sc->sc_tq);
764 taskqueue_start_threads(&sc->sc_tq, 1, PI_NET,
765 "%s taskq", device_get_nameunit(sc->sc_dev));
766}
767
768static void
769bwn_sprom_bugfixes(device_t dev)
770{
771#define BWN_ISDEV(_vendor, _device, _subvendor, _subdevice) \
772 ((siba_get_pci_vendor(dev) == PCI_VENDOR_##_vendor) && \
773 (siba_get_pci_device(dev) == _device) && \
774 (siba_get_pci_subvendor(dev) == PCI_VENDOR_##_subvendor) && \
775 (siba_get_pci_subdevice(dev) == _subdevice))
776
777 if (siba_get_pci_subvendor(dev) == PCI_VENDOR_APPLE &&
778 siba_get_pci_subdevice(dev) == 0x4e &&
779 siba_get_pci_revid(dev) > 0x40)
780 siba_sprom_set_bf_lo(dev,
781 siba_sprom_get_bf_lo(dev) | BWN_BFL_PACTRL);
782 if (siba_get_pci_subvendor(dev) == SIBA_BOARDVENDOR_DELL &&
783 siba_get_chipid(dev) == 0x4301 && siba_get_pci_revid(dev) == 0x74)
784 siba_sprom_set_bf_lo(dev,
785 siba_sprom_get_bf_lo(dev) | BWN_BFL_BTCOEXIST);
786 if (siba_get_type(dev) == SIBA_TYPE_PCI) {
787 if (BWN_ISDEV(BROADCOM, 0x4318, ASUSTEK, 0x100f) ||
788 BWN_ISDEV(BROADCOM, 0x4320, DELL, 0x0003) ||
789 BWN_ISDEV(BROADCOM, 0x4320, HP, 0x12f8) ||
790 BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0013) ||
791 BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0014) ||
792 BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0015) ||
793 BWN_ISDEV(BROADCOM, 0x4320, MOTOROLA, 0x7010))
794 siba_sprom_set_bf_lo(dev,
795 siba_sprom_get_bf_lo(dev) & ~BWN_BFL_BTCOEXIST);
796 }
797#undef BWN_ISDEV
798}
799
800static void
801bwn_parent(struct ieee80211com *ic)
802{
803 struct bwn_softc *sc = ic->ic_softc;
804 int startall = 0;
805
806 BWN_LOCK(sc);
807 if (ic->ic_nrunning > 0) {
808 if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0) {
809 bwn_init(sc);
810 startall = 1;
811 } else
812 bwn_update_promisc(ic);
813 } else if (sc->sc_flags & BWN_FLAG_RUNNING)
814 bwn_stop(sc);
815 BWN_UNLOCK(sc);
816
817 if (startall)
818 ieee80211_start_all(ic);
819}
820
821static int
822bwn_transmit(struct ieee80211com *ic, struct mbuf *m)
823{
824 struct bwn_softc *sc = ic->ic_softc;
825 int error;
826
827 BWN_LOCK(sc);
828 if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0) {
829 BWN_UNLOCK(sc);
830 return (ENXIO);
831 }
832 error = mbufq_enqueue(&sc->sc_snd, m);
833 if (error) {
834 BWN_UNLOCK(sc);
835 return (error);
836 }
837 bwn_start(sc);
838 BWN_UNLOCK(sc);
839 return (0);
840}
841
842static void
843bwn_start(struct bwn_softc *sc)
844{
845 struct bwn_mac *mac = sc->sc_curmac;
846 struct ieee80211_frame *wh;
847 struct ieee80211_node *ni;
848 struct ieee80211_key *k;
849 struct mbuf *m;
850
851 BWN_ASSERT_LOCKED(sc);
852
853 if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0 || mac == NULL ||
854 mac->mac_status < BWN_MAC_STATUS_STARTED)
855 return;
856
857 while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
858 if (bwn_tx_isfull(sc, m))
859 break;
860 ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
861 if (ni == NULL) {
862 device_printf(sc->sc_dev, "unexpected NULL ni\n");
863 m_freem(m);
864 counter_u64_add(sc->sc_ic.ic_oerrors, 1);
865 continue;
866 }
867 wh = mtod(m, struct ieee80211_frame *);
868 if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
869 k = ieee80211_crypto_encap(ni, m);
870 if (k == NULL) {
871 if_inc_counter(ni->ni_vap->iv_ifp,
872 IFCOUNTER_OERRORS, 1);
873 ieee80211_free_node(ni);
874 m_freem(m);
875 continue;
876 }
877 }
878 wh = NULL; /* Catch any invalid use */
879 if (bwn_tx_start(sc, ni, m) != 0) {
880 if (ni != NULL) {
881 if_inc_counter(ni->ni_vap->iv_ifp,
882 IFCOUNTER_OERRORS, 1);
883 ieee80211_free_node(ni);
884 }
885 continue;
886 }
887 sc->sc_watchdog_timer = 5;
888 }
889}
890
891static int
892bwn_tx_isfull(struct bwn_softc *sc, struct mbuf *m)
893{
894 struct bwn_dma_ring *dr;
895 struct bwn_mac *mac = sc->sc_curmac;
896 struct bwn_pio_txqueue *tq;
897 int pktlen = roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
898
899 BWN_ASSERT_LOCKED(sc);
900
901 if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
902 dr = bwn_dma_select(mac, M_WME_GETAC(m));
903 if (dr->dr_stop == 1 ||
904 bwn_dma_freeslot(dr) < BWN_TX_SLOTS_PER_FRAME) {
905 dr->dr_stop = 1;
906 goto full;
907 }
908 } else {
909 tq = bwn_pio_select(mac, M_WME_GETAC(m));
910 if (tq->tq_free == 0 || pktlen > tq->tq_size ||
911 pktlen > (tq->tq_size - tq->tq_used))
912 goto full;
913 }
914 return (0);
915full:
916 mbufq_prepend(&sc->sc_snd, m);
917 return (1);
918}
919
920static int
921bwn_tx_start(struct bwn_softc *sc, struct ieee80211_node *ni, struct mbuf *m)
922{
923 struct bwn_mac *mac = sc->sc_curmac;
924 int error;
925
926 BWN_ASSERT_LOCKED(sc);
927
928 if (m->m_pkthdr.len < IEEE80211_MIN_LEN || mac == NULL) {
929 m_freem(m);
930 return (ENXIO);
931 }
932
933 error = (mac->mac_flags & BWN_MAC_FLAG_DMA) ?
934 bwn_dma_tx_start(mac, ni, m) : bwn_pio_tx_start(mac, ni, m);
935 if (error) {
936 m_freem(m);
937 return (error);
938 }
939 return (0);
940}
941
942static int
943bwn_pio_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
944{
945 struct bwn_pio_txpkt *tp;
946 struct bwn_pio_txqueue *tq = bwn_pio_select(mac, M_WME_GETAC(m));
947 struct bwn_softc *sc = mac->mac_sc;
948 struct bwn_txhdr txhdr;
949 struct mbuf *m_new;
950 uint32_t ctl32;
951 int error;
952 uint16_t ctl16;
953
954 BWN_ASSERT_LOCKED(sc);
955
956 /* XXX TODO send packets after DTIM */
957
958 KASSERT(!TAILQ_EMPTY(&tq->tq_pktlist), ("%s: fail", __func__));
959 tp = TAILQ_FIRST(&tq->tq_pktlist);
960 tp->tp_ni = ni;
961 tp->tp_m = m;
962
963 error = bwn_set_txhdr(mac, ni, m, &txhdr, BWN_PIO_COOKIE(tq, tp));
964 if (error) {
965 device_printf(sc->sc_dev, "tx fail\n");
966 return (error);
967 }
968
969 TAILQ_REMOVE(&tq->tq_pktlist, tp, tp_list);
970 tq->tq_used += roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
971 tq->tq_free--;
972
973 if (siba_get_revid(sc->sc_dev) >= 8) {
974 /*
975 * XXX please removes m_defrag(9)
976 */
977 m_new = m_defrag(m, M_NOWAIT);
978 if (m_new == NULL) {
979 device_printf(sc->sc_dev,
980 "%s: can't defrag TX buffer\n",
981 __func__);
982 return (ENOBUFS);
983 }
984 if (m_new->m_next != NULL)
985 device_printf(sc->sc_dev,
986 "TODO: fragmented packets for PIO\n");
987 tp->tp_m = m_new;
988
989 /* send HEADER */
990 ctl32 = bwn_pio_write_multi_4(mac, tq,
991 (BWN_PIO_READ_4(mac, tq, BWN_PIO8_TXCTL) |
992 BWN_PIO8_TXCTL_FRAMEREADY) & ~BWN_PIO8_TXCTL_EOF,
993 (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
994 /* send BODY */
995 ctl32 = bwn_pio_write_multi_4(mac, tq, ctl32,
996 mtod(m_new, const void *), m_new->m_pkthdr.len);
997 bwn_pio_write_4(mac, tq, BWN_PIO_TXCTL,
998 ctl32 | BWN_PIO8_TXCTL_EOF);
999 } else {
1000 ctl16 = bwn_pio_write_multi_2(mac, tq,
1001 (bwn_pio_read_2(mac, tq, BWN_PIO_TXCTL) |
1002 BWN_PIO_TXCTL_FRAMEREADY) & ~BWN_PIO_TXCTL_EOF,
1003 (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1004 ctl16 = bwn_pio_write_mbuf_2(mac, tq, ctl16, m);
1005 BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL,
1006 ctl16 | BWN_PIO_TXCTL_EOF);
1007 }
1008
1009 return (0);
1010}
1011
1012static struct bwn_pio_txqueue *
1013bwn_pio_select(struct bwn_mac *mac, uint8_t prio)
1014{
1015
1016 if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
1017 return (&mac->mac_method.pio.wme[WME_AC_BE]);
1018
1019 switch (prio) {
1020 case 0:
1021 return (&mac->mac_method.pio.wme[WME_AC_BE]);
1022 case 1:
1023 return (&mac->mac_method.pio.wme[WME_AC_BK]);
1024 case 2:
1025 return (&mac->mac_method.pio.wme[WME_AC_VI]);
1026 case 3:
1027 return (&mac->mac_method.pio.wme[WME_AC_VO]);
1028 }
1029 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
1030 return (NULL);
1031}
1032
1033static int
1034bwn_dma_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1035{
1036#define BWN_GET_TXHDRCACHE(slot) \
1037 &(txhdr_cache[(slot / BWN_TX_SLOTS_PER_FRAME) * BWN_HDRSIZE(mac)])
1038 struct bwn_dma *dma = &mac->mac_method.dma;
1039 struct bwn_dma_ring *dr = bwn_dma_select(mac, M_WME_GETAC(m));
1040 struct bwn_dmadesc_generic *desc;
1041 struct bwn_dmadesc_meta *mt;
1042 struct bwn_softc *sc = mac->mac_sc;
1043 uint8_t *txhdr_cache = (uint8_t *)dr->dr_txhdr_cache;
1044 int error, slot, backup[2] = { dr->dr_curslot, dr->dr_usedslot };
1045
1046 BWN_ASSERT_LOCKED(sc);
1047 KASSERT(!dr->dr_stop, ("%s:%d: fail", __func__, __LINE__));
1048
1049 /* XXX send after DTIM */
1050
1051 slot = bwn_dma_getslot(dr);
1052 dr->getdesc(dr, slot, &desc, &mt);
1053 KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_HEADER,
1054 ("%s:%d: fail", __func__, __LINE__));
1055
1056 error = bwn_set_txhdr(dr->dr_mac, ni, m,
1057 (struct bwn_txhdr *)BWN_GET_TXHDRCACHE(slot),
1058 BWN_DMA_COOKIE(dr, slot));
1059 if (error)
1060 goto fail;
1061 error = bus_dmamap_load(dr->dr_txring_dtag, mt->mt_dmap,
1062 BWN_GET_TXHDRCACHE(slot), BWN_HDRSIZE(mac), bwn_dma_ring_addr,
1063 &mt->mt_paddr, BUS_DMA_NOWAIT);
1064 if (error) {
1065 device_printf(sc->sc_dev, "%s: can't load TX buffer (1) %d\n",
1066 __func__, error);
1067 goto fail;
1068 }
1069 bus_dmamap_sync(dr->dr_txring_dtag, mt->mt_dmap,
1070 BUS_DMASYNC_PREWRITE);
1071 dr->setdesc(dr, desc, mt->mt_paddr, BWN_HDRSIZE(mac), 1, 0, 0);
1072 bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1073 BUS_DMASYNC_PREWRITE);
1074
1075 slot = bwn_dma_getslot(dr);
1076 dr->getdesc(dr, slot, &desc, &mt);
1077 KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_BODY &&
1078 mt->mt_islast == 1, ("%s:%d: fail", __func__, __LINE__));
1079 mt->mt_m = m;
1080 mt->mt_ni = ni;
1081
1082 error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap, m,
1083 bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1084 if (error && error != EFBIG) {
1085 device_printf(sc->sc_dev, "%s: can't load TX buffer (1) %d\n",
1086 __func__, error);
1087 goto fail;
1088 }
1089 if (error) { /* error == EFBIG */
1090 struct mbuf *m_new;
1091
1092 m_new = m_defrag(m, M_NOWAIT);
1093 if (m_new == NULL) {
1094 device_printf(sc->sc_dev,
1095 "%s: can't defrag TX buffer\n",
1096 __func__);
1097 error = ENOBUFS;
1098 goto fail;
1099 } else {
1100 m = m_new;
1101 }
1102
1103 mt->mt_m = m;
1104 error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap,
1105 m, bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1106 if (error) {
1107 device_printf(sc->sc_dev,
1108 "%s: can't load TX buffer (2) %d\n",
1109 __func__, error);
1110 goto fail;
1111 }
1112 }
1113 bus_dmamap_sync(dma->txbuf_dtag, mt->mt_dmap, BUS_DMASYNC_PREWRITE);
1114 dr->setdesc(dr, desc, mt->mt_paddr, m->m_pkthdr.len, 0, 1, 1);
1115 bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1116 BUS_DMASYNC_PREWRITE);
1117
1118 /* XXX send after DTIM */
1119
1120 dr->start_transfer(dr, bwn_dma_nextslot(dr, slot));
1121 return (0);
1122fail:
1123 dr->dr_curslot = backup[0];
1124 dr->dr_usedslot = backup[1];
1125 return (error);
1126#undef BWN_GET_TXHDRCACHE
1127}
1128
1129static void
1130bwn_watchdog(void *arg)
1131{
1132 struct bwn_softc *sc = arg;
1133
1134 if (sc->sc_watchdog_timer != 0 && --sc->sc_watchdog_timer == 0) {
1135 device_printf(sc->sc_dev, "device timeout\n");
1136 counter_u64_add(sc->sc_ic.ic_oerrors, 1);
1137 }
1138 callout_schedule(&sc->sc_watchdog_ch, hz);
1139}
1140
1141static int
1142bwn_attach_core(struct bwn_mac *mac)
1143{
1144 struct bwn_softc *sc = mac->mac_sc;
1145 int error, have_bg = 0, have_a = 0;
1146 uint32_t high;
1147
1148 KASSERT(siba_get_revid(sc->sc_dev) >= 5,
1149 ("unsupported revision %d", siba_get_revid(sc->sc_dev)));
1150
1151 siba_powerup(sc->sc_dev, 0);
1152
1153 high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH);
1154
1155 /*
1156 * Guess at whether it has A-PHY or G-PHY.
1157 * This is just used for resetting the core to probe things;
1158 * we will re-guess once it's all up and working.
1159 *
1160 * XXX TODO: there's the TGSHIGH DUALPHY flag based on
1161 * the PHY revision.
1162 */
1163 bwn_reset_core(mac, !!(high & BWN_TGSHIGH_HAVE_2GHZ));
1164
1165 /*
1166 * Get the PHY version.
1167 */
1168 error = bwn_phy_getinfo(mac, high);
1169 if (error)
1170 goto fail;
1171
1172 /* XXX TODO need bhnd */
1173 if (bwn_is_bus_siba(mac)) {
1174 have_a = (high & BWN_TGSHIGH_HAVE_5GHZ) ? 1 : 0;
1175 have_bg = (high & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1176 if (high & BWN_TGSHIGH_DUALPHY) {
1177 have_bg = 1;
1178 have_a = 1;
1179 }
1180 } else {
1181 device_printf(sc->sc_dev, "%s: not siba; bailing\n", __func__);
1182 error = ENXIO;
1183 goto fail;
1184 }
1185
1186#if 0
1187 device_printf(sc->sc_dev, "%s: high=0x%08x, have_a=%d, have_bg=%d,"
1188 " deviceid=0x%04x, siba_deviceid=0x%04x\n",
1189 __func__,
1190 high,
1191 have_a,
1192 have_bg,
1193 siba_get_pci_device(sc->sc_dev),
1194 siba_get_chipid(sc->sc_dev));
1195#endif
1196
1197 if (siba_get_pci_device(sc->sc_dev) != 0x4312 &&
1198 siba_get_pci_device(sc->sc_dev) != 0x4319 &&
1199 siba_get_pci_device(sc->sc_dev) != 0x4324 &&
1200 siba_get_pci_device(sc->sc_dev) != 0x4328) {
1201 have_a = have_bg = 0;
1202 if (mac->mac_phy.type == BWN_PHYTYPE_A)
1203 have_a = 1;
1204 else if (mac->mac_phy.type == BWN_PHYTYPE_G ||
1205 mac->mac_phy.type == BWN_PHYTYPE_N ||
1206 mac->mac_phy.type == BWN_PHYTYPE_LP)
1207 have_bg = 1;
1208 else
1209 KASSERT(0 == 1, ("%s: unknown phy type (%d)", __func__,
1210 mac->mac_phy.type));
1211 }
1212
1213 /*
1214 * XXX turns off PHY A because it's not supported.
1215 * Implement PHY-A support so we can use it for PHY-G
1216 * dual-band support.
1217 */
1218 if (mac->mac_phy.type != BWN_PHYTYPE_LP &&
1219 mac->mac_phy.type != BWN_PHYTYPE_N) {
1220 device_printf(sc->sc_dev,
1221 "%s: forcing 2GHz only; missing PHY-A support\n",
1222 __func__);
1223 have_a = 0;
1224 have_bg = 1;
1225 }
1226
1227 mac->mac_phy.phy_n = NULL;
1228
1229 if (mac->mac_phy.type == BWN_PHYTYPE_G) {
1230 mac->mac_phy.attach = bwn_phy_g_attach;
1231 mac->mac_phy.detach = bwn_phy_g_detach;
1232 mac->mac_phy.prepare_hw = bwn_phy_g_prepare_hw;
1233 mac->mac_phy.init_pre = bwn_phy_g_init_pre;
1234 mac->mac_phy.init = bwn_phy_g_init;
1235 mac->mac_phy.exit = bwn_phy_g_exit;
1236 mac->mac_phy.phy_read = bwn_phy_g_read;
1237 mac->mac_phy.phy_write = bwn_phy_g_write;
1238 mac->mac_phy.rf_read = bwn_phy_g_rf_read;
1239 mac->mac_phy.rf_write = bwn_phy_g_rf_write;
1240 mac->mac_phy.use_hwpctl = bwn_phy_g_hwpctl;
1241 mac->mac_phy.rf_onoff = bwn_phy_g_rf_onoff;
1242 mac->mac_phy.switch_analog = bwn_phy_switch_analog;
1243 mac->mac_phy.switch_channel = bwn_phy_g_switch_channel;
1244 mac->mac_phy.get_default_chan = bwn_phy_g_get_default_chan;
1245 mac->mac_phy.set_antenna = bwn_phy_g_set_antenna;
1246 mac->mac_phy.set_im = bwn_phy_g_im;
1247 mac->mac_phy.recalc_txpwr = bwn_phy_g_recalc_txpwr;
1248 mac->mac_phy.set_txpwr = bwn_phy_g_set_txpwr;
1249 mac->mac_phy.task_15s = bwn_phy_g_task_15s;
1250 mac->mac_phy.task_60s = bwn_phy_g_task_60s;
1251 } else if (mac->mac_phy.type == BWN_PHYTYPE_LP) {
1252 mac->mac_phy.init_pre = bwn_phy_lp_init_pre;
1253 mac->mac_phy.init = bwn_phy_lp_init;
1254 mac->mac_phy.phy_read = bwn_phy_lp_read;
1255 mac->mac_phy.phy_write = bwn_phy_lp_write;
1256 mac->mac_phy.phy_maskset = bwn_phy_lp_maskset;
1257 mac->mac_phy.rf_read = bwn_phy_lp_rf_read;
1258 mac->mac_phy.rf_write = bwn_phy_lp_rf_write;
1259 mac->mac_phy.rf_onoff = bwn_phy_lp_rf_onoff;
1260 mac->mac_phy.switch_analog = bwn_phy_lp_switch_analog;
1261 mac->mac_phy.switch_channel = bwn_phy_lp_switch_channel;
1262 mac->mac_phy.get_default_chan = bwn_phy_lp_get_default_chan;
1263 mac->mac_phy.set_antenna = bwn_phy_lp_set_antenna;
1264 mac->mac_phy.task_60s = bwn_phy_lp_task_60s;
1265 } else if (mac->mac_phy.type == BWN_PHYTYPE_N) {
1266 mac->mac_phy.attach = bwn_phy_n_attach;
1267 mac->mac_phy.detach = bwn_phy_n_detach;
1268 mac->mac_phy.prepare_hw = bwn_phy_n_prepare_hw;
1269 mac->mac_phy.init_pre = bwn_phy_n_init_pre;
1270 mac->mac_phy.init = bwn_phy_n_init;
1271 mac->mac_phy.exit = bwn_phy_n_exit;
1272 mac->mac_phy.phy_read = bwn_phy_n_read;
1273 mac->mac_phy.phy_write = bwn_phy_n_write;
1274 mac->mac_phy.rf_read = bwn_phy_n_rf_read;
1275 mac->mac_phy.rf_write = bwn_phy_n_rf_write;
1276 mac->mac_phy.use_hwpctl = bwn_phy_n_hwpctl;
1277 mac->mac_phy.rf_onoff = bwn_phy_n_rf_onoff;
1278 mac->mac_phy.switch_analog = bwn_phy_n_switch_analog;
1279 mac->mac_phy.switch_channel = bwn_phy_n_switch_channel;
1280 mac->mac_phy.get_default_chan = bwn_phy_n_get_default_chan;
1281 mac->mac_phy.set_antenna = bwn_phy_n_set_antenna;
1282 mac->mac_phy.set_im = bwn_phy_n_im;
1283 mac->mac_phy.recalc_txpwr = bwn_phy_n_recalc_txpwr;
1284 mac->mac_phy.set_txpwr = bwn_phy_n_set_txpwr;
1285 mac->mac_phy.task_15s = bwn_phy_n_task_15s;
1286 mac->mac_phy.task_60s = bwn_phy_n_task_60s;
1287 } else {
1288 device_printf(sc->sc_dev, "unsupported PHY type (%d)\n",
1289 mac->mac_phy.type);
1290 error = ENXIO;
1291 goto fail;
1292 }
1293
1294 mac->mac_phy.gmode = have_bg;
1295 if (mac->mac_phy.attach != NULL) {
1296 error = mac->mac_phy.attach(mac);
1297 if (error) {
1298 device_printf(sc->sc_dev, "failed\n");
1299 goto fail;
1300 }
1301 }
1302
1303 bwn_reset_core(mac, have_bg);
1304
1305 error = bwn_chiptest(mac);
1306 if (error)
1307 goto fail;
1308 error = bwn_setup_channels(mac, have_bg, have_a);
1309 if (error) {
1310 device_printf(sc->sc_dev, "failed to setup channels\n");
1311 goto fail;
1312 }
1313
1314 if (sc->sc_curmac == NULL)
1315 sc->sc_curmac = mac;
1316
1317 error = bwn_dma_attach(mac);
1318 if (error != 0) {
1319 device_printf(sc->sc_dev, "failed to initialize DMA\n");
1320 goto fail;
1321 }
1322
1323 mac->mac_phy.switch_analog(mac, 0);
1324
1325 siba_dev_down(sc->sc_dev, 0);
1326fail:
1327 siba_powerdown(sc->sc_dev);
1328 return (error);
1329}
1330
1331/*
1332 * Reset - SIBA.
1333 *
1334 * XXX TODO: implement BCMA version!
1335 */
1336void
1337bwn_reset_core(struct bwn_mac *mac, int g_mode)
1338{
1339 struct bwn_softc *sc = mac->mac_sc;
1340 uint32_t low, ctl;
1341 uint32_t flags = 0;
1342
1343 DPRINTF(sc, BWN_DEBUG_RESET, "%s: g_mode=%d\n", __func__, g_mode);
1344
1345 flags |= (BWN_TGSLOW_PHYCLOCK_ENABLE | BWN_TGSLOW_PHYRESET);
1346 if (g_mode)
1347 flags |= BWN_TGSLOW_SUPPORT_G;
1348
1349 /* XXX N-PHY only; and hard-code to 20MHz for now */
1350 if (mac->mac_phy.type == BWN_PHYTYPE_N)
1351 flags |= BWN_TGSLOW_PHY_BANDWIDTH_20MHZ;
1352
1353 siba_dev_up(sc->sc_dev, flags);
1354 DELAY(2000);
1355
1356 /* Take PHY out of reset */
1357 low = (siba_read_4(sc->sc_dev, SIBA_TGSLOW) | SIBA_TGSLOW_FGC) &
1358 ~BWN_TGSLOW_PHYRESET;
1359 siba_write_4(sc->sc_dev, SIBA_TGSLOW, low);
1360 siba_read_4(sc->sc_dev, SIBA_TGSLOW);
1361 DELAY(1000);
1362 siba_write_4(sc->sc_dev, SIBA_TGSLOW, low & ~SIBA_TGSLOW_FGC);
1363 siba_read_4(sc->sc_dev, SIBA_TGSLOW);
1364 DELAY(1000);
1365
1366 if (mac->mac_phy.switch_analog != NULL)
1367 mac->mac_phy.switch_analog(mac, 1);
1368
1369 ctl = BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GMODE;
1370 if (g_mode)
1371 ctl |= BWN_MACCTL_GMODE;
1372 BWN_WRITE_4(mac, BWN_MACCTL, ctl | BWN_MACCTL_IHR_ON);
1373}
1374
1375static int
1376bwn_phy_getinfo(struct bwn_mac *mac, int tgshigh)
1377{
1378 struct bwn_phy *phy = &mac->mac_phy;
1379 struct bwn_softc *sc = mac->mac_sc;
1380 uint32_t tmp;
1381
1382 /* PHY */
1383 tmp = BWN_READ_2(mac, BWN_PHYVER);
1384 phy->gmode = !! (tgshigh & BWN_TGSHIGH_HAVE_2GHZ);
1385 phy->rf_on = 1;
1386 phy->analog = (tmp & BWN_PHYVER_ANALOG) >> 12;
1387 phy->type = (tmp & BWN_PHYVER_TYPE) >> 8;
1388 phy->rev = (tmp & BWN_PHYVER_VERSION);
1389 if ((phy->type == BWN_PHYTYPE_A && phy->rev >= 4) ||
1390 (phy->type == BWN_PHYTYPE_B && phy->rev != 2 &&
1391 phy->rev != 4 && phy->rev != 6 && phy->rev != 7) ||
1392 (phy->type == BWN_PHYTYPE_G && phy->rev > 9) ||
1393 (phy->type == BWN_PHYTYPE_N && phy->rev > 4) ||
1394 (phy->type == BWN_PHYTYPE_LP && phy->rev > 2))
1395 goto unsupphy;
1396
1397 /* RADIO */
1398 if (siba_get_chipid(sc->sc_dev) == 0x4317) {
1399 if (siba_get_chiprev(sc->sc_dev) == 0)
1400 tmp = 0x3205017f;
1401 else if (siba_get_chiprev(sc->sc_dev) == 1)
1402 tmp = 0x4205017f;
1403 else
1404 tmp = 0x5205017f;
1405 } else {
1406 BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1407 tmp = BWN_READ_2(mac, BWN_RFDATALO);
1408 BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1409 tmp |= (uint32_t)BWN_READ_2(mac, BWN_RFDATAHI) << 16;
1410 }
1411 phy->rf_rev = (tmp & 0xf0000000) >> 28;
1412 phy->rf_ver = (tmp & 0x0ffff000) >> 12;
1413 phy->rf_manuf = (tmp & 0x00000fff);
1414
1415 /*
1416 * For now, just always do full init (ie, what bwn has traditionally
1417 * done)
1418 */
1419 phy->phy_do_full_init = 1;
1420
1421 if (phy->rf_manuf != 0x17f) /* 0x17f is broadcom */
1422 goto unsupradio;
1423 if ((phy->type == BWN_PHYTYPE_A && (phy->rf_ver != 0x2060 ||
1424 phy->rf_rev != 1 || phy->rf_manuf != 0x17f)) ||
1425 (phy->type == BWN_PHYTYPE_B && (phy->rf_ver & 0xfff0) != 0x2050) ||
1426 (phy->type == BWN_PHYTYPE_G && phy->rf_ver != 0x2050) ||
1427 (phy->type == BWN_PHYTYPE_N &&
1428 phy->rf_ver != 0x2055 && phy->rf_ver != 0x2056) ||
1429 (phy->type == BWN_PHYTYPE_LP &&
1430 phy->rf_ver != 0x2062 && phy->rf_ver != 0x2063))
1431 goto unsupradio;
1432
1433 return (0);
1434unsupphy:
1435 device_printf(sc->sc_dev, "unsupported PHY (type %#x, rev %#x, "
1436 "analog %#x)\n",
1437 phy->type, phy->rev, phy->analog);
1438 return (ENXIO);
1439unsupradio:
1440 device_printf(sc->sc_dev, "unsupported radio (manuf %#x, ver %#x, "
1441 "rev %#x)\n",
1442 phy->rf_manuf, phy->rf_ver, phy->rf_rev);
1443 return (ENXIO);
1444}
1445
1446static int
1447bwn_chiptest(struct bwn_mac *mac)
1448{
1449#define TESTVAL0 0x55aaaa55
1450#define TESTVAL1 0xaa5555aa
1451 struct bwn_softc *sc = mac->mac_sc;
1452 uint32_t v, backup;
1453
1454 BWN_LOCK(sc);
1455
1456 backup = bwn_shm_read_4(mac, BWN_SHARED, 0);
1457
1458 bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL0);
1459 if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL0)
1460 goto error;
1461 bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL1);
1462 if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL1)
1463 goto error;
1464
1465 bwn_shm_write_4(mac, BWN_SHARED, 0, backup);
1466
1467 if ((siba_get_revid(sc->sc_dev) >= 3) &&
1468 (siba_get_revid(sc->sc_dev) <= 10)) {
1469 BWN_WRITE_2(mac, BWN_TSF_CFP_START, 0xaaaa);
1470 BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0xccccbbbb);
1471 if (BWN_READ_2(mac, BWN_TSF_CFP_START_LOW) != 0xbbbb)
1472 goto error;
1473 if (BWN_READ_2(mac, BWN_TSF_CFP_START_HIGH) != 0xcccc)
1474 goto error;
1475 }
1476 BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0);
1477
1478 v = BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_GMODE;
1479 if (v != (BWN_MACCTL_GMODE | BWN_MACCTL_IHR_ON))
1480 goto error;
1481
1482 BWN_UNLOCK(sc);
1483 return (0);
1484error:
1485 BWN_UNLOCK(sc);
1486 device_printf(sc->sc_dev, "failed to validate the chipaccess\n");
1487 return (ENODEV);
1488}
1489
1490static int
1491bwn_setup_channels(struct bwn_mac *mac, int have_bg, int have_a)
1492{
1493 struct bwn_softc *sc = mac->mac_sc;
1494 struct ieee80211com *ic = &sc->sc_ic;
1495 uint8_t bands[howmany(IEEE80211_MODE_MAX, 8)];
1496
1497 memset(ic->ic_channels, 0, sizeof(ic->ic_channels));
1498 ic->ic_nchans = 0;
1499
1500 DPRINTF(sc, BWN_DEBUG_EEPROM, "%s: called; bg=%d, a=%d\n",
1501 __func__,
1502 have_bg,
1503 have_a);
1504
1505 if (have_bg) {
1506 memset(bands, 0, sizeof(bands));
1507 setbit(bands, IEEE80211_MODE_11B);
1508 setbit(bands, IEEE80211_MODE_11G);
1509 bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1510 &ic->ic_nchans, &bwn_chantable_bg, bands);
1511 }
1512
1513 if (have_a) {
1514 memset(bands, 0, sizeof(bands));
1515 setbit(bands, IEEE80211_MODE_11A);
1516 bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1517 &ic->ic_nchans, &bwn_chantable_a, bands);
1518 }
1519
1520 mac->mac_phy.supports_2ghz = have_bg;
1521 mac->mac_phy.supports_5ghz = have_a;
1522
1523 return (ic->ic_nchans == 0 ? ENXIO : 0);
1524}
1525
1526uint32_t
1527bwn_shm_read_4(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1528{
1529 uint32_t ret;
1530
1531 BWN_ASSERT_LOCKED(mac->mac_sc);
1532
1533 if (way == BWN_SHARED) {
1534 KASSERT((offset & 0x0001) == 0,
1535 ("%s:%d warn", __func__, __LINE__));
1536 if (offset & 0x0003) {
1537 bwn_shm_ctlword(mac, way, offset >> 2);
1538 ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1539 ret <<= 16;
1540 bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1541 ret |= BWN_READ_2(mac, BWN_SHM_DATA);
1542 goto out;
1543 }
1544 offset >>= 2;
1545 }
1546 bwn_shm_ctlword(mac, way, offset);
1547 ret = BWN_READ_4(mac, BWN_SHM_DATA);
1548out:
1549 return (ret);
1550}
1551
1552uint16_t
1553bwn_shm_read_2(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1554{
1555 uint16_t ret;
1556
1557 BWN_ASSERT_LOCKED(mac->mac_sc);
1558
1559 if (way == BWN_SHARED) {
1560 KASSERT((offset & 0x0001) == 0,
1561 ("%s:%d warn", __func__, __LINE__));
1562 if (offset & 0x0003) {
1563 bwn_shm_ctlword(mac, way, offset >> 2);
1564 ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1565 goto out;
1566 }
1567 offset >>= 2;
1568 }
1569 bwn_shm_ctlword(mac, way, offset);
1570 ret = BWN_READ_2(mac, BWN_SHM_DATA);
1571out:
1572
1573 return (ret);
1574}
1575
1576static void
1577bwn_shm_ctlword(struct bwn_mac *mac, uint16_t way,
1578 uint16_t offset)
1579{
1580 uint32_t control;
1581
1582 control = way;
1583 control <<= 16;
1584 control |= offset;
1585 BWN_WRITE_4(mac, BWN_SHM_CONTROL, control);
1586}
1587
1588void
1589bwn_shm_write_4(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1590 uint32_t value)
1591{
1592 BWN_ASSERT_LOCKED(mac->mac_sc);
1593
1594 if (way == BWN_SHARED) {
1595 KASSERT((offset & 0x0001) == 0,
1596 ("%s:%d warn", __func__, __LINE__));
1597 if (offset & 0x0003) {
1598 bwn_shm_ctlword(mac, way, offset >> 2);
1599 BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED,
1600 (value >> 16) & 0xffff);
1601 bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1602 BWN_WRITE_2(mac, BWN_SHM_DATA, value & 0xffff);
1603 return;
1604 }
1605 offset >>= 2;
1606 }
1607 bwn_shm_ctlword(mac, way, offset);
1608 BWN_WRITE_4(mac, BWN_SHM_DATA, value);
1609}
1610
1611void
1612bwn_shm_write_2(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1613 uint16_t value)
1614{
1615 BWN_ASSERT_LOCKED(mac->mac_sc);
1616
1617 if (way == BWN_SHARED) {
1618 KASSERT((offset & 0x0001) == 0,
1619 ("%s:%d warn", __func__, __LINE__));
1620 if (offset & 0x0003) {
1621 bwn_shm_ctlword(mac, way, offset >> 2);
1622 BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED, value);
1623 return;
1624 }
1625 offset >>= 2;
1626 }
1627 bwn_shm_ctlword(mac, way, offset);
1628 BWN_WRITE_2(mac, BWN_SHM_DATA, value);
1629}
1630
1631static void
1632bwn_addchannels(struct ieee80211_channel chans[], int maxchans, int *nchans,
1633 const struct bwn_channelinfo *ci, const uint8_t bands[])
1634{
1635 int i, error;
1636
1637 for (i = 0, error = 0; i < ci->nchannels && error == 0; i++) {
1638 const struct bwn_channel *hc = &ci->channels[i];
1639
1640 error = ieee80211_add_channel(chans, maxchans, nchans,
1641 hc->ieee, hc->freq, hc->maxTxPow, 0, bands);
1642 }
1643}
1644
1645static int
1646bwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
1647 const struct ieee80211_bpf_params *params)
1648{
1649 struct ieee80211com *ic = ni->ni_ic;
1650 struct bwn_softc *sc = ic->ic_softc;
1651 struct bwn_mac *mac = sc->sc_curmac;
1652 int error;
1653
1654 if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0 ||
1655 mac->mac_status < BWN_MAC_STATUS_STARTED) {
1656 m_freem(m);
1657 return (ENETDOWN);
1658 }
1659
1660 BWN_LOCK(sc);
1661 if (bwn_tx_isfull(sc, m)) {
1662 m_freem(m);
1663 BWN_UNLOCK(sc);
1664 return (ENOBUFS);
1665 }
1666
1667 error = bwn_tx_start(sc, ni, m);
1668 if (error == 0)
1669 sc->sc_watchdog_timer = 5;
1670 BWN_UNLOCK(sc);
1671 return (error);
1672}
1673
1674/*
1675 * Callback from the 802.11 layer to update the slot time
1676 * based on the current setting. We use it to notify the
1677 * firmware of ERP changes and the f/w takes care of things
1678 * like slot time and preamble.
1679 */
1680static void
1681bwn_updateslot(struct ieee80211com *ic)
1682{
1683 struct bwn_softc *sc = ic->ic_softc;
1684 struct bwn_mac *mac;
1685
1686 BWN_LOCK(sc);
1687 if (sc->sc_flags & BWN_FLAG_RUNNING) {
1688 mac = (struct bwn_mac *)sc->sc_curmac;
1689 bwn_set_slot_time(mac, IEEE80211_GET_SLOTTIME(ic));
1690 }
1691 BWN_UNLOCK(sc);
1692}
1693
1694/*
1695 * Callback from the 802.11 layer after a promiscuous mode change.
1696 * Note this interface does not check the operating mode as this
1697 * is an internal callback and we are expected to honor the current
1698 * state (e.g. this is used for setting the interface in promiscuous
1699 * mode when operating in hostap mode to do ACS).
1700 */
1701static void
1702bwn_update_promisc(struct ieee80211com *ic)
1703{
1704 struct bwn_softc *sc = ic->ic_softc;
1705 struct bwn_mac *mac = sc->sc_curmac;
1706
1707 BWN_LOCK(sc);
1708 mac = sc->sc_curmac;
1709 if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
1710 if (ic->ic_promisc > 0)
1711 sc->sc_filters |= BWN_MACCTL_PROMISC;
1712 else
1713 sc->sc_filters &= ~BWN_MACCTL_PROMISC;
1714 bwn_set_opmode(mac);
1715 }
1716 BWN_UNLOCK(sc);
1717}
1718
1719/*
1720 * Callback from the 802.11 layer to update WME parameters.
1721 */
1722static int
1723bwn_wme_update(struct ieee80211com *ic)
1724{
1725 struct bwn_softc *sc = ic->ic_softc;
1726 struct bwn_mac *mac = sc->sc_curmac;
1727 struct wmeParams *wmep;
1728 int i;
1729
1730 BWN_LOCK(sc);
1731 mac = sc->sc_curmac;
1732 if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
1733 bwn_mac_suspend(mac);
1734 for (i = 0; i < N(sc->sc_wmeParams); i++) {
1735 wmep = &ic->ic_wme.wme_chanParams.cap_wmeParams[i];
1736 bwn_wme_loadparams(mac, wmep, bwn_wme_shm_offsets[i]);
1737 }
1738 bwn_mac_enable(mac);
1739 }
1740 BWN_UNLOCK(sc);
1741 return (0);
1742}
1743
1744static void
1745bwn_scan_start(struct ieee80211com *ic)
1746{
1747 struct bwn_softc *sc = ic->ic_softc;
1748 struct bwn_mac *mac;
1749
1750 BWN_LOCK(sc);
1751 mac = sc->sc_curmac;
1752 if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
1753 sc->sc_filters |= BWN_MACCTL_BEACON_PROMISC;
1754 bwn_set_opmode(mac);
1755 /* disable CFP update during scan */
1756 bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_SKIP_CFP_UPDATE);
1757 }
1758 BWN_UNLOCK(sc);
1759}
1760
1761static void
1762bwn_scan_end(struct ieee80211com *ic)
1763{
1764 struct bwn_softc *sc = ic->ic_softc;
1765 struct bwn_mac *mac;
1766
1767 BWN_LOCK(sc);
1768 mac = sc->sc_curmac;
1769 if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
1770 sc->sc_filters &= ~BWN_MACCTL_BEACON_PROMISC;
1771 bwn_set_opmode(mac);
1772 bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_SKIP_CFP_UPDATE);
1773 }
1774 BWN_UNLOCK(sc);
1775}
1776
1777static void
1778bwn_set_channel(struct ieee80211com *ic)
1779{
1780 struct bwn_softc *sc = ic->ic_softc;
1781 struct bwn_mac *mac = sc->sc_curmac;
1782 struct bwn_phy *phy = &mac->mac_phy;
1783 int chan, error;
1784
1785 BWN_LOCK(sc);
1786
1787 error = bwn_switch_band(sc, ic->ic_curchan);
1788 if (error)
1789 goto fail;
1790 bwn_mac_suspend(mac);
1791 bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
1792 chan = ieee80211_chan2ieee(ic, ic->ic_curchan);
1793 if (chan != phy->chan)
1794 bwn_switch_channel(mac, chan);
1795
1796 /* TX power level */
1797 if (ic->ic_curchan->ic_maxpower != 0 &&
1798 ic->ic_curchan->ic_maxpower != phy->txpower) {
1799 phy->txpower = ic->ic_curchan->ic_maxpower / 2;
1800 bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME |
1801 BWN_TXPWR_IGNORE_TSSI);
1802 }
1803
1804 bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
1805 if (phy->set_antenna)
1806 phy->set_antenna(mac, BWN_ANT_DEFAULT);
1807
1808 if (sc->sc_rf_enabled != phy->rf_on) {
1809 if (sc->sc_rf_enabled) {
1810 bwn_rf_turnon(mac);
1811 if (!(mac->mac_flags & BWN_MAC_FLAG_RADIO_ON))
1812 device_printf(sc->sc_dev,
1813 "please turn on the RF switch\n");
1814 } else
1815 bwn_rf_turnoff(mac);
1816 }
1817
1818 bwn_mac_enable(mac);
1819
1820fail:
1821 /*
1822 * Setup radio tap channel freq and flags
1823 */
1824 sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq =
1825 htole16(ic->ic_curchan->ic_freq);
1826 sc->sc_tx_th.wt_chan_flags = sc->sc_rx_th.wr_chan_flags =
1827 htole16(ic->ic_curchan->ic_flags & 0xffff);
1828
1829 BWN_UNLOCK(sc);
1830}
1831
1832static struct ieee80211vap *
1833bwn_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
1834 enum ieee80211_opmode opmode, int flags,
1835 const uint8_t bssid[IEEE80211_ADDR_LEN],
1836 const uint8_t mac[IEEE80211_ADDR_LEN])
1837{
1838 struct ieee80211vap *vap;
1839 struct bwn_vap *bvp;
1840
1841 switch (opmode) {
1842 case IEEE80211_M_HOSTAP:
1843 case IEEE80211_M_MBSS:
1844 case IEEE80211_M_STA:
1845 case IEEE80211_M_WDS:
1846 case IEEE80211_M_MONITOR:
1847 case IEEE80211_M_IBSS:
1848 case IEEE80211_M_AHDEMO:
1849 break;
1850 default:
1851 return (NULL);
1852 }
1853
1854 bvp = malloc(sizeof(struct bwn_vap), M_80211_VAP, M_WAITOK | M_ZERO);
1855 vap = &bvp->bv_vap;
1856 ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid);
1857 /* override with driver methods */
1858 bvp->bv_newstate = vap->iv_newstate;
1859 vap->iv_newstate = bwn_newstate;
1860
1861 /* override max aid so sta's cannot assoc when we're out of sta id's */
1862 vap->iv_max_aid = BWN_STAID_MAX;
1863
1864 ieee80211_ratectl_init(vap);
1865
1866 /* complete setup */
1867 ieee80211_vap_attach(vap, ieee80211_media_change,
1868 ieee80211_media_status, mac);
1869 return (vap);
1870}
1871
1872static void
1873bwn_vap_delete(struct ieee80211vap *vap)
1874{
1875 struct bwn_vap *bvp = BWN_VAP(vap);
1876
1877 ieee80211_ratectl_deinit(vap);
1878 ieee80211_vap_detach(vap);
1879 free(bvp, M_80211_VAP);
1880}
1881
1882static int
1883bwn_init(struct bwn_softc *sc)
1884{
1885 struct bwn_mac *mac;
1886 int error;
1887
1888 BWN_ASSERT_LOCKED(sc);
1889
1890 DPRINTF(sc, BWN_DEBUG_RESET, "%s: called\n", __func__);
1891
1892 bzero(sc->sc_bssid, IEEE80211_ADDR_LEN);
1893 sc->sc_flags |= BWN_FLAG_NEED_BEACON_TP;
1894 sc->sc_filters = 0;
1895 bwn_wme_clear(sc);
1896 sc->sc_beacons[0] = sc->sc_beacons[1] = 0;
1897 sc->sc_rf_enabled = 1;
1898
1899 mac = sc->sc_curmac;
1900 if (mac->mac_status == BWN_MAC_STATUS_UNINIT) {
1901 error = bwn_core_init(mac);
1902 if (error != 0)
1903 return (error);
1904 }
1905 if (mac->mac_status == BWN_MAC_STATUS_INITED)
1906 bwn_core_start(mac);
1907
1908 bwn_set_opmode(mac);
1909 bwn_set_pretbtt(mac);
1910 bwn_spu_setdelay(mac, 0);
1911 bwn_set_macaddr(mac);
1912
1913 sc->sc_flags |= BWN_FLAG_RUNNING;
1914 callout_reset(&sc->sc_rfswitch_ch, hz, bwn_rfswitch, sc);
1915 callout_reset(&sc->sc_watchdog_ch, hz, bwn_watchdog, sc);
1916
1917 return (0);
1918}
1919
1920static void
1921bwn_stop(struct bwn_softc *sc)
1922{
1923 struct bwn_mac *mac = sc->sc_curmac;
1924
1925 BWN_ASSERT_LOCKED(sc);
1926
1927 DPRINTF(sc, BWN_DEBUG_RESET, "%s: called\n", __func__);
1928
1929 if (mac->mac_status >= BWN_MAC_STATUS_INITED) {
1930 /* XXX FIXME opmode not based on VAP */
1931 bwn_set_opmode(mac);
1932 bwn_set_macaddr(mac);
1933 }
1934
1935 if (mac->mac_status >= BWN_MAC_STATUS_STARTED)
1936 bwn_core_stop(mac);
1937
1938 callout_stop(&sc->sc_led_blink_ch);
1939 sc->sc_led_blinking = 0;
1940
1941 bwn_core_exit(mac);
1942 sc->sc_rf_enabled = 0;
1943
1944 sc->sc_flags &= ~BWN_FLAG_RUNNING;
1945}
1946
1947static void
1948bwn_wme_clear(struct bwn_softc *sc)
1949{
1950#define MS(_v, _f) (((_v) & _f) >> _f##_S)
1951 struct wmeParams *p;
1952 unsigned int i;
1953
1954 KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
1955 ("%s:%d: fail", __func__, __LINE__));
1956
1957 for (i = 0; i < N(sc->sc_wmeParams); i++) {
1958 p = &(sc->sc_wmeParams[i]);
1959
1960 switch (bwn_wme_shm_offsets[i]) {
1961 case BWN_WME_VOICE:
1962 p->wmep_txopLimit = 0;
1963 p->wmep_aifsn = 2;
1964 /* XXX FIXME: log2(cwmin) */
1965 p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
1966 p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
1967 break;
1968 case BWN_WME_VIDEO:
1969 p->wmep_txopLimit = 0;
1970 p->wmep_aifsn = 2;
1971 /* XXX FIXME: log2(cwmin) */
1972 p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
1973 p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
1974 break;
1975 case BWN_WME_BESTEFFORT:
1976 p->wmep_txopLimit = 0;
1977 p->wmep_aifsn = 3;
1978 /* XXX FIXME: log2(cwmin) */
1979 p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
1980 p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
1981 break;
1982 case BWN_WME_BACKGROUND:
1983 p->wmep_txopLimit = 0;
1984 p->wmep_aifsn = 7;
1985 /* XXX FIXME: log2(cwmin) */
1986 p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
1987 p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
1988 break;
1989 default:
1990 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
1991 }
1992 }
1993}
1994
1995static int
1996bwn_core_init(struct bwn_mac *mac)
1997{
1998 struct bwn_softc *sc = mac->mac_sc;
1999 uint64_t hf;
2000 int error;
2001
2002 KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
2003 ("%s:%d: fail", __func__, __LINE__));
2004
2005 siba_powerup(sc->sc_dev, 0);
2006 if (!siba_dev_isup(sc->sc_dev))
2007 bwn_reset_core(mac, mac->mac_phy.gmode);
2008
2009 mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
2010 mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
2011 mac->mac_phy.hwpctl = (bwn_hwpctl) ? 1 : 0;
2012 BWN_GETTIME(mac->mac_phy.nexttime);
2013 mac->mac_phy.txerrors = BWN_TXERROR_MAX;
2014 bzero(&mac->mac_stats, sizeof(mac->mac_stats));
2015 mac->mac_stats.link_noise = -95;
2016 mac->mac_reason_intr = 0;
2017 bzero(mac->mac_reason, sizeof(mac->mac_reason));
2018 mac->mac_intr_mask = BWN_INTR_MASKTEMPLATE;
2019#ifdef BWN_DEBUG
2020 if (sc->sc_debug & BWN_DEBUG_XMIT)
2021 mac->mac_intr_mask &= ~BWN_INTR_PHY_TXERR;
2022#endif
2023 mac->mac_suspended = 1;
2024 mac->mac_task_state = 0;
2025 memset(&mac->mac_noise, 0, sizeof(mac->mac_noise));
2026
2027 mac->mac_phy.init_pre(mac);
2028
2029 siba_pcicore_intr(sc->sc_dev);
2030
2031 siba_fix_imcfglobug(sc->sc_dev);
2032 bwn_bt_disable(mac);
2033 if (mac->mac_phy.prepare_hw) {
2034 error = mac->mac_phy.prepare_hw(mac);
2035 if (error)
2036 goto fail0;
2037 }
2038 error = bwn_chip_init(mac);
2039 if (error)
2040 goto fail0;
2041 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_COREREV,
2042 siba_get_revid(sc->sc_dev));
2043 hf = bwn_hf_read(mac);
2044 if (mac->mac_phy.type == BWN_PHYTYPE_G) {
2045 hf |= BWN_HF_GPHY_SYM_WORKAROUND;
2046 if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
2047 hf |= BWN_HF_PAGAINBOOST_OFDM_ON;
2048 if (mac->mac_phy.rev == 1)
2049 hf |= BWN_HF_GPHY_DC_CANCELFILTER;
2050 }
2051 if (mac->mac_phy.rf_ver == 0x2050) {
2052 if (mac->mac_phy.rf_rev < 6)
2053 hf |= BWN_HF_FORCE_VCO_RECALC;
2054 if (mac->mac_phy.rf_rev == 6)
2055 hf |= BWN_HF_4318_TSSI;
2056 }
2057 if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW)
2058 hf |= BWN_HF_SLOWCLOCK_REQ_OFF;
2059 if ((siba_get_type(sc->sc_dev) == SIBA_TYPE_PCI) &&
2060 (siba_get_pcicore_revid(sc->sc_dev) <= 10))
2061 hf |= BWN_HF_PCI_SLOWCLOCK_WORKAROUND;
2062 hf &= ~BWN_HF_SKIP_CFP_UPDATE;
2063 bwn_hf_write(mac, hf);
2064
2065 bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
2066 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SHORT_RETRY_FALLBACK, 3);
2067 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_LONG_RETRY_FALLBACK, 2);
2068 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_MAXTIME, 1);
2069
2070 bwn_rate_init(mac);
2071 bwn_set_phytxctl(mac);
2072
2073 bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MIN,
2074 (mac->mac_phy.type == BWN_PHYTYPE_B) ? 0x1f : 0xf);
2075 bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MAX, 0x3ff);
2076
2077 if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
2078 bwn_pio_init(mac);
2079 else
2080 bwn_dma_init(mac);
2081 bwn_wme_init(mac);
2082 bwn_spu_setdelay(mac, 1);
2083 bwn_bt_enable(mac);
2084
2085 siba_powerup(sc->sc_dev,
2086 !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW));
2087 bwn_set_macaddr(mac);
2088 bwn_crypt_init(mac);
2089
2090 /* XXX LED initializatin */
2091
2092 mac->mac_status = BWN_MAC_STATUS_INITED;
2093
2094 return (error);
2095
2096fail0:
2097 siba_powerdown(sc->sc_dev);
2098 KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
2099 ("%s:%d: fail", __func__, __LINE__));
2100 return (error);
2101}
2102
2103static void
2104bwn_core_start(struct bwn_mac *mac)
2105{
2106 struct bwn_softc *sc = mac->mac_sc;
2107 uint32_t tmp;
2108
2109 KASSERT(mac->mac_status == BWN_MAC_STATUS_INITED,
2110 ("%s:%d: fail", __func__, __LINE__));
2111
2112 if (siba_get_revid(sc->sc_dev) < 5)
2113 return;
2114
2115 while (1) {
2116 tmp = BWN_READ_4(mac, BWN_XMITSTAT_0);
2117 if (!(tmp & 0x00000001))
2118 break;
2119 tmp = BWN_READ_4(mac, BWN_XMITSTAT_1);
2120 }
2121
2122 bwn_mac_enable(mac);
2123 BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
2124 callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
2125
2126 mac->mac_status = BWN_MAC_STATUS_STARTED;
2127}
2128
2129static void
2130bwn_core_exit(struct bwn_mac *mac)
2131{
2132 struct bwn_softc *sc = mac->mac_sc;
2133 uint32_t macctl;
2134
2135 BWN_ASSERT_LOCKED(mac->mac_sc);
2136
2137 KASSERT(mac->mac_status <= BWN_MAC_STATUS_INITED,
2138 ("%s:%d: fail", __func__, __LINE__));
2139
2140 if (mac->mac_status != BWN_MAC_STATUS_INITED)
2141 return;
2142 mac->mac_status = BWN_MAC_STATUS_UNINIT;
2143
2144 macctl = BWN_READ_4(mac, BWN_MACCTL);
2145 macctl &= ~BWN_MACCTL_MCODE_RUN;
2146 macctl |= BWN_MACCTL_MCODE_JMP0;
2147 BWN_WRITE_4(mac, BWN_MACCTL, macctl);
2148
2149 bwn_dma_stop(mac);
2150 bwn_pio_stop(mac);
2151 bwn_chip_exit(mac);
2152 mac->mac_phy.switch_analog(mac, 0);
2153 siba_dev_down(sc->sc_dev, 0);
2154 siba_powerdown(sc->sc_dev);
2155}
2156
2157static void
2158bwn_bt_disable(struct bwn_mac *mac)
2159{
2160 struct bwn_softc *sc = mac->mac_sc;
2161
2162 (void)sc;
2163 /* XXX do nothing yet */
2164}
2165
2166static int
2167bwn_chip_init(struct bwn_mac *mac)
2168{
2169 struct bwn_softc *sc = mac->mac_sc;
2170 struct bwn_phy *phy = &mac->mac_phy;
2171 uint32_t macctl;
2172 int error;
2173
2174 macctl = BWN_MACCTL_IHR_ON | BWN_MACCTL_SHM_ON | BWN_MACCTL_STA;
2175 if (phy->gmode)
2176 macctl |= BWN_MACCTL_GMODE;
2177 BWN_WRITE_4(mac, BWN_MACCTL, macctl);
2178
2179 error = bwn_fw_fillinfo(mac);
2180 if (error)
2181 return (error);
2182 error = bwn_fw_loaducode(mac);
2183 if (error)
2184 return (error);
2185
2186 error = bwn_gpio_init(mac);
2187 if (error)
2188 return (error);
2189
2190 error = bwn_fw_loadinitvals(mac);
2191 if (error) {
2192 siba_gpio_set(sc->sc_dev, 0);
2193 return (error);
2194 }
2195 phy->switch_analog(mac, 1);
2196 error = bwn_phy_init(mac);
2197 if (error) {
2198 siba_gpio_set(sc->sc_dev, 0);
2199 return (error);
2200 }
2201 if (phy->set_im)
2202 phy->set_im(mac, BWN_IMMODE_NONE);
2203 if (phy->set_antenna)
2204 phy->set_antenna(mac, BWN_ANT_DEFAULT);
2205 bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
2206
2207 if (phy->type == BWN_PHYTYPE_B)
2208 BWN_WRITE_2(mac, 0x005e, BWN_READ_2(mac, 0x005e) | 0x0004);
2209 BWN_WRITE_4(mac, 0x0100, 0x01000000);
2210 if (siba_get_revid(sc->sc_dev) < 5)
2211 BWN_WRITE_4(mac, 0x010c, 0x01000000);
2212
2213 BWN_WRITE_4(mac, BWN_MACCTL,
2214 BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_STA);
2215 BWN_WRITE_4(mac, BWN_MACCTL,
2216 BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_STA);
2217 bwn_shm_write_2(mac, BWN_SHARED, 0x0074, 0x0000);
2218
2219 bwn_set_opmode(mac);
2220 if (siba_get_revid(sc->sc_dev) < 3) {
2221 BWN_WRITE_2(mac, 0x060e, 0x0000);
2222 BWN_WRITE_2(mac, 0x0610, 0x8000);
2223 BWN_WRITE_2(mac, 0x0604, 0x0000);
2224 BWN_WRITE_2(mac, 0x0606, 0x0200);
2225 } else {
2226 BWN_WRITE_4(mac, 0x0188, 0x80000000);
2227 BWN_WRITE_4(mac, 0x018c, 0x02000000);
2228 }
2229 BWN_WRITE_4(mac, BWN_INTR_REASON, 0x00004000);
2230 BWN_WRITE_4(mac, BWN_DMA0_INTR_MASK, 0x0001dc00);
2231 BWN_WRITE_4(mac, BWN_DMA1_INTR_MASK, 0x0000dc00);
2232 BWN_WRITE_4(mac, BWN_DMA2_INTR_MASK, 0x0000dc00);
2233 BWN_WRITE_4(mac, BWN_DMA3_INTR_MASK, 0x0001dc00);
2234 BWN_WRITE_4(mac, BWN_DMA4_INTR_MASK, 0x0000dc00);
2235 BWN_WRITE_4(mac, BWN_DMA5_INTR_MASK, 0x0000dc00);
2236
2237 bwn_mac_phy_clock_set(mac, true);
2238
2239 /* SIBA powerup */
2240 /* XXX TODO: BCMA powerup */
2241 BWN_WRITE_2(mac, BWN_POWERUP_DELAY, siba_get_cc_powerdelay(sc->sc_dev));
2242 return (error);
2243}
2244
2245/* read hostflags */
2246uint64_t
2247bwn_hf_read(struct bwn_mac *mac)
2248{
2249 uint64_t ret;
2250
2251 ret = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFHI);
2252 ret <<= 16;
2253 ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFMI);
2254 ret <<= 16;
2255 ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO);
2256 return (ret);
2257}
2258
2259void
2260bwn_hf_write(struct bwn_mac *mac, uint64_t value)
2261{
2262
2263 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFLO,
2264 (value & 0x00000000ffffull));
2265 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFMI,
2266 (value & 0x0000ffff0000ull) >> 16);
2267 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFHI,
2268 (value & 0xffff00000000ULL) >> 32);
2269}
2270
2271static void
2272bwn_set_txretry(struct bwn_mac *mac, int s, int l)
2273{
2274
2275 bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_SHORT_RETRY, MIN(s, 0xf));
2276 bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_LONG_RETRY, MIN(l, 0xf));
2277}
2278
2279static void
2280bwn_rate_init(struct bwn_mac *mac)
2281{
2282
2283 switch (mac->mac_phy.type) {
2284 case BWN_PHYTYPE_A:
2285 case BWN_PHYTYPE_G:
2286 case BWN_PHYTYPE_LP:
2287 case BWN_PHYTYPE_N:
2288 bwn_rate_write(mac, BWN_OFDM_RATE_6MB, 1);
2289 bwn_rate_write(mac, BWN_OFDM_RATE_12MB, 1);
2290 bwn_rate_write(mac, BWN_OFDM_RATE_18MB, 1);
2291 bwn_rate_write(mac, BWN_OFDM_RATE_24MB, 1);
2292 bwn_rate_write(mac, BWN_OFDM_RATE_36MB, 1);
2293 bwn_rate_write(mac, BWN_OFDM_RATE_48MB, 1);
2294 bwn_rate_write(mac, BWN_OFDM_RATE_54MB, 1);
2295 if (mac->mac_phy.type == BWN_PHYTYPE_A)
2296 break;
2297 /* FALLTHROUGH */
2298 case BWN_PHYTYPE_B:
2299 bwn_rate_write(mac, BWN_CCK_RATE_1MB, 0);
2300 bwn_rate_write(mac, BWN_CCK_RATE_2MB, 0);
2301 bwn_rate_write(mac, BWN_CCK_RATE_5MB, 0);
2302 bwn_rate_write(mac, BWN_CCK_RATE_11MB, 0);
2303 break;
2304 default:
2305 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
2306 }
2307}
2308
2309static void
2310bwn_rate_write(struct bwn_mac *mac, uint16_t rate, int ofdm)
2311{
2312 uint16_t offset;
2313
2314 if (ofdm) {
2315 offset = 0x480;
2316 offset += (bwn_plcp_getofdm(rate) & 0x000f) * 2;
2317 } else {
2318 offset = 0x4c0;
2319 offset += (bwn_plcp_getcck(rate) & 0x000f) * 2;
2320 }
2321 bwn_shm_write_2(mac, BWN_SHARED, offset + 0x20,
2322 bwn_shm_read_2(mac, BWN_SHARED, offset));
2323}
2324
2325static uint8_t
2326bwn_plcp_getcck(const uint8_t bitrate)
2327{
2328
2329 switch (bitrate) {
2330 case BWN_CCK_RATE_1MB:
2331 return (0x0a);
2332 case BWN_CCK_RATE_2MB:
2333 return (0x14);
2334 case BWN_CCK_RATE_5MB:
2335 return (0x37);
2336 case BWN_CCK_RATE_11MB:
2337 return (0x6e);
2338 }
2339 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
2340 return (0);
2341}
2342
2343static uint8_t
2344bwn_plcp_getofdm(const uint8_t bitrate)
2345{
2346
2347 switch (bitrate) {
2348 case BWN_OFDM_RATE_6MB:
2349 return (0xb);
2350 case BWN_OFDM_RATE_9MB:
2351 return (0xf);
2352 case BWN_OFDM_RATE_12MB:
2353 return (0xa);
2354 case BWN_OFDM_RATE_18MB:
2355 return (0xe);
2356 case BWN_OFDM_RATE_24MB:
2357 return (0x9);
2358 case BWN_OFDM_RATE_36MB:
2359 return (0xd);
2360 case BWN_OFDM_RATE_48MB:
2361 return (0x8);
2362 case BWN_OFDM_RATE_54MB:
2363 return (0xc);
2364 }
2365 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
2366 return (0);
2367}
2368
2369static void
2370bwn_set_phytxctl(struct bwn_mac *mac)
2371{
2372 uint16_t ctl;
2373
2374 ctl = (BWN_TX_PHY_ENC_CCK | BWN_TX_PHY_ANT01AUTO |
2375 BWN_TX_PHY_TXPWR);
2376 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_BEACON_PHYCTL, ctl);
2377 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, ctl);
2378 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, ctl);
2379}
2380
2381static void
2382bwn_pio_init(struct bwn_mac *mac)
2383{
2384 struct bwn_pio *pio = &mac->mac_method.pio;
2385
2386 BWN_WRITE_4(mac, BWN_MACCTL, BWN_READ_4(mac, BWN_MACCTL)
2387 & ~BWN_MACCTL_BIGENDIAN);
2388 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RX_PADOFFSET, 0);
2389
2390 bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BK], 0);
2391 bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BE], 1);
2392 bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VI], 2);
2393 bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VO], 3);
2394 bwn_pio_set_txqueue(mac, &pio->mcast, 4);
2395 bwn_pio_setupqueue_rx(mac, &pio->rx, 0);
2396}
2397
2398static void
2399bwn_pio_set_txqueue(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
2400 int index)
2401{
2402 struct bwn_pio_txpkt *tp;
2403 struct bwn_softc *sc = mac->mac_sc;
2404 unsigned int i;
2405
2406 tq->tq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_TXQOFFSET(mac);
2407 tq->tq_index = index;
2408
2409 tq->tq_free = BWN_PIO_MAX_TXPACKETS;
2410 if (siba_get_revid(sc->sc_dev) >= 8)
2411 tq->tq_size = 1920;
2412 else {
2413 tq->tq_size = bwn_pio_read_2(mac, tq, BWN_PIO_TXQBUFSIZE);
2414 tq->tq_size -= 80;
2415 }
2416
2417 TAILQ_INIT(&tq->tq_pktlist);
2418 for (i = 0; i < N(tq->tq_pkts); i++) {
2419 tp = &(tq->tq_pkts[i]);
2420 tp->tp_index = i;
2421 tp->tp_queue = tq;
2422 TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
2423 }
2424}
2425
2426static uint16_t
2427bwn_pio_idx2base(struct bwn_mac *mac, int index)
2428{
2429 struct bwn_softc *sc = mac->mac_sc;
2430 static const uint16_t bases[] = {
2431 BWN_PIO_BASE0,
2432 BWN_PIO_BASE1,
2433 BWN_PIO_BASE2,
2434 BWN_PIO_BASE3,
2435 BWN_PIO_BASE4,
2436 BWN_PIO_BASE5,
2437 BWN_PIO_BASE6,
2438 BWN_PIO_BASE7,
2439 };
2440 static const uint16_t bases_rev11[] = {
2441 BWN_PIO11_BASE0,
2442 BWN_PIO11_BASE1,
2443 BWN_PIO11_BASE2,
2444 BWN_PIO11_BASE3,
2445 BWN_PIO11_BASE4,
2446 BWN_PIO11_BASE5,
2447 };
2448
2449 if (siba_get_revid(sc->sc_dev) >= 11) {
2450 if (index >= N(bases_rev11))
2451 device_printf(sc->sc_dev, "%s: warning\n", __func__);
2452 return (bases_rev11[index]);
2453 }
2454 if (index >= N(bases))
2455 device_printf(sc->sc_dev, "%s: warning\n", __func__);
2456 return (bases[index]);
2457}
2458
2459static void
2460bwn_pio_setupqueue_rx(struct bwn_mac *mac, struct bwn_pio_rxqueue *prq,
2461 int index)
2462{
2463 struct bwn_softc *sc = mac->mac_sc;
2464
2465 prq->prq_mac = mac;
2466 prq->prq_rev = siba_get_revid(sc->sc_dev);
2467 prq->prq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_RXQOFFSET(mac);
2468 bwn_dma_rxdirectfifo(mac, index, 1);
2469}
2470
2471static void
2472bwn_destroy_pioqueue_tx(struct bwn_pio_txqueue *tq)
2473{
2474 if (tq == NULL)
2475 return;
2476 bwn_pio_cancel_tx_packets(tq);
2477}
2478
2479static void
2480bwn_destroy_queue_tx(struct bwn_pio_txqueue *pio)
2481{
2482
2483 bwn_destroy_pioqueue_tx(pio);
2484}
2485
2486static uint16_t
2487bwn_pio_read_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
2488 uint16_t offset)
2489{
2490
2491 return (BWN_READ_2(mac, tq->tq_base + offset));
2492}
2493
2494static void
2495bwn_dma_rxdirectfifo(struct bwn_mac *mac, int idx, uint8_t enable)
2496{
2497 uint32_t ctl;
2498 int type;
2499 uint16_t base;
2500
2501 type = bwn_dma_mask2type(bwn_dma_mask(mac));
2502 base = bwn_dma_base(type, idx);
2503 if (type == BWN_DMA_64BIT) {
2504 ctl = BWN_READ_4(mac, base + BWN_DMA64_RXCTL);
2505 ctl &= ~BWN_DMA64_RXDIRECTFIFO;
2506 if (enable)
2507 ctl |= BWN_DMA64_RXDIRECTFIFO;
2508 BWN_WRITE_4(mac, base + BWN_DMA64_RXCTL, ctl);
2509 } else {
2510 ctl = BWN_READ_4(mac, base + BWN_DMA32_RXCTL);
2511 ctl &= ~BWN_DMA32_RXDIRECTFIFO;
2512 if (enable)
2513 ctl |= BWN_DMA32_RXDIRECTFIFO;
2514 BWN_WRITE_4(mac, base + BWN_DMA32_RXCTL, ctl);
2515 }
2516}
2517
2518static uint64_t
2519bwn_dma_mask(struct bwn_mac *mac)
2520{
2521 uint32_t tmp;
2522 uint16_t base;
2523
2524 tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
2525 if (tmp & SIBA_TGSHIGH_DMA64)
2526 return (BWN_DMA_BIT_MASK(64));
2527 base = bwn_dma_base(0, 0);
2528 BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
2529 tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
2530 if (tmp & BWN_DMA32_TXADDREXT_MASK)
2531 return (BWN_DMA_BIT_MASK(32));
2532
2533 return (BWN_DMA_BIT_MASK(30));
2534}
2535
2536static int
2537bwn_dma_mask2type(uint64_t dmamask)
2538{
2539
2540 if (dmamask == BWN_DMA_BIT_MASK(30))
2541 return (BWN_DMA_30BIT);
2542 if (dmamask == BWN_DMA_BIT_MASK(32))
2543 return (BWN_DMA_32BIT);
2544 if (dmamask == BWN_DMA_BIT_MASK(64))
2545 return (BWN_DMA_64BIT);
2546 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
2547 return (BWN_DMA_30BIT);
2548}
2549
2550static void
2551bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *tq)
2552{
2553 struct bwn_pio_txpkt *tp;
2554 unsigned int i;
2555
2556 for (i = 0; i < N(tq->tq_pkts); i++) {
2557 tp = &(tq->tq_pkts[i]);
2558 if (tp->tp_m) {
2559 m_freem(tp->tp_m);
2560 tp->tp_m = NULL;
2561 }
2562 }
2563}
2564
2565static uint16_t
2566bwn_dma_base(int type, int controller_idx)
2567{
2568 static const uint16_t map64[] = {
2569 BWN_DMA64_BASE0,
2570 BWN_DMA64_BASE1,
2571 BWN_DMA64_BASE2,
2572 BWN_DMA64_BASE3,
2573 BWN_DMA64_BASE4,
2574 BWN_DMA64_BASE5,
2575 };
2576 static const uint16_t map32[] = {
2577 BWN_DMA32_BASE0,
2578 BWN_DMA32_BASE1,
2579 BWN_DMA32_BASE2,
2580 BWN_DMA32_BASE3,
2581 BWN_DMA32_BASE4,
2582 BWN_DMA32_BASE5,
2583 };
2584
2585 if (type == BWN_DMA_64BIT) {
2586 KASSERT(controller_idx >= 0 && controller_idx < N(map64),
2587 ("%s:%d: fail", __func__, __LINE__));
2588 return (map64[controller_idx]);
2589 }
2590 KASSERT(controller_idx >= 0 && controller_idx < N(map32),
2591 ("%s:%d: fail", __func__, __LINE__));
2592 return (map32[controller_idx]);
2593}
2594
2595static void
2596bwn_dma_init(struct bwn_mac *mac)
2597{
2598 struct bwn_dma *dma = &mac->mac_method.dma;
2599
2600 /* setup TX DMA channels. */
2601 bwn_dma_setup(dma->wme[WME_AC_BK]);
2602 bwn_dma_setup(dma->wme[WME_AC_BE]);
2603 bwn_dma_setup(dma->wme[WME_AC_VI]);
2604 bwn_dma_setup(dma->wme[WME_AC_VO]);
2605 bwn_dma_setup(dma->mcast);
2606 /* setup RX DMA channel. */
2607 bwn_dma_setup(dma->rx);
2608}
2609
2610static struct bwn_dma_ring *
2611bwn_dma_ringsetup(struct bwn_mac *mac, int controller_index,
2612 int for_tx, int type)
2613{
2614 struct bwn_dma *dma = &mac->mac_method.dma;
2615 struct bwn_dma_ring *dr;
2616 struct bwn_dmadesc_generic *desc;
2617 struct bwn_dmadesc_meta *mt;
2618 struct bwn_softc *sc = mac->mac_sc;
2619 int error, i;
2620
2621 dr = malloc(sizeof(*dr), M_DEVBUF, M_NOWAIT | M_ZERO);
2622 if (dr == NULL)
2623 goto out;
2624 dr->dr_numslots = BWN_RXRING_SLOTS;
2625 if (for_tx)
2626 dr->dr_numslots = BWN_TXRING_SLOTS;
2627
2628 dr->dr_meta = malloc(dr->dr_numslots * sizeof(struct bwn_dmadesc_meta),
2629 M_DEVBUF, M_NOWAIT | M_ZERO);
2630 if (dr->dr_meta == NULL)
2631 goto fail0;
2632
2633 dr->dr_type = type;
2634 dr->dr_mac = mac;
2635 dr->dr_base = bwn_dma_base(type, controller_index);
2636 dr->dr_index = controller_index;
2637 if (type == BWN_DMA_64BIT) {
2638 dr->getdesc = bwn_dma_64_getdesc;
2639 dr->setdesc = bwn_dma_64_setdesc;
2640 dr->start_transfer = bwn_dma_64_start_transfer;
2641 dr->suspend = bwn_dma_64_suspend;
2642 dr->resume = bwn_dma_64_resume;
2643 dr->get_curslot = bwn_dma_64_get_curslot;
2644 dr->set_curslot = bwn_dma_64_set_curslot;
2645 } else {
2646 dr->getdesc = bwn_dma_32_getdesc;
2647 dr->setdesc = bwn_dma_32_setdesc;
2648 dr->start_transfer = bwn_dma_32_start_transfer;
2649 dr->suspend = bwn_dma_32_suspend;
2650 dr->resume = bwn_dma_32_resume;
2651 dr->get_curslot = bwn_dma_32_get_curslot;
2652 dr->set_curslot = bwn_dma_32_set_curslot;
2653 }
2654 if (for_tx) {
2655 dr->dr_tx = 1;
2656 dr->dr_curslot = -1;
2657 } else {
2658 if (dr->dr_index == 0) {
2659 dr->dr_rx_bufsize = BWN_DMA0_RX_BUFFERSIZE;
2660 dr->dr_frameoffset = BWN_DMA0_RX_FRAMEOFFSET;
2659 switch (mac->mac_fw.fw_hdr_format) {
2660 case BWN_FW_HDR_351:
2661 case BWN_FW_HDR_410:
2662 dr->dr_rx_bufsize =
2663 BWN_DMA0_RX_BUFFERSIZE_FW351;
2664 dr->dr_frameoffset =
2665 BWN_DMA0_RX_FRAMEOFFSET_FW351;
2666 break;
2667 case BWN_FW_HDR_598:
2668 dr->dr_rx_bufsize =
2669 BWN_DMA0_RX_BUFFERSIZE_FW598;
2670 dr->dr_frameoffset =
2671 BWN_DMA0_RX_FRAMEOFFSET_FW598;
2672 break;
2673 }
2661 } else
2662 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
2663 }
2664
2665 error = bwn_dma_allocringmemory(dr);
2666 if (error)
2667 goto fail2;
2668
2669 if (for_tx) {
2670 /*
2671 * Assumption: BWN_TXRING_SLOTS can be divided by
2672 * BWN_TX_SLOTS_PER_FRAME
2673 */
2674 KASSERT(BWN_TXRING_SLOTS % BWN_TX_SLOTS_PER_FRAME == 0,
2675 ("%s:%d: fail", __func__, __LINE__));
2676
2677 dr->dr_txhdr_cache = contigmalloc(
2678 (dr->dr_numslots / BWN_TX_SLOTS_PER_FRAME) *
2674 } else
2675 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
2676 }
2677
2678 error = bwn_dma_allocringmemory(dr);
2679 if (error)
2680 goto fail2;
2681
2682 if (for_tx) {
2683 /*
2684 * Assumption: BWN_TXRING_SLOTS can be divided by
2685 * BWN_TX_SLOTS_PER_FRAME
2686 */
2687 KASSERT(BWN_TXRING_SLOTS % BWN_TX_SLOTS_PER_FRAME == 0,
2688 ("%s:%d: fail", __func__, __LINE__));
2689
2690 dr->dr_txhdr_cache = contigmalloc(
2691 (dr->dr_numslots / BWN_TX_SLOTS_PER_FRAME) *
2679 BWN_HDRSIZE(mac), M_DEVBUF, M_ZERO,
2692 BWN_MAXTXHDRSIZE, M_DEVBUF, M_ZERO,
2680 0, BUS_SPACE_MAXADDR, 8, 0);
2681 if (dr->dr_txhdr_cache == NULL) {
2682 device_printf(sc->sc_dev,
2683 "can't allocate TX header DMA memory\n");
2684 goto fail1;
2685 }
2686
2687 /*
2688 * Create TX ring DMA stuffs
2689 */
2690 error = bus_dma_tag_create(dma->parent_dtag,
2691 BWN_ALIGN, 0,
2692 BUS_SPACE_MAXADDR,
2693 BUS_SPACE_MAXADDR,
2694 NULL, NULL,
2695 BWN_HDRSIZE(mac),
2696 1,
2697 BUS_SPACE_MAXSIZE_32BIT,
2698 0,
2699 NULL, NULL,
2700 &dr->dr_txring_dtag);
2701 if (error) {
2702 device_printf(sc->sc_dev,
2703 "can't create TX ring DMA tag: TODO frees\n");
2704 goto fail2;
2705 }
2706
2707 for (i = 0; i < dr->dr_numslots; i += 2) {
2708 dr->getdesc(dr, i, &desc, &mt);
2709
2710 mt->mt_txtype = BWN_DMADESC_METATYPE_HEADER;
2711 mt->mt_m = NULL;
2712 mt->mt_ni = NULL;
2713 mt->mt_islast = 0;
2714 error = bus_dmamap_create(dr->dr_txring_dtag, 0,
2715 &mt->mt_dmap);
2716 if (error) {
2717 device_printf(sc->sc_dev,
2718 "can't create RX buf DMA map\n");
2719 goto fail2;
2720 }
2721
2722 dr->getdesc(dr, i + 1, &desc, &mt);
2723
2724 mt->mt_txtype = BWN_DMADESC_METATYPE_BODY;
2725 mt->mt_m = NULL;
2726 mt->mt_ni = NULL;
2727 mt->mt_islast = 1;
2728 error = bus_dmamap_create(dma->txbuf_dtag, 0,
2729 &mt->mt_dmap);
2730 if (error) {
2731 device_printf(sc->sc_dev,
2732 "can't create RX buf DMA map\n");
2733 goto fail2;
2734 }
2735 }
2736 } else {
2737 error = bus_dmamap_create(dma->rxbuf_dtag, 0,
2738 &dr->dr_spare_dmap);
2739 if (error) {
2740 device_printf(sc->sc_dev,
2741 "can't create RX buf DMA map\n");
2742 goto out; /* XXX wrong! */
2743 }
2744
2745 for (i = 0; i < dr->dr_numslots; i++) {
2746 dr->getdesc(dr, i, &desc, &mt);
2747
2748 error = bus_dmamap_create(dma->rxbuf_dtag, 0,
2749 &mt->mt_dmap);
2750 if (error) {
2751 device_printf(sc->sc_dev,
2752 "can't create RX buf DMA map\n");
2753 goto out; /* XXX wrong! */
2754 }
2755 error = bwn_dma_newbuf(dr, desc, mt, 1);
2756 if (error) {
2757 device_printf(sc->sc_dev,
2758 "failed to allocate RX buf\n");
2759 goto out; /* XXX wrong! */
2760 }
2761 }
2762
2763 bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
2764 BUS_DMASYNC_PREWRITE);
2765
2766 dr->dr_usedslot = dr->dr_numslots;
2767 }
2768
2769 out:
2770 return (dr);
2771
2772fail2:
2773 if (dr->dr_txhdr_cache != NULL) {
2774 contigfree(dr->dr_txhdr_cache,
2775 (dr->dr_numslots / BWN_TX_SLOTS_PER_FRAME) *
2693 0, BUS_SPACE_MAXADDR, 8, 0);
2694 if (dr->dr_txhdr_cache == NULL) {
2695 device_printf(sc->sc_dev,
2696 "can't allocate TX header DMA memory\n");
2697 goto fail1;
2698 }
2699
2700 /*
2701 * Create TX ring DMA stuffs
2702 */
2703 error = bus_dma_tag_create(dma->parent_dtag,
2704 BWN_ALIGN, 0,
2705 BUS_SPACE_MAXADDR,
2706 BUS_SPACE_MAXADDR,
2707 NULL, NULL,
2708 BWN_HDRSIZE(mac),
2709 1,
2710 BUS_SPACE_MAXSIZE_32BIT,
2711 0,
2712 NULL, NULL,
2713 &dr->dr_txring_dtag);
2714 if (error) {
2715 device_printf(sc->sc_dev,
2716 "can't create TX ring DMA tag: TODO frees\n");
2717 goto fail2;
2718 }
2719
2720 for (i = 0; i < dr->dr_numslots; i += 2) {
2721 dr->getdesc(dr, i, &desc, &mt);
2722
2723 mt->mt_txtype = BWN_DMADESC_METATYPE_HEADER;
2724 mt->mt_m = NULL;
2725 mt->mt_ni = NULL;
2726 mt->mt_islast = 0;
2727 error = bus_dmamap_create(dr->dr_txring_dtag, 0,
2728 &mt->mt_dmap);
2729 if (error) {
2730 device_printf(sc->sc_dev,
2731 "can't create RX buf DMA map\n");
2732 goto fail2;
2733 }
2734
2735 dr->getdesc(dr, i + 1, &desc, &mt);
2736
2737 mt->mt_txtype = BWN_DMADESC_METATYPE_BODY;
2738 mt->mt_m = NULL;
2739 mt->mt_ni = NULL;
2740 mt->mt_islast = 1;
2741 error = bus_dmamap_create(dma->txbuf_dtag, 0,
2742 &mt->mt_dmap);
2743 if (error) {
2744 device_printf(sc->sc_dev,
2745 "can't create RX buf DMA map\n");
2746 goto fail2;
2747 }
2748 }
2749 } else {
2750 error = bus_dmamap_create(dma->rxbuf_dtag, 0,
2751 &dr->dr_spare_dmap);
2752 if (error) {
2753 device_printf(sc->sc_dev,
2754 "can't create RX buf DMA map\n");
2755 goto out; /* XXX wrong! */
2756 }
2757
2758 for (i = 0; i < dr->dr_numslots; i++) {
2759 dr->getdesc(dr, i, &desc, &mt);
2760
2761 error = bus_dmamap_create(dma->rxbuf_dtag, 0,
2762 &mt->mt_dmap);
2763 if (error) {
2764 device_printf(sc->sc_dev,
2765 "can't create RX buf DMA map\n");
2766 goto out; /* XXX wrong! */
2767 }
2768 error = bwn_dma_newbuf(dr, desc, mt, 1);
2769 if (error) {
2770 device_printf(sc->sc_dev,
2771 "failed to allocate RX buf\n");
2772 goto out; /* XXX wrong! */
2773 }
2774 }
2775
2776 bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
2777 BUS_DMASYNC_PREWRITE);
2778
2779 dr->dr_usedslot = dr->dr_numslots;
2780 }
2781
2782 out:
2783 return (dr);
2784
2785fail2:
2786 if (dr->dr_txhdr_cache != NULL) {
2787 contigfree(dr->dr_txhdr_cache,
2788 (dr->dr_numslots / BWN_TX_SLOTS_PER_FRAME) *
2776 BWN_HDRSIZE(mac), M_DEVBUF);
2789 BWN_MAXTXHDRSIZE, M_DEVBUF);
2777 }
2778fail1:
2779 free(dr->dr_meta, M_DEVBUF);
2780fail0:
2781 free(dr, M_DEVBUF);
2782 return (NULL);
2783}
2784
2785static void
2786bwn_dma_ringfree(struct bwn_dma_ring **dr)
2787{
2788
2789 if (dr == NULL)
2790 return;
2791
2792 bwn_dma_free_descbufs(*dr);
2793 bwn_dma_free_ringmemory(*dr);
2794
2795 if ((*dr)->dr_txhdr_cache != NULL) {
2796 contigfree((*dr)->dr_txhdr_cache,
2797 ((*dr)->dr_numslots / BWN_TX_SLOTS_PER_FRAME) *
2790 }
2791fail1:
2792 free(dr->dr_meta, M_DEVBUF);
2793fail0:
2794 free(dr, M_DEVBUF);
2795 return (NULL);
2796}
2797
2798static void
2799bwn_dma_ringfree(struct bwn_dma_ring **dr)
2800{
2801
2802 if (dr == NULL)
2803 return;
2804
2805 bwn_dma_free_descbufs(*dr);
2806 bwn_dma_free_ringmemory(*dr);
2807
2808 if ((*dr)->dr_txhdr_cache != NULL) {
2809 contigfree((*dr)->dr_txhdr_cache,
2810 ((*dr)->dr_numslots / BWN_TX_SLOTS_PER_FRAME) *
2798 BWN_HDRSIZE((*dr)->dr_mac), M_DEVBUF);
2811 BWN_MAXTXHDRSIZE, M_DEVBUF);
2799 }
2800 free((*dr)->dr_meta, M_DEVBUF);
2801 free(*dr, M_DEVBUF);
2802
2803 *dr = NULL;
2804}
2805
2806static void
2807bwn_dma_32_getdesc(struct bwn_dma_ring *dr, int slot,
2808 struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
2809{
2810 struct bwn_dmadesc32 *desc;
2811
2812 *meta = &(dr->dr_meta[slot]);
2813 desc = dr->dr_ring_descbase;
2814 desc = &(desc[slot]);
2815
2816 *gdesc = (struct bwn_dmadesc_generic *)desc;
2817}
2818
2819static void
2820bwn_dma_32_setdesc(struct bwn_dma_ring *dr,
2821 struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
2822 int start, int end, int irq)
2823{
2824 struct bwn_dmadesc32 *descbase = dr->dr_ring_descbase;
2825 struct bwn_softc *sc = dr->dr_mac->mac_sc;
2826 uint32_t addr, addrext, ctl;
2827 int slot;
2828
2829 slot = (int)(&(desc->dma.dma32) - descbase);
2830 KASSERT(slot >= 0 && slot < dr->dr_numslots,
2831 ("%s:%d: fail", __func__, __LINE__));
2832
2833 addr = (uint32_t) (dmaaddr & ~SIBA_DMA_TRANSLATION_MASK);
2834 addrext = (uint32_t) (dmaaddr & SIBA_DMA_TRANSLATION_MASK) >> 30;
2835 addr |= siba_dma_translation(sc->sc_dev);
2836 ctl = bufsize & BWN_DMA32_DCTL_BYTECNT;
2837 if (slot == dr->dr_numslots - 1)
2838 ctl |= BWN_DMA32_DCTL_DTABLEEND;
2839 if (start)
2840 ctl |= BWN_DMA32_DCTL_FRAMESTART;
2841 if (end)
2842 ctl |= BWN_DMA32_DCTL_FRAMEEND;
2843 if (irq)
2844 ctl |= BWN_DMA32_DCTL_IRQ;
2845 ctl |= (addrext << BWN_DMA32_DCTL_ADDREXT_SHIFT)
2846 & BWN_DMA32_DCTL_ADDREXT_MASK;
2847
2848 desc->dma.dma32.control = htole32(ctl);
2849 desc->dma.dma32.address = htole32(addr);
2850}
2851
2852static void
2853bwn_dma_32_start_transfer(struct bwn_dma_ring *dr, int slot)
2854{
2855
2856 BWN_DMA_WRITE(dr, BWN_DMA32_TXINDEX,
2857 (uint32_t)(slot * sizeof(struct bwn_dmadesc32)));
2858}
2859
2860static void
2861bwn_dma_32_suspend(struct bwn_dma_ring *dr)
2862{
2863
2864 BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
2865 BWN_DMA_READ(dr, BWN_DMA32_TXCTL) | BWN_DMA32_TXSUSPEND);
2866}
2867
2868static void
2869bwn_dma_32_resume(struct bwn_dma_ring *dr)
2870{
2871
2872 BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
2873 BWN_DMA_READ(dr, BWN_DMA32_TXCTL) & ~BWN_DMA32_TXSUSPEND);
2874}
2875
2876static int
2877bwn_dma_32_get_curslot(struct bwn_dma_ring *dr)
2878{
2879 uint32_t val;
2880
2881 val = BWN_DMA_READ(dr, BWN_DMA32_RXSTATUS);
2882 val &= BWN_DMA32_RXDPTR;
2883
2884 return (val / sizeof(struct bwn_dmadesc32));
2885}
2886
2887static void
2888bwn_dma_32_set_curslot(struct bwn_dma_ring *dr, int slot)
2889{
2890
2891 BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX,
2892 (uint32_t) (slot * sizeof(struct bwn_dmadesc32)));
2893}
2894
2895static void
2896bwn_dma_64_getdesc(struct bwn_dma_ring *dr, int slot,
2897 struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
2898{
2899 struct bwn_dmadesc64 *desc;
2900
2901 *meta = &(dr->dr_meta[slot]);
2902 desc = dr->dr_ring_descbase;
2903 desc = &(desc[slot]);
2904
2905 *gdesc = (struct bwn_dmadesc_generic *)desc;
2906}
2907
2908static void
2909bwn_dma_64_setdesc(struct bwn_dma_ring *dr,
2910 struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
2911 int start, int end, int irq)
2912{
2913 struct bwn_dmadesc64 *descbase = dr->dr_ring_descbase;
2914 struct bwn_softc *sc = dr->dr_mac->mac_sc;
2915 int slot;
2916 uint32_t ctl0 = 0, ctl1 = 0;
2917 uint32_t addrlo, addrhi;
2918 uint32_t addrext;
2919
2920 slot = (int)(&(desc->dma.dma64) - descbase);
2921 KASSERT(slot >= 0 && slot < dr->dr_numslots,
2922 ("%s:%d: fail", __func__, __LINE__));
2923
2924 addrlo = (uint32_t) (dmaaddr & 0xffffffff);
2925 addrhi = (((uint64_t) dmaaddr >> 32) & ~SIBA_DMA_TRANSLATION_MASK);
2926 addrext = (((uint64_t) dmaaddr >> 32) & SIBA_DMA_TRANSLATION_MASK) >>
2927 30;
2928 addrhi |= (siba_dma_translation(sc->sc_dev) << 1);
2929 if (slot == dr->dr_numslots - 1)
2930 ctl0 |= BWN_DMA64_DCTL0_DTABLEEND;
2931 if (start)
2932 ctl0 |= BWN_DMA64_DCTL0_FRAMESTART;
2933 if (end)
2934 ctl0 |= BWN_DMA64_DCTL0_FRAMEEND;
2935 if (irq)
2936 ctl0 |= BWN_DMA64_DCTL0_IRQ;
2937 ctl1 |= bufsize & BWN_DMA64_DCTL1_BYTECNT;
2938 ctl1 |= (addrext << BWN_DMA64_DCTL1_ADDREXT_SHIFT)
2939 & BWN_DMA64_DCTL1_ADDREXT_MASK;
2940
2941 desc->dma.dma64.control0 = htole32(ctl0);
2942 desc->dma.dma64.control1 = htole32(ctl1);
2943 desc->dma.dma64.address_low = htole32(addrlo);
2944 desc->dma.dma64.address_high = htole32(addrhi);
2945}
2946
2947static void
2948bwn_dma_64_start_transfer(struct bwn_dma_ring *dr, int slot)
2949{
2950
2951 BWN_DMA_WRITE(dr, BWN_DMA64_TXINDEX,
2952 (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
2953}
2954
2955static void
2956bwn_dma_64_suspend(struct bwn_dma_ring *dr)
2957{
2958
2959 BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
2960 BWN_DMA_READ(dr, BWN_DMA64_TXCTL) | BWN_DMA64_TXSUSPEND);
2961}
2962
2963static void
2964bwn_dma_64_resume(struct bwn_dma_ring *dr)
2965{
2966
2967 BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
2968 BWN_DMA_READ(dr, BWN_DMA64_TXCTL) & ~BWN_DMA64_TXSUSPEND);
2969}
2970
2971static int
2972bwn_dma_64_get_curslot(struct bwn_dma_ring *dr)
2973{
2974 uint32_t val;
2975
2976 val = BWN_DMA_READ(dr, BWN_DMA64_RXSTATUS);
2977 val &= BWN_DMA64_RXSTATDPTR;
2978
2979 return (val / sizeof(struct bwn_dmadesc64));
2980}
2981
2982static void
2983bwn_dma_64_set_curslot(struct bwn_dma_ring *dr, int slot)
2984{
2985
2986 BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX,
2987 (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
2988}
2989
2990static int
2991bwn_dma_allocringmemory(struct bwn_dma_ring *dr)
2992{
2993 struct bwn_mac *mac = dr->dr_mac;
2994 struct bwn_dma *dma = &mac->mac_method.dma;
2995 struct bwn_softc *sc = mac->mac_sc;
2996 int error;
2997
2998 error = bus_dma_tag_create(dma->parent_dtag,
2999 BWN_ALIGN, 0,
3000 BUS_SPACE_MAXADDR,
3001 BUS_SPACE_MAXADDR,
3002 NULL, NULL,
3003 BWN_DMA_RINGMEMSIZE,
3004 1,
3005 BUS_SPACE_MAXSIZE_32BIT,
3006 0,
3007 NULL, NULL,
3008 &dr->dr_ring_dtag);
3009 if (error) {
3010 device_printf(sc->sc_dev,
3011 "can't create TX ring DMA tag: TODO frees\n");
3012 return (-1);
3013 }
3014
3015 error = bus_dmamem_alloc(dr->dr_ring_dtag,
3016 &dr->dr_ring_descbase, BUS_DMA_WAITOK | BUS_DMA_ZERO,
3017 &dr->dr_ring_dmap);
3018 if (error) {
3019 device_printf(sc->sc_dev,
3020 "can't allocate DMA mem: TODO frees\n");
3021 return (-1);
3022 }
3023 error = bus_dmamap_load(dr->dr_ring_dtag, dr->dr_ring_dmap,
3024 dr->dr_ring_descbase, BWN_DMA_RINGMEMSIZE,
3025 bwn_dma_ring_addr, &dr->dr_ring_dmabase, BUS_DMA_NOWAIT);
3026 if (error) {
3027 device_printf(sc->sc_dev,
3028 "can't load DMA mem: TODO free\n");
3029 return (-1);
3030 }
3031
3032 return (0);
3033}
3034
3035static void
3036bwn_dma_setup(struct bwn_dma_ring *dr)
3037{
3038 struct bwn_softc *sc = dr->dr_mac->mac_sc;
3039 uint64_t ring64;
3040 uint32_t addrext, ring32, value;
3041 uint32_t trans = siba_dma_translation(sc->sc_dev);
3042
3043 if (dr->dr_tx) {
3044 dr->dr_curslot = -1;
3045
3046 if (dr->dr_type == BWN_DMA_64BIT) {
3047 ring64 = (uint64_t)(dr->dr_ring_dmabase);
3048 addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK)
3049 >> 30;
3050 value = BWN_DMA64_TXENABLE;
3051 value |= (addrext << BWN_DMA64_TXADDREXT_SHIFT)
3052 & BWN_DMA64_TXADDREXT_MASK;
3053 BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL, value);
3054 BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO,
3055 (ring64 & 0xffffffff));
3056 BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI,
3057 ((ring64 >> 32) &
3058 ~SIBA_DMA_TRANSLATION_MASK) | (trans << 1));
3059 } else {
3060 ring32 = (uint32_t)(dr->dr_ring_dmabase);
3061 addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
3062 value = BWN_DMA32_TXENABLE;
3063 value |= (addrext << BWN_DMA32_TXADDREXT_SHIFT)
3064 & BWN_DMA32_TXADDREXT_MASK;
3065 BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL, value);
3066 BWN_DMA_WRITE(dr, BWN_DMA32_TXRING,
3067 (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
3068 }
3069 return;
3070 }
3071
3072 /*
3073 * set for RX
3074 */
3075 dr->dr_usedslot = dr->dr_numslots;
3076
3077 if (dr->dr_type == BWN_DMA_64BIT) {
3078 ring64 = (uint64_t)(dr->dr_ring_dmabase);
3079 addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK) >> 30;
3080 value = (dr->dr_frameoffset << BWN_DMA64_RXFROFF_SHIFT);
3081 value |= BWN_DMA64_RXENABLE;
3082 value |= (addrext << BWN_DMA64_RXADDREXT_SHIFT)
3083 & BWN_DMA64_RXADDREXT_MASK;
3084 BWN_DMA_WRITE(dr, BWN_DMA64_RXCTL, value);
3085 BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, (ring64 & 0xffffffff));
3086 BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI,
3087 ((ring64 >> 32) & ~SIBA_DMA_TRANSLATION_MASK)
3088 | (trans << 1));
3089 BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX, dr->dr_numslots *
3090 sizeof(struct bwn_dmadesc64));
3091 } else {
3092 ring32 = (uint32_t)(dr->dr_ring_dmabase);
3093 addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
3094 value = (dr->dr_frameoffset << BWN_DMA32_RXFROFF_SHIFT);
3095 value |= BWN_DMA32_RXENABLE;
3096 value |= (addrext << BWN_DMA32_RXADDREXT_SHIFT)
3097 & BWN_DMA32_RXADDREXT_MASK;
3098 BWN_DMA_WRITE(dr, BWN_DMA32_RXCTL, value);
3099 BWN_DMA_WRITE(dr, BWN_DMA32_RXRING,
3100 (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
3101 BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX, dr->dr_numslots *
3102 sizeof(struct bwn_dmadesc32));
3103 }
3104}
3105
3106static void
3107bwn_dma_free_ringmemory(struct bwn_dma_ring *dr)
3108{
3109
3110 bus_dmamap_unload(dr->dr_ring_dtag, dr->dr_ring_dmap);
3111 bus_dmamem_free(dr->dr_ring_dtag, dr->dr_ring_descbase,
3112 dr->dr_ring_dmap);
3113}
3114
3115static void
3116bwn_dma_cleanup(struct bwn_dma_ring *dr)
3117{
3118
3119 if (dr->dr_tx) {
3120 bwn_dma_tx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
3121 if (dr->dr_type == BWN_DMA_64BIT) {
3122 BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO, 0);
3123 BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI, 0);
3124 } else
3125 BWN_DMA_WRITE(dr, BWN_DMA32_TXRING, 0);
3126 } else {
3127 bwn_dma_rx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
3128 if (dr->dr_type == BWN_DMA_64BIT) {
3129 BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, 0);
3130 BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI, 0);
3131 } else
3132 BWN_DMA_WRITE(dr, BWN_DMA32_RXRING, 0);
3133 }
3134}
3135
3136static void
3137bwn_dma_free_descbufs(struct bwn_dma_ring *dr)
3138{
3139 struct bwn_dmadesc_generic *desc;
3140 struct bwn_dmadesc_meta *meta;
3141 struct bwn_mac *mac = dr->dr_mac;
3142 struct bwn_dma *dma = &mac->mac_method.dma;
3143 struct bwn_softc *sc = mac->mac_sc;
3144 int i;
3145
3146 if (!dr->dr_usedslot)
3147 return;
3148 for (i = 0; i < dr->dr_numslots; i++) {
3149 dr->getdesc(dr, i, &desc, &meta);
3150
3151 if (meta->mt_m == NULL) {
3152 if (!dr->dr_tx)
3153 device_printf(sc->sc_dev, "%s: not TX?\n",
3154 __func__);
3155 continue;
3156 }
3157 if (dr->dr_tx) {
3158 if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
3159 bus_dmamap_unload(dr->dr_txring_dtag,
3160 meta->mt_dmap);
3161 else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
3162 bus_dmamap_unload(dma->txbuf_dtag,
3163 meta->mt_dmap);
3164 } else
3165 bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
3166 bwn_dma_free_descbuf(dr, meta);
3167 }
3168}
3169
3170static int
3171bwn_dma_tx_reset(struct bwn_mac *mac, uint16_t base,
3172 int type)
3173{
3174 struct bwn_softc *sc = mac->mac_sc;
3175 uint32_t value;
3176 int i;
3177 uint16_t offset;
3178
3179 for (i = 0; i < 10; i++) {
3180 offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
3181 BWN_DMA32_TXSTATUS;
3182 value = BWN_READ_4(mac, base + offset);
3183 if (type == BWN_DMA_64BIT) {
3184 value &= BWN_DMA64_TXSTAT;
3185 if (value == BWN_DMA64_TXSTAT_DISABLED ||
3186 value == BWN_DMA64_TXSTAT_IDLEWAIT ||
3187 value == BWN_DMA64_TXSTAT_STOPPED)
3188 break;
3189 } else {
3190 value &= BWN_DMA32_TXSTATE;
3191 if (value == BWN_DMA32_TXSTAT_DISABLED ||
3192 value == BWN_DMA32_TXSTAT_IDLEWAIT ||
3193 value == BWN_DMA32_TXSTAT_STOPPED)
3194 break;
3195 }
3196 DELAY(1000);
3197 }
3198 offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXCTL : BWN_DMA32_TXCTL;
3199 BWN_WRITE_4(mac, base + offset, 0);
3200 for (i = 0; i < 10; i++) {
3201 offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
3202 BWN_DMA32_TXSTATUS;
3203 value = BWN_READ_4(mac, base + offset);
3204 if (type == BWN_DMA_64BIT) {
3205 value &= BWN_DMA64_TXSTAT;
3206 if (value == BWN_DMA64_TXSTAT_DISABLED) {
3207 i = -1;
3208 break;
3209 }
3210 } else {
3211 value &= BWN_DMA32_TXSTATE;
3212 if (value == BWN_DMA32_TXSTAT_DISABLED) {
3213 i = -1;
3214 break;
3215 }
3216 }
3217 DELAY(1000);
3218 }
3219 if (i != -1) {
3220 device_printf(sc->sc_dev, "%s: timed out\n", __func__);
3221 return (ENODEV);
3222 }
3223 DELAY(1000);
3224
3225 return (0);
3226}
3227
3228static int
3229bwn_dma_rx_reset(struct bwn_mac *mac, uint16_t base,
3230 int type)
3231{
3232 struct bwn_softc *sc = mac->mac_sc;
3233 uint32_t value;
3234 int i;
3235 uint16_t offset;
3236
3237 offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXCTL : BWN_DMA32_RXCTL;
3238 BWN_WRITE_4(mac, base + offset, 0);
3239 for (i = 0; i < 10; i++) {
3240 offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXSTATUS :
3241 BWN_DMA32_RXSTATUS;
3242 value = BWN_READ_4(mac, base + offset);
3243 if (type == BWN_DMA_64BIT) {
3244 value &= BWN_DMA64_RXSTAT;
3245 if (value == BWN_DMA64_RXSTAT_DISABLED) {
3246 i = -1;
3247 break;
3248 }
3249 } else {
3250 value &= BWN_DMA32_RXSTATE;
3251 if (value == BWN_DMA32_RXSTAT_DISABLED) {
3252 i = -1;
3253 break;
3254 }
3255 }
3256 DELAY(1000);
3257 }
3258 if (i != -1) {
3259 device_printf(sc->sc_dev, "%s: timed out\n", __func__);
3260 return (ENODEV);
3261 }
3262
3263 return (0);
3264}
3265
3266static void
3267bwn_dma_free_descbuf(struct bwn_dma_ring *dr,
3268 struct bwn_dmadesc_meta *meta)
3269{
3270
3271 if (meta->mt_m != NULL) {
3272 m_freem(meta->mt_m);
3273 meta->mt_m = NULL;
3274 }
3275 if (meta->mt_ni != NULL) {
3276 ieee80211_free_node(meta->mt_ni);
3277 meta->mt_ni = NULL;
3278 }
3279}
3280
3281static void
3282bwn_dma_set_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
3283{
3284 struct bwn_rxhdr4 *rxhdr;
3285 unsigned char *frame;
3286
3287 rxhdr = mtod(m, struct bwn_rxhdr4 *);
3288 rxhdr->frame_len = 0;
3289
3290 KASSERT(dr->dr_rx_bufsize >= dr->dr_frameoffset +
3291 sizeof(struct bwn_plcp6) + 2,
3292 ("%s:%d: fail", __func__, __LINE__));
3293 frame = mtod(m, char *) + dr->dr_frameoffset;
3294 memset(frame, 0xff, sizeof(struct bwn_plcp6) + 2 /* padding */);
3295}
3296
3297static uint8_t
3298bwn_dma_check_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
3299{
3300 unsigned char *f = mtod(m, char *) + dr->dr_frameoffset;
3301
3302 return ((f[0] & f[1] & f[2] & f[3] & f[4] & f[5] & f[6] & f[7])
3303 == 0xff);
3304}
3305
3306static void
3307bwn_wme_init(struct bwn_mac *mac)
3308{
3309
3310 bwn_wme_load(mac);
3311
3312 /* enable WME support. */
3313 bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_EDCF);
3314 BWN_WRITE_2(mac, BWN_IFSCTL, BWN_READ_2(mac, BWN_IFSCTL) |
3315 BWN_IFSCTL_USE_EDCF);
3316}
3317
3318static void
3319bwn_spu_setdelay(struct bwn_mac *mac, int idle)
3320{
3321 struct bwn_softc *sc = mac->mac_sc;
3322 struct ieee80211com *ic = &sc->sc_ic;
3323 uint16_t delay; /* microsec */
3324
3325 delay = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 3700 : 1050;
3326 if (ic->ic_opmode == IEEE80211_M_IBSS || idle)
3327 delay = 500;
3328 if ((mac->mac_phy.rf_ver == 0x2050) && (mac->mac_phy.rf_rev == 8))
3329 delay = max(delay, (uint16_t)2400);
3330
3331 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SPU_WAKEUP, delay);
3332}
3333
3334static void
3335bwn_bt_enable(struct bwn_mac *mac)
3336{
3337 struct bwn_softc *sc = mac->mac_sc;
3338 uint64_t hf;
3339
3340 if (bwn_bluetooth == 0)
3341 return;
3342 if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCOEXIST) == 0)
3343 return;
3344 if (mac->mac_phy.type != BWN_PHYTYPE_B && !mac->mac_phy.gmode)
3345 return;
3346
3347 hf = bwn_hf_read(mac);
3348 if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCMOD)
3349 hf |= BWN_HF_BT_COEXISTALT;
3350 else
3351 hf |= BWN_HF_BT_COEXIST;
3352 bwn_hf_write(mac, hf);
3353}
3354
3355static void
3356bwn_set_macaddr(struct bwn_mac *mac)
3357{
3358
3359 bwn_mac_write_bssid(mac);
3360 bwn_mac_setfilter(mac, BWN_MACFILTER_SELF,
3361 mac->mac_sc->sc_ic.ic_macaddr);
3362}
3363
3364static void
3365bwn_clear_keys(struct bwn_mac *mac)
3366{
3367 int i;
3368
3369 for (i = 0; i < mac->mac_max_nr_keys; i++) {
3370 KASSERT(i >= 0 && i < mac->mac_max_nr_keys,
3371 ("%s:%d: fail", __func__, __LINE__));
3372
3373 bwn_key_dowrite(mac, i, BWN_SEC_ALGO_NONE,
3374 NULL, BWN_SEC_KEYSIZE, NULL);
3375 if ((i <= 3) && !BWN_SEC_NEWAPI(mac)) {
3376 bwn_key_dowrite(mac, i + 4, BWN_SEC_ALGO_NONE,
3377 NULL, BWN_SEC_KEYSIZE, NULL);
3378 }
3379 mac->mac_key[i].keyconf = NULL;
3380 }
3381}
3382
3383static void
3384bwn_crypt_init(struct bwn_mac *mac)
3385{
3386 struct bwn_softc *sc = mac->mac_sc;
3387
3388 mac->mac_max_nr_keys = (siba_get_revid(sc->sc_dev) >= 5) ? 58 : 20;
3389 KASSERT(mac->mac_max_nr_keys <= N(mac->mac_key),
3390 ("%s:%d: fail", __func__, __LINE__));
3391 mac->mac_ktp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_KEY_TABLEP);
3392 mac->mac_ktp *= 2;
3393 if (siba_get_revid(sc->sc_dev) >= 5)
3394 BWN_WRITE_2(mac, BWN_RCMTA_COUNT, mac->mac_max_nr_keys - 8);
3395 bwn_clear_keys(mac);
3396}
3397
3398static void
3399bwn_chip_exit(struct bwn_mac *mac)
3400{
3401 struct bwn_softc *sc = mac->mac_sc;
3402
3403 bwn_phy_exit(mac);
3404 siba_gpio_set(sc->sc_dev, 0);
3405}
3406
3407static int
3408bwn_fw_fillinfo(struct bwn_mac *mac)
3409{
3410 int error;
3411
3412 error = bwn_fw_gets(mac, BWN_FWTYPE_DEFAULT);
3413 if (error == 0)
3414 return (0);
3415 error = bwn_fw_gets(mac, BWN_FWTYPE_OPENSOURCE);
3416 if (error == 0)
3417 return (0);
3418 return (error);
3419}
3420
3421static int
3422bwn_gpio_init(struct bwn_mac *mac)
3423{
3424 struct bwn_softc *sc = mac->mac_sc;
3425 uint32_t mask = 0x1f, set = 0xf, value;
3426
3427 BWN_WRITE_4(mac, BWN_MACCTL,
3428 BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GPOUT_MASK);
3429 BWN_WRITE_2(mac, BWN_GPIO_MASK,
3430 BWN_READ_2(mac, BWN_GPIO_MASK) | 0x000f);
3431
3432 if (siba_get_chipid(sc->sc_dev) == 0x4301) {
3433 mask |= 0x0060;
3434 set |= 0x0060;
3435 }
3436 if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL) {
3437 BWN_WRITE_2(mac, BWN_GPIO_MASK,
3438 BWN_READ_2(mac, BWN_GPIO_MASK) | 0x0200);
3439 mask |= 0x0200;
3440 set |= 0x0200;
3441 }
3442 if (siba_get_revid(sc->sc_dev) >= 2)
3443 mask |= 0x0010;
3444
3445 value = siba_gpio_get(sc->sc_dev);
3446 if (value == -1)
3447 return (0);
3448 siba_gpio_set(sc->sc_dev, (value & mask) | set);
3449
3450 return (0);
3451}
3452
3453static int
3454bwn_fw_loadinitvals(struct bwn_mac *mac)
3455{
3456#define GETFWOFFSET(fwp, offset) \
3457 ((const struct bwn_fwinitvals *)((const char *)fwp.fw->data + offset))
3458 const size_t hdr_len = sizeof(struct bwn_fwhdr);
3459 const struct bwn_fwhdr *hdr;
3460 struct bwn_fw *fw = &mac->mac_fw;
3461 int error;
3462
3463 hdr = (const struct bwn_fwhdr *)(fw->initvals.fw->data);
3464 error = bwn_fwinitvals_write(mac, GETFWOFFSET(fw->initvals, hdr_len),
3465 be32toh(hdr->size), fw->initvals.fw->datasize - hdr_len);
3466 if (error)
3467 return (error);
3468 if (fw->initvals_band.fw) {
3469 hdr = (const struct bwn_fwhdr *)(fw->initvals_band.fw->data);
3470 error = bwn_fwinitvals_write(mac,
3471 GETFWOFFSET(fw->initvals_band, hdr_len),
3472 be32toh(hdr->size),
3473 fw->initvals_band.fw->datasize - hdr_len);
3474 }
3475 return (error);
3476#undef GETFWOFFSET
3477}
3478
3479static int
3480bwn_phy_init(struct bwn_mac *mac)
3481{
3482 struct bwn_softc *sc = mac->mac_sc;
3483 int error;
3484
3485 mac->mac_phy.chan = mac->mac_phy.get_default_chan(mac);
3486 mac->mac_phy.rf_onoff(mac, 1);
3487 error = mac->mac_phy.init(mac);
3488 if (error) {
3489 device_printf(sc->sc_dev, "PHY init failed\n");
3490 goto fail0;
3491 }
3492 error = bwn_switch_channel(mac,
3493 mac->mac_phy.get_default_chan(mac));
3494 if (error) {
3495 device_printf(sc->sc_dev,
3496 "failed to switch default channel\n");
3497 goto fail1;
3498 }
3499 return (0);
3500fail1:
3501 if (mac->mac_phy.exit)
3502 mac->mac_phy.exit(mac);
3503fail0:
3504 mac->mac_phy.rf_onoff(mac, 0);
3505
3506 return (error);
3507}
3508
3509static void
3510bwn_set_txantenna(struct bwn_mac *mac, int antenna)
3511{
3512 uint16_t ant;
3513 uint16_t tmp;
3514
3515 ant = bwn_ant2phy(antenna);
3516
3517 /* For ACK/CTS */
3518 tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL);
3519 tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
3520 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, tmp);
3521 /* For Probe Resposes */
3522 tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL);
3523 tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
3524 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, tmp);
3525}
3526
3527static void
3528bwn_set_opmode(struct bwn_mac *mac)
3529{
3530 struct bwn_softc *sc = mac->mac_sc;
3531 struct ieee80211com *ic = &sc->sc_ic;
3532 uint32_t ctl;
3533 uint16_t cfp_pretbtt;
3534
3535 ctl = BWN_READ_4(mac, BWN_MACCTL);
3536 ctl &= ~(BWN_MACCTL_HOSTAP | BWN_MACCTL_PASS_CTL |
3537 BWN_MACCTL_PASS_BADPLCP | BWN_MACCTL_PASS_BADFCS |
3538 BWN_MACCTL_PROMISC | BWN_MACCTL_BEACON_PROMISC);
3539 ctl |= BWN_MACCTL_STA;
3540
3541 if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
3542 ic->ic_opmode == IEEE80211_M_MBSS)
3543 ctl |= BWN_MACCTL_HOSTAP;
3544 else if (ic->ic_opmode == IEEE80211_M_IBSS)
3545 ctl &= ~BWN_MACCTL_STA;
3546 ctl |= sc->sc_filters;
3547
3548 if (siba_get_revid(sc->sc_dev) <= 4)
3549 ctl |= BWN_MACCTL_PROMISC;
3550
3551 BWN_WRITE_4(mac, BWN_MACCTL, ctl);
3552
3553 cfp_pretbtt = 2;
3554 if ((ctl & BWN_MACCTL_STA) && !(ctl & BWN_MACCTL_HOSTAP)) {
3555 if (siba_get_chipid(sc->sc_dev) == 0x4306 &&
3556 siba_get_chiprev(sc->sc_dev) == 3)
3557 cfp_pretbtt = 100;
3558 else
3559 cfp_pretbtt = 50;
3560 }
3561 BWN_WRITE_2(mac, 0x612, cfp_pretbtt);
3562}
3563
3564static int
3565bwn_dma_gettype(struct bwn_mac *mac)
3566{
3567 uint32_t tmp;
3568 uint16_t base;
3569
3570 tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
3571 if (tmp & SIBA_TGSHIGH_DMA64)
3572 return (BWN_DMA_64BIT);
3573 base = bwn_dma_base(0, 0);
3574 BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
3575 tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
3576 if (tmp & BWN_DMA32_TXADDREXT_MASK)
3577 return (BWN_DMA_32BIT);
3578
3579 return (BWN_DMA_30BIT);
3580}
3581
3582static void
3583bwn_dma_ring_addr(void *arg, bus_dma_segment_t *seg, int nseg, int error)
3584{
3585 if (!error) {
3586 KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
3587 *((bus_addr_t *)arg) = seg->ds_addr;
3588 }
3589}
3590
3591void
3592bwn_dummy_transmission(struct bwn_mac *mac, int ofdm, int paon)
3593{
3594 struct bwn_phy *phy = &mac->mac_phy;
3595 struct bwn_softc *sc = mac->mac_sc;
3596 unsigned int i, max_loop;
3597 uint16_t value;
3598 uint32_t buffer[5] = {
3599 0x00000000, 0x00d40000, 0x00000000, 0x01000000, 0x00000000
3600 };
3601
3602 if (ofdm) {
3603 max_loop = 0x1e;
3604 buffer[0] = 0x000201cc;
3605 } else {
3606 max_loop = 0xfa;
3607 buffer[0] = 0x000b846e;
3608 }
3609
3610 BWN_ASSERT_LOCKED(mac->mac_sc);
3611
3612 for (i = 0; i < 5; i++)
3613 bwn_ram_write(mac, i * 4, buffer[i]);
3614
3615 BWN_WRITE_2(mac, 0x0568, 0x0000);
3616 BWN_WRITE_2(mac, 0x07c0,
3617 (siba_get_revid(sc->sc_dev) < 11) ? 0x0000 : 0x0100);
3618
3619 value = (ofdm ? 0x41 : 0x40);
3620 BWN_WRITE_2(mac, 0x050c, value);
3621
3622 if (phy->type == BWN_PHYTYPE_N || phy->type == BWN_PHYTYPE_LP ||
3623 phy->type == BWN_PHYTYPE_LCN)
3624 BWN_WRITE_2(mac, 0x0514, 0x1a02);
3625 BWN_WRITE_2(mac, 0x0508, 0x0000);
3626 BWN_WRITE_2(mac, 0x050a, 0x0000);
3627 BWN_WRITE_2(mac, 0x054c, 0x0000);
3628 BWN_WRITE_2(mac, 0x056a, 0x0014);
3629 BWN_WRITE_2(mac, 0x0568, 0x0826);
3630 BWN_WRITE_2(mac, 0x0500, 0x0000);
3631
3632 /* XXX TODO: n phy pa override? */
3633
3634 switch (phy->type) {
3635 case BWN_PHYTYPE_N:
3636 case BWN_PHYTYPE_LCN:
3637 BWN_WRITE_2(mac, 0x0502, 0x00d0);
3638 break;
3639 case BWN_PHYTYPE_LP:
3640 BWN_WRITE_2(mac, 0x0502, 0x0050);
3641 break;
3642 default:
3643 BWN_WRITE_2(mac, 0x0502, 0x0030);
3644 break;
3645 }
3646
3647 /* flush */
3648 BWN_READ_2(mac, 0x0502);
3649
3650 if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
3651 BWN_RF_WRITE(mac, 0x0051, 0x0017);
3652 for (i = 0x00; i < max_loop; i++) {
3653 value = BWN_READ_2(mac, 0x050e);
3654 if (value & 0x0080)
3655 break;
3656 DELAY(10);
3657 }
3658 for (i = 0x00; i < 0x0a; i++) {
3659 value = BWN_READ_2(mac, 0x050e);
3660 if (value & 0x0400)
3661 break;
3662 DELAY(10);
3663 }
3664 for (i = 0x00; i < 0x19; i++) {
3665 value = BWN_READ_2(mac, 0x0690);
3666 if (!(value & 0x0100))
3667 break;
3668 DELAY(10);
3669 }
3670 if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
3671 BWN_RF_WRITE(mac, 0x0051, 0x0037);
3672}
3673
3674void
3675bwn_ram_write(struct bwn_mac *mac, uint16_t offset, uint32_t val)
3676{
3677 uint32_t macctl;
3678
3679 KASSERT(offset % 4 == 0, ("%s:%d: fail", __func__, __LINE__));
3680
3681 macctl = BWN_READ_4(mac, BWN_MACCTL);
3682 if (macctl & BWN_MACCTL_BIGENDIAN)
3683 printf("TODO: need swap\n");
3684
3685 BWN_WRITE_4(mac, BWN_RAM_CONTROL, offset);
3686 BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
3687 BWN_WRITE_4(mac, BWN_RAM_DATA, val);
3688}
3689
3690void
3691bwn_mac_suspend(struct bwn_mac *mac)
3692{
3693 struct bwn_softc *sc = mac->mac_sc;
3694 int i;
3695 uint32_t tmp;
3696
3697 KASSERT(mac->mac_suspended >= 0,
3698 ("%s:%d: fail", __func__, __LINE__));
3699
3700 if (mac->mac_suspended == 0) {
3701 bwn_psctl(mac, BWN_PS_AWAKE);
3702 BWN_WRITE_4(mac, BWN_MACCTL,
3703 BWN_READ_4(mac, BWN_MACCTL)
3704 & ~BWN_MACCTL_ON);
3705 BWN_READ_4(mac, BWN_MACCTL);
3706 for (i = 35; i; i--) {
3707 tmp = BWN_READ_4(mac, BWN_INTR_REASON);
3708 if (tmp & BWN_INTR_MAC_SUSPENDED)
3709 goto out;
3710 DELAY(10);
3711 }
3712 for (i = 40; i; i--) {
3713 tmp = BWN_READ_4(mac, BWN_INTR_REASON);
3714 if (tmp & BWN_INTR_MAC_SUSPENDED)
3715 goto out;
3716 DELAY(1000);
3717 }
3718 device_printf(sc->sc_dev, "MAC suspend failed\n");
3719 }
3720out:
3721 mac->mac_suspended++;
3722}
3723
3724void
3725bwn_mac_enable(struct bwn_mac *mac)
3726{
3727 struct bwn_softc *sc = mac->mac_sc;
3728 uint16_t state;
3729
3730 state = bwn_shm_read_2(mac, BWN_SHARED,
3731 BWN_SHARED_UCODESTAT);
3732 if (state != BWN_SHARED_UCODESTAT_SUSPEND &&
3733 state != BWN_SHARED_UCODESTAT_SLEEP)
3734 device_printf(sc->sc_dev, "warn: firmware state (%d)\n", state);
3735
3736 mac->mac_suspended--;
3737 KASSERT(mac->mac_suspended >= 0,
3738 ("%s:%d: fail", __func__, __LINE__));
3739 if (mac->mac_suspended == 0) {
3740 BWN_WRITE_4(mac, BWN_MACCTL,
3741 BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_ON);
3742 BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_MAC_SUSPENDED);
3743 BWN_READ_4(mac, BWN_MACCTL);
3744 BWN_READ_4(mac, BWN_INTR_REASON);
3745 bwn_psctl(mac, 0);
3746 }
3747}
3748
3749void
3750bwn_psctl(struct bwn_mac *mac, uint32_t flags)
3751{
3752 struct bwn_softc *sc = mac->mac_sc;
3753 int i;
3754 uint16_t ucstat;
3755
3756 KASSERT(!((flags & BWN_PS_ON) && (flags & BWN_PS_OFF)),
3757 ("%s:%d: fail", __func__, __LINE__));
3758 KASSERT(!((flags & BWN_PS_AWAKE) && (flags & BWN_PS_ASLEEP)),
3759 ("%s:%d: fail", __func__, __LINE__));
3760
3761 /* XXX forcibly awake and hwps-off */
3762
3763 BWN_WRITE_4(mac, BWN_MACCTL,
3764 (BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_AWAKE) &
3765 ~BWN_MACCTL_HWPS);
3766 BWN_READ_4(mac, BWN_MACCTL);
3767 if (siba_get_revid(sc->sc_dev) >= 5) {
3768 for (i = 0; i < 100; i++) {
3769 ucstat = bwn_shm_read_2(mac, BWN_SHARED,
3770 BWN_SHARED_UCODESTAT);
3771 if (ucstat != BWN_SHARED_UCODESTAT_SLEEP)
3772 break;
3773 DELAY(10);
3774 }
3775 }
3776}
3777
3778static int
3779bwn_fw_gets(struct bwn_mac *mac, enum bwn_fwtype type)
3780{
3781 struct bwn_softc *sc = mac->mac_sc;
3782 struct bwn_fw *fw = &mac->mac_fw;
3783 const uint8_t rev = siba_get_revid(sc->sc_dev);
3784 const char *filename;
3785 uint32_t high;
3786 int error;
3787
3788 /* microcode */
3789 filename = NULL;
3790 switch (rev) {
3791 case 42:
3792 if (mac->mac_phy.type == BWN_PHYTYPE_AC)
3793 filename = "ucode42";
3794 break;
3795 case 40:
3796 if (mac->mac_phy.type == BWN_PHYTYPE_AC)
3797 filename = "ucode40";
3798 break;
3799 case 33:
3800 if (mac->mac_phy.type == BWN_PHYTYPE_LCN40)
3801 filename = "ucode33_lcn40";
3802 break;
3803 case 30:
3804 if (mac->mac_phy.type == BWN_PHYTYPE_N)
3805 filename = "ucode30_mimo";
3806 break;
3807 case 29:
3808 if (mac->mac_phy.type == BWN_PHYTYPE_HT)
3809 filename = "ucode29_mimo";
3810 break;
3811 case 26:
3812 if (mac->mac_phy.type == BWN_PHYTYPE_HT)
3813 filename = "ucode26_mimo";
3814 break;
3815 case 28:
3816 case 25:
3817 if (mac->mac_phy.type == BWN_PHYTYPE_N)
3818 filename = "ucode25_mimo";
3819 else if (mac->mac_phy.type == BWN_PHYTYPE_LCN)
3820 filename = "ucode25_lcn";
3821 break;
3822 case 24:
3823 if (mac->mac_phy.type == BWN_PHYTYPE_LCN)
3824 filename = "ucode24_lcn";
3825 break;
3826 case 23:
3827 if (mac->mac_phy.type == BWN_PHYTYPE_N)
3828 filename = "ucode16_mimo";
3829 break;
3830 case 16:
3831 case 17:
3832 case 18:
3833 case 19:
3834 if (mac->mac_phy.type == BWN_PHYTYPE_N)
3835 filename = "ucode16_mimo";
3836 else if (mac->mac_phy.type == BWN_PHYTYPE_LP)
3837 filename = "ucode16_lp";
3838 break;
3839 case 15:
3840 filename = "ucode15";
3841 break;
3842 case 14:
3843 filename = "ucode14";
3844 break;
3845 case 13:
3846 filename = "ucode13";
3847 break;
3848 case 12:
3849 case 11:
3850 filename = "ucode11";
3851 break;
3852 case 10:
3853 case 9:
3854 case 8:
3855 case 7:
3856 case 6:
3857 case 5:
3858 filename = "ucode5";
3859 break;
3860 default:
3861 device_printf(sc->sc_dev, "no ucode for rev %d\n", rev);
3862 bwn_release_firmware(mac);
3863 return (EOPNOTSUPP);
3864 }
3865
3866 device_printf(sc->sc_dev, "ucode fw: %s\n", filename);
3867 error = bwn_fw_get(mac, type, filename, &fw->ucode);
3868 if (error) {
3869 bwn_release_firmware(mac);
3870 return (error);
3871 }
3872
3873 /* PCM */
3874 KASSERT(fw->no_pcmfile == 0, ("%s:%d fail", __func__, __LINE__));
3875 if (rev >= 5 && rev <= 10) {
3876 error = bwn_fw_get(mac, type, "pcm5", &fw->pcm);
3877 if (error == ENOENT)
3878 fw->no_pcmfile = 1;
3879 else if (error) {
3880 bwn_release_firmware(mac);
3881 return (error);
3882 }
3883 } else if (rev < 11) {
3884 device_printf(sc->sc_dev, "no PCM for rev %d\n", rev);
3885 return (EOPNOTSUPP);
3886 }
3887
3888 /* initvals */
3889 high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH);
3890 switch (mac->mac_phy.type) {
3891 case BWN_PHYTYPE_A:
3892 if (rev < 5 || rev > 10)
3893 goto fail1;
3894 if (high & BWN_TGSHIGH_HAVE_2GHZ)
3895 filename = "a0g1initvals5";
3896 else
3897 filename = "a0g0initvals5";
3898 break;
3899 case BWN_PHYTYPE_G:
3900 if (rev >= 5 && rev <= 10)
3901 filename = "b0g0initvals5";
3902 else if (rev >= 13)
3903 filename = "b0g0initvals13";
3904 else
3905 goto fail1;
3906 break;
3907 case BWN_PHYTYPE_LP:
3908 if (rev == 13)
3909 filename = "lp0initvals13";
3910 else if (rev == 14)
3911 filename = "lp0initvals14";
3912 else if (rev >= 15)
3913 filename = "lp0initvals15";
3914 else
3915 goto fail1;
3916 break;
3917 case BWN_PHYTYPE_N:
3918 if (rev == 30)
3919 filename = "n16initvals30";
3920 else if (rev == 28 || rev == 25)
3921 filename = "n0initvals25";
3922 else if (rev == 24)
3923 filename = "n0initvals24";
3924 else if (rev == 23)
3925 filename = "n0initvals16";
3926 else if (rev >= 16 && rev <= 18)
3927 filename = "n0initvals16";
3928 else if (rev >= 11 && rev <= 12)
3929 filename = "n0initvals11";
3930 else
3931 goto fail1;
3932 break;
3933 default:
3934 goto fail1;
3935 }
3936 error = bwn_fw_get(mac, type, filename, &fw->initvals);
3937 if (error) {
3938 bwn_release_firmware(mac);
3939 return (error);
3940 }
3941
3942 /* bandswitch initvals */
3943 switch (mac->mac_phy.type) {
3944 case BWN_PHYTYPE_A:
3945 if (rev >= 5 && rev <= 10) {
3946 if (high & BWN_TGSHIGH_HAVE_2GHZ)
3947 filename = "a0g1bsinitvals5";
3948 else
3949 filename = "a0g0bsinitvals5";
3950 } else if (rev >= 11)
3951 filename = NULL;
3952 else
3953 goto fail1;
3954 break;
3955 case BWN_PHYTYPE_G:
3956 if (rev >= 5 && rev <= 10)
3957 filename = "b0g0bsinitvals5";
3958 else if (rev >= 11)
3959 filename = NULL;
3960 else
3961 goto fail1;
3962 break;
3963 case BWN_PHYTYPE_LP:
3964 if (rev == 13)
3965 filename = "lp0bsinitvals13";
3966 else if (rev == 14)
3967 filename = "lp0bsinitvals14";
3968 else if (rev >= 15)
3969 filename = "lp0bsinitvals15";
3970 else
3971 goto fail1;
3972 break;
3973 case BWN_PHYTYPE_N:
3974 if (rev == 30)
3975 filename = "n16bsinitvals30";
3976 else if (rev == 28 || rev == 25)
3977 filename = "n0bsinitvals25";
3978 else if (rev == 24)
3979 filename = "n0bsinitvals24";
3980 else if (rev == 23)
3981 filename = "n0bsinitvals16";
3982 else if (rev >= 16 && rev <= 18)
3983 filename = "n0bsinitvals16";
3984 else if (rev >= 11 && rev <= 12)
3985 filename = "n0bsinitvals11";
3986 else
3987 goto fail1;
3988 break;
3989 default:
3990 device_printf(sc->sc_dev, "unknown phy (%d)\n",
3991 mac->mac_phy.type);
3992 goto fail1;
3993 }
3994 error = bwn_fw_get(mac, type, filename, &fw->initvals_band);
3995 if (error) {
3996 bwn_release_firmware(mac);
3997 return (error);
3998 }
3999 return (0);
4000fail1:
4001 device_printf(sc->sc_dev, "no INITVALS for rev %d, phy.type %d\n",
4002 rev, mac->mac_phy.type);
4003 bwn_release_firmware(mac);
4004 return (EOPNOTSUPP);
4005}
4006
4007static int
4008bwn_fw_get(struct bwn_mac *mac, enum bwn_fwtype type,
4009 const char *name, struct bwn_fwfile *bfw)
4010{
4011 const struct bwn_fwhdr *hdr;
4012 struct bwn_softc *sc = mac->mac_sc;
4013 const struct firmware *fw;
4014 char namebuf[64];
4015
4016 if (name == NULL) {
4017 bwn_do_release_fw(bfw);
4018 return (0);
4019 }
4020 if (bfw->filename != NULL) {
4021 if (bfw->type == type && (strcmp(bfw->filename, name) == 0))
4022 return (0);
4023 bwn_do_release_fw(bfw);
4024 }
4025
4026 snprintf(namebuf, sizeof(namebuf), "bwn%s_v4_%s%s",
4027 (type == BWN_FWTYPE_OPENSOURCE) ? "-open" : "",
4028 (mac->mac_phy.type == BWN_PHYTYPE_LP) ? "lp_" : "", name);
4029 /* XXX Sleeping on "fwload" with the non-sleepable locks held */
4030 fw = firmware_get(namebuf);
4031 if (fw == NULL) {
4032 device_printf(sc->sc_dev, "the fw file(%s) not found\n",
4033 namebuf);
4034 return (ENOENT);
4035 }
4036 if (fw->datasize < sizeof(struct bwn_fwhdr))
4037 goto fail;
4038 hdr = (const struct bwn_fwhdr *)(fw->data);
4039 switch (hdr->type) {
4040 case BWN_FWTYPE_UCODE:
4041 case BWN_FWTYPE_PCM:
4042 if (be32toh(hdr->size) !=
4043 (fw->datasize - sizeof(struct bwn_fwhdr)))
4044 goto fail;
4045 /* FALLTHROUGH */
4046 case BWN_FWTYPE_IV:
4047 if (hdr->ver != 1)
4048 goto fail;
4049 break;
4050 default:
4051 goto fail;
4052 }
4053 bfw->filename = name;
4054 bfw->fw = fw;
4055 bfw->type = type;
4056 return (0);
4057fail:
4058 device_printf(sc->sc_dev, "the fw file(%s) format error\n", namebuf);
4059 if (fw != NULL)
4060 firmware_put(fw, FIRMWARE_UNLOAD);
4061 return (EPROTO);
4062}
4063
4064static void
4065bwn_release_firmware(struct bwn_mac *mac)
4066{
4067
4068 bwn_do_release_fw(&mac->mac_fw.ucode);
4069 bwn_do_release_fw(&mac->mac_fw.pcm);
4070 bwn_do_release_fw(&mac->mac_fw.initvals);
4071 bwn_do_release_fw(&mac->mac_fw.initvals_band);
4072}
4073
4074static void
4075bwn_do_release_fw(struct bwn_fwfile *bfw)
4076{
4077
4078 if (bfw->fw != NULL)
4079 firmware_put(bfw->fw, FIRMWARE_UNLOAD);
4080 bfw->fw = NULL;
4081 bfw->filename = NULL;
4082}
4083
4084static int
4085bwn_fw_loaducode(struct bwn_mac *mac)
4086{
4087#define GETFWOFFSET(fwp, offset) \
4088 ((const uint32_t *)((const char *)fwp.fw->data + offset))
4089#define GETFWSIZE(fwp, offset) \
4090 ((fwp.fw->datasize - offset) / sizeof(uint32_t))
4091 struct bwn_softc *sc = mac->mac_sc;
4092 const uint32_t *data;
4093 unsigned int i;
4094 uint32_t ctl;
4095 uint16_t date, fwcaps, time;
4096 int error = 0;
4097
4098 ctl = BWN_READ_4(mac, BWN_MACCTL);
4099 ctl |= BWN_MACCTL_MCODE_JMP0;
4100 KASSERT(!(ctl & BWN_MACCTL_MCODE_RUN), ("%s:%d: fail", __func__,
4101 __LINE__));
4102 BWN_WRITE_4(mac, BWN_MACCTL, ctl);
4103 for (i = 0; i < 64; i++)
4104 bwn_shm_write_2(mac, BWN_SCRATCH, i, 0);
4105 for (i = 0; i < 4096; i += 2)
4106 bwn_shm_write_2(mac, BWN_SHARED, i, 0);
4107
4108 data = GETFWOFFSET(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
4109 bwn_shm_ctlword(mac, BWN_UCODE | BWN_SHARED_AUTOINC, 0x0000);
4110 for (i = 0; i < GETFWSIZE(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
4111 i++) {
4112 BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
4113 DELAY(10);
4114 }
4115
4116 if (mac->mac_fw.pcm.fw) {
4117 data = GETFWOFFSET(mac->mac_fw.pcm, sizeof(struct bwn_fwhdr));
4118 bwn_shm_ctlword(mac, BWN_HW, 0x01ea);
4119 BWN_WRITE_4(mac, BWN_SHM_DATA, 0x00004000);
4120 bwn_shm_ctlword(mac, BWN_HW, 0x01eb);
4121 for (i = 0; i < GETFWSIZE(mac->mac_fw.pcm,
4122 sizeof(struct bwn_fwhdr)); i++) {
4123 BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
4124 DELAY(10);
4125 }
4126 }
4127
4128 BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_ALL);
4129 BWN_WRITE_4(mac, BWN_MACCTL,
4130 (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_JMP0) |
4131 BWN_MACCTL_MCODE_RUN);
4132
4133 for (i = 0; i < 21; i++) {
4134 if (BWN_READ_4(mac, BWN_INTR_REASON) == BWN_INTR_MAC_SUSPENDED)
4135 break;
4136 if (i >= 20) {
4137 device_printf(sc->sc_dev, "ucode timeout\n");
4138 error = ENXIO;
4139 goto error;
4140 }
4141 DELAY(50000);
4142 }
4143 BWN_READ_4(mac, BWN_INTR_REASON);
4144
4145 mac->mac_fw.rev = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_REV);
4146 if (mac->mac_fw.rev <= 0x128) {
4147 device_printf(sc->sc_dev, "the firmware is too old\n");
4148 error = EOPNOTSUPP;
4149 goto error;
4150 }
4151
4152 /*
4153 * Determine firmware header version; needed for TX/RX packet
4154 * handling.
4155 */
4156 if (mac->mac_fw.rev >= 598)
4157 mac->mac_fw.fw_hdr_format = BWN_FW_HDR_598;
4158 else if (mac->mac_fw.rev >= 410)
4159 mac->mac_fw.fw_hdr_format = BWN_FW_HDR_410;
4160 else
4161 mac->mac_fw.fw_hdr_format = BWN_FW_HDR_351;
4162
4163 /*
4164 * We don't support rev 598 or later; that requires
4165 * another round of changes to the TX/RX descriptor
4166 * and status layout.
4167 *
4168 * So, complain this is the case and exit out, rather
4169 * than attaching and then failing.
4170 */
4171 if (mac->mac_fw.fw_hdr_format == BWN_FW_HDR_598) {
4172 device_printf(sc->sc_dev,
4173 "firmware is too new (>=598); not supported\n");
4174 error = EOPNOTSUPP;
4175 goto error;
4176 }
4177
4178 mac->mac_fw.patch = bwn_shm_read_2(mac, BWN_SHARED,
4179 BWN_SHARED_UCODE_PATCH);
4180 date = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_DATE);
4181 mac->mac_fw.opensource = (date == 0xffff);
4182 if (bwn_wme != 0)
4183 mac->mac_flags |= BWN_MAC_FLAG_WME;
4184 mac->mac_flags |= BWN_MAC_FLAG_HWCRYPTO;
4185
4186 time = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_TIME);
4187 if (mac->mac_fw.opensource == 0) {
4188 device_printf(sc->sc_dev,
4189 "firmware version (rev %u patch %u date %#x time %#x)\n",
4190 mac->mac_fw.rev, mac->mac_fw.patch, date, time);
4191 if (mac->mac_fw.no_pcmfile)
4192 device_printf(sc->sc_dev,
4193 "no HW crypto acceleration due to pcm5\n");
4194 } else {
4195 mac->mac_fw.patch = time;
4196 fwcaps = bwn_fwcaps_read(mac);
4197 if (!(fwcaps & BWN_FWCAPS_HWCRYPTO) || mac->mac_fw.no_pcmfile) {
4198 device_printf(sc->sc_dev,
4199 "disabling HW crypto acceleration\n");
4200 mac->mac_flags &= ~BWN_MAC_FLAG_HWCRYPTO;
4201 }
4202 if (!(fwcaps & BWN_FWCAPS_WME)) {
4203 device_printf(sc->sc_dev, "disabling WME support\n");
4204 mac->mac_flags &= ~BWN_MAC_FLAG_WME;
4205 }
4206 }
4207
4208 if (BWN_ISOLDFMT(mac))
4209 device_printf(sc->sc_dev, "using old firmware image\n");
4210
4211 return (0);
4212
4213error:
4214 BWN_WRITE_4(mac, BWN_MACCTL,
4215 (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_RUN) |
4216 BWN_MACCTL_MCODE_JMP0);
4217
4218 return (error);
4219#undef GETFWSIZE
4220#undef GETFWOFFSET
4221}
4222
4223/* OpenFirmware only */
4224static uint16_t
4225bwn_fwcaps_read(struct bwn_mac *mac)
4226{
4227
4228 KASSERT(mac->mac_fw.opensource == 1,
4229 ("%s:%d: fail", __func__, __LINE__));
4230 return (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_FWCAPS));
4231}
4232
4233static int
4234bwn_fwinitvals_write(struct bwn_mac *mac, const struct bwn_fwinitvals *ivals,
4235 size_t count, size_t array_size)
4236{
4237#define GET_NEXTIV16(iv) \
4238 ((const struct bwn_fwinitvals *)((const uint8_t *)(iv) + \
4239 sizeof(uint16_t) + sizeof(uint16_t)))
4240#define GET_NEXTIV32(iv) \
4241 ((const struct bwn_fwinitvals *)((const uint8_t *)(iv) + \
4242 sizeof(uint16_t) + sizeof(uint32_t)))
4243 struct bwn_softc *sc = mac->mac_sc;
4244 const struct bwn_fwinitvals *iv;
4245 uint16_t offset;
4246 size_t i;
4247 uint8_t bit32;
4248
4249 KASSERT(sizeof(struct bwn_fwinitvals) == 6,
4250 ("%s:%d: fail", __func__, __LINE__));
4251 iv = ivals;
4252 for (i = 0; i < count; i++) {
4253 if (array_size < sizeof(iv->offset_size))
4254 goto fail;
4255 array_size -= sizeof(iv->offset_size);
4256 offset = be16toh(iv->offset_size);
4257 bit32 = (offset & BWN_FWINITVALS_32BIT) ? 1 : 0;
4258 offset &= BWN_FWINITVALS_OFFSET_MASK;
4259 if (offset >= 0x1000)
4260 goto fail;
4261 if (bit32) {
4262 if (array_size < sizeof(iv->data.d32))
4263 goto fail;
4264 array_size -= sizeof(iv->data.d32);
4265 BWN_WRITE_4(mac, offset, be32toh(iv->data.d32));
4266 iv = GET_NEXTIV32(iv);
4267 } else {
4268
4269 if (array_size < sizeof(iv->data.d16))
4270 goto fail;
4271 array_size -= sizeof(iv->data.d16);
4272 BWN_WRITE_2(mac, offset, be16toh(iv->data.d16));
4273
4274 iv = GET_NEXTIV16(iv);
4275 }
4276 }
4277 if (array_size != 0)
4278 goto fail;
4279 return (0);
4280fail:
4281 device_printf(sc->sc_dev, "initvals: invalid format\n");
4282 return (EPROTO);
4283#undef GET_NEXTIV16
4284#undef GET_NEXTIV32
4285}
4286
4287int
4288bwn_switch_channel(struct bwn_mac *mac, int chan)
4289{
4290 struct bwn_phy *phy = &(mac->mac_phy);
4291 struct bwn_softc *sc = mac->mac_sc;
4292 struct ieee80211com *ic = &sc->sc_ic;
4293 uint16_t channelcookie, savedcookie;
4294 int error;
4295
4296 if (chan == 0xffff)
4297 chan = phy->get_default_chan(mac);
4298
4299 channelcookie = chan;
4300 if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan))
4301 channelcookie |= 0x100;
4302 savedcookie = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_CHAN);
4303 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, channelcookie);
4304 error = phy->switch_channel(mac, chan);
4305 if (error)
4306 goto fail;
4307
4308 mac->mac_phy.chan = chan;
4309 DELAY(8000);
4310 return (0);
4311fail:
4312 device_printf(sc->sc_dev, "failed to switch channel\n");
4313 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, savedcookie);
4314 return (error);
4315}
4316
4317static uint16_t
4318bwn_ant2phy(int antenna)
4319{
4320
4321 switch (antenna) {
4322 case BWN_ANT0:
4323 return (BWN_TX_PHY_ANT0);
4324 case BWN_ANT1:
4325 return (BWN_TX_PHY_ANT1);
4326 case BWN_ANT2:
4327 return (BWN_TX_PHY_ANT2);
4328 case BWN_ANT3:
4329 return (BWN_TX_PHY_ANT3);
4330 case BWN_ANTAUTO:
4331 return (BWN_TX_PHY_ANT01AUTO);
4332 }
4333 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
4334 return (0);
4335}
4336
4337static void
4338bwn_wme_load(struct bwn_mac *mac)
4339{
4340 struct bwn_softc *sc = mac->mac_sc;
4341 int i;
4342
4343 KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
4344 ("%s:%d: fail", __func__, __LINE__));
4345
4346 bwn_mac_suspend(mac);
4347 for (i = 0; i < N(sc->sc_wmeParams); i++)
4348 bwn_wme_loadparams(mac, &(sc->sc_wmeParams[i]),
4349 bwn_wme_shm_offsets[i]);
4350 bwn_mac_enable(mac);
4351}
4352
4353static void
4354bwn_wme_loadparams(struct bwn_mac *mac,
4355 const struct wmeParams *p, uint16_t shm_offset)
4356{
4357#define SM(_v, _f) (((_v) << _f##_S) & _f)
4358 struct bwn_softc *sc = mac->mac_sc;
4359 uint16_t params[BWN_NR_WMEPARAMS];
4360 int slot, tmp;
4361 unsigned int i;
4362
4363 slot = BWN_READ_2(mac, BWN_RNG) &
4364 SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
4365
4366 memset(&params, 0, sizeof(params));
4367
4368 DPRINTF(sc, BWN_DEBUG_WME, "wmep_txopLimit %d wmep_logcwmin %d "
4369 "wmep_logcwmax %d wmep_aifsn %d\n", p->wmep_txopLimit,
4370 p->wmep_logcwmin, p->wmep_logcwmax, p->wmep_aifsn);
4371
4372 params[BWN_WMEPARAM_TXOP] = p->wmep_txopLimit * 32;
4373 params[BWN_WMEPARAM_CWMIN] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
4374 params[BWN_WMEPARAM_CWMAX] = SM(p->wmep_logcwmax, WME_PARAM_LOGCWMAX);
4375 params[BWN_WMEPARAM_CWCUR] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
4376 params[BWN_WMEPARAM_AIFS] = p->wmep_aifsn;
4377 params[BWN_WMEPARAM_BSLOTS] = slot;
4378 params[BWN_WMEPARAM_REGGAP] = slot + p->wmep_aifsn;
4379
4380 for (i = 0; i < N(params); i++) {
4381 if (i == BWN_WMEPARAM_STATUS) {
4382 tmp = bwn_shm_read_2(mac, BWN_SHARED,
4383 shm_offset + (i * 2));
4384 tmp |= 0x100;
4385 bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
4386 tmp);
4387 } else {
4388 bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
4389 params[i]);
4390 }
4391 }
4392}
4393
4394static void
4395bwn_mac_write_bssid(struct bwn_mac *mac)
4396{
4397 struct bwn_softc *sc = mac->mac_sc;
4398 uint32_t tmp;
4399 int i;
4400 uint8_t mac_bssid[IEEE80211_ADDR_LEN * 2];
4401
4402 bwn_mac_setfilter(mac, BWN_MACFILTER_BSSID, sc->sc_bssid);
4403 memcpy(mac_bssid, sc->sc_ic.ic_macaddr, IEEE80211_ADDR_LEN);
4404 memcpy(mac_bssid + IEEE80211_ADDR_LEN, sc->sc_bssid,
4405 IEEE80211_ADDR_LEN);
4406
4407 for (i = 0; i < N(mac_bssid); i += sizeof(uint32_t)) {
4408 tmp = (uint32_t) (mac_bssid[i + 0]);
4409 tmp |= (uint32_t) (mac_bssid[i + 1]) << 8;
4410 tmp |= (uint32_t) (mac_bssid[i + 2]) << 16;
4411 tmp |= (uint32_t) (mac_bssid[i + 3]) << 24;
4412 bwn_ram_write(mac, 0x20 + i, tmp);
4413 }
4414}
4415
4416static void
4417bwn_mac_setfilter(struct bwn_mac *mac, uint16_t offset,
4418 const uint8_t *macaddr)
4419{
4420 static const uint8_t zero[IEEE80211_ADDR_LEN] = { 0 };
4421 uint16_t data;
4422
4423 if (!mac)
4424 macaddr = zero;
4425
4426 offset |= 0x0020;
4427 BWN_WRITE_2(mac, BWN_MACFILTER_CONTROL, offset);
4428
4429 data = macaddr[0];
4430 data |= macaddr[1] << 8;
4431 BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
4432 data = macaddr[2];
4433 data |= macaddr[3] << 8;
4434 BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
4435 data = macaddr[4];
4436 data |= macaddr[5] << 8;
4437 BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
4438}
4439
4440static void
4441bwn_key_dowrite(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
4442 const uint8_t *key, size_t key_len, const uint8_t *mac_addr)
4443{
4444 uint8_t buf[BWN_SEC_KEYSIZE] = { 0, };
4445 uint8_t per_sta_keys_start = 8;
4446
4447 if (BWN_SEC_NEWAPI(mac))
4448 per_sta_keys_start = 4;
4449
4450 KASSERT(index < mac->mac_max_nr_keys,
4451 ("%s:%d: fail", __func__, __LINE__));
4452 KASSERT(key_len <= BWN_SEC_KEYSIZE,
4453 ("%s:%d: fail", __func__, __LINE__));
4454
4455 if (index >= per_sta_keys_start)
4456 bwn_key_macwrite(mac, index, NULL);
4457 if (key)
4458 memcpy(buf, key, key_len);
4459 bwn_key_write(mac, index, algorithm, buf);
4460 if (index >= per_sta_keys_start)
4461 bwn_key_macwrite(mac, index, mac_addr);
4462
4463 mac->mac_key[index].algorithm = algorithm;
4464}
4465
4466static void
4467bwn_key_macwrite(struct bwn_mac *mac, uint8_t index, const uint8_t *addr)
4468{
4469 struct bwn_softc *sc = mac->mac_sc;
4470 uint32_t addrtmp[2] = { 0, 0 };
4471 uint8_t start = 8;
4472
4473 if (BWN_SEC_NEWAPI(mac))
4474 start = 4;
4475
4476 KASSERT(index >= start,
4477 ("%s:%d: fail", __func__, __LINE__));
4478 index -= start;
4479
4480 if (addr) {
4481 addrtmp[0] = addr[0];
4482 addrtmp[0] |= ((uint32_t) (addr[1]) << 8);
4483 addrtmp[0] |= ((uint32_t) (addr[2]) << 16);
4484 addrtmp[0] |= ((uint32_t) (addr[3]) << 24);
4485 addrtmp[1] = addr[4];
4486 addrtmp[1] |= ((uint32_t) (addr[5]) << 8);
4487 }
4488
4489 if (siba_get_revid(sc->sc_dev) >= 5) {
4490 bwn_shm_write_4(mac, BWN_RCMTA, (index * 2) + 0, addrtmp[0]);
4491 bwn_shm_write_2(mac, BWN_RCMTA, (index * 2) + 1, addrtmp[1]);
4492 } else {
4493 if (index >= 8) {
4494 bwn_shm_write_4(mac, BWN_SHARED,
4495 BWN_SHARED_PSM + (index * 6) + 0, addrtmp[0]);
4496 bwn_shm_write_2(mac, BWN_SHARED,
4497 BWN_SHARED_PSM + (index * 6) + 4, addrtmp[1]);
4498 }
4499 }
4500}
4501
4502static void
4503bwn_key_write(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
4504 const uint8_t *key)
4505{
4506 unsigned int i;
4507 uint32_t offset;
4508 uint16_t kidx, value;
4509
4510 kidx = BWN_SEC_KEY2FW(mac, index);
4511 bwn_shm_write_2(mac, BWN_SHARED,
4512 BWN_SHARED_KEYIDX_BLOCK + (kidx * 2), (kidx << 4) | algorithm);
4513
4514 offset = mac->mac_ktp + (index * BWN_SEC_KEYSIZE);
4515 for (i = 0; i < BWN_SEC_KEYSIZE; i += 2) {
4516 value = key[i];
4517 value |= (uint16_t)(key[i + 1]) << 8;
4518 bwn_shm_write_2(mac, BWN_SHARED, offset + i, value);
4519 }
4520}
4521
4522static void
4523bwn_phy_exit(struct bwn_mac *mac)
4524{
4525
4526 mac->mac_phy.rf_onoff(mac, 0);
4527 if (mac->mac_phy.exit != NULL)
4528 mac->mac_phy.exit(mac);
4529}
4530
4531static void
4532bwn_dma_free(struct bwn_mac *mac)
4533{
4534 struct bwn_dma *dma;
4535
4536 if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
4537 return;
4538 dma = &mac->mac_method.dma;
4539
4540 bwn_dma_ringfree(&dma->rx);
4541 bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
4542 bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
4543 bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
4544 bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
4545 bwn_dma_ringfree(&dma->mcast);
4546}
4547
4548static void
4549bwn_core_stop(struct bwn_mac *mac)
4550{
4551 struct bwn_softc *sc = mac->mac_sc;
4552
4553 BWN_ASSERT_LOCKED(sc);
4554
4555 if (mac->mac_status < BWN_MAC_STATUS_STARTED)
4556 return;
4557
4558 callout_stop(&sc->sc_rfswitch_ch);
4559 callout_stop(&sc->sc_task_ch);
4560 callout_stop(&sc->sc_watchdog_ch);
4561 sc->sc_watchdog_timer = 0;
4562 BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
4563 BWN_READ_4(mac, BWN_INTR_MASK);
4564 bwn_mac_suspend(mac);
4565
4566 mac->mac_status = BWN_MAC_STATUS_INITED;
4567}
4568
4569static int
4570bwn_switch_band(struct bwn_softc *sc, struct ieee80211_channel *chan)
4571{
4572 struct bwn_mac *up_dev = NULL;
4573 struct bwn_mac *down_dev;
4574 struct bwn_mac *mac;
4575 int err, status;
4576 uint8_t gmode;
4577
4578 BWN_ASSERT_LOCKED(sc);
4579
4580 TAILQ_FOREACH(mac, &sc->sc_maclist, mac_list) {
4581 if (IEEE80211_IS_CHAN_2GHZ(chan) &&
4582 mac->mac_phy.supports_2ghz) {
4583 up_dev = mac;
4584 gmode = 1;
4585 } else if (IEEE80211_IS_CHAN_5GHZ(chan) &&
4586 mac->mac_phy.supports_5ghz) {
4587 up_dev = mac;
4588 gmode = 0;
4589 } else {
4590 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
4591 return (EINVAL);
4592 }
4593 if (up_dev != NULL)
4594 break;
4595 }
4596 if (up_dev == NULL) {
4597 device_printf(sc->sc_dev, "Could not find a device\n");
4598 return (ENODEV);
4599 }
4600 if (up_dev == sc->sc_curmac && sc->sc_curmac->mac_phy.gmode == gmode)
4601 return (0);
4602
4603 DPRINTF(sc, BWN_DEBUG_RF | BWN_DEBUG_PHY | BWN_DEBUG_RESET,
4604 "switching to %s-GHz band\n",
4605 IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
4606
4607 down_dev = sc->sc_curmac;
4608 status = down_dev->mac_status;
4609 if (status >= BWN_MAC_STATUS_STARTED)
4610 bwn_core_stop(down_dev);
4611 if (status >= BWN_MAC_STATUS_INITED)
4612 bwn_core_exit(down_dev);
4613
4614 if (down_dev != up_dev)
4615 bwn_phy_reset(down_dev);
4616
4617 up_dev->mac_phy.gmode = gmode;
4618 if (status >= BWN_MAC_STATUS_INITED) {
4619 err = bwn_core_init(up_dev);
4620 if (err) {
4621 device_printf(sc->sc_dev,
4622 "fatal: failed to initialize for %s-GHz\n",
4623 IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
4624 goto fail;
4625 }
4626 }
4627 if (status >= BWN_MAC_STATUS_STARTED)
4628 bwn_core_start(up_dev);
4629 KASSERT(up_dev->mac_status == status, ("%s: fail", __func__));
4630 sc->sc_curmac = up_dev;
4631
4632 return (0);
4633fail:
4634 sc->sc_curmac = NULL;
4635 return (err);
4636}
4637
4638static void
4639bwn_rf_turnon(struct bwn_mac *mac)
4640{
4641
4642 DPRINTF(mac->mac_sc, BWN_DEBUG_RESET, "%s: called\n", __func__);
4643
4644 bwn_mac_suspend(mac);
4645 mac->mac_phy.rf_onoff(mac, 1);
4646 mac->mac_phy.rf_on = 1;
4647 bwn_mac_enable(mac);
4648}
4649
4650static void
4651bwn_rf_turnoff(struct bwn_mac *mac)
4652{
4653
4654 DPRINTF(mac->mac_sc, BWN_DEBUG_RESET, "%s: called\n", __func__);
4655
4656 bwn_mac_suspend(mac);
4657 mac->mac_phy.rf_onoff(mac, 0);
4658 mac->mac_phy.rf_on = 0;
4659 bwn_mac_enable(mac);
4660}
4661
4662/*
4663 * SSB PHY reset.
4664 *
4665 * XXX TODO: BCMA PHY reset.
4666 */
4667static void
4668bwn_phy_reset(struct bwn_mac *mac)
4669{
4670 struct bwn_softc *sc = mac->mac_sc;
4671
4672 siba_write_4(sc->sc_dev, SIBA_TGSLOW,
4673 ((siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~BWN_TGSLOW_SUPPORT_G) |
4674 BWN_TGSLOW_PHYRESET) | SIBA_TGSLOW_FGC);
4675 DELAY(1000);
4676 siba_write_4(sc->sc_dev, SIBA_TGSLOW,
4677 (siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~SIBA_TGSLOW_FGC));
4678 DELAY(1000);
4679}
4680
4681static int
4682bwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
4683{
4684 struct bwn_vap *bvp = BWN_VAP(vap);
4685 struct ieee80211com *ic= vap->iv_ic;
4686 enum ieee80211_state ostate = vap->iv_state;
4687 struct bwn_softc *sc = ic->ic_softc;
4688 struct bwn_mac *mac = sc->sc_curmac;
4689 int error;
4690
4691 DPRINTF(sc, BWN_DEBUG_STATE, "%s: %s -> %s\n", __func__,
4692 ieee80211_state_name[vap->iv_state],
4693 ieee80211_state_name[nstate]);
4694
4695 error = bvp->bv_newstate(vap, nstate, arg);
4696 if (error != 0)
4697 return (error);
4698
4699 BWN_LOCK(sc);
4700
4701 bwn_led_newstate(mac, nstate);
4702
4703 /*
4704 * Clear the BSSID when we stop a STA
4705 */
4706 if (vap->iv_opmode == IEEE80211_M_STA) {
4707 if (ostate == IEEE80211_S_RUN && nstate != IEEE80211_S_RUN) {
4708 /*
4709 * Clear out the BSSID. If we reassociate to
4710 * the same AP, this will reinialize things
4711 * correctly...
4712 */
4713 if (ic->ic_opmode == IEEE80211_M_STA &&
4714 (sc->sc_flags & BWN_FLAG_INVALID) == 0) {
4715 memset(sc->sc_bssid, 0, IEEE80211_ADDR_LEN);
4716 bwn_set_macaddr(mac);
4717 }
4718 }
4719 }
4720
4721 if (vap->iv_opmode == IEEE80211_M_MONITOR ||
4722 vap->iv_opmode == IEEE80211_M_AHDEMO) {
4723 /* XXX nothing to do? */
4724 } else if (nstate == IEEE80211_S_RUN) {
4725 memcpy(sc->sc_bssid, vap->iv_bss->ni_bssid, IEEE80211_ADDR_LEN);
4726 bwn_set_opmode(mac);
4727 bwn_set_pretbtt(mac);
4728 bwn_spu_setdelay(mac, 0);
4729 bwn_set_macaddr(mac);
4730 }
4731
4732 BWN_UNLOCK(sc);
4733
4734 return (error);
4735}
4736
4737static void
4738bwn_set_pretbtt(struct bwn_mac *mac)
4739{
4740 struct bwn_softc *sc = mac->mac_sc;
4741 struct ieee80211com *ic = &sc->sc_ic;
4742 uint16_t pretbtt;
4743
4744 if (ic->ic_opmode == IEEE80211_M_IBSS)
4745 pretbtt = 2;
4746 else
4747 pretbtt = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 120 : 250;
4748 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PRETBTT, pretbtt);
4749 BWN_WRITE_2(mac, BWN_TSF_CFP_PRETBTT, pretbtt);
4750}
4751
4752static int
4753bwn_intr(void *arg)
4754{
4755 struct bwn_mac *mac = arg;
4756 struct bwn_softc *sc = mac->mac_sc;
4757 uint32_t reason;
4758
4759 if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
4760 (sc->sc_flags & BWN_FLAG_INVALID))
4761 return (FILTER_STRAY);
4762
4763 reason = BWN_READ_4(mac, BWN_INTR_REASON);
4764 if (reason == 0xffffffff) /* shared IRQ */
4765 return (FILTER_STRAY);
4766 reason &= mac->mac_intr_mask;
4767 if (reason == 0)
4768 return (FILTER_HANDLED);
4769
4770 mac->mac_reason[0] = BWN_READ_4(mac, BWN_DMA0_REASON) & 0x0001dc00;
4771 mac->mac_reason[1] = BWN_READ_4(mac, BWN_DMA1_REASON) & 0x0000dc00;
4772 mac->mac_reason[2] = BWN_READ_4(mac, BWN_DMA2_REASON) & 0x0000dc00;
4773 mac->mac_reason[3] = BWN_READ_4(mac, BWN_DMA3_REASON) & 0x0001dc00;
4774 mac->mac_reason[4] = BWN_READ_4(mac, BWN_DMA4_REASON) & 0x0000dc00;
4775 BWN_WRITE_4(mac, BWN_INTR_REASON, reason);
4776 BWN_WRITE_4(mac, BWN_DMA0_REASON, mac->mac_reason[0]);
4777 BWN_WRITE_4(mac, BWN_DMA1_REASON, mac->mac_reason[1]);
4778 BWN_WRITE_4(mac, BWN_DMA2_REASON, mac->mac_reason[2]);
4779 BWN_WRITE_4(mac, BWN_DMA3_REASON, mac->mac_reason[3]);
4780 BWN_WRITE_4(mac, BWN_DMA4_REASON, mac->mac_reason[4]);
4781
4782 /* Disable interrupts. */
4783 BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
4784
4785 mac->mac_reason_intr = reason;
4786
4787 BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
4788 BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
4789
4790 taskqueue_enqueue(sc->sc_tq, &mac->mac_intrtask);
4791 return (FILTER_HANDLED);
4792}
4793
4794static void
4795bwn_intrtask(void *arg, int npending)
4796{
4797 struct bwn_mac *mac = arg;
4798 struct bwn_softc *sc = mac->mac_sc;
4799 uint32_t merged = 0;
4800 int i, tx = 0, rx = 0;
4801
4802 BWN_LOCK(sc);
4803 if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
4804 (sc->sc_flags & BWN_FLAG_INVALID)) {
4805 BWN_UNLOCK(sc);
4806 return;
4807 }
4808
4809 for (i = 0; i < N(mac->mac_reason); i++)
4810 merged |= mac->mac_reason[i];
4811
4812 if (mac->mac_reason_intr & BWN_INTR_MAC_TXERR)
4813 device_printf(sc->sc_dev, "MAC trans error\n");
4814
4815 if (mac->mac_reason_intr & BWN_INTR_PHY_TXERR) {
4816 DPRINTF(sc, BWN_DEBUG_INTR, "%s: PHY trans error\n", __func__);
4817 mac->mac_phy.txerrors--;
4818 if (mac->mac_phy.txerrors == 0) {
4819 mac->mac_phy.txerrors = BWN_TXERROR_MAX;
4820 bwn_restart(mac, "PHY TX errors");
4821 }
4822 }
4823
4824 if (merged & (BWN_DMAINTR_FATALMASK | BWN_DMAINTR_NONFATALMASK)) {
4825 if (merged & BWN_DMAINTR_FATALMASK) {
4826 device_printf(sc->sc_dev,
4827 "Fatal DMA error: %#x %#x %#x %#x %#x %#x\n",
4828 mac->mac_reason[0], mac->mac_reason[1],
4829 mac->mac_reason[2], mac->mac_reason[3],
4830 mac->mac_reason[4], mac->mac_reason[5]);
4831 bwn_restart(mac, "DMA error");
4832 BWN_UNLOCK(sc);
4833 return;
4834 }
4835 if (merged & BWN_DMAINTR_NONFATALMASK) {
4836 device_printf(sc->sc_dev,
4837 "DMA error: %#x %#x %#x %#x %#x %#x\n",
4838 mac->mac_reason[0], mac->mac_reason[1],
4839 mac->mac_reason[2], mac->mac_reason[3],
4840 mac->mac_reason[4], mac->mac_reason[5]);
4841 }
4842 }
4843
4844 if (mac->mac_reason_intr & BWN_INTR_UCODE_DEBUG)
4845 bwn_intr_ucode_debug(mac);
4846 if (mac->mac_reason_intr & BWN_INTR_TBTT_INDI)
4847 bwn_intr_tbtt_indication(mac);
4848 if (mac->mac_reason_intr & BWN_INTR_ATIM_END)
4849 bwn_intr_atim_end(mac);
4850 if (mac->mac_reason_intr & BWN_INTR_BEACON)
4851 bwn_intr_beacon(mac);
4852 if (mac->mac_reason_intr & BWN_INTR_PMQ)
4853 bwn_intr_pmq(mac);
4854 if (mac->mac_reason_intr & BWN_INTR_NOISESAMPLE_OK)
4855 bwn_intr_noise(mac);
4856
4857 if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
4858 if (mac->mac_reason[0] & BWN_DMAINTR_RX_DONE) {
4859 bwn_dma_rx(mac->mac_method.dma.rx);
4860 rx = 1;
4861 }
4862 } else
4863 rx = bwn_pio_rx(&mac->mac_method.pio.rx);
4864
4865 KASSERT(!(mac->mac_reason[1] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
4866 KASSERT(!(mac->mac_reason[2] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
4867 KASSERT(!(mac->mac_reason[3] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
4868 KASSERT(!(mac->mac_reason[4] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
4869 KASSERT(!(mac->mac_reason[5] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
4870
4871 if (mac->mac_reason_intr & BWN_INTR_TX_OK) {
4872 bwn_intr_txeof(mac);
4873 tx = 1;
4874 }
4875
4876 BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
4877
4878 if (sc->sc_blink_led != NULL && sc->sc_led_blink) {
4879 int evt = BWN_LED_EVENT_NONE;
4880
4881 if (tx && rx) {
4882 if (sc->sc_rx_rate > sc->sc_tx_rate)
4883 evt = BWN_LED_EVENT_RX;
4884 else
4885 evt = BWN_LED_EVENT_TX;
4886 } else if (tx) {
4887 evt = BWN_LED_EVENT_TX;
4888 } else if (rx) {
4889 evt = BWN_LED_EVENT_RX;
4890 } else if (rx == 0) {
4891 evt = BWN_LED_EVENT_POLL;
4892 }
4893
4894 if (evt != BWN_LED_EVENT_NONE)
4895 bwn_led_event(mac, evt);
4896 }
4897
4898 if (mbufq_first(&sc->sc_snd) != NULL)
4899 bwn_start(sc);
4900
4901 BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
4902 BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
4903
4904 BWN_UNLOCK(sc);
4905}
4906
4907static void
4908bwn_restart(struct bwn_mac *mac, const char *msg)
4909{
4910 struct bwn_softc *sc = mac->mac_sc;
4911 struct ieee80211com *ic = &sc->sc_ic;
4912
4913 if (mac->mac_status < BWN_MAC_STATUS_INITED)
4914 return;
4915
4916 device_printf(sc->sc_dev, "HW reset: %s\n", msg);
4917 ieee80211_runtask(ic, &mac->mac_hwreset);
4918}
4919
4920static void
4921bwn_intr_ucode_debug(struct bwn_mac *mac)
4922{
4923 struct bwn_softc *sc = mac->mac_sc;
4924 uint16_t reason;
4925
4926 if (mac->mac_fw.opensource == 0)
4927 return;
4928
4929 reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG);
4930 switch (reason) {
4931 case BWN_DEBUGINTR_PANIC:
4932 bwn_handle_fwpanic(mac);
4933 break;
4934 case BWN_DEBUGINTR_DUMP_SHM:
4935 device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_SHM\n");
4936 break;
4937 case BWN_DEBUGINTR_DUMP_REGS:
4938 device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_REGS\n");
4939 break;
4940 case BWN_DEBUGINTR_MARKER:
4941 device_printf(sc->sc_dev, "BWN_DEBUGINTR_MARKER\n");
4942 break;
4943 default:
4944 device_printf(sc->sc_dev,
4945 "ucode debug unknown reason: %#x\n", reason);
4946 }
4947
4948 bwn_shm_write_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG,
4949 BWN_DEBUGINTR_ACK);
4950}
4951
4952static void
4953bwn_intr_tbtt_indication(struct bwn_mac *mac)
4954{
4955 struct bwn_softc *sc = mac->mac_sc;
4956 struct ieee80211com *ic = &sc->sc_ic;
4957
4958 if (ic->ic_opmode != IEEE80211_M_HOSTAP)
4959 bwn_psctl(mac, 0);
4960 if (ic->ic_opmode == IEEE80211_M_IBSS)
4961 mac->mac_flags |= BWN_MAC_FLAG_DFQVALID;
4962}
4963
4964static void
4965bwn_intr_atim_end(struct bwn_mac *mac)
4966{
4967
4968 if (mac->mac_flags & BWN_MAC_FLAG_DFQVALID) {
4969 BWN_WRITE_4(mac, BWN_MACCMD,
4970 BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_DFQ_VALID);
4971 mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
4972 }
4973}
4974
4975static void
4976bwn_intr_beacon(struct bwn_mac *mac)
4977{
4978 struct bwn_softc *sc = mac->mac_sc;
4979 struct ieee80211com *ic = &sc->sc_ic;
4980 uint32_t cmd, beacon0, beacon1;
4981
4982 if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
4983 ic->ic_opmode == IEEE80211_M_MBSS)
4984 return;
4985
4986 mac->mac_intr_mask &= ~BWN_INTR_BEACON;
4987
4988 cmd = BWN_READ_4(mac, BWN_MACCMD);
4989 beacon0 = (cmd & BWN_MACCMD_BEACON0_VALID);
4990 beacon1 = (cmd & BWN_MACCMD_BEACON1_VALID);
4991
4992 if (beacon0 && beacon1) {
4993 BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_BEACON);
4994 mac->mac_intr_mask |= BWN_INTR_BEACON;
4995 return;
4996 }
4997
4998 if (sc->sc_flags & BWN_FLAG_NEED_BEACON_TP) {
4999 sc->sc_flags &= ~BWN_FLAG_NEED_BEACON_TP;
5000 bwn_load_beacon0(mac);
5001 bwn_load_beacon1(mac);
5002 cmd = BWN_READ_4(mac, BWN_MACCMD);
5003 cmd |= BWN_MACCMD_BEACON0_VALID;
5004 BWN_WRITE_4(mac, BWN_MACCMD, cmd);
5005 } else {
5006 if (!beacon0) {
5007 bwn_load_beacon0(mac);
5008 cmd = BWN_READ_4(mac, BWN_MACCMD);
5009 cmd |= BWN_MACCMD_BEACON0_VALID;
5010 BWN_WRITE_4(mac, BWN_MACCMD, cmd);
5011 } else if (!beacon1) {
5012 bwn_load_beacon1(mac);
5013 cmd = BWN_READ_4(mac, BWN_MACCMD);
5014 cmd |= BWN_MACCMD_BEACON1_VALID;
5015 BWN_WRITE_4(mac, BWN_MACCMD, cmd);
5016 }
5017 }
5018}
5019
5020static void
5021bwn_intr_pmq(struct bwn_mac *mac)
5022{
5023 uint32_t tmp;
5024
5025 while (1) {
5026 tmp = BWN_READ_4(mac, BWN_PS_STATUS);
5027 if (!(tmp & 0x00000008))
5028 break;
5029 }
5030 BWN_WRITE_2(mac, BWN_PS_STATUS, 0x0002);
5031}
5032
5033static void
5034bwn_intr_noise(struct bwn_mac *mac)
5035{
5036 struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5037 uint16_t tmp;
5038 uint8_t noise[4];
5039 uint8_t i, j;
5040 int32_t average;
5041
5042 if (mac->mac_phy.type != BWN_PHYTYPE_G)
5043 return;
5044
5045 KASSERT(mac->mac_noise.noi_running, ("%s: fail", __func__));
5046 *((uint32_t *)noise) = htole32(bwn_jssi_read(mac));
5047 if (noise[0] == 0x7f || noise[1] == 0x7f || noise[2] == 0x7f ||
5048 noise[3] == 0x7f)
5049 goto new;
5050
5051 KASSERT(mac->mac_noise.noi_nsamples < 8,
5052 ("%s:%d: fail", __func__, __LINE__));
5053 i = mac->mac_noise.noi_nsamples;
5054 noise[0] = MIN(MAX(noise[0], 0), N(pg->pg_nrssi_lt) - 1);
5055 noise[1] = MIN(MAX(noise[1], 0), N(pg->pg_nrssi_lt) - 1);
5056 noise[2] = MIN(MAX(noise[2], 0), N(pg->pg_nrssi_lt) - 1);
5057 noise[3] = MIN(MAX(noise[3], 0), N(pg->pg_nrssi_lt) - 1);
5058 mac->mac_noise.noi_samples[i][0] = pg->pg_nrssi_lt[noise[0]];
5059 mac->mac_noise.noi_samples[i][1] = pg->pg_nrssi_lt[noise[1]];
5060 mac->mac_noise.noi_samples[i][2] = pg->pg_nrssi_lt[noise[2]];
5061 mac->mac_noise.noi_samples[i][3] = pg->pg_nrssi_lt[noise[3]];
5062 mac->mac_noise.noi_nsamples++;
5063 if (mac->mac_noise.noi_nsamples == 8) {
5064 average = 0;
5065 for (i = 0; i < 8; i++) {
5066 for (j = 0; j < 4; j++)
5067 average += mac->mac_noise.noi_samples[i][j];
5068 }
5069 average = (((average / 32) * 125) + 64) / 128;
5070 tmp = (bwn_shm_read_2(mac, BWN_SHARED, 0x40c) / 128) & 0x1f;
5071 if (tmp >= 8)
5072 average += 2;
5073 else
5074 average -= 25;
5075 average -= (tmp == 8) ? 72 : 48;
5076
5077 mac->mac_stats.link_noise = average;
5078 mac->mac_noise.noi_running = 0;
5079 return;
5080 }
5081new:
5082 bwn_noise_gensample(mac);
5083}
5084
5085static int
5086bwn_pio_rx(struct bwn_pio_rxqueue *prq)
5087{
5088 struct bwn_mac *mac = prq->prq_mac;
5089 struct bwn_softc *sc = mac->mac_sc;
5090 unsigned int i;
5091
5092 BWN_ASSERT_LOCKED(sc);
5093
5094 if (mac->mac_status < BWN_MAC_STATUS_STARTED)
5095 return (0);
5096
5097 for (i = 0; i < 5000; i++) {
5098 if (bwn_pio_rxeof(prq) == 0)
5099 break;
5100 }
5101 if (i >= 5000)
5102 device_printf(sc->sc_dev, "too many RX frames in PIO mode\n");
5103 return ((i > 0) ? 1 : 0);
5104}
5105
5106static void
5107bwn_dma_rx(struct bwn_dma_ring *dr)
5108{
5109 int slot, curslot;
5110
5111 KASSERT(!dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
5112 curslot = dr->get_curslot(dr);
5113 KASSERT(curslot >= 0 && curslot < dr->dr_numslots,
5114 ("%s:%d: fail", __func__, __LINE__));
5115
5116 slot = dr->dr_curslot;
5117 for (; slot != curslot; slot = bwn_dma_nextslot(dr, slot))
5118 bwn_dma_rxeof(dr, &slot);
5119
5120 bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
5121 BUS_DMASYNC_PREWRITE);
5122
5123 dr->set_curslot(dr, slot);
5124 dr->dr_curslot = slot;
5125}
5126
5127static void
5128bwn_intr_txeof(struct bwn_mac *mac)
5129{
5130 struct bwn_txstatus stat;
5131 uint32_t stat0, stat1;
5132 uint16_t tmp;
5133
5134 BWN_ASSERT_LOCKED(mac->mac_sc);
5135
5136 while (1) {
5137 stat0 = BWN_READ_4(mac, BWN_XMITSTAT_0);
5138 if (!(stat0 & 0x00000001))
5139 break;
5140 stat1 = BWN_READ_4(mac, BWN_XMITSTAT_1);
5141
5142 DPRINTF(mac->mac_sc, BWN_DEBUG_XMIT,
5143 "%s: stat0=0x%08x, stat1=0x%08x\n",
5144 __func__,
5145 stat0,
5146 stat1);
5147
5148 stat.cookie = (stat0 >> 16);
5149 stat.seq = (stat1 & 0x0000ffff);
5150 stat.phy_stat = ((stat1 & 0x00ff0000) >> 16);
5151 tmp = (stat0 & 0x0000ffff);
5152 stat.framecnt = ((tmp & 0xf000) >> 12);
5153 stat.rtscnt = ((tmp & 0x0f00) >> 8);
5154 stat.sreason = ((tmp & 0x001c) >> 2);
5155 stat.pm = (tmp & 0x0080) ? 1 : 0;
5156 stat.im = (tmp & 0x0040) ? 1 : 0;
5157 stat.ampdu = (tmp & 0x0020) ? 1 : 0;
5158 stat.ack = (tmp & 0x0002) ? 1 : 0;
5159
5160 DPRINTF(mac->mac_sc, BWN_DEBUG_XMIT,
5161 "%s: cookie=%d, seq=%d, phystat=0x%02x, framecnt=%d, "
5162 "rtscnt=%d, sreason=%d, pm=%d, im=%d, ampdu=%d, ack=%d\n",
5163 __func__,
5164 stat.cookie,
5165 stat.seq,
5166 stat.phy_stat,
5167 stat.framecnt,
5168 stat.rtscnt,
5169 stat.sreason,
5170 stat.pm,
5171 stat.im,
5172 stat.ampdu,
5173 stat.ack);
5174
5175 bwn_handle_txeof(mac, &stat);
5176 }
5177}
5178
5179static void
5180bwn_hwreset(void *arg, int npending)
5181{
5182 struct bwn_mac *mac = arg;
5183 struct bwn_softc *sc = mac->mac_sc;
5184 int error = 0;
5185 int prev_status;
5186
5187 BWN_LOCK(sc);
5188
5189 prev_status = mac->mac_status;
5190 if (prev_status >= BWN_MAC_STATUS_STARTED)
5191 bwn_core_stop(mac);
5192 if (prev_status >= BWN_MAC_STATUS_INITED)
5193 bwn_core_exit(mac);
5194
5195 if (prev_status >= BWN_MAC_STATUS_INITED) {
5196 error = bwn_core_init(mac);
5197 if (error)
5198 goto out;
5199 }
5200 if (prev_status >= BWN_MAC_STATUS_STARTED)
5201 bwn_core_start(mac);
5202out:
5203 if (error) {
5204 device_printf(sc->sc_dev, "%s: failed (%d)\n", __func__, error);
5205 sc->sc_curmac = NULL;
5206 }
5207 BWN_UNLOCK(sc);
5208}
5209
5210static void
5211bwn_handle_fwpanic(struct bwn_mac *mac)
5212{
5213 struct bwn_softc *sc = mac->mac_sc;
5214 uint16_t reason;
5215
5216 reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_FWPANIC_REASON_REG);
5217 device_printf(sc->sc_dev,"fw panic (%u)\n", reason);
5218
5219 if (reason == BWN_FWPANIC_RESTART)
5220 bwn_restart(mac, "ucode panic");
5221}
5222
5223static void
5224bwn_load_beacon0(struct bwn_mac *mac)
5225{
5226
5227 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5228}
5229
5230static void
5231bwn_load_beacon1(struct bwn_mac *mac)
5232{
5233
5234 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5235}
5236
5237static uint32_t
5238bwn_jssi_read(struct bwn_mac *mac)
5239{
5240 uint32_t val = 0;
5241
5242 val = bwn_shm_read_2(mac, BWN_SHARED, 0x08a);
5243 val <<= 16;
5244 val |= bwn_shm_read_2(mac, BWN_SHARED, 0x088);
5245
5246 return (val);
5247}
5248
5249static void
5250bwn_noise_gensample(struct bwn_mac *mac)
5251{
5252 uint32_t jssi = 0x7f7f7f7f;
5253
5254 bwn_shm_write_2(mac, BWN_SHARED, 0x088, (jssi & 0x0000ffff));
5255 bwn_shm_write_2(mac, BWN_SHARED, 0x08a, (jssi & 0xffff0000) >> 16);
5256 BWN_WRITE_4(mac, BWN_MACCMD,
5257 BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_BGNOISE);
5258}
5259
5260static int
5261bwn_dma_freeslot(struct bwn_dma_ring *dr)
5262{
5263 BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
5264
5265 return (dr->dr_numslots - dr->dr_usedslot);
5266}
5267
5268static int
5269bwn_dma_nextslot(struct bwn_dma_ring *dr, int slot)
5270{
5271 BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
5272
5273 KASSERT(slot >= -1 && slot <= dr->dr_numslots - 1,
5274 ("%s:%d: fail", __func__, __LINE__));
5275 if (slot == dr->dr_numslots - 1)
5276 return (0);
5277 return (slot + 1);
5278}
5279
5280static void
5281bwn_dma_rxeof(struct bwn_dma_ring *dr, int *slot)
5282{
5283 struct bwn_mac *mac = dr->dr_mac;
5284 struct bwn_softc *sc = mac->mac_sc;
5285 struct bwn_dma *dma = &mac->mac_method.dma;
5286 struct bwn_dmadesc_generic *desc;
5287 struct bwn_dmadesc_meta *meta;
5288 struct bwn_rxhdr4 *rxhdr;
5289 struct mbuf *m;
5290 uint32_t macstat;
5291 int32_t tmp;
5292 int cnt = 0;
5293 uint16_t len;
5294
5295 dr->getdesc(dr, *slot, &desc, &meta);
5296
5297 bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap, BUS_DMASYNC_POSTREAD);
5298 m = meta->mt_m;
5299
5300 if (bwn_dma_newbuf(dr, desc, meta, 0)) {
5301 counter_u64_add(sc->sc_ic.ic_ierrors, 1);
5302 return;
5303 }
5304
5305 rxhdr = mtod(m, struct bwn_rxhdr4 *);
5306 len = le16toh(rxhdr->frame_len);
5307 if (len <= 0) {
5308 counter_u64_add(sc->sc_ic.ic_ierrors, 1);
5309 return;
5310 }
5311 if (bwn_dma_check_redzone(dr, m)) {
5312 device_printf(sc->sc_dev, "redzone error.\n");
5313 bwn_dma_set_redzone(dr, m);
5314 bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
5315 BUS_DMASYNC_PREWRITE);
5316 return;
5317 }
5318 if (len > dr->dr_rx_bufsize) {
5319 tmp = len;
5320 while (1) {
5321 dr->getdesc(dr, *slot, &desc, &meta);
5322 bwn_dma_set_redzone(dr, meta->mt_m);
5323 bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
5324 BUS_DMASYNC_PREWRITE);
5325 *slot = bwn_dma_nextslot(dr, *slot);
5326 cnt++;
5327 tmp -= dr->dr_rx_bufsize;
5328 if (tmp <= 0)
5329 break;
5330 }
5331 device_printf(sc->sc_dev, "too small buffer "
5332 "(len %u buffer %u dropped %d)\n",
5333 len, dr->dr_rx_bufsize, cnt);
5334 return;
5335 }
5336 macstat = le32toh(rxhdr->mac_status);
5337 if (macstat & BWN_RX_MAC_FCSERR) {
5338 if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
5339 device_printf(sc->sc_dev, "RX drop\n");
5340 return;
5341 }
5342 }
5343
5344 m->m_len = m->m_pkthdr.len = len + dr->dr_frameoffset;
5345 m_adj(m, dr->dr_frameoffset);
5346
5347 bwn_rxeof(dr->dr_mac, m, rxhdr);
5348}
5349
5350static void
5351bwn_handle_txeof(struct bwn_mac *mac, const struct bwn_txstatus *status)
5352{
5353 struct bwn_softc *sc = mac->mac_sc;
5354 struct bwn_stats *stats = &mac->mac_stats;
5355
5356 BWN_ASSERT_LOCKED(mac->mac_sc);
5357
5358 if (status->im)
5359 device_printf(sc->sc_dev, "TODO: STATUS IM\n");
5360 if (status->ampdu)
5361 device_printf(sc->sc_dev, "TODO: STATUS AMPDU\n");
5362 if (status->rtscnt) {
5363 if (status->rtscnt == 0xf)
5364 stats->rtsfail++;
5365 else
5366 stats->rts++;
5367 }
5368
5369 if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
5370 bwn_dma_handle_txeof(mac, status);
5371 } else {
5372 bwn_pio_handle_txeof(mac, status);
5373 }
5374
5375 bwn_phy_txpower_check(mac, 0);
5376}
5377
5378static uint8_t
5379bwn_pio_rxeof(struct bwn_pio_rxqueue *prq)
5380{
5381 struct bwn_mac *mac = prq->prq_mac;
5382 struct bwn_softc *sc = mac->mac_sc;
5383 struct bwn_rxhdr4 rxhdr;
5384 struct mbuf *m;
5385 uint32_t ctl32, macstat, v32;
5386 unsigned int i, padding;
5387 uint16_t ctl16, len, totlen, v16;
5388 unsigned char *mp;
5389 char *data;
5390
5391 memset(&rxhdr, 0, sizeof(rxhdr));
5392
5393 if (prq->prq_rev >= 8) {
5394 ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
5395 if (!(ctl32 & BWN_PIO8_RXCTL_FRAMEREADY))
5396 return (0);
5397 bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
5398 BWN_PIO8_RXCTL_FRAMEREADY);
5399 for (i = 0; i < 10; i++) {
5400 ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
5401 if (ctl32 & BWN_PIO8_RXCTL_DATAREADY)
5402 goto ready;
5403 DELAY(10);
5404 }
5405 } else {
5406 ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
5407 if (!(ctl16 & BWN_PIO_RXCTL_FRAMEREADY))
5408 return (0);
5409 bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL,
5410 BWN_PIO_RXCTL_FRAMEREADY);
5411 for (i = 0; i < 10; i++) {
5412 ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
5413 if (ctl16 & BWN_PIO_RXCTL_DATAREADY)
5414 goto ready;
5415 DELAY(10);
5416 }
5417 }
5418 device_printf(sc->sc_dev, "%s: timed out\n", __func__);
5419 return (1);
5420ready:
5421 if (prq->prq_rev >= 8)
5422 siba_read_multi_4(sc->sc_dev, &rxhdr, sizeof(rxhdr),
5423 prq->prq_base + BWN_PIO8_RXDATA);
5424 else
5425 siba_read_multi_2(sc->sc_dev, &rxhdr, sizeof(rxhdr),
5426 prq->prq_base + BWN_PIO_RXDATA);
5427 len = le16toh(rxhdr.frame_len);
5428 if (len > 0x700) {
5429 device_printf(sc->sc_dev, "%s: len is too big\n", __func__);
5430 goto error;
5431 }
5432 if (len == 0) {
5433 device_printf(sc->sc_dev, "%s: len is 0\n", __func__);
5434 goto error;
5435 }
5436
5437 macstat = le32toh(rxhdr.mac_status);
5438 if (macstat & BWN_RX_MAC_FCSERR) {
5439 if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
5440 device_printf(sc->sc_dev, "%s: FCS error", __func__);
5441 goto error;
5442 }
5443 }
5444
5445 padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
5446 totlen = len + padding;
5447 KASSERT(totlen <= MCLBYTES, ("too big..\n"));
5448 m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
5449 if (m == NULL) {
5450 device_printf(sc->sc_dev, "%s: out of memory", __func__);
5451 goto error;
5452 }
5453 mp = mtod(m, unsigned char *);
5454 if (prq->prq_rev >= 8) {
5455 siba_read_multi_4(sc->sc_dev, mp, (totlen & ~3),
5456 prq->prq_base + BWN_PIO8_RXDATA);
5457 if (totlen & 3) {
5458 v32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXDATA);
5459 data = &(mp[totlen - 1]);
5460 switch (totlen & 3) {
5461 case 3:
5462 *data = (v32 >> 16);
5463 data--;
5464 case 2:
5465 *data = (v32 >> 8);
5466 data--;
5467 case 1:
5468 *data = v32;
5469 }
5470 }
5471 } else {
5472 siba_read_multi_2(sc->sc_dev, mp, (totlen & ~1),
5473 prq->prq_base + BWN_PIO_RXDATA);
5474 if (totlen & 1) {
5475 v16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXDATA);
5476 mp[totlen - 1] = v16;
5477 }
5478 }
5479
5480 m->m_len = m->m_pkthdr.len = totlen;
5481
5482 bwn_rxeof(prq->prq_mac, m, &rxhdr);
5483
5484 return (1);
5485error:
5486 if (prq->prq_rev >= 8)
5487 bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
5488 BWN_PIO8_RXCTL_DATAREADY);
5489 else
5490 bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL, BWN_PIO_RXCTL_DATAREADY);
5491 return (1);
5492}
5493
5494static int
5495bwn_dma_newbuf(struct bwn_dma_ring *dr, struct bwn_dmadesc_generic *desc,
5496 struct bwn_dmadesc_meta *meta, int init)
5497{
5498 struct bwn_mac *mac = dr->dr_mac;
5499 struct bwn_dma *dma = &mac->mac_method.dma;
5500 struct bwn_rxhdr4 *hdr;
5501 bus_dmamap_t map;
5502 bus_addr_t paddr;
5503 struct mbuf *m;
5504 int error;
5505
5506 m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
5507 if (m == NULL) {
5508 error = ENOBUFS;
5509
5510 /*
5511 * If the NIC is up and running, we need to:
5512 * - Clear RX buffer's header.
5513 * - Restore RX descriptor settings.
5514 */
5515 if (init)
5516 return (error);
5517 else
5518 goto back;
5519 }
5520 m->m_len = m->m_pkthdr.len = MCLBYTES;
5521
5522 bwn_dma_set_redzone(dr, m);
5523
5524 /*
5525 * Try to load RX buf into temporary DMA map
5526 */
5527 error = bus_dmamap_load_mbuf(dma->rxbuf_dtag, dr->dr_spare_dmap, m,
5528 bwn_dma_buf_addr, &paddr, BUS_DMA_NOWAIT);
5529 if (error) {
5530 m_freem(m);
5531
5532 /*
5533 * See the comment above
5534 */
5535 if (init)
5536 return (error);
5537 else
5538 goto back;
5539 }
5540
5541 if (!init)
5542 bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
5543 meta->mt_m = m;
5544 meta->mt_paddr = paddr;
5545
5546 /*
5547 * Swap RX buf's DMA map with the loaded temporary one
5548 */
5549 map = meta->mt_dmap;
5550 meta->mt_dmap = dr->dr_spare_dmap;
5551 dr->dr_spare_dmap = map;
5552
5553back:
5554 /*
5555 * Clear RX buf header
5556 */
5557 hdr = mtod(meta->mt_m, struct bwn_rxhdr4 *);
5558 bzero(hdr, sizeof(*hdr));
5559 bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
5560 BUS_DMASYNC_PREWRITE);
5561
5562 /*
5563 * Setup RX buf descriptor
5564 */
5565 dr->setdesc(dr, desc, meta->mt_paddr, meta->mt_m->m_len -
5566 sizeof(*hdr), 0, 0, 0);
5567 return (error);
5568}
5569
5570static void
5571bwn_dma_buf_addr(void *arg, bus_dma_segment_t *seg, int nseg,
5572 bus_size_t mapsz __unused, int error)
5573{
5574
5575 if (!error) {
5576 KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
5577 *((bus_addr_t *)arg) = seg->ds_addr;
5578 }
5579}
5580
5581static int
5582bwn_hwrate2ieeerate(int rate)
5583{
5584
5585 switch (rate) {
5586 case BWN_CCK_RATE_1MB:
5587 return (2);
5588 case BWN_CCK_RATE_2MB:
5589 return (4);
5590 case BWN_CCK_RATE_5MB:
5591 return (11);
5592 case BWN_CCK_RATE_11MB:
5593 return (22);
5594 case BWN_OFDM_RATE_6MB:
5595 return (12);
5596 case BWN_OFDM_RATE_9MB:
5597 return (18);
5598 case BWN_OFDM_RATE_12MB:
5599 return (24);
5600 case BWN_OFDM_RATE_18MB:
5601 return (36);
5602 case BWN_OFDM_RATE_24MB:
5603 return (48);
5604 case BWN_OFDM_RATE_36MB:
5605 return (72);
5606 case BWN_OFDM_RATE_48MB:
5607 return (96);
5608 case BWN_OFDM_RATE_54MB:
5609 return (108);
5610 default:
5611 printf("Ooops\n");
5612 return (0);
5613 }
5614}
5615
5616/*
5617 * Post process the RX provided RSSI.
5618 *
5619 * Valid for A, B, G, LP PHYs.
5620 */
5621static int8_t
5622bwn_rx_rssi_calc(struct bwn_mac *mac, uint8_t in_rssi,
5623 int ofdm, int adjust_2053, int adjust_2050)
5624{
5625 struct bwn_phy *phy = &mac->mac_phy;
5626 struct bwn_phy_g *gphy = &phy->phy_g;
5627 int tmp;
5628
5629 switch (phy->rf_ver) {
5630 case 0x2050:
5631 if (ofdm) {
5632 tmp = in_rssi;
5633 if (tmp > 127)
5634 tmp -= 256;
5635 tmp = tmp * 73 / 64;
5636 if (adjust_2050)
5637 tmp += 25;
5638 else
5639 tmp -= 3;
5640 } else {
5641 if (siba_sprom_get_bf_lo(mac->mac_sc->sc_dev)
5642 & BWN_BFL_RSSI) {
5643 if (in_rssi > 63)
5644 in_rssi = 63;
5645 tmp = gphy->pg_nrssi_lt[in_rssi];
5646 tmp = (31 - tmp) * -131 / 128 - 57;
5647 } else {
5648 tmp = in_rssi;
5649 tmp = (31 - tmp) * -149 / 128 - 68;
5650 }
5651 if (phy->type == BWN_PHYTYPE_G && adjust_2050)
5652 tmp += 25;
5653 }
5654 break;
5655 case 0x2060:
5656 if (in_rssi > 127)
5657 tmp = in_rssi - 256;
5658 else
5659 tmp = in_rssi;
5660 break;
5661 default:
5662 tmp = in_rssi;
5663 tmp = (tmp - 11) * 103 / 64;
5664 if (adjust_2053)
5665 tmp -= 109;
5666 else
5667 tmp -= 83;
5668 }
5669
5670 return (tmp);
5671}
5672
5673static void
5674bwn_rxeof(struct bwn_mac *mac, struct mbuf *m, const void *_rxhdr)
5675{
5676 const struct bwn_rxhdr4 *rxhdr = _rxhdr;
5677 struct bwn_plcp6 *plcp;
5678 struct bwn_softc *sc = mac->mac_sc;
5679 struct ieee80211_frame_min *wh;
5680 struct ieee80211_node *ni;
5681 struct ieee80211com *ic = &sc->sc_ic;
5682 uint32_t macstat;
5683 int padding, rate, rssi = 0, noise = 0, type;
5684 uint16_t phytype, phystat0, phystat3, chanstat;
5685 unsigned char *mp = mtod(m, unsigned char *);
5686 static int rx_mac_dec_rpt = 0;
5687
5688 BWN_ASSERT_LOCKED(sc);
5689
5690 phystat0 = le16toh(rxhdr->phy_status0);
5691 phystat3 = le16toh(rxhdr->phy_status3);
5692
5693 /* XXX Note: mactime, macstat, chanstat need fixing for fw 598 */
5694 macstat = le32toh(rxhdr->mac_status);
5695 chanstat = le16toh(rxhdr->channel);
5696
5697 phytype = chanstat & BWN_RX_CHAN_PHYTYPE;
5698
5699 if (macstat & BWN_RX_MAC_FCSERR)
5700 device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_FCS_CRC\n");
5701 if (phystat0 & (BWN_RX_PHYST0_PLCPHCF | BWN_RX_PHYST0_PLCPFV))
5702 device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_PLCP_CRC\n");
5703 if (macstat & BWN_RX_MAC_DECERR)
5704 goto drop;
5705
5706 padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
5707 if (m->m_pkthdr.len < (sizeof(struct bwn_plcp6) + padding)) {
5708 device_printf(sc->sc_dev, "frame too short (length=%d)\n",
5709 m->m_pkthdr.len);
5710 goto drop;
5711 }
5712 plcp = (struct bwn_plcp6 *)(mp + padding);
5713 m_adj(m, sizeof(struct bwn_plcp6) + padding);
5714 if (m->m_pkthdr.len < IEEE80211_MIN_LEN) {
5715 device_printf(sc->sc_dev, "frame too short (length=%d)\n",
5716 m->m_pkthdr.len);
5717 goto drop;
5718 }
5719 wh = mtod(m, struct ieee80211_frame_min *);
5720
5721 if (macstat & BWN_RX_MAC_DEC && rx_mac_dec_rpt++ < 50)
5722 device_printf(sc->sc_dev,
5723 "RX decryption attempted (old %d keyidx %#x)\n",
5724 BWN_ISOLDFMT(mac),
5725 (macstat & BWN_RX_MAC_KEYIDX) >> BWN_RX_MAC_KEYIDX_SHIFT);
5726
5727 if (phystat0 & BWN_RX_PHYST0_OFDM)
5728 rate = bwn_plcp_get_ofdmrate(mac, plcp,
5729 phytype == BWN_PHYTYPE_A);
5730 else
5731 rate = bwn_plcp_get_cckrate(mac, plcp);
5732 if (rate == -1) {
5733 if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADPLCP))
5734 goto drop;
5735 }
5736 sc->sc_rx_rate = bwn_hwrate2ieeerate(rate);
5737
5738 /* rssi/noise */
5739 switch (phytype) {
5740 case BWN_PHYTYPE_A:
5741 case BWN_PHYTYPE_B:
5742 case BWN_PHYTYPE_G:
5743 case BWN_PHYTYPE_LP:
5744 rssi = bwn_rx_rssi_calc(mac, rxhdr->phy.abg.rssi,
5745 !! (phystat0 & BWN_RX_PHYST0_OFDM),
5746 !! (phystat0 & BWN_RX_PHYST0_GAINCTL),
5747 !! (phystat3 & BWN_RX_PHYST3_TRSTATE));
5748 break;
5749 case BWN_PHYTYPE_N:
5750 /* Broadcom has code for min/avg, but always used max */
5751 if (rxhdr->phy.n.power0 == 16 || rxhdr->phy.n.power0 == 32)
5752 rssi = max(rxhdr->phy.n.power1, rxhdr->ps2.n.power2);
5753 else
5754 rssi = max(rxhdr->phy.n.power0, rxhdr->phy.n.power1);
5755 break;
5756 default:
5757 /* XXX TODO: implement rssi for other PHYs */
5758 break;
5759 }
5760
5761 noise = mac->mac_stats.link_noise;
5762
5763 /* RX radio tap */
5764 if (ieee80211_radiotap_active(ic))
5765 bwn_rx_radiotap(mac, m, rxhdr, plcp, rate, rssi, noise);
5766 m_adj(m, -IEEE80211_CRC_LEN);
5767
5768 BWN_UNLOCK(sc);
5769
5770 ni = ieee80211_find_rxnode(ic, wh);
5771 if (ni != NULL) {
5772 type = ieee80211_input(ni, m, rssi, noise);
5773 ieee80211_free_node(ni);
5774 } else
5775 type = ieee80211_input_all(ic, m, rssi, noise);
5776
5777 BWN_LOCK(sc);
5778 return;
5779drop:
5780 device_printf(sc->sc_dev, "%s: dropped\n", __func__);
5781}
5782
5783static void
5784bwn_dma_handle_txeof(struct bwn_mac *mac,
5785 const struct bwn_txstatus *status)
5786{
5787 struct bwn_dma *dma = &mac->mac_method.dma;
5788 struct bwn_dma_ring *dr;
5789 struct bwn_dmadesc_generic *desc;
5790 struct bwn_dmadesc_meta *meta;
5791 struct bwn_softc *sc = mac->mac_sc;
5792 int slot;
5793 int retrycnt = 0;
5794
5795 BWN_ASSERT_LOCKED(sc);
5796
5797 dr = bwn_dma_parse_cookie(mac, status, status->cookie, &slot);
5798 if (dr == NULL) {
5799 device_printf(sc->sc_dev, "failed to parse cookie\n");
5800 return;
5801 }
5802 KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
5803
5804 while (1) {
5805 KASSERT(slot >= 0 && slot < dr->dr_numslots,
5806 ("%s:%d: fail", __func__, __LINE__));
5807 dr->getdesc(dr, slot, &desc, &meta);
5808
5809 if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
5810 bus_dmamap_unload(dr->dr_txring_dtag, meta->mt_dmap);
5811 else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
5812 bus_dmamap_unload(dma->txbuf_dtag, meta->mt_dmap);
5813
5814 if (meta->mt_islast) {
5815 KASSERT(meta->mt_m != NULL,
5816 ("%s:%d: fail", __func__, __LINE__));
5817
5818 /*
5819 * If we don't get an ACK, then we should log the
5820 * full framecnt. That may be 0 if it's a PHY
5821 * failure, so ensure that gets logged as some
5822 * retry attempt.
5823 */
5824 if (status->ack) {
5825 retrycnt = status->framecnt - 1;
5826 } else {
5827 retrycnt = status->framecnt;
5828 if (retrycnt == 0)
5829 retrycnt = 1;
5830 }
5831 ieee80211_ratectl_tx_complete(meta->mt_ni->ni_vap, meta->mt_ni,
5832 status->ack ?
5833 IEEE80211_RATECTL_TX_SUCCESS :
5834 IEEE80211_RATECTL_TX_FAILURE,
5835 &retrycnt, 0);
5836 ieee80211_tx_complete(meta->mt_ni, meta->mt_m, 0);
5837 meta->mt_ni = NULL;
5838 meta->mt_m = NULL;
5839 } else
5840 KASSERT(meta->mt_m == NULL,
5841 ("%s:%d: fail", __func__, __LINE__));
5842
5843 dr->dr_usedslot--;
5844 if (meta->mt_islast)
5845 break;
5846 slot = bwn_dma_nextslot(dr, slot);
5847 }
5848 sc->sc_watchdog_timer = 0;
5849 if (dr->dr_stop) {
5850 KASSERT(bwn_dma_freeslot(dr) >= BWN_TX_SLOTS_PER_FRAME,
5851 ("%s:%d: fail", __func__, __LINE__));
5852 dr->dr_stop = 0;
5853 }
5854}
5855
5856static void
5857bwn_pio_handle_txeof(struct bwn_mac *mac,
5858 const struct bwn_txstatus *status)
5859{
5860 struct bwn_pio_txqueue *tq;
5861 struct bwn_pio_txpkt *tp = NULL;
5862 struct bwn_softc *sc = mac->mac_sc;
5863 int retrycnt = 0;
5864
5865 BWN_ASSERT_LOCKED(sc);
5866
5867 tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
5868 if (tq == NULL)
5869 return;
5870
5871 tq->tq_used -= roundup(tp->tp_m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
5872 tq->tq_free++;
5873
5874 if (tp->tp_ni != NULL) {
5875 /*
5876 * Do any tx complete callback. Note this must
5877 * be done before releasing the node reference.
5878 */
5879
5880 /*
5881 * If we don't get an ACK, then we should log the
5882 * full framecnt. That may be 0 if it's a PHY
5883 * failure, so ensure that gets logged as some
5884 * retry attempt.
5885 */
5886 if (status->ack) {
5887 retrycnt = status->framecnt - 1;
5888 } else {
5889 retrycnt = status->framecnt;
5890 if (retrycnt == 0)
5891 retrycnt = 1;
5892 }
5893 ieee80211_ratectl_tx_complete(tp->tp_ni->ni_vap, tp->tp_ni,
5894 status->ack ?
5895 IEEE80211_RATECTL_TX_SUCCESS :
5896 IEEE80211_RATECTL_TX_FAILURE,
5897 &retrycnt, 0);
5898
5899 if (tp->tp_m->m_flags & M_TXCB)
5900 ieee80211_process_callback(tp->tp_ni, tp->tp_m, 0);
5901 ieee80211_free_node(tp->tp_ni);
5902 tp->tp_ni = NULL;
5903 }
5904 m_freem(tp->tp_m);
5905 tp->tp_m = NULL;
5906 TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
5907
5908 sc->sc_watchdog_timer = 0;
5909}
5910
5911static void
5912bwn_phy_txpower_check(struct bwn_mac *mac, uint32_t flags)
5913{
5914 struct bwn_softc *sc = mac->mac_sc;
5915 struct bwn_phy *phy = &mac->mac_phy;
5916 struct ieee80211com *ic = &sc->sc_ic;
5917 unsigned long now;
5918 bwn_txpwr_result_t result;
5919
5920 BWN_GETTIME(now);
5921
5922 if (!(flags & BWN_TXPWR_IGNORE_TIME) && ieee80211_time_before(now, phy->nexttime))
5923 return;
5924 phy->nexttime = now + 2 * 1000;
5925
5926 if (siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM &&
5927 siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306)
5928 return;
5929
5930 if (phy->recalc_txpwr != NULL) {
5931 result = phy->recalc_txpwr(mac,
5932 (flags & BWN_TXPWR_IGNORE_TSSI) ? 1 : 0);
5933 if (result == BWN_TXPWR_RES_DONE)
5934 return;
5935 KASSERT(result == BWN_TXPWR_RES_NEED_ADJUST,
5936 ("%s: fail", __func__));
5937 KASSERT(phy->set_txpwr != NULL, ("%s: fail", __func__));
5938
5939 ieee80211_runtask(ic, &mac->mac_txpower);
5940 }
5941}
5942
5943static uint16_t
5944bwn_pio_rx_read_2(struct bwn_pio_rxqueue *prq, uint16_t offset)
5945{
5946
5947 return (BWN_READ_2(prq->prq_mac, prq->prq_base + offset));
5948}
5949
5950static uint32_t
5951bwn_pio_rx_read_4(struct bwn_pio_rxqueue *prq, uint16_t offset)
5952{
5953
5954 return (BWN_READ_4(prq->prq_mac, prq->prq_base + offset));
5955}
5956
5957static void
5958bwn_pio_rx_write_2(struct bwn_pio_rxqueue *prq, uint16_t offset, uint16_t value)
5959{
5960
5961 BWN_WRITE_2(prq->prq_mac, prq->prq_base + offset, value);
5962}
5963
5964static void
5965bwn_pio_rx_write_4(struct bwn_pio_rxqueue *prq, uint16_t offset, uint32_t value)
5966{
5967
5968 BWN_WRITE_4(prq->prq_mac, prq->prq_base + offset, value);
5969}
5970
5971static int
5972bwn_ieeerate2hwrate(struct bwn_softc *sc, int rate)
5973{
5974
5975 switch (rate) {
5976 /* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
5977 case 12:
5978 return (BWN_OFDM_RATE_6MB);
5979 case 18:
5980 return (BWN_OFDM_RATE_9MB);
5981 case 24:
5982 return (BWN_OFDM_RATE_12MB);
5983 case 36:
5984 return (BWN_OFDM_RATE_18MB);
5985 case 48:
5986 return (BWN_OFDM_RATE_24MB);
5987 case 72:
5988 return (BWN_OFDM_RATE_36MB);
5989 case 96:
5990 return (BWN_OFDM_RATE_48MB);
5991 case 108:
5992 return (BWN_OFDM_RATE_54MB);
5993 /* CCK rates (NB: not IEEE std, device-specific) */
5994 case 2:
5995 return (BWN_CCK_RATE_1MB);
5996 case 4:
5997 return (BWN_CCK_RATE_2MB);
5998 case 11:
5999 return (BWN_CCK_RATE_5MB);
6000 case 22:
6001 return (BWN_CCK_RATE_11MB);
6002 }
6003
6004 device_printf(sc->sc_dev, "unsupported rate %d\n", rate);
6005 return (BWN_CCK_RATE_1MB);
6006}
6007
6008static uint16_t
6009bwn_set_txhdr_phyctl1(struct bwn_mac *mac, uint8_t bitrate)
6010{
6011 struct bwn_phy *phy = &mac->mac_phy;
6012 uint16_t control = 0;
6013 uint16_t bw;
6014
6015 /* XXX TODO: this is for LP phy, what about N-PHY, etc? */
6016 bw = BWN_TXH_PHY1_BW_20;
6017
6018 if (BWN_ISCCKRATE(bitrate) && phy->type != BWN_PHYTYPE_LP) {
6019 control = bw;
6020 } else {
6021 control = bw;
6022 /* Figure out coding rate and modulation */
6023 /* XXX TODO: table-ize, for MCS transmit */
6024 /* Note: this is BWN_*_RATE values */
6025 switch (bitrate) {
6026 case BWN_CCK_RATE_1MB:
6027 control |= 0;
6028 break;
6029 case BWN_CCK_RATE_2MB:
6030 control |= 1;
6031 break;
6032 case BWN_CCK_RATE_5MB:
6033 control |= 2;
6034 break;
6035 case BWN_CCK_RATE_11MB:
6036 control |= 3;
6037 break;
6038 case BWN_OFDM_RATE_6MB:
6039 control |= BWN_TXH_PHY1_CRATE_1_2;
6040 control |= BWN_TXH_PHY1_MODUL_BPSK;
6041 break;
6042 case BWN_OFDM_RATE_9MB:
6043 control |= BWN_TXH_PHY1_CRATE_3_4;
6044 control |= BWN_TXH_PHY1_MODUL_BPSK;
6045 break;
6046 case BWN_OFDM_RATE_12MB:
6047 control |= BWN_TXH_PHY1_CRATE_1_2;
6048 control |= BWN_TXH_PHY1_MODUL_QPSK;
6049 break;
6050 case BWN_OFDM_RATE_18MB:
6051 control |= BWN_TXH_PHY1_CRATE_3_4;
6052 control |= BWN_TXH_PHY1_MODUL_QPSK;
6053 break;
6054 case BWN_OFDM_RATE_24MB:
6055 control |= BWN_TXH_PHY1_CRATE_1_2;
6056 control |= BWN_TXH_PHY1_MODUL_QAM16;
6057 break;
6058 case BWN_OFDM_RATE_36MB:
6059 control |= BWN_TXH_PHY1_CRATE_3_4;
6060 control |= BWN_TXH_PHY1_MODUL_QAM16;
6061 break;
6062 case BWN_OFDM_RATE_48MB:
6063 control |= BWN_TXH_PHY1_CRATE_1_2;
6064 control |= BWN_TXH_PHY1_MODUL_QAM64;
6065 break;
6066 case BWN_OFDM_RATE_54MB:
6067 control |= BWN_TXH_PHY1_CRATE_3_4;
6068 control |= BWN_TXH_PHY1_MODUL_QAM64;
6069 break;
6070 default:
6071 break;
6072 }
6073 control |= BWN_TXH_PHY1_MODE_SISO;
6074 }
6075
6076 return control;
6077}
6078
6079static int
6080bwn_set_txhdr(struct bwn_mac *mac, struct ieee80211_node *ni,
6081 struct mbuf *m, struct bwn_txhdr *txhdr, uint16_t cookie)
6082{
6083 const struct bwn_phy *phy = &mac->mac_phy;
6084 struct bwn_softc *sc = mac->mac_sc;
6085 struct ieee80211_frame *wh;
6086 struct ieee80211_frame *protwh;
6087 struct ieee80211_frame_cts *cts;
6088 struct ieee80211_frame_rts *rts;
6089 const struct ieee80211_txparam *tp;
6090 struct ieee80211vap *vap = ni->ni_vap;
6091 struct ieee80211com *ic = &sc->sc_ic;
6092 struct mbuf *mprot;
6093 unsigned int len;
6094 uint32_t macctl = 0;
6095 int protdur, rts_rate, rts_rate_fb, ismcast, isshort, rix, type;
6096 uint16_t phyctl = 0;
6097 uint8_t rate, rate_fb;
6098 int fill_phy_ctl1 = 0;
6099
6100 wh = mtod(m, struct ieee80211_frame *);
6101 memset(txhdr, 0, sizeof(*txhdr));
6102
6103 type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
6104 ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
6105 isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0;
6106
6107 if ((phy->type == BWN_PHYTYPE_N) || (phy->type == BWN_PHYTYPE_LP)
6108 || (phy->type == BWN_PHYTYPE_HT))
6109 fill_phy_ctl1 = 1;
6110
6111 /*
6112 * Find TX rate
6113 */
6114 tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)];
6115 if (type != IEEE80211_FC0_TYPE_DATA || (m->m_flags & M_EAPOL))
6116 rate = rate_fb = tp->mgmtrate;
6117 else if (ismcast)
6118 rate = rate_fb = tp->mcastrate;
6119 else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
6120 rate = rate_fb = tp->ucastrate;
6121 else {
6122 /* XXX TODO: don't fall back to CCK rates for OFDM */
6123 rix = ieee80211_ratectl_rate(ni, NULL, 0);
6124 rate = ni->ni_txrate;
6125
6126 if (rix > 0)
6127 rate_fb = ni->ni_rates.rs_rates[rix - 1] &
6128 IEEE80211_RATE_VAL;
6129 else
6130 rate_fb = rate;
6131 }
6132
6133 sc->sc_tx_rate = rate;
6134
6135 /* Note: this maps the select ieee80211 rate to hardware rate */
6136 rate = bwn_ieeerate2hwrate(sc, rate);
6137 rate_fb = bwn_ieeerate2hwrate(sc, rate_fb);
6138
6139 txhdr->phyrate = (BWN_ISOFDMRATE(rate)) ? bwn_plcp_getofdm(rate) :
6140 bwn_plcp_getcck(rate);
6141 bcopy(wh->i_fc, txhdr->macfc, sizeof(txhdr->macfc));
6142 bcopy(wh->i_addr1, txhdr->addr1, IEEE80211_ADDR_LEN);
6143
6144 /* XXX rate/rate_fb is the hardware rate */
6145 if ((rate_fb == rate) ||
6146 (*(u_int16_t *)wh->i_dur & htole16(0x8000)) ||
6147 (*(u_int16_t *)wh->i_dur == htole16(0)))
6148 txhdr->dur_fb = *(u_int16_t *)wh->i_dur;
6149 else
6150 txhdr->dur_fb = ieee80211_compute_duration(ic->ic_rt,
6151 m->m_pkthdr.len, rate, isshort);
6152
6153 /* XXX TX encryption */
6154 bwn_plcp_genhdr(BWN_ISOLDFMT(mac) ?
6155 (struct bwn_plcp4 *)(&txhdr->body.old.plcp) :
6156 (struct bwn_plcp4 *)(&txhdr->body.new.plcp),
6157 m->m_pkthdr.len + IEEE80211_CRC_LEN, rate);
6158 bwn_plcp_genhdr((struct bwn_plcp4 *)(&txhdr->plcp_fb),
6159 m->m_pkthdr.len + IEEE80211_CRC_LEN, rate_fb);
6160
6161 txhdr->eftypes |= (BWN_ISOFDMRATE(rate_fb)) ? BWN_TX_EFT_FB_OFDM :
6162 BWN_TX_EFT_FB_CCK;
6163 txhdr->chan = phy->chan;
6164 phyctl |= (BWN_ISOFDMRATE(rate)) ? BWN_TX_PHY_ENC_OFDM :
6165 BWN_TX_PHY_ENC_CCK;
6166 /* XXX preamble? obey net80211 */
6167 if (isshort && (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
6168 rate == BWN_CCK_RATE_11MB))
6169 phyctl |= BWN_TX_PHY_SHORTPRMBL;
6170
6171 if (! phy->gmode)
6172 macctl |= BWN_TX_MAC_5GHZ;
6173
6174 /* XXX TX antenna selection */
6175
6176 switch (bwn_antenna_sanitize(mac, 0)) {
6177 case 0:
6178 phyctl |= BWN_TX_PHY_ANT01AUTO;
6179 break;
6180 case 1:
6181 phyctl |= BWN_TX_PHY_ANT0;
6182 break;
6183 case 2:
6184 phyctl |= BWN_TX_PHY_ANT1;
6185 break;
6186 case 3:
6187 phyctl |= BWN_TX_PHY_ANT2;
6188 break;
6189 case 4:
6190 phyctl |= BWN_TX_PHY_ANT3;
6191 break;
6192 default:
6193 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
6194 }
6195
6196 if (!ismcast)
6197 macctl |= BWN_TX_MAC_ACK;
6198
6199 macctl |= (BWN_TX_MAC_HWSEQ | BWN_TX_MAC_START_MSDU);
6200 if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
6201 m->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold)
6202 macctl |= BWN_TX_MAC_LONGFRAME;
6203
6204 if (ic->ic_flags & IEEE80211_F_USEPROT) {
6205 /* XXX RTS rate is always 1MB??? */
6206 /* XXX TODO: don't fall back to CCK rates for OFDM */
6207 rts_rate = BWN_CCK_RATE_1MB;
6208 rts_rate_fb = bwn_get_fbrate(rts_rate);
6209
6210 /* XXX 'rate' here is hardware rate now, not the net80211 rate */
6211 protdur = ieee80211_compute_duration(ic->ic_rt,
6212 m->m_pkthdr.len, rate, isshort) +
6213 + ieee80211_ack_duration(ic->ic_rt, rate, isshort);
6214
6215 if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) {
6216 cts = (struct ieee80211_frame_cts *)(BWN_ISOLDFMT(mac) ?
6217 (txhdr->body.old.rts_frame) :
6218 (txhdr->body.new.rts_frame));
6219 mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr,
6220 protdur);
6221 KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
6222 bcopy(mtod(mprot, uint8_t *), (uint8_t *)cts,
6223 mprot->m_pkthdr.len);
6224 m_freem(mprot);
6225 macctl |= BWN_TX_MAC_SEND_CTSTOSELF;
6226 len = sizeof(struct ieee80211_frame_cts);
6227 } else {
6228 rts = (struct ieee80211_frame_rts *)(BWN_ISOLDFMT(mac) ?
6229 (txhdr->body.old.rts_frame) :
6230 (txhdr->body.new.rts_frame));
6231 /* XXX rate/rate_fb is the hardware rate */
6232 protdur += ieee80211_ack_duration(ic->ic_rt, rate,
6233 isshort);
6234 mprot = ieee80211_alloc_rts(ic, wh->i_addr1,
6235 wh->i_addr2, protdur);
6236 KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
6237 bcopy(mtod(mprot, uint8_t *), (uint8_t *)rts,
6238 mprot->m_pkthdr.len);
6239 m_freem(mprot);
6240 macctl |= BWN_TX_MAC_SEND_RTSCTS;
6241 len = sizeof(struct ieee80211_frame_rts);
6242 }
6243 len += IEEE80211_CRC_LEN;
6244 bwn_plcp_genhdr((struct bwn_plcp4 *)((BWN_ISOLDFMT(mac)) ?
6245 &txhdr->body.old.rts_plcp :
6246 &txhdr->body.new.rts_plcp), len, rts_rate);
6247 bwn_plcp_genhdr((struct bwn_plcp4 *)&txhdr->rts_plcp_fb, len,
6248 rts_rate_fb);
6249
6250 protwh = (struct ieee80211_frame *)(BWN_ISOLDFMT(mac) ?
6251 (&txhdr->body.old.rts_frame) :
6252 (&txhdr->body.new.rts_frame));
6253 txhdr->rts_dur_fb = *(u_int16_t *)protwh->i_dur;
6254
6255 if (BWN_ISOFDMRATE(rts_rate)) {
6256 txhdr->eftypes |= BWN_TX_EFT_RTS_OFDM;
6257 txhdr->phyrate_rts = bwn_plcp_getofdm(rts_rate);
6258 } else {
6259 txhdr->eftypes |= BWN_TX_EFT_RTS_CCK;
6260 txhdr->phyrate_rts = bwn_plcp_getcck(rts_rate);
6261 }
6262 txhdr->eftypes |= (BWN_ISOFDMRATE(rts_rate_fb)) ?
6263 BWN_TX_EFT_RTS_FBOFDM : BWN_TX_EFT_RTS_FBCCK;
6264
6265 if (fill_phy_ctl1) {
6266 txhdr->phyctl_1rts = htole16(bwn_set_txhdr_phyctl1(mac, rts_rate));
6267 txhdr->phyctl_1rtsfb = htole16(bwn_set_txhdr_phyctl1(mac, rts_rate_fb));
6268 }
6269 }
6270
6271 if (fill_phy_ctl1) {
6272 txhdr->phyctl_1 = htole16(bwn_set_txhdr_phyctl1(mac, rate));
6273 txhdr->phyctl_1fb = htole16(bwn_set_txhdr_phyctl1(mac, rate_fb));
6274 }
6275
6276 if (BWN_ISOLDFMT(mac))
6277 txhdr->body.old.cookie = htole16(cookie);
6278 else
6279 txhdr->body.new.cookie = htole16(cookie);
6280
6281 txhdr->macctl = htole32(macctl);
6282 txhdr->phyctl = htole16(phyctl);
6283
6284 /*
6285 * TX radio tap
6286 */
6287 if (ieee80211_radiotap_active_vap(vap)) {
6288 sc->sc_tx_th.wt_flags = 0;
6289 if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED)
6290 sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP;
6291 if (isshort &&
6292 (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
6293 rate == BWN_CCK_RATE_11MB))
6294 sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
6295 sc->sc_tx_th.wt_rate = rate;
6296
6297 ieee80211_radiotap_tx(vap, m);
6298 }
6299
6300 return (0);
6301}
6302
6303static void
6304bwn_plcp_genhdr(struct bwn_plcp4 *plcp, const uint16_t octets,
6305 const uint8_t rate)
6306{
6307 uint32_t d, plen;
6308 uint8_t *raw = plcp->o.raw;
6309
6310 if (BWN_ISOFDMRATE(rate)) {
6311 d = bwn_plcp_getofdm(rate);
6312 KASSERT(!(octets & 0xf000),
6313 ("%s:%d: fail", __func__, __LINE__));
6314 d |= (octets << 5);
6315 plcp->o.data = htole32(d);
6316 } else {
6317 plen = octets * 16 / rate;
6318 if ((octets * 16 % rate) > 0) {
6319 plen++;
6320 if ((rate == BWN_CCK_RATE_11MB)
6321 && ((octets * 8 % 11) < 4)) {
6322 raw[1] = 0x84;
6323 } else
6324 raw[1] = 0x04;
6325 } else
6326 raw[1] = 0x04;
6327 plcp->o.data |= htole32(plen << 16);
6328 raw[0] = bwn_plcp_getcck(rate);
6329 }
6330}
6331
6332static uint8_t
6333bwn_antenna_sanitize(struct bwn_mac *mac, uint8_t n)
6334{
6335 struct bwn_softc *sc = mac->mac_sc;
6336 uint8_t mask;
6337
6338 if (n == 0)
6339 return (0);
6340 if (mac->mac_phy.gmode)
6341 mask = siba_sprom_get_ant_bg(sc->sc_dev);
6342 else
6343 mask = siba_sprom_get_ant_a(sc->sc_dev);
6344 if (!(mask & (1 << (n - 1))))
6345 return (0);
6346 return (n);
6347}
6348
6349/*
6350 * Return a fallback rate for the given rate.
6351 *
6352 * Note: Don't fall back from OFDM to CCK.
6353 */
6354static uint8_t
6355bwn_get_fbrate(uint8_t bitrate)
6356{
6357 switch (bitrate) {
6358 /* CCK */
6359 case BWN_CCK_RATE_1MB:
6360 return (BWN_CCK_RATE_1MB);
6361 case BWN_CCK_RATE_2MB:
6362 return (BWN_CCK_RATE_1MB);
6363 case BWN_CCK_RATE_5MB:
6364 return (BWN_CCK_RATE_2MB);
6365 case BWN_CCK_RATE_11MB:
6366 return (BWN_CCK_RATE_5MB);
6367
6368 /* OFDM */
6369 case BWN_OFDM_RATE_6MB:
6370 return (BWN_OFDM_RATE_6MB);
6371 case BWN_OFDM_RATE_9MB:
6372 return (BWN_OFDM_RATE_6MB);
6373 case BWN_OFDM_RATE_12MB:
6374 return (BWN_OFDM_RATE_9MB);
6375 case BWN_OFDM_RATE_18MB:
6376 return (BWN_OFDM_RATE_12MB);
6377 case BWN_OFDM_RATE_24MB:
6378 return (BWN_OFDM_RATE_18MB);
6379 case BWN_OFDM_RATE_36MB:
6380 return (BWN_OFDM_RATE_24MB);
6381 case BWN_OFDM_RATE_48MB:
6382 return (BWN_OFDM_RATE_36MB);
6383 case BWN_OFDM_RATE_54MB:
6384 return (BWN_OFDM_RATE_48MB);
6385 }
6386 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
6387 return (0);
6388}
6389
6390static uint32_t
6391bwn_pio_write_multi_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
6392 uint32_t ctl, const void *_data, int len)
6393{
6394 struct bwn_softc *sc = mac->mac_sc;
6395 uint32_t value = 0;
6396 const uint8_t *data = _data;
6397
6398 ctl |= BWN_PIO8_TXCTL_0_7 | BWN_PIO8_TXCTL_8_15 |
6399 BWN_PIO8_TXCTL_16_23 | BWN_PIO8_TXCTL_24_31;
6400 bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
6401
6402 siba_write_multi_4(sc->sc_dev, data, (len & ~3),
6403 tq->tq_base + BWN_PIO8_TXDATA);
6404 if (len & 3) {
6405 ctl &= ~(BWN_PIO8_TXCTL_8_15 | BWN_PIO8_TXCTL_16_23 |
6406 BWN_PIO8_TXCTL_24_31);
6407 data = &(data[len - 1]);
6408 switch (len & 3) {
6409 case 3:
6410 ctl |= BWN_PIO8_TXCTL_16_23;
6411 value |= (uint32_t)(*data) << 16;
6412 data--;
6413 case 2:
6414 ctl |= BWN_PIO8_TXCTL_8_15;
6415 value |= (uint32_t)(*data) << 8;
6416 data--;
6417 case 1:
6418 value |= (uint32_t)(*data);
6419 }
6420 bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
6421 bwn_pio_write_4(mac, tq, BWN_PIO8_TXDATA, value);
6422 }
6423
6424 return (ctl);
6425}
6426
6427static void
6428bwn_pio_write_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
6429 uint16_t offset, uint32_t value)
6430{
6431
6432 BWN_WRITE_4(mac, tq->tq_base + offset, value);
6433}
6434
6435static uint16_t
6436bwn_pio_write_multi_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
6437 uint16_t ctl, const void *_data, int len)
6438{
6439 struct bwn_softc *sc = mac->mac_sc;
6440 const uint8_t *data = _data;
6441
6442 ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
6443 BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
6444
6445 siba_write_multi_2(sc->sc_dev, data, (len & ~1),
6446 tq->tq_base + BWN_PIO_TXDATA);
6447 if (len & 1) {
6448 ctl &= ~BWN_PIO_TXCTL_WRITEHI;
6449 BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
6450 BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data[len - 1]);
6451 }
6452
6453 return (ctl);
6454}
6455
6456static uint16_t
6457bwn_pio_write_mbuf_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
6458 uint16_t ctl, struct mbuf *m0)
6459{
6460 int i, j = 0;
6461 uint16_t data = 0;
6462 const uint8_t *buf;
6463 struct mbuf *m = m0;
6464
6465 ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
6466 BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
6467
6468 for (; m != NULL; m = m->m_next) {
6469 buf = mtod(m, const uint8_t *);
6470 for (i = 0; i < m->m_len; i++) {
6471 if (!((j++) % 2))
6472 data |= buf[i];
6473 else {
6474 data |= (buf[i] << 8);
6475 BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
6476 data = 0;
6477 }
6478 }
6479 }
6480 if (m0->m_pkthdr.len % 2) {
6481 ctl &= ~BWN_PIO_TXCTL_WRITEHI;
6482 BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
6483 BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
6484 }
6485
6486 return (ctl);
6487}
6488
6489static void
6490bwn_set_slot_time(struct bwn_mac *mac, uint16_t time)
6491{
6492
6493 /* XXX should exit if 5GHz band .. */
6494 if (mac->mac_phy.type != BWN_PHYTYPE_G)
6495 return;
6496
6497 BWN_WRITE_2(mac, 0x684, 510 + time);
6498 /* Disabled in Linux b43, can adversely effect performance */
6499#if 0
6500 bwn_shm_write_2(mac, BWN_SHARED, 0x0010, time);
6501#endif
6502}
6503
6504static struct bwn_dma_ring *
6505bwn_dma_select(struct bwn_mac *mac, uint8_t prio)
6506{
6507
6508 if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
6509 return (mac->mac_method.dma.wme[WME_AC_BE]);
6510
6511 switch (prio) {
6512 case 3:
6513 return (mac->mac_method.dma.wme[WME_AC_VO]);
6514 case 2:
6515 return (mac->mac_method.dma.wme[WME_AC_VI]);
6516 case 0:
6517 return (mac->mac_method.dma.wme[WME_AC_BE]);
6518 case 1:
6519 return (mac->mac_method.dma.wme[WME_AC_BK]);
6520 }
6521 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
6522 return (NULL);
6523}
6524
6525static int
6526bwn_dma_getslot(struct bwn_dma_ring *dr)
6527{
6528 int slot;
6529
6530 BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
6531
6532 KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
6533 KASSERT(!(dr->dr_stop), ("%s:%d: fail", __func__, __LINE__));
6534 KASSERT(bwn_dma_freeslot(dr) != 0, ("%s:%d: fail", __func__, __LINE__));
6535
6536 slot = bwn_dma_nextslot(dr, dr->dr_curslot);
6537 KASSERT(!(slot & ~0x0fff), ("%s:%d: fail", __func__, __LINE__));
6538 dr->dr_curslot = slot;
6539 dr->dr_usedslot++;
6540
6541 return (slot);
6542}
6543
6544static struct bwn_pio_txqueue *
6545bwn_pio_parse_cookie(struct bwn_mac *mac, uint16_t cookie,
6546 struct bwn_pio_txpkt **pack)
6547{
6548 struct bwn_pio *pio = &mac->mac_method.pio;
6549 struct bwn_pio_txqueue *tq = NULL;
6550 unsigned int index;
6551
6552 switch (cookie & 0xf000) {
6553 case 0x1000:
6554 tq = &pio->wme[WME_AC_BK];
6555 break;
6556 case 0x2000:
6557 tq = &pio->wme[WME_AC_BE];
6558 break;
6559 case 0x3000:
6560 tq = &pio->wme[WME_AC_VI];
6561 break;
6562 case 0x4000:
6563 tq = &pio->wme[WME_AC_VO];
6564 break;
6565 case 0x5000:
6566 tq = &pio->mcast;
6567 break;
6568 }
6569 KASSERT(tq != NULL, ("%s:%d: fail", __func__, __LINE__));
6570 if (tq == NULL)
6571 return (NULL);
6572 index = (cookie & 0x0fff);
6573 KASSERT(index < N(tq->tq_pkts), ("%s:%d: fail", __func__, __LINE__));
6574 if (index >= N(tq->tq_pkts))
6575 return (NULL);
6576 *pack = &tq->tq_pkts[index];
6577 KASSERT(*pack != NULL, ("%s:%d: fail", __func__, __LINE__));
6578 return (tq);
6579}
6580
6581static void
6582bwn_txpwr(void *arg, int npending)
6583{
6584 struct bwn_mac *mac = arg;
6585 struct bwn_softc *sc = mac->mac_sc;
6586
6587 BWN_LOCK(sc);
6588 if (mac && mac->mac_status >= BWN_MAC_STATUS_STARTED &&
6589 mac->mac_phy.set_txpwr != NULL)
6590 mac->mac_phy.set_txpwr(mac);
6591 BWN_UNLOCK(sc);
6592}
6593
6594static void
6595bwn_task_15s(struct bwn_mac *mac)
6596{
6597 uint16_t reg;
6598
6599 if (mac->mac_fw.opensource) {
6600 reg = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG);
6601 if (reg) {
6602 bwn_restart(mac, "fw watchdog");
6603 return;
6604 }
6605 bwn_shm_write_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG, 1);
6606 }
6607 if (mac->mac_phy.task_15s)
6608 mac->mac_phy.task_15s(mac);
6609
6610 mac->mac_phy.txerrors = BWN_TXERROR_MAX;
6611}
6612
6613static void
6614bwn_task_30s(struct bwn_mac *mac)
6615{
6616
6617 if (mac->mac_phy.type != BWN_PHYTYPE_G || mac->mac_noise.noi_running)
6618 return;
6619 mac->mac_noise.noi_running = 1;
6620 mac->mac_noise.noi_nsamples = 0;
6621
6622 bwn_noise_gensample(mac);
6623}
6624
6625static void
6626bwn_task_60s(struct bwn_mac *mac)
6627{
6628
6629 if (mac->mac_phy.task_60s)
6630 mac->mac_phy.task_60s(mac);
6631 bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME);
6632}
6633
6634static void
6635bwn_tasks(void *arg)
6636{
6637 struct bwn_mac *mac = arg;
6638 struct bwn_softc *sc = mac->mac_sc;
6639
6640 BWN_ASSERT_LOCKED(sc);
6641 if (mac->mac_status != BWN_MAC_STATUS_STARTED)
6642 return;
6643
6644 if (mac->mac_task_state % 4 == 0)
6645 bwn_task_60s(mac);
6646 if (mac->mac_task_state % 2 == 0)
6647 bwn_task_30s(mac);
6648 bwn_task_15s(mac);
6649
6650 mac->mac_task_state++;
6651 callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
6652}
6653
6654static int
6655bwn_plcp_get_ofdmrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp, uint8_t a)
6656{
6657 struct bwn_softc *sc = mac->mac_sc;
6658
6659 KASSERT(a == 0, ("not support APHY\n"));
6660
6661 switch (plcp->o.raw[0] & 0xf) {
6662 case 0xb:
6663 return (BWN_OFDM_RATE_6MB);
6664 case 0xf:
6665 return (BWN_OFDM_RATE_9MB);
6666 case 0xa:
6667 return (BWN_OFDM_RATE_12MB);
6668 case 0xe:
6669 return (BWN_OFDM_RATE_18MB);
6670 case 0x9:
6671 return (BWN_OFDM_RATE_24MB);
6672 case 0xd:
6673 return (BWN_OFDM_RATE_36MB);
6674 case 0x8:
6675 return (BWN_OFDM_RATE_48MB);
6676 case 0xc:
6677 return (BWN_OFDM_RATE_54MB);
6678 }
6679 device_printf(sc->sc_dev, "incorrect OFDM rate %d\n",
6680 plcp->o.raw[0] & 0xf);
6681 return (-1);
6682}
6683
6684static int
6685bwn_plcp_get_cckrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp)
6686{
6687 struct bwn_softc *sc = mac->mac_sc;
6688
6689 switch (plcp->o.raw[0]) {
6690 case 0x0a:
6691 return (BWN_CCK_RATE_1MB);
6692 case 0x14:
6693 return (BWN_CCK_RATE_2MB);
6694 case 0x37:
6695 return (BWN_CCK_RATE_5MB);
6696 case 0x6e:
6697 return (BWN_CCK_RATE_11MB);
6698 }
6699 device_printf(sc->sc_dev, "incorrect CCK rate %d\n", plcp->o.raw[0]);
6700 return (-1);
6701}
6702
6703static void
6704bwn_rx_radiotap(struct bwn_mac *mac, struct mbuf *m,
6705 const struct bwn_rxhdr4 *rxhdr, struct bwn_plcp6 *plcp, int rate,
6706 int rssi, int noise)
6707{
6708 struct bwn_softc *sc = mac->mac_sc;
6709 const struct ieee80211_frame_min *wh;
6710 uint64_t tsf;
6711 uint16_t low_mactime_now;
6712
6713 if (htole16(rxhdr->phy_status0) & BWN_RX_PHYST0_SHORTPRMBL)
6714 sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
6715
6716 wh = mtod(m, const struct ieee80211_frame_min *);
6717 if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED)
6718 sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_WEP;
6719
6720 bwn_tsf_read(mac, &tsf);
6721 low_mactime_now = tsf;
6722 tsf = tsf & ~0xffffULL;
6723 tsf += le16toh(rxhdr->mac_time);
6724 if (low_mactime_now < le16toh(rxhdr->mac_time))
6725 tsf -= 0x10000;
6726
6727 sc->sc_rx_th.wr_tsf = tsf;
6728 sc->sc_rx_th.wr_rate = rate;
6729 sc->sc_rx_th.wr_antsignal = rssi;
6730 sc->sc_rx_th.wr_antnoise = noise;
6731}
6732
6733static void
6734bwn_tsf_read(struct bwn_mac *mac, uint64_t *tsf)
6735{
6736 uint32_t low, high;
6737
6738 KASSERT(siba_get_revid(mac->mac_sc->sc_dev) >= 3,
6739 ("%s:%d: fail", __func__, __LINE__));
6740
6741 low = BWN_READ_4(mac, BWN_REV3PLUS_TSF_LOW);
6742 high = BWN_READ_4(mac, BWN_REV3PLUS_TSF_HIGH);
6743 *tsf = high;
6744 *tsf <<= 32;
6745 *tsf |= low;
6746}
6747
6748static int
6749bwn_dma_attach(struct bwn_mac *mac)
6750{
6751 struct bwn_dma *dma = &mac->mac_method.dma;
6752 struct bwn_softc *sc = mac->mac_sc;
6753 bus_addr_t lowaddr = 0;
6754 int error;
6755
6756 if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
6757 return (0);
6758
6759 KASSERT(siba_get_revid(sc->sc_dev) >= 5, ("%s: fail", __func__));
6760
6761 mac->mac_flags |= BWN_MAC_FLAG_DMA;
6762
6763 dma->dmatype = bwn_dma_gettype(mac);
6764 if (dma->dmatype == BWN_DMA_30BIT)
6765 lowaddr = BWN_BUS_SPACE_MAXADDR_30BIT;
6766 else if (dma->dmatype == BWN_DMA_32BIT)
6767 lowaddr = BUS_SPACE_MAXADDR_32BIT;
6768 else
6769 lowaddr = BUS_SPACE_MAXADDR;
6770
6771 /*
6772 * Create top level DMA tag
6773 */
6774 error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), /* parent */
6775 BWN_ALIGN, 0, /* alignment, bounds */
6776 lowaddr, /* lowaddr */
6777 BUS_SPACE_MAXADDR, /* highaddr */
6778 NULL, NULL, /* filter, filterarg */
6779 BUS_SPACE_MAXSIZE, /* maxsize */
6780 BUS_SPACE_UNRESTRICTED, /* nsegments */
6781 BUS_SPACE_MAXSIZE, /* maxsegsize */
6782 0, /* flags */
6783 NULL, NULL, /* lockfunc, lockarg */
6784 &dma->parent_dtag);
6785 if (error) {
6786 device_printf(sc->sc_dev, "can't create parent DMA tag\n");
6787 return (error);
6788 }
6789
6790 /*
6791 * Create TX/RX mbuf DMA tag
6792 */
6793 error = bus_dma_tag_create(dma->parent_dtag,
6794 1,
6795 0,
6796 BUS_SPACE_MAXADDR,
6797 BUS_SPACE_MAXADDR,
6798 NULL, NULL,
6799 MCLBYTES,
6800 1,
6801 BUS_SPACE_MAXSIZE_32BIT,
6802 0,
6803 NULL, NULL,
6804 &dma->rxbuf_dtag);
6805 if (error) {
6806 device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
6807 goto fail0;
6808 }
6809 error = bus_dma_tag_create(dma->parent_dtag,
6810 1,
6811 0,
6812 BUS_SPACE_MAXADDR,
6813 BUS_SPACE_MAXADDR,
6814 NULL, NULL,
6815 MCLBYTES,
6816 1,
6817 BUS_SPACE_MAXSIZE_32BIT,
6818 0,
6819 NULL, NULL,
6820 &dma->txbuf_dtag);
6821 if (error) {
6822 device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
6823 goto fail1;
6824 }
6825
6826 dma->wme[WME_AC_BK] = bwn_dma_ringsetup(mac, 0, 1, dma->dmatype);
6827 if (!dma->wme[WME_AC_BK])
6828 goto fail2;
6829
6830 dma->wme[WME_AC_BE] = bwn_dma_ringsetup(mac, 1, 1, dma->dmatype);
6831 if (!dma->wme[WME_AC_BE])
6832 goto fail3;
6833
6834 dma->wme[WME_AC_VI] = bwn_dma_ringsetup(mac, 2, 1, dma->dmatype);
6835 if (!dma->wme[WME_AC_VI])
6836 goto fail4;
6837
6838 dma->wme[WME_AC_VO] = bwn_dma_ringsetup(mac, 3, 1, dma->dmatype);
6839 if (!dma->wme[WME_AC_VO])
6840 goto fail5;
6841
6842 dma->mcast = bwn_dma_ringsetup(mac, 4, 1, dma->dmatype);
6843 if (!dma->mcast)
6844 goto fail6;
6845 dma->rx = bwn_dma_ringsetup(mac, 0, 0, dma->dmatype);
6846 if (!dma->rx)
6847 goto fail7;
6848
6849 return (error);
6850
6851fail7: bwn_dma_ringfree(&dma->mcast);
6852fail6: bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
6853fail5: bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
6854fail4: bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
6855fail3: bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
6856fail2: bus_dma_tag_destroy(dma->txbuf_dtag);
6857fail1: bus_dma_tag_destroy(dma->rxbuf_dtag);
6858fail0: bus_dma_tag_destroy(dma->parent_dtag);
6859 return (error);
6860}
6861
6862static struct bwn_dma_ring *
6863bwn_dma_parse_cookie(struct bwn_mac *mac, const struct bwn_txstatus *status,
6864 uint16_t cookie, int *slot)
6865{
6866 struct bwn_dma *dma = &mac->mac_method.dma;
6867 struct bwn_dma_ring *dr;
6868 struct bwn_softc *sc = mac->mac_sc;
6869
6870 BWN_ASSERT_LOCKED(mac->mac_sc);
6871
6872 switch (cookie & 0xf000) {
6873 case 0x1000:
6874 dr = dma->wme[WME_AC_BK];
6875 break;
6876 case 0x2000:
6877 dr = dma->wme[WME_AC_BE];
6878 break;
6879 case 0x3000:
6880 dr = dma->wme[WME_AC_VI];
6881 break;
6882 case 0x4000:
6883 dr = dma->wme[WME_AC_VO];
6884 break;
6885 case 0x5000:
6886 dr = dma->mcast;
6887 break;
6888 default:
6889 dr = NULL;
6890 KASSERT(0 == 1,
6891 ("invalid cookie value %d", cookie & 0xf000));
6892 }
6893 *slot = (cookie & 0x0fff);
6894 if (*slot < 0 || *slot >= dr->dr_numslots) {
6895 /*
6896 * XXX FIXME: sometimes H/W returns TX DONE events duplicately
6897 * that it occurs events which have same H/W sequence numbers.
6898 * When it's occurred just prints a WARNING msgs and ignores.
6899 */
6900 KASSERT(status->seq == dma->lastseq,
6901 ("%s:%d: fail", __func__, __LINE__));
6902 device_printf(sc->sc_dev,
6903 "out of slot ranges (0 < %d < %d)\n", *slot,
6904 dr->dr_numslots);
6905 return (NULL);
6906 }
6907 dma->lastseq = status->seq;
6908 return (dr);
6909}
6910
6911static void
6912bwn_dma_stop(struct bwn_mac *mac)
6913{
6914 struct bwn_dma *dma;
6915
6916 if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
6917 return;
6918 dma = &mac->mac_method.dma;
6919
6920 bwn_dma_ringstop(&dma->rx);
6921 bwn_dma_ringstop(&dma->wme[WME_AC_BK]);
6922 bwn_dma_ringstop(&dma->wme[WME_AC_BE]);
6923 bwn_dma_ringstop(&dma->wme[WME_AC_VI]);
6924 bwn_dma_ringstop(&dma->wme[WME_AC_VO]);
6925 bwn_dma_ringstop(&dma->mcast);
6926}
6927
6928static void
6929bwn_dma_ringstop(struct bwn_dma_ring **dr)
6930{
6931
6932 if (dr == NULL)
6933 return;
6934
6935 bwn_dma_cleanup(*dr);
6936}
6937
6938static void
6939bwn_pio_stop(struct bwn_mac *mac)
6940{
6941 struct bwn_pio *pio;
6942
6943 if (mac->mac_flags & BWN_MAC_FLAG_DMA)
6944 return;
6945 pio = &mac->mac_method.pio;
6946
6947 bwn_destroy_queue_tx(&pio->mcast);
6948 bwn_destroy_queue_tx(&pio->wme[WME_AC_VO]);
6949 bwn_destroy_queue_tx(&pio->wme[WME_AC_VI]);
6950 bwn_destroy_queue_tx(&pio->wme[WME_AC_BE]);
6951 bwn_destroy_queue_tx(&pio->wme[WME_AC_BK]);
6952}
6953
6954static void
6955bwn_led_attach(struct bwn_mac *mac)
6956{
6957 struct bwn_softc *sc = mac->mac_sc;
6958 const uint8_t *led_act = NULL;
6959 uint16_t val[BWN_LED_MAX];
6960 int i;
6961
6962 sc->sc_led_idle = (2350 * hz) / 1000;
6963 sc->sc_led_blink = 1;
6964
6965 for (i = 0; i < N(bwn_vendor_led_act); ++i) {
6966 if (siba_get_pci_subvendor(sc->sc_dev) ==
6967 bwn_vendor_led_act[i].vid) {
6968 led_act = bwn_vendor_led_act[i].led_act;
6969 break;
6970 }
6971 }
6972 if (led_act == NULL)
6973 led_act = bwn_default_led_act;
6974
6975 val[0] = siba_sprom_get_gpio0(sc->sc_dev);
6976 val[1] = siba_sprom_get_gpio1(sc->sc_dev);
6977 val[2] = siba_sprom_get_gpio2(sc->sc_dev);
6978 val[3] = siba_sprom_get_gpio3(sc->sc_dev);
6979
6980 for (i = 0; i < BWN_LED_MAX; ++i) {
6981 struct bwn_led *led = &sc->sc_leds[i];
6982
6983 if (val[i] == 0xff) {
6984 led->led_act = led_act[i];
6985 } else {
6986 if (val[i] & BWN_LED_ACT_LOW)
6987 led->led_flags |= BWN_LED_F_ACTLOW;
6988 led->led_act = val[i] & BWN_LED_ACT_MASK;
6989 }
6990 led->led_mask = (1 << i);
6991
6992 if (led->led_act == BWN_LED_ACT_BLINK_SLOW ||
6993 led->led_act == BWN_LED_ACT_BLINK_POLL ||
6994 led->led_act == BWN_LED_ACT_BLINK) {
6995 led->led_flags |= BWN_LED_F_BLINK;
6996 if (led->led_act == BWN_LED_ACT_BLINK_POLL)
6997 led->led_flags |= BWN_LED_F_POLLABLE;
6998 else if (led->led_act == BWN_LED_ACT_BLINK_SLOW)
6999 led->led_flags |= BWN_LED_F_SLOW;
7000
7001 if (sc->sc_blink_led == NULL) {
7002 sc->sc_blink_led = led;
7003 if (led->led_flags & BWN_LED_F_SLOW)
7004 BWN_LED_SLOWDOWN(sc->sc_led_idle);
7005 }
7006 }
7007
7008 DPRINTF(sc, BWN_DEBUG_LED,
7009 "%dth led, act %d, lowact %d\n", i,
7010 led->led_act, led->led_flags & BWN_LED_F_ACTLOW);
7011 }
7012 callout_init_mtx(&sc->sc_led_blink_ch, &sc->sc_mtx, 0);
7013}
7014
7015static __inline uint16_t
7016bwn_led_onoff(const struct bwn_led *led, uint16_t val, int on)
7017{
7018
7019 if (led->led_flags & BWN_LED_F_ACTLOW)
7020 on = !on;
7021 if (on)
7022 val |= led->led_mask;
7023 else
7024 val &= ~led->led_mask;
7025 return val;
7026}
7027
7028static void
7029bwn_led_newstate(struct bwn_mac *mac, enum ieee80211_state nstate)
7030{
7031 struct bwn_softc *sc = mac->mac_sc;
7032 struct ieee80211com *ic = &sc->sc_ic;
7033 uint16_t val;
7034 int i;
7035
7036 if (nstate == IEEE80211_S_INIT) {
7037 callout_stop(&sc->sc_led_blink_ch);
7038 sc->sc_led_blinking = 0;
7039 }
7040
7041 if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0)
7042 return;
7043
7044 val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
7045 for (i = 0; i < BWN_LED_MAX; ++i) {
7046 struct bwn_led *led = &sc->sc_leds[i];
7047 int on;
7048
7049 if (led->led_act == BWN_LED_ACT_UNKN ||
7050 led->led_act == BWN_LED_ACT_NULL)
7051 continue;
7052
7053 if ((led->led_flags & BWN_LED_F_BLINK) &&
7054 nstate != IEEE80211_S_INIT)
7055 continue;
7056
7057 switch (led->led_act) {
7058 case BWN_LED_ACT_ON: /* Always on */
7059 on = 1;
7060 break;
7061 case BWN_LED_ACT_OFF: /* Always off */
7062 case BWN_LED_ACT_5GHZ: /* TODO: 11A */
7063 on = 0;
7064 break;
7065 default:
7066 on = 1;
7067 switch (nstate) {
7068 case IEEE80211_S_INIT:
7069 on = 0;
7070 break;
7071 case IEEE80211_S_RUN:
7072 if (led->led_act == BWN_LED_ACT_11G &&
7073 ic->ic_curmode != IEEE80211_MODE_11G)
7074 on = 0;
7075 break;
7076 default:
7077 if (led->led_act == BWN_LED_ACT_ASSOC)
7078 on = 0;
7079 break;
7080 }
7081 break;
7082 }
7083
7084 val = bwn_led_onoff(led, val, on);
7085 }
7086 BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
7087}
7088
7089static void
7090bwn_led_event(struct bwn_mac *mac, int event)
7091{
7092 struct bwn_softc *sc = mac->mac_sc;
7093 struct bwn_led *led = sc->sc_blink_led;
7094 int rate;
7095
7096 if (event == BWN_LED_EVENT_POLL) {
7097 if ((led->led_flags & BWN_LED_F_POLLABLE) == 0)
7098 return;
7099 if (ticks - sc->sc_led_ticks < sc->sc_led_idle)
7100 return;
7101 }
7102
7103 sc->sc_led_ticks = ticks;
7104 if (sc->sc_led_blinking)
7105 return;
7106
7107 switch (event) {
7108 case BWN_LED_EVENT_RX:
7109 rate = sc->sc_rx_rate;
7110 break;
7111 case BWN_LED_EVENT_TX:
7112 rate = sc->sc_tx_rate;
7113 break;
7114 case BWN_LED_EVENT_POLL:
7115 rate = 0;
7116 break;
7117 default:
7118 panic("unknown LED event %d\n", event);
7119 break;
7120 }
7121 bwn_led_blink_start(mac, bwn_led_duration[rate].on_dur,
7122 bwn_led_duration[rate].off_dur);
7123}
7124
7125static void
7126bwn_led_blink_start(struct bwn_mac *mac, int on_dur, int off_dur)
7127{
7128 struct bwn_softc *sc = mac->mac_sc;
7129 struct bwn_led *led = sc->sc_blink_led;
7130 uint16_t val;
7131
7132 val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
7133 val = bwn_led_onoff(led, val, 1);
7134 BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
7135
7136 if (led->led_flags & BWN_LED_F_SLOW) {
7137 BWN_LED_SLOWDOWN(on_dur);
7138 BWN_LED_SLOWDOWN(off_dur);
7139 }
7140
7141 sc->sc_led_blinking = 1;
7142 sc->sc_led_blink_offdur = off_dur;
7143
7144 callout_reset(&sc->sc_led_blink_ch, on_dur, bwn_led_blink_next, mac);
7145}
7146
7147static void
7148bwn_led_blink_next(void *arg)
7149{
7150 struct bwn_mac *mac = arg;
7151 struct bwn_softc *sc = mac->mac_sc;
7152 uint16_t val;
7153
7154 val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
7155 val = bwn_led_onoff(sc->sc_blink_led, val, 0);
7156 BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
7157
7158 callout_reset(&sc->sc_led_blink_ch, sc->sc_led_blink_offdur,
7159 bwn_led_blink_end, mac);
7160}
7161
7162static void
7163bwn_led_blink_end(void *arg)
7164{
7165 struct bwn_mac *mac = arg;
7166 struct bwn_softc *sc = mac->mac_sc;
7167
7168 sc->sc_led_blinking = 0;
7169}
7170
7171static int
7172bwn_suspend(device_t dev)
7173{
7174 struct bwn_softc *sc = device_get_softc(dev);
7175
7176 BWN_LOCK(sc);
7177 bwn_stop(sc);
7178 BWN_UNLOCK(sc);
7179 return (0);
7180}
7181
7182static int
7183bwn_resume(device_t dev)
7184{
7185 struct bwn_softc *sc = device_get_softc(dev);
7186 int error = EDOOFUS;
7187
7188 BWN_LOCK(sc);
7189 if (sc->sc_ic.ic_nrunning > 0)
7190 error = bwn_init(sc);
7191 BWN_UNLOCK(sc);
7192 if (error == 0)
7193 ieee80211_start_all(&sc->sc_ic);
7194 return (0);
7195}
7196
7197static void
7198bwn_rfswitch(void *arg)
7199{
7200 struct bwn_softc *sc = arg;
7201 struct bwn_mac *mac = sc->sc_curmac;
7202 int cur = 0, prev = 0;
7203
7204 KASSERT(mac->mac_status >= BWN_MAC_STATUS_STARTED,
7205 ("%s: invalid MAC status %d", __func__, mac->mac_status));
7206
7207 if (mac->mac_phy.rev >= 3 || mac->mac_phy.type == BWN_PHYTYPE_LP
7208 || mac->mac_phy.type == BWN_PHYTYPE_N) {
7209 if (!(BWN_READ_4(mac, BWN_RF_HWENABLED_HI)
7210 & BWN_RF_HWENABLED_HI_MASK))
7211 cur = 1;
7212 } else {
7213 if (BWN_READ_2(mac, BWN_RF_HWENABLED_LO)
7214 & BWN_RF_HWENABLED_LO_MASK)
7215 cur = 1;
7216 }
7217
7218 if (mac->mac_flags & BWN_MAC_FLAG_RADIO_ON)
7219 prev = 1;
7220
7221 DPRINTF(sc, BWN_DEBUG_RESET, "%s: called; cur=%d, prev=%d\n",
7222 __func__, cur, prev);
7223
7224 if (cur != prev) {
7225 if (cur)
7226 mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
7227 else
7228 mac->mac_flags &= ~BWN_MAC_FLAG_RADIO_ON;
7229
7230 device_printf(sc->sc_dev,
7231 "status of RF switch is changed to %s\n",
7232 cur ? "ON" : "OFF");
7233 if (cur != mac->mac_phy.rf_on) {
7234 if (cur)
7235 bwn_rf_turnon(mac);
7236 else
7237 bwn_rf_turnoff(mac);
7238 }
7239 }
7240
7241 callout_schedule(&sc->sc_rfswitch_ch, hz);
7242}
7243
7244static void
7245bwn_sysctl_node(struct bwn_softc *sc)
7246{
7247 device_t dev = sc->sc_dev;
7248 struct bwn_mac *mac;
7249 struct bwn_stats *stats;
7250
7251 /* XXX assume that count of MAC is only 1. */
7252
7253 if ((mac = sc->sc_curmac) == NULL)
7254 return;
7255 stats = &mac->mac_stats;
7256
7257 SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
7258 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
7259 "linknoise", CTLFLAG_RW, &stats->rts, 0, "Noise level");
7260 SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
7261 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
7262 "rts", CTLFLAG_RW, &stats->rts, 0, "RTS");
7263 SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
7264 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
7265 "rtsfail", CTLFLAG_RW, &stats->rtsfail, 0, "RTS failed to send");
7266
7267#ifdef BWN_DEBUG
7268 SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
7269 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
7270 "debug", CTLFLAG_RW, &sc->sc_debug, 0, "Debug flags");
7271#endif
7272}
7273
7274static device_method_t bwn_methods[] = {
7275 /* Device interface */
7276 DEVMETHOD(device_probe, bwn_probe),
7277 DEVMETHOD(device_attach, bwn_attach),
7278 DEVMETHOD(device_detach, bwn_detach),
7279 DEVMETHOD(device_suspend, bwn_suspend),
7280 DEVMETHOD(device_resume, bwn_resume),
7281 DEVMETHOD_END
7282};
7283static driver_t bwn_driver = {
7284 "bwn",
7285 bwn_methods,
7286 sizeof(struct bwn_softc)
7287};
7288static devclass_t bwn_devclass;
7289DRIVER_MODULE(bwn, siba_bwn, bwn_driver, bwn_devclass, 0, 0);
7290MODULE_DEPEND(bwn, siba_bwn, 1, 1, 1);
7291MODULE_DEPEND(bwn, wlan, 1, 1, 1); /* 802.11 media layer */
7292MODULE_DEPEND(bwn, firmware, 1, 1, 1); /* firmware support */
7293MODULE_DEPEND(bwn, wlan_amrr, 1, 1, 1);
7294MODULE_VERSION(bwn, 1);
2812 }
2813 free((*dr)->dr_meta, M_DEVBUF);
2814 free(*dr, M_DEVBUF);
2815
2816 *dr = NULL;
2817}
2818
2819static void
2820bwn_dma_32_getdesc(struct bwn_dma_ring *dr, int slot,
2821 struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
2822{
2823 struct bwn_dmadesc32 *desc;
2824
2825 *meta = &(dr->dr_meta[slot]);
2826 desc = dr->dr_ring_descbase;
2827 desc = &(desc[slot]);
2828
2829 *gdesc = (struct bwn_dmadesc_generic *)desc;
2830}
2831
2832static void
2833bwn_dma_32_setdesc(struct bwn_dma_ring *dr,
2834 struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
2835 int start, int end, int irq)
2836{
2837 struct bwn_dmadesc32 *descbase = dr->dr_ring_descbase;
2838 struct bwn_softc *sc = dr->dr_mac->mac_sc;
2839 uint32_t addr, addrext, ctl;
2840 int slot;
2841
2842 slot = (int)(&(desc->dma.dma32) - descbase);
2843 KASSERT(slot >= 0 && slot < dr->dr_numslots,
2844 ("%s:%d: fail", __func__, __LINE__));
2845
2846 addr = (uint32_t) (dmaaddr & ~SIBA_DMA_TRANSLATION_MASK);
2847 addrext = (uint32_t) (dmaaddr & SIBA_DMA_TRANSLATION_MASK) >> 30;
2848 addr |= siba_dma_translation(sc->sc_dev);
2849 ctl = bufsize & BWN_DMA32_DCTL_BYTECNT;
2850 if (slot == dr->dr_numslots - 1)
2851 ctl |= BWN_DMA32_DCTL_DTABLEEND;
2852 if (start)
2853 ctl |= BWN_DMA32_DCTL_FRAMESTART;
2854 if (end)
2855 ctl |= BWN_DMA32_DCTL_FRAMEEND;
2856 if (irq)
2857 ctl |= BWN_DMA32_DCTL_IRQ;
2858 ctl |= (addrext << BWN_DMA32_DCTL_ADDREXT_SHIFT)
2859 & BWN_DMA32_DCTL_ADDREXT_MASK;
2860
2861 desc->dma.dma32.control = htole32(ctl);
2862 desc->dma.dma32.address = htole32(addr);
2863}
2864
2865static void
2866bwn_dma_32_start_transfer(struct bwn_dma_ring *dr, int slot)
2867{
2868
2869 BWN_DMA_WRITE(dr, BWN_DMA32_TXINDEX,
2870 (uint32_t)(slot * sizeof(struct bwn_dmadesc32)));
2871}
2872
2873static void
2874bwn_dma_32_suspend(struct bwn_dma_ring *dr)
2875{
2876
2877 BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
2878 BWN_DMA_READ(dr, BWN_DMA32_TXCTL) | BWN_DMA32_TXSUSPEND);
2879}
2880
2881static void
2882bwn_dma_32_resume(struct bwn_dma_ring *dr)
2883{
2884
2885 BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
2886 BWN_DMA_READ(dr, BWN_DMA32_TXCTL) & ~BWN_DMA32_TXSUSPEND);
2887}
2888
2889static int
2890bwn_dma_32_get_curslot(struct bwn_dma_ring *dr)
2891{
2892 uint32_t val;
2893
2894 val = BWN_DMA_READ(dr, BWN_DMA32_RXSTATUS);
2895 val &= BWN_DMA32_RXDPTR;
2896
2897 return (val / sizeof(struct bwn_dmadesc32));
2898}
2899
2900static void
2901bwn_dma_32_set_curslot(struct bwn_dma_ring *dr, int slot)
2902{
2903
2904 BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX,
2905 (uint32_t) (slot * sizeof(struct bwn_dmadesc32)));
2906}
2907
2908static void
2909bwn_dma_64_getdesc(struct bwn_dma_ring *dr, int slot,
2910 struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
2911{
2912 struct bwn_dmadesc64 *desc;
2913
2914 *meta = &(dr->dr_meta[slot]);
2915 desc = dr->dr_ring_descbase;
2916 desc = &(desc[slot]);
2917
2918 *gdesc = (struct bwn_dmadesc_generic *)desc;
2919}
2920
2921static void
2922bwn_dma_64_setdesc(struct bwn_dma_ring *dr,
2923 struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
2924 int start, int end, int irq)
2925{
2926 struct bwn_dmadesc64 *descbase = dr->dr_ring_descbase;
2927 struct bwn_softc *sc = dr->dr_mac->mac_sc;
2928 int slot;
2929 uint32_t ctl0 = 0, ctl1 = 0;
2930 uint32_t addrlo, addrhi;
2931 uint32_t addrext;
2932
2933 slot = (int)(&(desc->dma.dma64) - descbase);
2934 KASSERT(slot >= 0 && slot < dr->dr_numslots,
2935 ("%s:%d: fail", __func__, __LINE__));
2936
2937 addrlo = (uint32_t) (dmaaddr & 0xffffffff);
2938 addrhi = (((uint64_t) dmaaddr >> 32) & ~SIBA_DMA_TRANSLATION_MASK);
2939 addrext = (((uint64_t) dmaaddr >> 32) & SIBA_DMA_TRANSLATION_MASK) >>
2940 30;
2941 addrhi |= (siba_dma_translation(sc->sc_dev) << 1);
2942 if (slot == dr->dr_numslots - 1)
2943 ctl0 |= BWN_DMA64_DCTL0_DTABLEEND;
2944 if (start)
2945 ctl0 |= BWN_DMA64_DCTL0_FRAMESTART;
2946 if (end)
2947 ctl0 |= BWN_DMA64_DCTL0_FRAMEEND;
2948 if (irq)
2949 ctl0 |= BWN_DMA64_DCTL0_IRQ;
2950 ctl1 |= bufsize & BWN_DMA64_DCTL1_BYTECNT;
2951 ctl1 |= (addrext << BWN_DMA64_DCTL1_ADDREXT_SHIFT)
2952 & BWN_DMA64_DCTL1_ADDREXT_MASK;
2953
2954 desc->dma.dma64.control0 = htole32(ctl0);
2955 desc->dma.dma64.control1 = htole32(ctl1);
2956 desc->dma.dma64.address_low = htole32(addrlo);
2957 desc->dma.dma64.address_high = htole32(addrhi);
2958}
2959
2960static void
2961bwn_dma_64_start_transfer(struct bwn_dma_ring *dr, int slot)
2962{
2963
2964 BWN_DMA_WRITE(dr, BWN_DMA64_TXINDEX,
2965 (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
2966}
2967
2968static void
2969bwn_dma_64_suspend(struct bwn_dma_ring *dr)
2970{
2971
2972 BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
2973 BWN_DMA_READ(dr, BWN_DMA64_TXCTL) | BWN_DMA64_TXSUSPEND);
2974}
2975
2976static void
2977bwn_dma_64_resume(struct bwn_dma_ring *dr)
2978{
2979
2980 BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
2981 BWN_DMA_READ(dr, BWN_DMA64_TXCTL) & ~BWN_DMA64_TXSUSPEND);
2982}
2983
2984static int
2985bwn_dma_64_get_curslot(struct bwn_dma_ring *dr)
2986{
2987 uint32_t val;
2988
2989 val = BWN_DMA_READ(dr, BWN_DMA64_RXSTATUS);
2990 val &= BWN_DMA64_RXSTATDPTR;
2991
2992 return (val / sizeof(struct bwn_dmadesc64));
2993}
2994
2995static void
2996bwn_dma_64_set_curslot(struct bwn_dma_ring *dr, int slot)
2997{
2998
2999 BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX,
3000 (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
3001}
3002
3003static int
3004bwn_dma_allocringmemory(struct bwn_dma_ring *dr)
3005{
3006 struct bwn_mac *mac = dr->dr_mac;
3007 struct bwn_dma *dma = &mac->mac_method.dma;
3008 struct bwn_softc *sc = mac->mac_sc;
3009 int error;
3010
3011 error = bus_dma_tag_create(dma->parent_dtag,
3012 BWN_ALIGN, 0,
3013 BUS_SPACE_MAXADDR,
3014 BUS_SPACE_MAXADDR,
3015 NULL, NULL,
3016 BWN_DMA_RINGMEMSIZE,
3017 1,
3018 BUS_SPACE_MAXSIZE_32BIT,
3019 0,
3020 NULL, NULL,
3021 &dr->dr_ring_dtag);
3022 if (error) {
3023 device_printf(sc->sc_dev,
3024 "can't create TX ring DMA tag: TODO frees\n");
3025 return (-1);
3026 }
3027
3028 error = bus_dmamem_alloc(dr->dr_ring_dtag,
3029 &dr->dr_ring_descbase, BUS_DMA_WAITOK | BUS_DMA_ZERO,
3030 &dr->dr_ring_dmap);
3031 if (error) {
3032 device_printf(sc->sc_dev,
3033 "can't allocate DMA mem: TODO frees\n");
3034 return (-1);
3035 }
3036 error = bus_dmamap_load(dr->dr_ring_dtag, dr->dr_ring_dmap,
3037 dr->dr_ring_descbase, BWN_DMA_RINGMEMSIZE,
3038 bwn_dma_ring_addr, &dr->dr_ring_dmabase, BUS_DMA_NOWAIT);
3039 if (error) {
3040 device_printf(sc->sc_dev,
3041 "can't load DMA mem: TODO free\n");
3042 return (-1);
3043 }
3044
3045 return (0);
3046}
3047
3048static void
3049bwn_dma_setup(struct bwn_dma_ring *dr)
3050{
3051 struct bwn_softc *sc = dr->dr_mac->mac_sc;
3052 uint64_t ring64;
3053 uint32_t addrext, ring32, value;
3054 uint32_t trans = siba_dma_translation(sc->sc_dev);
3055
3056 if (dr->dr_tx) {
3057 dr->dr_curslot = -1;
3058
3059 if (dr->dr_type == BWN_DMA_64BIT) {
3060 ring64 = (uint64_t)(dr->dr_ring_dmabase);
3061 addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK)
3062 >> 30;
3063 value = BWN_DMA64_TXENABLE;
3064 value |= (addrext << BWN_DMA64_TXADDREXT_SHIFT)
3065 & BWN_DMA64_TXADDREXT_MASK;
3066 BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL, value);
3067 BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO,
3068 (ring64 & 0xffffffff));
3069 BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI,
3070 ((ring64 >> 32) &
3071 ~SIBA_DMA_TRANSLATION_MASK) | (trans << 1));
3072 } else {
3073 ring32 = (uint32_t)(dr->dr_ring_dmabase);
3074 addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
3075 value = BWN_DMA32_TXENABLE;
3076 value |= (addrext << BWN_DMA32_TXADDREXT_SHIFT)
3077 & BWN_DMA32_TXADDREXT_MASK;
3078 BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL, value);
3079 BWN_DMA_WRITE(dr, BWN_DMA32_TXRING,
3080 (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
3081 }
3082 return;
3083 }
3084
3085 /*
3086 * set for RX
3087 */
3088 dr->dr_usedslot = dr->dr_numslots;
3089
3090 if (dr->dr_type == BWN_DMA_64BIT) {
3091 ring64 = (uint64_t)(dr->dr_ring_dmabase);
3092 addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK) >> 30;
3093 value = (dr->dr_frameoffset << BWN_DMA64_RXFROFF_SHIFT);
3094 value |= BWN_DMA64_RXENABLE;
3095 value |= (addrext << BWN_DMA64_RXADDREXT_SHIFT)
3096 & BWN_DMA64_RXADDREXT_MASK;
3097 BWN_DMA_WRITE(dr, BWN_DMA64_RXCTL, value);
3098 BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, (ring64 & 0xffffffff));
3099 BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI,
3100 ((ring64 >> 32) & ~SIBA_DMA_TRANSLATION_MASK)
3101 | (trans << 1));
3102 BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX, dr->dr_numslots *
3103 sizeof(struct bwn_dmadesc64));
3104 } else {
3105 ring32 = (uint32_t)(dr->dr_ring_dmabase);
3106 addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
3107 value = (dr->dr_frameoffset << BWN_DMA32_RXFROFF_SHIFT);
3108 value |= BWN_DMA32_RXENABLE;
3109 value |= (addrext << BWN_DMA32_RXADDREXT_SHIFT)
3110 & BWN_DMA32_RXADDREXT_MASK;
3111 BWN_DMA_WRITE(dr, BWN_DMA32_RXCTL, value);
3112 BWN_DMA_WRITE(dr, BWN_DMA32_RXRING,
3113 (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
3114 BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX, dr->dr_numslots *
3115 sizeof(struct bwn_dmadesc32));
3116 }
3117}
3118
3119static void
3120bwn_dma_free_ringmemory(struct bwn_dma_ring *dr)
3121{
3122
3123 bus_dmamap_unload(dr->dr_ring_dtag, dr->dr_ring_dmap);
3124 bus_dmamem_free(dr->dr_ring_dtag, dr->dr_ring_descbase,
3125 dr->dr_ring_dmap);
3126}
3127
3128static void
3129bwn_dma_cleanup(struct bwn_dma_ring *dr)
3130{
3131
3132 if (dr->dr_tx) {
3133 bwn_dma_tx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
3134 if (dr->dr_type == BWN_DMA_64BIT) {
3135 BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO, 0);
3136 BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI, 0);
3137 } else
3138 BWN_DMA_WRITE(dr, BWN_DMA32_TXRING, 0);
3139 } else {
3140 bwn_dma_rx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
3141 if (dr->dr_type == BWN_DMA_64BIT) {
3142 BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, 0);
3143 BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI, 0);
3144 } else
3145 BWN_DMA_WRITE(dr, BWN_DMA32_RXRING, 0);
3146 }
3147}
3148
3149static void
3150bwn_dma_free_descbufs(struct bwn_dma_ring *dr)
3151{
3152 struct bwn_dmadesc_generic *desc;
3153 struct bwn_dmadesc_meta *meta;
3154 struct bwn_mac *mac = dr->dr_mac;
3155 struct bwn_dma *dma = &mac->mac_method.dma;
3156 struct bwn_softc *sc = mac->mac_sc;
3157 int i;
3158
3159 if (!dr->dr_usedslot)
3160 return;
3161 for (i = 0; i < dr->dr_numslots; i++) {
3162 dr->getdesc(dr, i, &desc, &meta);
3163
3164 if (meta->mt_m == NULL) {
3165 if (!dr->dr_tx)
3166 device_printf(sc->sc_dev, "%s: not TX?\n",
3167 __func__);
3168 continue;
3169 }
3170 if (dr->dr_tx) {
3171 if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
3172 bus_dmamap_unload(dr->dr_txring_dtag,
3173 meta->mt_dmap);
3174 else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
3175 bus_dmamap_unload(dma->txbuf_dtag,
3176 meta->mt_dmap);
3177 } else
3178 bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
3179 bwn_dma_free_descbuf(dr, meta);
3180 }
3181}
3182
3183static int
3184bwn_dma_tx_reset(struct bwn_mac *mac, uint16_t base,
3185 int type)
3186{
3187 struct bwn_softc *sc = mac->mac_sc;
3188 uint32_t value;
3189 int i;
3190 uint16_t offset;
3191
3192 for (i = 0; i < 10; i++) {
3193 offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
3194 BWN_DMA32_TXSTATUS;
3195 value = BWN_READ_4(mac, base + offset);
3196 if (type == BWN_DMA_64BIT) {
3197 value &= BWN_DMA64_TXSTAT;
3198 if (value == BWN_DMA64_TXSTAT_DISABLED ||
3199 value == BWN_DMA64_TXSTAT_IDLEWAIT ||
3200 value == BWN_DMA64_TXSTAT_STOPPED)
3201 break;
3202 } else {
3203 value &= BWN_DMA32_TXSTATE;
3204 if (value == BWN_DMA32_TXSTAT_DISABLED ||
3205 value == BWN_DMA32_TXSTAT_IDLEWAIT ||
3206 value == BWN_DMA32_TXSTAT_STOPPED)
3207 break;
3208 }
3209 DELAY(1000);
3210 }
3211 offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXCTL : BWN_DMA32_TXCTL;
3212 BWN_WRITE_4(mac, base + offset, 0);
3213 for (i = 0; i < 10; i++) {
3214 offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
3215 BWN_DMA32_TXSTATUS;
3216 value = BWN_READ_4(mac, base + offset);
3217 if (type == BWN_DMA_64BIT) {
3218 value &= BWN_DMA64_TXSTAT;
3219 if (value == BWN_DMA64_TXSTAT_DISABLED) {
3220 i = -1;
3221 break;
3222 }
3223 } else {
3224 value &= BWN_DMA32_TXSTATE;
3225 if (value == BWN_DMA32_TXSTAT_DISABLED) {
3226 i = -1;
3227 break;
3228 }
3229 }
3230 DELAY(1000);
3231 }
3232 if (i != -1) {
3233 device_printf(sc->sc_dev, "%s: timed out\n", __func__);
3234 return (ENODEV);
3235 }
3236 DELAY(1000);
3237
3238 return (0);
3239}
3240
3241static int
3242bwn_dma_rx_reset(struct bwn_mac *mac, uint16_t base,
3243 int type)
3244{
3245 struct bwn_softc *sc = mac->mac_sc;
3246 uint32_t value;
3247 int i;
3248 uint16_t offset;
3249
3250 offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXCTL : BWN_DMA32_RXCTL;
3251 BWN_WRITE_4(mac, base + offset, 0);
3252 for (i = 0; i < 10; i++) {
3253 offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXSTATUS :
3254 BWN_DMA32_RXSTATUS;
3255 value = BWN_READ_4(mac, base + offset);
3256 if (type == BWN_DMA_64BIT) {
3257 value &= BWN_DMA64_RXSTAT;
3258 if (value == BWN_DMA64_RXSTAT_DISABLED) {
3259 i = -1;
3260 break;
3261 }
3262 } else {
3263 value &= BWN_DMA32_RXSTATE;
3264 if (value == BWN_DMA32_RXSTAT_DISABLED) {
3265 i = -1;
3266 break;
3267 }
3268 }
3269 DELAY(1000);
3270 }
3271 if (i != -1) {
3272 device_printf(sc->sc_dev, "%s: timed out\n", __func__);
3273 return (ENODEV);
3274 }
3275
3276 return (0);
3277}
3278
3279static void
3280bwn_dma_free_descbuf(struct bwn_dma_ring *dr,
3281 struct bwn_dmadesc_meta *meta)
3282{
3283
3284 if (meta->mt_m != NULL) {
3285 m_freem(meta->mt_m);
3286 meta->mt_m = NULL;
3287 }
3288 if (meta->mt_ni != NULL) {
3289 ieee80211_free_node(meta->mt_ni);
3290 meta->mt_ni = NULL;
3291 }
3292}
3293
3294static void
3295bwn_dma_set_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
3296{
3297 struct bwn_rxhdr4 *rxhdr;
3298 unsigned char *frame;
3299
3300 rxhdr = mtod(m, struct bwn_rxhdr4 *);
3301 rxhdr->frame_len = 0;
3302
3303 KASSERT(dr->dr_rx_bufsize >= dr->dr_frameoffset +
3304 sizeof(struct bwn_plcp6) + 2,
3305 ("%s:%d: fail", __func__, __LINE__));
3306 frame = mtod(m, char *) + dr->dr_frameoffset;
3307 memset(frame, 0xff, sizeof(struct bwn_plcp6) + 2 /* padding */);
3308}
3309
3310static uint8_t
3311bwn_dma_check_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
3312{
3313 unsigned char *f = mtod(m, char *) + dr->dr_frameoffset;
3314
3315 return ((f[0] & f[1] & f[2] & f[3] & f[4] & f[5] & f[6] & f[7])
3316 == 0xff);
3317}
3318
3319static void
3320bwn_wme_init(struct bwn_mac *mac)
3321{
3322
3323 bwn_wme_load(mac);
3324
3325 /* enable WME support. */
3326 bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_EDCF);
3327 BWN_WRITE_2(mac, BWN_IFSCTL, BWN_READ_2(mac, BWN_IFSCTL) |
3328 BWN_IFSCTL_USE_EDCF);
3329}
3330
3331static void
3332bwn_spu_setdelay(struct bwn_mac *mac, int idle)
3333{
3334 struct bwn_softc *sc = mac->mac_sc;
3335 struct ieee80211com *ic = &sc->sc_ic;
3336 uint16_t delay; /* microsec */
3337
3338 delay = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 3700 : 1050;
3339 if (ic->ic_opmode == IEEE80211_M_IBSS || idle)
3340 delay = 500;
3341 if ((mac->mac_phy.rf_ver == 0x2050) && (mac->mac_phy.rf_rev == 8))
3342 delay = max(delay, (uint16_t)2400);
3343
3344 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SPU_WAKEUP, delay);
3345}
3346
3347static void
3348bwn_bt_enable(struct bwn_mac *mac)
3349{
3350 struct bwn_softc *sc = mac->mac_sc;
3351 uint64_t hf;
3352
3353 if (bwn_bluetooth == 0)
3354 return;
3355 if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCOEXIST) == 0)
3356 return;
3357 if (mac->mac_phy.type != BWN_PHYTYPE_B && !mac->mac_phy.gmode)
3358 return;
3359
3360 hf = bwn_hf_read(mac);
3361 if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCMOD)
3362 hf |= BWN_HF_BT_COEXISTALT;
3363 else
3364 hf |= BWN_HF_BT_COEXIST;
3365 bwn_hf_write(mac, hf);
3366}
3367
3368static void
3369bwn_set_macaddr(struct bwn_mac *mac)
3370{
3371
3372 bwn_mac_write_bssid(mac);
3373 bwn_mac_setfilter(mac, BWN_MACFILTER_SELF,
3374 mac->mac_sc->sc_ic.ic_macaddr);
3375}
3376
3377static void
3378bwn_clear_keys(struct bwn_mac *mac)
3379{
3380 int i;
3381
3382 for (i = 0; i < mac->mac_max_nr_keys; i++) {
3383 KASSERT(i >= 0 && i < mac->mac_max_nr_keys,
3384 ("%s:%d: fail", __func__, __LINE__));
3385
3386 bwn_key_dowrite(mac, i, BWN_SEC_ALGO_NONE,
3387 NULL, BWN_SEC_KEYSIZE, NULL);
3388 if ((i <= 3) && !BWN_SEC_NEWAPI(mac)) {
3389 bwn_key_dowrite(mac, i + 4, BWN_SEC_ALGO_NONE,
3390 NULL, BWN_SEC_KEYSIZE, NULL);
3391 }
3392 mac->mac_key[i].keyconf = NULL;
3393 }
3394}
3395
3396static void
3397bwn_crypt_init(struct bwn_mac *mac)
3398{
3399 struct bwn_softc *sc = mac->mac_sc;
3400
3401 mac->mac_max_nr_keys = (siba_get_revid(sc->sc_dev) >= 5) ? 58 : 20;
3402 KASSERT(mac->mac_max_nr_keys <= N(mac->mac_key),
3403 ("%s:%d: fail", __func__, __LINE__));
3404 mac->mac_ktp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_KEY_TABLEP);
3405 mac->mac_ktp *= 2;
3406 if (siba_get_revid(sc->sc_dev) >= 5)
3407 BWN_WRITE_2(mac, BWN_RCMTA_COUNT, mac->mac_max_nr_keys - 8);
3408 bwn_clear_keys(mac);
3409}
3410
3411static void
3412bwn_chip_exit(struct bwn_mac *mac)
3413{
3414 struct bwn_softc *sc = mac->mac_sc;
3415
3416 bwn_phy_exit(mac);
3417 siba_gpio_set(sc->sc_dev, 0);
3418}
3419
3420static int
3421bwn_fw_fillinfo(struct bwn_mac *mac)
3422{
3423 int error;
3424
3425 error = bwn_fw_gets(mac, BWN_FWTYPE_DEFAULT);
3426 if (error == 0)
3427 return (0);
3428 error = bwn_fw_gets(mac, BWN_FWTYPE_OPENSOURCE);
3429 if (error == 0)
3430 return (0);
3431 return (error);
3432}
3433
3434static int
3435bwn_gpio_init(struct bwn_mac *mac)
3436{
3437 struct bwn_softc *sc = mac->mac_sc;
3438 uint32_t mask = 0x1f, set = 0xf, value;
3439
3440 BWN_WRITE_4(mac, BWN_MACCTL,
3441 BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GPOUT_MASK);
3442 BWN_WRITE_2(mac, BWN_GPIO_MASK,
3443 BWN_READ_2(mac, BWN_GPIO_MASK) | 0x000f);
3444
3445 if (siba_get_chipid(sc->sc_dev) == 0x4301) {
3446 mask |= 0x0060;
3447 set |= 0x0060;
3448 }
3449 if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL) {
3450 BWN_WRITE_2(mac, BWN_GPIO_MASK,
3451 BWN_READ_2(mac, BWN_GPIO_MASK) | 0x0200);
3452 mask |= 0x0200;
3453 set |= 0x0200;
3454 }
3455 if (siba_get_revid(sc->sc_dev) >= 2)
3456 mask |= 0x0010;
3457
3458 value = siba_gpio_get(sc->sc_dev);
3459 if (value == -1)
3460 return (0);
3461 siba_gpio_set(sc->sc_dev, (value & mask) | set);
3462
3463 return (0);
3464}
3465
3466static int
3467bwn_fw_loadinitvals(struct bwn_mac *mac)
3468{
3469#define GETFWOFFSET(fwp, offset) \
3470 ((const struct bwn_fwinitvals *)((const char *)fwp.fw->data + offset))
3471 const size_t hdr_len = sizeof(struct bwn_fwhdr);
3472 const struct bwn_fwhdr *hdr;
3473 struct bwn_fw *fw = &mac->mac_fw;
3474 int error;
3475
3476 hdr = (const struct bwn_fwhdr *)(fw->initvals.fw->data);
3477 error = bwn_fwinitvals_write(mac, GETFWOFFSET(fw->initvals, hdr_len),
3478 be32toh(hdr->size), fw->initvals.fw->datasize - hdr_len);
3479 if (error)
3480 return (error);
3481 if (fw->initvals_band.fw) {
3482 hdr = (const struct bwn_fwhdr *)(fw->initvals_band.fw->data);
3483 error = bwn_fwinitvals_write(mac,
3484 GETFWOFFSET(fw->initvals_band, hdr_len),
3485 be32toh(hdr->size),
3486 fw->initvals_band.fw->datasize - hdr_len);
3487 }
3488 return (error);
3489#undef GETFWOFFSET
3490}
3491
3492static int
3493bwn_phy_init(struct bwn_mac *mac)
3494{
3495 struct bwn_softc *sc = mac->mac_sc;
3496 int error;
3497
3498 mac->mac_phy.chan = mac->mac_phy.get_default_chan(mac);
3499 mac->mac_phy.rf_onoff(mac, 1);
3500 error = mac->mac_phy.init(mac);
3501 if (error) {
3502 device_printf(sc->sc_dev, "PHY init failed\n");
3503 goto fail0;
3504 }
3505 error = bwn_switch_channel(mac,
3506 mac->mac_phy.get_default_chan(mac));
3507 if (error) {
3508 device_printf(sc->sc_dev,
3509 "failed to switch default channel\n");
3510 goto fail1;
3511 }
3512 return (0);
3513fail1:
3514 if (mac->mac_phy.exit)
3515 mac->mac_phy.exit(mac);
3516fail0:
3517 mac->mac_phy.rf_onoff(mac, 0);
3518
3519 return (error);
3520}
3521
3522static void
3523bwn_set_txantenna(struct bwn_mac *mac, int antenna)
3524{
3525 uint16_t ant;
3526 uint16_t tmp;
3527
3528 ant = bwn_ant2phy(antenna);
3529
3530 /* For ACK/CTS */
3531 tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL);
3532 tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
3533 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, tmp);
3534 /* For Probe Resposes */
3535 tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL);
3536 tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
3537 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, tmp);
3538}
3539
3540static void
3541bwn_set_opmode(struct bwn_mac *mac)
3542{
3543 struct bwn_softc *sc = mac->mac_sc;
3544 struct ieee80211com *ic = &sc->sc_ic;
3545 uint32_t ctl;
3546 uint16_t cfp_pretbtt;
3547
3548 ctl = BWN_READ_4(mac, BWN_MACCTL);
3549 ctl &= ~(BWN_MACCTL_HOSTAP | BWN_MACCTL_PASS_CTL |
3550 BWN_MACCTL_PASS_BADPLCP | BWN_MACCTL_PASS_BADFCS |
3551 BWN_MACCTL_PROMISC | BWN_MACCTL_BEACON_PROMISC);
3552 ctl |= BWN_MACCTL_STA;
3553
3554 if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
3555 ic->ic_opmode == IEEE80211_M_MBSS)
3556 ctl |= BWN_MACCTL_HOSTAP;
3557 else if (ic->ic_opmode == IEEE80211_M_IBSS)
3558 ctl &= ~BWN_MACCTL_STA;
3559 ctl |= sc->sc_filters;
3560
3561 if (siba_get_revid(sc->sc_dev) <= 4)
3562 ctl |= BWN_MACCTL_PROMISC;
3563
3564 BWN_WRITE_4(mac, BWN_MACCTL, ctl);
3565
3566 cfp_pretbtt = 2;
3567 if ((ctl & BWN_MACCTL_STA) && !(ctl & BWN_MACCTL_HOSTAP)) {
3568 if (siba_get_chipid(sc->sc_dev) == 0x4306 &&
3569 siba_get_chiprev(sc->sc_dev) == 3)
3570 cfp_pretbtt = 100;
3571 else
3572 cfp_pretbtt = 50;
3573 }
3574 BWN_WRITE_2(mac, 0x612, cfp_pretbtt);
3575}
3576
3577static int
3578bwn_dma_gettype(struct bwn_mac *mac)
3579{
3580 uint32_t tmp;
3581 uint16_t base;
3582
3583 tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
3584 if (tmp & SIBA_TGSHIGH_DMA64)
3585 return (BWN_DMA_64BIT);
3586 base = bwn_dma_base(0, 0);
3587 BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
3588 tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
3589 if (tmp & BWN_DMA32_TXADDREXT_MASK)
3590 return (BWN_DMA_32BIT);
3591
3592 return (BWN_DMA_30BIT);
3593}
3594
3595static void
3596bwn_dma_ring_addr(void *arg, bus_dma_segment_t *seg, int nseg, int error)
3597{
3598 if (!error) {
3599 KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
3600 *((bus_addr_t *)arg) = seg->ds_addr;
3601 }
3602}
3603
3604void
3605bwn_dummy_transmission(struct bwn_mac *mac, int ofdm, int paon)
3606{
3607 struct bwn_phy *phy = &mac->mac_phy;
3608 struct bwn_softc *sc = mac->mac_sc;
3609 unsigned int i, max_loop;
3610 uint16_t value;
3611 uint32_t buffer[5] = {
3612 0x00000000, 0x00d40000, 0x00000000, 0x01000000, 0x00000000
3613 };
3614
3615 if (ofdm) {
3616 max_loop = 0x1e;
3617 buffer[0] = 0x000201cc;
3618 } else {
3619 max_loop = 0xfa;
3620 buffer[0] = 0x000b846e;
3621 }
3622
3623 BWN_ASSERT_LOCKED(mac->mac_sc);
3624
3625 for (i = 0; i < 5; i++)
3626 bwn_ram_write(mac, i * 4, buffer[i]);
3627
3628 BWN_WRITE_2(mac, 0x0568, 0x0000);
3629 BWN_WRITE_2(mac, 0x07c0,
3630 (siba_get_revid(sc->sc_dev) < 11) ? 0x0000 : 0x0100);
3631
3632 value = (ofdm ? 0x41 : 0x40);
3633 BWN_WRITE_2(mac, 0x050c, value);
3634
3635 if (phy->type == BWN_PHYTYPE_N || phy->type == BWN_PHYTYPE_LP ||
3636 phy->type == BWN_PHYTYPE_LCN)
3637 BWN_WRITE_2(mac, 0x0514, 0x1a02);
3638 BWN_WRITE_2(mac, 0x0508, 0x0000);
3639 BWN_WRITE_2(mac, 0x050a, 0x0000);
3640 BWN_WRITE_2(mac, 0x054c, 0x0000);
3641 BWN_WRITE_2(mac, 0x056a, 0x0014);
3642 BWN_WRITE_2(mac, 0x0568, 0x0826);
3643 BWN_WRITE_2(mac, 0x0500, 0x0000);
3644
3645 /* XXX TODO: n phy pa override? */
3646
3647 switch (phy->type) {
3648 case BWN_PHYTYPE_N:
3649 case BWN_PHYTYPE_LCN:
3650 BWN_WRITE_2(mac, 0x0502, 0x00d0);
3651 break;
3652 case BWN_PHYTYPE_LP:
3653 BWN_WRITE_2(mac, 0x0502, 0x0050);
3654 break;
3655 default:
3656 BWN_WRITE_2(mac, 0x0502, 0x0030);
3657 break;
3658 }
3659
3660 /* flush */
3661 BWN_READ_2(mac, 0x0502);
3662
3663 if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
3664 BWN_RF_WRITE(mac, 0x0051, 0x0017);
3665 for (i = 0x00; i < max_loop; i++) {
3666 value = BWN_READ_2(mac, 0x050e);
3667 if (value & 0x0080)
3668 break;
3669 DELAY(10);
3670 }
3671 for (i = 0x00; i < 0x0a; i++) {
3672 value = BWN_READ_2(mac, 0x050e);
3673 if (value & 0x0400)
3674 break;
3675 DELAY(10);
3676 }
3677 for (i = 0x00; i < 0x19; i++) {
3678 value = BWN_READ_2(mac, 0x0690);
3679 if (!(value & 0x0100))
3680 break;
3681 DELAY(10);
3682 }
3683 if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
3684 BWN_RF_WRITE(mac, 0x0051, 0x0037);
3685}
3686
3687void
3688bwn_ram_write(struct bwn_mac *mac, uint16_t offset, uint32_t val)
3689{
3690 uint32_t macctl;
3691
3692 KASSERT(offset % 4 == 0, ("%s:%d: fail", __func__, __LINE__));
3693
3694 macctl = BWN_READ_4(mac, BWN_MACCTL);
3695 if (macctl & BWN_MACCTL_BIGENDIAN)
3696 printf("TODO: need swap\n");
3697
3698 BWN_WRITE_4(mac, BWN_RAM_CONTROL, offset);
3699 BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
3700 BWN_WRITE_4(mac, BWN_RAM_DATA, val);
3701}
3702
3703void
3704bwn_mac_suspend(struct bwn_mac *mac)
3705{
3706 struct bwn_softc *sc = mac->mac_sc;
3707 int i;
3708 uint32_t tmp;
3709
3710 KASSERT(mac->mac_suspended >= 0,
3711 ("%s:%d: fail", __func__, __LINE__));
3712
3713 if (mac->mac_suspended == 0) {
3714 bwn_psctl(mac, BWN_PS_AWAKE);
3715 BWN_WRITE_4(mac, BWN_MACCTL,
3716 BWN_READ_4(mac, BWN_MACCTL)
3717 & ~BWN_MACCTL_ON);
3718 BWN_READ_4(mac, BWN_MACCTL);
3719 for (i = 35; i; i--) {
3720 tmp = BWN_READ_4(mac, BWN_INTR_REASON);
3721 if (tmp & BWN_INTR_MAC_SUSPENDED)
3722 goto out;
3723 DELAY(10);
3724 }
3725 for (i = 40; i; i--) {
3726 tmp = BWN_READ_4(mac, BWN_INTR_REASON);
3727 if (tmp & BWN_INTR_MAC_SUSPENDED)
3728 goto out;
3729 DELAY(1000);
3730 }
3731 device_printf(sc->sc_dev, "MAC suspend failed\n");
3732 }
3733out:
3734 mac->mac_suspended++;
3735}
3736
3737void
3738bwn_mac_enable(struct bwn_mac *mac)
3739{
3740 struct bwn_softc *sc = mac->mac_sc;
3741 uint16_t state;
3742
3743 state = bwn_shm_read_2(mac, BWN_SHARED,
3744 BWN_SHARED_UCODESTAT);
3745 if (state != BWN_SHARED_UCODESTAT_SUSPEND &&
3746 state != BWN_SHARED_UCODESTAT_SLEEP)
3747 device_printf(sc->sc_dev, "warn: firmware state (%d)\n", state);
3748
3749 mac->mac_suspended--;
3750 KASSERT(mac->mac_suspended >= 0,
3751 ("%s:%d: fail", __func__, __LINE__));
3752 if (mac->mac_suspended == 0) {
3753 BWN_WRITE_4(mac, BWN_MACCTL,
3754 BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_ON);
3755 BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_MAC_SUSPENDED);
3756 BWN_READ_4(mac, BWN_MACCTL);
3757 BWN_READ_4(mac, BWN_INTR_REASON);
3758 bwn_psctl(mac, 0);
3759 }
3760}
3761
3762void
3763bwn_psctl(struct bwn_mac *mac, uint32_t flags)
3764{
3765 struct bwn_softc *sc = mac->mac_sc;
3766 int i;
3767 uint16_t ucstat;
3768
3769 KASSERT(!((flags & BWN_PS_ON) && (flags & BWN_PS_OFF)),
3770 ("%s:%d: fail", __func__, __LINE__));
3771 KASSERT(!((flags & BWN_PS_AWAKE) && (flags & BWN_PS_ASLEEP)),
3772 ("%s:%d: fail", __func__, __LINE__));
3773
3774 /* XXX forcibly awake and hwps-off */
3775
3776 BWN_WRITE_4(mac, BWN_MACCTL,
3777 (BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_AWAKE) &
3778 ~BWN_MACCTL_HWPS);
3779 BWN_READ_4(mac, BWN_MACCTL);
3780 if (siba_get_revid(sc->sc_dev) >= 5) {
3781 for (i = 0; i < 100; i++) {
3782 ucstat = bwn_shm_read_2(mac, BWN_SHARED,
3783 BWN_SHARED_UCODESTAT);
3784 if (ucstat != BWN_SHARED_UCODESTAT_SLEEP)
3785 break;
3786 DELAY(10);
3787 }
3788 }
3789}
3790
3791static int
3792bwn_fw_gets(struct bwn_mac *mac, enum bwn_fwtype type)
3793{
3794 struct bwn_softc *sc = mac->mac_sc;
3795 struct bwn_fw *fw = &mac->mac_fw;
3796 const uint8_t rev = siba_get_revid(sc->sc_dev);
3797 const char *filename;
3798 uint32_t high;
3799 int error;
3800
3801 /* microcode */
3802 filename = NULL;
3803 switch (rev) {
3804 case 42:
3805 if (mac->mac_phy.type == BWN_PHYTYPE_AC)
3806 filename = "ucode42";
3807 break;
3808 case 40:
3809 if (mac->mac_phy.type == BWN_PHYTYPE_AC)
3810 filename = "ucode40";
3811 break;
3812 case 33:
3813 if (mac->mac_phy.type == BWN_PHYTYPE_LCN40)
3814 filename = "ucode33_lcn40";
3815 break;
3816 case 30:
3817 if (mac->mac_phy.type == BWN_PHYTYPE_N)
3818 filename = "ucode30_mimo";
3819 break;
3820 case 29:
3821 if (mac->mac_phy.type == BWN_PHYTYPE_HT)
3822 filename = "ucode29_mimo";
3823 break;
3824 case 26:
3825 if (mac->mac_phy.type == BWN_PHYTYPE_HT)
3826 filename = "ucode26_mimo";
3827 break;
3828 case 28:
3829 case 25:
3830 if (mac->mac_phy.type == BWN_PHYTYPE_N)
3831 filename = "ucode25_mimo";
3832 else if (mac->mac_phy.type == BWN_PHYTYPE_LCN)
3833 filename = "ucode25_lcn";
3834 break;
3835 case 24:
3836 if (mac->mac_phy.type == BWN_PHYTYPE_LCN)
3837 filename = "ucode24_lcn";
3838 break;
3839 case 23:
3840 if (mac->mac_phy.type == BWN_PHYTYPE_N)
3841 filename = "ucode16_mimo";
3842 break;
3843 case 16:
3844 case 17:
3845 case 18:
3846 case 19:
3847 if (mac->mac_phy.type == BWN_PHYTYPE_N)
3848 filename = "ucode16_mimo";
3849 else if (mac->mac_phy.type == BWN_PHYTYPE_LP)
3850 filename = "ucode16_lp";
3851 break;
3852 case 15:
3853 filename = "ucode15";
3854 break;
3855 case 14:
3856 filename = "ucode14";
3857 break;
3858 case 13:
3859 filename = "ucode13";
3860 break;
3861 case 12:
3862 case 11:
3863 filename = "ucode11";
3864 break;
3865 case 10:
3866 case 9:
3867 case 8:
3868 case 7:
3869 case 6:
3870 case 5:
3871 filename = "ucode5";
3872 break;
3873 default:
3874 device_printf(sc->sc_dev, "no ucode for rev %d\n", rev);
3875 bwn_release_firmware(mac);
3876 return (EOPNOTSUPP);
3877 }
3878
3879 device_printf(sc->sc_dev, "ucode fw: %s\n", filename);
3880 error = bwn_fw_get(mac, type, filename, &fw->ucode);
3881 if (error) {
3882 bwn_release_firmware(mac);
3883 return (error);
3884 }
3885
3886 /* PCM */
3887 KASSERT(fw->no_pcmfile == 0, ("%s:%d fail", __func__, __LINE__));
3888 if (rev >= 5 && rev <= 10) {
3889 error = bwn_fw_get(mac, type, "pcm5", &fw->pcm);
3890 if (error == ENOENT)
3891 fw->no_pcmfile = 1;
3892 else if (error) {
3893 bwn_release_firmware(mac);
3894 return (error);
3895 }
3896 } else if (rev < 11) {
3897 device_printf(sc->sc_dev, "no PCM for rev %d\n", rev);
3898 return (EOPNOTSUPP);
3899 }
3900
3901 /* initvals */
3902 high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH);
3903 switch (mac->mac_phy.type) {
3904 case BWN_PHYTYPE_A:
3905 if (rev < 5 || rev > 10)
3906 goto fail1;
3907 if (high & BWN_TGSHIGH_HAVE_2GHZ)
3908 filename = "a0g1initvals5";
3909 else
3910 filename = "a0g0initvals5";
3911 break;
3912 case BWN_PHYTYPE_G:
3913 if (rev >= 5 && rev <= 10)
3914 filename = "b0g0initvals5";
3915 else if (rev >= 13)
3916 filename = "b0g0initvals13";
3917 else
3918 goto fail1;
3919 break;
3920 case BWN_PHYTYPE_LP:
3921 if (rev == 13)
3922 filename = "lp0initvals13";
3923 else if (rev == 14)
3924 filename = "lp0initvals14";
3925 else if (rev >= 15)
3926 filename = "lp0initvals15";
3927 else
3928 goto fail1;
3929 break;
3930 case BWN_PHYTYPE_N:
3931 if (rev == 30)
3932 filename = "n16initvals30";
3933 else if (rev == 28 || rev == 25)
3934 filename = "n0initvals25";
3935 else if (rev == 24)
3936 filename = "n0initvals24";
3937 else if (rev == 23)
3938 filename = "n0initvals16";
3939 else if (rev >= 16 && rev <= 18)
3940 filename = "n0initvals16";
3941 else if (rev >= 11 && rev <= 12)
3942 filename = "n0initvals11";
3943 else
3944 goto fail1;
3945 break;
3946 default:
3947 goto fail1;
3948 }
3949 error = bwn_fw_get(mac, type, filename, &fw->initvals);
3950 if (error) {
3951 bwn_release_firmware(mac);
3952 return (error);
3953 }
3954
3955 /* bandswitch initvals */
3956 switch (mac->mac_phy.type) {
3957 case BWN_PHYTYPE_A:
3958 if (rev >= 5 && rev <= 10) {
3959 if (high & BWN_TGSHIGH_HAVE_2GHZ)
3960 filename = "a0g1bsinitvals5";
3961 else
3962 filename = "a0g0bsinitvals5";
3963 } else if (rev >= 11)
3964 filename = NULL;
3965 else
3966 goto fail1;
3967 break;
3968 case BWN_PHYTYPE_G:
3969 if (rev >= 5 && rev <= 10)
3970 filename = "b0g0bsinitvals5";
3971 else if (rev >= 11)
3972 filename = NULL;
3973 else
3974 goto fail1;
3975 break;
3976 case BWN_PHYTYPE_LP:
3977 if (rev == 13)
3978 filename = "lp0bsinitvals13";
3979 else if (rev == 14)
3980 filename = "lp0bsinitvals14";
3981 else if (rev >= 15)
3982 filename = "lp0bsinitvals15";
3983 else
3984 goto fail1;
3985 break;
3986 case BWN_PHYTYPE_N:
3987 if (rev == 30)
3988 filename = "n16bsinitvals30";
3989 else if (rev == 28 || rev == 25)
3990 filename = "n0bsinitvals25";
3991 else if (rev == 24)
3992 filename = "n0bsinitvals24";
3993 else if (rev == 23)
3994 filename = "n0bsinitvals16";
3995 else if (rev >= 16 && rev <= 18)
3996 filename = "n0bsinitvals16";
3997 else if (rev >= 11 && rev <= 12)
3998 filename = "n0bsinitvals11";
3999 else
4000 goto fail1;
4001 break;
4002 default:
4003 device_printf(sc->sc_dev, "unknown phy (%d)\n",
4004 mac->mac_phy.type);
4005 goto fail1;
4006 }
4007 error = bwn_fw_get(mac, type, filename, &fw->initvals_band);
4008 if (error) {
4009 bwn_release_firmware(mac);
4010 return (error);
4011 }
4012 return (0);
4013fail1:
4014 device_printf(sc->sc_dev, "no INITVALS for rev %d, phy.type %d\n",
4015 rev, mac->mac_phy.type);
4016 bwn_release_firmware(mac);
4017 return (EOPNOTSUPP);
4018}
4019
4020static int
4021bwn_fw_get(struct bwn_mac *mac, enum bwn_fwtype type,
4022 const char *name, struct bwn_fwfile *bfw)
4023{
4024 const struct bwn_fwhdr *hdr;
4025 struct bwn_softc *sc = mac->mac_sc;
4026 const struct firmware *fw;
4027 char namebuf[64];
4028
4029 if (name == NULL) {
4030 bwn_do_release_fw(bfw);
4031 return (0);
4032 }
4033 if (bfw->filename != NULL) {
4034 if (bfw->type == type && (strcmp(bfw->filename, name) == 0))
4035 return (0);
4036 bwn_do_release_fw(bfw);
4037 }
4038
4039 snprintf(namebuf, sizeof(namebuf), "bwn%s_v4_%s%s",
4040 (type == BWN_FWTYPE_OPENSOURCE) ? "-open" : "",
4041 (mac->mac_phy.type == BWN_PHYTYPE_LP) ? "lp_" : "", name);
4042 /* XXX Sleeping on "fwload" with the non-sleepable locks held */
4043 fw = firmware_get(namebuf);
4044 if (fw == NULL) {
4045 device_printf(sc->sc_dev, "the fw file(%s) not found\n",
4046 namebuf);
4047 return (ENOENT);
4048 }
4049 if (fw->datasize < sizeof(struct bwn_fwhdr))
4050 goto fail;
4051 hdr = (const struct bwn_fwhdr *)(fw->data);
4052 switch (hdr->type) {
4053 case BWN_FWTYPE_UCODE:
4054 case BWN_FWTYPE_PCM:
4055 if (be32toh(hdr->size) !=
4056 (fw->datasize - sizeof(struct bwn_fwhdr)))
4057 goto fail;
4058 /* FALLTHROUGH */
4059 case BWN_FWTYPE_IV:
4060 if (hdr->ver != 1)
4061 goto fail;
4062 break;
4063 default:
4064 goto fail;
4065 }
4066 bfw->filename = name;
4067 bfw->fw = fw;
4068 bfw->type = type;
4069 return (0);
4070fail:
4071 device_printf(sc->sc_dev, "the fw file(%s) format error\n", namebuf);
4072 if (fw != NULL)
4073 firmware_put(fw, FIRMWARE_UNLOAD);
4074 return (EPROTO);
4075}
4076
4077static void
4078bwn_release_firmware(struct bwn_mac *mac)
4079{
4080
4081 bwn_do_release_fw(&mac->mac_fw.ucode);
4082 bwn_do_release_fw(&mac->mac_fw.pcm);
4083 bwn_do_release_fw(&mac->mac_fw.initvals);
4084 bwn_do_release_fw(&mac->mac_fw.initvals_band);
4085}
4086
4087static void
4088bwn_do_release_fw(struct bwn_fwfile *bfw)
4089{
4090
4091 if (bfw->fw != NULL)
4092 firmware_put(bfw->fw, FIRMWARE_UNLOAD);
4093 bfw->fw = NULL;
4094 bfw->filename = NULL;
4095}
4096
4097static int
4098bwn_fw_loaducode(struct bwn_mac *mac)
4099{
4100#define GETFWOFFSET(fwp, offset) \
4101 ((const uint32_t *)((const char *)fwp.fw->data + offset))
4102#define GETFWSIZE(fwp, offset) \
4103 ((fwp.fw->datasize - offset) / sizeof(uint32_t))
4104 struct bwn_softc *sc = mac->mac_sc;
4105 const uint32_t *data;
4106 unsigned int i;
4107 uint32_t ctl;
4108 uint16_t date, fwcaps, time;
4109 int error = 0;
4110
4111 ctl = BWN_READ_4(mac, BWN_MACCTL);
4112 ctl |= BWN_MACCTL_MCODE_JMP0;
4113 KASSERT(!(ctl & BWN_MACCTL_MCODE_RUN), ("%s:%d: fail", __func__,
4114 __LINE__));
4115 BWN_WRITE_4(mac, BWN_MACCTL, ctl);
4116 for (i = 0; i < 64; i++)
4117 bwn_shm_write_2(mac, BWN_SCRATCH, i, 0);
4118 for (i = 0; i < 4096; i += 2)
4119 bwn_shm_write_2(mac, BWN_SHARED, i, 0);
4120
4121 data = GETFWOFFSET(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
4122 bwn_shm_ctlword(mac, BWN_UCODE | BWN_SHARED_AUTOINC, 0x0000);
4123 for (i = 0; i < GETFWSIZE(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
4124 i++) {
4125 BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
4126 DELAY(10);
4127 }
4128
4129 if (mac->mac_fw.pcm.fw) {
4130 data = GETFWOFFSET(mac->mac_fw.pcm, sizeof(struct bwn_fwhdr));
4131 bwn_shm_ctlword(mac, BWN_HW, 0x01ea);
4132 BWN_WRITE_4(mac, BWN_SHM_DATA, 0x00004000);
4133 bwn_shm_ctlword(mac, BWN_HW, 0x01eb);
4134 for (i = 0; i < GETFWSIZE(mac->mac_fw.pcm,
4135 sizeof(struct bwn_fwhdr)); i++) {
4136 BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
4137 DELAY(10);
4138 }
4139 }
4140
4141 BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_ALL);
4142 BWN_WRITE_4(mac, BWN_MACCTL,
4143 (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_JMP0) |
4144 BWN_MACCTL_MCODE_RUN);
4145
4146 for (i = 0; i < 21; i++) {
4147 if (BWN_READ_4(mac, BWN_INTR_REASON) == BWN_INTR_MAC_SUSPENDED)
4148 break;
4149 if (i >= 20) {
4150 device_printf(sc->sc_dev, "ucode timeout\n");
4151 error = ENXIO;
4152 goto error;
4153 }
4154 DELAY(50000);
4155 }
4156 BWN_READ_4(mac, BWN_INTR_REASON);
4157
4158 mac->mac_fw.rev = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_REV);
4159 if (mac->mac_fw.rev <= 0x128) {
4160 device_printf(sc->sc_dev, "the firmware is too old\n");
4161 error = EOPNOTSUPP;
4162 goto error;
4163 }
4164
4165 /*
4166 * Determine firmware header version; needed for TX/RX packet
4167 * handling.
4168 */
4169 if (mac->mac_fw.rev >= 598)
4170 mac->mac_fw.fw_hdr_format = BWN_FW_HDR_598;
4171 else if (mac->mac_fw.rev >= 410)
4172 mac->mac_fw.fw_hdr_format = BWN_FW_HDR_410;
4173 else
4174 mac->mac_fw.fw_hdr_format = BWN_FW_HDR_351;
4175
4176 /*
4177 * We don't support rev 598 or later; that requires
4178 * another round of changes to the TX/RX descriptor
4179 * and status layout.
4180 *
4181 * So, complain this is the case and exit out, rather
4182 * than attaching and then failing.
4183 */
4184 if (mac->mac_fw.fw_hdr_format == BWN_FW_HDR_598) {
4185 device_printf(sc->sc_dev,
4186 "firmware is too new (>=598); not supported\n");
4187 error = EOPNOTSUPP;
4188 goto error;
4189 }
4190
4191 mac->mac_fw.patch = bwn_shm_read_2(mac, BWN_SHARED,
4192 BWN_SHARED_UCODE_PATCH);
4193 date = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_DATE);
4194 mac->mac_fw.opensource = (date == 0xffff);
4195 if (bwn_wme != 0)
4196 mac->mac_flags |= BWN_MAC_FLAG_WME;
4197 mac->mac_flags |= BWN_MAC_FLAG_HWCRYPTO;
4198
4199 time = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_TIME);
4200 if (mac->mac_fw.opensource == 0) {
4201 device_printf(sc->sc_dev,
4202 "firmware version (rev %u patch %u date %#x time %#x)\n",
4203 mac->mac_fw.rev, mac->mac_fw.patch, date, time);
4204 if (mac->mac_fw.no_pcmfile)
4205 device_printf(sc->sc_dev,
4206 "no HW crypto acceleration due to pcm5\n");
4207 } else {
4208 mac->mac_fw.patch = time;
4209 fwcaps = bwn_fwcaps_read(mac);
4210 if (!(fwcaps & BWN_FWCAPS_HWCRYPTO) || mac->mac_fw.no_pcmfile) {
4211 device_printf(sc->sc_dev,
4212 "disabling HW crypto acceleration\n");
4213 mac->mac_flags &= ~BWN_MAC_FLAG_HWCRYPTO;
4214 }
4215 if (!(fwcaps & BWN_FWCAPS_WME)) {
4216 device_printf(sc->sc_dev, "disabling WME support\n");
4217 mac->mac_flags &= ~BWN_MAC_FLAG_WME;
4218 }
4219 }
4220
4221 if (BWN_ISOLDFMT(mac))
4222 device_printf(sc->sc_dev, "using old firmware image\n");
4223
4224 return (0);
4225
4226error:
4227 BWN_WRITE_4(mac, BWN_MACCTL,
4228 (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_RUN) |
4229 BWN_MACCTL_MCODE_JMP0);
4230
4231 return (error);
4232#undef GETFWSIZE
4233#undef GETFWOFFSET
4234}
4235
4236/* OpenFirmware only */
4237static uint16_t
4238bwn_fwcaps_read(struct bwn_mac *mac)
4239{
4240
4241 KASSERT(mac->mac_fw.opensource == 1,
4242 ("%s:%d: fail", __func__, __LINE__));
4243 return (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_FWCAPS));
4244}
4245
4246static int
4247bwn_fwinitvals_write(struct bwn_mac *mac, const struct bwn_fwinitvals *ivals,
4248 size_t count, size_t array_size)
4249{
4250#define GET_NEXTIV16(iv) \
4251 ((const struct bwn_fwinitvals *)((const uint8_t *)(iv) + \
4252 sizeof(uint16_t) + sizeof(uint16_t)))
4253#define GET_NEXTIV32(iv) \
4254 ((const struct bwn_fwinitvals *)((const uint8_t *)(iv) + \
4255 sizeof(uint16_t) + sizeof(uint32_t)))
4256 struct bwn_softc *sc = mac->mac_sc;
4257 const struct bwn_fwinitvals *iv;
4258 uint16_t offset;
4259 size_t i;
4260 uint8_t bit32;
4261
4262 KASSERT(sizeof(struct bwn_fwinitvals) == 6,
4263 ("%s:%d: fail", __func__, __LINE__));
4264 iv = ivals;
4265 for (i = 0; i < count; i++) {
4266 if (array_size < sizeof(iv->offset_size))
4267 goto fail;
4268 array_size -= sizeof(iv->offset_size);
4269 offset = be16toh(iv->offset_size);
4270 bit32 = (offset & BWN_FWINITVALS_32BIT) ? 1 : 0;
4271 offset &= BWN_FWINITVALS_OFFSET_MASK;
4272 if (offset >= 0x1000)
4273 goto fail;
4274 if (bit32) {
4275 if (array_size < sizeof(iv->data.d32))
4276 goto fail;
4277 array_size -= sizeof(iv->data.d32);
4278 BWN_WRITE_4(mac, offset, be32toh(iv->data.d32));
4279 iv = GET_NEXTIV32(iv);
4280 } else {
4281
4282 if (array_size < sizeof(iv->data.d16))
4283 goto fail;
4284 array_size -= sizeof(iv->data.d16);
4285 BWN_WRITE_2(mac, offset, be16toh(iv->data.d16));
4286
4287 iv = GET_NEXTIV16(iv);
4288 }
4289 }
4290 if (array_size != 0)
4291 goto fail;
4292 return (0);
4293fail:
4294 device_printf(sc->sc_dev, "initvals: invalid format\n");
4295 return (EPROTO);
4296#undef GET_NEXTIV16
4297#undef GET_NEXTIV32
4298}
4299
4300int
4301bwn_switch_channel(struct bwn_mac *mac, int chan)
4302{
4303 struct bwn_phy *phy = &(mac->mac_phy);
4304 struct bwn_softc *sc = mac->mac_sc;
4305 struct ieee80211com *ic = &sc->sc_ic;
4306 uint16_t channelcookie, savedcookie;
4307 int error;
4308
4309 if (chan == 0xffff)
4310 chan = phy->get_default_chan(mac);
4311
4312 channelcookie = chan;
4313 if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan))
4314 channelcookie |= 0x100;
4315 savedcookie = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_CHAN);
4316 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, channelcookie);
4317 error = phy->switch_channel(mac, chan);
4318 if (error)
4319 goto fail;
4320
4321 mac->mac_phy.chan = chan;
4322 DELAY(8000);
4323 return (0);
4324fail:
4325 device_printf(sc->sc_dev, "failed to switch channel\n");
4326 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, savedcookie);
4327 return (error);
4328}
4329
4330static uint16_t
4331bwn_ant2phy(int antenna)
4332{
4333
4334 switch (antenna) {
4335 case BWN_ANT0:
4336 return (BWN_TX_PHY_ANT0);
4337 case BWN_ANT1:
4338 return (BWN_TX_PHY_ANT1);
4339 case BWN_ANT2:
4340 return (BWN_TX_PHY_ANT2);
4341 case BWN_ANT3:
4342 return (BWN_TX_PHY_ANT3);
4343 case BWN_ANTAUTO:
4344 return (BWN_TX_PHY_ANT01AUTO);
4345 }
4346 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
4347 return (0);
4348}
4349
4350static void
4351bwn_wme_load(struct bwn_mac *mac)
4352{
4353 struct bwn_softc *sc = mac->mac_sc;
4354 int i;
4355
4356 KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
4357 ("%s:%d: fail", __func__, __LINE__));
4358
4359 bwn_mac_suspend(mac);
4360 for (i = 0; i < N(sc->sc_wmeParams); i++)
4361 bwn_wme_loadparams(mac, &(sc->sc_wmeParams[i]),
4362 bwn_wme_shm_offsets[i]);
4363 bwn_mac_enable(mac);
4364}
4365
4366static void
4367bwn_wme_loadparams(struct bwn_mac *mac,
4368 const struct wmeParams *p, uint16_t shm_offset)
4369{
4370#define SM(_v, _f) (((_v) << _f##_S) & _f)
4371 struct bwn_softc *sc = mac->mac_sc;
4372 uint16_t params[BWN_NR_WMEPARAMS];
4373 int slot, tmp;
4374 unsigned int i;
4375
4376 slot = BWN_READ_2(mac, BWN_RNG) &
4377 SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
4378
4379 memset(&params, 0, sizeof(params));
4380
4381 DPRINTF(sc, BWN_DEBUG_WME, "wmep_txopLimit %d wmep_logcwmin %d "
4382 "wmep_logcwmax %d wmep_aifsn %d\n", p->wmep_txopLimit,
4383 p->wmep_logcwmin, p->wmep_logcwmax, p->wmep_aifsn);
4384
4385 params[BWN_WMEPARAM_TXOP] = p->wmep_txopLimit * 32;
4386 params[BWN_WMEPARAM_CWMIN] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
4387 params[BWN_WMEPARAM_CWMAX] = SM(p->wmep_logcwmax, WME_PARAM_LOGCWMAX);
4388 params[BWN_WMEPARAM_CWCUR] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
4389 params[BWN_WMEPARAM_AIFS] = p->wmep_aifsn;
4390 params[BWN_WMEPARAM_BSLOTS] = slot;
4391 params[BWN_WMEPARAM_REGGAP] = slot + p->wmep_aifsn;
4392
4393 for (i = 0; i < N(params); i++) {
4394 if (i == BWN_WMEPARAM_STATUS) {
4395 tmp = bwn_shm_read_2(mac, BWN_SHARED,
4396 shm_offset + (i * 2));
4397 tmp |= 0x100;
4398 bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
4399 tmp);
4400 } else {
4401 bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
4402 params[i]);
4403 }
4404 }
4405}
4406
4407static void
4408bwn_mac_write_bssid(struct bwn_mac *mac)
4409{
4410 struct bwn_softc *sc = mac->mac_sc;
4411 uint32_t tmp;
4412 int i;
4413 uint8_t mac_bssid[IEEE80211_ADDR_LEN * 2];
4414
4415 bwn_mac_setfilter(mac, BWN_MACFILTER_BSSID, sc->sc_bssid);
4416 memcpy(mac_bssid, sc->sc_ic.ic_macaddr, IEEE80211_ADDR_LEN);
4417 memcpy(mac_bssid + IEEE80211_ADDR_LEN, sc->sc_bssid,
4418 IEEE80211_ADDR_LEN);
4419
4420 for (i = 0; i < N(mac_bssid); i += sizeof(uint32_t)) {
4421 tmp = (uint32_t) (mac_bssid[i + 0]);
4422 tmp |= (uint32_t) (mac_bssid[i + 1]) << 8;
4423 tmp |= (uint32_t) (mac_bssid[i + 2]) << 16;
4424 tmp |= (uint32_t) (mac_bssid[i + 3]) << 24;
4425 bwn_ram_write(mac, 0x20 + i, tmp);
4426 }
4427}
4428
4429static void
4430bwn_mac_setfilter(struct bwn_mac *mac, uint16_t offset,
4431 const uint8_t *macaddr)
4432{
4433 static const uint8_t zero[IEEE80211_ADDR_LEN] = { 0 };
4434 uint16_t data;
4435
4436 if (!mac)
4437 macaddr = zero;
4438
4439 offset |= 0x0020;
4440 BWN_WRITE_2(mac, BWN_MACFILTER_CONTROL, offset);
4441
4442 data = macaddr[0];
4443 data |= macaddr[1] << 8;
4444 BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
4445 data = macaddr[2];
4446 data |= macaddr[3] << 8;
4447 BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
4448 data = macaddr[4];
4449 data |= macaddr[5] << 8;
4450 BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
4451}
4452
4453static void
4454bwn_key_dowrite(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
4455 const uint8_t *key, size_t key_len, const uint8_t *mac_addr)
4456{
4457 uint8_t buf[BWN_SEC_KEYSIZE] = { 0, };
4458 uint8_t per_sta_keys_start = 8;
4459
4460 if (BWN_SEC_NEWAPI(mac))
4461 per_sta_keys_start = 4;
4462
4463 KASSERT(index < mac->mac_max_nr_keys,
4464 ("%s:%d: fail", __func__, __LINE__));
4465 KASSERT(key_len <= BWN_SEC_KEYSIZE,
4466 ("%s:%d: fail", __func__, __LINE__));
4467
4468 if (index >= per_sta_keys_start)
4469 bwn_key_macwrite(mac, index, NULL);
4470 if (key)
4471 memcpy(buf, key, key_len);
4472 bwn_key_write(mac, index, algorithm, buf);
4473 if (index >= per_sta_keys_start)
4474 bwn_key_macwrite(mac, index, mac_addr);
4475
4476 mac->mac_key[index].algorithm = algorithm;
4477}
4478
4479static void
4480bwn_key_macwrite(struct bwn_mac *mac, uint8_t index, const uint8_t *addr)
4481{
4482 struct bwn_softc *sc = mac->mac_sc;
4483 uint32_t addrtmp[2] = { 0, 0 };
4484 uint8_t start = 8;
4485
4486 if (BWN_SEC_NEWAPI(mac))
4487 start = 4;
4488
4489 KASSERT(index >= start,
4490 ("%s:%d: fail", __func__, __LINE__));
4491 index -= start;
4492
4493 if (addr) {
4494 addrtmp[0] = addr[0];
4495 addrtmp[0] |= ((uint32_t) (addr[1]) << 8);
4496 addrtmp[0] |= ((uint32_t) (addr[2]) << 16);
4497 addrtmp[0] |= ((uint32_t) (addr[3]) << 24);
4498 addrtmp[1] = addr[4];
4499 addrtmp[1] |= ((uint32_t) (addr[5]) << 8);
4500 }
4501
4502 if (siba_get_revid(sc->sc_dev) >= 5) {
4503 bwn_shm_write_4(mac, BWN_RCMTA, (index * 2) + 0, addrtmp[0]);
4504 bwn_shm_write_2(mac, BWN_RCMTA, (index * 2) + 1, addrtmp[1]);
4505 } else {
4506 if (index >= 8) {
4507 bwn_shm_write_4(mac, BWN_SHARED,
4508 BWN_SHARED_PSM + (index * 6) + 0, addrtmp[0]);
4509 bwn_shm_write_2(mac, BWN_SHARED,
4510 BWN_SHARED_PSM + (index * 6) + 4, addrtmp[1]);
4511 }
4512 }
4513}
4514
4515static void
4516bwn_key_write(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
4517 const uint8_t *key)
4518{
4519 unsigned int i;
4520 uint32_t offset;
4521 uint16_t kidx, value;
4522
4523 kidx = BWN_SEC_KEY2FW(mac, index);
4524 bwn_shm_write_2(mac, BWN_SHARED,
4525 BWN_SHARED_KEYIDX_BLOCK + (kidx * 2), (kidx << 4) | algorithm);
4526
4527 offset = mac->mac_ktp + (index * BWN_SEC_KEYSIZE);
4528 for (i = 0; i < BWN_SEC_KEYSIZE; i += 2) {
4529 value = key[i];
4530 value |= (uint16_t)(key[i + 1]) << 8;
4531 bwn_shm_write_2(mac, BWN_SHARED, offset + i, value);
4532 }
4533}
4534
4535static void
4536bwn_phy_exit(struct bwn_mac *mac)
4537{
4538
4539 mac->mac_phy.rf_onoff(mac, 0);
4540 if (mac->mac_phy.exit != NULL)
4541 mac->mac_phy.exit(mac);
4542}
4543
4544static void
4545bwn_dma_free(struct bwn_mac *mac)
4546{
4547 struct bwn_dma *dma;
4548
4549 if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
4550 return;
4551 dma = &mac->mac_method.dma;
4552
4553 bwn_dma_ringfree(&dma->rx);
4554 bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
4555 bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
4556 bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
4557 bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
4558 bwn_dma_ringfree(&dma->mcast);
4559}
4560
4561static void
4562bwn_core_stop(struct bwn_mac *mac)
4563{
4564 struct bwn_softc *sc = mac->mac_sc;
4565
4566 BWN_ASSERT_LOCKED(sc);
4567
4568 if (mac->mac_status < BWN_MAC_STATUS_STARTED)
4569 return;
4570
4571 callout_stop(&sc->sc_rfswitch_ch);
4572 callout_stop(&sc->sc_task_ch);
4573 callout_stop(&sc->sc_watchdog_ch);
4574 sc->sc_watchdog_timer = 0;
4575 BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
4576 BWN_READ_4(mac, BWN_INTR_MASK);
4577 bwn_mac_suspend(mac);
4578
4579 mac->mac_status = BWN_MAC_STATUS_INITED;
4580}
4581
4582static int
4583bwn_switch_band(struct bwn_softc *sc, struct ieee80211_channel *chan)
4584{
4585 struct bwn_mac *up_dev = NULL;
4586 struct bwn_mac *down_dev;
4587 struct bwn_mac *mac;
4588 int err, status;
4589 uint8_t gmode;
4590
4591 BWN_ASSERT_LOCKED(sc);
4592
4593 TAILQ_FOREACH(mac, &sc->sc_maclist, mac_list) {
4594 if (IEEE80211_IS_CHAN_2GHZ(chan) &&
4595 mac->mac_phy.supports_2ghz) {
4596 up_dev = mac;
4597 gmode = 1;
4598 } else if (IEEE80211_IS_CHAN_5GHZ(chan) &&
4599 mac->mac_phy.supports_5ghz) {
4600 up_dev = mac;
4601 gmode = 0;
4602 } else {
4603 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
4604 return (EINVAL);
4605 }
4606 if (up_dev != NULL)
4607 break;
4608 }
4609 if (up_dev == NULL) {
4610 device_printf(sc->sc_dev, "Could not find a device\n");
4611 return (ENODEV);
4612 }
4613 if (up_dev == sc->sc_curmac && sc->sc_curmac->mac_phy.gmode == gmode)
4614 return (0);
4615
4616 DPRINTF(sc, BWN_DEBUG_RF | BWN_DEBUG_PHY | BWN_DEBUG_RESET,
4617 "switching to %s-GHz band\n",
4618 IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
4619
4620 down_dev = sc->sc_curmac;
4621 status = down_dev->mac_status;
4622 if (status >= BWN_MAC_STATUS_STARTED)
4623 bwn_core_stop(down_dev);
4624 if (status >= BWN_MAC_STATUS_INITED)
4625 bwn_core_exit(down_dev);
4626
4627 if (down_dev != up_dev)
4628 bwn_phy_reset(down_dev);
4629
4630 up_dev->mac_phy.gmode = gmode;
4631 if (status >= BWN_MAC_STATUS_INITED) {
4632 err = bwn_core_init(up_dev);
4633 if (err) {
4634 device_printf(sc->sc_dev,
4635 "fatal: failed to initialize for %s-GHz\n",
4636 IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
4637 goto fail;
4638 }
4639 }
4640 if (status >= BWN_MAC_STATUS_STARTED)
4641 bwn_core_start(up_dev);
4642 KASSERT(up_dev->mac_status == status, ("%s: fail", __func__));
4643 sc->sc_curmac = up_dev;
4644
4645 return (0);
4646fail:
4647 sc->sc_curmac = NULL;
4648 return (err);
4649}
4650
4651static void
4652bwn_rf_turnon(struct bwn_mac *mac)
4653{
4654
4655 DPRINTF(mac->mac_sc, BWN_DEBUG_RESET, "%s: called\n", __func__);
4656
4657 bwn_mac_suspend(mac);
4658 mac->mac_phy.rf_onoff(mac, 1);
4659 mac->mac_phy.rf_on = 1;
4660 bwn_mac_enable(mac);
4661}
4662
4663static void
4664bwn_rf_turnoff(struct bwn_mac *mac)
4665{
4666
4667 DPRINTF(mac->mac_sc, BWN_DEBUG_RESET, "%s: called\n", __func__);
4668
4669 bwn_mac_suspend(mac);
4670 mac->mac_phy.rf_onoff(mac, 0);
4671 mac->mac_phy.rf_on = 0;
4672 bwn_mac_enable(mac);
4673}
4674
4675/*
4676 * SSB PHY reset.
4677 *
4678 * XXX TODO: BCMA PHY reset.
4679 */
4680static void
4681bwn_phy_reset(struct bwn_mac *mac)
4682{
4683 struct bwn_softc *sc = mac->mac_sc;
4684
4685 siba_write_4(sc->sc_dev, SIBA_TGSLOW,
4686 ((siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~BWN_TGSLOW_SUPPORT_G) |
4687 BWN_TGSLOW_PHYRESET) | SIBA_TGSLOW_FGC);
4688 DELAY(1000);
4689 siba_write_4(sc->sc_dev, SIBA_TGSLOW,
4690 (siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~SIBA_TGSLOW_FGC));
4691 DELAY(1000);
4692}
4693
4694static int
4695bwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
4696{
4697 struct bwn_vap *bvp = BWN_VAP(vap);
4698 struct ieee80211com *ic= vap->iv_ic;
4699 enum ieee80211_state ostate = vap->iv_state;
4700 struct bwn_softc *sc = ic->ic_softc;
4701 struct bwn_mac *mac = sc->sc_curmac;
4702 int error;
4703
4704 DPRINTF(sc, BWN_DEBUG_STATE, "%s: %s -> %s\n", __func__,
4705 ieee80211_state_name[vap->iv_state],
4706 ieee80211_state_name[nstate]);
4707
4708 error = bvp->bv_newstate(vap, nstate, arg);
4709 if (error != 0)
4710 return (error);
4711
4712 BWN_LOCK(sc);
4713
4714 bwn_led_newstate(mac, nstate);
4715
4716 /*
4717 * Clear the BSSID when we stop a STA
4718 */
4719 if (vap->iv_opmode == IEEE80211_M_STA) {
4720 if (ostate == IEEE80211_S_RUN && nstate != IEEE80211_S_RUN) {
4721 /*
4722 * Clear out the BSSID. If we reassociate to
4723 * the same AP, this will reinialize things
4724 * correctly...
4725 */
4726 if (ic->ic_opmode == IEEE80211_M_STA &&
4727 (sc->sc_flags & BWN_FLAG_INVALID) == 0) {
4728 memset(sc->sc_bssid, 0, IEEE80211_ADDR_LEN);
4729 bwn_set_macaddr(mac);
4730 }
4731 }
4732 }
4733
4734 if (vap->iv_opmode == IEEE80211_M_MONITOR ||
4735 vap->iv_opmode == IEEE80211_M_AHDEMO) {
4736 /* XXX nothing to do? */
4737 } else if (nstate == IEEE80211_S_RUN) {
4738 memcpy(sc->sc_bssid, vap->iv_bss->ni_bssid, IEEE80211_ADDR_LEN);
4739 bwn_set_opmode(mac);
4740 bwn_set_pretbtt(mac);
4741 bwn_spu_setdelay(mac, 0);
4742 bwn_set_macaddr(mac);
4743 }
4744
4745 BWN_UNLOCK(sc);
4746
4747 return (error);
4748}
4749
4750static void
4751bwn_set_pretbtt(struct bwn_mac *mac)
4752{
4753 struct bwn_softc *sc = mac->mac_sc;
4754 struct ieee80211com *ic = &sc->sc_ic;
4755 uint16_t pretbtt;
4756
4757 if (ic->ic_opmode == IEEE80211_M_IBSS)
4758 pretbtt = 2;
4759 else
4760 pretbtt = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 120 : 250;
4761 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PRETBTT, pretbtt);
4762 BWN_WRITE_2(mac, BWN_TSF_CFP_PRETBTT, pretbtt);
4763}
4764
4765static int
4766bwn_intr(void *arg)
4767{
4768 struct bwn_mac *mac = arg;
4769 struct bwn_softc *sc = mac->mac_sc;
4770 uint32_t reason;
4771
4772 if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
4773 (sc->sc_flags & BWN_FLAG_INVALID))
4774 return (FILTER_STRAY);
4775
4776 reason = BWN_READ_4(mac, BWN_INTR_REASON);
4777 if (reason == 0xffffffff) /* shared IRQ */
4778 return (FILTER_STRAY);
4779 reason &= mac->mac_intr_mask;
4780 if (reason == 0)
4781 return (FILTER_HANDLED);
4782
4783 mac->mac_reason[0] = BWN_READ_4(mac, BWN_DMA0_REASON) & 0x0001dc00;
4784 mac->mac_reason[1] = BWN_READ_4(mac, BWN_DMA1_REASON) & 0x0000dc00;
4785 mac->mac_reason[2] = BWN_READ_4(mac, BWN_DMA2_REASON) & 0x0000dc00;
4786 mac->mac_reason[3] = BWN_READ_4(mac, BWN_DMA3_REASON) & 0x0001dc00;
4787 mac->mac_reason[4] = BWN_READ_4(mac, BWN_DMA4_REASON) & 0x0000dc00;
4788 BWN_WRITE_4(mac, BWN_INTR_REASON, reason);
4789 BWN_WRITE_4(mac, BWN_DMA0_REASON, mac->mac_reason[0]);
4790 BWN_WRITE_4(mac, BWN_DMA1_REASON, mac->mac_reason[1]);
4791 BWN_WRITE_4(mac, BWN_DMA2_REASON, mac->mac_reason[2]);
4792 BWN_WRITE_4(mac, BWN_DMA3_REASON, mac->mac_reason[3]);
4793 BWN_WRITE_4(mac, BWN_DMA4_REASON, mac->mac_reason[4]);
4794
4795 /* Disable interrupts. */
4796 BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
4797
4798 mac->mac_reason_intr = reason;
4799
4800 BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
4801 BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
4802
4803 taskqueue_enqueue(sc->sc_tq, &mac->mac_intrtask);
4804 return (FILTER_HANDLED);
4805}
4806
4807static void
4808bwn_intrtask(void *arg, int npending)
4809{
4810 struct bwn_mac *mac = arg;
4811 struct bwn_softc *sc = mac->mac_sc;
4812 uint32_t merged = 0;
4813 int i, tx = 0, rx = 0;
4814
4815 BWN_LOCK(sc);
4816 if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
4817 (sc->sc_flags & BWN_FLAG_INVALID)) {
4818 BWN_UNLOCK(sc);
4819 return;
4820 }
4821
4822 for (i = 0; i < N(mac->mac_reason); i++)
4823 merged |= mac->mac_reason[i];
4824
4825 if (mac->mac_reason_intr & BWN_INTR_MAC_TXERR)
4826 device_printf(sc->sc_dev, "MAC trans error\n");
4827
4828 if (mac->mac_reason_intr & BWN_INTR_PHY_TXERR) {
4829 DPRINTF(sc, BWN_DEBUG_INTR, "%s: PHY trans error\n", __func__);
4830 mac->mac_phy.txerrors--;
4831 if (mac->mac_phy.txerrors == 0) {
4832 mac->mac_phy.txerrors = BWN_TXERROR_MAX;
4833 bwn_restart(mac, "PHY TX errors");
4834 }
4835 }
4836
4837 if (merged & (BWN_DMAINTR_FATALMASK | BWN_DMAINTR_NONFATALMASK)) {
4838 if (merged & BWN_DMAINTR_FATALMASK) {
4839 device_printf(sc->sc_dev,
4840 "Fatal DMA error: %#x %#x %#x %#x %#x %#x\n",
4841 mac->mac_reason[0], mac->mac_reason[1],
4842 mac->mac_reason[2], mac->mac_reason[3],
4843 mac->mac_reason[4], mac->mac_reason[5]);
4844 bwn_restart(mac, "DMA error");
4845 BWN_UNLOCK(sc);
4846 return;
4847 }
4848 if (merged & BWN_DMAINTR_NONFATALMASK) {
4849 device_printf(sc->sc_dev,
4850 "DMA error: %#x %#x %#x %#x %#x %#x\n",
4851 mac->mac_reason[0], mac->mac_reason[1],
4852 mac->mac_reason[2], mac->mac_reason[3],
4853 mac->mac_reason[4], mac->mac_reason[5]);
4854 }
4855 }
4856
4857 if (mac->mac_reason_intr & BWN_INTR_UCODE_DEBUG)
4858 bwn_intr_ucode_debug(mac);
4859 if (mac->mac_reason_intr & BWN_INTR_TBTT_INDI)
4860 bwn_intr_tbtt_indication(mac);
4861 if (mac->mac_reason_intr & BWN_INTR_ATIM_END)
4862 bwn_intr_atim_end(mac);
4863 if (mac->mac_reason_intr & BWN_INTR_BEACON)
4864 bwn_intr_beacon(mac);
4865 if (mac->mac_reason_intr & BWN_INTR_PMQ)
4866 bwn_intr_pmq(mac);
4867 if (mac->mac_reason_intr & BWN_INTR_NOISESAMPLE_OK)
4868 bwn_intr_noise(mac);
4869
4870 if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
4871 if (mac->mac_reason[0] & BWN_DMAINTR_RX_DONE) {
4872 bwn_dma_rx(mac->mac_method.dma.rx);
4873 rx = 1;
4874 }
4875 } else
4876 rx = bwn_pio_rx(&mac->mac_method.pio.rx);
4877
4878 KASSERT(!(mac->mac_reason[1] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
4879 KASSERT(!(mac->mac_reason[2] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
4880 KASSERT(!(mac->mac_reason[3] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
4881 KASSERT(!(mac->mac_reason[4] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
4882 KASSERT(!(mac->mac_reason[5] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
4883
4884 if (mac->mac_reason_intr & BWN_INTR_TX_OK) {
4885 bwn_intr_txeof(mac);
4886 tx = 1;
4887 }
4888
4889 BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
4890
4891 if (sc->sc_blink_led != NULL && sc->sc_led_blink) {
4892 int evt = BWN_LED_EVENT_NONE;
4893
4894 if (tx && rx) {
4895 if (sc->sc_rx_rate > sc->sc_tx_rate)
4896 evt = BWN_LED_EVENT_RX;
4897 else
4898 evt = BWN_LED_EVENT_TX;
4899 } else if (tx) {
4900 evt = BWN_LED_EVENT_TX;
4901 } else if (rx) {
4902 evt = BWN_LED_EVENT_RX;
4903 } else if (rx == 0) {
4904 evt = BWN_LED_EVENT_POLL;
4905 }
4906
4907 if (evt != BWN_LED_EVENT_NONE)
4908 bwn_led_event(mac, evt);
4909 }
4910
4911 if (mbufq_first(&sc->sc_snd) != NULL)
4912 bwn_start(sc);
4913
4914 BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
4915 BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
4916
4917 BWN_UNLOCK(sc);
4918}
4919
4920static void
4921bwn_restart(struct bwn_mac *mac, const char *msg)
4922{
4923 struct bwn_softc *sc = mac->mac_sc;
4924 struct ieee80211com *ic = &sc->sc_ic;
4925
4926 if (mac->mac_status < BWN_MAC_STATUS_INITED)
4927 return;
4928
4929 device_printf(sc->sc_dev, "HW reset: %s\n", msg);
4930 ieee80211_runtask(ic, &mac->mac_hwreset);
4931}
4932
4933static void
4934bwn_intr_ucode_debug(struct bwn_mac *mac)
4935{
4936 struct bwn_softc *sc = mac->mac_sc;
4937 uint16_t reason;
4938
4939 if (mac->mac_fw.opensource == 0)
4940 return;
4941
4942 reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG);
4943 switch (reason) {
4944 case BWN_DEBUGINTR_PANIC:
4945 bwn_handle_fwpanic(mac);
4946 break;
4947 case BWN_DEBUGINTR_DUMP_SHM:
4948 device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_SHM\n");
4949 break;
4950 case BWN_DEBUGINTR_DUMP_REGS:
4951 device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_REGS\n");
4952 break;
4953 case BWN_DEBUGINTR_MARKER:
4954 device_printf(sc->sc_dev, "BWN_DEBUGINTR_MARKER\n");
4955 break;
4956 default:
4957 device_printf(sc->sc_dev,
4958 "ucode debug unknown reason: %#x\n", reason);
4959 }
4960
4961 bwn_shm_write_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG,
4962 BWN_DEBUGINTR_ACK);
4963}
4964
4965static void
4966bwn_intr_tbtt_indication(struct bwn_mac *mac)
4967{
4968 struct bwn_softc *sc = mac->mac_sc;
4969 struct ieee80211com *ic = &sc->sc_ic;
4970
4971 if (ic->ic_opmode != IEEE80211_M_HOSTAP)
4972 bwn_psctl(mac, 0);
4973 if (ic->ic_opmode == IEEE80211_M_IBSS)
4974 mac->mac_flags |= BWN_MAC_FLAG_DFQVALID;
4975}
4976
4977static void
4978bwn_intr_atim_end(struct bwn_mac *mac)
4979{
4980
4981 if (mac->mac_flags & BWN_MAC_FLAG_DFQVALID) {
4982 BWN_WRITE_4(mac, BWN_MACCMD,
4983 BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_DFQ_VALID);
4984 mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
4985 }
4986}
4987
4988static void
4989bwn_intr_beacon(struct bwn_mac *mac)
4990{
4991 struct bwn_softc *sc = mac->mac_sc;
4992 struct ieee80211com *ic = &sc->sc_ic;
4993 uint32_t cmd, beacon0, beacon1;
4994
4995 if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
4996 ic->ic_opmode == IEEE80211_M_MBSS)
4997 return;
4998
4999 mac->mac_intr_mask &= ~BWN_INTR_BEACON;
5000
5001 cmd = BWN_READ_4(mac, BWN_MACCMD);
5002 beacon0 = (cmd & BWN_MACCMD_BEACON0_VALID);
5003 beacon1 = (cmd & BWN_MACCMD_BEACON1_VALID);
5004
5005 if (beacon0 && beacon1) {
5006 BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_BEACON);
5007 mac->mac_intr_mask |= BWN_INTR_BEACON;
5008 return;
5009 }
5010
5011 if (sc->sc_flags & BWN_FLAG_NEED_BEACON_TP) {
5012 sc->sc_flags &= ~BWN_FLAG_NEED_BEACON_TP;
5013 bwn_load_beacon0(mac);
5014 bwn_load_beacon1(mac);
5015 cmd = BWN_READ_4(mac, BWN_MACCMD);
5016 cmd |= BWN_MACCMD_BEACON0_VALID;
5017 BWN_WRITE_4(mac, BWN_MACCMD, cmd);
5018 } else {
5019 if (!beacon0) {
5020 bwn_load_beacon0(mac);
5021 cmd = BWN_READ_4(mac, BWN_MACCMD);
5022 cmd |= BWN_MACCMD_BEACON0_VALID;
5023 BWN_WRITE_4(mac, BWN_MACCMD, cmd);
5024 } else if (!beacon1) {
5025 bwn_load_beacon1(mac);
5026 cmd = BWN_READ_4(mac, BWN_MACCMD);
5027 cmd |= BWN_MACCMD_BEACON1_VALID;
5028 BWN_WRITE_4(mac, BWN_MACCMD, cmd);
5029 }
5030 }
5031}
5032
5033static void
5034bwn_intr_pmq(struct bwn_mac *mac)
5035{
5036 uint32_t tmp;
5037
5038 while (1) {
5039 tmp = BWN_READ_4(mac, BWN_PS_STATUS);
5040 if (!(tmp & 0x00000008))
5041 break;
5042 }
5043 BWN_WRITE_2(mac, BWN_PS_STATUS, 0x0002);
5044}
5045
5046static void
5047bwn_intr_noise(struct bwn_mac *mac)
5048{
5049 struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5050 uint16_t tmp;
5051 uint8_t noise[4];
5052 uint8_t i, j;
5053 int32_t average;
5054
5055 if (mac->mac_phy.type != BWN_PHYTYPE_G)
5056 return;
5057
5058 KASSERT(mac->mac_noise.noi_running, ("%s: fail", __func__));
5059 *((uint32_t *)noise) = htole32(bwn_jssi_read(mac));
5060 if (noise[0] == 0x7f || noise[1] == 0x7f || noise[2] == 0x7f ||
5061 noise[3] == 0x7f)
5062 goto new;
5063
5064 KASSERT(mac->mac_noise.noi_nsamples < 8,
5065 ("%s:%d: fail", __func__, __LINE__));
5066 i = mac->mac_noise.noi_nsamples;
5067 noise[0] = MIN(MAX(noise[0], 0), N(pg->pg_nrssi_lt) - 1);
5068 noise[1] = MIN(MAX(noise[1], 0), N(pg->pg_nrssi_lt) - 1);
5069 noise[2] = MIN(MAX(noise[2], 0), N(pg->pg_nrssi_lt) - 1);
5070 noise[3] = MIN(MAX(noise[3], 0), N(pg->pg_nrssi_lt) - 1);
5071 mac->mac_noise.noi_samples[i][0] = pg->pg_nrssi_lt[noise[0]];
5072 mac->mac_noise.noi_samples[i][1] = pg->pg_nrssi_lt[noise[1]];
5073 mac->mac_noise.noi_samples[i][2] = pg->pg_nrssi_lt[noise[2]];
5074 mac->mac_noise.noi_samples[i][3] = pg->pg_nrssi_lt[noise[3]];
5075 mac->mac_noise.noi_nsamples++;
5076 if (mac->mac_noise.noi_nsamples == 8) {
5077 average = 0;
5078 for (i = 0; i < 8; i++) {
5079 for (j = 0; j < 4; j++)
5080 average += mac->mac_noise.noi_samples[i][j];
5081 }
5082 average = (((average / 32) * 125) + 64) / 128;
5083 tmp = (bwn_shm_read_2(mac, BWN_SHARED, 0x40c) / 128) & 0x1f;
5084 if (tmp >= 8)
5085 average += 2;
5086 else
5087 average -= 25;
5088 average -= (tmp == 8) ? 72 : 48;
5089
5090 mac->mac_stats.link_noise = average;
5091 mac->mac_noise.noi_running = 0;
5092 return;
5093 }
5094new:
5095 bwn_noise_gensample(mac);
5096}
5097
5098static int
5099bwn_pio_rx(struct bwn_pio_rxqueue *prq)
5100{
5101 struct bwn_mac *mac = prq->prq_mac;
5102 struct bwn_softc *sc = mac->mac_sc;
5103 unsigned int i;
5104
5105 BWN_ASSERT_LOCKED(sc);
5106
5107 if (mac->mac_status < BWN_MAC_STATUS_STARTED)
5108 return (0);
5109
5110 for (i = 0; i < 5000; i++) {
5111 if (bwn_pio_rxeof(prq) == 0)
5112 break;
5113 }
5114 if (i >= 5000)
5115 device_printf(sc->sc_dev, "too many RX frames in PIO mode\n");
5116 return ((i > 0) ? 1 : 0);
5117}
5118
5119static void
5120bwn_dma_rx(struct bwn_dma_ring *dr)
5121{
5122 int slot, curslot;
5123
5124 KASSERT(!dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
5125 curslot = dr->get_curslot(dr);
5126 KASSERT(curslot >= 0 && curslot < dr->dr_numslots,
5127 ("%s:%d: fail", __func__, __LINE__));
5128
5129 slot = dr->dr_curslot;
5130 for (; slot != curslot; slot = bwn_dma_nextslot(dr, slot))
5131 bwn_dma_rxeof(dr, &slot);
5132
5133 bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
5134 BUS_DMASYNC_PREWRITE);
5135
5136 dr->set_curslot(dr, slot);
5137 dr->dr_curslot = slot;
5138}
5139
5140static void
5141bwn_intr_txeof(struct bwn_mac *mac)
5142{
5143 struct bwn_txstatus stat;
5144 uint32_t stat0, stat1;
5145 uint16_t tmp;
5146
5147 BWN_ASSERT_LOCKED(mac->mac_sc);
5148
5149 while (1) {
5150 stat0 = BWN_READ_4(mac, BWN_XMITSTAT_0);
5151 if (!(stat0 & 0x00000001))
5152 break;
5153 stat1 = BWN_READ_4(mac, BWN_XMITSTAT_1);
5154
5155 DPRINTF(mac->mac_sc, BWN_DEBUG_XMIT,
5156 "%s: stat0=0x%08x, stat1=0x%08x\n",
5157 __func__,
5158 stat0,
5159 stat1);
5160
5161 stat.cookie = (stat0 >> 16);
5162 stat.seq = (stat1 & 0x0000ffff);
5163 stat.phy_stat = ((stat1 & 0x00ff0000) >> 16);
5164 tmp = (stat0 & 0x0000ffff);
5165 stat.framecnt = ((tmp & 0xf000) >> 12);
5166 stat.rtscnt = ((tmp & 0x0f00) >> 8);
5167 stat.sreason = ((tmp & 0x001c) >> 2);
5168 stat.pm = (tmp & 0x0080) ? 1 : 0;
5169 stat.im = (tmp & 0x0040) ? 1 : 0;
5170 stat.ampdu = (tmp & 0x0020) ? 1 : 0;
5171 stat.ack = (tmp & 0x0002) ? 1 : 0;
5172
5173 DPRINTF(mac->mac_sc, BWN_DEBUG_XMIT,
5174 "%s: cookie=%d, seq=%d, phystat=0x%02x, framecnt=%d, "
5175 "rtscnt=%d, sreason=%d, pm=%d, im=%d, ampdu=%d, ack=%d\n",
5176 __func__,
5177 stat.cookie,
5178 stat.seq,
5179 stat.phy_stat,
5180 stat.framecnt,
5181 stat.rtscnt,
5182 stat.sreason,
5183 stat.pm,
5184 stat.im,
5185 stat.ampdu,
5186 stat.ack);
5187
5188 bwn_handle_txeof(mac, &stat);
5189 }
5190}
5191
5192static void
5193bwn_hwreset(void *arg, int npending)
5194{
5195 struct bwn_mac *mac = arg;
5196 struct bwn_softc *sc = mac->mac_sc;
5197 int error = 0;
5198 int prev_status;
5199
5200 BWN_LOCK(sc);
5201
5202 prev_status = mac->mac_status;
5203 if (prev_status >= BWN_MAC_STATUS_STARTED)
5204 bwn_core_stop(mac);
5205 if (prev_status >= BWN_MAC_STATUS_INITED)
5206 bwn_core_exit(mac);
5207
5208 if (prev_status >= BWN_MAC_STATUS_INITED) {
5209 error = bwn_core_init(mac);
5210 if (error)
5211 goto out;
5212 }
5213 if (prev_status >= BWN_MAC_STATUS_STARTED)
5214 bwn_core_start(mac);
5215out:
5216 if (error) {
5217 device_printf(sc->sc_dev, "%s: failed (%d)\n", __func__, error);
5218 sc->sc_curmac = NULL;
5219 }
5220 BWN_UNLOCK(sc);
5221}
5222
5223static void
5224bwn_handle_fwpanic(struct bwn_mac *mac)
5225{
5226 struct bwn_softc *sc = mac->mac_sc;
5227 uint16_t reason;
5228
5229 reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_FWPANIC_REASON_REG);
5230 device_printf(sc->sc_dev,"fw panic (%u)\n", reason);
5231
5232 if (reason == BWN_FWPANIC_RESTART)
5233 bwn_restart(mac, "ucode panic");
5234}
5235
5236static void
5237bwn_load_beacon0(struct bwn_mac *mac)
5238{
5239
5240 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5241}
5242
5243static void
5244bwn_load_beacon1(struct bwn_mac *mac)
5245{
5246
5247 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5248}
5249
5250static uint32_t
5251bwn_jssi_read(struct bwn_mac *mac)
5252{
5253 uint32_t val = 0;
5254
5255 val = bwn_shm_read_2(mac, BWN_SHARED, 0x08a);
5256 val <<= 16;
5257 val |= bwn_shm_read_2(mac, BWN_SHARED, 0x088);
5258
5259 return (val);
5260}
5261
5262static void
5263bwn_noise_gensample(struct bwn_mac *mac)
5264{
5265 uint32_t jssi = 0x7f7f7f7f;
5266
5267 bwn_shm_write_2(mac, BWN_SHARED, 0x088, (jssi & 0x0000ffff));
5268 bwn_shm_write_2(mac, BWN_SHARED, 0x08a, (jssi & 0xffff0000) >> 16);
5269 BWN_WRITE_4(mac, BWN_MACCMD,
5270 BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_BGNOISE);
5271}
5272
5273static int
5274bwn_dma_freeslot(struct bwn_dma_ring *dr)
5275{
5276 BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
5277
5278 return (dr->dr_numslots - dr->dr_usedslot);
5279}
5280
5281static int
5282bwn_dma_nextslot(struct bwn_dma_ring *dr, int slot)
5283{
5284 BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
5285
5286 KASSERT(slot >= -1 && slot <= dr->dr_numslots - 1,
5287 ("%s:%d: fail", __func__, __LINE__));
5288 if (slot == dr->dr_numslots - 1)
5289 return (0);
5290 return (slot + 1);
5291}
5292
5293static void
5294bwn_dma_rxeof(struct bwn_dma_ring *dr, int *slot)
5295{
5296 struct bwn_mac *mac = dr->dr_mac;
5297 struct bwn_softc *sc = mac->mac_sc;
5298 struct bwn_dma *dma = &mac->mac_method.dma;
5299 struct bwn_dmadesc_generic *desc;
5300 struct bwn_dmadesc_meta *meta;
5301 struct bwn_rxhdr4 *rxhdr;
5302 struct mbuf *m;
5303 uint32_t macstat;
5304 int32_t tmp;
5305 int cnt = 0;
5306 uint16_t len;
5307
5308 dr->getdesc(dr, *slot, &desc, &meta);
5309
5310 bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap, BUS_DMASYNC_POSTREAD);
5311 m = meta->mt_m;
5312
5313 if (bwn_dma_newbuf(dr, desc, meta, 0)) {
5314 counter_u64_add(sc->sc_ic.ic_ierrors, 1);
5315 return;
5316 }
5317
5318 rxhdr = mtod(m, struct bwn_rxhdr4 *);
5319 len = le16toh(rxhdr->frame_len);
5320 if (len <= 0) {
5321 counter_u64_add(sc->sc_ic.ic_ierrors, 1);
5322 return;
5323 }
5324 if (bwn_dma_check_redzone(dr, m)) {
5325 device_printf(sc->sc_dev, "redzone error.\n");
5326 bwn_dma_set_redzone(dr, m);
5327 bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
5328 BUS_DMASYNC_PREWRITE);
5329 return;
5330 }
5331 if (len > dr->dr_rx_bufsize) {
5332 tmp = len;
5333 while (1) {
5334 dr->getdesc(dr, *slot, &desc, &meta);
5335 bwn_dma_set_redzone(dr, meta->mt_m);
5336 bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
5337 BUS_DMASYNC_PREWRITE);
5338 *slot = bwn_dma_nextslot(dr, *slot);
5339 cnt++;
5340 tmp -= dr->dr_rx_bufsize;
5341 if (tmp <= 0)
5342 break;
5343 }
5344 device_printf(sc->sc_dev, "too small buffer "
5345 "(len %u buffer %u dropped %d)\n",
5346 len, dr->dr_rx_bufsize, cnt);
5347 return;
5348 }
5349 macstat = le32toh(rxhdr->mac_status);
5350 if (macstat & BWN_RX_MAC_FCSERR) {
5351 if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
5352 device_printf(sc->sc_dev, "RX drop\n");
5353 return;
5354 }
5355 }
5356
5357 m->m_len = m->m_pkthdr.len = len + dr->dr_frameoffset;
5358 m_adj(m, dr->dr_frameoffset);
5359
5360 bwn_rxeof(dr->dr_mac, m, rxhdr);
5361}
5362
5363static void
5364bwn_handle_txeof(struct bwn_mac *mac, const struct bwn_txstatus *status)
5365{
5366 struct bwn_softc *sc = mac->mac_sc;
5367 struct bwn_stats *stats = &mac->mac_stats;
5368
5369 BWN_ASSERT_LOCKED(mac->mac_sc);
5370
5371 if (status->im)
5372 device_printf(sc->sc_dev, "TODO: STATUS IM\n");
5373 if (status->ampdu)
5374 device_printf(sc->sc_dev, "TODO: STATUS AMPDU\n");
5375 if (status->rtscnt) {
5376 if (status->rtscnt == 0xf)
5377 stats->rtsfail++;
5378 else
5379 stats->rts++;
5380 }
5381
5382 if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
5383 bwn_dma_handle_txeof(mac, status);
5384 } else {
5385 bwn_pio_handle_txeof(mac, status);
5386 }
5387
5388 bwn_phy_txpower_check(mac, 0);
5389}
5390
5391static uint8_t
5392bwn_pio_rxeof(struct bwn_pio_rxqueue *prq)
5393{
5394 struct bwn_mac *mac = prq->prq_mac;
5395 struct bwn_softc *sc = mac->mac_sc;
5396 struct bwn_rxhdr4 rxhdr;
5397 struct mbuf *m;
5398 uint32_t ctl32, macstat, v32;
5399 unsigned int i, padding;
5400 uint16_t ctl16, len, totlen, v16;
5401 unsigned char *mp;
5402 char *data;
5403
5404 memset(&rxhdr, 0, sizeof(rxhdr));
5405
5406 if (prq->prq_rev >= 8) {
5407 ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
5408 if (!(ctl32 & BWN_PIO8_RXCTL_FRAMEREADY))
5409 return (0);
5410 bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
5411 BWN_PIO8_RXCTL_FRAMEREADY);
5412 for (i = 0; i < 10; i++) {
5413 ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
5414 if (ctl32 & BWN_PIO8_RXCTL_DATAREADY)
5415 goto ready;
5416 DELAY(10);
5417 }
5418 } else {
5419 ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
5420 if (!(ctl16 & BWN_PIO_RXCTL_FRAMEREADY))
5421 return (0);
5422 bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL,
5423 BWN_PIO_RXCTL_FRAMEREADY);
5424 for (i = 0; i < 10; i++) {
5425 ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
5426 if (ctl16 & BWN_PIO_RXCTL_DATAREADY)
5427 goto ready;
5428 DELAY(10);
5429 }
5430 }
5431 device_printf(sc->sc_dev, "%s: timed out\n", __func__);
5432 return (1);
5433ready:
5434 if (prq->prq_rev >= 8)
5435 siba_read_multi_4(sc->sc_dev, &rxhdr, sizeof(rxhdr),
5436 prq->prq_base + BWN_PIO8_RXDATA);
5437 else
5438 siba_read_multi_2(sc->sc_dev, &rxhdr, sizeof(rxhdr),
5439 prq->prq_base + BWN_PIO_RXDATA);
5440 len = le16toh(rxhdr.frame_len);
5441 if (len > 0x700) {
5442 device_printf(sc->sc_dev, "%s: len is too big\n", __func__);
5443 goto error;
5444 }
5445 if (len == 0) {
5446 device_printf(sc->sc_dev, "%s: len is 0\n", __func__);
5447 goto error;
5448 }
5449
5450 macstat = le32toh(rxhdr.mac_status);
5451 if (macstat & BWN_RX_MAC_FCSERR) {
5452 if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
5453 device_printf(sc->sc_dev, "%s: FCS error", __func__);
5454 goto error;
5455 }
5456 }
5457
5458 padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
5459 totlen = len + padding;
5460 KASSERT(totlen <= MCLBYTES, ("too big..\n"));
5461 m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
5462 if (m == NULL) {
5463 device_printf(sc->sc_dev, "%s: out of memory", __func__);
5464 goto error;
5465 }
5466 mp = mtod(m, unsigned char *);
5467 if (prq->prq_rev >= 8) {
5468 siba_read_multi_4(sc->sc_dev, mp, (totlen & ~3),
5469 prq->prq_base + BWN_PIO8_RXDATA);
5470 if (totlen & 3) {
5471 v32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXDATA);
5472 data = &(mp[totlen - 1]);
5473 switch (totlen & 3) {
5474 case 3:
5475 *data = (v32 >> 16);
5476 data--;
5477 case 2:
5478 *data = (v32 >> 8);
5479 data--;
5480 case 1:
5481 *data = v32;
5482 }
5483 }
5484 } else {
5485 siba_read_multi_2(sc->sc_dev, mp, (totlen & ~1),
5486 prq->prq_base + BWN_PIO_RXDATA);
5487 if (totlen & 1) {
5488 v16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXDATA);
5489 mp[totlen - 1] = v16;
5490 }
5491 }
5492
5493 m->m_len = m->m_pkthdr.len = totlen;
5494
5495 bwn_rxeof(prq->prq_mac, m, &rxhdr);
5496
5497 return (1);
5498error:
5499 if (prq->prq_rev >= 8)
5500 bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
5501 BWN_PIO8_RXCTL_DATAREADY);
5502 else
5503 bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL, BWN_PIO_RXCTL_DATAREADY);
5504 return (1);
5505}
5506
5507static int
5508bwn_dma_newbuf(struct bwn_dma_ring *dr, struct bwn_dmadesc_generic *desc,
5509 struct bwn_dmadesc_meta *meta, int init)
5510{
5511 struct bwn_mac *mac = dr->dr_mac;
5512 struct bwn_dma *dma = &mac->mac_method.dma;
5513 struct bwn_rxhdr4 *hdr;
5514 bus_dmamap_t map;
5515 bus_addr_t paddr;
5516 struct mbuf *m;
5517 int error;
5518
5519 m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
5520 if (m == NULL) {
5521 error = ENOBUFS;
5522
5523 /*
5524 * If the NIC is up and running, we need to:
5525 * - Clear RX buffer's header.
5526 * - Restore RX descriptor settings.
5527 */
5528 if (init)
5529 return (error);
5530 else
5531 goto back;
5532 }
5533 m->m_len = m->m_pkthdr.len = MCLBYTES;
5534
5535 bwn_dma_set_redzone(dr, m);
5536
5537 /*
5538 * Try to load RX buf into temporary DMA map
5539 */
5540 error = bus_dmamap_load_mbuf(dma->rxbuf_dtag, dr->dr_spare_dmap, m,
5541 bwn_dma_buf_addr, &paddr, BUS_DMA_NOWAIT);
5542 if (error) {
5543 m_freem(m);
5544
5545 /*
5546 * See the comment above
5547 */
5548 if (init)
5549 return (error);
5550 else
5551 goto back;
5552 }
5553
5554 if (!init)
5555 bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
5556 meta->mt_m = m;
5557 meta->mt_paddr = paddr;
5558
5559 /*
5560 * Swap RX buf's DMA map with the loaded temporary one
5561 */
5562 map = meta->mt_dmap;
5563 meta->mt_dmap = dr->dr_spare_dmap;
5564 dr->dr_spare_dmap = map;
5565
5566back:
5567 /*
5568 * Clear RX buf header
5569 */
5570 hdr = mtod(meta->mt_m, struct bwn_rxhdr4 *);
5571 bzero(hdr, sizeof(*hdr));
5572 bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
5573 BUS_DMASYNC_PREWRITE);
5574
5575 /*
5576 * Setup RX buf descriptor
5577 */
5578 dr->setdesc(dr, desc, meta->mt_paddr, meta->mt_m->m_len -
5579 sizeof(*hdr), 0, 0, 0);
5580 return (error);
5581}
5582
5583static void
5584bwn_dma_buf_addr(void *arg, bus_dma_segment_t *seg, int nseg,
5585 bus_size_t mapsz __unused, int error)
5586{
5587
5588 if (!error) {
5589 KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
5590 *((bus_addr_t *)arg) = seg->ds_addr;
5591 }
5592}
5593
5594static int
5595bwn_hwrate2ieeerate(int rate)
5596{
5597
5598 switch (rate) {
5599 case BWN_CCK_RATE_1MB:
5600 return (2);
5601 case BWN_CCK_RATE_2MB:
5602 return (4);
5603 case BWN_CCK_RATE_5MB:
5604 return (11);
5605 case BWN_CCK_RATE_11MB:
5606 return (22);
5607 case BWN_OFDM_RATE_6MB:
5608 return (12);
5609 case BWN_OFDM_RATE_9MB:
5610 return (18);
5611 case BWN_OFDM_RATE_12MB:
5612 return (24);
5613 case BWN_OFDM_RATE_18MB:
5614 return (36);
5615 case BWN_OFDM_RATE_24MB:
5616 return (48);
5617 case BWN_OFDM_RATE_36MB:
5618 return (72);
5619 case BWN_OFDM_RATE_48MB:
5620 return (96);
5621 case BWN_OFDM_RATE_54MB:
5622 return (108);
5623 default:
5624 printf("Ooops\n");
5625 return (0);
5626 }
5627}
5628
5629/*
5630 * Post process the RX provided RSSI.
5631 *
5632 * Valid for A, B, G, LP PHYs.
5633 */
5634static int8_t
5635bwn_rx_rssi_calc(struct bwn_mac *mac, uint8_t in_rssi,
5636 int ofdm, int adjust_2053, int adjust_2050)
5637{
5638 struct bwn_phy *phy = &mac->mac_phy;
5639 struct bwn_phy_g *gphy = &phy->phy_g;
5640 int tmp;
5641
5642 switch (phy->rf_ver) {
5643 case 0x2050:
5644 if (ofdm) {
5645 tmp = in_rssi;
5646 if (tmp > 127)
5647 tmp -= 256;
5648 tmp = tmp * 73 / 64;
5649 if (adjust_2050)
5650 tmp += 25;
5651 else
5652 tmp -= 3;
5653 } else {
5654 if (siba_sprom_get_bf_lo(mac->mac_sc->sc_dev)
5655 & BWN_BFL_RSSI) {
5656 if (in_rssi > 63)
5657 in_rssi = 63;
5658 tmp = gphy->pg_nrssi_lt[in_rssi];
5659 tmp = (31 - tmp) * -131 / 128 - 57;
5660 } else {
5661 tmp = in_rssi;
5662 tmp = (31 - tmp) * -149 / 128 - 68;
5663 }
5664 if (phy->type == BWN_PHYTYPE_G && adjust_2050)
5665 tmp += 25;
5666 }
5667 break;
5668 case 0x2060:
5669 if (in_rssi > 127)
5670 tmp = in_rssi - 256;
5671 else
5672 tmp = in_rssi;
5673 break;
5674 default:
5675 tmp = in_rssi;
5676 tmp = (tmp - 11) * 103 / 64;
5677 if (adjust_2053)
5678 tmp -= 109;
5679 else
5680 tmp -= 83;
5681 }
5682
5683 return (tmp);
5684}
5685
5686static void
5687bwn_rxeof(struct bwn_mac *mac, struct mbuf *m, const void *_rxhdr)
5688{
5689 const struct bwn_rxhdr4 *rxhdr = _rxhdr;
5690 struct bwn_plcp6 *plcp;
5691 struct bwn_softc *sc = mac->mac_sc;
5692 struct ieee80211_frame_min *wh;
5693 struct ieee80211_node *ni;
5694 struct ieee80211com *ic = &sc->sc_ic;
5695 uint32_t macstat;
5696 int padding, rate, rssi = 0, noise = 0, type;
5697 uint16_t phytype, phystat0, phystat3, chanstat;
5698 unsigned char *mp = mtod(m, unsigned char *);
5699 static int rx_mac_dec_rpt = 0;
5700
5701 BWN_ASSERT_LOCKED(sc);
5702
5703 phystat0 = le16toh(rxhdr->phy_status0);
5704 phystat3 = le16toh(rxhdr->phy_status3);
5705
5706 /* XXX Note: mactime, macstat, chanstat need fixing for fw 598 */
5707 macstat = le32toh(rxhdr->mac_status);
5708 chanstat = le16toh(rxhdr->channel);
5709
5710 phytype = chanstat & BWN_RX_CHAN_PHYTYPE;
5711
5712 if (macstat & BWN_RX_MAC_FCSERR)
5713 device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_FCS_CRC\n");
5714 if (phystat0 & (BWN_RX_PHYST0_PLCPHCF | BWN_RX_PHYST0_PLCPFV))
5715 device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_PLCP_CRC\n");
5716 if (macstat & BWN_RX_MAC_DECERR)
5717 goto drop;
5718
5719 padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
5720 if (m->m_pkthdr.len < (sizeof(struct bwn_plcp6) + padding)) {
5721 device_printf(sc->sc_dev, "frame too short (length=%d)\n",
5722 m->m_pkthdr.len);
5723 goto drop;
5724 }
5725 plcp = (struct bwn_plcp6 *)(mp + padding);
5726 m_adj(m, sizeof(struct bwn_plcp6) + padding);
5727 if (m->m_pkthdr.len < IEEE80211_MIN_LEN) {
5728 device_printf(sc->sc_dev, "frame too short (length=%d)\n",
5729 m->m_pkthdr.len);
5730 goto drop;
5731 }
5732 wh = mtod(m, struct ieee80211_frame_min *);
5733
5734 if (macstat & BWN_RX_MAC_DEC && rx_mac_dec_rpt++ < 50)
5735 device_printf(sc->sc_dev,
5736 "RX decryption attempted (old %d keyidx %#x)\n",
5737 BWN_ISOLDFMT(mac),
5738 (macstat & BWN_RX_MAC_KEYIDX) >> BWN_RX_MAC_KEYIDX_SHIFT);
5739
5740 if (phystat0 & BWN_RX_PHYST0_OFDM)
5741 rate = bwn_plcp_get_ofdmrate(mac, plcp,
5742 phytype == BWN_PHYTYPE_A);
5743 else
5744 rate = bwn_plcp_get_cckrate(mac, plcp);
5745 if (rate == -1) {
5746 if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADPLCP))
5747 goto drop;
5748 }
5749 sc->sc_rx_rate = bwn_hwrate2ieeerate(rate);
5750
5751 /* rssi/noise */
5752 switch (phytype) {
5753 case BWN_PHYTYPE_A:
5754 case BWN_PHYTYPE_B:
5755 case BWN_PHYTYPE_G:
5756 case BWN_PHYTYPE_LP:
5757 rssi = bwn_rx_rssi_calc(mac, rxhdr->phy.abg.rssi,
5758 !! (phystat0 & BWN_RX_PHYST0_OFDM),
5759 !! (phystat0 & BWN_RX_PHYST0_GAINCTL),
5760 !! (phystat3 & BWN_RX_PHYST3_TRSTATE));
5761 break;
5762 case BWN_PHYTYPE_N:
5763 /* Broadcom has code for min/avg, but always used max */
5764 if (rxhdr->phy.n.power0 == 16 || rxhdr->phy.n.power0 == 32)
5765 rssi = max(rxhdr->phy.n.power1, rxhdr->ps2.n.power2);
5766 else
5767 rssi = max(rxhdr->phy.n.power0, rxhdr->phy.n.power1);
5768 break;
5769 default:
5770 /* XXX TODO: implement rssi for other PHYs */
5771 break;
5772 }
5773
5774 noise = mac->mac_stats.link_noise;
5775
5776 /* RX radio tap */
5777 if (ieee80211_radiotap_active(ic))
5778 bwn_rx_radiotap(mac, m, rxhdr, plcp, rate, rssi, noise);
5779 m_adj(m, -IEEE80211_CRC_LEN);
5780
5781 BWN_UNLOCK(sc);
5782
5783 ni = ieee80211_find_rxnode(ic, wh);
5784 if (ni != NULL) {
5785 type = ieee80211_input(ni, m, rssi, noise);
5786 ieee80211_free_node(ni);
5787 } else
5788 type = ieee80211_input_all(ic, m, rssi, noise);
5789
5790 BWN_LOCK(sc);
5791 return;
5792drop:
5793 device_printf(sc->sc_dev, "%s: dropped\n", __func__);
5794}
5795
5796static void
5797bwn_dma_handle_txeof(struct bwn_mac *mac,
5798 const struct bwn_txstatus *status)
5799{
5800 struct bwn_dma *dma = &mac->mac_method.dma;
5801 struct bwn_dma_ring *dr;
5802 struct bwn_dmadesc_generic *desc;
5803 struct bwn_dmadesc_meta *meta;
5804 struct bwn_softc *sc = mac->mac_sc;
5805 int slot;
5806 int retrycnt = 0;
5807
5808 BWN_ASSERT_LOCKED(sc);
5809
5810 dr = bwn_dma_parse_cookie(mac, status, status->cookie, &slot);
5811 if (dr == NULL) {
5812 device_printf(sc->sc_dev, "failed to parse cookie\n");
5813 return;
5814 }
5815 KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
5816
5817 while (1) {
5818 KASSERT(slot >= 0 && slot < dr->dr_numslots,
5819 ("%s:%d: fail", __func__, __LINE__));
5820 dr->getdesc(dr, slot, &desc, &meta);
5821
5822 if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
5823 bus_dmamap_unload(dr->dr_txring_dtag, meta->mt_dmap);
5824 else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
5825 bus_dmamap_unload(dma->txbuf_dtag, meta->mt_dmap);
5826
5827 if (meta->mt_islast) {
5828 KASSERT(meta->mt_m != NULL,
5829 ("%s:%d: fail", __func__, __LINE__));
5830
5831 /*
5832 * If we don't get an ACK, then we should log the
5833 * full framecnt. That may be 0 if it's a PHY
5834 * failure, so ensure that gets logged as some
5835 * retry attempt.
5836 */
5837 if (status->ack) {
5838 retrycnt = status->framecnt - 1;
5839 } else {
5840 retrycnt = status->framecnt;
5841 if (retrycnt == 0)
5842 retrycnt = 1;
5843 }
5844 ieee80211_ratectl_tx_complete(meta->mt_ni->ni_vap, meta->mt_ni,
5845 status->ack ?
5846 IEEE80211_RATECTL_TX_SUCCESS :
5847 IEEE80211_RATECTL_TX_FAILURE,
5848 &retrycnt, 0);
5849 ieee80211_tx_complete(meta->mt_ni, meta->mt_m, 0);
5850 meta->mt_ni = NULL;
5851 meta->mt_m = NULL;
5852 } else
5853 KASSERT(meta->mt_m == NULL,
5854 ("%s:%d: fail", __func__, __LINE__));
5855
5856 dr->dr_usedslot--;
5857 if (meta->mt_islast)
5858 break;
5859 slot = bwn_dma_nextslot(dr, slot);
5860 }
5861 sc->sc_watchdog_timer = 0;
5862 if (dr->dr_stop) {
5863 KASSERT(bwn_dma_freeslot(dr) >= BWN_TX_SLOTS_PER_FRAME,
5864 ("%s:%d: fail", __func__, __LINE__));
5865 dr->dr_stop = 0;
5866 }
5867}
5868
5869static void
5870bwn_pio_handle_txeof(struct bwn_mac *mac,
5871 const struct bwn_txstatus *status)
5872{
5873 struct bwn_pio_txqueue *tq;
5874 struct bwn_pio_txpkt *tp = NULL;
5875 struct bwn_softc *sc = mac->mac_sc;
5876 int retrycnt = 0;
5877
5878 BWN_ASSERT_LOCKED(sc);
5879
5880 tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
5881 if (tq == NULL)
5882 return;
5883
5884 tq->tq_used -= roundup(tp->tp_m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
5885 tq->tq_free++;
5886
5887 if (tp->tp_ni != NULL) {
5888 /*
5889 * Do any tx complete callback. Note this must
5890 * be done before releasing the node reference.
5891 */
5892
5893 /*
5894 * If we don't get an ACK, then we should log the
5895 * full framecnt. That may be 0 if it's a PHY
5896 * failure, so ensure that gets logged as some
5897 * retry attempt.
5898 */
5899 if (status->ack) {
5900 retrycnt = status->framecnt - 1;
5901 } else {
5902 retrycnt = status->framecnt;
5903 if (retrycnt == 0)
5904 retrycnt = 1;
5905 }
5906 ieee80211_ratectl_tx_complete(tp->tp_ni->ni_vap, tp->tp_ni,
5907 status->ack ?
5908 IEEE80211_RATECTL_TX_SUCCESS :
5909 IEEE80211_RATECTL_TX_FAILURE,
5910 &retrycnt, 0);
5911
5912 if (tp->tp_m->m_flags & M_TXCB)
5913 ieee80211_process_callback(tp->tp_ni, tp->tp_m, 0);
5914 ieee80211_free_node(tp->tp_ni);
5915 tp->tp_ni = NULL;
5916 }
5917 m_freem(tp->tp_m);
5918 tp->tp_m = NULL;
5919 TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
5920
5921 sc->sc_watchdog_timer = 0;
5922}
5923
5924static void
5925bwn_phy_txpower_check(struct bwn_mac *mac, uint32_t flags)
5926{
5927 struct bwn_softc *sc = mac->mac_sc;
5928 struct bwn_phy *phy = &mac->mac_phy;
5929 struct ieee80211com *ic = &sc->sc_ic;
5930 unsigned long now;
5931 bwn_txpwr_result_t result;
5932
5933 BWN_GETTIME(now);
5934
5935 if (!(flags & BWN_TXPWR_IGNORE_TIME) && ieee80211_time_before(now, phy->nexttime))
5936 return;
5937 phy->nexttime = now + 2 * 1000;
5938
5939 if (siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM &&
5940 siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306)
5941 return;
5942
5943 if (phy->recalc_txpwr != NULL) {
5944 result = phy->recalc_txpwr(mac,
5945 (flags & BWN_TXPWR_IGNORE_TSSI) ? 1 : 0);
5946 if (result == BWN_TXPWR_RES_DONE)
5947 return;
5948 KASSERT(result == BWN_TXPWR_RES_NEED_ADJUST,
5949 ("%s: fail", __func__));
5950 KASSERT(phy->set_txpwr != NULL, ("%s: fail", __func__));
5951
5952 ieee80211_runtask(ic, &mac->mac_txpower);
5953 }
5954}
5955
5956static uint16_t
5957bwn_pio_rx_read_2(struct bwn_pio_rxqueue *prq, uint16_t offset)
5958{
5959
5960 return (BWN_READ_2(prq->prq_mac, prq->prq_base + offset));
5961}
5962
5963static uint32_t
5964bwn_pio_rx_read_4(struct bwn_pio_rxqueue *prq, uint16_t offset)
5965{
5966
5967 return (BWN_READ_4(prq->prq_mac, prq->prq_base + offset));
5968}
5969
5970static void
5971bwn_pio_rx_write_2(struct bwn_pio_rxqueue *prq, uint16_t offset, uint16_t value)
5972{
5973
5974 BWN_WRITE_2(prq->prq_mac, prq->prq_base + offset, value);
5975}
5976
5977static void
5978bwn_pio_rx_write_4(struct bwn_pio_rxqueue *prq, uint16_t offset, uint32_t value)
5979{
5980
5981 BWN_WRITE_4(prq->prq_mac, prq->prq_base + offset, value);
5982}
5983
5984static int
5985bwn_ieeerate2hwrate(struct bwn_softc *sc, int rate)
5986{
5987
5988 switch (rate) {
5989 /* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
5990 case 12:
5991 return (BWN_OFDM_RATE_6MB);
5992 case 18:
5993 return (BWN_OFDM_RATE_9MB);
5994 case 24:
5995 return (BWN_OFDM_RATE_12MB);
5996 case 36:
5997 return (BWN_OFDM_RATE_18MB);
5998 case 48:
5999 return (BWN_OFDM_RATE_24MB);
6000 case 72:
6001 return (BWN_OFDM_RATE_36MB);
6002 case 96:
6003 return (BWN_OFDM_RATE_48MB);
6004 case 108:
6005 return (BWN_OFDM_RATE_54MB);
6006 /* CCK rates (NB: not IEEE std, device-specific) */
6007 case 2:
6008 return (BWN_CCK_RATE_1MB);
6009 case 4:
6010 return (BWN_CCK_RATE_2MB);
6011 case 11:
6012 return (BWN_CCK_RATE_5MB);
6013 case 22:
6014 return (BWN_CCK_RATE_11MB);
6015 }
6016
6017 device_printf(sc->sc_dev, "unsupported rate %d\n", rate);
6018 return (BWN_CCK_RATE_1MB);
6019}
6020
6021static uint16_t
6022bwn_set_txhdr_phyctl1(struct bwn_mac *mac, uint8_t bitrate)
6023{
6024 struct bwn_phy *phy = &mac->mac_phy;
6025 uint16_t control = 0;
6026 uint16_t bw;
6027
6028 /* XXX TODO: this is for LP phy, what about N-PHY, etc? */
6029 bw = BWN_TXH_PHY1_BW_20;
6030
6031 if (BWN_ISCCKRATE(bitrate) && phy->type != BWN_PHYTYPE_LP) {
6032 control = bw;
6033 } else {
6034 control = bw;
6035 /* Figure out coding rate and modulation */
6036 /* XXX TODO: table-ize, for MCS transmit */
6037 /* Note: this is BWN_*_RATE values */
6038 switch (bitrate) {
6039 case BWN_CCK_RATE_1MB:
6040 control |= 0;
6041 break;
6042 case BWN_CCK_RATE_2MB:
6043 control |= 1;
6044 break;
6045 case BWN_CCK_RATE_5MB:
6046 control |= 2;
6047 break;
6048 case BWN_CCK_RATE_11MB:
6049 control |= 3;
6050 break;
6051 case BWN_OFDM_RATE_6MB:
6052 control |= BWN_TXH_PHY1_CRATE_1_2;
6053 control |= BWN_TXH_PHY1_MODUL_BPSK;
6054 break;
6055 case BWN_OFDM_RATE_9MB:
6056 control |= BWN_TXH_PHY1_CRATE_3_4;
6057 control |= BWN_TXH_PHY1_MODUL_BPSK;
6058 break;
6059 case BWN_OFDM_RATE_12MB:
6060 control |= BWN_TXH_PHY1_CRATE_1_2;
6061 control |= BWN_TXH_PHY1_MODUL_QPSK;
6062 break;
6063 case BWN_OFDM_RATE_18MB:
6064 control |= BWN_TXH_PHY1_CRATE_3_4;
6065 control |= BWN_TXH_PHY1_MODUL_QPSK;
6066 break;
6067 case BWN_OFDM_RATE_24MB:
6068 control |= BWN_TXH_PHY1_CRATE_1_2;
6069 control |= BWN_TXH_PHY1_MODUL_QAM16;
6070 break;
6071 case BWN_OFDM_RATE_36MB:
6072 control |= BWN_TXH_PHY1_CRATE_3_4;
6073 control |= BWN_TXH_PHY1_MODUL_QAM16;
6074 break;
6075 case BWN_OFDM_RATE_48MB:
6076 control |= BWN_TXH_PHY1_CRATE_1_2;
6077 control |= BWN_TXH_PHY1_MODUL_QAM64;
6078 break;
6079 case BWN_OFDM_RATE_54MB:
6080 control |= BWN_TXH_PHY1_CRATE_3_4;
6081 control |= BWN_TXH_PHY1_MODUL_QAM64;
6082 break;
6083 default:
6084 break;
6085 }
6086 control |= BWN_TXH_PHY1_MODE_SISO;
6087 }
6088
6089 return control;
6090}
6091
6092static int
6093bwn_set_txhdr(struct bwn_mac *mac, struct ieee80211_node *ni,
6094 struct mbuf *m, struct bwn_txhdr *txhdr, uint16_t cookie)
6095{
6096 const struct bwn_phy *phy = &mac->mac_phy;
6097 struct bwn_softc *sc = mac->mac_sc;
6098 struct ieee80211_frame *wh;
6099 struct ieee80211_frame *protwh;
6100 struct ieee80211_frame_cts *cts;
6101 struct ieee80211_frame_rts *rts;
6102 const struct ieee80211_txparam *tp;
6103 struct ieee80211vap *vap = ni->ni_vap;
6104 struct ieee80211com *ic = &sc->sc_ic;
6105 struct mbuf *mprot;
6106 unsigned int len;
6107 uint32_t macctl = 0;
6108 int protdur, rts_rate, rts_rate_fb, ismcast, isshort, rix, type;
6109 uint16_t phyctl = 0;
6110 uint8_t rate, rate_fb;
6111 int fill_phy_ctl1 = 0;
6112
6113 wh = mtod(m, struct ieee80211_frame *);
6114 memset(txhdr, 0, sizeof(*txhdr));
6115
6116 type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
6117 ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
6118 isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0;
6119
6120 if ((phy->type == BWN_PHYTYPE_N) || (phy->type == BWN_PHYTYPE_LP)
6121 || (phy->type == BWN_PHYTYPE_HT))
6122 fill_phy_ctl1 = 1;
6123
6124 /*
6125 * Find TX rate
6126 */
6127 tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)];
6128 if (type != IEEE80211_FC0_TYPE_DATA || (m->m_flags & M_EAPOL))
6129 rate = rate_fb = tp->mgmtrate;
6130 else if (ismcast)
6131 rate = rate_fb = tp->mcastrate;
6132 else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
6133 rate = rate_fb = tp->ucastrate;
6134 else {
6135 /* XXX TODO: don't fall back to CCK rates for OFDM */
6136 rix = ieee80211_ratectl_rate(ni, NULL, 0);
6137 rate = ni->ni_txrate;
6138
6139 if (rix > 0)
6140 rate_fb = ni->ni_rates.rs_rates[rix - 1] &
6141 IEEE80211_RATE_VAL;
6142 else
6143 rate_fb = rate;
6144 }
6145
6146 sc->sc_tx_rate = rate;
6147
6148 /* Note: this maps the select ieee80211 rate to hardware rate */
6149 rate = bwn_ieeerate2hwrate(sc, rate);
6150 rate_fb = bwn_ieeerate2hwrate(sc, rate_fb);
6151
6152 txhdr->phyrate = (BWN_ISOFDMRATE(rate)) ? bwn_plcp_getofdm(rate) :
6153 bwn_plcp_getcck(rate);
6154 bcopy(wh->i_fc, txhdr->macfc, sizeof(txhdr->macfc));
6155 bcopy(wh->i_addr1, txhdr->addr1, IEEE80211_ADDR_LEN);
6156
6157 /* XXX rate/rate_fb is the hardware rate */
6158 if ((rate_fb == rate) ||
6159 (*(u_int16_t *)wh->i_dur & htole16(0x8000)) ||
6160 (*(u_int16_t *)wh->i_dur == htole16(0)))
6161 txhdr->dur_fb = *(u_int16_t *)wh->i_dur;
6162 else
6163 txhdr->dur_fb = ieee80211_compute_duration(ic->ic_rt,
6164 m->m_pkthdr.len, rate, isshort);
6165
6166 /* XXX TX encryption */
6167 bwn_plcp_genhdr(BWN_ISOLDFMT(mac) ?
6168 (struct bwn_plcp4 *)(&txhdr->body.old.plcp) :
6169 (struct bwn_plcp4 *)(&txhdr->body.new.plcp),
6170 m->m_pkthdr.len + IEEE80211_CRC_LEN, rate);
6171 bwn_plcp_genhdr((struct bwn_plcp4 *)(&txhdr->plcp_fb),
6172 m->m_pkthdr.len + IEEE80211_CRC_LEN, rate_fb);
6173
6174 txhdr->eftypes |= (BWN_ISOFDMRATE(rate_fb)) ? BWN_TX_EFT_FB_OFDM :
6175 BWN_TX_EFT_FB_CCK;
6176 txhdr->chan = phy->chan;
6177 phyctl |= (BWN_ISOFDMRATE(rate)) ? BWN_TX_PHY_ENC_OFDM :
6178 BWN_TX_PHY_ENC_CCK;
6179 /* XXX preamble? obey net80211 */
6180 if (isshort && (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
6181 rate == BWN_CCK_RATE_11MB))
6182 phyctl |= BWN_TX_PHY_SHORTPRMBL;
6183
6184 if (! phy->gmode)
6185 macctl |= BWN_TX_MAC_5GHZ;
6186
6187 /* XXX TX antenna selection */
6188
6189 switch (bwn_antenna_sanitize(mac, 0)) {
6190 case 0:
6191 phyctl |= BWN_TX_PHY_ANT01AUTO;
6192 break;
6193 case 1:
6194 phyctl |= BWN_TX_PHY_ANT0;
6195 break;
6196 case 2:
6197 phyctl |= BWN_TX_PHY_ANT1;
6198 break;
6199 case 3:
6200 phyctl |= BWN_TX_PHY_ANT2;
6201 break;
6202 case 4:
6203 phyctl |= BWN_TX_PHY_ANT3;
6204 break;
6205 default:
6206 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
6207 }
6208
6209 if (!ismcast)
6210 macctl |= BWN_TX_MAC_ACK;
6211
6212 macctl |= (BWN_TX_MAC_HWSEQ | BWN_TX_MAC_START_MSDU);
6213 if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
6214 m->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold)
6215 macctl |= BWN_TX_MAC_LONGFRAME;
6216
6217 if (ic->ic_flags & IEEE80211_F_USEPROT) {
6218 /* XXX RTS rate is always 1MB??? */
6219 /* XXX TODO: don't fall back to CCK rates for OFDM */
6220 rts_rate = BWN_CCK_RATE_1MB;
6221 rts_rate_fb = bwn_get_fbrate(rts_rate);
6222
6223 /* XXX 'rate' here is hardware rate now, not the net80211 rate */
6224 protdur = ieee80211_compute_duration(ic->ic_rt,
6225 m->m_pkthdr.len, rate, isshort) +
6226 + ieee80211_ack_duration(ic->ic_rt, rate, isshort);
6227
6228 if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) {
6229 cts = (struct ieee80211_frame_cts *)(BWN_ISOLDFMT(mac) ?
6230 (txhdr->body.old.rts_frame) :
6231 (txhdr->body.new.rts_frame));
6232 mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr,
6233 protdur);
6234 KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
6235 bcopy(mtod(mprot, uint8_t *), (uint8_t *)cts,
6236 mprot->m_pkthdr.len);
6237 m_freem(mprot);
6238 macctl |= BWN_TX_MAC_SEND_CTSTOSELF;
6239 len = sizeof(struct ieee80211_frame_cts);
6240 } else {
6241 rts = (struct ieee80211_frame_rts *)(BWN_ISOLDFMT(mac) ?
6242 (txhdr->body.old.rts_frame) :
6243 (txhdr->body.new.rts_frame));
6244 /* XXX rate/rate_fb is the hardware rate */
6245 protdur += ieee80211_ack_duration(ic->ic_rt, rate,
6246 isshort);
6247 mprot = ieee80211_alloc_rts(ic, wh->i_addr1,
6248 wh->i_addr2, protdur);
6249 KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
6250 bcopy(mtod(mprot, uint8_t *), (uint8_t *)rts,
6251 mprot->m_pkthdr.len);
6252 m_freem(mprot);
6253 macctl |= BWN_TX_MAC_SEND_RTSCTS;
6254 len = sizeof(struct ieee80211_frame_rts);
6255 }
6256 len += IEEE80211_CRC_LEN;
6257 bwn_plcp_genhdr((struct bwn_plcp4 *)((BWN_ISOLDFMT(mac)) ?
6258 &txhdr->body.old.rts_plcp :
6259 &txhdr->body.new.rts_plcp), len, rts_rate);
6260 bwn_plcp_genhdr((struct bwn_plcp4 *)&txhdr->rts_plcp_fb, len,
6261 rts_rate_fb);
6262
6263 protwh = (struct ieee80211_frame *)(BWN_ISOLDFMT(mac) ?
6264 (&txhdr->body.old.rts_frame) :
6265 (&txhdr->body.new.rts_frame));
6266 txhdr->rts_dur_fb = *(u_int16_t *)protwh->i_dur;
6267
6268 if (BWN_ISOFDMRATE(rts_rate)) {
6269 txhdr->eftypes |= BWN_TX_EFT_RTS_OFDM;
6270 txhdr->phyrate_rts = bwn_plcp_getofdm(rts_rate);
6271 } else {
6272 txhdr->eftypes |= BWN_TX_EFT_RTS_CCK;
6273 txhdr->phyrate_rts = bwn_plcp_getcck(rts_rate);
6274 }
6275 txhdr->eftypes |= (BWN_ISOFDMRATE(rts_rate_fb)) ?
6276 BWN_TX_EFT_RTS_FBOFDM : BWN_TX_EFT_RTS_FBCCK;
6277
6278 if (fill_phy_ctl1) {
6279 txhdr->phyctl_1rts = htole16(bwn_set_txhdr_phyctl1(mac, rts_rate));
6280 txhdr->phyctl_1rtsfb = htole16(bwn_set_txhdr_phyctl1(mac, rts_rate_fb));
6281 }
6282 }
6283
6284 if (fill_phy_ctl1) {
6285 txhdr->phyctl_1 = htole16(bwn_set_txhdr_phyctl1(mac, rate));
6286 txhdr->phyctl_1fb = htole16(bwn_set_txhdr_phyctl1(mac, rate_fb));
6287 }
6288
6289 if (BWN_ISOLDFMT(mac))
6290 txhdr->body.old.cookie = htole16(cookie);
6291 else
6292 txhdr->body.new.cookie = htole16(cookie);
6293
6294 txhdr->macctl = htole32(macctl);
6295 txhdr->phyctl = htole16(phyctl);
6296
6297 /*
6298 * TX radio tap
6299 */
6300 if (ieee80211_radiotap_active_vap(vap)) {
6301 sc->sc_tx_th.wt_flags = 0;
6302 if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED)
6303 sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP;
6304 if (isshort &&
6305 (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
6306 rate == BWN_CCK_RATE_11MB))
6307 sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
6308 sc->sc_tx_th.wt_rate = rate;
6309
6310 ieee80211_radiotap_tx(vap, m);
6311 }
6312
6313 return (0);
6314}
6315
6316static void
6317bwn_plcp_genhdr(struct bwn_plcp4 *plcp, const uint16_t octets,
6318 const uint8_t rate)
6319{
6320 uint32_t d, plen;
6321 uint8_t *raw = plcp->o.raw;
6322
6323 if (BWN_ISOFDMRATE(rate)) {
6324 d = bwn_plcp_getofdm(rate);
6325 KASSERT(!(octets & 0xf000),
6326 ("%s:%d: fail", __func__, __LINE__));
6327 d |= (octets << 5);
6328 plcp->o.data = htole32(d);
6329 } else {
6330 plen = octets * 16 / rate;
6331 if ((octets * 16 % rate) > 0) {
6332 plen++;
6333 if ((rate == BWN_CCK_RATE_11MB)
6334 && ((octets * 8 % 11) < 4)) {
6335 raw[1] = 0x84;
6336 } else
6337 raw[1] = 0x04;
6338 } else
6339 raw[1] = 0x04;
6340 plcp->o.data |= htole32(plen << 16);
6341 raw[0] = bwn_plcp_getcck(rate);
6342 }
6343}
6344
6345static uint8_t
6346bwn_antenna_sanitize(struct bwn_mac *mac, uint8_t n)
6347{
6348 struct bwn_softc *sc = mac->mac_sc;
6349 uint8_t mask;
6350
6351 if (n == 0)
6352 return (0);
6353 if (mac->mac_phy.gmode)
6354 mask = siba_sprom_get_ant_bg(sc->sc_dev);
6355 else
6356 mask = siba_sprom_get_ant_a(sc->sc_dev);
6357 if (!(mask & (1 << (n - 1))))
6358 return (0);
6359 return (n);
6360}
6361
6362/*
6363 * Return a fallback rate for the given rate.
6364 *
6365 * Note: Don't fall back from OFDM to CCK.
6366 */
6367static uint8_t
6368bwn_get_fbrate(uint8_t bitrate)
6369{
6370 switch (bitrate) {
6371 /* CCK */
6372 case BWN_CCK_RATE_1MB:
6373 return (BWN_CCK_RATE_1MB);
6374 case BWN_CCK_RATE_2MB:
6375 return (BWN_CCK_RATE_1MB);
6376 case BWN_CCK_RATE_5MB:
6377 return (BWN_CCK_RATE_2MB);
6378 case BWN_CCK_RATE_11MB:
6379 return (BWN_CCK_RATE_5MB);
6380
6381 /* OFDM */
6382 case BWN_OFDM_RATE_6MB:
6383 return (BWN_OFDM_RATE_6MB);
6384 case BWN_OFDM_RATE_9MB:
6385 return (BWN_OFDM_RATE_6MB);
6386 case BWN_OFDM_RATE_12MB:
6387 return (BWN_OFDM_RATE_9MB);
6388 case BWN_OFDM_RATE_18MB:
6389 return (BWN_OFDM_RATE_12MB);
6390 case BWN_OFDM_RATE_24MB:
6391 return (BWN_OFDM_RATE_18MB);
6392 case BWN_OFDM_RATE_36MB:
6393 return (BWN_OFDM_RATE_24MB);
6394 case BWN_OFDM_RATE_48MB:
6395 return (BWN_OFDM_RATE_36MB);
6396 case BWN_OFDM_RATE_54MB:
6397 return (BWN_OFDM_RATE_48MB);
6398 }
6399 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
6400 return (0);
6401}
6402
6403static uint32_t
6404bwn_pio_write_multi_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
6405 uint32_t ctl, const void *_data, int len)
6406{
6407 struct bwn_softc *sc = mac->mac_sc;
6408 uint32_t value = 0;
6409 const uint8_t *data = _data;
6410
6411 ctl |= BWN_PIO8_TXCTL_0_7 | BWN_PIO8_TXCTL_8_15 |
6412 BWN_PIO8_TXCTL_16_23 | BWN_PIO8_TXCTL_24_31;
6413 bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
6414
6415 siba_write_multi_4(sc->sc_dev, data, (len & ~3),
6416 tq->tq_base + BWN_PIO8_TXDATA);
6417 if (len & 3) {
6418 ctl &= ~(BWN_PIO8_TXCTL_8_15 | BWN_PIO8_TXCTL_16_23 |
6419 BWN_PIO8_TXCTL_24_31);
6420 data = &(data[len - 1]);
6421 switch (len & 3) {
6422 case 3:
6423 ctl |= BWN_PIO8_TXCTL_16_23;
6424 value |= (uint32_t)(*data) << 16;
6425 data--;
6426 case 2:
6427 ctl |= BWN_PIO8_TXCTL_8_15;
6428 value |= (uint32_t)(*data) << 8;
6429 data--;
6430 case 1:
6431 value |= (uint32_t)(*data);
6432 }
6433 bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
6434 bwn_pio_write_4(mac, tq, BWN_PIO8_TXDATA, value);
6435 }
6436
6437 return (ctl);
6438}
6439
6440static void
6441bwn_pio_write_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
6442 uint16_t offset, uint32_t value)
6443{
6444
6445 BWN_WRITE_4(mac, tq->tq_base + offset, value);
6446}
6447
6448static uint16_t
6449bwn_pio_write_multi_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
6450 uint16_t ctl, const void *_data, int len)
6451{
6452 struct bwn_softc *sc = mac->mac_sc;
6453 const uint8_t *data = _data;
6454
6455 ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
6456 BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
6457
6458 siba_write_multi_2(sc->sc_dev, data, (len & ~1),
6459 tq->tq_base + BWN_PIO_TXDATA);
6460 if (len & 1) {
6461 ctl &= ~BWN_PIO_TXCTL_WRITEHI;
6462 BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
6463 BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data[len - 1]);
6464 }
6465
6466 return (ctl);
6467}
6468
6469static uint16_t
6470bwn_pio_write_mbuf_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
6471 uint16_t ctl, struct mbuf *m0)
6472{
6473 int i, j = 0;
6474 uint16_t data = 0;
6475 const uint8_t *buf;
6476 struct mbuf *m = m0;
6477
6478 ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
6479 BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
6480
6481 for (; m != NULL; m = m->m_next) {
6482 buf = mtod(m, const uint8_t *);
6483 for (i = 0; i < m->m_len; i++) {
6484 if (!((j++) % 2))
6485 data |= buf[i];
6486 else {
6487 data |= (buf[i] << 8);
6488 BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
6489 data = 0;
6490 }
6491 }
6492 }
6493 if (m0->m_pkthdr.len % 2) {
6494 ctl &= ~BWN_PIO_TXCTL_WRITEHI;
6495 BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
6496 BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
6497 }
6498
6499 return (ctl);
6500}
6501
6502static void
6503bwn_set_slot_time(struct bwn_mac *mac, uint16_t time)
6504{
6505
6506 /* XXX should exit if 5GHz band .. */
6507 if (mac->mac_phy.type != BWN_PHYTYPE_G)
6508 return;
6509
6510 BWN_WRITE_2(mac, 0x684, 510 + time);
6511 /* Disabled in Linux b43, can adversely effect performance */
6512#if 0
6513 bwn_shm_write_2(mac, BWN_SHARED, 0x0010, time);
6514#endif
6515}
6516
6517static struct bwn_dma_ring *
6518bwn_dma_select(struct bwn_mac *mac, uint8_t prio)
6519{
6520
6521 if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
6522 return (mac->mac_method.dma.wme[WME_AC_BE]);
6523
6524 switch (prio) {
6525 case 3:
6526 return (mac->mac_method.dma.wme[WME_AC_VO]);
6527 case 2:
6528 return (mac->mac_method.dma.wme[WME_AC_VI]);
6529 case 0:
6530 return (mac->mac_method.dma.wme[WME_AC_BE]);
6531 case 1:
6532 return (mac->mac_method.dma.wme[WME_AC_BK]);
6533 }
6534 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
6535 return (NULL);
6536}
6537
6538static int
6539bwn_dma_getslot(struct bwn_dma_ring *dr)
6540{
6541 int slot;
6542
6543 BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
6544
6545 KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
6546 KASSERT(!(dr->dr_stop), ("%s:%d: fail", __func__, __LINE__));
6547 KASSERT(bwn_dma_freeslot(dr) != 0, ("%s:%d: fail", __func__, __LINE__));
6548
6549 slot = bwn_dma_nextslot(dr, dr->dr_curslot);
6550 KASSERT(!(slot & ~0x0fff), ("%s:%d: fail", __func__, __LINE__));
6551 dr->dr_curslot = slot;
6552 dr->dr_usedslot++;
6553
6554 return (slot);
6555}
6556
6557static struct bwn_pio_txqueue *
6558bwn_pio_parse_cookie(struct bwn_mac *mac, uint16_t cookie,
6559 struct bwn_pio_txpkt **pack)
6560{
6561 struct bwn_pio *pio = &mac->mac_method.pio;
6562 struct bwn_pio_txqueue *tq = NULL;
6563 unsigned int index;
6564
6565 switch (cookie & 0xf000) {
6566 case 0x1000:
6567 tq = &pio->wme[WME_AC_BK];
6568 break;
6569 case 0x2000:
6570 tq = &pio->wme[WME_AC_BE];
6571 break;
6572 case 0x3000:
6573 tq = &pio->wme[WME_AC_VI];
6574 break;
6575 case 0x4000:
6576 tq = &pio->wme[WME_AC_VO];
6577 break;
6578 case 0x5000:
6579 tq = &pio->mcast;
6580 break;
6581 }
6582 KASSERT(tq != NULL, ("%s:%d: fail", __func__, __LINE__));
6583 if (tq == NULL)
6584 return (NULL);
6585 index = (cookie & 0x0fff);
6586 KASSERT(index < N(tq->tq_pkts), ("%s:%d: fail", __func__, __LINE__));
6587 if (index >= N(tq->tq_pkts))
6588 return (NULL);
6589 *pack = &tq->tq_pkts[index];
6590 KASSERT(*pack != NULL, ("%s:%d: fail", __func__, __LINE__));
6591 return (tq);
6592}
6593
6594static void
6595bwn_txpwr(void *arg, int npending)
6596{
6597 struct bwn_mac *mac = arg;
6598 struct bwn_softc *sc = mac->mac_sc;
6599
6600 BWN_LOCK(sc);
6601 if (mac && mac->mac_status >= BWN_MAC_STATUS_STARTED &&
6602 mac->mac_phy.set_txpwr != NULL)
6603 mac->mac_phy.set_txpwr(mac);
6604 BWN_UNLOCK(sc);
6605}
6606
6607static void
6608bwn_task_15s(struct bwn_mac *mac)
6609{
6610 uint16_t reg;
6611
6612 if (mac->mac_fw.opensource) {
6613 reg = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG);
6614 if (reg) {
6615 bwn_restart(mac, "fw watchdog");
6616 return;
6617 }
6618 bwn_shm_write_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG, 1);
6619 }
6620 if (mac->mac_phy.task_15s)
6621 mac->mac_phy.task_15s(mac);
6622
6623 mac->mac_phy.txerrors = BWN_TXERROR_MAX;
6624}
6625
6626static void
6627bwn_task_30s(struct bwn_mac *mac)
6628{
6629
6630 if (mac->mac_phy.type != BWN_PHYTYPE_G || mac->mac_noise.noi_running)
6631 return;
6632 mac->mac_noise.noi_running = 1;
6633 mac->mac_noise.noi_nsamples = 0;
6634
6635 bwn_noise_gensample(mac);
6636}
6637
6638static void
6639bwn_task_60s(struct bwn_mac *mac)
6640{
6641
6642 if (mac->mac_phy.task_60s)
6643 mac->mac_phy.task_60s(mac);
6644 bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME);
6645}
6646
6647static void
6648bwn_tasks(void *arg)
6649{
6650 struct bwn_mac *mac = arg;
6651 struct bwn_softc *sc = mac->mac_sc;
6652
6653 BWN_ASSERT_LOCKED(sc);
6654 if (mac->mac_status != BWN_MAC_STATUS_STARTED)
6655 return;
6656
6657 if (mac->mac_task_state % 4 == 0)
6658 bwn_task_60s(mac);
6659 if (mac->mac_task_state % 2 == 0)
6660 bwn_task_30s(mac);
6661 bwn_task_15s(mac);
6662
6663 mac->mac_task_state++;
6664 callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
6665}
6666
6667static int
6668bwn_plcp_get_ofdmrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp, uint8_t a)
6669{
6670 struct bwn_softc *sc = mac->mac_sc;
6671
6672 KASSERT(a == 0, ("not support APHY\n"));
6673
6674 switch (plcp->o.raw[0] & 0xf) {
6675 case 0xb:
6676 return (BWN_OFDM_RATE_6MB);
6677 case 0xf:
6678 return (BWN_OFDM_RATE_9MB);
6679 case 0xa:
6680 return (BWN_OFDM_RATE_12MB);
6681 case 0xe:
6682 return (BWN_OFDM_RATE_18MB);
6683 case 0x9:
6684 return (BWN_OFDM_RATE_24MB);
6685 case 0xd:
6686 return (BWN_OFDM_RATE_36MB);
6687 case 0x8:
6688 return (BWN_OFDM_RATE_48MB);
6689 case 0xc:
6690 return (BWN_OFDM_RATE_54MB);
6691 }
6692 device_printf(sc->sc_dev, "incorrect OFDM rate %d\n",
6693 plcp->o.raw[0] & 0xf);
6694 return (-1);
6695}
6696
6697static int
6698bwn_plcp_get_cckrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp)
6699{
6700 struct bwn_softc *sc = mac->mac_sc;
6701
6702 switch (plcp->o.raw[0]) {
6703 case 0x0a:
6704 return (BWN_CCK_RATE_1MB);
6705 case 0x14:
6706 return (BWN_CCK_RATE_2MB);
6707 case 0x37:
6708 return (BWN_CCK_RATE_5MB);
6709 case 0x6e:
6710 return (BWN_CCK_RATE_11MB);
6711 }
6712 device_printf(sc->sc_dev, "incorrect CCK rate %d\n", plcp->o.raw[0]);
6713 return (-1);
6714}
6715
6716static void
6717bwn_rx_radiotap(struct bwn_mac *mac, struct mbuf *m,
6718 const struct bwn_rxhdr4 *rxhdr, struct bwn_plcp6 *plcp, int rate,
6719 int rssi, int noise)
6720{
6721 struct bwn_softc *sc = mac->mac_sc;
6722 const struct ieee80211_frame_min *wh;
6723 uint64_t tsf;
6724 uint16_t low_mactime_now;
6725
6726 if (htole16(rxhdr->phy_status0) & BWN_RX_PHYST0_SHORTPRMBL)
6727 sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
6728
6729 wh = mtod(m, const struct ieee80211_frame_min *);
6730 if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED)
6731 sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_WEP;
6732
6733 bwn_tsf_read(mac, &tsf);
6734 low_mactime_now = tsf;
6735 tsf = tsf & ~0xffffULL;
6736 tsf += le16toh(rxhdr->mac_time);
6737 if (low_mactime_now < le16toh(rxhdr->mac_time))
6738 tsf -= 0x10000;
6739
6740 sc->sc_rx_th.wr_tsf = tsf;
6741 sc->sc_rx_th.wr_rate = rate;
6742 sc->sc_rx_th.wr_antsignal = rssi;
6743 sc->sc_rx_th.wr_antnoise = noise;
6744}
6745
6746static void
6747bwn_tsf_read(struct bwn_mac *mac, uint64_t *tsf)
6748{
6749 uint32_t low, high;
6750
6751 KASSERT(siba_get_revid(mac->mac_sc->sc_dev) >= 3,
6752 ("%s:%d: fail", __func__, __LINE__));
6753
6754 low = BWN_READ_4(mac, BWN_REV3PLUS_TSF_LOW);
6755 high = BWN_READ_4(mac, BWN_REV3PLUS_TSF_HIGH);
6756 *tsf = high;
6757 *tsf <<= 32;
6758 *tsf |= low;
6759}
6760
6761static int
6762bwn_dma_attach(struct bwn_mac *mac)
6763{
6764 struct bwn_dma *dma = &mac->mac_method.dma;
6765 struct bwn_softc *sc = mac->mac_sc;
6766 bus_addr_t lowaddr = 0;
6767 int error;
6768
6769 if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
6770 return (0);
6771
6772 KASSERT(siba_get_revid(sc->sc_dev) >= 5, ("%s: fail", __func__));
6773
6774 mac->mac_flags |= BWN_MAC_FLAG_DMA;
6775
6776 dma->dmatype = bwn_dma_gettype(mac);
6777 if (dma->dmatype == BWN_DMA_30BIT)
6778 lowaddr = BWN_BUS_SPACE_MAXADDR_30BIT;
6779 else if (dma->dmatype == BWN_DMA_32BIT)
6780 lowaddr = BUS_SPACE_MAXADDR_32BIT;
6781 else
6782 lowaddr = BUS_SPACE_MAXADDR;
6783
6784 /*
6785 * Create top level DMA tag
6786 */
6787 error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), /* parent */
6788 BWN_ALIGN, 0, /* alignment, bounds */
6789 lowaddr, /* lowaddr */
6790 BUS_SPACE_MAXADDR, /* highaddr */
6791 NULL, NULL, /* filter, filterarg */
6792 BUS_SPACE_MAXSIZE, /* maxsize */
6793 BUS_SPACE_UNRESTRICTED, /* nsegments */
6794 BUS_SPACE_MAXSIZE, /* maxsegsize */
6795 0, /* flags */
6796 NULL, NULL, /* lockfunc, lockarg */
6797 &dma->parent_dtag);
6798 if (error) {
6799 device_printf(sc->sc_dev, "can't create parent DMA tag\n");
6800 return (error);
6801 }
6802
6803 /*
6804 * Create TX/RX mbuf DMA tag
6805 */
6806 error = bus_dma_tag_create(dma->parent_dtag,
6807 1,
6808 0,
6809 BUS_SPACE_MAXADDR,
6810 BUS_SPACE_MAXADDR,
6811 NULL, NULL,
6812 MCLBYTES,
6813 1,
6814 BUS_SPACE_MAXSIZE_32BIT,
6815 0,
6816 NULL, NULL,
6817 &dma->rxbuf_dtag);
6818 if (error) {
6819 device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
6820 goto fail0;
6821 }
6822 error = bus_dma_tag_create(dma->parent_dtag,
6823 1,
6824 0,
6825 BUS_SPACE_MAXADDR,
6826 BUS_SPACE_MAXADDR,
6827 NULL, NULL,
6828 MCLBYTES,
6829 1,
6830 BUS_SPACE_MAXSIZE_32BIT,
6831 0,
6832 NULL, NULL,
6833 &dma->txbuf_dtag);
6834 if (error) {
6835 device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
6836 goto fail1;
6837 }
6838
6839 dma->wme[WME_AC_BK] = bwn_dma_ringsetup(mac, 0, 1, dma->dmatype);
6840 if (!dma->wme[WME_AC_BK])
6841 goto fail2;
6842
6843 dma->wme[WME_AC_BE] = bwn_dma_ringsetup(mac, 1, 1, dma->dmatype);
6844 if (!dma->wme[WME_AC_BE])
6845 goto fail3;
6846
6847 dma->wme[WME_AC_VI] = bwn_dma_ringsetup(mac, 2, 1, dma->dmatype);
6848 if (!dma->wme[WME_AC_VI])
6849 goto fail4;
6850
6851 dma->wme[WME_AC_VO] = bwn_dma_ringsetup(mac, 3, 1, dma->dmatype);
6852 if (!dma->wme[WME_AC_VO])
6853 goto fail5;
6854
6855 dma->mcast = bwn_dma_ringsetup(mac, 4, 1, dma->dmatype);
6856 if (!dma->mcast)
6857 goto fail6;
6858 dma->rx = bwn_dma_ringsetup(mac, 0, 0, dma->dmatype);
6859 if (!dma->rx)
6860 goto fail7;
6861
6862 return (error);
6863
6864fail7: bwn_dma_ringfree(&dma->mcast);
6865fail6: bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
6866fail5: bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
6867fail4: bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
6868fail3: bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
6869fail2: bus_dma_tag_destroy(dma->txbuf_dtag);
6870fail1: bus_dma_tag_destroy(dma->rxbuf_dtag);
6871fail0: bus_dma_tag_destroy(dma->parent_dtag);
6872 return (error);
6873}
6874
6875static struct bwn_dma_ring *
6876bwn_dma_parse_cookie(struct bwn_mac *mac, const struct bwn_txstatus *status,
6877 uint16_t cookie, int *slot)
6878{
6879 struct bwn_dma *dma = &mac->mac_method.dma;
6880 struct bwn_dma_ring *dr;
6881 struct bwn_softc *sc = mac->mac_sc;
6882
6883 BWN_ASSERT_LOCKED(mac->mac_sc);
6884
6885 switch (cookie & 0xf000) {
6886 case 0x1000:
6887 dr = dma->wme[WME_AC_BK];
6888 break;
6889 case 0x2000:
6890 dr = dma->wme[WME_AC_BE];
6891 break;
6892 case 0x3000:
6893 dr = dma->wme[WME_AC_VI];
6894 break;
6895 case 0x4000:
6896 dr = dma->wme[WME_AC_VO];
6897 break;
6898 case 0x5000:
6899 dr = dma->mcast;
6900 break;
6901 default:
6902 dr = NULL;
6903 KASSERT(0 == 1,
6904 ("invalid cookie value %d", cookie & 0xf000));
6905 }
6906 *slot = (cookie & 0x0fff);
6907 if (*slot < 0 || *slot >= dr->dr_numslots) {
6908 /*
6909 * XXX FIXME: sometimes H/W returns TX DONE events duplicately
6910 * that it occurs events which have same H/W sequence numbers.
6911 * When it's occurred just prints a WARNING msgs and ignores.
6912 */
6913 KASSERT(status->seq == dma->lastseq,
6914 ("%s:%d: fail", __func__, __LINE__));
6915 device_printf(sc->sc_dev,
6916 "out of slot ranges (0 < %d < %d)\n", *slot,
6917 dr->dr_numslots);
6918 return (NULL);
6919 }
6920 dma->lastseq = status->seq;
6921 return (dr);
6922}
6923
6924static void
6925bwn_dma_stop(struct bwn_mac *mac)
6926{
6927 struct bwn_dma *dma;
6928
6929 if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
6930 return;
6931 dma = &mac->mac_method.dma;
6932
6933 bwn_dma_ringstop(&dma->rx);
6934 bwn_dma_ringstop(&dma->wme[WME_AC_BK]);
6935 bwn_dma_ringstop(&dma->wme[WME_AC_BE]);
6936 bwn_dma_ringstop(&dma->wme[WME_AC_VI]);
6937 bwn_dma_ringstop(&dma->wme[WME_AC_VO]);
6938 bwn_dma_ringstop(&dma->mcast);
6939}
6940
6941static void
6942bwn_dma_ringstop(struct bwn_dma_ring **dr)
6943{
6944
6945 if (dr == NULL)
6946 return;
6947
6948 bwn_dma_cleanup(*dr);
6949}
6950
6951static void
6952bwn_pio_stop(struct bwn_mac *mac)
6953{
6954 struct bwn_pio *pio;
6955
6956 if (mac->mac_flags & BWN_MAC_FLAG_DMA)
6957 return;
6958 pio = &mac->mac_method.pio;
6959
6960 bwn_destroy_queue_tx(&pio->mcast);
6961 bwn_destroy_queue_tx(&pio->wme[WME_AC_VO]);
6962 bwn_destroy_queue_tx(&pio->wme[WME_AC_VI]);
6963 bwn_destroy_queue_tx(&pio->wme[WME_AC_BE]);
6964 bwn_destroy_queue_tx(&pio->wme[WME_AC_BK]);
6965}
6966
6967static void
6968bwn_led_attach(struct bwn_mac *mac)
6969{
6970 struct bwn_softc *sc = mac->mac_sc;
6971 const uint8_t *led_act = NULL;
6972 uint16_t val[BWN_LED_MAX];
6973 int i;
6974
6975 sc->sc_led_idle = (2350 * hz) / 1000;
6976 sc->sc_led_blink = 1;
6977
6978 for (i = 0; i < N(bwn_vendor_led_act); ++i) {
6979 if (siba_get_pci_subvendor(sc->sc_dev) ==
6980 bwn_vendor_led_act[i].vid) {
6981 led_act = bwn_vendor_led_act[i].led_act;
6982 break;
6983 }
6984 }
6985 if (led_act == NULL)
6986 led_act = bwn_default_led_act;
6987
6988 val[0] = siba_sprom_get_gpio0(sc->sc_dev);
6989 val[1] = siba_sprom_get_gpio1(sc->sc_dev);
6990 val[2] = siba_sprom_get_gpio2(sc->sc_dev);
6991 val[3] = siba_sprom_get_gpio3(sc->sc_dev);
6992
6993 for (i = 0; i < BWN_LED_MAX; ++i) {
6994 struct bwn_led *led = &sc->sc_leds[i];
6995
6996 if (val[i] == 0xff) {
6997 led->led_act = led_act[i];
6998 } else {
6999 if (val[i] & BWN_LED_ACT_LOW)
7000 led->led_flags |= BWN_LED_F_ACTLOW;
7001 led->led_act = val[i] & BWN_LED_ACT_MASK;
7002 }
7003 led->led_mask = (1 << i);
7004
7005 if (led->led_act == BWN_LED_ACT_BLINK_SLOW ||
7006 led->led_act == BWN_LED_ACT_BLINK_POLL ||
7007 led->led_act == BWN_LED_ACT_BLINK) {
7008 led->led_flags |= BWN_LED_F_BLINK;
7009 if (led->led_act == BWN_LED_ACT_BLINK_POLL)
7010 led->led_flags |= BWN_LED_F_POLLABLE;
7011 else if (led->led_act == BWN_LED_ACT_BLINK_SLOW)
7012 led->led_flags |= BWN_LED_F_SLOW;
7013
7014 if (sc->sc_blink_led == NULL) {
7015 sc->sc_blink_led = led;
7016 if (led->led_flags & BWN_LED_F_SLOW)
7017 BWN_LED_SLOWDOWN(sc->sc_led_idle);
7018 }
7019 }
7020
7021 DPRINTF(sc, BWN_DEBUG_LED,
7022 "%dth led, act %d, lowact %d\n", i,
7023 led->led_act, led->led_flags & BWN_LED_F_ACTLOW);
7024 }
7025 callout_init_mtx(&sc->sc_led_blink_ch, &sc->sc_mtx, 0);
7026}
7027
7028static __inline uint16_t
7029bwn_led_onoff(const struct bwn_led *led, uint16_t val, int on)
7030{
7031
7032 if (led->led_flags & BWN_LED_F_ACTLOW)
7033 on = !on;
7034 if (on)
7035 val |= led->led_mask;
7036 else
7037 val &= ~led->led_mask;
7038 return val;
7039}
7040
7041static void
7042bwn_led_newstate(struct bwn_mac *mac, enum ieee80211_state nstate)
7043{
7044 struct bwn_softc *sc = mac->mac_sc;
7045 struct ieee80211com *ic = &sc->sc_ic;
7046 uint16_t val;
7047 int i;
7048
7049 if (nstate == IEEE80211_S_INIT) {
7050 callout_stop(&sc->sc_led_blink_ch);
7051 sc->sc_led_blinking = 0;
7052 }
7053
7054 if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0)
7055 return;
7056
7057 val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
7058 for (i = 0; i < BWN_LED_MAX; ++i) {
7059 struct bwn_led *led = &sc->sc_leds[i];
7060 int on;
7061
7062 if (led->led_act == BWN_LED_ACT_UNKN ||
7063 led->led_act == BWN_LED_ACT_NULL)
7064 continue;
7065
7066 if ((led->led_flags & BWN_LED_F_BLINK) &&
7067 nstate != IEEE80211_S_INIT)
7068 continue;
7069
7070 switch (led->led_act) {
7071 case BWN_LED_ACT_ON: /* Always on */
7072 on = 1;
7073 break;
7074 case BWN_LED_ACT_OFF: /* Always off */
7075 case BWN_LED_ACT_5GHZ: /* TODO: 11A */
7076 on = 0;
7077 break;
7078 default:
7079 on = 1;
7080 switch (nstate) {
7081 case IEEE80211_S_INIT:
7082 on = 0;
7083 break;
7084 case IEEE80211_S_RUN:
7085 if (led->led_act == BWN_LED_ACT_11G &&
7086 ic->ic_curmode != IEEE80211_MODE_11G)
7087 on = 0;
7088 break;
7089 default:
7090 if (led->led_act == BWN_LED_ACT_ASSOC)
7091 on = 0;
7092 break;
7093 }
7094 break;
7095 }
7096
7097 val = bwn_led_onoff(led, val, on);
7098 }
7099 BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
7100}
7101
7102static void
7103bwn_led_event(struct bwn_mac *mac, int event)
7104{
7105 struct bwn_softc *sc = mac->mac_sc;
7106 struct bwn_led *led = sc->sc_blink_led;
7107 int rate;
7108
7109 if (event == BWN_LED_EVENT_POLL) {
7110 if ((led->led_flags & BWN_LED_F_POLLABLE) == 0)
7111 return;
7112 if (ticks - sc->sc_led_ticks < sc->sc_led_idle)
7113 return;
7114 }
7115
7116 sc->sc_led_ticks = ticks;
7117 if (sc->sc_led_blinking)
7118 return;
7119
7120 switch (event) {
7121 case BWN_LED_EVENT_RX:
7122 rate = sc->sc_rx_rate;
7123 break;
7124 case BWN_LED_EVENT_TX:
7125 rate = sc->sc_tx_rate;
7126 break;
7127 case BWN_LED_EVENT_POLL:
7128 rate = 0;
7129 break;
7130 default:
7131 panic("unknown LED event %d\n", event);
7132 break;
7133 }
7134 bwn_led_blink_start(mac, bwn_led_duration[rate].on_dur,
7135 bwn_led_duration[rate].off_dur);
7136}
7137
7138static void
7139bwn_led_blink_start(struct bwn_mac *mac, int on_dur, int off_dur)
7140{
7141 struct bwn_softc *sc = mac->mac_sc;
7142 struct bwn_led *led = sc->sc_blink_led;
7143 uint16_t val;
7144
7145 val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
7146 val = bwn_led_onoff(led, val, 1);
7147 BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
7148
7149 if (led->led_flags & BWN_LED_F_SLOW) {
7150 BWN_LED_SLOWDOWN(on_dur);
7151 BWN_LED_SLOWDOWN(off_dur);
7152 }
7153
7154 sc->sc_led_blinking = 1;
7155 sc->sc_led_blink_offdur = off_dur;
7156
7157 callout_reset(&sc->sc_led_blink_ch, on_dur, bwn_led_blink_next, mac);
7158}
7159
7160static void
7161bwn_led_blink_next(void *arg)
7162{
7163 struct bwn_mac *mac = arg;
7164 struct bwn_softc *sc = mac->mac_sc;
7165 uint16_t val;
7166
7167 val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
7168 val = bwn_led_onoff(sc->sc_blink_led, val, 0);
7169 BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
7170
7171 callout_reset(&sc->sc_led_blink_ch, sc->sc_led_blink_offdur,
7172 bwn_led_blink_end, mac);
7173}
7174
7175static void
7176bwn_led_blink_end(void *arg)
7177{
7178 struct bwn_mac *mac = arg;
7179 struct bwn_softc *sc = mac->mac_sc;
7180
7181 sc->sc_led_blinking = 0;
7182}
7183
7184static int
7185bwn_suspend(device_t dev)
7186{
7187 struct bwn_softc *sc = device_get_softc(dev);
7188
7189 BWN_LOCK(sc);
7190 bwn_stop(sc);
7191 BWN_UNLOCK(sc);
7192 return (0);
7193}
7194
7195static int
7196bwn_resume(device_t dev)
7197{
7198 struct bwn_softc *sc = device_get_softc(dev);
7199 int error = EDOOFUS;
7200
7201 BWN_LOCK(sc);
7202 if (sc->sc_ic.ic_nrunning > 0)
7203 error = bwn_init(sc);
7204 BWN_UNLOCK(sc);
7205 if (error == 0)
7206 ieee80211_start_all(&sc->sc_ic);
7207 return (0);
7208}
7209
7210static void
7211bwn_rfswitch(void *arg)
7212{
7213 struct bwn_softc *sc = arg;
7214 struct bwn_mac *mac = sc->sc_curmac;
7215 int cur = 0, prev = 0;
7216
7217 KASSERT(mac->mac_status >= BWN_MAC_STATUS_STARTED,
7218 ("%s: invalid MAC status %d", __func__, mac->mac_status));
7219
7220 if (mac->mac_phy.rev >= 3 || mac->mac_phy.type == BWN_PHYTYPE_LP
7221 || mac->mac_phy.type == BWN_PHYTYPE_N) {
7222 if (!(BWN_READ_4(mac, BWN_RF_HWENABLED_HI)
7223 & BWN_RF_HWENABLED_HI_MASK))
7224 cur = 1;
7225 } else {
7226 if (BWN_READ_2(mac, BWN_RF_HWENABLED_LO)
7227 & BWN_RF_HWENABLED_LO_MASK)
7228 cur = 1;
7229 }
7230
7231 if (mac->mac_flags & BWN_MAC_FLAG_RADIO_ON)
7232 prev = 1;
7233
7234 DPRINTF(sc, BWN_DEBUG_RESET, "%s: called; cur=%d, prev=%d\n",
7235 __func__, cur, prev);
7236
7237 if (cur != prev) {
7238 if (cur)
7239 mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
7240 else
7241 mac->mac_flags &= ~BWN_MAC_FLAG_RADIO_ON;
7242
7243 device_printf(sc->sc_dev,
7244 "status of RF switch is changed to %s\n",
7245 cur ? "ON" : "OFF");
7246 if (cur != mac->mac_phy.rf_on) {
7247 if (cur)
7248 bwn_rf_turnon(mac);
7249 else
7250 bwn_rf_turnoff(mac);
7251 }
7252 }
7253
7254 callout_schedule(&sc->sc_rfswitch_ch, hz);
7255}
7256
7257static void
7258bwn_sysctl_node(struct bwn_softc *sc)
7259{
7260 device_t dev = sc->sc_dev;
7261 struct bwn_mac *mac;
7262 struct bwn_stats *stats;
7263
7264 /* XXX assume that count of MAC is only 1. */
7265
7266 if ((mac = sc->sc_curmac) == NULL)
7267 return;
7268 stats = &mac->mac_stats;
7269
7270 SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
7271 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
7272 "linknoise", CTLFLAG_RW, &stats->rts, 0, "Noise level");
7273 SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
7274 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
7275 "rts", CTLFLAG_RW, &stats->rts, 0, "RTS");
7276 SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
7277 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
7278 "rtsfail", CTLFLAG_RW, &stats->rtsfail, 0, "RTS failed to send");
7279
7280#ifdef BWN_DEBUG
7281 SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
7282 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
7283 "debug", CTLFLAG_RW, &sc->sc_debug, 0, "Debug flags");
7284#endif
7285}
7286
7287static device_method_t bwn_methods[] = {
7288 /* Device interface */
7289 DEVMETHOD(device_probe, bwn_probe),
7290 DEVMETHOD(device_attach, bwn_attach),
7291 DEVMETHOD(device_detach, bwn_detach),
7292 DEVMETHOD(device_suspend, bwn_suspend),
7293 DEVMETHOD(device_resume, bwn_resume),
7294 DEVMETHOD_END
7295};
7296static driver_t bwn_driver = {
7297 "bwn",
7298 bwn_methods,
7299 sizeof(struct bwn_softc)
7300};
7301static devclass_t bwn_devclass;
7302DRIVER_MODULE(bwn, siba_bwn, bwn_driver, bwn_devclass, 0, 0);
7303MODULE_DEPEND(bwn, siba_bwn, 1, 1, 1);
7304MODULE_DEPEND(bwn, wlan, 1, 1, 1); /* 802.11 media layer */
7305MODULE_DEPEND(bwn, firmware, 1, 1, 1); /* firmware support */
7306MODULE_DEPEND(bwn, wlan_amrr, 1, 1, 1);
7307MODULE_VERSION(bwn, 1);