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