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