kernel: Use NULL for pointers in DRIVER_MODULE().
[dragonfly.git] / sys / dev / netif / bwn / 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  * $FreeBSD: head/sys/dev/bwn/if_bwn.c 299801 2016-05-14 23:50:44Z adrian $
30  */
31
32 /*
33  * The Broadcom Wireless LAN controller driver.
34  */
35
36 #include <opt_wlan.h>
37 #include <opt_bwn.h>
38
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/kernel.h>
42 #include <sys/malloc.h>
43 #include <sys/module.h>
44 #include <sys/endian.h>
45 #include <sys/errno.h>
46 #include <sys/firmware.h>
47 #include <sys/lock.h>
48 #include <sys/mutex.h>
49 #if !defined(__DragonFly__)
50 #include <machine/bus.h>
51 #include <machine/resource.h>
52 #endif
53 #include <sys/bus.h>
54 #include <sys/rman.h>
55 #include <sys/socket.h>
56 #include <sys/sockio.h>
57
58 #include <net/ethernet.h>
59 #include <net/if.h>
60 #include <net/if_var.h>
61 #include <net/if_arp.h>
62 #include <net/if_dl.h>
63 #include <net/if_llc.h>
64 #include <net/if_media.h>
65 #include <net/if_types.h>
66
67 #if defined(__DragonFly__)
68 #include <bus/pci/pcivar.h>
69 #include <bus/pci/pcireg.h>
70 #include <dev/netif/bwn/siba/siba_ids.h>
71 #include <dev/netif/bwn/siba/sibareg.h>
72 #include <dev/netif/bwn/siba/sibavar.h>
73 #else
74 #include <dev/pci/pcivar.h>
75 #include <dev/pci/pcireg.h>
76 #include <dev/siba/siba_ids.h>
77 #include <dev/siba/sibareg.h>
78 #include <dev/siba/sibavar.h>
79 #endif
80
81 #if defined(__DragonFly__)
82 #include <netproto/802_11/ieee80211_var.h>
83 #include <netproto/802_11/ieee80211_radiotap.h>
84 #include <netproto/802_11/ieee80211_regdomain.h>
85 #include <netproto/802_11/ieee80211_phy.h>
86 #include <netproto/802_11/ieee80211_ratectl.h>
87 #else
88 #include <net80211/ieee80211_var.h>
89 #include <net80211/ieee80211_radiotap.h>
90 #include <net80211/ieee80211_regdomain.h>
91 #include <net80211/ieee80211_phy.h>
92 #include <net80211/ieee80211_ratectl.h>
93 #endif
94
95 #if defined(__DragonFly__)
96 #include "if_bwnreg.h"
97 #include "if_bwnvar.h"
98 #else
99 #include <dev/bwn/if_bwnreg.h>
100 #include <dev/bwn/if_bwnvar.h>
101 #endif
102
103 #if defined(__DragonFly__)
104 #include "if_bwn_debug.h"
105 #include "if_bwn_misc.h"
106 #include "if_bwn_util.h"
107 #include "if_bwn_phy_common.h"
108 #include "if_bwn_phy_g.h"
109 #include "if_bwn_phy_lp.h"
110 #else
111 #include <dev/bwn/if_bwn_debug.h>
112 #include <dev/bwn/if_bwn_misc.h>
113 #include <dev/bwn/if_bwn_util.h>
114 #include <dev/bwn/if_bwn_phy_common.h>
115 #include <dev/bwn/if_bwn_phy_g.h>
116 #include <dev/bwn/if_bwn_phy_lp.h>
117 #endif
118
119 static SYSCTL_NODE(_hw, OID_AUTO, bwn, CTLFLAG_RD, 0,
120     "Broadcom driver parameters");
121
122 /*
123  * Tunable & sysctl variables.
124  */
125
126 #ifdef BWN_DEBUG
127 static  int bwn_debug = 0;
128 SYSCTL_INT(_hw_bwn, OID_AUTO, debug, CTLFLAG_RW, &bwn_debug, 0,
129     "Broadcom debugging printfs");
130 #endif
131
132 static int      bwn_bfp = 0;            /* use "Bad Frames Preemption" */
133 SYSCTL_INT(_hw_bwn, OID_AUTO, bfp, CTLFLAG_RW, &bwn_bfp, 0,
134     "uses Bad Frames Preemption");
135 static int      bwn_bluetooth = 1;
136 SYSCTL_INT(_hw_bwn, OID_AUTO, bluetooth, CTLFLAG_RW, &bwn_bluetooth, 0,
137     "turns on Bluetooth Coexistence");
138 static int      bwn_hwpctl = 0;
139 SYSCTL_INT(_hw_bwn, OID_AUTO, hwpctl, CTLFLAG_RW, &bwn_hwpctl, 0,
140     "uses H/W power control");
141 #if defined(__DragonFly__)
142 static int      bwn_msi_enable = 1;
143 TUNABLE_INT("hw.bwn.msi.enable", &bwn_msi_enable);
144 #else
145 static int      bwn_msi_disable = 0;            /* MSI disabled  */
146 TUNABLE_INT("hw.bwn.msi_disable", &bwn_msi_disable);
147 #endif
148 static int      bwn_usedma = 1;
149 SYSCTL_INT(_hw_bwn, OID_AUTO, usedma, CTLFLAG_RD, &bwn_usedma, 0,
150     "uses DMA");
151 TUNABLE_INT("hw.bwn.usedma", &bwn_usedma);
152 static int      bwn_wme = 1;
153 SYSCTL_INT(_hw_bwn, OID_AUTO, wme, CTLFLAG_RW, &bwn_wme, 0,
154     "uses WME support");
155
156 static void     bwn_attach_pre(struct bwn_softc *);
157 static int      bwn_attach_post(struct bwn_softc *);
158 static void     bwn_sprom_bugfixes(device_t);
159 static int      bwn_init(struct bwn_softc *);
160 static void     bwn_parent(struct ieee80211com *);
161 static void     bwn_start(struct bwn_softc *);
162 static int      bwn_transmit(struct ieee80211com *, struct mbuf *);
163 static int      bwn_attach_core(struct bwn_mac *);
164 static int      bwn_phy_getinfo(struct bwn_mac *, int);
165 static int      bwn_chiptest(struct bwn_mac *);
166 static int      bwn_setup_channels(struct bwn_mac *, int, int);
167 static void     bwn_shm_ctlword(struct bwn_mac *, uint16_t,
168                     uint16_t);
169 static void     bwn_addchannels(struct ieee80211_channel [], int, int *,
170                     const struct bwn_channelinfo *, int);
171 static int      bwn_raw_xmit(struct ieee80211_node *, struct mbuf *,
172                     const struct ieee80211_bpf_params *);
173 static void     bwn_updateslot(struct ieee80211com *);
174 static void     bwn_update_promisc(struct ieee80211com *);
175 static void     bwn_wme_init(struct bwn_mac *);
176 static int      bwn_wme_update(struct ieee80211com *);
177 static void     bwn_wme_clear(struct bwn_softc *);
178 static void     bwn_wme_load(struct bwn_mac *);
179 static void     bwn_wme_loadparams(struct bwn_mac *,
180                     const struct wmeParams *, uint16_t);
181 static void     bwn_scan_start(struct ieee80211com *);
182 static void     bwn_scan_end(struct ieee80211com *);
183 static void     bwn_set_channel(struct ieee80211com *);
184 static struct ieee80211vap *bwn_vap_create(struct ieee80211com *,
185                     const char [IFNAMSIZ], int, enum ieee80211_opmode, int,
186                     const uint8_t [IEEE80211_ADDR_LEN],
187                     const uint8_t [IEEE80211_ADDR_LEN]);
188 static void     bwn_vap_delete(struct ieee80211vap *);
189 static void     bwn_stop(struct bwn_softc *);
190 static int      bwn_core_init(struct bwn_mac *);
191 static void     bwn_core_start(struct bwn_mac *);
192 static void     bwn_core_exit(struct bwn_mac *);
193 static void     bwn_bt_disable(struct bwn_mac *);
194 static int      bwn_chip_init(struct bwn_mac *);
195 static void     bwn_set_txretry(struct bwn_mac *, int, int);
196 static void     bwn_rate_init(struct bwn_mac *);
197 static void     bwn_set_phytxctl(struct bwn_mac *);
198 static void     bwn_spu_setdelay(struct bwn_mac *, int);
199 static void     bwn_bt_enable(struct bwn_mac *);
200 static void     bwn_set_macaddr(struct bwn_mac *);
201 static void     bwn_crypt_init(struct bwn_mac *);
202 static void     bwn_chip_exit(struct bwn_mac *);
203 static int      bwn_fw_fillinfo(struct bwn_mac *);
204 static int      bwn_fw_loaducode(struct bwn_mac *);
205 static int      bwn_gpio_init(struct bwn_mac *);
206 static int      bwn_fw_loadinitvals(struct bwn_mac *);
207 static int      bwn_phy_init(struct bwn_mac *);
208 static void     bwn_set_txantenna(struct bwn_mac *, int);
209 static void     bwn_set_opmode(struct bwn_mac *);
210 static void     bwn_rate_write(struct bwn_mac *, uint16_t, int);
211 static uint8_t  bwn_plcp_getcck(const uint8_t);
212 static uint8_t  bwn_plcp_getofdm(const uint8_t);
213 static void     bwn_pio_init(struct bwn_mac *);
214 static uint16_t bwn_pio_idx2base(struct bwn_mac *, int);
215 static void     bwn_pio_set_txqueue(struct bwn_mac *, struct bwn_pio_txqueue *,
216                     int);
217 static void     bwn_pio_setupqueue_rx(struct bwn_mac *,
218                     struct bwn_pio_rxqueue *, int);
219 static void     bwn_destroy_queue_tx(struct bwn_pio_txqueue *);
220 static uint16_t bwn_pio_read_2(struct bwn_mac *, struct bwn_pio_txqueue *,
221                     uint16_t);
222 static void     bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *);
223 static int      bwn_pio_rx(struct bwn_pio_rxqueue *);
224 static uint8_t  bwn_pio_rxeof(struct bwn_pio_rxqueue *);
225 static void     bwn_pio_handle_txeof(struct bwn_mac *,
226                     const struct bwn_txstatus *);
227 static uint16_t bwn_pio_rx_read_2(struct bwn_pio_rxqueue *, uint16_t);
228 static uint32_t bwn_pio_rx_read_4(struct bwn_pio_rxqueue *, uint16_t);
229 static void     bwn_pio_rx_write_2(struct bwn_pio_rxqueue *, uint16_t,
230                     uint16_t);
231 static void     bwn_pio_rx_write_4(struct bwn_pio_rxqueue *, uint16_t,
232                     uint32_t);
233 static int      bwn_pio_tx_start(struct bwn_mac *, struct ieee80211_node *,
234                     struct mbuf *);
235 static struct bwn_pio_txqueue *bwn_pio_select(struct bwn_mac *, uint8_t);
236 static uint32_t bwn_pio_write_multi_4(struct bwn_mac *,
237                     struct bwn_pio_txqueue *, uint32_t, const void *, int);
238 static void     bwn_pio_write_4(struct bwn_mac *, struct bwn_pio_txqueue *,
239                     uint16_t, uint32_t);
240 static uint16_t bwn_pio_write_multi_2(struct bwn_mac *,
241                     struct bwn_pio_txqueue *, uint16_t, const void *, int);
242 static uint16_t bwn_pio_write_mbuf_2(struct bwn_mac *,
243                     struct bwn_pio_txqueue *, uint16_t, struct mbuf *);
244 static struct bwn_pio_txqueue *bwn_pio_parse_cookie(struct bwn_mac *,
245                     uint16_t, struct bwn_pio_txpkt **);
246 static void     bwn_dma_init(struct bwn_mac *);
247 static void     bwn_dma_rxdirectfifo(struct bwn_mac *, int, uint8_t);
248 static int      bwn_dma_mask2type(uint64_t);
249 static uint64_t bwn_dma_mask(struct bwn_mac *);
250 static uint16_t bwn_dma_base(int, int);
251 static void     bwn_dma_ringfree(struct bwn_dma_ring **);
252 static void     bwn_dma_32_getdesc(struct bwn_dma_ring *,
253                     int, struct bwn_dmadesc_generic **,
254                     struct bwn_dmadesc_meta **);
255 static void     bwn_dma_32_setdesc(struct bwn_dma_ring *,
256                     struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int,
257                     int, int);
258 static void     bwn_dma_32_start_transfer(struct bwn_dma_ring *, int);
259 static void     bwn_dma_32_suspend(struct bwn_dma_ring *);
260 static void     bwn_dma_32_resume(struct bwn_dma_ring *);
261 static int      bwn_dma_32_get_curslot(struct bwn_dma_ring *);
262 static void     bwn_dma_32_set_curslot(struct bwn_dma_ring *, int);
263 static void     bwn_dma_64_getdesc(struct bwn_dma_ring *,
264                     int, struct bwn_dmadesc_generic **,
265                     struct bwn_dmadesc_meta **);
266 static void     bwn_dma_64_setdesc(struct bwn_dma_ring *,
267                     struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int,
268                     int, int);
269 static void     bwn_dma_64_start_transfer(struct bwn_dma_ring *, int);
270 static void     bwn_dma_64_suspend(struct bwn_dma_ring *);
271 static void     bwn_dma_64_resume(struct bwn_dma_ring *);
272 static int      bwn_dma_64_get_curslot(struct bwn_dma_ring *);
273 static void     bwn_dma_64_set_curslot(struct bwn_dma_ring *, int);
274 static int      bwn_dma_allocringmemory(struct bwn_dma_ring *);
275 static void     bwn_dma_setup(struct bwn_dma_ring *);
276 static void     bwn_dma_free_ringmemory(struct bwn_dma_ring *);
277 static void     bwn_dma_cleanup(struct bwn_dma_ring *);
278 static void     bwn_dma_free_descbufs(struct bwn_dma_ring *);
279 static int      bwn_dma_tx_reset(struct bwn_mac *, uint16_t, int);
280 static void     bwn_dma_rx_handle_overflow(struct bwn_dma_ring *);
281 static void     bwn_dma_rx(struct bwn_dma_ring *);
282 static int      bwn_dma_rx_reset(struct bwn_mac *, uint16_t, int);
283 static void     bwn_dma_free_descbuf(struct bwn_dma_ring *,
284                     struct bwn_dmadesc_meta *);
285 static void     bwn_dma_set_redzone(struct bwn_dma_ring *, struct mbuf *);
286 static int      bwn_dma_gettype(struct bwn_mac *);
287 static void     bwn_dma_ring_addr(void *, bus_dma_segment_t *, int, int);
288 static int      bwn_dma_freeslot(struct bwn_dma_ring *);
289 static int      bwn_dma_nextslot(struct bwn_dma_ring *, int);
290 static void     bwn_dma_rxeof(struct bwn_dma_ring *, int *);
291 static int      bwn_dma_newbuf(struct bwn_dma_ring *,
292                     struct bwn_dmadesc_generic *, struct bwn_dmadesc_meta *,
293                     int);
294 static void     bwn_dma_buf_addr(void *, bus_dma_segment_t *, int,
295                     bus_size_t, int);
296 static uint8_t  bwn_dma_check_redzone(struct bwn_dma_ring *, struct mbuf *);
297 static void     bwn_dma_handle_txeof(struct bwn_mac *,
298                     const struct bwn_txstatus *);
299 static int      bwn_dma_tx_start(struct bwn_mac *, struct ieee80211_node *,
300                     struct mbuf *);
301 static int      bwn_dma_getslot(struct bwn_dma_ring *);
302 static struct bwn_dma_ring *bwn_dma_select(struct bwn_mac *,
303                     uint8_t);
304 static int      bwn_dma_attach(struct bwn_mac *);
305 static struct bwn_dma_ring *bwn_dma_ringsetup(struct bwn_mac *,
306                     int, int, int);
307 static struct bwn_dma_ring *bwn_dma_parse_cookie(struct bwn_mac *,
308                     const struct bwn_txstatus *, uint16_t, int *);
309 static void     bwn_dma_free(struct bwn_mac *);
310 static int      bwn_fw_gets(struct bwn_mac *, enum bwn_fwtype);
311 static int      bwn_fw_get(struct bwn_mac *, enum bwn_fwtype,
312                     const char *, struct bwn_fwfile *);
313 static void     bwn_release_firmware(struct bwn_mac *);
314 static void     bwn_do_release_fw(struct bwn_fwfile *);
315 static uint16_t bwn_fwcaps_read(struct bwn_mac *);
316 static int      bwn_fwinitvals_write(struct bwn_mac *,
317                     const struct bwn_fwinitvals *, size_t, size_t);
318 static uint16_t bwn_ant2phy(int);
319 static void     bwn_mac_write_bssid(struct bwn_mac *);
320 static void     bwn_mac_setfilter(struct bwn_mac *, uint16_t,
321                     const uint8_t *);
322 static void     bwn_key_dowrite(struct bwn_mac *, uint8_t, uint8_t,
323                     const uint8_t *, size_t, const uint8_t *);
324 static void     bwn_key_macwrite(struct bwn_mac *, uint8_t,
325                     const uint8_t *);
326 static void     bwn_key_write(struct bwn_mac *, uint8_t, uint8_t,
327                     const uint8_t *);
328 static void     bwn_phy_exit(struct bwn_mac *);
329 static void     bwn_core_stop(struct bwn_mac *);
330 static int      bwn_switch_band(struct bwn_softc *,
331                     struct ieee80211_channel *);
332 static void     bwn_phy_reset(struct bwn_mac *);
333 static int      bwn_newstate(struct ieee80211vap *, enum ieee80211_state, int);
334 static void     bwn_set_pretbtt(struct bwn_mac *);
335 #if defined(__DragonFly__)
336 static void     bwn_intr(void *);
337 #else
338 static int      bwn_intr(void *);
339 #endif
340 static void     bwn_intrtask(void *, int);
341 static void     bwn_restart(struct bwn_mac *, const char *);
342 static void     bwn_intr_ucode_debug(struct bwn_mac *);
343 static void     bwn_intr_tbtt_indication(struct bwn_mac *);
344 static void     bwn_intr_atim_end(struct bwn_mac *);
345 static void     bwn_intr_beacon(struct bwn_mac *);
346 static void     bwn_intr_pmq(struct bwn_mac *);
347 static void     bwn_intr_noise(struct bwn_mac *);
348 static void     bwn_intr_txeof(struct bwn_mac *);
349 static void     bwn_hwreset(void *, int);
350 static void     bwn_handle_fwpanic(struct bwn_mac *);
351 static void     bwn_load_beacon0(struct bwn_mac *);
352 static void     bwn_load_beacon1(struct bwn_mac *);
353 static uint32_t bwn_jssi_read(struct bwn_mac *);
354 static void     bwn_noise_gensample(struct bwn_mac *);
355 static void     bwn_handle_txeof(struct bwn_mac *,
356                     const struct bwn_txstatus *);
357 static void     bwn_rxeof(struct bwn_mac *, struct mbuf *, const void *);
358 static void     bwn_phy_txpower_check(struct bwn_mac *, uint32_t);
359 static int      bwn_tx_start(struct bwn_softc *, struct ieee80211_node *,
360                     struct mbuf *);
361 static int      bwn_tx_isfull(struct bwn_softc *, struct mbuf *);
362 static int      bwn_set_txhdr(struct bwn_mac *,
363                     struct ieee80211_node *, struct mbuf *, struct bwn_txhdr *,
364                     uint16_t);
365 static void     bwn_plcp_genhdr(struct bwn_plcp4 *, const uint16_t,
366                     const uint8_t);
367 static uint8_t  bwn_antenna_sanitize(struct bwn_mac *, uint8_t);
368 static uint8_t  bwn_get_fbrate(uint8_t);
369 static void     bwn_txpwr(void *, int);
370 static void     bwn_tasks(void *);
371 static void     bwn_task_15s(struct bwn_mac *);
372 static void     bwn_task_30s(struct bwn_mac *);
373 static void     bwn_task_60s(struct bwn_mac *);
374 static int      bwn_plcp_get_ofdmrate(struct bwn_mac *, struct bwn_plcp6 *,
375                     uint8_t);
376 static int      bwn_plcp_get_cckrate(struct bwn_mac *, struct bwn_plcp6 *);
377 static void     bwn_rx_radiotap(struct bwn_mac *, struct mbuf *,
378                     const struct bwn_rxhdr4 *, struct bwn_plcp6 *, int,
379                     int, int);
380 static void     bwn_tsf_read(struct bwn_mac *, uint64_t *);
381 static void     bwn_set_slot_time(struct bwn_mac *, uint16_t);
382 static void     bwn_watchdog(void *);
383 static void     bwn_dma_stop(struct bwn_mac *);
384 static void     bwn_pio_stop(struct bwn_mac *);
385 static void     bwn_dma_ringstop(struct bwn_dma_ring **);
386 static void     bwn_led_attach(struct bwn_mac *);
387 static void     bwn_led_newstate(struct bwn_mac *, enum ieee80211_state);
388 static void     bwn_led_event(struct bwn_mac *, int);
389 static void     bwn_led_blink_start(struct bwn_mac *, int, int);
390 static void     bwn_led_blink_next(void *);
391 static void     bwn_led_blink_end(void *);
392 static void     bwn_rfswitch(void *);
393 static void     bwn_rf_turnon(struct bwn_mac *);
394 static void     bwn_rf_turnoff(struct bwn_mac *);
395 static void     bwn_sysctl_node(struct bwn_softc *);
396
397 #if !defined(__DragonFly__)
398 static struct resource_spec bwn_res_spec_legacy[] = {
399         { SYS_RES_IRQ,          0,              RF_ACTIVE | RF_SHAREABLE },
400         { -1,                   0,              0 }
401 };
402
403 static struct resource_spec bwn_res_spec_msi[] = {
404         { SYS_RES_IRQ,          1,              RF_ACTIVE },
405         { -1,                   0,              0 }
406 };
407 #endif
408
409 static const struct bwn_channelinfo bwn_chantable_bg = {
410         .channels = {
411                 { 2412,  1, 30 }, { 2417,  2, 30 }, { 2422,  3, 30 },
412                 { 2427,  4, 30 }, { 2432,  5, 30 }, { 2437,  6, 30 },
413                 { 2442,  7, 30 }, { 2447,  8, 30 }, { 2452,  9, 30 },
414                 { 2457, 10, 30 }, { 2462, 11, 30 }, { 2467, 12, 30 },
415                 { 2472, 13, 30 }, { 2484, 14, 30 } },
416         .nchannels = 14
417 };
418
419 static const struct bwn_channelinfo bwn_chantable_a = {
420         .channels = {
421                 { 5170,  34, 30 }, { 5180,  36, 30 }, { 5190,  38, 30 },
422                 { 5200,  40, 30 }, { 5210,  42, 30 }, { 5220,  44, 30 },
423                 { 5230,  46, 30 }, { 5240,  48, 30 }, { 5260,  52, 30 },
424                 { 5280,  56, 30 }, { 5300,  60, 30 }, { 5320,  64, 30 },
425                 { 5500, 100, 30 }, { 5520, 104, 30 }, { 5540, 108, 30 },
426                 { 5560, 112, 30 }, { 5580, 116, 30 }, { 5600, 120, 30 },
427                 { 5620, 124, 30 }, { 5640, 128, 30 }, { 5660, 132, 30 },
428                 { 5680, 136, 30 }, { 5700, 140, 30 }, { 5745, 149, 30 },
429                 { 5765, 153, 30 }, { 5785, 157, 30 }, { 5805, 161, 30 },
430                 { 5825, 165, 30 }, { 5920, 184, 30 }, { 5940, 188, 30 },
431                 { 5960, 192, 30 }, { 5980, 196, 30 }, { 6000, 200, 30 },
432                 { 6020, 204, 30 }, { 6040, 208, 30 }, { 6060, 212, 30 },
433                 { 6080, 216, 30 } },
434         .nchannels = 37
435 };
436
437 #if 0
438 static const struct bwn_channelinfo bwn_chantable_n = {
439         .channels = {
440                 { 5160,  32, 30 }, { 5170,  34, 30 }, { 5180,  36, 30 },
441                 { 5190,  38, 30 }, { 5200,  40, 30 }, { 5210,  42, 30 },
442                 { 5220,  44, 30 }, { 5230,  46, 30 }, { 5240,  48, 30 },
443                 { 5250,  50, 30 }, { 5260,  52, 30 }, { 5270,  54, 30 },
444                 { 5280,  56, 30 }, { 5290,  58, 30 }, { 5300,  60, 30 },
445                 { 5310,  62, 30 }, { 5320,  64, 30 }, { 5330,  66, 30 },
446                 { 5340,  68, 30 }, { 5350,  70, 30 }, { 5360,  72, 30 },
447                 { 5370,  74, 30 }, { 5380,  76, 30 }, { 5390,  78, 30 },
448                 { 5400,  80, 30 }, { 5410,  82, 30 }, { 5420,  84, 30 },
449                 { 5430,  86, 30 }, { 5440,  88, 30 }, { 5450,  90, 30 },
450                 { 5460,  92, 30 }, { 5470,  94, 30 }, { 5480,  96, 30 },
451                 { 5490,  98, 30 }, { 5500, 100, 30 }, { 5510, 102, 30 },
452                 { 5520, 104, 30 }, { 5530, 106, 30 }, { 5540, 108, 30 },
453                 { 5550, 110, 30 }, { 5560, 112, 30 }, { 5570, 114, 30 },
454                 { 5580, 116, 30 }, { 5590, 118, 30 }, { 5600, 120, 30 },
455                 { 5610, 122, 30 }, { 5620, 124, 30 }, { 5630, 126, 30 },
456                 { 5640, 128, 30 }, { 5650, 130, 30 }, { 5660, 132, 30 },
457                 { 5670, 134, 30 }, { 5680, 136, 30 }, { 5690, 138, 30 },
458                 { 5700, 140, 30 }, { 5710, 142, 30 }, { 5720, 144, 30 },
459                 { 5725, 145, 30 }, { 5730, 146, 30 }, { 5735, 147, 30 },
460                 { 5740, 148, 30 }, { 5745, 149, 30 }, { 5750, 150, 30 },
461                 { 5755, 151, 30 }, { 5760, 152, 30 }, { 5765, 153, 30 },
462                 { 5770, 154, 30 }, { 5775, 155, 30 }, { 5780, 156, 30 },
463                 { 5785, 157, 30 }, { 5790, 158, 30 }, { 5795, 159, 30 },
464                 { 5800, 160, 30 }, { 5805, 161, 30 }, { 5810, 162, 30 },
465                 { 5815, 163, 30 }, { 5820, 164, 30 }, { 5825, 165, 30 },
466                 { 5830, 166, 30 }, { 5840, 168, 30 }, { 5850, 170, 30 },
467                 { 5860, 172, 30 }, { 5870, 174, 30 }, { 5880, 176, 30 },
468                 { 5890, 178, 30 }, { 5900, 180, 30 }, { 5910, 182, 30 },
469                 { 5920, 184, 30 }, { 5930, 186, 30 }, { 5940, 188, 30 },
470                 { 5950, 190, 30 }, { 5960, 192, 30 }, { 5970, 194, 30 },
471                 { 5980, 196, 30 }, { 5990, 198, 30 }, { 6000, 200, 30 },
472                 { 6010, 202, 30 }, { 6020, 204, 30 }, { 6030, 206, 30 },
473                 { 6040, 208, 30 }, { 6050, 210, 30 }, { 6060, 212, 30 },
474                 { 6070, 214, 30 }, { 6080, 216, 30 }, { 6090, 218, 30 },
475                 { 6100, 220, 30 }, { 6110, 222, 30 }, { 6120, 224, 30 },
476                 { 6130, 226, 30 }, { 6140, 228, 30 } },
477         .nchannels = 110
478 };
479 #endif
480
481 #define VENDOR_LED_ACT(vendor)                          \
482 {                                                       \
483         .vid = PCI_VENDOR_##vendor,                     \
484         .led_act = { BWN_VENDOR_LED_ACT_##vendor }      \
485 }
486
487 static const struct {
488         uint16_t        vid;
489         uint8_t         led_act[BWN_LED_MAX];
490 } bwn_vendor_led_act[] = {
491         VENDOR_LED_ACT(COMPAQ),
492         VENDOR_LED_ACT(ASUSTEK)
493 };
494
495 static const uint8_t bwn_default_led_act[BWN_LED_MAX] =
496         { BWN_VENDOR_LED_ACT_DEFAULT };
497
498 #undef VENDOR_LED_ACT
499
500 static const struct {
501         int             on_dur;
502         int             off_dur;
503 } bwn_led_duration[109] = {
504         [0]     = { 400, 100 },
505         [2]     = { 150, 75 },
506         [4]     = { 90, 45 },
507         [11]    = { 66, 34 },
508         [12]    = { 53, 26 },
509         [18]    = { 42, 21 },
510         [22]    = { 35, 17 },
511         [24]    = { 32, 16 },
512         [36]    = { 21, 10 },
513         [48]    = { 16, 8 },
514         [72]    = { 11, 5 },
515         [96]    = { 9, 4 },
516         [108]   = { 7, 3 }
517 };
518
519 static const uint16_t bwn_wme_shm_offsets[] = {
520         [0] = BWN_WME_BESTEFFORT,
521         [1] = BWN_WME_BACKGROUND,
522         [2] = BWN_WME_VOICE,
523         [3] = BWN_WME_VIDEO,
524 };
525
526 static const struct siba_devid bwn_devs[] = {
527         SIBA_DEV(BROADCOM, 80211, 5, "Revision 5"),
528         SIBA_DEV(BROADCOM, 80211, 6, "Revision 6"),
529         SIBA_DEV(BROADCOM, 80211, 7, "Revision 7"),
530         SIBA_DEV(BROADCOM, 80211, 9, "Revision 9"),
531         SIBA_DEV(BROADCOM, 80211, 10, "Revision 10"),
532         SIBA_DEV(BROADCOM, 80211, 11, "Revision 11"),
533         SIBA_DEV(BROADCOM, 80211, 12, "Revision 12"),
534         SIBA_DEV(BROADCOM, 80211, 13, "Revision 13"),
535         SIBA_DEV(BROADCOM, 80211, 15, "Revision 15"),
536         SIBA_DEV(BROADCOM, 80211, 16, "Revision 16")
537 };
538
539 static int
540 bwn_probe(device_t dev)
541 {
542         int i;
543
544         for (i = 0; i < N(bwn_devs); i++) {
545                 if (siba_get_vendor(dev) == bwn_devs[i].sd_vendor &&
546                     siba_get_device(dev) == bwn_devs[i].sd_device &&
547                     siba_get_revid(dev) == bwn_devs[i].sd_rev)
548                         return (BUS_PROBE_DEFAULT);
549         }
550
551         return (ENXIO);
552 }
553
554 static int
555 bwn_attach(device_t dev)
556 {
557         struct bwn_mac *mac;
558         struct bwn_softc *sc = device_get_softc(dev);
559 #if defined(__DragonFly__)
560         u_int irq_flags;
561         int error;
562 #else
563         int error, i, msic, reg;
564 #endif
565
566         sc->sc_dev = dev;
567 #ifdef BWN_DEBUG
568         sc->sc_debug = bwn_debug;
569 #endif
570
571         if ((sc->sc_flags & BWN_FLAG_ATTACHED) == 0) {
572                 bwn_attach_pre(sc);
573                 bwn_sprom_bugfixes(dev);
574                 sc->sc_flags |= BWN_FLAG_ATTACHED;
575         }
576
577         if (!TAILQ_EMPTY(&sc->sc_maclist)) {
578                 if (siba_get_pci_device(dev) != 0x4313 &&
579                     siba_get_pci_device(dev) != 0x431a &&
580                     siba_get_pci_device(dev) != 0x4321) {
581                         device_printf(sc->sc_dev,
582                             "skip 802.11 cores\n");
583                         return (ENODEV);
584                 }
585         }
586
587         mac = kmalloc(sizeof(*mac), M_DEVBUF, M_WAITOK | M_ZERO);
588         mac->mac_sc = sc;
589         mac->mac_status = BWN_MAC_STATUS_UNINIT;
590         if (bwn_bfp != 0)
591                 mac->mac_flags |= BWN_MAC_FLAG_BADFRAME_PREEMP;
592
593         TASK_INIT(&mac->mac_hwreset, 0, bwn_hwreset, mac);
594         TASK_INIT(&mac->mac_intrtask, 0, bwn_intrtask, mac);
595         TASK_INIT(&mac->mac_txpower, 0, bwn_txpwr, mac);
596
597         error = bwn_attach_core(mac);
598         if (error)
599                 goto fail0;
600         bwn_led_attach(mac);
601
602         device_printf(sc->sc_dev, "WLAN (chipid %#x rev %u) "
603             "PHY (analog %d type %d rev %d) RADIO (manuf %#x ver %#x rev %d)\n",
604             siba_get_chipid(sc->sc_dev), siba_get_revid(sc->sc_dev),
605             mac->mac_phy.analog, mac->mac_phy.type, mac->mac_phy.rev,
606             mac->mac_phy.rf_manuf, mac->mac_phy.rf_ver,
607             mac->mac_phy.rf_rev);
608         if (mac->mac_flags & BWN_MAC_FLAG_DMA)
609                 device_printf(sc->sc_dev, "DMA (%d bits)\n",
610                     mac->mac_method.dma.dmatype);
611         else
612                 device_printf(sc->sc_dev, "PIO\n");
613
614         /*
615          * setup PCI resources and interrupt.
616          */
617 #if defined(__DragonFly__)
618         /* Allocate IRQ resource. */
619         sc->bwn_irq_rid = 0;
620         sc->bwn_irq_type = pci_alloc_1intr(sc->sc_dev, bwn_msi_enable,
621             &sc->bwn_irq_rid, &irq_flags);
622         if ((sc->bwn_irq = bus_alloc_resource_any(sc->sc_dev, SYS_RES_IRQ,
623             &sc->bwn_irq_rid, irq_flags)) == NULL) {
624                 device_printf(sc->sc_dev, "Cannot allocate interrupt\n");
625                 error = EINVAL;
626                 goto fail1;
627         }
628         if ((error = bus_setup_intr(sc->sc_dev, sc->bwn_irq, INTR_MPSAFE,
629             bwn_intr, mac, &sc->bwn_intr, &wlan_global_serializer)) != 0) {
630                 device_printf(sc->sc_dev, "Cannot set up interrupt\n");
631                 goto fail1;
632         }
633 #else
634         if (pci_find_cap(dev, PCIY_EXPRESS, &reg) == 0) {
635                 msic = pci_msi_count(dev);
636                 if (bootverbose)
637                         device_printf(sc->sc_dev, "MSI count : %d\n", msic);
638         } else
639                 msic = 0;
640
641         mac->mac_intr_spec = bwn_res_spec_legacy;
642         if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0) {
643                 if (pci_alloc_msi(dev, &msic) == 0) {
644                         device_printf(sc->sc_dev,
645                             "Using %d MSI messages\n", msic);
646                         mac->mac_intr_spec = bwn_res_spec_msi;
647                         mac->mac_msi = 1;
648                 }
649         }
650
651         error = bus_alloc_resources(dev, mac->mac_intr_spec,
652             mac->mac_res_irq);
653         if (error) {
654                 device_printf(sc->sc_dev,
655                     "couldn't allocate IRQ resources (%d)\n", error);
656                 goto fail1;
657         }
658
659         if (mac->mac_msi == 0)
660                 error = bus_setup_intr(dev, mac->mac_res_irq[0],
661                     INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac,
662                     &mac->mac_intrhand[0]);
663         else {
664                 for (i = 0; i < BWN_MSI_MESSAGES; i++) {
665                         error = bus_setup_intr(dev, mac->mac_res_irq[i],
666                             INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac,
667                             &mac->mac_intrhand[i]);
668                         if (error != 0) {
669                                 device_printf(sc->sc_dev,
670                                     "couldn't setup interrupt (%d)\n", error);
671                                 break;
672                         }
673                 }
674         }
675 #endif
676
677         TAILQ_INSERT_TAIL(&sc->sc_maclist, mac, mac_list);
678
679         /*
680          * calls attach-post routine
681          */
682         if ((sc->sc_flags & BWN_FLAG_ATTACHED) != 0)
683                 bwn_attach_post(sc);
684
685         return (0);
686 fail1:
687 #if defined(__DragonFly__)
688         if (sc->bwn_irq_type == PCI_INTR_TYPE_MSI)
689                 pci_release_msi(dev);
690 #else
691         if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0)
692                 pci_release_msi(dev);
693 #endif
694 fail0:
695         kfree(mac, M_DEVBUF);
696         return (error);
697 }
698
699 static int
700 bwn_is_valid_ether_addr(uint8_t *addr)
701 {
702         char zero_addr[6] = { 0, 0, 0, 0, 0, 0 };
703
704         if ((addr[0] & 1) || (!bcmp(addr, zero_addr, ETHER_ADDR_LEN)))
705                 return (FALSE);
706
707         return (TRUE);
708 }
709
710 static int
711 bwn_attach_post(struct bwn_softc *sc)
712 {
713         struct ieee80211com *ic = &sc->sc_ic;
714
715         ic->ic_softc = sc;
716         ic->ic_name = device_get_nameunit(sc->sc_dev);
717         /* XXX not right but it's not used anywhere important */
718         ic->ic_phytype = IEEE80211_T_OFDM;
719         ic->ic_opmode = IEEE80211_M_STA;
720         ic->ic_caps =
721                   IEEE80211_C_STA               /* station mode supported */
722                 | IEEE80211_C_MONITOR           /* monitor mode */
723                 | IEEE80211_C_AHDEMO            /* adhoc demo mode */
724                 | IEEE80211_C_SHPREAMBLE        /* short preamble supported */
725                 | IEEE80211_C_SHSLOT            /* short slot time supported */
726                 | IEEE80211_C_WME               /* WME/WMM supported */
727                 | IEEE80211_C_WPA               /* capable of WPA1+WPA2 */
728 #if 0
729                 | IEEE80211_C_BGSCAN            /* capable of bg scanning */
730 #endif
731                 | IEEE80211_C_TXPMGT            /* capable of txpow mgt */
732                 ;
733
734         ic->ic_flags_ext |= IEEE80211_FEXT_SWBMISS;     /* s/w bmiss */
735
736         IEEE80211_ADDR_COPY(ic->ic_macaddr,
737             bwn_is_valid_ether_addr(siba_sprom_get_mac_80211a(sc->sc_dev)) ?
738             siba_sprom_get_mac_80211a(sc->sc_dev) :
739             siba_sprom_get_mac_80211bg(sc->sc_dev));
740
741         /* call MI attach routine. */
742         ieee80211_ifattach(ic);
743
744         ic->ic_headroom = sizeof(struct bwn_txhdr);
745
746         /* override default methods */
747         ic->ic_raw_xmit = bwn_raw_xmit;
748         ic->ic_updateslot = bwn_updateslot;
749         ic->ic_update_promisc = bwn_update_promisc;
750         ic->ic_wme.wme_update = bwn_wme_update;
751         ic->ic_scan_start = bwn_scan_start;
752         ic->ic_scan_end = bwn_scan_end;
753         ic->ic_set_channel = bwn_set_channel;
754         ic->ic_vap_create = bwn_vap_create;
755         ic->ic_vap_delete = bwn_vap_delete;
756         ic->ic_transmit = bwn_transmit;
757         ic->ic_parent = bwn_parent;
758
759         ieee80211_radiotap_attach(ic,
760             &sc->sc_tx_th.wt_ihdr, sizeof(sc->sc_tx_th),
761             BWN_TX_RADIOTAP_PRESENT,
762             &sc->sc_rx_th.wr_ihdr, sizeof(sc->sc_rx_th),
763             BWN_RX_RADIOTAP_PRESENT);
764
765         bwn_sysctl_node(sc);
766
767         if (bootverbose)
768                 ieee80211_announce(ic);
769         return (0);
770 }
771
772 static void
773 bwn_phy_detach(struct bwn_mac *mac)
774 {
775
776         if (mac->mac_phy.detach != NULL)
777                 mac->mac_phy.detach(mac);
778 }
779
780 static int
781 bwn_detach(device_t dev)
782 {
783         struct bwn_softc *sc = device_get_softc(dev);
784         struct bwn_mac *mac = sc->sc_curmac;
785         struct ieee80211com *ic = &sc->sc_ic;
786 #if !defined(__DragonFly__)
787         int i;
788 #endif
789
790         sc->sc_flags |= BWN_FLAG_INVALID;
791
792         if (device_is_attached(sc->sc_dev)) {
793                 BWN_LOCK(sc);
794                 bwn_stop(sc);
795                 BWN_UNLOCK(sc);
796                 bwn_dma_free(mac);
797                 callout_drain(&sc->sc_led_blink_ch);
798                 callout_drain(&sc->sc_rfswitch_ch);
799                 callout_drain(&sc->sc_task_ch);
800                 callout_drain(&sc->sc_watchdog_ch);
801                 bwn_phy_detach(mac);
802                 ieee80211_draintask(ic, &mac->mac_hwreset);
803                 ieee80211_draintask(ic, &mac->mac_txpower);
804                 ieee80211_ifdetach(ic);
805         }
806         taskqueue_drain(sc->sc_tq, &mac->mac_intrtask);
807         taskqueue_free(sc->sc_tq);
808
809 #if defined(__DragonFly__)
810         if (sc->bwn_intr)
811                 bus_teardown_intr(dev, sc->bwn_irq, sc->bwn_intr);
812         if (sc->bwn_irq != NULL) {
813                 bus_release_resource(dev, SYS_RES_IRQ, sc->bwn_irq_rid,
814                     sc->bwn_irq);
815         }
816
817         if (sc->bwn_irq_type == PCI_INTR_TYPE_MSI)
818                 pci_release_msi(dev);
819 #else
820         for (i = 0; i < BWN_MSI_MESSAGES; i++) {
821                 if (mac->mac_intrhand[i] != NULL) {
822                         bus_teardown_intr(dev, mac->mac_res_irq[i],
823                             mac->mac_intrhand[i]);
824                         mac->mac_intrhand[i] = NULL;
825                 }
826         }
827         bus_release_resources(dev, mac->mac_intr_spec, mac->mac_res_irq);
828         if (mac->mac_msi != 0)
829                 pci_release_msi(dev);
830 #endif
831         mbufq_drain(&sc->sc_snd);
832         BWN_LOCK_DESTROY(sc);
833         return (0);
834 }
835
836 static void
837 bwn_attach_pre(struct bwn_softc *sc)
838 {
839
840         BWN_LOCK_INIT(sc);
841         TAILQ_INIT(&sc->sc_maclist);
842 #if defined(__DragonFly__)
843         callout_init_lk(&sc->sc_rfswitch_ch, &sc->sc_lk);
844         callout_init_lk(&sc->sc_task_ch, &sc->sc_lk);
845         callout_init_lk(&sc->sc_watchdog_ch, &sc->sc_lk);
846 #else
847         callout_init_mtx(&sc->sc_rfswitch_ch, &sc->sc_mtx, 0);
848         callout_init_mtx(&sc->sc_task_ch, &sc->sc_mtx, 0);
849         callout_init_mtx(&sc->sc_watchdog_ch, &sc->sc_mtx, 0);
850 #endif
851         mbufq_init(&sc->sc_snd, ifqmaxlen);
852 #if defined(__DragonFly__)
853         sc->sc_tq = taskqueue_create("bwn_taskq", M_WAITOK,
854             taskqueue_thread_enqueue, &sc->sc_tq);
855         taskqueue_start_threads(&sc->sc_tq, 1, TDPRI_KERN_DAEMON,
856             -1, "%s taskq", device_get_nameunit(sc->sc_dev));
857 #else
858         sc->sc_tq = taskqueue_create_fast("bwn_taskq", M_NOWAIT,
859                 taskqueue_thread_enqueue, &sc->sc_tq);
860         taskqueue_start_threads(&sc->sc_tq, 1, PI_NET,
861                 "%s taskq", device_get_nameunit(sc->sc_dev));
862 #endif
863 }
864
865 static void
866 bwn_sprom_bugfixes(device_t dev)
867 {
868 #define BWN_ISDEV(_vendor, _device, _subvendor, _subdevice)             \
869         ((siba_get_pci_vendor(dev) == PCI_VENDOR_##_vendor) &&          \
870          (siba_get_pci_device(dev) == _device) &&                       \
871          (siba_get_pci_subvendor(dev) == PCI_VENDOR_##_subvendor) &&    \
872          (siba_get_pci_subdevice(dev) == _subdevice))
873
874         if (siba_get_pci_subvendor(dev) == PCI_VENDOR_APPLE &&
875             siba_get_pci_subdevice(dev) == 0x4e &&
876             siba_get_pci_revid(dev) > 0x40)
877                 siba_sprom_set_bf_lo(dev,
878                     siba_sprom_get_bf_lo(dev) | BWN_BFL_PACTRL);
879         if (siba_get_pci_subvendor(dev) == SIBA_BOARDVENDOR_DELL &&
880             siba_get_chipid(dev) == 0x4301 && siba_get_pci_revid(dev) == 0x74)
881                 siba_sprom_set_bf_lo(dev,
882                     siba_sprom_get_bf_lo(dev) | BWN_BFL_BTCOEXIST);
883         if (siba_get_type(dev) == SIBA_TYPE_PCI) {
884                 if (BWN_ISDEV(BROADCOM, 0x4318, ASUSTEK, 0x100f) ||
885                     BWN_ISDEV(BROADCOM, 0x4320, DELL, 0x0003) ||
886                     BWN_ISDEV(BROADCOM, 0x4320, HP, 0x12f8) ||
887                     BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0013) ||
888                     BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0014) ||
889                     BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0015) ||
890                     BWN_ISDEV(BROADCOM, 0x4320, MOTOROLA, 0x7010))
891                         siba_sprom_set_bf_lo(dev,
892                             siba_sprom_get_bf_lo(dev) & ~BWN_BFL_BTCOEXIST);
893         }
894 #undef  BWN_ISDEV
895 }
896
897 static void
898 bwn_parent(struct ieee80211com *ic)
899 {
900         struct bwn_softc *sc = ic->ic_softc;
901         int startall = 0;
902
903         BWN_LOCK(sc);
904         if (ic->ic_nrunning > 0) {
905                 if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0) {
906                         bwn_init(sc);
907                         startall = 1;
908                 } else
909                         bwn_update_promisc(ic);
910         } else if (sc->sc_flags & BWN_FLAG_RUNNING)
911                 bwn_stop(sc);
912         BWN_UNLOCK(sc);
913
914         if (startall)
915                 ieee80211_start_all(ic);
916 }
917
918 static int
919 bwn_transmit(struct ieee80211com *ic, struct mbuf *m)
920 {
921         struct bwn_softc *sc = ic->ic_softc;
922         int error;
923
924         BWN_LOCK(sc);
925         if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0) {
926                 BWN_UNLOCK(sc);
927                 return (ENXIO);
928         }
929         error = mbufq_enqueue(&sc->sc_snd, m);
930         if (error) {
931                 BWN_UNLOCK(sc);
932                 return (error);
933         }
934         bwn_start(sc);
935         BWN_UNLOCK(sc);
936         return (0);
937 }
938
939 static void
940 bwn_start(struct bwn_softc *sc)
941 {
942         struct bwn_mac *mac = sc->sc_curmac;
943         struct ieee80211_frame *wh;
944         struct ieee80211_node *ni;
945         struct ieee80211_key *k;
946         struct mbuf *m;
947
948         BWN_ASSERT_LOCKED(sc);
949
950         if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0 || mac == NULL ||
951             mac->mac_status < BWN_MAC_STATUS_STARTED)
952                 return;
953
954         while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
955                 if (bwn_tx_isfull(sc, m))
956                         break;
957                 ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
958                 if (ni == NULL) {
959                         device_printf(sc->sc_dev, "unexpected NULL ni\n");
960                         m_freem(m);
961 #if defined(__DragonFly__)
962                         ++sc->sc_ic.ic_oerrors;
963 #else
964                         counter_u64_add(sc->sc_ic.ic_oerrors, 1);
965 #endif
966                         continue;
967                 }
968                 wh = mtod(m, struct ieee80211_frame *);
969                 if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
970                         k = ieee80211_crypto_encap(ni, m);
971                         if (k == NULL) {
972                                 if_inc_counter(ni->ni_vap->iv_ifp,
973                                     IFCOUNTER_OERRORS, 1);
974                                 ieee80211_free_node(ni);
975                                 m_freem(m);
976                                 continue;
977                         }
978                 }
979                 wh = NULL;      /* Catch any invalid use */
980                 if (bwn_tx_start(sc, ni, m) != 0) {
981                         if (ni != NULL) {
982                                 if_inc_counter(ni->ni_vap->iv_ifp,
983                                     IFCOUNTER_OERRORS, 1);
984                                 ieee80211_free_node(ni);
985                         }
986                         continue;
987                 }
988                 sc->sc_watchdog_timer = 5;
989         }
990 }
991
992 static int
993 bwn_tx_isfull(struct bwn_softc *sc, struct mbuf *m)
994 {
995         struct bwn_dma_ring *dr;
996         struct bwn_mac *mac = sc->sc_curmac;
997         struct bwn_pio_txqueue *tq;
998         int pktlen = roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
999
1000         BWN_ASSERT_LOCKED(sc);
1001
1002         if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
1003                 dr = bwn_dma_select(mac, M_WME_GETAC(m));
1004                 if (dr->dr_stop == 1 ||
1005                     bwn_dma_freeslot(dr) < BWN_TX_SLOTS_PER_FRAME) {
1006                         dr->dr_stop = 1;
1007                         goto full;
1008                 }
1009         } else {
1010                 tq = bwn_pio_select(mac, M_WME_GETAC(m));
1011                 if (tq->tq_free == 0 || pktlen > tq->tq_size ||
1012                     pktlen > (tq->tq_size - tq->tq_used))
1013                         goto full;
1014         }
1015         return (0);
1016 full:
1017         mbufq_prepend(&sc->sc_snd, m);
1018         return (1);
1019 }
1020
1021 static int
1022 bwn_tx_start(struct bwn_softc *sc, struct ieee80211_node *ni, struct mbuf *m)
1023 {
1024         struct bwn_mac *mac = sc->sc_curmac;
1025         int error;
1026
1027         BWN_ASSERT_LOCKED(sc);
1028
1029         if (m->m_pkthdr.len < IEEE80211_MIN_LEN || mac == NULL) {
1030                 m_freem(m);
1031                 return (ENXIO);
1032         }
1033
1034         error = (mac->mac_flags & BWN_MAC_FLAG_DMA) ?
1035             bwn_dma_tx_start(mac, ni, m) : bwn_pio_tx_start(mac, ni, m);
1036         if (error) {
1037                 m_freem(m);
1038                 return (error);
1039         }
1040         return (0);
1041 }
1042
1043 static int
1044 bwn_pio_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1045 {
1046         struct bwn_pio_txpkt *tp;
1047         struct bwn_pio_txqueue *tq = bwn_pio_select(mac, M_WME_GETAC(m));
1048         struct bwn_softc *sc = mac->mac_sc;
1049         struct bwn_txhdr txhdr;
1050         struct mbuf *m_new;
1051         uint32_t ctl32;
1052         int error;
1053         uint16_t ctl16;
1054
1055         BWN_ASSERT_LOCKED(sc);
1056
1057         /* XXX TODO send packets after DTIM */
1058
1059         KASSERT(!TAILQ_EMPTY(&tq->tq_pktlist), ("%s: fail", __func__));
1060         tp = TAILQ_FIRST(&tq->tq_pktlist);
1061         tp->tp_ni = ni;
1062         tp->tp_m = m;
1063
1064         error = bwn_set_txhdr(mac, ni, m, &txhdr, BWN_PIO_COOKIE(tq, tp));
1065         if (error) {
1066                 device_printf(sc->sc_dev, "tx fail\n");
1067                 return (error);
1068         }
1069
1070         TAILQ_REMOVE(&tq->tq_pktlist, tp, tp_list);
1071         tq->tq_used += roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1072         tq->tq_free--;
1073
1074         if (siba_get_revid(sc->sc_dev) >= 8) {
1075                 /*
1076                  * XXX please removes m_defrag(9)
1077                  */
1078                 m_new = m_defrag(m, M_NOWAIT);
1079                 if (m_new == NULL) {
1080                         device_printf(sc->sc_dev,
1081                             "%s: can't defrag TX buffer\n",
1082                             __func__);
1083                         return (ENOBUFS);
1084                 }
1085                 if (m_new->m_next != NULL)
1086                         device_printf(sc->sc_dev,
1087                             "TODO: fragmented packets for PIO\n");
1088                 tp->tp_m = m_new;
1089
1090                 /* send HEADER */
1091                 ctl32 = bwn_pio_write_multi_4(mac, tq,
1092                     (BWN_PIO_READ_4(mac, tq, BWN_PIO8_TXCTL) |
1093                         BWN_PIO8_TXCTL_FRAMEREADY) & ~BWN_PIO8_TXCTL_EOF,
1094                     (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1095                 /* send BODY */
1096                 ctl32 = bwn_pio_write_multi_4(mac, tq, ctl32,
1097                     mtod(m_new, const void *), m_new->m_pkthdr.len);
1098                 bwn_pio_write_4(mac, tq, BWN_PIO_TXCTL,
1099                     ctl32 | BWN_PIO8_TXCTL_EOF);
1100         } else {
1101                 ctl16 = bwn_pio_write_multi_2(mac, tq,
1102                     (bwn_pio_read_2(mac, tq, BWN_PIO_TXCTL) |
1103                         BWN_PIO_TXCTL_FRAMEREADY) & ~BWN_PIO_TXCTL_EOF,
1104                     (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1105                 ctl16 = bwn_pio_write_mbuf_2(mac, tq, ctl16, m);
1106                 BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL,
1107                     ctl16 | BWN_PIO_TXCTL_EOF);
1108         }
1109
1110         return (0);
1111 }
1112
1113 static struct bwn_pio_txqueue *
1114 bwn_pio_select(struct bwn_mac *mac, uint8_t prio)
1115 {
1116
1117         if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
1118                 return (&mac->mac_method.pio.wme[WME_AC_BE]);
1119
1120         switch (prio) {
1121         case 0:
1122                 return (&mac->mac_method.pio.wme[WME_AC_BE]);
1123         case 1:
1124                 return (&mac->mac_method.pio.wme[WME_AC_BK]);
1125         case 2:
1126                 return (&mac->mac_method.pio.wme[WME_AC_VI]);
1127         case 3:
1128                 return (&mac->mac_method.pio.wme[WME_AC_VO]);
1129         }
1130         KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
1131         return (NULL);
1132 }
1133
1134 static int
1135 bwn_dma_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1136 {
1137 #define BWN_GET_TXHDRCACHE(slot)                                        \
1138         &(txhdr_cache[(slot / BWN_TX_SLOTS_PER_FRAME) * BWN_HDRSIZE(mac)])
1139         struct bwn_dma *dma = &mac->mac_method.dma;
1140         struct bwn_dma_ring *dr = bwn_dma_select(mac, M_WME_GETAC(m));
1141         struct bwn_dmadesc_generic *desc;
1142         struct bwn_dmadesc_meta *mt;
1143         struct bwn_softc *sc = mac->mac_sc;
1144         uint8_t *txhdr_cache = (uint8_t *)dr->dr_txhdr_cache;
1145         int error, slot, backup[2] = { dr->dr_curslot, dr->dr_usedslot };
1146
1147         BWN_ASSERT_LOCKED(sc);
1148         KASSERT(!dr->dr_stop, ("%s:%d: fail", __func__, __LINE__));
1149
1150         /* XXX send after DTIM */
1151
1152         slot = bwn_dma_getslot(dr);
1153         dr->getdesc(dr, slot, &desc, &mt);
1154         KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_HEADER,
1155             ("%s:%d: fail", __func__, __LINE__));
1156
1157         error = bwn_set_txhdr(dr->dr_mac, ni, m,
1158             (struct bwn_txhdr *)BWN_GET_TXHDRCACHE(slot),
1159             BWN_DMA_COOKIE(dr, slot));
1160         if (error)
1161                 goto fail;
1162         error = bus_dmamap_load(dr->dr_txring_dtag, mt->mt_dmap,
1163             BWN_GET_TXHDRCACHE(slot), BWN_HDRSIZE(mac), bwn_dma_ring_addr,
1164             &mt->mt_paddr, BUS_DMA_NOWAIT);
1165         if (error) {
1166                 device_printf(sc->sc_dev, "%s: can't load TX buffer (1) %d\n",
1167                     __func__, error);
1168                 goto fail;
1169         }
1170         if (mt->mt_paddr == 0) {
1171                 device_printf(sc->sc_dev,
1172                     "%s: can't load TX buffer within segment constraints (1)\n",
1173                     __func__);
1174                 goto fail;
1175         }
1176         bus_dmamap_sync(dr->dr_txring_dtag, mt->mt_dmap,
1177             BUS_DMASYNC_PREWRITE);
1178         dr->setdesc(dr, desc, mt->mt_paddr, BWN_HDRSIZE(mac), 1, 0, 0);
1179         bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1180             BUS_DMASYNC_PREWRITE);
1181
1182         slot = bwn_dma_getslot(dr);
1183         dr->getdesc(dr, slot, &desc, &mt);
1184         KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_BODY &&
1185             mt->mt_islast == 1, ("%s:%d: fail", __func__, __LINE__));
1186         mt->mt_m = m;
1187         mt->mt_ni = ni;
1188
1189         error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap, m,
1190             bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1191         if (error && error != EFBIG) {
1192                 device_printf(sc->sc_dev, "%s: can't load TX buffer (1) %d\n",
1193                     __func__, error);
1194                 goto fail;
1195         }
1196         if (error) {    /* error == EFBIG */
1197                 struct mbuf *m_new;
1198
1199                 m_new = m_defrag(m, M_NOWAIT);
1200                 if (m_new == NULL) {
1201                         device_printf(sc->sc_dev,
1202                             "%s: can't defrag TX buffer\n",
1203                             __func__);
1204                         error = ENOBUFS;
1205                         goto fail;
1206                 } else {
1207                         m = m_new;
1208                 }
1209
1210                 mt->mt_m = m;
1211                 error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap,
1212                     m, bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1213                 if (error) {
1214                         device_printf(sc->sc_dev,
1215                             "%s: can't load TX buffer (2) %d\n",
1216                             __func__, error);
1217                         goto fail;
1218                 }
1219         }
1220         bus_dmamap_sync(dma->txbuf_dtag, mt->mt_dmap, BUS_DMASYNC_PREWRITE);
1221         dr->setdesc(dr, desc, mt->mt_paddr, m->m_pkthdr.len, 0, 1, 1);
1222         bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1223             BUS_DMASYNC_PREWRITE);
1224
1225         /* XXX send after DTIM */
1226
1227         dr->start_transfer(dr, bwn_dma_nextslot(dr, slot));
1228         return (0);
1229 fail:
1230         dr->dr_curslot = backup[0];
1231         dr->dr_usedslot = backup[1];
1232         return (error);
1233 #undef BWN_GET_TXHDRCACHE
1234 }
1235
1236 static void
1237 bwn_watchdog(void *arg)
1238 {
1239         struct bwn_softc *sc = arg;
1240
1241         if (sc->sc_watchdog_timer != 0 && --sc->sc_watchdog_timer == 0) {
1242                 device_printf(sc->sc_dev, "device timeout\n");
1243 #if defined(__DragonFly__)
1244                 ++sc->sc_ic.ic_oerrors;
1245 #else
1246                 counter_u64_add(sc->sc_ic.ic_oerrors, 1);
1247 #endif
1248         }
1249 #if defined(__DragonFly__)
1250         callout_reset(&sc->sc_watchdog_ch, hz, bwn_watchdog, sc);
1251 #else
1252         callout_schedule(&sc->sc_watchdog_ch, hz);
1253 #endif
1254 }
1255
1256 static int
1257 bwn_attach_core(struct bwn_mac *mac)
1258 {
1259         struct bwn_softc *sc = mac->mac_sc;
1260         int error, have_bg = 0, have_a = 0;
1261         uint32_t high;
1262
1263         KASSERT(siba_get_revid(sc->sc_dev) >= 5,
1264             ("unsupported revision %d", siba_get_revid(sc->sc_dev)));
1265
1266         siba_powerup(sc->sc_dev, 0);
1267
1268         high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH);
1269         bwn_reset_core(mac, !!(high & BWN_TGSHIGH_HAVE_2GHZ));
1270         error = bwn_phy_getinfo(mac, high);
1271         if (error)
1272                 goto fail;
1273
1274         /* XXX need bhnd */
1275         if (bwn_is_bus_siba(mac)) {
1276                 have_a = (high & BWN_TGSHIGH_HAVE_5GHZ) ? 1 : 0;
1277                 have_bg = (high & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1278         } else {
1279                 device_printf(sc->sc_dev, "%s: not siba; bailing\n", __func__);
1280                 error = ENXIO;
1281                 goto fail;
1282         }
1283
1284 #if 0
1285         device_printf(sc->sc_dev, "%s: high=0x%08x, have_a=%d, have_bg=%d,"
1286             " deviceid=0x%04x, siba_deviceid=0x%04x\n",
1287             __func__,
1288             high,
1289             have_a,
1290             have_bg,
1291             siba_get_pci_device(sc->sc_dev),
1292             siba_get_chipid(sc->sc_dev));
1293 #endif
1294
1295         if (siba_get_pci_device(sc->sc_dev) != 0x4312 &&
1296             siba_get_pci_device(sc->sc_dev) != 0x4319 &&
1297             siba_get_pci_device(sc->sc_dev) != 0x4324) {
1298                 have_a = have_bg = 0;
1299                 if (mac->mac_phy.type == BWN_PHYTYPE_A)
1300                         have_a = 1;
1301                 else if (mac->mac_phy.type == BWN_PHYTYPE_G ||
1302                     mac->mac_phy.type == BWN_PHYTYPE_N ||
1303                     mac->mac_phy.type == BWN_PHYTYPE_LP)
1304                         have_bg = 1;
1305                 else
1306                         KASSERT(0 == 1, ("%s: unknown phy type (%d)", __func__,
1307                             mac->mac_phy.type));
1308         }
1309         /* XXX turns off PHY A because it's not supported */
1310         if (mac->mac_phy.type != BWN_PHYTYPE_LP &&
1311             mac->mac_phy.type != BWN_PHYTYPE_N) {
1312                 have_a = 0;
1313                 have_bg = 1;
1314         }
1315
1316         if (mac->mac_phy.type == BWN_PHYTYPE_G) {
1317                 mac->mac_phy.attach = bwn_phy_g_attach;
1318                 mac->mac_phy.detach = bwn_phy_g_detach;
1319                 mac->mac_phy.prepare_hw = bwn_phy_g_prepare_hw;
1320                 mac->mac_phy.init_pre = bwn_phy_g_init_pre;
1321                 mac->mac_phy.init = bwn_phy_g_init;
1322                 mac->mac_phy.exit = bwn_phy_g_exit;
1323                 mac->mac_phy.phy_read = bwn_phy_g_read;
1324                 mac->mac_phy.phy_write = bwn_phy_g_write;
1325                 mac->mac_phy.rf_read = bwn_phy_g_rf_read;
1326                 mac->mac_phy.rf_write = bwn_phy_g_rf_write;
1327                 mac->mac_phy.use_hwpctl = bwn_phy_g_hwpctl;
1328                 mac->mac_phy.rf_onoff = bwn_phy_g_rf_onoff;
1329                 mac->mac_phy.switch_analog = bwn_phy_switch_analog;
1330                 mac->mac_phy.switch_channel = bwn_phy_g_switch_channel;
1331                 mac->mac_phy.get_default_chan = bwn_phy_g_get_default_chan;
1332                 mac->mac_phy.set_antenna = bwn_phy_g_set_antenna;
1333                 mac->mac_phy.set_im = bwn_phy_g_im;
1334                 mac->mac_phy.recalc_txpwr = bwn_phy_g_recalc_txpwr;
1335                 mac->mac_phy.set_txpwr = bwn_phy_g_set_txpwr;
1336                 mac->mac_phy.task_15s = bwn_phy_g_task_15s;
1337                 mac->mac_phy.task_60s = bwn_phy_g_task_60s;
1338         } else if (mac->mac_phy.type == BWN_PHYTYPE_LP) {
1339                 mac->mac_phy.init_pre = bwn_phy_lp_init_pre;
1340                 mac->mac_phy.init = bwn_phy_lp_init;
1341                 mac->mac_phy.phy_read = bwn_phy_lp_read;
1342                 mac->mac_phy.phy_write = bwn_phy_lp_write;
1343                 mac->mac_phy.phy_maskset = bwn_phy_lp_maskset;
1344                 mac->mac_phy.rf_read = bwn_phy_lp_rf_read;
1345                 mac->mac_phy.rf_write = bwn_phy_lp_rf_write;
1346                 mac->mac_phy.rf_onoff = bwn_phy_lp_rf_onoff;
1347                 mac->mac_phy.switch_analog = bwn_phy_lp_switch_analog;
1348                 mac->mac_phy.switch_channel = bwn_phy_lp_switch_channel;
1349                 mac->mac_phy.get_default_chan = bwn_phy_lp_get_default_chan;
1350                 mac->mac_phy.set_antenna = bwn_phy_lp_set_antenna;
1351                 mac->mac_phy.task_60s = bwn_phy_lp_task_60s;
1352         } else {
1353                 device_printf(sc->sc_dev, "unsupported PHY type (%d)\n",
1354                     mac->mac_phy.type);
1355                 error = ENXIO;
1356                 goto fail;
1357         }
1358
1359         mac->mac_phy.gmode = have_bg;
1360         if (mac->mac_phy.attach != NULL) {
1361                 error = mac->mac_phy.attach(mac);
1362                 if (error) {
1363                         device_printf(sc->sc_dev, "failed\n");
1364                         goto fail;
1365                 }
1366         }
1367
1368         bwn_reset_core(mac, have_bg);
1369
1370         error = bwn_chiptest(mac);
1371         if (error)
1372                 goto fail;
1373         error = bwn_setup_channels(mac, have_bg, have_a);
1374         if (error) {
1375                 device_printf(sc->sc_dev, "failed to setup channels\n");
1376                 goto fail;
1377         }
1378
1379         if (sc->sc_curmac == NULL)
1380                 sc->sc_curmac = mac;
1381
1382         error = bwn_dma_attach(mac);
1383         if (error != 0) {
1384                 device_printf(sc->sc_dev, "failed to initialize DMA\n");
1385                 goto fail;
1386         }
1387
1388         mac->mac_phy.switch_analog(mac, 0);
1389
1390         siba_dev_down(sc->sc_dev, 0);
1391 fail:
1392         siba_powerdown(sc->sc_dev);
1393         return (error);
1394 }
1395
1396 /*
1397  * Reset - SIBA.
1398  *
1399  * XXX TODO: implement BCMA version!
1400  */
1401 void
1402 bwn_reset_core(struct bwn_mac *mac, int g_mode)
1403 {
1404         struct bwn_softc *sc = mac->mac_sc;
1405         uint32_t low, ctl;
1406         uint32_t flags = 0;
1407
1408         DPRINTF(sc, BWN_DEBUG_RESET, "%s: g_mode=%d\n", __func__, g_mode);
1409
1410         flags |= (BWN_TGSLOW_PHYCLOCK_ENABLE | BWN_TGSLOW_PHYRESET);
1411         if (g_mode)
1412                 flags |= BWN_TGSLOW_SUPPORT_G;
1413
1414         /* XXX N-PHY only; and hard-code to 20MHz for now */
1415         if (mac->mac_phy.type == BWN_PHYTYPE_N)
1416                 flags |= BWN_TGSLOW_PHY_BANDWIDTH_20MHZ;
1417
1418         siba_dev_up(sc->sc_dev, flags);
1419         DELAY(2000);
1420
1421         /* Take PHY out of reset */
1422         low = (siba_read_4(sc->sc_dev, SIBA_TGSLOW) | SIBA_TGSLOW_FGC) &
1423             ~BWN_TGSLOW_PHYRESET;
1424         siba_write_4(sc->sc_dev, SIBA_TGSLOW, low);
1425         siba_read_4(sc->sc_dev, SIBA_TGSLOW);
1426         DELAY(1000);
1427         siba_write_4(sc->sc_dev, SIBA_TGSLOW, low & ~SIBA_TGSLOW_FGC);
1428         siba_read_4(sc->sc_dev, SIBA_TGSLOW);
1429         DELAY(1000);
1430
1431         if (mac->mac_phy.switch_analog != NULL)
1432                 mac->mac_phy.switch_analog(mac, 1);
1433
1434         ctl = BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GMODE;
1435         if (g_mode)
1436                 ctl |= BWN_MACCTL_GMODE;
1437         BWN_WRITE_4(mac, BWN_MACCTL, ctl | BWN_MACCTL_IHR_ON);
1438 }
1439
1440 static int
1441 bwn_phy_getinfo(struct bwn_mac *mac, int tgshigh)
1442 {
1443         struct bwn_phy *phy = &mac->mac_phy;
1444         struct bwn_softc *sc = mac->mac_sc;
1445         uint32_t tmp;
1446
1447         /* PHY */
1448         tmp = BWN_READ_2(mac, BWN_PHYVER);
1449         phy->gmode = !! (tgshigh & BWN_TGSHIGH_HAVE_2GHZ);
1450         phy->rf_on = 1;
1451         phy->analog = (tmp & BWN_PHYVER_ANALOG) >> 12;
1452         phy->type = (tmp & BWN_PHYVER_TYPE) >> 8;
1453         phy->rev = (tmp & BWN_PHYVER_VERSION);
1454         if ((phy->type == BWN_PHYTYPE_A && phy->rev >= 4) ||
1455             (phy->type == BWN_PHYTYPE_B && phy->rev != 2 &&
1456                 phy->rev != 4 && phy->rev != 6 && phy->rev != 7) ||
1457             (phy->type == BWN_PHYTYPE_G && phy->rev > 9) ||
1458             (phy->type == BWN_PHYTYPE_N && phy->rev > 4) ||
1459             (phy->type == BWN_PHYTYPE_LP && phy->rev > 2))
1460                 goto unsupphy;
1461
1462         /* RADIO */
1463         if (siba_get_chipid(sc->sc_dev) == 0x4317) {
1464                 if (siba_get_chiprev(sc->sc_dev) == 0)
1465                         tmp = 0x3205017f;
1466                 else if (siba_get_chiprev(sc->sc_dev) == 1)
1467                         tmp = 0x4205017f;
1468                 else
1469                         tmp = 0x5205017f;
1470         } else {
1471                 BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1472                 tmp = BWN_READ_2(mac, BWN_RFDATALO);
1473                 BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1474                 tmp |= (uint32_t)BWN_READ_2(mac, BWN_RFDATAHI) << 16;
1475         }
1476         phy->rf_rev = (tmp & 0xf0000000) >> 28;
1477         phy->rf_ver = (tmp & 0x0ffff000) >> 12;
1478         phy->rf_manuf = (tmp & 0x00000fff);
1479
1480         /*
1481          * For now, just always do full init (ie, what bwn has traditionally
1482          * done)
1483          */
1484         phy->phy_do_full_init = 1;
1485
1486         if (phy->rf_manuf != 0x17f)     /* 0x17f is broadcom */
1487                 goto unsupradio;
1488         if ((phy->type == BWN_PHYTYPE_A && (phy->rf_ver != 0x2060 ||
1489              phy->rf_rev != 1 || phy->rf_manuf != 0x17f)) ||
1490             (phy->type == BWN_PHYTYPE_B && (phy->rf_ver & 0xfff0) != 0x2050) ||
1491             (phy->type == BWN_PHYTYPE_G && phy->rf_ver != 0x2050) ||
1492             (phy->type == BWN_PHYTYPE_N &&
1493              phy->rf_ver != 0x2055 && phy->rf_ver != 0x2056) ||
1494             (phy->type == BWN_PHYTYPE_LP &&
1495              phy->rf_ver != 0x2062 && phy->rf_ver != 0x2063))
1496                 goto unsupradio;
1497
1498         return (0);
1499 unsupphy:
1500         device_printf(sc->sc_dev, "unsupported PHY (type %#x, rev %#x, "
1501             "analog %#x)\n",
1502             phy->type, phy->rev, phy->analog);
1503         return (ENXIO);
1504 unsupradio:
1505         device_printf(sc->sc_dev, "unsupported radio (manuf %#x, ver %#x, "
1506             "rev %#x)\n",
1507             phy->rf_manuf, phy->rf_ver, phy->rf_rev);
1508         return (ENXIO);
1509 }
1510
1511 static int
1512 bwn_chiptest(struct bwn_mac *mac)
1513 {
1514 #define TESTVAL0        0x55aaaa55
1515 #define TESTVAL1        0xaa5555aa
1516         struct bwn_softc *sc = mac->mac_sc;
1517         uint32_t v, backup;
1518
1519         BWN_LOCK(sc);
1520
1521         backup = bwn_shm_read_4(mac, BWN_SHARED, 0);
1522
1523         bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL0);
1524         if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL0)
1525                 goto error;
1526         bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL1);
1527         if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL1)
1528                 goto error;
1529
1530         bwn_shm_write_4(mac, BWN_SHARED, 0, backup);
1531
1532         if ((siba_get_revid(sc->sc_dev) >= 3) &&
1533             (siba_get_revid(sc->sc_dev) <= 10)) {
1534                 BWN_WRITE_2(mac, BWN_TSF_CFP_START, 0xaaaa);
1535                 BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0xccccbbbb);
1536                 if (BWN_READ_2(mac, BWN_TSF_CFP_START_LOW) != 0xbbbb)
1537                         goto error;
1538                 if (BWN_READ_2(mac, BWN_TSF_CFP_START_HIGH) != 0xcccc)
1539                         goto error;
1540         }
1541         BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0);
1542
1543         v = BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_GMODE;
1544         if (v != (BWN_MACCTL_GMODE | BWN_MACCTL_IHR_ON))
1545                 goto error;
1546
1547         BWN_UNLOCK(sc);
1548         return (0);
1549 error:
1550         BWN_UNLOCK(sc);
1551         device_printf(sc->sc_dev, "failed to validate the chipaccess\n");
1552         return (ENODEV);
1553 }
1554
1555 #define IEEE80211_CHAN_HTG      (IEEE80211_CHAN_HT | IEEE80211_CHAN_G)
1556 #define IEEE80211_CHAN_HTA      (IEEE80211_CHAN_HT | IEEE80211_CHAN_A)
1557
1558 static int
1559 bwn_setup_channels(struct bwn_mac *mac, int have_bg, int have_a)
1560 {
1561         struct bwn_softc *sc = mac->mac_sc;
1562         struct ieee80211com *ic = &sc->sc_ic;
1563
1564         memset(ic->ic_channels, 0, sizeof(ic->ic_channels));
1565         ic->ic_nchans = 0;
1566
1567         DPRINTF(sc, BWN_DEBUG_EEPROM, "%s: called; bg=%d, a=%d\n",
1568             __func__,
1569             have_bg,
1570             have_a);
1571
1572         if (have_bg)
1573                 bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1574                     &ic->ic_nchans, &bwn_chantable_bg, IEEE80211_CHAN_G);
1575 #if 0
1576         if (mac->mac_phy.type == BWN_PHYTYPE_N) {
1577                 if (have_a)
1578                         bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1579                             &ic->ic_nchans, &bwn_chantable_n,
1580                             IEEE80211_CHAN_HTA);
1581         } else {
1582                 if (have_a)
1583                         bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1584                             &ic->ic_nchans, &bwn_chantable_a,
1585                             IEEE80211_CHAN_A);
1586         }
1587 #endif
1588         if (have_a)
1589                 bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1590                     &ic->ic_nchans, &bwn_chantable_a,
1591                     IEEE80211_CHAN_A);
1592
1593         mac->mac_phy.supports_2ghz = have_bg;
1594         mac->mac_phy.supports_5ghz = have_a;
1595
1596         return (ic->ic_nchans == 0 ? ENXIO : 0);
1597 }
1598
1599 uint32_t
1600 bwn_shm_read_4(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1601 {
1602         uint32_t ret;
1603
1604         BWN_ASSERT_LOCKED(mac->mac_sc);
1605
1606         if (way == BWN_SHARED) {
1607                 KASSERT((offset & 0x0001) == 0,
1608                     ("%s:%d warn", __func__, __LINE__));
1609                 if (offset & 0x0003) {
1610                         bwn_shm_ctlword(mac, way, offset >> 2);
1611                         ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1612                         ret <<= 16;
1613                         bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1614                         ret |= BWN_READ_2(mac, BWN_SHM_DATA);
1615                         goto out;
1616                 }
1617                 offset >>= 2;
1618         }
1619         bwn_shm_ctlword(mac, way, offset);
1620         ret = BWN_READ_4(mac, BWN_SHM_DATA);
1621 out:
1622         return (ret);
1623 }
1624
1625 uint16_t
1626 bwn_shm_read_2(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1627 {
1628         uint16_t ret;
1629
1630         BWN_ASSERT_LOCKED(mac->mac_sc);
1631
1632         if (way == BWN_SHARED) {
1633                 KASSERT((offset & 0x0001) == 0,
1634                     ("%s:%d warn", __func__, __LINE__));
1635                 if (offset & 0x0003) {
1636                         bwn_shm_ctlword(mac, way, offset >> 2);
1637                         ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1638                         goto out;
1639                 }
1640                 offset >>= 2;
1641         }
1642         bwn_shm_ctlword(mac, way, offset);
1643         ret = BWN_READ_2(mac, BWN_SHM_DATA);
1644 out:
1645
1646         return (ret);
1647 }
1648
1649 static void
1650 bwn_shm_ctlword(struct bwn_mac *mac, uint16_t way,
1651     uint16_t offset)
1652 {
1653         uint32_t control;
1654
1655         control = way;
1656         control <<= 16;
1657         control |= offset;
1658         BWN_WRITE_4(mac, BWN_SHM_CONTROL, control);
1659 }
1660
1661 void
1662 bwn_shm_write_4(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1663     uint32_t value)
1664 {
1665         BWN_ASSERT_LOCKED(mac->mac_sc);
1666
1667         if (way == BWN_SHARED) {
1668                 KASSERT((offset & 0x0001) == 0,
1669                     ("%s:%d warn", __func__, __LINE__));
1670                 if (offset & 0x0003) {
1671                         bwn_shm_ctlword(mac, way, offset >> 2);
1672                         BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED,
1673                                     (value >> 16) & 0xffff);
1674                         bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1675                         BWN_WRITE_2(mac, BWN_SHM_DATA, value & 0xffff);
1676                         return;
1677                 }
1678                 offset >>= 2;
1679         }
1680         bwn_shm_ctlword(mac, way, offset);
1681         BWN_WRITE_4(mac, BWN_SHM_DATA, value);
1682 }
1683
1684 void
1685 bwn_shm_write_2(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1686     uint16_t value)
1687 {
1688         BWN_ASSERT_LOCKED(mac->mac_sc);
1689
1690         if (way == BWN_SHARED) {
1691                 KASSERT((offset & 0x0001) == 0,
1692                     ("%s:%d warn", __func__, __LINE__));
1693                 if (offset & 0x0003) {
1694                         bwn_shm_ctlword(mac, way, offset >> 2);
1695                         BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED, value);
1696                         return;
1697                 }
1698                 offset >>= 2;
1699         }
1700         bwn_shm_ctlword(mac, way, offset);
1701         BWN_WRITE_2(mac, BWN_SHM_DATA, value);
1702 }
1703
1704 static void
1705 bwn_addchan(struct ieee80211_channel *c, int freq, int flags, int ieee,
1706     int txpow)
1707 {
1708
1709         c->ic_freq = freq;
1710         c->ic_flags = flags;
1711         c->ic_ieee = ieee;
1712         c->ic_minpower = 0;
1713         c->ic_maxpower = 2 * txpow;
1714         c->ic_maxregpower = txpow;
1715 }
1716
1717 static void
1718 bwn_addchannels(struct ieee80211_channel chans[], int maxchans, int *nchans,
1719     const struct bwn_channelinfo *ci, int flags)
1720 {
1721         struct ieee80211_channel *c;
1722         int i;
1723
1724         c = &chans[*nchans];
1725
1726         for (i = 0; i < ci->nchannels; i++) {
1727                 const struct bwn_channel *hc;
1728
1729                 hc = &ci->channels[i];
1730                 if (*nchans >= maxchans)
1731                         break;
1732                 bwn_addchan(c, hc->freq, flags, hc->ieee, hc->maxTxPow);
1733                 c++, (*nchans)++;
1734                 if (flags == IEEE80211_CHAN_G || flags == IEEE80211_CHAN_HTG) {
1735                         /* g channel have a separate b-only entry */
1736                         if (*nchans >= maxchans)
1737                                 break;
1738                         c[0] = c[-1];
1739                         c[-1].ic_flags = IEEE80211_CHAN_B;
1740                         c++, (*nchans)++;
1741                 }
1742                 if (flags == IEEE80211_CHAN_HTG) {
1743                         /* HT g channel have a separate g-only entry */
1744                         if (*nchans >= maxchans)
1745                                 break;
1746                         c[-1].ic_flags = IEEE80211_CHAN_G;
1747                         c[0] = c[-1];
1748                         c[0].ic_flags &= ~IEEE80211_CHAN_HT;
1749                         c[0].ic_flags |= IEEE80211_CHAN_HT20;   /* HT20 */
1750                         c++, (*nchans)++;
1751                 }
1752                 if (flags == IEEE80211_CHAN_HTA) {
1753                         /* HT a channel have a separate a-only entry */
1754                         if (*nchans >= maxchans)
1755                                 break;
1756                         c[-1].ic_flags = IEEE80211_CHAN_A;
1757                         c[0] = c[-1];
1758                         c[0].ic_flags &= ~IEEE80211_CHAN_HT;
1759                         c[0].ic_flags |= IEEE80211_CHAN_HT20;   /* HT20 */
1760                         c++, (*nchans)++;
1761                 }
1762         }
1763 }
1764
1765 static int
1766 bwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
1767         const struct ieee80211_bpf_params *params)
1768 {
1769         struct ieee80211com *ic = ni->ni_ic;
1770         struct bwn_softc *sc = ic->ic_softc;
1771         struct bwn_mac *mac = sc->sc_curmac;
1772         int error;
1773
1774         if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0 ||
1775             mac->mac_status < BWN_MAC_STATUS_STARTED) {
1776                 m_freem(m);
1777                 return (ENETDOWN);
1778         }
1779
1780         BWN_LOCK(sc);
1781         if (bwn_tx_isfull(sc, m)) {
1782                 m_freem(m);
1783                 BWN_UNLOCK(sc);
1784                 return (ENOBUFS);
1785         }
1786
1787         error = bwn_tx_start(sc, ni, m);
1788         if (error == 0)
1789                 sc->sc_watchdog_timer = 5;
1790         BWN_UNLOCK(sc);
1791         return (error);
1792 }
1793
1794 /*
1795  * Callback from the 802.11 layer to update the slot time
1796  * based on the current setting.  We use it to notify the
1797  * firmware of ERP changes and the f/w takes care of things
1798  * like slot time and preamble.
1799  */
1800 static void
1801 bwn_updateslot(struct ieee80211com *ic)
1802 {
1803         struct bwn_softc *sc = ic->ic_softc;
1804         struct bwn_mac *mac;
1805
1806         BWN_LOCK(sc);
1807         if (sc->sc_flags & BWN_FLAG_RUNNING) {
1808                 mac = (struct bwn_mac *)sc->sc_curmac;
1809                 bwn_set_slot_time(mac, IEEE80211_GET_SLOTTIME(ic));
1810         }
1811         BWN_UNLOCK(sc);
1812 }
1813
1814 /*
1815  * Callback from the 802.11 layer after a promiscuous mode change.
1816  * Note this interface does not check the operating mode as this
1817  * is an internal callback and we are expected to honor the current
1818  * state (e.g. this is used for setting the interface in promiscuous
1819  * mode when operating in hostap mode to do ACS).
1820  */
1821 static void
1822 bwn_update_promisc(struct ieee80211com *ic)
1823 {
1824         struct bwn_softc *sc = ic->ic_softc;
1825         struct bwn_mac *mac = sc->sc_curmac;
1826
1827         BWN_LOCK(sc);
1828         mac = sc->sc_curmac;
1829         if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
1830                 if (ic->ic_promisc > 0)
1831                         sc->sc_filters |= BWN_MACCTL_PROMISC;
1832                 else
1833                         sc->sc_filters &= ~BWN_MACCTL_PROMISC;
1834                 bwn_set_opmode(mac);
1835         }
1836         BWN_UNLOCK(sc);
1837 }
1838
1839 /*
1840  * Callback from the 802.11 layer to update WME parameters.
1841  */
1842 static int
1843 bwn_wme_update(struct ieee80211com *ic)
1844 {
1845         struct bwn_softc *sc = ic->ic_softc;
1846         struct bwn_mac *mac = sc->sc_curmac;
1847         struct wmeParams *wmep;
1848         int i;
1849
1850         BWN_LOCK(sc);
1851         mac = sc->sc_curmac;
1852         if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
1853                 bwn_mac_suspend(mac);
1854                 for (i = 0; i < N(sc->sc_wmeParams); i++) {
1855                         wmep = &ic->ic_wme.wme_chanParams.cap_wmeParams[i];
1856                         bwn_wme_loadparams(mac, wmep, bwn_wme_shm_offsets[i]);
1857                 }
1858                 bwn_mac_enable(mac);
1859         }
1860         BWN_UNLOCK(sc);
1861         return (0);
1862 }
1863
1864 static void
1865 bwn_scan_start(struct ieee80211com *ic)
1866 {
1867         struct bwn_softc *sc = ic->ic_softc;
1868         struct bwn_mac *mac;
1869
1870         BWN_LOCK(sc);
1871         mac = sc->sc_curmac;
1872         if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
1873                 sc->sc_filters |= BWN_MACCTL_BEACON_PROMISC;
1874                 bwn_set_opmode(mac);
1875                 /* disable CFP update during scan */
1876                 bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_SKIP_CFP_UPDATE);
1877         }
1878         BWN_UNLOCK(sc);
1879 }
1880
1881 static void
1882 bwn_scan_end(struct ieee80211com *ic)
1883 {
1884         struct bwn_softc *sc = ic->ic_softc;
1885         struct bwn_mac *mac;
1886
1887         BWN_LOCK(sc);
1888         mac = sc->sc_curmac;
1889         if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
1890                 sc->sc_filters &= ~BWN_MACCTL_BEACON_PROMISC;
1891                 bwn_set_opmode(mac);
1892                 bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_SKIP_CFP_UPDATE);
1893         }
1894         BWN_UNLOCK(sc);
1895 }
1896
1897 static void
1898 bwn_set_channel(struct ieee80211com *ic)
1899 {
1900         struct bwn_softc *sc = ic->ic_softc;
1901         struct bwn_mac *mac = sc->sc_curmac;
1902         struct bwn_phy *phy = &mac->mac_phy;
1903         int chan, error;
1904
1905         BWN_LOCK(sc);
1906
1907         error = bwn_switch_band(sc, ic->ic_curchan);
1908         if (error)
1909                 goto fail;
1910         bwn_mac_suspend(mac);
1911         bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
1912         chan = ieee80211_chan2ieee(ic, ic->ic_curchan);
1913         if (chan != phy->chan)
1914                 bwn_switch_channel(mac, chan);
1915
1916         /* TX power level */
1917         if (ic->ic_curchan->ic_maxpower != 0 &&
1918             ic->ic_curchan->ic_maxpower != phy->txpower) {
1919                 phy->txpower = ic->ic_curchan->ic_maxpower / 2;
1920                 bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME |
1921                     BWN_TXPWR_IGNORE_TSSI);
1922         }
1923
1924         bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
1925         if (phy->set_antenna)
1926                 phy->set_antenna(mac, BWN_ANT_DEFAULT);
1927
1928         if (sc->sc_rf_enabled != phy->rf_on) {
1929                 if (sc->sc_rf_enabled) {
1930                         bwn_rf_turnon(mac);
1931                         if (!(mac->mac_flags & BWN_MAC_FLAG_RADIO_ON))
1932                                 device_printf(sc->sc_dev,
1933                                     "please turn on the RF switch\n");
1934                 } else
1935                         bwn_rf_turnoff(mac);
1936         }
1937
1938         bwn_mac_enable(mac);
1939
1940 fail:
1941         /*
1942          * Setup radio tap channel freq and flags
1943          */
1944         sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq =
1945                 htole16(ic->ic_curchan->ic_freq);
1946         sc->sc_tx_th.wt_chan_flags = sc->sc_rx_th.wr_chan_flags =
1947                 htole16(ic->ic_curchan->ic_flags & 0xffff);
1948
1949         BWN_UNLOCK(sc);
1950 }
1951
1952 static struct ieee80211vap *
1953 bwn_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
1954     enum ieee80211_opmode opmode, int flags,
1955     const uint8_t bssid[IEEE80211_ADDR_LEN],
1956     const uint8_t mac[IEEE80211_ADDR_LEN])
1957 {
1958         struct ieee80211vap *vap;
1959         struct bwn_vap *bvp;
1960
1961         switch (opmode) {
1962         case IEEE80211_M_HOSTAP:
1963         case IEEE80211_M_MBSS:
1964         case IEEE80211_M_STA:
1965         case IEEE80211_M_WDS:
1966         case IEEE80211_M_MONITOR:
1967         case IEEE80211_M_IBSS:
1968         case IEEE80211_M_AHDEMO:
1969                 break;
1970         default:
1971                 return (NULL);
1972         }
1973
1974         bvp = kmalloc(sizeof(struct bwn_vap), M_80211_VAP, M_WAITOK | M_ZERO);
1975         vap = &bvp->bv_vap;
1976         ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid);
1977         /* override with driver methods */
1978         bvp->bv_newstate = vap->iv_newstate;
1979         vap->iv_newstate = bwn_newstate;
1980
1981         /* override max aid so sta's cannot assoc when we're out of sta id's */
1982         vap->iv_max_aid = BWN_STAID_MAX;
1983
1984         ieee80211_ratectl_init(vap);
1985
1986         /* complete setup */
1987         ieee80211_vap_attach(vap, ieee80211_media_change,
1988             ieee80211_media_status, mac);
1989         return (vap);
1990 }
1991
1992 static void
1993 bwn_vap_delete(struct ieee80211vap *vap)
1994 {
1995         struct bwn_vap *bvp = BWN_VAP(vap);
1996
1997         ieee80211_ratectl_deinit(vap);
1998         ieee80211_vap_detach(vap);
1999         kfree(bvp, M_80211_VAP);
2000 }
2001
2002 static int
2003 bwn_init(struct bwn_softc *sc)
2004 {
2005         struct bwn_mac *mac;
2006         int error;
2007
2008         BWN_ASSERT_LOCKED(sc);
2009
2010         DPRINTF(sc, BWN_DEBUG_RESET, "%s: called\n", __func__);
2011
2012         bzero(sc->sc_bssid, IEEE80211_ADDR_LEN);
2013         sc->sc_flags |= BWN_FLAG_NEED_BEACON_TP;
2014         sc->sc_filters = 0;
2015         bwn_wme_clear(sc);
2016         sc->sc_beacons[0] = sc->sc_beacons[1] = 0;
2017         sc->sc_rf_enabled = 1;
2018
2019         mac = sc->sc_curmac;
2020         if (mac->mac_status == BWN_MAC_STATUS_UNINIT) {
2021                 error = bwn_core_init(mac);
2022                 if (error != 0)
2023                         return (error);
2024         }
2025         if (mac->mac_status == BWN_MAC_STATUS_INITED)
2026                 bwn_core_start(mac);
2027
2028         bwn_set_opmode(mac);
2029         bwn_set_pretbtt(mac);
2030         bwn_spu_setdelay(mac, 0);
2031         bwn_set_macaddr(mac);
2032
2033         sc->sc_flags |= BWN_FLAG_RUNNING;
2034         callout_reset(&sc->sc_rfswitch_ch, hz, bwn_rfswitch, sc);
2035         callout_reset(&sc->sc_watchdog_ch, hz, bwn_watchdog, sc);
2036
2037         return (0);
2038 }
2039
2040 static void
2041 bwn_stop(struct bwn_softc *sc)
2042 {
2043         struct bwn_mac *mac = sc->sc_curmac;
2044
2045         BWN_ASSERT_LOCKED(sc);
2046
2047         DPRINTF(sc, BWN_DEBUG_RESET, "%s: called\n", __func__);
2048
2049         if (mac->mac_status >= BWN_MAC_STATUS_INITED) {
2050                 /* XXX FIXME opmode not based on VAP */
2051                 bwn_set_opmode(mac);
2052                 bwn_set_macaddr(mac);
2053         }
2054
2055         if (mac->mac_status >= BWN_MAC_STATUS_STARTED)
2056                 bwn_core_stop(mac);
2057
2058         callout_stop(&sc->sc_led_blink_ch);
2059         sc->sc_led_blinking = 0;
2060
2061         bwn_core_exit(mac);
2062         sc->sc_rf_enabled = 0;
2063
2064         sc->sc_flags &= ~BWN_FLAG_RUNNING;
2065 }
2066
2067 static void
2068 bwn_wme_clear(struct bwn_softc *sc)
2069 {
2070 #define MS(_v, _f)      (((_v) & _f) >> _f##_S)
2071         struct wmeParams *p;
2072         unsigned int i;
2073
2074         KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
2075             ("%s:%d: fail", __func__, __LINE__));
2076
2077         for (i = 0; i < N(sc->sc_wmeParams); i++) {
2078                 p = &(sc->sc_wmeParams[i]);
2079
2080                 switch (bwn_wme_shm_offsets[i]) {
2081                 case BWN_WME_VOICE:
2082                         p->wmep_txopLimit = 0;
2083                         p->wmep_aifsn = 2;
2084                         /* XXX FIXME: log2(cwmin) */
2085                         p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
2086                         p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
2087                         break;
2088                 case BWN_WME_VIDEO:
2089                         p->wmep_txopLimit = 0;
2090                         p->wmep_aifsn = 2;
2091                         /* XXX FIXME: log2(cwmin) */
2092                         p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
2093                         p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
2094                         break;
2095                 case BWN_WME_BESTEFFORT:
2096                         p->wmep_txopLimit = 0;
2097                         p->wmep_aifsn = 3;
2098                         /* XXX FIXME: log2(cwmin) */
2099                         p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
2100                         p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
2101                         break;
2102                 case BWN_WME_BACKGROUND:
2103                         p->wmep_txopLimit = 0;
2104                         p->wmep_aifsn = 7;
2105                         /* XXX FIXME: log2(cwmin) */
2106                         p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
2107                         p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
2108                         break;
2109                 default:
2110                         KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
2111                 }
2112         }
2113 }
2114
2115 static int
2116 bwn_core_init(struct bwn_mac *mac)
2117 {
2118         struct bwn_softc *sc = mac->mac_sc;
2119         uint64_t hf;
2120         int error;
2121
2122         KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
2123             ("%s:%d: fail", __func__, __LINE__));
2124
2125         siba_powerup(sc->sc_dev, 0);
2126         if (!siba_dev_isup(sc->sc_dev))
2127                 bwn_reset_core(mac, mac->mac_phy.gmode);
2128
2129         mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
2130         mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
2131         mac->mac_phy.hwpctl = (bwn_hwpctl) ? 1 : 0;
2132         BWN_GETTIME(mac->mac_phy.nexttime);
2133         mac->mac_phy.txerrors = BWN_TXERROR_MAX;
2134         bzero(&mac->mac_stats, sizeof(mac->mac_stats));
2135         mac->mac_stats.link_noise = -95;
2136         mac->mac_reason_intr = 0;
2137         bzero(mac->mac_reason, sizeof(mac->mac_reason));
2138         mac->mac_intr_mask = BWN_INTR_MASKTEMPLATE;
2139 #ifdef BWN_DEBUG
2140         if (sc->sc_debug & BWN_DEBUG_XMIT)
2141                 mac->mac_intr_mask &= ~BWN_INTR_PHY_TXERR;
2142 #endif
2143         mac->mac_suspended = 1;
2144         mac->mac_task_state = 0;
2145         memset(&mac->mac_noise, 0, sizeof(mac->mac_noise));
2146
2147         mac->mac_phy.init_pre(mac);
2148
2149         siba_pcicore_intr(sc->sc_dev);
2150
2151         siba_fix_imcfglobug(sc->sc_dev);
2152         bwn_bt_disable(mac);
2153         if (mac->mac_phy.prepare_hw) {
2154                 error = mac->mac_phy.prepare_hw(mac);
2155                 if (error)
2156                         goto fail0;
2157         }
2158         error = bwn_chip_init(mac);
2159         if (error)
2160                 goto fail0;
2161         bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_COREREV,
2162             siba_get_revid(sc->sc_dev));
2163         hf = bwn_hf_read(mac);
2164         if (mac->mac_phy.type == BWN_PHYTYPE_G) {
2165                 hf |= BWN_HF_GPHY_SYM_WORKAROUND;
2166                 if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
2167                         hf |= BWN_HF_PAGAINBOOST_OFDM_ON;
2168                 if (mac->mac_phy.rev == 1)
2169                         hf |= BWN_HF_GPHY_DC_CANCELFILTER;
2170         }
2171         if (mac->mac_phy.rf_ver == 0x2050) {
2172                 if (mac->mac_phy.rf_rev < 6)
2173                         hf |= BWN_HF_FORCE_VCO_RECALC;
2174                 if (mac->mac_phy.rf_rev == 6)
2175                         hf |= BWN_HF_4318_TSSI;
2176         }
2177         if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW)
2178                 hf |= BWN_HF_SLOWCLOCK_REQ_OFF;
2179         if ((siba_get_type(sc->sc_dev) == SIBA_TYPE_PCI) &&
2180             (siba_get_pcicore_revid(sc->sc_dev) <= 10))
2181                 hf |= BWN_HF_PCI_SLOWCLOCK_WORKAROUND;
2182         hf &= ~BWN_HF_SKIP_CFP_UPDATE;
2183         bwn_hf_write(mac, hf);
2184
2185         bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
2186         bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SHORT_RETRY_FALLBACK, 3);
2187         bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_LONG_RETRY_FALLBACK, 2);
2188         bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_MAXTIME, 1);
2189
2190         bwn_rate_init(mac);
2191         bwn_set_phytxctl(mac);
2192
2193         bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MIN,
2194             (mac->mac_phy.type == BWN_PHYTYPE_B) ? 0x1f : 0xf);
2195         bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MAX, 0x3ff);
2196
2197         if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
2198                 bwn_pio_init(mac);
2199         else
2200                 bwn_dma_init(mac);
2201         bwn_wme_init(mac);
2202         bwn_spu_setdelay(mac, 1);
2203         bwn_bt_enable(mac);
2204
2205         siba_powerup(sc->sc_dev,
2206             !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW));
2207         bwn_set_macaddr(mac);
2208         bwn_crypt_init(mac);
2209
2210         /* XXX LED initializatin */
2211
2212         mac->mac_status = BWN_MAC_STATUS_INITED;
2213
2214         return (error);
2215
2216 fail0:
2217         siba_powerdown(sc->sc_dev);
2218         KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
2219             ("%s:%d: fail", __func__, __LINE__));
2220         return (error);
2221 }
2222
2223 static void
2224 bwn_core_start(struct bwn_mac *mac)
2225 {
2226         struct bwn_softc *sc = mac->mac_sc;
2227         uint32_t tmp;
2228
2229         KASSERT(mac->mac_status == BWN_MAC_STATUS_INITED,
2230             ("%s:%d: fail", __func__, __LINE__));
2231
2232         if (siba_get_revid(sc->sc_dev) < 5)
2233                 return;
2234
2235         while (1) {
2236                 tmp = BWN_READ_4(mac, BWN_XMITSTAT_0);
2237                 if (!(tmp & 0x00000001))
2238                         break;
2239                 tmp = BWN_READ_4(mac, BWN_XMITSTAT_1);
2240         }
2241
2242         bwn_mac_enable(mac);
2243         BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
2244         callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
2245
2246         mac->mac_status = BWN_MAC_STATUS_STARTED;
2247 }
2248
2249 static void
2250 bwn_core_exit(struct bwn_mac *mac)
2251 {
2252         struct bwn_softc *sc = mac->mac_sc;
2253         uint32_t macctl;
2254
2255         BWN_ASSERT_LOCKED(mac->mac_sc);
2256
2257         KASSERT(mac->mac_status <= BWN_MAC_STATUS_INITED,
2258             ("%s:%d: fail", __func__, __LINE__));
2259
2260         if (mac->mac_status != BWN_MAC_STATUS_INITED)
2261                 return;
2262         mac->mac_status = BWN_MAC_STATUS_UNINIT;
2263
2264         macctl = BWN_READ_4(mac, BWN_MACCTL);
2265         macctl &= ~BWN_MACCTL_MCODE_RUN;
2266         macctl |= BWN_MACCTL_MCODE_JMP0;
2267         BWN_WRITE_4(mac, BWN_MACCTL, macctl);
2268
2269         bwn_dma_stop(mac);
2270         bwn_pio_stop(mac);
2271         bwn_chip_exit(mac);
2272         mac->mac_phy.switch_analog(mac, 0);
2273         siba_dev_down(sc->sc_dev, 0);
2274         siba_powerdown(sc->sc_dev);
2275 }
2276
2277 static void
2278 bwn_bt_disable(struct bwn_mac *mac)
2279 {
2280         struct bwn_softc *sc = mac->mac_sc;
2281
2282         (void)sc;
2283         /* XXX do nothing yet */
2284 }
2285
2286 static int
2287 bwn_chip_init(struct bwn_mac *mac)
2288 {
2289         struct bwn_softc *sc = mac->mac_sc;
2290         struct bwn_phy *phy = &mac->mac_phy;
2291         uint32_t macctl;
2292         int error;
2293
2294         macctl = BWN_MACCTL_IHR_ON | BWN_MACCTL_SHM_ON | BWN_MACCTL_STA;
2295         if (phy->gmode)
2296                 macctl |= BWN_MACCTL_GMODE;
2297         BWN_WRITE_4(mac, BWN_MACCTL, macctl);
2298
2299         error = bwn_fw_fillinfo(mac);
2300         if (error)
2301                 return (error);
2302         error = bwn_fw_loaducode(mac);
2303         if (error)
2304                 return (error);
2305
2306         error = bwn_gpio_init(mac);
2307         if (error)
2308                 return (error);
2309
2310         error = bwn_fw_loadinitvals(mac);
2311         if (error) {
2312                 siba_gpio_set(sc->sc_dev, 0);
2313                 return (error);
2314         }
2315         phy->switch_analog(mac, 1);
2316         error = bwn_phy_init(mac);
2317         if (error) {
2318                 siba_gpio_set(sc->sc_dev, 0);
2319                 return (error);
2320         }
2321         if (phy->set_im)
2322                 phy->set_im(mac, BWN_IMMODE_NONE);
2323         if (phy->set_antenna)
2324                 phy->set_antenna(mac, BWN_ANT_DEFAULT);
2325         bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
2326
2327         if (phy->type == BWN_PHYTYPE_B)
2328                 BWN_WRITE_2(mac, 0x005e, BWN_READ_2(mac, 0x005e) | 0x0004);
2329         BWN_WRITE_4(mac, 0x0100, 0x01000000);
2330         if (siba_get_revid(sc->sc_dev) < 5)
2331                 BWN_WRITE_4(mac, 0x010c, 0x01000000);
2332
2333         BWN_WRITE_4(mac, BWN_MACCTL,
2334             BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_STA);
2335         BWN_WRITE_4(mac, BWN_MACCTL,
2336             BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_STA);
2337         bwn_shm_write_2(mac, BWN_SHARED, 0x0074, 0x0000);
2338
2339         bwn_set_opmode(mac);
2340         if (siba_get_revid(sc->sc_dev) < 3) {
2341                 BWN_WRITE_2(mac, 0x060e, 0x0000);
2342                 BWN_WRITE_2(mac, 0x0610, 0x8000);
2343                 BWN_WRITE_2(mac, 0x0604, 0x0000);
2344                 BWN_WRITE_2(mac, 0x0606, 0x0200);
2345         } else {
2346                 BWN_WRITE_4(mac, 0x0188, 0x80000000);
2347                 BWN_WRITE_4(mac, 0x018c, 0x02000000);
2348         }
2349         BWN_WRITE_4(mac, BWN_INTR_REASON, 0x00004000);
2350         BWN_WRITE_4(mac, BWN_DMA0_INTR_MASK, 0x0001fc00);
2351         BWN_WRITE_4(mac, BWN_DMA1_INTR_MASK, 0x0000dc00);
2352         BWN_WRITE_4(mac, BWN_DMA2_INTR_MASK, 0x0000dc00);
2353         BWN_WRITE_4(mac, BWN_DMA3_INTR_MASK, 0x0001dc00);
2354         BWN_WRITE_4(mac, BWN_DMA4_INTR_MASK, 0x0000dc00);
2355         BWN_WRITE_4(mac, BWN_DMA5_INTR_MASK, 0x0000dc00);
2356
2357         bwn_mac_phy_clock_set(mac, TRUE);
2358
2359         /* SIBA powerup */
2360         /* XXX TODO: BCMA powerup */
2361         BWN_WRITE_2(mac, BWN_POWERUP_DELAY, siba_get_cc_powerdelay(sc->sc_dev));
2362         return (error);
2363 }
2364
2365 /* read hostflags */
2366 uint64_t
2367 bwn_hf_read(struct bwn_mac *mac)
2368 {
2369         uint64_t ret;
2370
2371         ret = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFHI);
2372         ret <<= 16;
2373         ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFMI);
2374         ret <<= 16;
2375         ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO);
2376         return (ret);
2377 }
2378
2379 void
2380 bwn_hf_write(struct bwn_mac *mac, uint64_t value)
2381 {
2382
2383         bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFLO,
2384             (value & 0x00000000ffffull));
2385         bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFMI,
2386             (value & 0x0000ffff0000ull) >> 16);
2387         bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFHI,
2388             (value & 0xffff00000000ULL) >> 32);
2389 }
2390
2391 static void
2392 bwn_set_txretry(struct bwn_mac *mac, int s, int l)
2393 {
2394
2395         bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_SHORT_RETRY, MIN(s, 0xf));
2396         bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_LONG_RETRY, MIN(l, 0xf));
2397 }
2398
2399 static void
2400 bwn_rate_init(struct bwn_mac *mac)
2401 {
2402
2403         switch (mac->mac_phy.type) {
2404         case BWN_PHYTYPE_A:
2405         case BWN_PHYTYPE_G:
2406         case BWN_PHYTYPE_LP:
2407         case BWN_PHYTYPE_N:
2408                 bwn_rate_write(mac, BWN_OFDM_RATE_6MB, 1);
2409                 bwn_rate_write(mac, BWN_OFDM_RATE_12MB, 1);
2410                 bwn_rate_write(mac, BWN_OFDM_RATE_18MB, 1);
2411                 bwn_rate_write(mac, BWN_OFDM_RATE_24MB, 1);
2412                 bwn_rate_write(mac, BWN_OFDM_RATE_36MB, 1);
2413                 bwn_rate_write(mac, BWN_OFDM_RATE_48MB, 1);
2414                 bwn_rate_write(mac, BWN_OFDM_RATE_54MB, 1);
2415                 if (mac->mac_phy.type == BWN_PHYTYPE_A)
2416                         break;
2417                 /* FALLTHROUGH */
2418         case BWN_PHYTYPE_B:
2419                 bwn_rate_write(mac, BWN_CCK_RATE_1MB, 0);
2420                 bwn_rate_write(mac, BWN_CCK_RATE_2MB, 0);
2421                 bwn_rate_write(mac, BWN_CCK_RATE_5MB, 0);
2422                 bwn_rate_write(mac, BWN_CCK_RATE_11MB, 0);
2423                 break;
2424         default:
2425                 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
2426         }
2427 }
2428
2429 static void
2430 bwn_rate_write(struct bwn_mac *mac, uint16_t rate, int ofdm)
2431 {
2432         uint16_t offset;
2433
2434         if (ofdm) {
2435                 offset = 0x480;
2436                 offset += (bwn_plcp_getofdm(rate) & 0x000f) * 2;
2437         } else {
2438                 offset = 0x4c0;
2439                 offset += (bwn_plcp_getcck(rate) & 0x000f) * 2;
2440         }
2441         bwn_shm_write_2(mac, BWN_SHARED, offset + 0x20,
2442             bwn_shm_read_2(mac, BWN_SHARED, offset));
2443 }
2444
2445 static uint8_t
2446 bwn_plcp_getcck(const uint8_t bitrate)
2447 {
2448
2449         switch (bitrate) {
2450         case BWN_CCK_RATE_1MB:
2451                 return (0x0a);
2452         case BWN_CCK_RATE_2MB:
2453                 return (0x14);
2454         case BWN_CCK_RATE_5MB:
2455                 return (0x37);
2456         case BWN_CCK_RATE_11MB:
2457                 return (0x6e);
2458         }
2459         KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
2460         return (0);
2461 }
2462
2463 static uint8_t
2464 bwn_plcp_getofdm(const uint8_t bitrate)
2465 {
2466
2467         switch (bitrate) {
2468         case BWN_OFDM_RATE_6MB:
2469                 return (0xb);
2470         case BWN_OFDM_RATE_9MB:
2471                 return (0xf);
2472         case BWN_OFDM_RATE_12MB:
2473                 return (0xa);
2474         case BWN_OFDM_RATE_18MB:
2475                 return (0xe);
2476         case BWN_OFDM_RATE_24MB:
2477                 return (0x9);
2478         case BWN_OFDM_RATE_36MB:
2479                 return (0xd);
2480         case BWN_OFDM_RATE_48MB:
2481                 return (0x8);
2482         case BWN_OFDM_RATE_54MB:
2483                 return (0xc);
2484         }
2485         KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
2486         return (0);
2487 }
2488
2489 static void
2490 bwn_set_phytxctl(struct bwn_mac *mac)
2491 {
2492         uint16_t ctl;
2493
2494         ctl = (BWN_TX_PHY_ENC_CCK | BWN_TX_PHY_ANT01AUTO |
2495             BWN_TX_PHY_TXPWR);
2496         bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_BEACON_PHYCTL, ctl);
2497         bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, ctl);
2498         bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, ctl);
2499 }
2500
2501 static void
2502 bwn_pio_init(struct bwn_mac *mac)
2503 {
2504         struct bwn_pio *pio = &mac->mac_method.pio;
2505
2506         BWN_WRITE_4(mac, BWN_MACCTL, BWN_READ_4(mac, BWN_MACCTL)
2507             & ~BWN_MACCTL_BIGENDIAN);
2508         bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RX_PADOFFSET, 0);
2509
2510         bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BK], 0);
2511         bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BE], 1);
2512         bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VI], 2);
2513         bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VO], 3);
2514         bwn_pio_set_txqueue(mac, &pio->mcast, 4);
2515         bwn_pio_setupqueue_rx(mac, &pio->rx, 0);
2516 }
2517
2518 static void
2519 bwn_pio_set_txqueue(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
2520     int index)
2521 {
2522         struct bwn_pio_txpkt *tp;
2523         struct bwn_softc *sc = mac->mac_sc;
2524         unsigned int i;
2525
2526         tq->tq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_TXQOFFSET(mac);
2527         tq->tq_index = index;
2528
2529         tq->tq_free = BWN_PIO_MAX_TXPACKETS;
2530         if (siba_get_revid(sc->sc_dev) >= 8)
2531                 tq->tq_size = 1920;
2532         else {
2533                 tq->tq_size = bwn_pio_read_2(mac, tq, BWN_PIO_TXQBUFSIZE);
2534                 tq->tq_size -= 80;
2535         }
2536
2537         TAILQ_INIT(&tq->tq_pktlist);
2538         for (i = 0; i < N(tq->tq_pkts); i++) {
2539                 tp = &(tq->tq_pkts[i]);
2540                 tp->tp_index = i;
2541                 tp->tp_queue = tq;
2542                 TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
2543         }
2544 }
2545
2546 static uint16_t
2547 bwn_pio_idx2base(struct bwn_mac *mac, int index)
2548 {
2549         struct bwn_softc *sc = mac->mac_sc;
2550         static const uint16_t bases[] = {
2551                 BWN_PIO_BASE0,
2552                 BWN_PIO_BASE1,
2553                 BWN_PIO_BASE2,
2554                 BWN_PIO_BASE3,
2555                 BWN_PIO_BASE4,
2556                 BWN_PIO_BASE5,
2557                 BWN_PIO_BASE6,
2558                 BWN_PIO_BASE7,
2559         };
2560         static const uint16_t bases_rev11[] = {
2561                 BWN_PIO11_BASE0,
2562                 BWN_PIO11_BASE1,
2563                 BWN_PIO11_BASE2,
2564                 BWN_PIO11_BASE3,
2565                 BWN_PIO11_BASE4,
2566                 BWN_PIO11_BASE5,
2567         };
2568
2569         if (siba_get_revid(sc->sc_dev) >= 11) {
2570                 if (index >= N(bases_rev11))
2571                         device_printf(sc->sc_dev, "%s: warning\n", __func__);
2572                 return (bases_rev11[index]);
2573         }
2574         if (index >= N(bases))
2575                 device_printf(sc->sc_dev, "%s: warning\n", __func__);
2576         return (bases[index]);
2577 }
2578
2579 static void
2580 bwn_pio_setupqueue_rx(struct bwn_mac *mac, struct bwn_pio_rxqueue *prq,
2581     int index)
2582 {
2583         struct bwn_softc *sc = mac->mac_sc;
2584
2585         prq->prq_mac = mac;
2586         prq->prq_rev = siba_get_revid(sc->sc_dev);
2587         prq->prq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_RXQOFFSET(mac);
2588         bwn_dma_rxdirectfifo(mac, index, 1);
2589 }
2590
2591 static void
2592 bwn_destroy_pioqueue_tx(struct bwn_pio_txqueue *tq)
2593 {
2594         if (tq == NULL)
2595                 return;
2596         bwn_pio_cancel_tx_packets(tq);
2597 }
2598
2599 static void
2600 bwn_destroy_queue_tx(struct bwn_pio_txqueue *pio)
2601 {
2602
2603         bwn_destroy_pioqueue_tx(pio);
2604 }
2605
2606 static uint16_t
2607 bwn_pio_read_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
2608     uint16_t offset)
2609 {
2610
2611         return (BWN_READ_2(mac, tq->tq_base + offset));
2612 }
2613
2614 static void
2615 bwn_dma_rxdirectfifo(struct bwn_mac *mac, int idx, uint8_t enable)
2616 {
2617         uint32_t ctl;
2618         int type;
2619         uint16_t base;
2620
2621         type = bwn_dma_mask2type(bwn_dma_mask(mac));
2622         base = bwn_dma_base(type, idx);
2623         if (type == BWN_DMA_64BIT) {
2624                 ctl = BWN_READ_4(mac, base + BWN_DMA64_RXCTL);
2625                 ctl &= ~BWN_DMA64_RXDIRECTFIFO;
2626                 if (enable)
2627                         ctl |= BWN_DMA64_RXDIRECTFIFO;
2628                 BWN_WRITE_4(mac, base + BWN_DMA64_RXCTL, ctl);
2629         } else {
2630                 ctl = BWN_READ_4(mac, base + BWN_DMA32_RXCTL);
2631                 ctl &= ~BWN_DMA32_RXDIRECTFIFO;
2632                 if (enable)
2633                         ctl |= BWN_DMA32_RXDIRECTFIFO;
2634                 BWN_WRITE_4(mac, base + BWN_DMA32_RXCTL, ctl);
2635         }
2636 }
2637
2638 static uint64_t
2639 bwn_dma_mask(struct bwn_mac *mac)
2640 {
2641         uint32_t tmp;
2642         uint16_t base;
2643
2644         tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
2645         if (tmp & SIBA_TGSHIGH_DMA64)
2646                 return (BWN_DMA_BIT_MASK(64));
2647         base = bwn_dma_base(0, 0);
2648         BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
2649         tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
2650         if (tmp & BWN_DMA32_TXADDREXT_MASK)
2651                 return (BWN_DMA_BIT_MASK(32));
2652
2653         return (BWN_DMA_BIT_MASK(30));
2654 }
2655
2656 static int
2657 bwn_dma_mask2type(uint64_t dmamask)
2658 {
2659
2660         if (dmamask == BWN_DMA_BIT_MASK(30))
2661                 return (BWN_DMA_30BIT);
2662         if (dmamask == BWN_DMA_BIT_MASK(32))
2663                 return (BWN_DMA_32BIT);
2664         if (dmamask == BWN_DMA_BIT_MASK(64))
2665                 return (BWN_DMA_64BIT);
2666         KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
2667         return (BWN_DMA_30BIT);
2668 }
2669
2670 static void
2671 bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *tq)
2672 {
2673         struct bwn_pio_txpkt *tp;
2674         unsigned int i;
2675
2676         for (i = 0; i < N(tq->tq_pkts); i++) {
2677                 tp = &(tq->tq_pkts[i]);
2678                 if (tp->tp_m) {
2679                         m_freem(tp->tp_m);
2680                         tp->tp_m = NULL;
2681                 }
2682         }
2683 }
2684
2685 static uint16_t
2686 bwn_dma_base(int type, int controller_idx)
2687 {
2688         static const uint16_t map64[] = {
2689                 BWN_DMA64_BASE0,
2690                 BWN_DMA64_BASE1,
2691                 BWN_DMA64_BASE2,
2692                 BWN_DMA64_BASE3,
2693                 BWN_DMA64_BASE4,
2694                 BWN_DMA64_BASE5,
2695         };
2696         static const uint16_t map32[] = {
2697                 BWN_DMA32_BASE0,
2698                 BWN_DMA32_BASE1,
2699                 BWN_DMA32_BASE2,
2700                 BWN_DMA32_BASE3,
2701                 BWN_DMA32_BASE4,
2702                 BWN_DMA32_BASE5,
2703         };
2704
2705         if (type == BWN_DMA_64BIT) {
2706                 KASSERT(controller_idx >= 0 && controller_idx < N(map64),
2707                     ("%s:%d: fail", __func__, __LINE__));
2708                 return (map64[controller_idx]);
2709         }
2710         KASSERT(controller_idx >= 0 && controller_idx < N(map32),
2711             ("%s:%d: fail", __func__, __LINE__));
2712         return (map32[controller_idx]);
2713 }
2714
2715 static void
2716 bwn_dma_init(struct bwn_mac *mac)
2717 {
2718         struct bwn_dma *dma = &mac->mac_method.dma;
2719
2720         /* setup TX DMA channels. */
2721         bwn_dma_setup(dma->wme[WME_AC_BK]);
2722         bwn_dma_setup(dma->wme[WME_AC_BE]);
2723         bwn_dma_setup(dma->wme[WME_AC_VI]);
2724         bwn_dma_setup(dma->wme[WME_AC_VO]);
2725         bwn_dma_setup(dma->mcast);
2726         /* setup RX DMA channel. */
2727         bwn_dma_setup(dma->rx);
2728 }
2729
2730 static struct bwn_dma_ring *
2731 bwn_dma_ringsetup(struct bwn_mac *mac, int controller_index,
2732     int for_tx, int type)
2733 {
2734         struct bwn_dma *dma = &mac->mac_method.dma;
2735         struct bwn_dma_ring *dr;
2736         struct bwn_dmadesc_generic *desc;
2737         struct bwn_dmadesc_meta *mt;
2738         struct bwn_softc *sc = mac->mac_sc;
2739         int error, i;
2740
2741         dr = kmalloc(sizeof(*dr), M_DEVBUF, M_INTWAIT | M_ZERO);
2742         if (dr == NULL)
2743                 goto out;
2744         dr->dr_numslots = BWN_RXRING_SLOTS;
2745         if (for_tx)
2746                 dr->dr_numslots = BWN_TXRING_SLOTS;
2747
2748         dr->dr_meta = kmalloc(dr->dr_numslots * sizeof(struct bwn_dmadesc_meta),
2749             M_DEVBUF, M_INTWAIT | M_ZERO);
2750         if (dr->dr_meta == NULL)
2751                 goto fail0;
2752
2753         dr->dr_type = type;
2754         dr->dr_mac = mac;
2755         dr->dr_base = bwn_dma_base(type, controller_index);
2756         dr->dr_index = controller_index;
2757         if (type == BWN_DMA_64BIT) {
2758                 dr->getdesc = bwn_dma_64_getdesc;
2759                 dr->setdesc = bwn_dma_64_setdesc;
2760                 dr->start_transfer = bwn_dma_64_start_transfer;
2761                 dr->suspend = bwn_dma_64_suspend;
2762                 dr->resume = bwn_dma_64_resume;
2763                 dr->get_curslot = bwn_dma_64_get_curslot;
2764                 dr->set_curslot = bwn_dma_64_set_curslot;
2765         } else {
2766                 dr->getdesc = bwn_dma_32_getdesc;
2767                 dr->setdesc = bwn_dma_32_setdesc;
2768                 dr->start_transfer = bwn_dma_32_start_transfer;
2769                 dr->suspend = bwn_dma_32_suspend;
2770                 dr->resume = bwn_dma_32_resume;
2771                 dr->get_curslot = bwn_dma_32_get_curslot;
2772                 dr->set_curslot = bwn_dma_32_set_curslot;
2773         }
2774         if (for_tx) {
2775                 dr->dr_tx = 1;
2776                 dr->dr_curslot = -1;
2777         } else {
2778                 if (dr->dr_index == 0) {
2779                         dr->dr_rx_bufsize = BWN_DMA0_RX_BUFFERSIZE;
2780                         dr->dr_frameoffset = BWN_DMA0_RX_FRAMEOFFSET;
2781                 } else
2782                         KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
2783         }
2784
2785         error = bwn_dma_allocringmemory(dr);
2786         if (error)
2787                 goto fail1;
2788
2789         if (for_tx) {
2790                 /*
2791                  * Assumption: BWN_TXRING_SLOTS can be divided by
2792                  * BWN_TX_SLOTS_PER_FRAME
2793                  */
2794                 KASSERT(BWN_TXRING_SLOTS % BWN_TX_SLOTS_PER_FRAME == 0,
2795                     ("%s:%d: fail", __func__, __LINE__));
2796
2797                 dr->dr_txhdr_cache = contigmalloc(
2798                     (dr->dr_numslots / BWN_TX_SLOTS_PER_FRAME) *
2799                     BWN_MAXTXHDRSIZE, M_DEVBUF, M_WAITOK | M_ZERO,
2800                     0, BUS_SPACE_MAXADDR, 2, 0);
2801                 if (dr->dr_txhdr_cache == NULL) {
2802                         device_printf(sc->sc_dev,
2803                             "can't allocate TX header DMA memory\n");
2804                         goto fail1;
2805                 }
2806
2807                 /*
2808                  * Create TX ring DMA stuffs
2809                  */
2810                 error = bus_dma_tag_create(dma->parent_dtag,
2811                                     1, 0,
2812                                     BUS_SPACE_MAXADDR,
2813                                     BUS_SPACE_MAXADDR,
2814                                     NULL, NULL,
2815                                     BWN_HDRSIZE(mac),
2816                                     1,
2817                                     BUS_SPACE_MAXSIZE_32BIT,
2818                                     0,
2819 #if !defined(__DragonFly__)
2820                                     NULL, NULL,
2821 #endif
2822                                     &dr->dr_txring_dtag);
2823                 if (error) {
2824                         device_printf(sc->sc_dev,
2825                             "can't create TX ring DMA tag: TODO frees\n");
2826                         goto fail2;
2827                 }
2828
2829                 for (i = 0; i < dr->dr_numslots; i += 2) {
2830                         dr->getdesc(dr, i, &desc, &mt);
2831
2832                         mt->mt_txtype = BWN_DMADESC_METATYPE_HEADER;
2833                         mt->mt_m = NULL;
2834                         mt->mt_ni = NULL;
2835                         mt->mt_islast = 0;
2836                         error = bus_dmamap_create(dr->dr_txring_dtag, 0,
2837                             &mt->mt_dmap);
2838                         if (error) {
2839                                 device_printf(sc->sc_dev,
2840                                      "can't create RX buf DMA map\n");
2841                                 goto fail2;
2842                         }
2843
2844                         dr->getdesc(dr, i + 1, &desc, &mt);
2845
2846                         mt->mt_txtype = BWN_DMADESC_METATYPE_BODY;
2847                         mt->mt_m = NULL;
2848                         mt->mt_ni = NULL;
2849                         mt->mt_islast = 1;
2850                         error = bus_dmamap_create(dma->txbuf_dtag, 0,
2851                             &mt->mt_dmap);
2852                         if (error) {
2853                                 device_printf(sc->sc_dev,
2854                                      "can't create RX buf DMA map\n");
2855                                 goto fail2;
2856                         }
2857                 }
2858         } else {
2859                 error = bus_dmamap_create(dma->rxbuf_dtag, 0,
2860                     &dr->dr_spare_dmap);
2861                 if (error) {
2862                         device_printf(sc->sc_dev,
2863                             "can't create RX buf DMA map\n");
2864                         goto out;               /* XXX wrong! */
2865                 }
2866
2867                 for (i = 0; i < dr->dr_numslots; i++) {
2868                         dr->getdesc(dr, i, &desc, &mt);
2869
2870                         error = bus_dmamap_create(dma->rxbuf_dtag, 0,
2871                             &mt->mt_dmap);
2872                         if (error) {
2873                                 device_printf(sc->sc_dev,
2874                                     "can't create RX buf DMA map\n");
2875                                 goto out;       /* XXX wrong! */
2876                         }
2877                         error = bwn_dma_newbuf(dr, desc, mt, 1);
2878                         if (error) {
2879                                 device_printf(sc->sc_dev,
2880                                     "failed to allocate RX buf\n");
2881                                 goto out;       /* XXX wrong! */
2882                         }
2883                 }
2884
2885                 bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
2886                     BUS_DMASYNC_PREWRITE);
2887
2888                 dr->dr_usedslot = dr->dr_numslots;
2889         }
2890
2891       out:
2892         return (dr);
2893
2894 fail2:
2895         if (dr->dr_txhdr_cache != NULL) {
2896                 contigfree(dr->dr_txhdr_cache,
2897                     (dr->dr_numslots / BWN_TX_SLOTS_PER_FRAME) *
2898                     BWN_MAXTXHDRSIZE, M_DEVBUF);
2899         }
2900 fail1:
2901         kfree(dr->dr_meta, M_DEVBUF);
2902 fail0:
2903         kfree(dr, M_DEVBUF);
2904         return (NULL);
2905 }
2906
2907 static void
2908 bwn_dma_ringfree(struct bwn_dma_ring **dr)
2909 {
2910
2911         if (dr == NULL)
2912                 return;
2913
2914         bwn_dma_free_descbufs(*dr);
2915         bwn_dma_free_ringmemory(*dr);
2916
2917         if ((*dr)->dr_txhdr_cache != NULL) {
2918                 contigfree((*dr)->dr_txhdr_cache,
2919                     ((*dr)->dr_numslots / BWN_TX_SLOTS_PER_FRAME) *
2920                     BWN_MAXTXHDRSIZE, M_DEVBUF);
2921         }
2922         kfree((*dr)->dr_meta, M_DEVBUF);
2923         kfree(*dr, M_DEVBUF);
2924
2925         *dr = NULL;
2926 }
2927
2928 static void
2929 bwn_dma_32_getdesc(struct bwn_dma_ring *dr, int slot,
2930     struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
2931 {
2932         struct bwn_dmadesc32 *desc;
2933
2934         *meta = &(dr->dr_meta[slot]);
2935         desc = dr->dr_ring_descbase;
2936         desc = &(desc[slot]);
2937
2938         *gdesc = (struct bwn_dmadesc_generic *)desc;
2939 }
2940
2941 static void
2942 bwn_dma_32_setdesc(struct bwn_dma_ring *dr,
2943     struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
2944     int start, int end, int irq)
2945 {
2946         struct bwn_dmadesc32 *descbase = dr->dr_ring_descbase;
2947         struct bwn_softc *sc = dr->dr_mac->mac_sc;
2948         uint32_t addr, addrext, ctl;
2949         int slot;
2950
2951         slot = (int)(&(desc->dma.dma32) - descbase);
2952         KASSERT(slot >= 0 && slot < dr->dr_numslots,
2953             ("%s:%d: fail", __func__, __LINE__));
2954
2955         addr = (uint32_t) (dmaaddr & ~SIBA_DMA_TRANSLATION_MASK);
2956         addrext = (uint32_t) (dmaaddr & SIBA_DMA_TRANSLATION_MASK) >> 30;
2957         addr |= siba_dma_translation(sc->sc_dev);
2958         ctl = bufsize & BWN_DMA32_DCTL_BYTECNT;
2959         if (slot == dr->dr_numslots - 1)
2960                 ctl |= BWN_DMA32_DCTL_DTABLEEND;
2961         if (start)
2962                 ctl |= BWN_DMA32_DCTL_FRAMESTART;
2963         if (end)
2964                 ctl |= BWN_DMA32_DCTL_FRAMEEND;
2965         if (irq)
2966                 ctl |= BWN_DMA32_DCTL_IRQ;
2967         ctl |= (addrext << BWN_DMA32_DCTL_ADDREXT_SHIFT)
2968             & BWN_DMA32_DCTL_ADDREXT_MASK;
2969
2970         desc->dma.dma32.control = htole32(ctl);
2971         desc->dma.dma32.address = htole32(addr);
2972 }
2973
2974 static void
2975 bwn_dma_32_start_transfer(struct bwn_dma_ring *dr, int slot)
2976 {
2977
2978         BWN_DMA_WRITE(dr, BWN_DMA32_TXINDEX,
2979             (uint32_t)(slot * sizeof(struct bwn_dmadesc32)));
2980 }
2981
2982 static void
2983 bwn_dma_32_suspend(struct bwn_dma_ring *dr)
2984 {
2985
2986         BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
2987             BWN_DMA_READ(dr, BWN_DMA32_TXCTL) | BWN_DMA32_TXSUSPEND);
2988 }
2989
2990 static void
2991 bwn_dma_32_resume(struct bwn_dma_ring *dr)
2992 {
2993
2994         BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
2995             BWN_DMA_READ(dr, BWN_DMA32_TXCTL) & ~BWN_DMA32_TXSUSPEND);
2996 }
2997
2998 static int
2999 bwn_dma_32_get_curslot(struct bwn_dma_ring *dr)
3000 {
3001         uint32_t val;
3002
3003         val = BWN_DMA_READ(dr, BWN_DMA32_RXSTATUS);
3004         val &= BWN_DMA32_RXDPTR;
3005
3006         return (val / sizeof(struct bwn_dmadesc32));
3007 }
3008
3009 static void
3010 bwn_dma_32_set_curslot(struct bwn_dma_ring *dr, int slot)
3011 {
3012
3013         BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX,
3014             (uint32_t) (slot * sizeof(struct bwn_dmadesc32)));
3015 }
3016
3017 static void
3018 bwn_dma_64_getdesc(struct bwn_dma_ring *dr, int slot,
3019     struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
3020 {
3021         struct bwn_dmadesc64 *desc;
3022
3023         *meta = &(dr->dr_meta[slot]);
3024         desc = dr->dr_ring_descbase;
3025         desc = &(desc[slot]);
3026
3027         *gdesc = (struct bwn_dmadesc_generic *)desc;
3028 }
3029
3030 static void
3031 bwn_dma_64_setdesc(struct bwn_dma_ring *dr,
3032     struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
3033     int start, int end, int irq)
3034 {
3035         struct bwn_dmadesc64 *descbase = dr->dr_ring_descbase;
3036         struct bwn_softc *sc = dr->dr_mac->mac_sc;
3037         int slot;
3038         uint32_t ctl0 = 0, ctl1 = 0;
3039         uint32_t addrlo, addrhi;
3040         uint32_t addrext;
3041
3042         slot = (int)(&(desc->dma.dma64) - descbase);
3043         KASSERT(slot >= 0 && slot < dr->dr_numslots,
3044             ("%s:%d: fail", __func__, __LINE__));
3045
3046         addrlo = (uint32_t) (dmaaddr & 0xffffffff);
3047         addrhi = (((uint64_t) dmaaddr >> 32) & ~SIBA_DMA_TRANSLATION_MASK);
3048         addrext = (((uint64_t) dmaaddr >> 32) & SIBA_DMA_TRANSLATION_MASK) >>
3049             30;
3050         addrhi |= (siba_dma_translation(sc->sc_dev) << 1);
3051         if (slot == dr->dr_numslots - 1)
3052                 ctl0 |= BWN_DMA64_DCTL0_DTABLEEND;
3053         if (start)
3054                 ctl0 |= BWN_DMA64_DCTL0_FRAMESTART;
3055         if (end)
3056                 ctl0 |= BWN_DMA64_DCTL0_FRAMEEND;
3057         if (irq)
3058                 ctl0 |= BWN_DMA64_DCTL0_IRQ;
3059         ctl1 |= bufsize & BWN_DMA64_DCTL1_BYTECNT;
3060         ctl1 |= (addrext << BWN_DMA64_DCTL1_ADDREXT_SHIFT)
3061             & BWN_DMA64_DCTL1_ADDREXT_MASK;
3062
3063         desc->dma.dma64.control0 = htole32(ctl0);
3064         desc->dma.dma64.control1 = htole32(ctl1);
3065         desc->dma.dma64.address_low = htole32(addrlo);
3066         desc->dma.dma64.address_high = htole32(addrhi);
3067 }
3068
3069 static void
3070 bwn_dma_64_start_transfer(struct bwn_dma_ring *dr, int slot)
3071 {
3072
3073         BWN_DMA_WRITE(dr, BWN_DMA64_TXINDEX,
3074             (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
3075 }
3076
3077 static void
3078 bwn_dma_64_suspend(struct bwn_dma_ring *dr)
3079 {
3080
3081         BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
3082             BWN_DMA_READ(dr, BWN_DMA64_TXCTL) | BWN_DMA64_TXSUSPEND);
3083 }
3084
3085 static void
3086 bwn_dma_64_resume(struct bwn_dma_ring *dr)
3087 {
3088
3089         BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
3090             BWN_DMA_READ(dr, BWN_DMA64_TXCTL) & ~BWN_DMA64_TXSUSPEND);
3091 }
3092
3093 static int
3094 bwn_dma_64_get_curslot(struct bwn_dma_ring *dr)
3095 {
3096         uint32_t val;
3097
3098         val = BWN_DMA_READ(dr, BWN_DMA64_RXSTATUS);
3099         val &= BWN_DMA64_RXSTATDPTR;
3100
3101         return (val / sizeof(struct bwn_dmadesc64));
3102 }
3103
3104 static void
3105 bwn_dma_64_set_curslot(struct bwn_dma_ring *dr, int slot)
3106 {
3107
3108         BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX,
3109             (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
3110 }
3111
3112 static int
3113 bwn_dma_allocringmemory(struct bwn_dma_ring *dr)
3114 {
3115         struct bwn_mac *mac = dr->dr_mac;
3116         struct bwn_dma *dma = &mac->mac_method.dma;
3117         struct bwn_softc *sc = mac->mac_sc;
3118         int error;
3119
3120         error = bus_dma_tag_create(dma->parent_dtag,
3121                             BWN_ALIGN, 0,
3122                             BUS_SPACE_MAXADDR,
3123                             BUS_SPACE_MAXADDR,
3124                             NULL, NULL,
3125                             BWN_DMA_RINGMEMSIZE,
3126                             1,
3127                             BUS_SPACE_MAXSIZE_32BIT,
3128                             0,
3129 #if !defined(__DragonFly__)
3130                             NULL, NULL,
3131 #endif
3132                             &dr->dr_ring_dtag);
3133         if (error) {
3134                 device_printf(sc->sc_dev,
3135                     "can't create TX ring DMA tag: TODO frees\n");
3136                 return (-1);
3137         }
3138
3139         error = bus_dmamem_alloc(dr->dr_ring_dtag,
3140             &dr->dr_ring_descbase, BUS_DMA_WAITOK | BUS_DMA_ZERO,
3141             &dr->dr_ring_dmap);
3142         if (error) {
3143                 device_printf(sc->sc_dev,
3144                     "can't allocate DMA mem: TODO frees\n");
3145                 return (-1);
3146         }
3147         error = bus_dmamap_load(dr->dr_ring_dtag, dr->dr_ring_dmap,
3148             dr->dr_ring_descbase, BWN_DMA_RINGMEMSIZE,
3149             bwn_dma_ring_addr, &dr->dr_ring_dmabase, BUS_DMA_NOWAIT);
3150         if (error || dr->dr_ring_dmabase == 0) {
3151                 device_printf(sc->sc_dev,
3152                     "can't load DMA mem: TODO free\n");
3153                 return (-1);
3154         }
3155
3156         return (0);
3157 }
3158
3159 static void
3160 bwn_dma_setup(struct bwn_dma_ring *dr)
3161 {
3162         struct bwn_softc *sc = dr->dr_mac->mac_sc;
3163         uint64_t ring64;
3164         uint32_t addrext, ring32, value;
3165         uint32_t trans = siba_dma_translation(sc->sc_dev);
3166
3167         if (dr->dr_tx) {
3168                 dr->dr_curslot = -1;
3169
3170                 if (dr->dr_type == BWN_DMA_64BIT) {
3171                         ring64 = (uint64_t)(dr->dr_ring_dmabase);
3172                         addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK)
3173                             >> 30;
3174                         value = BWN_DMA64_TXENABLE;
3175                         value |= (addrext << BWN_DMA64_TXADDREXT_SHIFT)
3176                             & BWN_DMA64_TXADDREXT_MASK;
3177                         BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL, value);
3178                         BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO,
3179                             (ring64 & 0xffffffff));
3180                         BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI,
3181                             ((ring64 >> 32) &
3182                             ~SIBA_DMA_TRANSLATION_MASK) | (trans << 1));
3183                 } else {
3184                         ring32 = (uint32_t)(dr->dr_ring_dmabase);
3185                         addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
3186                         value = BWN_DMA32_TXENABLE;
3187                         value |= (addrext << BWN_DMA32_TXADDREXT_SHIFT)
3188                             & BWN_DMA32_TXADDREXT_MASK;
3189                         BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL, value);
3190                         BWN_DMA_WRITE(dr, BWN_DMA32_TXRING,
3191                             (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
3192                 }
3193                 return;
3194         }
3195
3196         /*
3197          * set for RX
3198          */
3199         dr->dr_usedslot = dr->dr_numslots;
3200
3201         if (dr->dr_type == BWN_DMA_64BIT) {
3202                 ring64 = (uint64_t)(dr->dr_ring_dmabase);
3203                 addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK) >> 30;
3204                 value = (dr->dr_frameoffset << BWN_DMA64_RXFROFF_SHIFT);
3205                 value |= BWN_DMA64_RXENABLE;
3206                 value |= (addrext << BWN_DMA64_RXADDREXT_SHIFT)
3207                     & BWN_DMA64_RXADDREXT_MASK;
3208                 BWN_DMA_WRITE(dr, BWN_DMA64_RXCTL, value);
3209                 BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, (ring64 & 0xffffffff));
3210                 BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI,
3211                     ((ring64 >> 32) & ~SIBA_DMA_TRANSLATION_MASK)
3212                     | (trans << 1));
3213                 BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX, dr->dr_numslots *
3214                     sizeof(struct bwn_dmadesc64));
3215         } else {
3216                 ring32 = (uint32_t)(dr->dr_ring_dmabase);
3217                 addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
3218                 value = (dr->dr_frameoffset << BWN_DMA32_RXFROFF_SHIFT);
3219                 value |= BWN_DMA32_RXENABLE;
3220                 value |= (addrext << BWN_DMA32_RXADDREXT_SHIFT)
3221                     & BWN_DMA32_RXADDREXT_MASK;
3222                 BWN_DMA_WRITE(dr, BWN_DMA32_RXCTL, value);
3223                 BWN_DMA_WRITE(dr, BWN_DMA32_RXRING,
3224                     (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
3225                 BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX, dr->dr_numslots *
3226                     sizeof(struct bwn_dmadesc32));
3227         }
3228 }
3229
3230 static void
3231 bwn_dma_free_ringmemory(struct bwn_dma_ring *dr)
3232 {
3233
3234         bus_dmamap_unload(dr->dr_ring_dtag, dr->dr_ring_dmap);
3235         bus_dmamem_free(dr->dr_ring_dtag, dr->dr_ring_descbase,
3236             dr->dr_ring_dmap);
3237 }
3238
3239 static void
3240 bwn_dma_cleanup(struct bwn_dma_ring *dr)
3241 {
3242
3243         if (dr->dr_tx) {
3244                 bwn_dma_tx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
3245                 if (dr->dr_type == BWN_DMA_64BIT) {
3246                         BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO, 0);
3247                         BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI, 0);
3248                 } else
3249                         BWN_DMA_WRITE(dr, BWN_DMA32_TXRING, 0);
3250         } else {
3251                 bwn_dma_rx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
3252                 if (dr->dr_type == BWN_DMA_64BIT) {
3253                         BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, 0);
3254                         BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI, 0);
3255                 } else
3256                         BWN_DMA_WRITE(dr, BWN_DMA32_RXRING, 0);
3257         }
3258 }
3259
3260 static void
3261 bwn_dma_free_descbufs(struct bwn_dma_ring *dr)
3262 {
3263         struct bwn_dmadesc_generic *desc;
3264         struct bwn_dmadesc_meta *meta;
3265         struct bwn_mac *mac = dr->dr_mac;
3266         struct bwn_dma *dma = &mac->mac_method.dma;
3267         struct bwn_softc *sc = mac->mac_sc;
3268         int i;
3269
3270         if (!dr->dr_usedslot)
3271                 return;
3272         for (i = 0; i < dr->dr_numslots; i++) {
3273                 dr->getdesc(dr, i, &desc, &meta);
3274
3275                 if (meta->mt_m == NULL) {
3276                         if (!dr->dr_tx)
3277                                 device_printf(sc->sc_dev, "%s: not TX?\n",
3278                                     __func__);
3279                         continue;
3280                 }
3281                 if (dr->dr_tx) {
3282                         if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER) {
3283                                 bus_dmamap_unload(dr->dr_txring_dtag,
3284                                     meta->mt_dmap);
3285                         } else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY) {
3286                                 bus_dmamap_unload(dma->txbuf_dtag,
3287                                     meta->mt_dmap);
3288                         }
3289                 } else
3290                         bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
3291                 bwn_dma_free_descbuf(dr, meta);
3292         }
3293 }
3294
3295 static int
3296 bwn_dma_tx_reset(struct bwn_mac *mac, uint16_t base,
3297     int type)
3298 {
3299         struct bwn_softc *sc = mac->mac_sc;
3300         uint32_t value;
3301         int i;
3302         uint16_t offset;
3303
3304         for (i = 0; i < 10; i++) {
3305                 offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
3306                     BWN_DMA32_TXSTATUS;
3307                 value = BWN_READ_4(mac, base + offset);
3308                 if (type == BWN_DMA_64BIT) {
3309                         value &= BWN_DMA64_TXSTAT;
3310                         if (value == BWN_DMA64_TXSTAT_DISABLED ||
3311                             value == BWN_DMA64_TXSTAT_IDLEWAIT ||
3312                             value == BWN_DMA64_TXSTAT_STOPPED)
3313                                 break;
3314                 } else {
3315                         value &= BWN_DMA32_TXSTATE;
3316                         if (value == BWN_DMA32_TXSTAT_DISABLED ||
3317                             value == BWN_DMA32_TXSTAT_IDLEWAIT ||
3318                             value == BWN_DMA32_TXSTAT_STOPPED)
3319                                 break;
3320                 }
3321                 DELAY(1000);
3322         }
3323         offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXCTL : BWN_DMA32_TXCTL;
3324         BWN_WRITE_4(mac, base + offset, 0);
3325         for (i = 0; i < 10; i++) {
3326                 offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
3327                                                    BWN_DMA32_TXSTATUS;
3328                 value = BWN_READ_4(mac, base + offset);
3329                 if (type == BWN_DMA_64BIT) {
3330                         value &= BWN_DMA64_TXSTAT;
3331                         if (value == BWN_DMA64_TXSTAT_DISABLED) {
3332                                 i = -1;
3333                                 break;
3334                         }
3335                 } else {
3336                         value &= BWN_DMA32_TXSTATE;
3337                         if (value == BWN_DMA32_TXSTAT_DISABLED) {
3338                                 i = -1;
3339                                 break;
3340                         }
3341                 }
3342                 DELAY(1000);
3343         }
3344         if (i != -1) {
3345                 device_printf(sc->sc_dev, "%s: timed out\n", __func__);
3346                 return (ENODEV);
3347         }
3348         DELAY(1000);
3349
3350         return (0);
3351 }
3352
3353 static int
3354 bwn_dma_rx_reset(struct bwn_mac *mac, uint16_t base,
3355     int type)
3356 {
3357         struct bwn_softc *sc = mac->mac_sc;
3358         uint32_t value;
3359         int i;
3360         uint16_t offset;
3361
3362         offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXCTL : BWN_DMA32_RXCTL;
3363         BWN_WRITE_4(mac, base + offset, 0);
3364         for (i = 0; i < 10; i++) {
3365                 offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXSTATUS :
3366                     BWN_DMA32_RXSTATUS;
3367                 value = BWN_READ_4(mac, base + offset);
3368                 if (type == BWN_DMA_64BIT) {
3369                         value &= BWN_DMA64_RXSTAT;
3370                         if (value == BWN_DMA64_RXSTAT_DISABLED) {
3371                                 i = -1;
3372                                 break;
3373                         }
3374                 } else {
3375                         value &= BWN_DMA32_RXSTATE;
3376                         if (value == BWN_DMA32_RXSTAT_DISABLED) {
3377                                 i = -1;
3378                                 break;
3379                         }
3380                 }
3381                 DELAY(1000);
3382         }
3383         if (i != -1) {
3384                 device_printf(sc->sc_dev, "%s: timed out\n", __func__);
3385                 return (ENODEV);
3386         }
3387
3388         return (0);
3389 }
3390
3391 static void
3392 bwn_dma_free_descbuf(struct bwn_dma_ring *dr,
3393     struct bwn_dmadesc_meta *meta)
3394 {
3395
3396         if (meta->mt_m != NULL) {
3397                 m_freem(meta->mt_m);
3398                 meta->mt_m = NULL;
3399         }
3400         if (meta->mt_ni != NULL) {
3401                 ieee80211_free_node(meta->mt_ni);
3402                 meta->mt_ni = NULL;
3403         }
3404 }
3405
3406 static void
3407 bwn_dma_set_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
3408 {
3409         struct bwn_rxhdr4 *rxhdr;
3410         unsigned char *frame;
3411
3412         rxhdr = mtod(m, struct bwn_rxhdr4 *);
3413         rxhdr->frame_len = 0;
3414
3415         KASSERT(dr->dr_rx_bufsize >= dr->dr_frameoffset +
3416             sizeof(struct bwn_plcp6) + 2,
3417             ("%s:%d: fail", __func__, __LINE__));
3418         frame = mtod(m, char *) + dr->dr_frameoffset;
3419         memset(frame, 0xff, sizeof(struct bwn_plcp6) + 2 /* padding */);
3420 }
3421
3422 static uint8_t
3423 bwn_dma_check_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
3424 {
3425         unsigned char *f = mtod(m, char *) + dr->dr_frameoffset;
3426
3427         return ((f[0] & f[1] & f[2] & f[3] & f[4] & f[5] & f[6] & f[7])
3428             == 0xff);
3429 }
3430
3431 static void
3432 bwn_wme_init(struct bwn_mac *mac)
3433 {
3434
3435         bwn_wme_load(mac);
3436
3437         /* enable WME support. */
3438         bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_EDCF);
3439         BWN_WRITE_2(mac, BWN_IFSCTL, BWN_READ_2(mac, BWN_IFSCTL) |
3440             BWN_IFSCTL_USE_EDCF);
3441 }
3442
3443 static void
3444 bwn_spu_setdelay(struct bwn_mac *mac, int idle)
3445 {
3446         struct bwn_softc *sc = mac->mac_sc;
3447         struct ieee80211com *ic = &sc->sc_ic;
3448         uint16_t delay; /* microsec */
3449
3450         delay = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 3700 : 1050;
3451         if (ic->ic_opmode == IEEE80211_M_IBSS || idle)
3452                 delay = 500;
3453         if ((mac->mac_phy.rf_ver == 0x2050) && (mac->mac_phy.rf_rev == 8))
3454                 delay = max(delay, (uint16_t)2400);
3455
3456         bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SPU_WAKEUP, delay);
3457 }
3458
3459 static void
3460 bwn_bt_enable(struct bwn_mac *mac)
3461 {
3462         struct bwn_softc *sc = mac->mac_sc;
3463         uint64_t hf;
3464
3465         if (bwn_bluetooth == 0)
3466                 return;
3467         if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCOEXIST) == 0)
3468                 return;
3469         if (mac->mac_phy.type != BWN_PHYTYPE_B && !mac->mac_phy.gmode)
3470                 return;
3471
3472         hf = bwn_hf_read(mac);
3473         if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCMOD)
3474                 hf |= BWN_HF_BT_COEXISTALT;
3475         else
3476                 hf |= BWN_HF_BT_COEXIST;
3477         bwn_hf_write(mac, hf);
3478 }
3479
3480 static void
3481 bwn_set_macaddr(struct bwn_mac *mac)
3482 {
3483
3484         bwn_mac_write_bssid(mac);
3485         bwn_mac_setfilter(mac, BWN_MACFILTER_SELF,
3486             mac->mac_sc->sc_ic.ic_macaddr);
3487 }
3488
3489 static void
3490 bwn_clear_keys(struct bwn_mac *mac)
3491 {
3492         int i;
3493
3494         for (i = 0; i < mac->mac_max_nr_keys; i++) {
3495                 KASSERT(i >= 0 && i < mac->mac_max_nr_keys,
3496                     ("%s:%d: fail", __func__, __LINE__));
3497
3498                 bwn_key_dowrite(mac, i, BWN_SEC_ALGO_NONE,
3499                     NULL, BWN_SEC_KEYSIZE, NULL);
3500                 if ((i <= 3) && !BWN_SEC_NEWAPI(mac)) {
3501                         bwn_key_dowrite(mac, i + 4, BWN_SEC_ALGO_NONE,
3502                             NULL, BWN_SEC_KEYSIZE, NULL);
3503                 }
3504                 mac->mac_key[i].keyconf = NULL;
3505         }
3506 }
3507
3508 static void
3509 bwn_crypt_init(struct bwn_mac *mac)
3510 {
3511         struct bwn_softc *sc = mac->mac_sc;
3512
3513         mac->mac_max_nr_keys = (siba_get_revid(sc->sc_dev) >= 5) ? 58 : 20;
3514         KASSERT(mac->mac_max_nr_keys <= N(mac->mac_key),
3515             ("%s:%d: fail", __func__, __LINE__));
3516         mac->mac_ktp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_KEY_TABLEP);
3517         mac->mac_ktp *= 2;
3518         if (siba_get_revid(sc->sc_dev) >= 5)
3519                 BWN_WRITE_2(mac, BWN_RCMTA_COUNT, mac->mac_max_nr_keys - 8);
3520         bwn_clear_keys(mac);
3521 }
3522
3523 static void
3524 bwn_chip_exit(struct bwn_mac *mac)
3525 {
3526         struct bwn_softc *sc = mac->mac_sc;
3527
3528         bwn_phy_exit(mac);
3529         siba_gpio_set(sc->sc_dev, 0);
3530 }
3531
3532 static int
3533 bwn_fw_fillinfo(struct bwn_mac *mac)
3534 {
3535         int error;
3536
3537         error = bwn_fw_gets(mac, BWN_FWTYPE_DEFAULT);
3538         if (error == 0)
3539                 return (0);
3540         error = bwn_fw_gets(mac, BWN_FWTYPE_OPENSOURCE);
3541         if (error == 0)
3542                 return (0);
3543         return (error);
3544 }
3545
3546 static int
3547 bwn_gpio_init(struct bwn_mac *mac)
3548 {
3549         struct bwn_softc *sc = mac->mac_sc;
3550         uint32_t mask = 0x1f, set = 0xf, value;
3551
3552         BWN_WRITE_4(mac, BWN_MACCTL,
3553             BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GPOUT_MASK);
3554         BWN_WRITE_2(mac, BWN_GPIO_MASK,
3555             BWN_READ_2(mac, BWN_GPIO_MASK) | 0x000f);
3556
3557         if (siba_get_chipid(sc->sc_dev) == 0x4301) {
3558                 mask |= 0x0060;
3559                 set |= 0x0060;
3560         }
3561         if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL) {
3562                 BWN_WRITE_2(mac, BWN_GPIO_MASK,
3563                     BWN_READ_2(mac, BWN_GPIO_MASK) | 0x0200);
3564                 mask |= 0x0200;
3565                 set |= 0x0200;
3566         }
3567         if (siba_get_revid(sc->sc_dev) >= 2)
3568                 mask |= 0x0010;
3569
3570         value = siba_gpio_get(sc->sc_dev);
3571         if (value == -1)
3572                 return (0);
3573         siba_gpio_set(sc->sc_dev, (value & mask) | set);
3574
3575         return (0);
3576 }
3577
3578 static int
3579 bwn_fw_loadinitvals(struct bwn_mac *mac)
3580 {
3581 #define GETFWOFFSET(fwp, offset)                                \
3582         ((const struct bwn_fwinitvals *)((const char *)fwp.fw->data + offset))
3583         const size_t hdr_len = sizeof(struct bwn_fwhdr);
3584         const struct bwn_fwhdr *hdr;
3585         struct bwn_fw *fw = &mac->mac_fw;
3586         int error;
3587
3588         hdr = (const struct bwn_fwhdr *)(fw->initvals.fw->data);
3589         error = bwn_fwinitvals_write(mac, GETFWOFFSET(fw->initvals, hdr_len),
3590             be32toh(hdr->size), fw->initvals.fw->datasize - hdr_len);
3591         if (error)
3592                 return (error);
3593         if (fw->initvals_band.fw) {
3594                 hdr = (const struct bwn_fwhdr *)(fw->initvals_band.fw->data);
3595                 error = bwn_fwinitvals_write(mac,
3596                     GETFWOFFSET(fw->initvals_band, hdr_len),
3597                     be32toh(hdr->size),
3598                     fw->initvals_band.fw->datasize - hdr_len);
3599         }
3600         return (error);
3601 #undef GETFWOFFSET
3602 }
3603
3604 static int
3605 bwn_phy_init(struct bwn_mac *mac)
3606 {
3607         struct bwn_softc *sc = mac->mac_sc;
3608         int error;
3609
3610         mac->mac_phy.chan = mac->mac_phy.get_default_chan(mac);
3611         mac->mac_phy.rf_onoff(mac, 1);
3612         error = mac->mac_phy.init(mac);
3613         if (error) {
3614                 device_printf(sc->sc_dev, "PHY init failed\n");
3615                 goto fail0;
3616         }
3617         error = bwn_switch_channel(mac,
3618             mac->mac_phy.get_default_chan(mac));
3619         if (error) {
3620                 device_printf(sc->sc_dev,
3621                     "failed to switch default channel\n");
3622                 goto fail1;
3623         }
3624         return (0);
3625 fail1:
3626         if (mac->mac_phy.exit)
3627                 mac->mac_phy.exit(mac);
3628 fail0:
3629         mac->mac_phy.rf_onoff(mac, 0);
3630
3631         return (error);
3632 }
3633
3634 static void
3635 bwn_set_txantenna(struct bwn_mac *mac, int antenna)
3636 {
3637         uint16_t ant;
3638         uint16_t tmp;
3639
3640         ant = bwn_ant2phy(antenna);
3641
3642         /* For ACK/CTS */
3643         tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL);
3644         tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
3645         bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, tmp);
3646         /* For Probe Resposes */
3647         tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL);
3648         tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
3649         bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, tmp);
3650 }
3651
3652 static void
3653 bwn_set_opmode(struct bwn_mac *mac)
3654 {
3655         struct bwn_softc *sc = mac->mac_sc;
3656         struct ieee80211com *ic = &sc->sc_ic;
3657         uint32_t ctl;
3658         uint16_t cfp_pretbtt;
3659
3660         ctl = BWN_READ_4(mac, BWN_MACCTL);
3661         ctl &= ~(BWN_MACCTL_HOSTAP | BWN_MACCTL_PASS_CTL |
3662             BWN_MACCTL_PASS_BADPLCP | BWN_MACCTL_PASS_BADFCS |
3663             BWN_MACCTL_PROMISC | BWN_MACCTL_BEACON_PROMISC);
3664         ctl |= BWN_MACCTL_STA;
3665
3666         if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
3667             ic->ic_opmode == IEEE80211_M_MBSS)
3668                 ctl |= BWN_MACCTL_HOSTAP;
3669         else if (ic->ic_opmode == IEEE80211_M_IBSS)
3670                 ctl &= ~BWN_MACCTL_STA;
3671         ctl |= sc->sc_filters;
3672
3673         if (siba_get_revid(sc->sc_dev) <= 4)
3674                 ctl |= BWN_MACCTL_PROMISC;
3675
3676         BWN_WRITE_4(mac, BWN_MACCTL, ctl);
3677
3678         cfp_pretbtt = 2;
3679         if ((ctl & BWN_MACCTL_STA) && !(ctl & BWN_MACCTL_HOSTAP)) {
3680                 if (siba_get_chipid(sc->sc_dev) == 0x4306 &&
3681                     siba_get_chiprev(sc->sc_dev) == 3)
3682                         cfp_pretbtt = 100;
3683                 else
3684                         cfp_pretbtt = 50;
3685         }
3686         BWN_WRITE_2(mac, 0x612, cfp_pretbtt);
3687 }
3688
3689 static int
3690 bwn_dma_gettype(struct bwn_mac *mac)
3691 {
3692         uint32_t tmp;
3693         uint16_t base;
3694
3695         tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
3696         if (tmp & SIBA_TGSHIGH_DMA64)
3697                 return (BWN_DMA_64BIT);
3698         base = bwn_dma_base(0, 0);
3699         BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
3700         tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
3701         if (tmp & BWN_DMA32_TXADDREXT_MASK)
3702                 return (BWN_DMA_32BIT);
3703
3704         return (BWN_DMA_30BIT);
3705 }
3706
3707 static void
3708 bwn_dma_ring_addr(void *arg, bus_dma_segment_t *seg, int nseg, int error)
3709 {
3710         if (error) {
3711                 *((bus_addr_t *)arg) = 0;
3712         } else {
3713                 KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
3714                 *((bus_addr_t *)arg) = seg->ds_addr;
3715         }
3716 }
3717
3718 void
3719 bwn_dummy_transmission(struct bwn_mac *mac, int ofdm, int paon)
3720 {
3721         struct bwn_phy *phy = &mac->mac_phy;
3722         struct bwn_softc *sc = mac->mac_sc;
3723         unsigned int i, max_loop;
3724         uint16_t value;
3725         uint32_t buffer[5] = {
3726                 0x00000000, 0x00d40000, 0x00000000, 0x01000000, 0x00000000
3727         };
3728
3729         if (ofdm) {
3730                 max_loop = 0x1e;
3731                 buffer[0] = 0x000201cc;
3732         } else {
3733                 max_loop = 0xfa;
3734                 buffer[0] = 0x000b846e;
3735         }
3736
3737         BWN_ASSERT_LOCKED(mac->mac_sc);
3738
3739         for (i = 0; i < 5; i++)
3740                 bwn_ram_write(mac, i * 4, buffer[i]);
3741
3742         BWN_WRITE_2(mac, 0x0568, 0x0000);
3743         BWN_WRITE_2(mac, 0x07c0,
3744             (siba_get_revid(sc->sc_dev) < 11) ? 0x0000 : 0x0100);
3745
3746         value = (ofdm ? 0x41 : 0x40);
3747         BWN_WRITE_2(mac, 0x050c, value);
3748
3749         if (phy->type == BWN_PHYTYPE_N || phy->type == BWN_PHYTYPE_LP ||
3750             phy->type == BWN_PHYTYPE_LCN)
3751                 BWN_WRITE_2(mac, 0x0514, 0x1a02);
3752         BWN_WRITE_2(mac, 0x0508, 0x0000);
3753         BWN_WRITE_2(mac, 0x050a, 0x0000);
3754         BWN_WRITE_2(mac, 0x054c, 0x0000);
3755         BWN_WRITE_2(mac, 0x056a, 0x0014);
3756         BWN_WRITE_2(mac, 0x0568, 0x0826);
3757         BWN_WRITE_2(mac, 0x0500, 0x0000);
3758
3759         /* XXX TODO: n phy pa override? */
3760
3761         switch (phy->type) {
3762         case BWN_PHYTYPE_N:
3763         case BWN_PHYTYPE_LCN:
3764                 BWN_WRITE_2(mac, 0x0502, 0x00d0);
3765                 break;
3766         case BWN_PHYTYPE_LP:
3767                 BWN_WRITE_2(mac, 0x0502, 0x0050);
3768                 break;
3769         default:
3770                 BWN_WRITE_2(mac, 0x0502, 0x0030);
3771                 break;
3772         }
3773
3774         /* flush */
3775         BWN_READ_2(mac, 0x0502);
3776
3777         if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
3778                 BWN_RF_WRITE(mac, 0x0051, 0x0017);
3779         for (i = 0x00; i < max_loop; i++) {
3780                 value = BWN_READ_2(mac, 0x050e);
3781                 if (value & 0x0080)
3782                         break;
3783                 DELAY(10);
3784         }
3785         for (i = 0x00; i < 0x0a; i++) {
3786                 value = BWN_READ_2(mac, 0x050e);
3787                 if (value & 0x0400)
3788                         break;
3789                 DELAY(10);
3790         }
3791         for (i = 0x00; i < 0x19; i++) {
3792                 value = BWN_READ_2(mac, 0x0690);
3793                 if (!(value & 0x0100))
3794                         break;
3795                 DELAY(10);
3796         }
3797         if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
3798                 BWN_RF_WRITE(mac, 0x0051, 0x0037);
3799 }
3800
3801 void
3802 bwn_ram_write(struct bwn_mac *mac, uint16_t offset, uint32_t val)
3803 {
3804         uint32_t macctl;
3805
3806         KASSERT(offset % 4 == 0, ("%s:%d: fail", __func__, __LINE__));
3807
3808         macctl = BWN_READ_4(mac, BWN_MACCTL);
3809         if (macctl & BWN_MACCTL_BIGENDIAN)
3810                 kprintf("TODO: need swap\n");
3811
3812         BWN_WRITE_4(mac, BWN_RAM_CONTROL, offset);
3813         BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
3814         BWN_WRITE_4(mac, BWN_RAM_DATA, val);
3815 }
3816
3817 void
3818 bwn_mac_suspend(struct bwn_mac *mac)
3819 {
3820         struct bwn_softc *sc = mac->mac_sc;
3821         int i;
3822         uint32_t tmp;
3823
3824         KASSERT(mac->mac_suspended >= 0,
3825             ("%s:%d: fail", __func__, __LINE__));
3826
3827         if (mac->mac_suspended == 0) {
3828                 bwn_psctl(mac, BWN_PS_AWAKE);
3829                 BWN_WRITE_4(mac, BWN_MACCTL,
3830                             BWN_READ_4(mac, BWN_MACCTL)
3831                             & ~BWN_MACCTL_ON);
3832                 BWN_READ_4(mac, BWN_MACCTL);
3833                 for (i = 35; i; i--) {
3834                         tmp = BWN_READ_4(mac, BWN_INTR_REASON);
3835                         if (tmp & BWN_INTR_MAC_SUSPENDED)
3836                                 goto out;
3837                         DELAY(10);
3838                 }
3839                 for (i = 40; i; i--) {
3840                         tmp = BWN_READ_4(mac, BWN_INTR_REASON);
3841                         if (tmp & BWN_INTR_MAC_SUSPENDED)
3842                                 goto out;
3843                         DELAY(1000);
3844                 }
3845                 device_printf(sc->sc_dev, "MAC suspend failed\n");
3846         }
3847 out:
3848         mac->mac_suspended++;
3849 }
3850
3851 void
3852 bwn_mac_enable(struct bwn_mac *mac)
3853 {
3854         struct bwn_softc *sc = mac->mac_sc;
3855         uint16_t state;
3856
3857         state = bwn_shm_read_2(mac, BWN_SHARED,
3858             BWN_SHARED_UCODESTAT);
3859         if (state != BWN_SHARED_UCODESTAT_SUSPEND &&
3860             state != BWN_SHARED_UCODESTAT_SLEEP)
3861                 device_printf(sc->sc_dev, "warn: firmware state (%d)\n", state);
3862
3863         mac->mac_suspended--;
3864         KASSERT(mac->mac_suspended >= 0,
3865             ("%s:%d: fail", __func__, __LINE__));
3866         if (mac->mac_suspended == 0) {
3867                 BWN_WRITE_4(mac, BWN_MACCTL,
3868                     BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_ON);
3869                 BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_MAC_SUSPENDED);
3870                 BWN_READ_4(mac, BWN_MACCTL);
3871                 BWN_READ_4(mac, BWN_INTR_REASON);
3872                 bwn_psctl(mac, 0);
3873         }
3874 }
3875
3876 void
3877 bwn_psctl(struct bwn_mac *mac, uint32_t flags)
3878 {
3879         struct bwn_softc *sc = mac->mac_sc;
3880         int i;
3881         uint16_t ucstat;
3882
3883         KASSERT(!((flags & BWN_PS_ON) && (flags & BWN_PS_OFF)),
3884             ("%s:%d: fail", __func__, __LINE__));
3885         KASSERT(!((flags & BWN_PS_AWAKE) && (flags & BWN_PS_ASLEEP)),
3886             ("%s:%d: fail", __func__, __LINE__));
3887
3888         /* XXX forcibly awake and hwps-off */
3889
3890         BWN_WRITE_4(mac, BWN_MACCTL,
3891             (BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_AWAKE) &
3892             ~BWN_MACCTL_HWPS);
3893         BWN_READ_4(mac, BWN_MACCTL);
3894         if (siba_get_revid(sc->sc_dev) >= 5) {
3895                 for (i = 0; i < 100; i++) {
3896                         ucstat = bwn_shm_read_2(mac, BWN_SHARED,
3897                             BWN_SHARED_UCODESTAT);
3898                         if (ucstat != BWN_SHARED_UCODESTAT_SLEEP)
3899                                 break;
3900                         DELAY(10);
3901                 }
3902         }
3903 }
3904
3905 static int
3906 bwn_fw_gets(struct bwn_mac *mac, enum bwn_fwtype type)
3907 {
3908         struct bwn_softc *sc = mac->mac_sc;
3909         struct bwn_fw *fw = &mac->mac_fw;
3910         const uint8_t rev = siba_get_revid(sc->sc_dev);
3911         const char *filename;
3912         uint32_t high;
3913         int error;
3914
3915         /* microcode */
3916         filename = NULL;
3917         switch (rev) {
3918         case 42:
3919                 if (mac->mac_phy.type == BWN_PHYTYPE_AC)
3920                         filename = "ucode42";
3921                 break;
3922         case 40:
3923                 if (mac->mac_phy.type == BWN_PHYTYPE_AC)
3924                         filename = "ucode40";
3925                 break;
3926         case 33:
3927                 if (mac->mac_phy.type == BWN_PHYTYPE_LCN40)
3928                         filename = "ucode33_lcn40";
3929                 break;
3930         case 30:
3931                 if (mac->mac_phy.type == BWN_PHYTYPE_N)
3932                         filename = "ucode30_mimo";
3933                 break;
3934         case 29:
3935                 if (mac->mac_phy.type == BWN_PHYTYPE_HT)
3936                         filename = "ucode29_mimo";
3937                 break;
3938         case 26:
3939                 if (mac->mac_phy.type == BWN_PHYTYPE_HT)
3940                         filename = "ucode26_mimo";
3941                 break;
3942         case 28:
3943         case 25:
3944                 if (mac->mac_phy.type == BWN_PHYTYPE_N)
3945                         filename = "ucode25_mimo";
3946                 else if (mac->mac_phy.type == BWN_PHYTYPE_LCN)
3947                         filename = "ucode25_lcn";
3948                 break;
3949         case 24:
3950                 if (mac->mac_phy.type == BWN_PHYTYPE_LCN)
3951                         filename = "ucode24_lcn";
3952                 break;
3953         case 23:
3954                 if (mac->mac_phy.type == BWN_PHYTYPE_N)
3955                         filename = "ucode16_mimo";
3956                 break;
3957         case 16:
3958         case 17:
3959         case 18:
3960         case 19:
3961                 if (mac->mac_phy.type == BWN_PHYTYPE_N)
3962                         filename = "ucode16_mimo";
3963                 else if (mac->mac_phy.type == BWN_PHYTYPE_LP)
3964                         filename = "ucode16_lp";
3965                 break;
3966         case 15:
3967                 filename = "ucode15";
3968                 break;
3969         case 14:
3970                 filename = "ucode14";
3971                 break;
3972         case 13:
3973                 filename = "ucode13";
3974                 break;
3975         case 12:
3976         case 11:
3977                 filename = "ucode11";
3978                 break;
3979         case 10:
3980         case 9:
3981         case 8:
3982         case 7:
3983         case 6:
3984         case 5:
3985                 filename = "ucode5";
3986                 break;
3987         default:
3988                 device_printf(sc->sc_dev, "no ucode for rev %d\n", rev);
3989                 bwn_release_firmware(mac);
3990                 return (EOPNOTSUPP);
3991         }
3992
3993         device_printf(sc->sc_dev, "ucode fw: %s\n", filename);
3994         error = bwn_fw_get(mac, type, filename, &fw->ucode);
3995         if (error) {
3996                 bwn_release_firmware(mac);
3997                 return (error);
3998         }
3999
4000         /* PCM */
4001         KASSERT(fw->no_pcmfile == 0, ("%s:%d fail", __func__, __LINE__));
4002         if (rev >= 5 && rev <= 10) {
4003                 error = bwn_fw_get(mac, type, "pcm5", &fw->pcm);
4004                 if (error == ENOENT)
4005                         fw->no_pcmfile = 1;
4006                 else if (error) {
4007                         bwn_release_firmware(mac);
4008                         return (error);
4009                 }
4010         } else if (rev < 11) {
4011                 device_printf(sc->sc_dev, "no PCM for rev %d\n", rev);
4012                 return (EOPNOTSUPP);
4013         }
4014
4015         /* initvals */
4016         high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH);
4017         switch (mac->mac_phy.type) {
4018         case BWN_PHYTYPE_A:
4019                 if (rev < 5 || rev > 10)
4020                         goto fail1;
4021                 if (high & BWN_TGSHIGH_HAVE_2GHZ)
4022                         filename = "a0g1initvals5";
4023                 else
4024                         filename = "a0g0initvals5";
4025                 break;
4026         case BWN_PHYTYPE_G:
4027