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