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