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