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