Deleted Added
full compact
if_bwn.c (204983) if_bwn.c (205141)
1/*-
2 * Copyright (c) 2009-2010 Weongyo Jeong <weongyo@freebsd.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer,
10 * without modification.
11 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13 * redistribution must be conditioned upon including a substantially
14 * similar Disclaimer requirement for further binary redistribution.
15 *
16 * NO WARRANTY
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
20 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
22 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27 * THE POSSIBILITY OF SUCH DAMAGES.
28 */
29
30#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2009-2010 Weongyo Jeong <weongyo@freebsd.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer,
10 * without modification.
11 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13 * redistribution must be conditioned upon including a substantially
14 * similar Disclaimer requirement for further binary redistribution.
15 *
16 * NO WARRANTY
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
20 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
22 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27 * THE POSSIBILITY OF SUCH DAMAGES.
28 */
29
30#include <sys/cdefs.h>
31__FBSDID("$FreeBSD: head/sys/dev/bwn/if_bwn.c 204983 2010-03-10 21:45:40Z yongari $");
31__FBSDID("$FreeBSD: head/sys/dev/bwn/if_bwn.c 205141 2010-03-14 02:13:11Z weongyo $");
32
33/*
34 * The Broadcom Wireless LAN controller driver.
35 */
36
37#include <sys/param.h>
38#include <sys/systm.h>
39#include <sys/module.h>
40#include <sys/kernel.h>
41#include <sys/endian.h>
42#include <sys/errno.h>
43#include <sys/firmware.h>
44#include <sys/lock.h>
45#include <sys/mutex.h>
46#include <machine/bus.h>
47#include <machine/resource.h>
48#include <sys/bus.h>
49#include <sys/rman.h>
50#include <sys/socket.h>
51#include <sys/sockio.h>
52
53#include <net/ethernet.h>
54#include <net/if.h>
55#include <net/if_arp.h>
56#include <net/if_dl.h>
57#include <net/if_llc.h>
58#include <net/if_media.h>
59#include <net/if_types.h>
60
61#include <dev/pci/pcivar.h>
62#include <dev/pci/pcireg.h>
63#include <dev/siba/siba_ids.h>
64#include <dev/siba/sibareg.h>
65#include <dev/siba/sibavar.h>
66
67#include <net80211/ieee80211_var.h>
68#include <net80211/ieee80211_radiotap.h>
69#include <net80211/ieee80211_regdomain.h>
70#include <net80211/ieee80211_amrr.h>
71#include <net80211/ieee80211_phy.h>
72
73#include <dev/bwn/if_bwnreg.h>
74#include <dev/bwn/if_bwnvar.h>
75
76SYSCTL_NODE(_hw, OID_AUTO, bwn, CTLFLAG_RD, 0, "Broadcom driver parameters");
77
78/*
79 * Tunable & sysctl variables.
80 */
81
82#ifdef BWN_DEBUG
83static int bwn_debug = 0;
84SYSCTL_INT(_hw_bwn, OID_AUTO, debug, CTLFLAG_RW, &bwn_debug, 0,
85 "Broadcom debugging printfs");
86TUNABLE_INT("hw.bwn.debug", &bwn_debug);
87enum {
88 BWN_DEBUG_XMIT = 0x00000001, /* basic xmit operation */
89 BWN_DEBUG_RECV = 0x00000002, /* basic recv operation */
90 BWN_DEBUG_STATE = 0x00000004, /* 802.11 state transitions */
91 BWN_DEBUG_TXPOW = 0x00000008, /* tx power processing */
92 BWN_DEBUG_RESET = 0x00000010, /* reset processing */
93 BWN_DEBUG_OPS = 0x00000020, /* bwn_ops processing */
94 BWN_DEBUG_BEACON = 0x00000040, /* beacon handling */
95 BWN_DEBUG_WATCHDOG = 0x00000080, /* watchdog timeout */
96 BWN_DEBUG_INTR = 0x00000100, /* ISR */
97 BWN_DEBUG_CALIBRATE = 0x00000200, /* periodic calibration */
98 BWN_DEBUG_NODE = 0x00000400, /* node management */
99 BWN_DEBUG_LED = 0x00000800, /* led management */
100 BWN_DEBUG_CMD = 0x00001000, /* cmd submission */
101 BWN_DEBUG_LO = 0x00002000, /* LO */
102 BWN_DEBUG_FW = 0x00004000, /* firmware */
103 BWN_DEBUG_WME = 0x00008000, /* WME */
104 BWN_DEBUG_RF = 0x00010000, /* RF */
105 BWN_DEBUG_FATAL = 0x80000000, /* fatal errors */
106 BWN_DEBUG_ANY = 0xffffffff
107};
108#define DPRINTF(sc, m, fmt, ...) do { \
109 if (sc->sc_debug & (m)) \
110 printf(fmt, __VA_ARGS__); \
111} while (0)
112#else
113#define DPRINTF(sc, m, fmt, ...) do { (void) sc; } while (0)
114#endif
115
116static int bwn_bfp = 0; /* use "Bad Frames Preemption" */
117SYSCTL_INT(_hw_bwn, OID_AUTO, bfp, CTLFLAG_RW, &bwn_bfp, 0,
118 "uses Bad Frames Preemption");
119static int bwn_bluetooth = 1;
120SYSCTL_INT(_hw_bwn, OID_AUTO, bluetooth, CTLFLAG_RW, &bwn_bluetooth, 0,
121 "turns on Bluetooth Coexistence");
122static int bwn_hwpctl = 0;
123SYSCTL_INT(_hw_bwn, OID_AUTO, hwpctl, CTLFLAG_RW, &bwn_hwpctl, 0,
124 "uses H/W power control");
125static int bwn_msi_disable = 0; /* MSI disabled */
126TUNABLE_INT("hw.bwn.msi_disable", &bwn_msi_disable);
127static int bwn_usedma = 1;
128SYSCTL_INT(_hw_bwn, OID_AUTO, usedma, CTLFLAG_RD, &bwn_usedma, 0,
129 "uses DMA");
130TUNABLE_INT("hw.bwn.usedma", &bwn_usedma);
131static int bwn_wme = 1;
132SYSCTL_INT(_hw_bwn, OID_AUTO, wme, CTLFLAG_RW, &bwn_wme, 0,
133 "uses WME support");
134
135static int bwn_attach_pre(struct bwn_softc *);
136static int bwn_attach_post(struct bwn_softc *);
137static void bwn_sprom_bugfixes(device_t);
138static void bwn_init(void *);
139static int bwn_init_locked(struct bwn_softc *);
140static int bwn_ioctl(struct ifnet *, u_long, caddr_t);
141static void bwn_start(struct ifnet *);
142static int bwn_attach_core(struct bwn_mac *);
143static void bwn_reset_core(struct bwn_mac *, uint32_t);
144static int bwn_phy_getinfo(struct bwn_mac *, int);
145static int bwn_chiptest(struct bwn_mac *);
146static int bwn_setup_channels(struct bwn_mac *, int, int);
147static int bwn_phy_g_attach(struct bwn_mac *);
148static void bwn_phy_g_detach(struct bwn_mac *);
149static void bwn_phy_g_init_pre(struct bwn_mac *);
150static int bwn_phy_g_prepare_hw(struct bwn_mac *);
151static int bwn_phy_g_init(struct bwn_mac *);
152static void bwn_phy_g_exit(struct bwn_mac *);
153static uint16_t bwn_phy_g_read(struct bwn_mac *, uint16_t);
154static void bwn_phy_g_write(struct bwn_mac *, uint16_t,
155 uint16_t);
156static uint16_t bwn_phy_g_rf_read(struct bwn_mac *, uint16_t);
157static void bwn_phy_g_rf_write(struct bwn_mac *, uint16_t,
158 uint16_t);
159static int bwn_phy_g_hwpctl(struct bwn_mac *);
160static void bwn_phy_g_rf_onoff(struct bwn_mac *, int);
161static int bwn_phy_g_switch_channel(struct bwn_mac *, uint32_t);
162static uint32_t bwn_phy_g_get_default_chan(struct bwn_mac *);
163static void bwn_phy_g_set_antenna(struct bwn_mac *, int);
164static int bwn_phy_g_im(struct bwn_mac *, int);
165static int bwn_phy_g_recalc_txpwr(struct bwn_mac *, int);
166static void bwn_phy_g_set_txpwr(struct bwn_mac *);
167static void bwn_phy_g_task_15s(struct bwn_mac *);
168static void bwn_phy_g_task_60s(struct bwn_mac *);
169static uint16_t bwn_phy_g_txctl(struct bwn_mac *);
170static void bwn_phy_switch_analog(struct bwn_mac *, int);
171static uint16_t bwn_shm_read_2(struct bwn_mac *, uint16_t, uint16_t);
172static void bwn_shm_write_2(struct bwn_mac *, uint16_t, uint16_t,
173 uint16_t);
174static uint32_t bwn_shm_read_4(struct bwn_mac *, uint16_t, uint16_t);
175static void bwn_shm_write_4(struct bwn_mac *, uint16_t, uint16_t,
176 uint32_t);
177static void bwn_shm_ctlword(struct bwn_mac *, uint16_t,
178 uint16_t);
179static void bwn_addchannels(struct ieee80211_channel [], int, int *,
180 const struct bwn_channelinfo *, int);
181static int bwn_raw_xmit(struct ieee80211_node *, struct mbuf *,
182 const struct ieee80211_bpf_params *);
183static void bwn_newassoc(struct ieee80211_node *, int);
184static void bwn_updateslot(struct ifnet *);
185static void bwn_update_promisc(struct ifnet *);
186static void bwn_wme_init(struct bwn_mac *);
187static int bwn_wme_update(struct ieee80211com *);
188static struct ieee80211_node *bwn_node_alloc(struct ieee80211vap *,
189 const uint8_t [IEEE80211_ADDR_LEN]);
190static void bwn_wme_clear(struct bwn_softc *);
191static void bwn_wme_load(struct bwn_mac *);
192static void bwn_wme_loadparams(struct bwn_mac *,
193 const struct wmeParams *, uint16_t);
194static void bwn_node_cleanup(struct ieee80211_node *);
195static void bwn_scan_start(struct ieee80211com *);
196static void bwn_scan_end(struct ieee80211com *);
197static void bwn_set_channel(struct ieee80211com *);
198static struct ieee80211vap *bwn_vap_create(struct ieee80211com *,
199 const char [IFNAMSIZ], int, int,
200 int, const uint8_t [IEEE80211_ADDR_LEN],
201 const uint8_t [IEEE80211_ADDR_LEN]);
202static void bwn_vap_delete(struct ieee80211vap *);
203static void bwn_stop(struct bwn_softc *, int);
204static void bwn_stop_locked(struct bwn_softc *, int);
205static int bwn_core_init(struct bwn_mac *);
206static void bwn_core_start(struct bwn_mac *);
207static void bwn_core_exit(struct bwn_mac *);
208static void bwn_bt_disable(struct bwn_mac *);
209static int bwn_chip_init(struct bwn_mac *);
210static uint64_t bwn_hf_read(struct bwn_mac *);
211static void bwn_hf_write(struct bwn_mac *, uint64_t);
212static void bwn_set_txretry(struct bwn_mac *, int, int);
213static void bwn_rate_init(struct bwn_mac *);
214static void bwn_set_phytxctl(struct bwn_mac *);
215static void bwn_spu_setdelay(struct bwn_mac *, int);
216static void bwn_bt_enable(struct bwn_mac *);
217static void bwn_set_macaddr(struct bwn_mac *);
218static void bwn_crypt_init(struct bwn_mac *);
219static void bwn_chip_exit(struct bwn_mac *);
220static int bwn_fw_fillinfo(struct bwn_mac *);
221static int bwn_fw_loaducode(struct bwn_mac *);
222static int bwn_gpio_init(struct bwn_mac *);
223static int bwn_fw_loadinitvals(struct bwn_mac *);
224static int bwn_phy_init(struct bwn_mac *);
225static void bwn_set_txantenna(struct bwn_mac *, int);
226static void bwn_set_opmode(struct bwn_mac *);
227static void bwn_rate_write(struct bwn_mac *, uint16_t, int);
228static uint8_t bwn_plcp_getcck(const uint8_t);
229static uint8_t bwn_plcp_getofdm(const uint8_t);
230static void bwn_pio_init(struct bwn_mac *);
231static uint16_t bwn_pio_idx2base(struct bwn_mac *, int);
232static void bwn_pio_set_txqueue(struct bwn_mac *, struct bwn_pio_txqueue *,
233 int);
234static void bwn_pio_setupqueue_rx(struct bwn_mac *,
235 struct bwn_pio_rxqueue *, int);
236static void bwn_destroy_queue_tx(struct bwn_pio_txqueue *);
237static uint16_t bwn_pio_read_2(struct bwn_mac *, struct bwn_pio_txqueue *,
238 uint16_t);
239static void bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *);
240static int bwn_pio_rx(struct bwn_pio_rxqueue *);
241static uint8_t bwn_pio_rxeof(struct bwn_pio_rxqueue *);
242static void bwn_pio_handle_txeof(struct bwn_mac *,
243 const struct bwn_txstatus *);
244static uint16_t bwn_pio_rx_read_2(struct bwn_pio_rxqueue *, uint16_t);
245static uint32_t bwn_pio_rx_read_4(struct bwn_pio_rxqueue *, uint16_t);
246static void bwn_pio_rx_write_2(struct bwn_pio_rxqueue *, uint16_t,
247 uint16_t);
248static void bwn_pio_rx_write_4(struct bwn_pio_rxqueue *, uint16_t,
249 uint32_t);
250static int bwn_pio_tx_start(struct bwn_mac *, struct ieee80211_node *,
251 struct mbuf *);
252static struct bwn_pio_txqueue *bwn_pio_select(struct bwn_mac *, uint8_t);
253static uint32_t bwn_pio_write_multi_4(struct bwn_mac *,
254 struct bwn_pio_txqueue *, uint32_t, const void *, int);
255static void bwn_pio_write_4(struct bwn_mac *, struct bwn_pio_txqueue *,
256 uint16_t, uint32_t);
257static uint16_t bwn_pio_write_multi_2(struct bwn_mac *,
258 struct bwn_pio_txqueue *, uint16_t, const void *, int);
259static uint16_t bwn_pio_write_mbuf_2(struct bwn_mac *,
260 struct bwn_pio_txqueue *, uint16_t, struct mbuf *);
261static struct bwn_pio_txqueue *bwn_pio_parse_cookie(struct bwn_mac *,
262 uint16_t, struct bwn_pio_txpkt **);
263static void bwn_dma_init(struct bwn_mac *);
264static void bwn_dma_rxdirectfifo(struct bwn_mac *, int, uint8_t);
265static int bwn_dma_mask2type(uint64_t);
266static uint64_t bwn_dma_mask(struct bwn_mac *);
267static uint16_t bwn_dma_base(int, int);
268static void bwn_dma_ringfree(struct bwn_dma_ring **);
269static void bwn_dma_32_getdesc(struct bwn_dma_ring *,
270 int, struct bwn_dmadesc_generic **,
271 struct bwn_dmadesc_meta **);
272static void bwn_dma_32_setdesc(struct bwn_dma_ring *,
273 struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int,
274 int, int);
275static void bwn_dma_32_start_transfer(struct bwn_dma_ring *, int);
276static void bwn_dma_32_suspend(struct bwn_dma_ring *);
277static void bwn_dma_32_resume(struct bwn_dma_ring *);
278static int bwn_dma_32_get_curslot(struct bwn_dma_ring *);
279static void bwn_dma_32_set_curslot(struct bwn_dma_ring *, int);
280static void bwn_dma_64_getdesc(struct bwn_dma_ring *,
281 int, struct bwn_dmadesc_generic **,
282 struct bwn_dmadesc_meta **);
283static void bwn_dma_64_setdesc(struct bwn_dma_ring *,
284 struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int,
285 int, int);
286static void bwn_dma_64_start_transfer(struct bwn_dma_ring *, int);
287static void bwn_dma_64_suspend(struct bwn_dma_ring *);
288static void bwn_dma_64_resume(struct bwn_dma_ring *);
289static int bwn_dma_64_get_curslot(struct bwn_dma_ring *);
290static void bwn_dma_64_set_curslot(struct bwn_dma_ring *, int);
291static int bwn_dma_allocringmemory(struct bwn_dma_ring *);
292static void bwn_dma_setup(struct bwn_dma_ring *);
293static void bwn_dma_free_ringmemory(struct bwn_dma_ring *);
294static void bwn_dma_cleanup(struct bwn_dma_ring *);
295static void bwn_dma_free_descbufs(struct bwn_dma_ring *);
296static int bwn_dma_tx_reset(struct bwn_mac *, uint16_t, int);
297static void bwn_dma_rx(struct bwn_dma_ring *);
298static int bwn_dma_rx_reset(struct bwn_mac *, uint16_t, int);
299static void bwn_dma_free_descbuf(struct bwn_dma_ring *,
300 struct bwn_dmadesc_meta *);
301static void bwn_dma_set_redzone(struct bwn_dma_ring *, struct mbuf *);
302static int bwn_dma_gettype(struct bwn_mac *);
303static void bwn_dma_ring_addr(void *, bus_dma_segment_t *, int, int);
304static int bwn_dma_freeslot(struct bwn_dma_ring *);
305static int bwn_dma_nextslot(struct bwn_dma_ring *, int);
306static void bwn_dma_rxeof(struct bwn_dma_ring *, int *);
307static int bwn_dma_newbuf(struct bwn_dma_ring *,
308 struct bwn_dmadesc_generic *, struct bwn_dmadesc_meta *,
309 int);
310static void bwn_dma_buf_addr(void *, bus_dma_segment_t *, int,
311 bus_size_t, int);
312static uint8_t bwn_dma_check_redzone(struct bwn_dma_ring *, struct mbuf *);
313static void bwn_dma_handle_txeof(struct bwn_mac *,
314 const struct bwn_txstatus *);
315static int bwn_dma_tx_start(struct bwn_mac *, struct ieee80211_node *,
316 struct mbuf *);
317static int bwn_dma_getslot(struct bwn_dma_ring *);
318static struct bwn_dma_ring *bwn_dma_select(struct bwn_mac *,
319 uint8_t);
320static int bwn_dma_attach(struct bwn_mac *);
321static struct bwn_dma_ring *bwn_dma_ringsetup(struct bwn_mac *,
322 int, int, int);
323static struct bwn_dma_ring *bwn_dma_parse_cookie(struct bwn_mac *,
324 const struct bwn_txstatus *, uint16_t, int *);
325static void bwn_dma_free(struct bwn_mac *);
326static void bwn_phy_g_init_sub(struct bwn_mac *);
327static uint8_t bwn_has_hwpctl(struct bwn_mac *);
328static void bwn_phy_init_b5(struct bwn_mac *);
329static void bwn_phy_init_b6(struct bwn_mac *);
330static void bwn_phy_init_a(struct bwn_mac *);
331static void bwn_loopback_calcgain(struct bwn_mac *);
332static uint16_t bwn_rf_init_bcm2050(struct bwn_mac *);
333static void bwn_lo_g_init(struct bwn_mac *);
334static void bwn_lo_g_adjust(struct bwn_mac *);
335static void bwn_lo_get_powervector(struct bwn_mac *);
336static struct bwn_lo_calib *bwn_lo_calibset(struct bwn_mac *,
337 const struct bwn_bbatt *, const struct bwn_rfatt *);
338static void bwn_lo_write(struct bwn_mac *, struct bwn_loctl *);
339static void bwn_phy_hwpctl_init(struct bwn_mac *);
340static void bwn_phy_g_switch_chan(struct bwn_mac *, int, uint8_t);
341static void bwn_phy_g_set_txpwr_sub(struct bwn_mac *,
342 const struct bwn_bbatt *, const struct bwn_rfatt *,
343 uint8_t);
344static void bwn_phy_g_set_bbatt(struct bwn_mac *, uint16_t);
345static uint16_t bwn_rf_2050_rfoverval(struct bwn_mac *, uint16_t, uint32_t);
346static void bwn_spu_workaround(struct bwn_mac *, uint8_t);
347static void bwn_wa_init(struct bwn_mac *);
348static void bwn_ofdmtab_write_2(struct bwn_mac *, uint16_t, uint16_t,
349 uint16_t);
350static void bwn_dummy_transmission(struct bwn_mac *, int, int);
351static void bwn_ofdmtab_write_4(struct bwn_mac *, uint16_t, uint16_t,
352 uint32_t);
353static void bwn_gtab_write(struct bwn_mac *, uint16_t, uint16_t,
354 uint16_t);
355static void bwn_ram_write(struct bwn_mac *, uint16_t, uint32_t);
356static void bwn_mac_suspend(struct bwn_mac *);
357static void bwn_mac_enable(struct bwn_mac *);
358static void bwn_psctl(struct bwn_mac *, uint32_t);
359static int16_t bwn_nrssi_read(struct bwn_mac *, uint16_t);
360static void bwn_nrssi_offset(struct bwn_mac *);
361static void bwn_nrssi_threshold(struct bwn_mac *);
362static void bwn_nrssi_slope_11g(struct bwn_mac *);
363static void bwn_set_all_gains(struct bwn_mac *, int16_t, int16_t,
364 int16_t);
365static void bwn_set_original_gains(struct bwn_mac *);
366static void bwn_hwpctl_early_init(struct bwn_mac *);
367static void bwn_hwpctl_init_gphy(struct bwn_mac *);
368static uint16_t bwn_phy_g_chan2freq(uint8_t);
369static int bwn_fw_gets(struct bwn_mac *, enum bwn_fwtype);
370static int bwn_fw_get(struct bwn_mac *, enum bwn_fwtype,
371 const char *, struct bwn_fwfile *);
372static void bwn_release_firmware(struct bwn_mac *);
373static void bwn_do_release_fw(struct bwn_fwfile *);
374static uint16_t bwn_fwcaps_read(struct bwn_mac *);
375static int bwn_fwinitvals_write(struct bwn_mac *,
376 const struct bwn_fwinitvals *, size_t, size_t);
377static int bwn_switch_channel(struct bwn_mac *, int);
378static uint16_t bwn_ant2phy(int);
379static void bwn_mac_write_bssid(struct bwn_mac *);
380static void bwn_mac_setfilter(struct bwn_mac *, uint16_t,
381 const uint8_t *);
382static void bwn_key_dowrite(struct bwn_mac *, uint8_t, uint8_t,
383 const uint8_t *, size_t, const uint8_t *);
384static void bwn_key_macwrite(struct bwn_mac *, uint8_t,
385 const uint8_t *);
386static void bwn_key_write(struct bwn_mac *, uint8_t, uint8_t,
387 const uint8_t *);
388static void bwn_phy_exit(struct bwn_mac *);
389static void bwn_core_stop(struct bwn_mac *);
390static int bwn_switch_band(struct bwn_softc *,
391 struct ieee80211_channel *);
392static void bwn_phy_reset(struct bwn_mac *);
393static int bwn_newstate(struct ieee80211vap *, enum ieee80211_state, int);
394static void bwn_set_pretbtt(struct bwn_mac *);
395static int bwn_intr(void *);
396static void bwn_intrtask(void *, int);
397static void bwn_restart(struct bwn_mac *, const char *);
398static void bwn_intr_ucode_debug(struct bwn_mac *);
399static void bwn_intr_tbtt_indication(struct bwn_mac *);
400static void bwn_intr_atim_end(struct bwn_mac *);
401static void bwn_intr_beacon(struct bwn_mac *);
402static void bwn_intr_pmq(struct bwn_mac *);
403static void bwn_intr_noise(struct bwn_mac *);
404static void bwn_intr_txeof(struct bwn_mac *);
405static void bwn_hwreset(void *, int);
406static void bwn_handle_fwpanic(struct bwn_mac *);
407static void bwn_load_beacon0(struct bwn_mac *);
408static void bwn_load_beacon1(struct bwn_mac *);
409static uint32_t bwn_jssi_read(struct bwn_mac *);
410static void bwn_noise_gensample(struct bwn_mac *);
411static void bwn_handle_txeof(struct bwn_mac *,
412 const struct bwn_txstatus *);
413static void bwn_rxeof(struct bwn_mac *, struct mbuf *, const void *);
414static void bwn_phy_txpower_check(struct bwn_mac *, uint32_t);
415static void bwn_start_locked(struct ifnet *);
416static int bwn_tx_start(struct bwn_softc *, struct ieee80211_node *,
417 struct mbuf *);
418static int bwn_tx_isfull(struct bwn_softc *, struct mbuf *);
419static int bwn_set_txhdr(struct bwn_mac *,
420 struct ieee80211_node *, struct mbuf *, struct bwn_txhdr *,
421 uint16_t);
422static void bwn_plcp_genhdr(struct bwn_plcp4 *, const uint16_t,
423 const uint8_t);
424static uint8_t bwn_antenna_sanitize(struct bwn_mac *, uint8_t);
425static uint8_t bwn_get_fbrate(uint8_t);
426static int bwn_phy_shm_tssi_read(struct bwn_mac *, uint16_t);
427static void bwn_phy_g_setatt(struct bwn_mac *, int *, int *);
428static void bwn_phy_lock(struct bwn_mac *);
429static void bwn_phy_unlock(struct bwn_mac *);
430static void bwn_rf_lock(struct bwn_mac *);
431static void bwn_rf_unlock(struct bwn_mac *);
432static void bwn_txpwr(void *, int);
433static void bwn_tasks(void *);
434static void bwn_task_15s(struct bwn_mac *);
435static void bwn_task_30s(struct bwn_mac *);
436static void bwn_task_60s(struct bwn_mac *);
437static int bwn_plcp_get_ofdmrate(struct bwn_mac *, struct bwn_plcp6 *,
438 uint8_t);
439static int bwn_plcp_get_cckrate(struct bwn_mac *, struct bwn_plcp6 *);
440static void bwn_rx_radiotap(struct bwn_mac *, struct mbuf *,
441 const struct bwn_rxhdr4 *, struct bwn_plcp6 *, int,
442 int, int);
443static void bwn_tsf_read(struct bwn_mac *, uint64_t *);
444static void bwn_phy_g_dc_lookup_init(struct bwn_mac *, uint8_t);
445static void bwn_set_slot_time(struct bwn_mac *, uint16_t);
446static void bwn_watchdog(void *);
447static void bwn_dma_stop(struct bwn_mac *);
448static void bwn_pio_stop(struct bwn_mac *);
449static void bwn_dma_ringstop(struct bwn_dma_ring **);
450static void bwn_led_attach(struct bwn_mac *);
451static void bwn_led_newstate(struct bwn_mac *, enum ieee80211_state);
452static void bwn_led_event(struct bwn_mac *, int);
453static void bwn_led_blink_start(struct bwn_mac *, int, int);
454static void bwn_led_blink_next(void *);
455static void bwn_led_blink_end(void *);
456static void bwn_rfswitch(void *);
457static void bwn_rf_turnon(struct bwn_mac *);
458static void bwn_rf_turnoff(struct bwn_mac *);
459static void bwn_phy_lp_init_pre(struct bwn_mac *);
460static int bwn_phy_lp_init(struct bwn_mac *);
461static uint16_t bwn_phy_lp_read(struct bwn_mac *, uint16_t);
462static void bwn_phy_lp_write(struct bwn_mac *, uint16_t, uint16_t);
463static void bwn_phy_lp_maskset(struct bwn_mac *, uint16_t, uint16_t,
464 uint16_t);
465static uint16_t bwn_phy_lp_rf_read(struct bwn_mac *, uint16_t);
466static void bwn_phy_lp_rf_write(struct bwn_mac *, uint16_t, uint16_t);
467static void bwn_phy_lp_rf_onoff(struct bwn_mac *, int);
468static int bwn_phy_lp_switch_channel(struct bwn_mac *, uint32_t);
469static uint32_t bwn_phy_lp_get_default_chan(struct bwn_mac *);
470static void bwn_phy_lp_set_antenna(struct bwn_mac *, int);
471static void bwn_phy_lp_task_60s(struct bwn_mac *);
472static void bwn_phy_lp_readsprom(struct bwn_mac *);
473static void bwn_phy_lp_bbinit(struct bwn_mac *);
474static void bwn_phy_lp_txpctl_init(struct bwn_mac *);
475static void bwn_phy_lp_calib(struct bwn_mac *);
476static void bwn_phy_lp_switch_analog(struct bwn_mac *, int);
477static int bwn_phy_lp_b2062_switch_channel(struct bwn_mac *, uint8_t);
478static int bwn_phy_lp_b2063_switch_channel(struct bwn_mac *, uint8_t);
479static void bwn_phy_lp_set_anafilter(struct bwn_mac *, uint8_t);
480static void bwn_phy_lp_set_gaintbl(struct bwn_mac *, uint32_t);
481static void bwn_phy_lp_digflt_save(struct bwn_mac *);
482static void bwn_phy_lp_get_txpctlmode(struct bwn_mac *);
483static void bwn_phy_lp_set_txpctlmode(struct bwn_mac *, uint8_t);
484static void bwn_phy_lp_bugfix(struct bwn_mac *);
485static void bwn_phy_lp_digflt_restore(struct bwn_mac *);
486static void bwn_phy_lp_tblinit(struct bwn_mac *);
487static void bwn_phy_lp_bbinit_r2(struct bwn_mac *);
488static void bwn_phy_lp_bbinit_r01(struct bwn_mac *);
489static void bwn_phy_lp_b2062_init(struct bwn_mac *);
490static void bwn_phy_lp_b2063_init(struct bwn_mac *);
491static void bwn_phy_lp_rxcal_r2(struct bwn_mac *);
492static void bwn_phy_lp_rccal_r12(struct bwn_mac *);
493static void bwn_phy_lp_set_rccap(struct bwn_mac *);
494static uint32_t bwn_phy_lp_roundup(uint32_t, uint32_t, uint8_t);
495static void bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *);
496static void bwn_phy_lp_b2062_vco_calib(struct bwn_mac *);
497static void bwn_tab_write_multi(struct bwn_mac *, uint32_t, int,
498 const void *);
499static void bwn_tab_read_multi(struct bwn_mac *, uint32_t, int, void *);
500static struct bwn_txgain
501 bwn_phy_lp_get_txgain(struct bwn_mac *);
502static uint8_t bwn_phy_lp_get_bbmult(struct bwn_mac *);
503static void bwn_phy_lp_set_txgain(struct bwn_mac *, struct bwn_txgain *);
504static void bwn_phy_lp_set_bbmult(struct bwn_mac *, uint8_t);
505static void bwn_phy_lp_set_trsw_over(struct bwn_mac *, uint8_t, uint8_t);
506static void bwn_phy_lp_set_rxgain(struct bwn_mac *, uint32_t);
507static void bwn_phy_lp_set_deaf(struct bwn_mac *, uint8_t);
508static int bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *, uint16_t);
509static void bwn_phy_lp_clear_deaf(struct bwn_mac *, uint8_t);
510static void bwn_phy_lp_tblinit_r01(struct bwn_mac *);
511static void bwn_phy_lp_tblinit_r2(struct bwn_mac *);
512static void bwn_phy_lp_tblinit_txgain(struct bwn_mac *);
513static void bwn_tab_write(struct bwn_mac *, uint32_t, uint32_t);
514static void bwn_phy_lp_b2062_tblinit(struct bwn_mac *);
515static void bwn_phy_lp_b2063_tblinit(struct bwn_mac *);
516static int bwn_phy_lp_loopback(struct bwn_mac *);
517static void bwn_phy_lp_set_rxgain_idx(struct bwn_mac *, uint16_t);
518static void bwn_phy_lp_ddfs_turnon(struct bwn_mac *, int, int, int, int,
519 int);
520static uint8_t bwn_phy_lp_rx_iq_est(struct bwn_mac *, uint16_t, uint8_t,
521 struct bwn_phy_lp_iq_est *);
522static void bwn_phy_lp_ddfs_turnoff(struct bwn_mac *);
523static uint32_t bwn_tab_read(struct bwn_mac *, uint32_t);
524static void bwn_phy_lp_set_txgain_dac(struct bwn_mac *, uint16_t);
525static void bwn_phy_lp_set_txgain_pa(struct bwn_mac *, uint16_t);
526static void bwn_phy_lp_set_txgain_override(struct bwn_mac *);
527static uint16_t bwn_phy_lp_get_pa_gain(struct bwn_mac *);
528static uint8_t bwn_nbits(int32_t);
529static void bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *, int, int,
530 struct bwn_txgain_entry *);
531static void bwn_phy_lp_gaintbl_write(struct bwn_mac *, int,
532 struct bwn_txgain_entry);
533static void bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *, int,
534 struct bwn_txgain_entry);
535static void bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *, int,
536 struct bwn_txgain_entry);
537static void bwn_sysctl_node(struct bwn_softc *);
538
539static struct resource_spec bwn_res_spec_legacy[] = {
540 { SYS_RES_IRQ, 0, RF_ACTIVE | RF_SHAREABLE },
541 { -1, 0, 0 }
542};
543
544static struct resource_spec bwn_res_spec_msi[] = {
545 { SYS_RES_IRQ, 1, RF_ACTIVE },
546 { -1, 0, 0 }
547};
548
549static const struct bwn_channelinfo bwn_chantable_bg = {
550 .channels = {
551 { 2412, 1, 30 }, { 2417, 2, 30 }, { 2422, 3, 30 },
552 { 2427, 4, 30 }, { 2432, 5, 30 }, { 2437, 6, 30 },
553 { 2442, 7, 30 }, { 2447, 8, 30 }, { 2452, 9, 30 },
554 { 2457, 10, 30 }, { 2462, 11, 30 }, { 2467, 12, 30 },
555 { 2472, 13, 30 }, { 2484, 14, 30 } },
556 .nchannels = 14
557};
558
559static const struct bwn_channelinfo bwn_chantable_a = {
560 .channels = {
561 { 5170, 34, 30 }, { 5180, 36, 30 }, { 5190, 38, 30 },
562 { 5200, 40, 30 }, { 5210, 42, 30 }, { 5220, 44, 30 },
563 { 5230, 46, 30 }, { 5240, 48, 30 }, { 5260, 52, 30 },
564 { 5280, 56, 30 }, { 5300, 60, 30 }, { 5320, 64, 30 },
565 { 5500, 100, 30 }, { 5520, 104, 30 }, { 5540, 108, 30 },
566 { 5560, 112, 30 }, { 5580, 116, 30 }, { 5600, 120, 30 },
567 { 5620, 124, 30 }, { 5640, 128, 30 }, { 5660, 132, 30 },
568 { 5680, 136, 30 }, { 5700, 140, 30 }, { 5745, 149, 30 },
569 { 5765, 153, 30 }, { 5785, 157, 30 }, { 5805, 161, 30 },
570 { 5825, 165, 30 }, { 5920, 184, 30 }, { 5940, 188, 30 },
571 { 5960, 192, 30 }, { 5980, 196, 30 }, { 6000, 200, 30 },
572 { 6020, 204, 30 }, { 6040, 208, 30 }, { 6060, 212, 30 },
573 { 6080, 216, 30 } },
574 .nchannels = 37
575};
576
577static const struct bwn_channelinfo bwn_chantable_n = {
578 .channels = {
579 { 5160, 32, 30 }, { 5170, 34, 30 }, { 5180, 36, 30 },
580 { 5190, 38, 30 }, { 5200, 40, 30 }, { 5210, 42, 30 },
581 { 5220, 44, 30 }, { 5230, 46, 30 }, { 5240, 48, 30 },
582 { 5250, 50, 30 }, { 5260, 52, 30 }, { 5270, 54, 30 },
583 { 5280, 56, 30 }, { 5290, 58, 30 }, { 5300, 60, 30 },
584 { 5310, 62, 30 }, { 5320, 64, 30 }, { 5330, 66, 30 },
585 { 5340, 68, 30 }, { 5350, 70, 30 }, { 5360, 72, 30 },
586 { 5370, 74, 30 }, { 5380, 76, 30 }, { 5390, 78, 30 },
587 { 5400, 80, 30 }, { 5410, 82, 30 }, { 5420, 84, 30 },
588 { 5430, 86, 30 }, { 5440, 88, 30 }, { 5450, 90, 30 },
589 { 5460, 92, 30 }, { 5470, 94, 30 }, { 5480, 96, 30 },
590 { 5490, 98, 30 }, { 5500, 100, 30 }, { 5510, 102, 30 },
591 { 5520, 104, 30 }, { 5530, 106, 30 }, { 5540, 108, 30 },
592 { 5550, 110, 30 }, { 5560, 112, 30 }, { 5570, 114, 30 },
593 { 5580, 116, 30 }, { 5590, 118, 30 }, { 5600, 120, 30 },
594 { 5610, 122, 30 }, { 5620, 124, 30 }, { 5630, 126, 30 },
595 { 5640, 128, 30 }, { 5650, 130, 30 }, { 5660, 132, 30 },
596 { 5670, 134, 30 }, { 5680, 136, 30 }, { 5690, 138, 30 },
597 { 5700, 140, 30 }, { 5710, 142, 30 }, { 5720, 144, 30 },
598 { 5725, 145, 30 }, { 5730, 146, 30 }, { 5735, 147, 30 },
599 { 5740, 148, 30 }, { 5745, 149, 30 }, { 5750, 150, 30 },
600 { 5755, 151, 30 }, { 5760, 152, 30 }, { 5765, 153, 30 },
601 { 5770, 154, 30 }, { 5775, 155, 30 }, { 5780, 156, 30 },
602 { 5785, 157, 30 }, { 5790, 158, 30 }, { 5795, 159, 30 },
603 { 5800, 160, 30 }, { 5805, 161, 30 }, { 5810, 162, 30 },
604 { 5815, 163, 30 }, { 5820, 164, 30 }, { 5825, 165, 30 },
605 { 5830, 166, 30 }, { 5840, 168, 30 }, { 5850, 170, 30 },
606 { 5860, 172, 30 }, { 5870, 174, 30 }, { 5880, 176, 30 },
607 { 5890, 178, 30 }, { 5900, 180, 30 }, { 5910, 182, 30 },
608 { 5920, 184, 30 }, { 5930, 186, 30 }, { 5940, 188, 30 },
609 { 5950, 190, 30 }, { 5960, 192, 30 }, { 5970, 194, 30 },
610 { 5980, 196, 30 }, { 5990, 198, 30 }, { 6000, 200, 30 },
611 { 6010, 202, 30 }, { 6020, 204, 30 }, { 6030, 206, 30 },
612 { 6040, 208, 30 }, { 6050, 210, 30 }, { 6060, 212, 30 },
613 { 6070, 214, 30 }, { 6080, 216, 30 }, { 6090, 218, 30 },
614 { 6100, 220, 30 }, { 6110, 222, 30 }, { 6120, 224, 30 },
615 { 6130, 226, 30 }, { 6140, 228, 30 } },
616 .nchannels = 110
617};
618
619static const uint8_t bwn_b2063_chantable_data[33][12] = {
620 { 0x6f, 0x3c, 0x3c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
621 { 0x6f, 0x2c, 0x2c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
622 { 0x6f, 0x1c, 0x1c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
623 { 0x6e, 0x1c, 0x1c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
624 { 0x6e, 0xc, 0xc, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
625 { 0x6a, 0xc, 0xc, 0, 0x2, 0x5, 0xd, 0xd, 0x77, 0x80, 0x20, 0 },
626 { 0x6a, 0xc, 0xc, 0, 0x1, 0x5, 0xd, 0xc, 0x77, 0x80, 0x20, 0 },
627 { 0x6a, 0xc, 0xc, 0, 0x1, 0x4, 0xc, 0xc, 0x77, 0x80, 0x20, 0 },
628 { 0x69, 0xc, 0xc, 0, 0x1, 0x4, 0xc, 0xc, 0x77, 0x70, 0x20, 0 },
629 { 0x69, 0xc, 0xc, 0, 0x1, 0x4, 0xb, 0xc, 0x77, 0x70, 0x20, 0 },
630 { 0x69, 0xc, 0xc, 0, 0, 0x4, 0xb, 0xb, 0x77, 0x60, 0x20, 0 },
631 { 0x69, 0xc, 0xc, 0, 0, 0x3, 0xa, 0xb, 0x77, 0x60, 0x20, 0 },
632 { 0x69, 0xc, 0xc, 0, 0, 0x3, 0xa, 0xa, 0x77, 0x60, 0x20, 0 },
633 { 0x68, 0xc, 0xc, 0, 0, 0x2, 0x9, 0x9, 0x77, 0x60, 0x20, 0 },
634 { 0x68, 0xc, 0xc, 0, 0, 0x1, 0x8, 0x8, 0x77, 0x50, 0x10, 0 },
635 { 0x67, 0xc, 0xc, 0, 0, 0, 0x8, 0x8, 0x77, 0x50, 0x10, 0 },
636 { 0x64, 0xc, 0xc, 0, 0, 0, 0x2, 0x1, 0x77, 0x20, 0, 0 },
637 { 0x64, 0xc, 0xc, 0, 0, 0, 0x1, 0x1, 0x77, 0x20, 0, 0 },
638 { 0x63, 0xc, 0xc, 0, 0, 0, 0x1, 0, 0x77, 0x10, 0, 0 },
639 { 0x63, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0x10, 0, 0 },
640 { 0x62, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0x10, 0, 0 },
641 { 0x62, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
642 { 0x61, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
643 { 0x60, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
644 { 0x6e, 0xc, 0xc, 0, 0x9, 0xe, 0xf, 0xf, 0x77, 0xc0, 0x50, 0 },
645 { 0x6e, 0xc, 0xc, 0, 0x9, 0xd, 0xf, 0xf, 0x77, 0xb0, 0x50, 0 },
646 { 0x6e, 0xc, 0xc, 0, 0x8, 0xc, 0xf, 0xf, 0x77, 0xb0, 0x50, 0 },
647 { 0x6d, 0xc, 0xc, 0, 0x8, 0xc, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
648 { 0x6d, 0xc, 0xc, 0, 0x8, 0xb, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
649 { 0x6d, 0xc, 0xc, 0, 0x8, 0xa, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
650 { 0x6c, 0xc, 0xc, 0, 0x7, 0x9, 0xf, 0xf, 0x77, 0x90, 0x40, 0 },
651 { 0x6c, 0xc, 0xc, 0, 0x6, 0x8, 0xf, 0xf, 0x77, 0x90, 0x40, 0 },
652 { 0x6c, 0xc, 0xc, 0, 0x5, 0x8, 0xf, 0xf, 0x77, 0x90, 0x40, 0 }
653};
654
655static const struct bwn_b206x_chan bwn_b2063_chantable[] = {
656 { 1, 2412, bwn_b2063_chantable_data[0] },
657 { 2, 2417, bwn_b2063_chantable_data[0] },
658 { 3, 2422, bwn_b2063_chantable_data[0] },
659 { 4, 2427, bwn_b2063_chantable_data[1] },
660 { 5, 2432, bwn_b2063_chantable_data[1] },
661 { 6, 2437, bwn_b2063_chantable_data[1] },
662 { 7, 2442, bwn_b2063_chantable_data[1] },
663 { 8, 2447, bwn_b2063_chantable_data[1] },
664 { 9, 2452, bwn_b2063_chantable_data[2] },
665 { 10, 2457, bwn_b2063_chantable_data[2] },
666 { 11, 2462, bwn_b2063_chantable_data[3] },
667 { 12, 2467, bwn_b2063_chantable_data[3] },
668 { 13, 2472, bwn_b2063_chantable_data[3] },
669 { 14, 2484, bwn_b2063_chantable_data[4] },
670 { 34, 5170, bwn_b2063_chantable_data[5] },
671 { 36, 5180, bwn_b2063_chantable_data[6] },
672 { 38, 5190, bwn_b2063_chantable_data[7] },
673 { 40, 5200, bwn_b2063_chantable_data[8] },
674 { 42, 5210, bwn_b2063_chantable_data[9] },
675 { 44, 5220, bwn_b2063_chantable_data[10] },
676 { 46, 5230, bwn_b2063_chantable_data[11] },
677 { 48, 5240, bwn_b2063_chantable_data[12] },
678 { 52, 5260, bwn_b2063_chantable_data[13] },
679 { 56, 5280, bwn_b2063_chantable_data[14] },
680 { 60, 5300, bwn_b2063_chantable_data[14] },
681 { 64, 5320, bwn_b2063_chantable_data[15] },
682 { 100, 5500, bwn_b2063_chantable_data[16] },
683 { 104, 5520, bwn_b2063_chantable_data[17] },
684 { 108, 5540, bwn_b2063_chantable_data[18] },
685 { 112, 5560, bwn_b2063_chantable_data[19] },
686 { 116, 5580, bwn_b2063_chantable_data[20] },
687 { 120, 5600, bwn_b2063_chantable_data[21] },
688 { 124, 5620, bwn_b2063_chantable_data[21] },
689 { 128, 5640, bwn_b2063_chantable_data[22] },
690 { 132, 5660, bwn_b2063_chantable_data[22] },
691 { 136, 5680, bwn_b2063_chantable_data[22] },
692 { 140, 5700, bwn_b2063_chantable_data[23] },
693 { 149, 5745, bwn_b2063_chantable_data[23] },
694 { 153, 5765, bwn_b2063_chantable_data[23] },
695 { 157, 5785, bwn_b2063_chantable_data[23] },
696 { 161, 5805, bwn_b2063_chantable_data[23] },
697 { 165, 5825, bwn_b2063_chantable_data[23] },
698 { 184, 4920, bwn_b2063_chantable_data[24] },
699 { 188, 4940, bwn_b2063_chantable_data[25] },
700 { 192, 4960, bwn_b2063_chantable_data[26] },
701 { 196, 4980, bwn_b2063_chantable_data[27] },
702 { 200, 5000, bwn_b2063_chantable_data[28] },
703 { 204, 5020, bwn_b2063_chantable_data[29] },
704 { 208, 5040, bwn_b2063_chantable_data[30] },
705 { 212, 5060, bwn_b2063_chantable_data[31] },
706 { 216, 5080, bwn_b2063_chantable_data[32] }
707};
708
709static const uint8_t bwn_b2062_chantable_data[22][12] = {
710 { 0xff, 0xff, 0xb5, 0x1b, 0x24, 0x32, 0x32, 0x88, 0x88, 0, 0, 0 },
711 { 0, 0x22, 0x20, 0x84, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
712 { 0, 0x11, 0x10, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
713 { 0, 0, 0, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
714 { 0, 0x11, 0x20, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
715 { 0, 0x11, 0x10, 0x84, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
716 { 0, 0x11, 0, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
717 { 0, 0, 0, 0x63, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
718 { 0, 0, 0, 0x62, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
719 { 0, 0, 0, 0x30, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
720 { 0, 0, 0, 0x20, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
721 { 0, 0, 0, 0x10, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
722 { 0, 0, 0, 0, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
723 { 0x55, 0x77, 0x90, 0xf7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
724 { 0x44, 0x77, 0x80, 0xe7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
725 { 0x44, 0x66, 0x80, 0xe7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
726 { 0x33, 0x66, 0x70, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
727 { 0x22, 0x55, 0x60, 0xd7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
728 { 0x22, 0x55, 0x60, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
729 { 0x22, 0x44, 0x50, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
730 { 0x11, 0x44, 0x50, 0xa5, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
731 { 0, 0x44, 0x40, 0xb6, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 }
732};
733
734static const struct bwn_b206x_chan bwn_b2062_chantable[] = {
735 { 1, 2412, bwn_b2062_chantable_data[0] },
736 { 2, 2417, bwn_b2062_chantable_data[0] },
737 { 3, 2422, bwn_b2062_chantable_data[0] },
738 { 4, 2427, bwn_b2062_chantable_data[0] },
739 { 5, 2432, bwn_b2062_chantable_data[0] },
740 { 6, 2437, bwn_b2062_chantable_data[0] },
741 { 7, 2442, bwn_b2062_chantable_data[0] },
742 { 8, 2447, bwn_b2062_chantable_data[0] },
743 { 9, 2452, bwn_b2062_chantable_data[0] },
744 { 10, 2457, bwn_b2062_chantable_data[0] },
745 { 11, 2462, bwn_b2062_chantable_data[0] },
746 { 12, 2467, bwn_b2062_chantable_data[0] },
747 { 13, 2472, bwn_b2062_chantable_data[0] },
748 { 14, 2484, bwn_b2062_chantable_data[0] },
749 { 34, 5170, bwn_b2062_chantable_data[1] },
750 { 38, 5190, bwn_b2062_chantable_data[2] },
751 { 42, 5210, bwn_b2062_chantable_data[2] },
752 { 46, 5230, bwn_b2062_chantable_data[3] },
753 { 36, 5180, bwn_b2062_chantable_data[4] },
754 { 40, 5200, bwn_b2062_chantable_data[5] },
755 { 44, 5220, bwn_b2062_chantable_data[6] },
756 { 48, 5240, bwn_b2062_chantable_data[3] },
757 { 52, 5260, bwn_b2062_chantable_data[3] },
758 { 56, 5280, bwn_b2062_chantable_data[3] },
759 { 60, 5300, bwn_b2062_chantable_data[7] },
760 { 64, 5320, bwn_b2062_chantable_data[8] },
761 { 100, 5500, bwn_b2062_chantable_data[9] },
762 { 104, 5520, bwn_b2062_chantable_data[10] },
763 { 108, 5540, bwn_b2062_chantable_data[10] },
764 { 112, 5560, bwn_b2062_chantable_data[10] },
765 { 116, 5580, bwn_b2062_chantable_data[11] },
766 { 120, 5600, bwn_b2062_chantable_data[12] },
767 { 124, 5620, bwn_b2062_chantable_data[12] },
768 { 128, 5640, bwn_b2062_chantable_data[12] },
769 { 132, 5660, bwn_b2062_chantable_data[12] },
770 { 136, 5680, bwn_b2062_chantable_data[12] },
771 { 140, 5700, bwn_b2062_chantable_data[12] },
772 { 149, 5745, bwn_b2062_chantable_data[12] },
773 { 153, 5765, bwn_b2062_chantable_data[12] },
774 { 157, 5785, bwn_b2062_chantable_data[12] },
775 { 161, 5805, bwn_b2062_chantable_data[12] },
776 { 165, 5825, bwn_b2062_chantable_data[12] },
777 { 184, 4920, bwn_b2062_chantable_data[13] },
778 { 188, 4940, bwn_b2062_chantable_data[14] },
779 { 192, 4960, bwn_b2062_chantable_data[15] },
780 { 196, 4980, bwn_b2062_chantable_data[16] },
781 { 200, 5000, bwn_b2062_chantable_data[17] },
782 { 204, 5020, bwn_b2062_chantable_data[18] },
783 { 208, 5040, bwn_b2062_chantable_data[19] },
784 { 212, 5060, bwn_b2062_chantable_data[20] },
785 { 216, 5080, bwn_b2062_chantable_data[21] }
786};
787
788/* for LP PHY */
789static const struct bwn_rxcompco bwn_rxcompco_5354[] = {
790 { 1, -66, 15 }, { 2, -66, 15 }, { 3, -66, 15 }, { 4, -66, 15 },
791 { 5, -66, 15 }, { 6, -66, 15 }, { 7, -66, 14 }, { 8, -66, 14 },
792 { 9, -66, 14 }, { 10, -66, 14 }, { 11, -66, 14 }, { 12, -66, 13 },
793 { 13, -66, 13 }, { 14, -66, 13 },
794};
795
796/* for LP PHY */
797static const struct bwn_rxcompco bwn_rxcompco_r12[] = {
798 { 1, -64, 13 }, { 2, -64, 13 }, { 3, -64, 13 }, { 4, -64, 13 },
799 { 5, -64, 12 }, { 6, -64, 12 }, { 7, -64, 12 }, { 8, -64, 12 },
800 { 9, -64, 12 }, { 10, -64, 11 }, { 11, -64, 11 }, { 12, -64, 11 },
801 { 13, -64, 11 }, { 14, -64, 10 }, { 34, -62, 24 }, { 38, -62, 24 },
802 { 42, -62, 24 }, { 46, -62, 23 }, { 36, -62, 24 }, { 40, -62, 24 },
803 { 44, -62, 23 }, { 48, -62, 23 }, { 52, -62, 23 }, { 56, -62, 22 },
804 { 60, -62, 22 }, { 64, -62, 22 }, { 100, -62, 16 }, { 104, -62, 16 },
805 { 108, -62, 15 }, { 112, -62, 14 }, { 116, -62, 14 }, { 120, -62, 13 },
806 { 124, -62, 12 }, { 128, -62, 12 }, { 132, -62, 12 }, { 136, -62, 11 },
807 { 140, -62, 10 }, { 149, -61, 9 }, { 153, -61, 9 }, { 157, -61, 9 },
808 { 161, -61, 8 }, { 165, -61, 8 }, { 184, -62, 25 }, { 188, -62, 25 },
809 { 192, -62, 25 }, { 196, -62, 25 }, { 200, -62, 25 }, { 204, -62, 25 },
810 { 208, -62, 25 }, { 212, -62, 25 }, { 216, -62, 26 },
811};
812
813static const struct bwn_rxcompco bwn_rxcompco_r2 = { 0, -64, 0 };
814
815static const uint8_t bwn_tab_sigsq_tbl[] = {
816 0xde, 0xdc, 0xda, 0xd8, 0xd6, 0xd4, 0xd2, 0xcf, 0xcd,
817 0xca, 0xc7, 0xc4, 0xc1, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
818 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0x00,
819 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
820 0xbe, 0xbe, 0xbe, 0xbe, 0xc1, 0xc4, 0xc7, 0xca, 0xcd,
821 0xcf, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
822};
823
824static const uint8_t bwn_tab_pllfrac_tbl[] = {
825 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x80,
826 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
827};
828
829static const uint16_t bwn_tabl_iqlocal_tbl[] = {
830 0x0200, 0x0300, 0x0400, 0x0600, 0x0800, 0x0b00, 0x1000, 0x1001, 0x1002,
831 0x1003, 0x1004, 0x1005, 0x1006, 0x1007, 0x1707, 0x2007, 0x2d07, 0x4007,
832 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
833 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0200, 0x0300, 0x0400, 0x0600,
834 0x0800, 0x0b00, 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006,
835 0x1007, 0x1707, 0x2007, 0x2d07, 0x4007, 0x0000, 0x0000, 0x0000, 0x0000,
836 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
837 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
838 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
839 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4000, 0x0000, 0x0000,
840 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
841 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
842};
843
844static const uint16_t bwn_tab_noise_g1[] = BWN_TAB_NOISE_G1;
845static const uint16_t bwn_tab_noise_g2[] = BWN_TAB_NOISE_G2;
846static const uint16_t bwn_tab_noisescale_g1[] = BWN_TAB_NOISESCALE_G1;
847static const uint16_t bwn_tab_noisescale_g2[] = BWN_TAB_NOISESCALE_G2;
848static const uint16_t bwn_tab_noisescale_g3[] = BWN_TAB_NOISESCALE_G3;
849const uint8_t bwn_bitrev_table[256] = BWN_BITREV_TABLE;
850
851#define VENDOR_LED_ACT(vendor) \
852{ \
853 .vid = PCI_VENDOR_##vendor, \
854 .led_act = { BWN_VENDOR_LED_ACT_##vendor } \
855}
856
857static const struct {
858 uint16_t vid;
859 uint8_t led_act[BWN_LED_MAX];
860} bwn_vendor_led_act[] = {
861 VENDOR_LED_ACT(COMPAQ),
862 VENDOR_LED_ACT(ASUSTEK)
863};
864
865static const uint8_t bwn_default_led_act[BWN_LED_MAX] =
866 { BWN_VENDOR_LED_ACT_DEFAULT };
867
868#undef VENDOR_LED_ACT
869
870static const struct {
871 int on_dur;
872 int off_dur;
873} bwn_led_duration[109] = {
874 [0] = { 400, 100 },
875 [2] = { 150, 75 },
876 [4] = { 90, 45 },
877 [11] = { 66, 34 },
878 [12] = { 53, 26 },
879 [18] = { 42, 21 },
880 [22] = { 35, 17 },
881 [24] = { 32, 16 },
882 [36] = { 21, 10 },
883 [48] = { 16, 8 },
884 [72] = { 11, 5 },
885 [96] = { 9, 4 },
886 [108] = { 7, 3 }
887};
888
889static const uint16_t bwn_wme_shm_offsets[] = {
890 [0] = BWN_WME_BESTEFFORT,
891 [1] = BWN_WME_BACKGROUND,
892 [2] = BWN_WME_VOICE,
893 [3] = BWN_WME_VIDEO,
894};
895
896static const struct siba_devid bwn_devs[] = {
897 SIBA_DEV(BROADCOM, 80211, 5, "Revision 5"),
898 SIBA_DEV(BROADCOM, 80211, 6, "Revision 6"),
899 SIBA_DEV(BROADCOM, 80211, 7, "Revision 7"),
900 SIBA_DEV(BROADCOM, 80211, 9, "Revision 9"),
901 SIBA_DEV(BROADCOM, 80211, 10, "Revision 10"),
902 SIBA_DEV(BROADCOM, 80211, 11, "Revision 11"),
903 SIBA_DEV(BROADCOM, 80211, 13, "Revision 13"),
904 SIBA_DEV(BROADCOM, 80211, 15, "Revision 15"),
905 SIBA_DEV(BROADCOM, 80211, 16, "Revision 16")
906};
907
908static int
909bwn_probe(device_t dev)
910{
911 int i;
912
913 for (i = 0; i < sizeof(bwn_devs) / sizeof(bwn_devs[0]); i++) {
914 if (siba_get_vendor(dev) == bwn_devs[i].sd_vendor &&
915 siba_get_device(dev) == bwn_devs[i].sd_device &&
916 siba_get_revid(dev) == bwn_devs[i].sd_rev)
917 return (BUS_PROBE_DEFAULT);
918 }
919
920 return (ENXIO);
921}
922
923static int
924bwn_attach(device_t dev)
925{
926 struct bwn_mac *mac;
927 struct bwn_softc *sc = device_get_softc(dev);
928 int error, i, msic, reg;
929
930 sc->sc_dev = dev;
931#ifdef BWN_DEBUG
932 sc->sc_debug = bwn_debug;
933#endif
934
935 if ((sc->sc_flags & BWN_FLAG_ATTACHED) == 0) {
936 error = bwn_attach_pre(sc);
937 if (error != 0)
938 return (error);
939 bwn_sprom_bugfixes(dev);
940 sc->sc_flags |= BWN_FLAG_ATTACHED;
941 }
942
943 if (!TAILQ_EMPTY(&sc->sc_maclist)) {
944 if (siba_get_pci_device(dev) != 0x4313 &&
945 siba_get_pci_device(dev) != 0x431a &&
946 siba_get_pci_device(dev) != 0x4321) {
947 device_printf(sc->sc_dev,
948 "skip 802.11 cores\n");
949 return (ENODEV);
950 }
951 }
952
953 mac = (struct bwn_mac *)malloc(sizeof(*mac), M_DEVBUF,
954 M_NOWAIT | M_ZERO);
955 if (mac == NULL)
956 return (ENOMEM);
957 mac->mac_sc = sc;
958 mac->mac_status = BWN_MAC_STATUS_UNINIT;
959 if (bwn_bfp != 0)
960 mac->mac_flags |= BWN_MAC_FLAG_BADFRAME_PREEMP;
961
962 TASK_INIT(&mac->mac_hwreset, 0, bwn_hwreset, mac);
963 TASK_INIT(&mac->mac_intrtask, 0, bwn_intrtask, mac);
964 TASK_INIT(&mac->mac_txpower, 0, bwn_txpwr, mac);
965
966 error = bwn_attach_core(mac);
967 if (error)
968 goto fail0;
969 bwn_led_attach(mac);
970
971 device_printf(sc->sc_dev, "WLAN (chipid %#x rev %u) "
972 "PHY (analog %d type %d rev %d) RADIO (manuf %#x ver %#x rev %d)\n",
973 siba_get_chipid(sc->sc_dev), siba_get_revid(sc->sc_dev),
974 mac->mac_phy.analog, mac->mac_phy.type, mac->mac_phy.rev,
975 mac->mac_phy.rf_manuf, mac->mac_phy.rf_ver,
976 mac->mac_phy.rf_rev);
977 if (mac->mac_flags & BWN_MAC_FLAG_DMA)
978 device_printf(sc->sc_dev, "DMA (%d bits)\n",
979 mac->mac_method.dma.dmatype);
980 else
981 device_printf(sc->sc_dev, "PIO\n");
982
983 /*
984 * setup PCI resources and interrupt.
985 */
986 if (pci_find_extcap(dev, PCIY_EXPRESS, &reg) == 0) {
987 msic = pci_msi_count(dev);
988 if (bootverbose)
989 device_printf(sc->sc_dev, "MSI count : %d\n", msic);
990 } else
991 msic = 0;
992
993 mac->mac_intr_spec = bwn_res_spec_legacy;
994 if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0) {
995 if (pci_alloc_msi(dev, &msic) == 0) {
996 device_printf(sc->sc_dev,
997 "Using %d MSI messages\n", msic);
998 mac->mac_intr_spec = bwn_res_spec_msi;
999 mac->mac_msi = 1;
1000 }
1001 }
1002
1003 error = bus_alloc_resources(dev, mac->mac_intr_spec,
1004 mac->mac_res_irq);
1005 if (error) {
1006 device_printf(sc->sc_dev,
1007 "couldn't allocate IRQ resources (%d)\n", error);
1008 goto fail1;
1009 }
1010
1011 if (mac->mac_msi == 0)
1012 error = bus_setup_intr(dev, mac->mac_res_irq[0],
1013 INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac,
1014 &mac->mac_intrhand[0]);
1015 else {
1016 for (i = 0; i < BWN_MSI_MESSAGES; i++) {
1017 error = bus_setup_intr(dev, mac->mac_res_irq[i],
1018 INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac,
1019 &mac->mac_intrhand[i]);
1020 if (error != 0) {
1021 device_printf(sc->sc_dev,
1022 "couldn't setup interrupt (%d)\n", error);
1023 break;
1024 }
1025 }
1026 }
1027
1028 TAILQ_INSERT_TAIL(&sc->sc_maclist, mac, mac_list);
1029
1030 /*
1031 * calls attach-post routine
1032 */
1033 if ((sc->sc_flags & BWN_FLAG_ATTACHED) != 0)
1034 bwn_attach_post(sc);
1035
1036 return (0);
1037fail1:
1038 if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0)
1039 pci_release_msi(dev);
1040fail0:
1041 free(mac, M_DEVBUF);
1042 return (error);
1043}
1044
1045static int
1046bwn_is_valid_ether_addr(uint8_t *addr)
1047{
1048 char zero_addr[6] = { 0, 0, 0, 0, 0, 0 };
1049
1050 if ((addr[0] & 1) || (!bcmp(addr, zero_addr, ETHER_ADDR_LEN)))
1051 return (FALSE);
1052
1053 return (TRUE);
1054}
1055
1056static int
1057bwn_attach_post(struct bwn_softc *sc)
1058{
1059 struct ieee80211com *ic;
1060 struct ifnet *ifp = sc->sc_ifp;
1061
1062 ic = ifp->if_l2com;
1063 ic->ic_ifp = ifp;
1064 /* XXX not right but it's not used anywhere important */
1065 ic->ic_phytype = IEEE80211_T_OFDM;
1066 ic->ic_opmode = IEEE80211_M_STA;
1067 ic->ic_caps =
1068 IEEE80211_C_STA /* station mode supported */
1069 | IEEE80211_C_MONITOR /* monitor mode */
1070 | IEEE80211_C_AHDEMO /* adhoc demo mode */
1071 | IEEE80211_C_SHPREAMBLE /* short preamble supported */
1072 | IEEE80211_C_SHSLOT /* short slot time supported */
1073 | IEEE80211_C_WME /* WME/WMM supported */
1074 | IEEE80211_C_WPA /* capable of WPA1+WPA2 */
1075 | IEEE80211_C_BGSCAN /* capable of bg scanning */
1076 | IEEE80211_C_TXPMGT /* capable of txpow mgt */
1077 ;
1078
32
33/*
34 * The Broadcom Wireless LAN controller driver.
35 */
36
37#include <sys/param.h>
38#include <sys/systm.h>
39#include <sys/module.h>
40#include <sys/kernel.h>
41#include <sys/endian.h>
42#include <sys/errno.h>
43#include <sys/firmware.h>
44#include <sys/lock.h>
45#include <sys/mutex.h>
46#include <machine/bus.h>
47#include <machine/resource.h>
48#include <sys/bus.h>
49#include <sys/rman.h>
50#include <sys/socket.h>
51#include <sys/sockio.h>
52
53#include <net/ethernet.h>
54#include <net/if.h>
55#include <net/if_arp.h>
56#include <net/if_dl.h>
57#include <net/if_llc.h>
58#include <net/if_media.h>
59#include <net/if_types.h>
60
61#include <dev/pci/pcivar.h>
62#include <dev/pci/pcireg.h>
63#include <dev/siba/siba_ids.h>
64#include <dev/siba/sibareg.h>
65#include <dev/siba/sibavar.h>
66
67#include <net80211/ieee80211_var.h>
68#include <net80211/ieee80211_radiotap.h>
69#include <net80211/ieee80211_regdomain.h>
70#include <net80211/ieee80211_amrr.h>
71#include <net80211/ieee80211_phy.h>
72
73#include <dev/bwn/if_bwnreg.h>
74#include <dev/bwn/if_bwnvar.h>
75
76SYSCTL_NODE(_hw, OID_AUTO, bwn, CTLFLAG_RD, 0, "Broadcom driver parameters");
77
78/*
79 * Tunable & sysctl variables.
80 */
81
82#ifdef BWN_DEBUG
83static int bwn_debug = 0;
84SYSCTL_INT(_hw_bwn, OID_AUTO, debug, CTLFLAG_RW, &bwn_debug, 0,
85 "Broadcom debugging printfs");
86TUNABLE_INT("hw.bwn.debug", &bwn_debug);
87enum {
88 BWN_DEBUG_XMIT = 0x00000001, /* basic xmit operation */
89 BWN_DEBUG_RECV = 0x00000002, /* basic recv operation */
90 BWN_DEBUG_STATE = 0x00000004, /* 802.11 state transitions */
91 BWN_DEBUG_TXPOW = 0x00000008, /* tx power processing */
92 BWN_DEBUG_RESET = 0x00000010, /* reset processing */
93 BWN_DEBUG_OPS = 0x00000020, /* bwn_ops processing */
94 BWN_DEBUG_BEACON = 0x00000040, /* beacon handling */
95 BWN_DEBUG_WATCHDOG = 0x00000080, /* watchdog timeout */
96 BWN_DEBUG_INTR = 0x00000100, /* ISR */
97 BWN_DEBUG_CALIBRATE = 0x00000200, /* periodic calibration */
98 BWN_DEBUG_NODE = 0x00000400, /* node management */
99 BWN_DEBUG_LED = 0x00000800, /* led management */
100 BWN_DEBUG_CMD = 0x00001000, /* cmd submission */
101 BWN_DEBUG_LO = 0x00002000, /* LO */
102 BWN_DEBUG_FW = 0x00004000, /* firmware */
103 BWN_DEBUG_WME = 0x00008000, /* WME */
104 BWN_DEBUG_RF = 0x00010000, /* RF */
105 BWN_DEBUG_FATAL = 0x80000000, /* fatal errors */
106 BWN_DEBUG_ANY = 0xffffffff
107};
108#define DPRINTF(sc, m, fmt, ...) do { \
109 if (sc->sc_debug & (m)) \
110 printf(fmt, __VA_ARGS__); \
111} while (0)
112#else
113#define DPRINTF(sc, m, fmt, ...) do { (void) sc; } while (0)
114#endif
115
116static int bwn_bfp = 0; /* use "Bad Frames Preemption" */
117SYSCTL_INT(_hw_bwn, OID_AUTO, bfp, CTLFLAG_RW, &bwn_bfp, 0,
118 "uses Bad Frames Preemption");
119static int bwn_bluetooth = 1;
120SYSCTL_INT(_hw_bwn, OID_AUTO, bluetooth, CTLFLAG_RW, &bwn_bluetooth, 0,
121 "turns on Bluetooth Coexistence");
122static int bwn_hwpctl = 0;
123SYSCTL_INT(_hw_bwn, OID_AUTO, hwpctl, CTLFLAG_RW, &bwn_hwpctl, 0,
124 "uses H/W power control");
125static int bwn_msi_disable = 0; /* MSI disabled */
126TUNABLE_INT("hw.bwn.msi_disable", &bwn_msi_disable);
127static int bwn_usedma = 1;
128SYSCTL_INT(_hw_bwn, OID_AUTO, usedma, CTLFLAG_RD, &bwn_usedma, 0,
129 "uses DMA");
130TUNABLE_INT("hw.bwn.usedma", &bwn_usedma);
131static int bwn_wme = 1;
132SYSCTL_INT(_hw_bwn, OID_AUTO, wme, CTLFLAG_RW, &bwn_wme, 0,
133 "uses WME support");
134
135static int bwn_attach_pre(struct bwn_softc *);
136static int bwn_attach_post(struct bwn_softc *);
137static void bwn_sprom_bugfixes(device_t);
138static void bwn_init(void *);
139static int bwn_init_locked(struct bwn_softc *);
140static int bwn_ioctl(struct ifnet *, u_long, caddr_t);
141static void bwn_start(struct ifnet *);
142static int bwn_attach_core(struct bwn_mac *);
143static void bwn_reset_core(struct bwn_mac *, uint32_t);
144static int bwn_phy_getinfo(struct bwn_mac *, int);
145static int bwn_chiptest(struct bwn_mac *);
146static int bwn_setup_channels(struct bwn_mac *, int, int);
147static int bwn_phy_g_attach(struct bwn_mac *);
148static void bwn_phy_g_detach(struct bwn_mac *);
149static void bwn_phy_g_init_pre(struct bwn_mac *);
150static int bwn_phy_g_prepare_hw(struct bwn_mac *);
151static int bwn_phy_g_init(struct bwn_mac *);
152static void bwn_phy_g_exit(struct bwn_mac *);
153static uint16_t bwn_phy_g_read(struct bwn_mac *, uint16_t);
154static void bwn_phy_g_write(struct bwn_mac *, uint16_t,
155 uint16_t);
156static uint16_t bwn_phy_g_rf_read(struct bwn_mac *, uint16_t);
157static void bwn_phy_g_rf_write(struct bwn_mac *, uint16_t,
158 uint16_t);
159static int bwn_phy_g_hwpctl(struct bwn_mac *);
160static void bwn_phy_g_rf_onoff(struct bwn_mac *, int);
161static int bwn_phy_g_switch_channel(struct bwn_mac *, uint32_t);
162static uint32_t bwn_phy_g_get_default_chan(struct bwn_mac *);
163static void bwn_phy_g_set_antenna(struct bwn_mac *, int);
164static int bwn_phy_g_im(struct bwn_mac *, int);
165static int bwn_phy_g_recalc_txpwr(struct bwn_mac *, int);
166static void bwn_phy_g_set_txpwr(struct bwn_mac *);
167static void bwn_phy_g_task_15s(struct bwn_mac *);
168static void bwn_phy_g_task_60s(struct bwn_mac *);
169static uint16_t bwn_phy_g_txctl(struct bwn_mac *);
170static void bwn_phy_switch_analog(struct bwn_mac *, int);
171static uint16_t bwn_shm_read_2(struct bwn_mac *, uint16_t, uint16_t);
172static void bwn_shm_write_2(struct bwn_mac *, uint16_t, uint16_t,
173 uint16_t);
174static uint32_t bwn_shm_read_4(struct bwn_mac *, uint16_t, uint16_t);
175static void bwn_shm_write_4(struct bwn_mac *, uint16_t, uint16_t,
176 uint32_t);
177static void bwn_shm_ctlword(struct bwn_mac *, uint16_t,
178 uint16_t);
179static void bwn_addchannels(struct ieee80211_channel [], int, int *,
180 const struct bwn_channelinfo *, int);
181static int bwn_raw_xmit(struct ieee80211_node *, struct mbuf *,
182 const struct ieee80211_bpf_params *);
183static void bwn_newassoc(struct ieee80211_node *, int);
184static void bwn_updateslot(struct ifnet *);
185static void bwn_update_promisc(struct ifnet *);
186static void bwn_wme_init(struct bwn_mac *);
187static int bwn_wme_update(struct ieee80211com *);
188static struct ieee80211_node *bwn_node_alloc(struct ieee80211vap *,
189 const uint8_t [IEEE80211_ADDR_LEN]);
190static void bwn_wme_clear(struct bwn_softc *);
191static void bwn_wme_load(struct bwn_mac *);
192static void bwn_wme_loadparams(struct bwn_mac *,
193 const struct wmeParams *, uint16_t);
194static void bwn_node_cleanup(struct ieee80211_node *);
195static void bwn_scan_start(struct ieee80211com *);
196static void bwn_scan_end(struct ieee80211com *);
197static void bwn_set_channel(struct ieee80211com *);
198static struct ieee80211vap *bwn_vap_create(struct ieee80211com *,
199 const char [IFNAMSIZ], int, int,
200 int, const uint8_t [IEEE80211_ADDR_LEN],
201 const uint8_t [IEEE80211_ADDR_LEN]);
202static void bwn_vap_delete(struct ieee80211vap *);
203static void bwn_stop(struct bwn_softc *, int);
204static void bwn_stop_locked(struct bwn_softc *, int);
205static int bwn_core_init(struct bwn_mac *);
206static void bwn_core_start(struct bwn_mac *);
207static void bwn_core_exit(struct bwn_mac *);
208static void bwn_bt_disable(struct bwn_mac *);
209static int bwn_chip_init(struct bwn_mac *);
210static uint64_t bwn_hf_read(struct bwn_mac *);
211static void bwn_hf_write(struct bwn_mac *, uint64_t);
212static void bwn_set_txretry(struct bwn_mac *, int, int);
213static void bwn_rate_init(struct bwn_mac *);
214static void bwn_set_phytxctl(struct bwn_mac *);
215static void bwn_spu_setdelay(struct bwn_mac *, int);
216static void bwn_bt_enable(struct bwn_mac *);
217static void bwn_set_macaddr(struct bwn_mac *);
218static void bwn_crypt_init(struct bwn_mac *);
219static void bwn_chip_exit(struct bwn_mac *);
220static int bwn_fw_fillinfo(struct bwn_mac *);
221static int bwn_fw_loaducode(struct bwn_mac *);
222static int bwn_gpio_init(struct bwn_mac *);
223static int bwn_fw_loadinitvals(struct bwn_mac *);
224static int bwn_phy_init(struct bwn_mac *);
225static void bwn_set_txantenna(struct bwn_mac *, int);
226static void bwn_set_opmode(struct bwn_mac *);
227static void bwn_rate_write(struct bwn_mac *, uint16_t, int);
228static uint8_t bwn_plcp_getcck(const uint8_t);
229static uint8_t bwn_plcp_getofdm(const uint8_t);
230static void bwn_pio_init(struct bwn_mac *);
231static uint16_t bwn_pio_idx2base(struct bwn_mac *, int);
232static void bwn_pio_set_txqueue(struct bwn_mac *, struct bwn_pio_txqueue *,
233 int);
234static void bwn_pio_setupqueue_rx(struct bwn_mac *,
235 struct bwn_pio_rxqueue *, int);
236static void bwn_destroy_queue_tx(struct bwn_pio_txqueue *);
237static uint16_t bwn_pio_read_2(struct bwn_mac *, struct bwn_pio_txqueue *,
238 uint16_t);
239static void bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *);
240static int bwn_pio_rx(struct bwn_pio_rxqueue *);
241static uint8_t bwn_pio_rxeof(struct bwn_pio_rxqueue *);
242static void bwn_pio_handle_txeof(struct bwn_mac *,
243 const struct bwn_txstatus *);
244static uint16_t bwn_pio_rx_read_2(struct bwn_pio_rxqueue *, uint16_t);
245static uint32_t bwn_pio_rx_read_4(struct bwn_pio_rxqueue *, uint16_t);
246static void bwn_pio_rx_write_2(struct bwn_pio_rxqueue *, uint16_t,
247 uint16_t);
248static void bwn_pio_rx_write_4(struct bwn_pio_rxqueue *, uint16_t,
249 uint32_t);
250static int bwn_pio_tx_start(struct bwn_mac *, struct ieee80211_node *,
251 struct mbuf *);
252static struct bwn_pio_txqueue *bwn_pio_select(struct bwn_mac *, uint8_t);
253static uint32_t bwn_pio_write_multi_4(struct bwn_mac *,
254 struct bwn_pio_txqueue *, uint32_t, const void *, int);
255static void bwn_pio_write_4(struct bwn_mac *, struct bwn_pio_txqueue *,
256 uint16_t, uint32_t);
257static uint16_t bwn_pio_write_multi_2(struct bwn_mac *,
258 struct bwn_pio_txqueue *, uint16_t, const void *, int);
259static uint16_t bwn_pio_write_mbuf_2(struct bwn_mac *,
260 struct bwn_pio_txqueue *, uint16_t, struct mbuf *);
261static struct bwn_pio_txqueue *bwn_pio_parse_cookie(struct bwn_mac *,
262 uint16_t, struct bwn_pio_txpkt **);
263static void bwn_dma_init(struct bwn_mac *);
264static void bwn_dma_rxdirectfifo(struct bwn_mac *, int, uint8_t);
265static int bwn_dma_mask2type(uint64_t);
266static uint64_t bwn_dma_mask(struct bwn_mac *);
267static uint16_t bwn_dma_base(int, int);
268static void bwn_dma_ringfree(struct bwn_dma_ring **);
269static void bwn_dma_32_getdesc(struct bwn_dma_ring *,
270 int, struct bwn_dmadesc_generic **,
271 struct bwn_dmadesc_meta **);
272static void bwn_dma_32_setdesc(struct bwn_dma_ring *,
273 struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int,
274 int, int);
275static void bwn_dma_32_start_transfer(struct bwn_dma_ring *, int);
276static void bwn_dma_32_suspend(struct bwn_dma_ring *);
277static void bwn_dma_32_resume(struct bwn_dma_ring *);
278static int bwn_dma_32_get_curslot(struct bwn_dma_ring *);
279static void bwn_dma_32_set_curslot(struct bwn_dma_ring *, int);
280static void bwn_dma_64_getdesc(struct bwn_dma_ring *,
281 int, struct bwn_dmadesc_generic **,
282 struct bwn_dmadesc_meta **);
283static void bwn_dma_64_setdesc(struct bwn_dma_ring *,
284 struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int,
285 int, int);
286static void bwn_dma_64_start_transfer(struct bwn_dma_ring *, int);
287static void bwn_dma_64_suspend(struct bwn_dma_ring *);
288static void bwn_dma_64_resume(struct bwn_dma_ring *);
289static int bwn_dma_64_get_curslot(struct bwn_dma_ring *);
290static void bwn_dma_64_set_curslot(struct bwn_dma_ring *, int);
291static int bwn_dma_allocringmemory(struct bwn_dma_ring *);
292static void bwn_dma_setup(struct bwn_dma_ring *);
293static void bwn_dma_free_ringmemory(struct bwn_dma_ring *);
294static void bwn_dma_cleanup(struct bwn_dma_ring *);
295static void bwn_dma_free_descbufs(struct bwn_dma_ring *);
296static int bwn_dma_tx_reset(struct bwn_mac *, uint16_t, int);
297static void bwn_dma_rx(struct bwn_dma_ring *);
298static int bwn_dma_rx_reset(struct bwn_mac *, uint16_t, int);
299static void bwn_dma_free_descbuf(struct bwn_dma_ring *,
300 struct bwn_dmadesc_meta *);
301static void bwn_dma_set_redzone(struct bwn_dma_ring *, struct mbuf *);
302static int bwn_dma_gettype(struct bwn_mac *);
303static void bwn_dma_ring_addr(void *, bus_dma_segment_t *, int, int);
304static int bwn_dma_freeslot(struct bwn_dma_ring *);
305static int bwn_dma_nextslot(struct bwn_dma_ring *, int);
306static void bwn_dma_rxeof(struct bwn_dma_ring *, int *);
307static int bwn_dma_newbuf(struct bwn_dma_ring *,
308 struct bwn_dmadesc_generic *, struct bwn_dmadesc_meta *,
309 int);
310static void bwn_dma_buf_addr(void *, bus_dma_segment_t *, int,
311 bus_size_t, int);
312static uint8_t bwn_dma_check_redzone(struct bwn_dma_ring *, struct mbuf *);
313static void bwn_dma_handle_txeof(struct bwn_mac *,
314 const struct bwn_txstatus *);
315static int bwn_dma_tx_start(struct bwn_mac *, struct ieee80211_node *,
316 struct mbuf *);
317static int bwn_dma_getslot(struct bwn_dma_ring *);
318static struct bwn_dma_ring *bwn_dma_select(struct bwn_mac *,
319 uint8_t);
320static int bwn_dma_attach(struct bwn_mac *);
321static struct bwn_dma_ring *bwn_dma_ringsetup(struct bwn_mac *,
322 int, int, int);
323static struct bwn_dma_ring *bwn_dma_parse_cookie(struct bwn_mac *,
324 const struct bwn_txstatus *, uint16_t, int *);
325static void bwn_dma_free(struct bwn_mac *);
326static void bwn_phy_g_init_sub(struct bwn_mac *);
327static uint8_t bwn_has_hwpctl(struct bwn_mac *);
328static void bwn_phy_init_b5(struct bwn_mac *);
329static void bwn_phy_init_b6(struct bwn_mac *);
330static void bwn_phy_init_a(struct bwn_mac *);
331static void bwn_loopback_calcgain(struct bwn_mac *);
332static uint16_t bwn_rf_init_bcm2050(struct bwn_mac *);
333static void bwn_lo_g_init(struct bwn_mac *);
334static void bwn_lo_g_adjust(struct bwn_mac *);
335static void bwn_lo_get_powervector(struct bwn_mac *);
336static struct bwn_lo_calib *bwn_lo_calibset(struct bwn_mac *,
337 const struct bwn_bbatt *, const struct bwn_rfatt *);
338static void bwn_lo_write(struct bwn_mac *, struct bwn_loctl *);
339static void bwn_phy_hwpctl_init(struct bwn_mac *);
340static void bwn_phy_g_switch_chan(struct bwn_mac *, int, uint8_t);
341static void bwn_phy_g_set_txpwr_sub(struct bwn_mac *,
342 const struct bwn_bbatt *, const struct bwn_rfatt *,
343 uint8_t);
344static void bwn_phy_g_set_bbatt(struct bwn_mac *, uint16_t);
345static uint16_t bwn_rf_2050_rfoverval(struct bwn_mac *, uint16_t, uint32_t);
346static void bwn_spu_workaround(struct bwn_mac *, uint8_t);
347static void bwn_wa_init(struct bwn_mac *);
348static void bwn_ofdmtab_write_2(struct bwn_mac *, uint16_t, uint16_t,
349 uint16_t);
350static void bwn_dummy_transmission(struct bwn_mac *, int, int);
351static void bwn_ofdmtab_write_4(struct bwn_mac *, uint16_t, uint16_t,
352 uint32_t);
353static void bwn_gtab_write(struct bwn_mac *, uint16_t, uint16_t,
354 uint16_t);
355static void bwn_ram_write(struct bwn_mac *, uint16_t, uint32_t);
356static void bwn_mac_suspend(struct bwn_mac *);
357static void bwn_mac_enable(struct bwn_mac *);
358static void bwn_psctl(struct bwn_mac *, uint32_t);
359static int16_t bwn_nrssi_read(struct bwn_mac *, uint16_t);
360static void bwn_nrssi_offset(struct bwn_mac *);
361static void bwn_nrssi_threshold(struct bwn_mac *);
362static void bwn_nrssi_slope_11g(struct bwn_mac *);
363static void bwn_set_all_gains(struct bwn_mac *, int16_t, int16_t,
364 int16_t);
365static void bwn_set_original_gains(struct bwn_mac *);
366static void bwn_hwpctl_early_init(struct bwn_mac *);
367static void bwn_hwpctl_init_gphy(struct bwn_mac *);
368static uint16_t bwn_phy_g_chan2freq(uint8_t);
369static int bwn_fw_gets(struct bwn_mac *, enum bwn_fwtype);
370static int bwn_fw_get(struct bwn_mac *, enum bwn_fwtype,
371 const char *, struct bwn_fwfile *);
372static void bwn_release_firmware(struct bwn_mac *);
373static void bwn_do_release_fw(struct bwn_fwfile *);
374static uint16_t bwn_fwcaps_read(struct bwn_mac *);
375static int bwn_fwinitvals_write(struct bwn_mac *,
376 const struct bwn_fwinitvals *, size_t, size_t);
377static int bwn_switch_channel(struct bwn_mac *, int);
378static uint16_t bwn_ant2phy(int);
379static void bwn_mac_write_bssid(struct bwn_mac *);
380static void bwn_mac_setfilter(struct bwn_mac *, uint16_t,
381 const uint8_t *);
382static void bwn_key_dowrite(struct bwn_mac *, uint8_t, uint8_t,
383 const uint8_t *, size_t, const uint8_t *);
384static void bwn_key_macwrite(struct bwn_mac *, uint8_t,
385 const uint8_t *);
386static void bwn_key_write(struct bwn_mac *, uint8_t, uint8_t,
387 const uint8_t *);
388static void bwn_phy_exit(struct bwn_mac *);
389static void bwn_core_stop(struct bwn_mac *);
390static int bwn_switch_band(struct bwn_softc *,
391 struct ieee80211_channel *);
392static void bwn_phy_reset(struct bwn_mac *);
393static int bwn_newstate(struct ieee80211vap *, enum ieee80211_state, int);
394static void bwn_set_pretbtt(struct bwn_mac *);
395static int bwn_intr(void *);
396static void bwn_intrtask(void *, int);
397static void bwn_restart(struct bwn_mac *, const char *);
398static void bwn_intr_ucode_debug(struct bwn_mac *);
399static void bwn_intr_tbtt_indication(struct bwn_mac *);
400static void bwn_intr_atim_end(struct bwn_mac *);
401static void bwn_intr_beacon(struct bwn_mac *);
402static void bwn_intr_pmq(struct bwn_mac *);
403static void bwn_intr_noise(struct bwn_mac *);
404static void bwn_intr_txeof(struct bwn_mac *);
405static void bwn_hwreset(void *, int);
406static void bwn_handle_fwpanic(struct bwn_mac *);
407static void bwn_load_beacon0(struct bwn_mac *);
408static void bwn_load_beacon1(struct bwn_mac *);
409static uint32_t bwn_jssi_read(struct bwn_mac *);
410static void bwn_noise_gensample(struct bwn_mac *);
411static void bwn_handle_txeof(struct bwn_mac *,
412 const struct bwn_txstatus *);
413static void bwn_rxeof(struct bwn_mac *, struct mbuf *, const void *);
414static void bwn_phy_txpower_check(struct bwn_mac *, uint32_t);
415static void bwn_start_locked(struct ifnet *);
416static int bwn_tx_start(struct bwn_softc *, struct ieee80211_node *,
417 struct mbuf *);
418static int bwn_tx_isfull(struct bwn_softc *, struct mbuf *);
419static int bwn_set_txhdr(struct bwn_mac *,
420 struct ieee80211_node *, struct mbuf *, struct bwn_txhdr *,
421 uint16_t);
422static void bwn_plcp_genhdr(struct bwn_plcp4 *, const uint16_t,
423 const uint8_t);
424static uint8_t bwn_antenna_sanitize(struct bwn_mac *, uint8_t);
425static uint8_t bwn_get_fbrate(uint8_t);
426static int bwn_phy_shm_tssi_read(struct bwn_mac *, uint16_t);
427static void bwn_phy_g_setatt(struct bwn_mac *, int *, int *);
428static void bwn_phy_lock(struct bwn_mac *);
429static void bwn_phy_unlock(struct bwn_mac *);
430static void bwn_rf_lock(struct bwn_mac *);
431static void bwn_rf_unlock(struct bwn_mac *);
432static void bwn_txpwr(void *, int);
433static void bwn_tasks(void *);
434static void bwn_task_15s(struct bwn_mac *);
435static void bwn_task_30s(struct bwn_mac *);
436static void bwn_task_60s(struct bwn_mac *);
437static int bwn_plcp_get_ofdmrate(struct bwn_mac *, struct bwn_plcp6 *,
438 uint8_t);
439static int bwn_plcp_get_cckrate(struct bwn_mac *, struct bwn_plcp6 *);
440static void bwn_rx_radiotap(struct bwn_mac *, struct mbuf *,
441 const struct bwn_rxhdr4 *, struct bwn_plcp6 *, int,
442 int, int);
443static void bwn_tsf_read(struct bwn_mac *, uint64_t *);
444static void bwn_phy_g_dc_lookup_init(struct bwn_mac *, uint8_t);
445static void bwn_set_slot_time(struct bwn_mac *, uint16_t);
446static void bwn_watchdog(void *);
447static void bwn_dma_stop(struct bwn_mac *);
448static void bwn_pio_stop(struct bwn_mac *);
449static void bwn_dma_ringstop(struct bwn_dma_ring **);
450static void bwn_led_attach(struct bwn_mac *);
451static void bwn_led_newstate(struct bwn_mac *, enum ieee80211_state);
452static void bwn_led_event(struct bwn_mac *, int);
453static void bwn_led_blink_start(struct bwn_mac *, int, int);
454static void bwn_led_blink_next(void *);
455static void bwn_led_blink_end(void *);
456static void bwn_rfswitch(void *);
457static void bwn_rf_turnon(struct bwn_mac *);
458static void bwn_rf_turnoff(struct bwn_mac *);
459static void bwn_phy_lp_init_pre(struct bwn_mac *);
460static int bwn_phy_lp_init(struct bwn_mac *);
461static uint16_t bwn_phy_lp_read(struct bwn_mac *, uint16_t);
462static void bwn_phy_lp_write(struct bwn_mac *, uint16_t, uint16_t);
463static void bwn_phy_lp_maskset(struct bwn_mac *, uint16_t, uint16_t,
464 uint16_t);
465static uint16_t bwn_phy_lp_rf_read(struct bwn_mac *, uint16_t);
466static void bwn_phy_lp_rf_write(struct bwn_mac *, uint16_t, uint16_t);
467static void bwn_phy_lp_rf_onoff(struct bwn_mac *, int);
468static int bwn_phy_lp_switch_channel(struct bwn_mac *, uint32_t);
469static uint32_t bwn_phy_lp_get_default_chan(struct bwn_mac *);
470static void bwn_phy_lp_set_antenna(struct bwn_mac *, int);
471static void bwn_phy_lp_task_60s(struct bwn_mac *);
472static void bwn_phy_lp_readsprom(struct bwn_mac *);
473static void bwn_phy_lp_bbinit(struct bwn_mac *);
474static void bwn_phy_lp_txpctl_init(struct bwn_mac *);
475static void bwn_phy_lp_calib(struct bwn_mac *);
476static void bwn_phy_lp_switch_analog(struct bwn_mac *, int);
477static int bwn_phy_lp_b2062_switch_channel(struct bwn_mac *, uint8_t);
478static int bwn_phy_lp_b2063_switch_channel(struct bwn_mac *, uint8_t);
479static void bwn_phy_lp_set_anafilter(struct bwn_mac *, uint8_t);
480static void bwn_phy_lp_set_gaintbl(struct bwn_mac *, uint32_t);
481static void bwn_phy_lp_digflt_save(struct bwn_mac *);
482static void bwn_phy_lp_get_txpctlmode(struct bwn_mac *);
483static void bwn_phy_lp_set_txpctlmode(struct bwn_mac *, uint8_t);
484static void bwn_phy_lp_bugfix(struct bwn_mac *);
485static void bwn_phy_lp_digflt_restore(struct bwn_mac *);
486static void bwn_phy_lp_tblinit(struct bwn_mac *);
487static void bwn_phy_lp_bbinit_r2(struct bwn_mac *);
488static void bwn_phy_lp_bbinit_r01(struct bwn_mac *);
489static void bwn_phy_lp_b2062_init(struct bwn_mac *);
490static void bwn_phy_lp_b2063_init(struct bwn_mac *);
491static void bwn_phy_lp_rxcal_r2(struct bwn_mac *);
492static void bwn_phy_lp_rccal_r12(struct bwn_mac *);
493static void bwn_phy_lp_set_rccap(struct bwn_mac *);
494static uint32_t bwn_phy_lp_roundup(uint32_t, uint32_t, uint8_t);
495static void bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *);
496static void bwn_phy_lp_b2062_vco_calib(struct bwn_mac *);
497static void bwn_tab_write_multi(struct bwn_mac *, uint32_t, int,
498 const void *);
499static void bwn_tab_read_multi(struct bwn_mac *, uint32_t, int, void *);
500static struct bwn_txgain
501 bwn_phy_lp_get_txgain(struct bwn_mac *);
502static uint8_t bwn_phy_lp_get_bbmult(struct bwn_mac *);
503static void bwn_phy_lp_set_txgain(struct bwn_mac *, struct bwn_txgain *);
504static void bwn_phy_lp_set_bbmult(struct bwn_mac *, uint8_t);
505static void bwn_phy_lp_set_trsw_over(struct bwn_mac *, uint8_t, uint8_t);
506static void bwn_phy_lp_set_rxgain(struct bwn_mac *, uint32_t);
507static void bwn_phy_lp_set_deaf(struct bwn_mac *, uint8_t);
508static int bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *, uint16_t);
509static void bwn_phy_lp_clear_deaf(struct bwn_mac *, uint8_t);
510static void bwn_phy_lp_tblinit_r01(struct bwn_mac *);
511static void bwn_phy_lp_tblinit_r2(struct bwn_mac *);
512static void bwn_phy_lp_tblinit_txgain(struct bwn_mac *);
513static void bwn_tab_write(struct bwn_mac *, uint32_t, uint32_t);
514static void bwn_phy_lp_b2062_tblinit(struct bwn_mac *);
515static void bwn_phy_lp_b2063_tblinit(struct bwn_mac *);
516static int bwn_phy_lp_loopback(struct bwn_mac *);
517static void bwn_phy_lp_set_rxgain_idx(struct bwn_mac *, uint16_t);
518static void bwn_phy_lp_ddfs_turnon(struct bwn_mac *, int, int, int, int,
519 int);
520static uint8_t bwn_phy_lp_rx_iq_est(struct bwn_mac *, uint16_t, uint8_t,
521 struct bwn_phy_lp_iq_est *);
522static void bwn_phy_lp_ddfs_turnoff(struct bwn_mac *);
523static uint32_t bwn_tab_read(struct bwn_mac *, uint32_t);
524static void bwn_phy_lp_set_txgain_dac(struct bwn_mac *, uint16_t);
525static void bwn_phy_lp_set_txgain_pa(struct bwn_mac *, uint16_t);
526static void bwn_phy_lp_set_txgain_override(struct bwn_mac *);
527static uint16_t bwn_phy_lp_get_pa_gain(struct bwn_mac *);
528static uint8_t bwn_nbits(int32_t);
529static void bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *, int, int,
530 struct bwn_txgain_entry *);
531static void bwn_phy_lp_gaintbl_write(struct bwn_mac *, int,
532 struct bwn_txgain_entry);
533static void bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *, int,
534 struct bwn_txgain_entry);
535static void bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *, int,
536 struct bwn_txgain_entry);
537static void bwn_sysctl_node(struct bwn_softc *);
538
539static struct resource_spec bwn_res_spec_legacy[] = {
540 { SYS_RES_IRQ, 0, RF_ACTIVE | RF_SHAREABLE },
541 { -1, 0, 0 }
542};
543
544static struct resource_spec bwn_res_spec_msi[] = {
545 { SYS_RES_IRQ, 1, RF_ACTIVE },
546 { -1, 0, 0 }
547};
548
549static const struct bwn_channelinfo bwn_chantable_bg = {
550 .channels = {
551 { 2412, 1, 30 }, { 2417, 2, 30 }, { 2422, 3, 30 },
552 { 2427, 4, 30 }, { 2432, 5, 30 }, { 2437, 6, 30 },
553 { 2442, 7, 30 }, { 2447, 8, 30 }, { 2452, 9, 30 },
554 { 2457, 10, 30 }, { 2462, 11, 30 }, { 2467, 12, 30 },
555 { 2472, 13, 30 }, { 2484, 14, 30 } },
556 .nchannels = 14
557};
558
559static const struct bwn_channelinfo bwn_chantable_a = {
560 .channels = {
561 { 5170, 34, 30 }, { 5180, 36, 30 }, { 5190, 38, 30 },
562 { 5200, 40, 30 }, { 5210, 42, 30 }, { 5220, 44, 30 },
563 { 5230, 46, 30 }, { 5240, 48, 30 }, { 5260, 52, 30 },
564 { 5280, 56, 30 }, { 5300, 60, 30 }, { 5320, 64, 30 },
565 { 5500, 100, 30 }, { 5520, 104, 30 }, { 5540, 108, 30 },
566 { 5560, 112, 30 }, { 5580, 116, 30 }, { 5600, 120, 30 },
567 { 5620, 124, 30 }, { 5640, 128, 30 }, { 5660, 132, 30 },
568 { 5680, 136, 30 }, { 5700, 140, 30 }, { 5745, 149, 30 },
569 { 5765, 153, 30 }, { 5785, 157, 30 }, { 5805, 161, 30 },
570 { 5825, 165, 30 }, { 5920, 184, 30 }, { 5940, 188, 30 },
571 { 5960, 192, 30 }, { 5980, 196, 30 }, { 6000, 200, 30 },
572 { 6020, 204, 30 }, { 6040, 208, 30 }, { 6060, 212, 30 },
573 { 6080, 216, 30 } },
574 .nchannels = 37
575};
576
577static const struct bwn_channelinfo bwn_chantable_n = {
578 .channels = {
579 { 5160, 32, 30 }, { 5170, 34, 30 }, { 5180, 36, 30 },
580 { 5190, 38, 30 }, { 5200, 40, 30 }, { 5210, 42, 30 },
581 { 5220, 44, 30 }, { 5230, 46, 30 }, { 5240, 48, 30 },
582 { 5250, 50, 30 }, { 5260, 52, 30 }, { 5270, 54, 30 },
583 { 5280, 56, 30 }, { 5290, 58, 30 }, { 5300, 60, 30 },
584 { 5310, 62, 30 }, { 5320, 64, 30 }, { 5330, 66, 30 },
585 { 5340, 68, 30 }, { 5350, 70, 30 }, { 5360, 72, 30 },
586 { 5370, 74, 30 }, { 5380, 76, 30 }, { 5390, 78, 30 },
587 { 5400, 80, 30 }, { 5410, 82, 30 }, { 5420, 84, 30 },
588 { 5430, 86, 30 }, { 5440, 88, 30 }, { 5450, 90, 30 },
589 { 5460, 92, 30 }, { 5470, 94, 30 }, { 5480, 96, 30 },
590 { 5490, 98, 30 }, { 5500, 100, 30 }, { 5510, 102, 30 },
591 { 5520, 104, 30 }, { 5530, 106, 30 }, { 5540, 108, 30 },
592 { 5550, 110, 30 }, { 5560, 112, 30 }, { 5570, 114, 30 },
593 { 5580, 116, 30 }, { 5590, 118, 30 }, { 5600, 120, 30 },
594 { 5610, 122, 30 }, { 5620, 124, 30 }, { 5630, 126, 30 },
595 { 5640, 128, 30 }, { 5650, 130, 30 }, { 5660, 132, 30 },
596 { 5670, 134, 30 }, { 5680, 136, 30 }, { 5690, 138, 30 },
597 { 5700, 140, 30 }, { 5710, 142, 30 }, { 5720, 144, 30 },
598 { 5725, 145, 30 }, { 5730, 146, 30 }, { 5735, 147, 30 },
599 { 5740, 148, 30 }, { 5745, 149, 30 }, { 5750, 150, 30 },
600 { 5755, 151, 30 }, { 5760, 152, 30 }, { 5765, 153, 30 },
601 { 5770, 154, 30 }, { 5775, 155, 30 }, { 5780, 156, 30 },
602 { 5785, 157, 30 }, { 5790, 158, 30 }, { 5795, 159, 30 },
603 { 5800, 160, 30 }, { 5805, 161, 30 }, { 5810, 162, 30 },
604 { 5815, 163, 30 }, { 5820, 164, 30 }, { 5825, 165, 30 },
605 { 5830, 166, 30 }, { 5840, 168, 30 }, { 5850, 170, 30 },
606 { 5860, 172, 30 }, { 5870, 174, 30 }, { 5880, 176, 30 },
607 { 5890, 178, 30 }, { 5900, 180, 30 }, { 5910, 182, 30 },
608 { 5920, 184, 30 }, { 5930, 186, 30 }, { 5940, 188, 30 },
609 { 5950, 190, 30 }, { 5960, 192, 30 }, { 5970, 194, 30 },
610 { 5980, 196, 30 }, { 5990, 198, 30 }, { 6000, 200, 30 },
611 { 6010, 202, 30 }, { 6020, 204, 30 }, { 6030, 206, 30 },
612 { 6040, 208, 30 }, { 6050, 210, 30 }, { 6060, 212, 30 },
613 { 6070, 214, 30 }, { 6080, 216, 30 }, { 6090, 218, 30 },
614 { 6100, 220, 30 }, { 6110, 222, 30 }, { 6120, 224, 30 },
615 { 6130, 226, 30 }, { 6140, 228, 30 } },
616 .nchannels = 110
617};
618
619static const uint8_t bwn_b2063_chantable_data[33][12] = {
620 { 0x6f, 0x3c, 0x3c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
621 { 0x6f, 0x2c, 0x2c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
622 { 0x6f, 0x1c, 0x1c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
623 { 0x6e, 0x1c, 0x1c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
624 { 0x6e, 0xc, 0xc, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
625 { 0x6a, 0xc, 0xc, 0, 0x2, 0x5, 0xd, 0xd, 0x77, 0x80, 0x20, 0 },
626 { 0x6a, 0xc, 0xc, 0, 0x1, 0x5, 0xd, 0xc, 0x77, 0x80, 0x20, 0 },
627 { 0x6a, 0xc, 0xc, 0, 0x1, 0x4, 0xc, 0xc, 0x77, 0x80, 0x20, 0 },
628 { 0x69, 0xc, 0xc, 0, 0x1, 0x4, 0xc, 0xc, 0x77, 0x70, 0x20, 0 },
629 { 0x69, 0xc, 0xc, 0, 0x1, 0x4, 0xb, 0xc, 0x77, 0x70, 0x20, 0 },
630 { 0x69, 0xc, 0xc, 0, 0, 0x4, 0xb, 0xb, 0x77, 0x60, 0x20, 0 },
631 { 0x69, 0xc, 0xc, 0, 0, 0x3, 0xa, 0xb, 0x77, 0x60, 0x20, 0 },
632 { 0x69, 0xc, 0xc, 0, 0, 0x3, 0xa, 0xa, 0x77, 0x60, 0x20, 0 },
633 { 0x68, 0xc, 0xc, 0, 0, 0x2, 0x9, 0x9, 0x77, 0x60, 0x20, 0 },
634 { 0x68, 0xc, 0xc, 0, 0, 0x1, 0x8, 0x8, 0x77, 0x50, 0x10, 0 },
635 { 0x67, 0xc, 0xc, 0, 0, 0, 0x8, 0x8, 0x77, 0x50, 0x10, 0 },
636 { 0x64, 0xc, 0xc, 0, 0, 0, 0x2, 0x1, 0x77, 0x20, 0, 0 },
637 { 0x64, 0xc, 0xc, 0, 0, 0, 0x1, 0x1, 0x77, 0x20, 0, 0 },
638 { 0x63, 0xc, 0xc, 0, 0, 0, 0x1, 0, 0x77, 0x10, 0, 0 },
639 { 0x63, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0x10, 0, 0 },
640 { 0x62, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0x10, 0, 0 },
641 { 0x62, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
642 { 0x61, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
643 { 0x60, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
644 { 0x6e, 0xc, 0xc, 0, 0x9, 0xe, 0xf, 0xf, 0x77, 0xc0, 0x50, 0 },
645 { 0x6e, 0xc, 0xc, 0, 0x9, 0xd, 0xf, 0xf, 0x77, 0xb0, 0x50, 0 },
646 { 0x6e, 0xc, 0xc, 0, 0x8, 0xc, 0xf, 0xf, 0x77, 0xb0, 0x50, 0 },
647 { 0x6d, 0xc, 0xc, 0, 0x8, 0xc, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
648 { 0x6d, 0xc, 0xc, 0, 0x8, 0xb, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
649 { 0x6d, 0xc, 0xc, 0, 0x8, 0xa, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
650 { 0x6c, 0xc, 0xc, 0, 0x7, 0x9, 0xf, 0xf, 0x77, 0x90, 0x40, 0 },
651 { 0x6c, 0xc, 0xc, 0, 0x6, 0x8, 0xf, 0xf, 0x77, 0x90, 0x40, 0 },
652 { 0x6c, 0xc, 0xc, 0, 0x5, 0x8, 0xf, 0xf, 0x77, 0x90, 0x40, 0 }
653};
654
655static const struct bwn_b206x_chan bwn_b2063_chantable[] = {
656 { 1, 2412, bwn_b2063_chantable_data[0] },
657 { 2, 2417, bwn_b2063_chantable_data[0] },
658 { 3, 2422, bwn_b2063_chantable_data[0] },
659 { 4, 2427, bwn_b2063_chantable_data[1] },
660 { 5, 2432, bwn_b2063_chantable_data[1] },
661 { 6, 2437, bwn_b2063_chantable_data[1] },
662 { 7, 2442, bwn_b2063_chantable_data[1] },
663 { 8, 2447, bwn_b2063_chantable_data[1] },
664 { 9, 2452, bwn_b2063_chantable_data[2] },
665 { 10, 2457, bwn_b2063_chantable_data[2] },
666 { 11, 2462, bwn_b2063_chantable_data[3] },
667 { 12, 2467, bwn_b2063_chantable_data[3] },
668 { 13, 2472, bwn_b2063_chantable_data[3] },
669 { 14, 2484, bwn_b2063_chantable_data[4] },
670 { 34, 5170, bwn_b2063_chantable_data[5] },
671 { 36, 5180, bwn_b2063_chantable_data[6] },
672 { 38, 5190, bwn_b2063_chantable_data[7] },
673 { 40, 5200, bwn_b2063_chantable_data[8] },
674 { 42, 5210, bwn_b2063_chantable_data[9] },
675 { 44, 5220, bwn_b2063_chantable_data[10] },
676 { 46, 5230, bwn_b2063_chantable_data[11] },
677 { 48, 5240, bwn_b2063_chantable_data[12] },
678 { 52, 5260, bwn_b2063_chantable_data[13] },
679 { 56, 5280, bwn_b2063_chantable_data[14] },
680 { 60, 5300, bwn_b2063_chantable_data[14] },
681 { 64, 5320, bwn_b2063_chantable_data[15] },
682 { 100, 5500, bwn_b2063_chantable_data[16] },
683 { 104, 5520, bwn_b2063_chantable_data[17] },
684 { 108, 5540, bwn_b2063_chantable_data[18] },
685 { 112, 5560, bwn_b2063_chantable_data[19] },
686 { 116, 5580, bwn_b2063_chantable_data[20] },
687 { 120, 5600, bwn_b2063_chantable_data[21] },
688 { 124, 5620, bwn_b2063_chantable_data[21] },
689 { 128, 5640, bwn_b2063_chantable_data[22] },
690 { 132, 5660, bwn_b2063_chantable_data[22] },
691 { 136, 5680, bwn_b2063_chantable_data[22] },
692 { 140, 5700, bwn_b2063_chantable_data[23] },
693 { 149, 5745, bwn_b2063_chantable_data[23] },
694 { 153, 5765, bwn_b2063_chantable_data[23] },
695 { 157, 5785, bwn_b2063_chantable_data[23] },
696 { 161, 5805, bwn_b2063_chantable_data[23] },
697 { 165, 5825, bwn_b2063_chantable_data[23] },
698 { 184, 4920, bwn_b2063_chantable_data[24] },
699 { 188, 4940, bwn_b2063_chantable_data[25] },
700 { 192, 4960, bwn_b2063_chantable_data[26] },
701 { 196, 4980, bwn_b2063_chantable_data[27] },
702 { 200, 5000, bwn_b2063_chantable_data[28] },
703 { 204, 5020, bwn_b2063_chantable_data[29] },
704 { 208, 5040, bwn_b2063_chantable_data[30] },
705 { 212, 5060, bwn_b2063_chantable_data[31] },
706 { 216, 5080, bwn_b2063_chantable_data[32] }
707};
708
709static const uint8_t bwn_b2062_chantable_data[22][12] = {
710 { 0xff, 0xff, 0xb5, 0x1b, 0x24, 0x32, 0x32, 0x88, 0x88, 0, 0, 0 },
711 { 0, 0x22, 0x20, 0x84, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
712 { 0, 0x11, 0x10, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
713 { 0, 0, 0, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
714 { 0, 0x11, 0x20, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
715 { 0, 0x11, 0x10, 0x84, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
716 { 0, 0x11, 0, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
717 { 0, 0, 0, 0x63, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
718 { 0, 0, 0, 0x62, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
719 { 0, 0, 0, 0x30, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
720 { 0, 0, 0, 0x20, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
721 { 0, 0, 0, 0x10, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
722 { 0, 0, 0, 0, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
723 { 0x55, 0x77, 0x90, 0xf7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
724 { 0x44, 0x77, 0x80, 0xe7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
725 { 0x44, 0x66, 0x80, 0xe7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
726 { 0x33, 0x66, 0x70, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
727 { 0x22, 0x55, 0x60, 0xd7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
728 { 0x22, 0x55, 0x60, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
729 { 0x22, 0x44, 0x50, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
730 { 0x11, 0x44, 0x50, 0xa5, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
731 { 0, 0x44, 0x40, 0xb6, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 }
732};
733
734static const struct bwn_b206x_chan bwn_b2062_chantable[] = {
735 { 1, 2412, bwn_b2062_chantable_data[0] },
736 { 2, 2417, bwn_b2062_chantable_data[0] },
737 { 3, 2422, bwn_b2062_chantable_data[0] },
738 { 4, 2427, bwn_b2062_chantable_data[0] },
739 { 5, 2432, bwn_b2062_chantable_data[0] },
740 { 6, 2437, bwn_b2062_chantable_data[0] },
741 { 7, 2442, bwn_b2062_chantable_data[0] },
742 { 8, 2447, bwn_b2062_chantable_data[0] },
743 { 9, 2452, bwn_b2062_chantable_data[0] },
744 { 10, 2457, bwn_b2062_chantable_data[0] },
745 { 11, 2462, bwn_b2062_chantable_data[0] },
746 { 12, 2467, bwn_b2062_chantable_data[0] },
747 { 13, 2472, bwn_b2062_chantable_data[0] },
748 { 14, 2484, bwn_b2062_chantable_data[0] },
749 { 34, 5170, bwn_b2062_chantable_data[1] },
750 { 38, 5190, bwn_b2062_chantable_data[2] },
751 { 42, 5210, bwn_b2062_chantable_data[2] },
752 { 46, 5230, bwn_b2062_chantable_data[3] },
753 { 36, 5180, bwn_b2062_chantable_data[4] },
754 { 40, 5200, bwn_b2062_chantable_data[5] },
755 { 44, 5220, bwn_b2062_chantable_data[6] },
756 { 48, 5240, bwn_b2062_chantable_data[3] },
757 { 52, 5260, bwn_b2062_chantable_data[3] },
758 { 56, 5280, bwn_b2062_chantable_data[3] },
759 { 60, 5300, bwn_b2062_chantable_data[7] },
760 { 64, 5320, bwn_b2062_chantable_data[8] },
761 { 100, 5500, bwn_b2062_chantable_data[9] },
762 { 104, 5520, bwn_b2062_chantable_data[10] },
763 { 108, 5540, bwn_b2062_chantable_data[10] },
764 { 112, 5560, bwn_b2062_chantable_data[10] },
765 { 116, 5580, bwn_b2062_chantable_data[11] },
766 { 120, 5600, bwn_b2062_chantable_data[12] },
767 { 124, 5620, bwn_b2062_chantable_data[12] },
768 { 128, 5640, bwn_b2062_chantable_data[12] },
769 { 132, 5660, bwn_b2062_chantable_data[12] },
770 { 136, 5680, bwn_b2062_chantable_data[12] },
771 { 140, 5700, bwn_b2062_chantable_data[12] },
772 { 149, 5745, bwn_b2062_chantable_data[12] },
773 { 153, 5765, bwn_b2062_chantable_data[12] },
774 { 157, 5785, bwn_b2062_chantable_data[12] },
775 { 161, 5805, bwn_b2062_chantable_data[12] },
776 { 165, 5825, bwn_b2062_chantable_data[12] },
777 { 184, 4920, bwn_b2062_chantable_data[13] },
778 { 188, 4940, bwn_b2062_chantable_data[14] },
779 { 192, 4960, bwn_b2062_chantable_data[15] },
780 { 196, 4980, bwn_b2062_chantable_data[16] },
781 { 200, 5000, bwn_b2062_chantable_data[17] },
782 { 204, 5020, bwn_b2062_chantable_data[18] },
783 { 208, 5040, bwn_b2062_chantable_data[19] },
784 { 212, 5060, bwn_b2062_chantable_data[20] },
785 { 216, 5080, bwn_b2062_chantable_data[21] }
786};
787
788/* for LP PHY */
789static const struct bwn_rxcompco bwn_rxcompco_5354[] = {
790 { 1, -66, 15 }, { 2, -66, 15 }, { 3, -66, 15 }, { 4, -66, 15 },
791 { 5, -66, 15 }, { 6, -66, 15 }, { 7, -66, 14 }, { 8, -66, 14 },
792 { 9, -66, 14 }, { 10, -66, 14 }, { 11, -66, 14 }, { 12, -66, 13 },
793 { 13, -66, 13 }, { 14, -66, 13 },
794};
795
796/* for LP PHY */
797static const struct bwn_rxcompco bwn_rxcompco_r12[] = {
798 { 1, -64, 13 }, { 2, -64, 13 }, { 3, -64, 13 }, { 4, -64, 13 },
799 { 5, -64, 12 }, { 6, -64, 12 }, { 7, -64, 12 }, { 8, -64, 12 },
800 { 9, -64, 12 }, { 10, -64, 11 }, { 11, -64, 11 }, { 12, -64, 11 },
801 { 13, -64, 11 }, { 14, -64, 10 }, { 34, -62, 24 }, { 38, -62, 24 },
802 { 42, -62, 24 }, { 46, -62, 23 }, { 36, -62, 24 }, { 40, -62, 24 },
803 { 44, -62, 23 }, { 48, -62, 23 }, { 52, -62, 23 }, { 56, -62, 22 },
804 { 60, -62, 22 }, { 64, -62, 22 }, { 100, -62, 16 }, { 104, -62, 16 },
805 { 108, -62, 15 }, { 112, -62, 14 }, { 116, -62, 14 }, { 120, -62, 13 },
806 { 124, -62, 12 }, { 128, -62, 12 }, { 132, -62, 12 }, { 136, -62, 11 },
807 { 140, -62, 10 }, { 149, -61, 9 }, { 153, -61, 9 }, { 157, -61, 9 },
808 { 161, -61, 8 }, { 165, -61, 8 }, { 184, -62, 25 }, { 188, -62, 25 },
809 { 192, -62, 25 }, { 196, -62, 25 }, { 200, -62, 25 }, { 204, -62, 25 },
810 { 208, -62, 25 }, { 212, -62, 25 }, { 216, -62, 26 },
811};
812
813static const struct bwn_rxcompco bwn_rxcompco_r2 = { 0, -64, 0 };
814
815static const uint8_t bwn_tab_sigsq_tbl[] = {
816 0xde, 0xdc, 0xda, 0xd8, 0xd6, 0xd4, 0xd2, 0xcf, 0xcd,
817 0xca, 0xc7, 0xc4, 0xc1, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
818 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0x00,
819 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
820 0xbe, 0xbe, 0xbe, 0xbe, 0xc1, 0xc4, 0xc7, 0xca, 0xcd,
821 0xcf, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
822};
823
824static const uint8_t bwn_tab_pllfrac_tbl[] = {
825 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x80,
826 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
827};
828
829static const uint16_t bwn_tabl_iqlocal_tbl[] = {
830 0x0200, 0x0300, 0x0400, 0x0600, 0x0800, 0x0b00, 0x1000, 0x1001, 0x1002,
831 0x1003, 0x1004, 0x1005, 0x1006, 0x1007, 0x1707, 0x2007, 0x2d07, 0x4007,
832 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
833 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0200, 0x0300, 0x0400, 0x0600,
834 0x0800, 0x0b00, 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006,
835 0x1007, 0x1707, 0x2007, 0x2d07, 0x4007, 0x0000, 0x0000, 0x0000, 0x0000,
836 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
837 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
838 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
839 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4000, 0x0000, 0x0000,
840 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
841 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
842};
843
844static const uint16_t bwn_tab_noise_g1[] = BWN_TAB_NOISE_G1;
845static const uint16_t bwn_tab_noise_g2[] = BWN_TAB_NOISE_G2;
846static const uint16_t bwn_tab_noisescale_g1[] = BWN_TAB_NOISESCALE_G1;
847static const uint16_t bwn_tab_noisescale_g2[] = BWN_TAB_NOISESCALE_G2;
848static const uint16_t bwn_tab_noisescale_g3[] = BWN_TAB_NOISESCALE_G3;
849const uint8_t bwn_bitrev_table[256] = BWN_BITREV_TABLE;
850
851#define VENDOR_LED_ACT(vendor) \
852{ \
853 .vid = PCI_VENDOR_##vendor, \
854 .led_act = { BWN_VENDOR_LED_ACT_##vendor } \
855}
856
857static const struct {
858 uint16_t vid;
859 uint8_t led_act[BWN_LED_MAX];
860} bwn_vendor_led_act[] = {
861 VENDOR_LED_ACT(COMPAQ),
862 VENDOR_LED_ACT(ASUSTEK)
863};
864
865static const uint8_t bwn_default_led_act[BWN_LED_MAX] =
866 { BWN_VENDOR_LED_ACT_DEFAULT };
867
868#undef VENDOR_LED_ACT
869
870static const struct {
871 int on_dur;
872 int off_dur;
873} bwn_led_duration[109] = {
874 [0] = { 400, 100 },
875 [2] = { 150, 75 },
876 [4] = { 90, 45 },
877 [11] = { 66, 34 },
878 [12] = { 53, 26 },
879 [18] = { 42, 21 },
880 [22] = { 35, 17 },
881 [24] = { 32, 16 },
882 [36] = { 21, 10 },
883 [48] = { 16, 8 },
884 [72] = { 11, 5 },
885 [96] = { 9, 4 },
886 [108] = { 7, 3 }
887};
888
889static const uint16_t bwn_wme_shm_offsets[] = {
890 [0] = BWN_WME_BESTEFFORT,
891 [1] = BWN_WME_BACKGROUND,
892 [2] = BWN_WME_VOICE,
893 [3] = BWN_WME_VIDEO,
894};
895
896static const struct siba_devid bwn_devs[] = {
897 SIBA_DEV(BROADCOM, 80211, 5, "Revision 5"),
898 SIBA_DEV(BROADCOM, 80211, 6, "Revision 6"),
899 SIBA_DEV(BROADCOM, 80211, 7, "Revision 7"),
900 SIBA_DEV(BROADCOM, 80211, 9, "Revision 9"),
901 SIBA_DEV(BROADCOM, 80211, 10, "Revision 10"),
902 SIBA_DEV(BROADCOM, 80211, 11, "Revision 11"),
903 SIBA_DEV(BROADCOM, 80211, 13, "Revision 13"),
904 SIBA_DEV(BROADCOM, 80211, 15, "Revision 15"),
905 SIBA_DEV(BROADCOM, 80211, 16, "Revision 16")
906};
907
908static int
909bwn_probe(device_t dev)
910{
911 int i;
912
913 for (i = 0; i < sizeof(bwn_devs) / sizeof(bwn_devs[0]); i++) {
914 if (siba_get_vendor(dev) == bwn_devs[i].sd_vendor &&
915 siba_get_device(dev) == bwn_devs[i].sd_device &&
916 siba_get_revid(dev) == bwn_devs[i].sd_rev)
917 return (BUS_PROBE_DEFAULT);
918 }
919
920 return (ENXIO);
921}
922
923static int
924bwn_attach(device_t dev)
925{
926 struct bwn_mac *mac;
927 struct bwn_softc *sc = device_get_softc(dev);
928 int error, i, msic, reg;
929
930 sc->sc_dev = dev;
931#ifdef BWN_DEBUG
932 sc->sc_debug = bwn_debug;
933#endif
934
935 if ((sc->sc_flags & BWN_FLAG_ATTACHED) == 0) {
936 error = bwn_attach_pre(sc);
937 if (error != 0)
938 return (error);
939 bwn_sprom_bugfixes(dev);
940 sc->sc_flags |= BWN_FLAG_ATTACHED;
941 }
942
943 if (!TAILQ_EMPTY(&sc->sc_maclist)) {
944 if (siba_get_pci_device(dev) != 0x4313 &&
945 siba_get_pci_device(dev) != 0x431a &&
946 siba_get_pci_device(dev) != 0x4321) {
947 device_printf(sc->sc_dev,
948 "skip 802.11 cores\n");
949 return (ENODEV);
950 }
951 }
952
953 mac = (struct bwn_mac *)malloc(sizeof(*mac), M_DEVBUF,
954 M_NOWAIT | M_ZERO);
955 if (mac == NULL)
956 return (ENOMEM);
957 mac->mac_sc = sc;
958 mac->mac_status = BWN_MAC_STATUS_UNINIT;
959 if (bwn_bfp != 0)
960 mac->mac_flags |= BWN_MAC_FLAG_BADFRAME_PREEMP;
961
962 TASK_INIT(&mac->mac_hwreset, 0, bwn_hwreset, mac);
963 TASK_INIT(&mac->mac_intrtask, 0, bwn_intrtask, mac);
964 TASK_INIT(&mac->mac_txpower, 0, bwn_txpwr, mac);
965
966 error = bwn_attach_core(mac);
967 if (error)
968 goto fail0;
969 bwn_led_attach(mac);
970
971 device_printf(sc->sc_dev, "WLAN (chipid %#x rev %u) "
972 "PHY (analog %d type %d rev %d) RADIO (manuf %#x ver %#x rev %d)\n",
973 siba_get_chipid(sc->sc_dev), siba_get_revid(sc->sc_dev),
974 mac->mac_phy.analog, mac->mac_phy.type, mac->mac_phy.rev,
975 mac->mac_phy.rf_manuf, mac->mac_phy.rf_ver,
976 mac->mac_phy.rf_rev);
977 if (mac->mac_flags & BWN_MAC_FLAG_DMA)
978 device_printf(sc->sc_dev, "DMA (%d bits)\n",
979 mac->mac_method.dma.dmatype);
980 else
981 device_printf(sc->sc_dev, "PIO\n");
982
983 /*
984 * setup PCI resources and interrupt.
985 */
986 if (pci_find_extcap(dev, PCIY_EXPRESS, &reg) == 0) {
987 msic = pci_msi_count(dev);
988 if (bootverbose)
989 device_printf(sc->sc_dev, "MSI count : %d\n", msic);
990 } else
991 msic = 0;
992
993 mac->mac_intr_spec = bwn_res_spec_legacy;
994 if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0) {
995 if (pci_alloc_msi(dev, &msic) == 0) {
996 device_printf(sc->sc_dev,
997 "Using %d MSI messages\n", msic);
998 mac->mac_intr_spec = bwn_res_spec_msi;
999 mac->mac_msi = 1;
1000 }
1001 }
1002
1003 error = bus_alloc_resources(dev, mac->mac_intr_spec,
1004 mac->mac_res_irq);
1005 if (error) {
1006 device_printf(sc->sc_dev,
1007 "couldn't allocate IRQ resources (%d)\n", error);
1008 goto fail1;
1009 }
1010
1011 if (mac->mac_msi == 0)
1012 error = bus_setup_intr(dev, mac->mac_res_irq[0],
1013 INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac,
1014 &mac->mac_intrhand[0]);
1015 else {
1016 for (i = 0; i < BWN_MSI_MESSAGES; i++) {
1017 error = bus_setup_intr(dev, mac->mac_res_irq[i],
1018 INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac,
1019 &mac->mac_intrhand[i]);
1020 if (error != 0) {
1021 device_printf(sc->sc_dev,
1022 "couldn't setup interrupt (%d)\n", error);
1023 break;
1024 }
1025 }
1026 }
1027
1028 TAILQ_INSERT_TAIL(&sc->sc_maclist, mac, mac_list);
1029
1030 /*
1031 * calls attach-post routine
1032 */
1033 if ((sc->sc_flags & BWN_FLAG_ATTACHED) != 0)
1034 bwn_attach_post(sc);
1035
1036 return (0);
1037fail1:
1038 if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0)
1039 pci_release_msi(dev);
1040fail0:
1041 free(mac, M_DEVBUF);
1042 return (error);
1043}
1044
1045static int
1046bwn_is_valid_ether_addr(uint8_t *addr)
1047{
1048 char zero_addr[6] = { 0, 0, 0, 0, 0, 0 };
1049
1050 if ((addr[0] & 1) || (!bcmp(addr, zero_addr, ETHER_ADDR_LEN)))
1051 return (FALSE);
1052
1053 return (TRUE);
1054}
1055
1056static int
1057bwn_attach_post(struct bwn_softc *sc)
1058{
1059 struct ieee80211com *ic;
1060 struct ifnet *ifp = sc->sc_ifp;
1061
1062 ic = ifp->if_l2com;
1063 ic->ic_ifp = ifp;
1064 /* XXX not right but it's not used anywhere important */
1065 ic->ic_phytype = IEEE80211_T_OFDM;
1066 ic->ic_opmode = IEEE80211_M_STA;
1067 ic->ic_caps =
1068 IEEE80211_C_STA /* station mode supported */
1069 | IEEE80211_C_MONITOR /* monitor mode */
1070 | IEEE80211_C_AHDEMO /* adhoc demo mode */
1071 | IEEE80211_C_SHPREAMBLE /* short preamble supported */
1072 | IEEE80211_C_SHSLOT /* short slot time supported */
1073 | IEEE80211_C_WME /* WME/WMM supported */
1074 | IEEE80211_C_WPA /* capable of WPA1+WPA2 */
1075 | IEEE80211_C_BGSCAN /* capable of bg scanning */
1076 | IEEE80211_C_TXPMGT /* capable of txpow mgt */
1077 ;
1078
1079 ic->ic_flags_ext |= IEEE80211_FEXT_SWBMISS; /* s/w bmiss */
1080
1079 /* call MI attach routine. */
1080 ieee80211_ifattach(ic,
1081 bwn_is_valid_ether_addr(siba_sprom_get_mac_80211a(sc->sc_dev)) ?
1082 siba_sprom_get_mac_80211a(sc->sc_dev) :
1083 siba_sprom_get_mac_80211bg(sc->sc_dev));
1084
1085 ic->ic_headroom = sizeof(struct bwn_txhdr);
1086
1087 /* override default methods */
1088 ic->ic_raw_xmit = bwn_raw_xmit;
1089 ic->ic_newassoc = bwn_newassoc;
1090 ic->ic_updateslot = bwn_updateslot;
1091 ic->ic_update_promisc = bwn_update_promisc;
1092 ic->ic_wme.wme_update = bwn_wme_update;
1093
1094 ic->ic_node_alloc = bwn_node_alloc;
1095 sc->sc_node_cleanup = ic->ic_node_cleanup;
1096 ic->ic_node_cleanup = bwn_node_cleanup;
1097
1098 ic->ic_scan_start = bwn_scan_start;
1099 ic->ic_scan_end = bwn_scan_end;
1100 ic->ic_set_channel = bwn_set_channel;
1101
1102 ic->ic_vap_create = bwn_vap_create;
1103 ic->ic_vap_delete = bwn_vap_delete;
1104
1105 ieee80211_radiotap_attach(ic,
1106 &sc->sc_tx_th.wt_ihdr, sizeof(sc->sc_tx_th),
1107 BWN_TX_RADIOTAP_PRESENT,
1108 &sc->sc_rx_th.wr_ihdr, sizeof(sc->sc_rx_th),
1109 BWN_RX_RADIOTAP_PRESENT);
1110
1111 bwn_sysctl_node(sc);
1112
1113 if (bootverbose)
1114 ieee80211_announce(ic);
1115 return (0);
1116}
1117
1118static void
1119bwn_phy_detach(struct bwn_mac *mac)
1120{
1121
1122 if (mac->mac_phy.detach != NULL)
1123 mac->mac_phy.detach(mac);
1124}
1125
1126static int
1127bwn_detach(device_t dev)
1128{
1129 struct bwn_softc *sc = device_get_softc(dev);
1130 struct bwn_mac *mac = sc->sc_curmac;
1131 struct ifnet *ifp = sc->sc_ifp;
1132 struct ieee80211com *ic = ifp->if_l2com;
1133 int i;
1134
1135 sc->sc_flags |= BWN_FLAG_INVALID;
1136
1137 if (device_is_attached(sc->sc_dev)) {
1138 bwn_stop(sc, 1);
1139 bwn_dma_free(mac);
1140 callout_drain(&sc->sc_led_blink_ch);
1141 callout_drain(&sc->sc_rfswitch_ch);
1142 callout_drain(&sc->sc_task_ch);
1143 callout_drain(&sc->sc_watchdog_ch);
1144 bwn_phy_detach(mac);
1145 if (ifp != NULL) {
1146 ieee80211_draintask(ic, &mac->mac_hwreset);
1147 ieee80211_draintask(ic, &mac->mac_txpower);
1148 ieee80211_ifdetach(ic);
1149 if_free(ifp);
1150 }
1151 }
1152 taskqueue_drain(sc->sc_tq, &mac->mac_intrtask);
1153 taskqueue_free(sc->sc_tq);
1154
1155 for (i = 0; i < BWN_MSI_MESSAGES; i++) {
1156 if (mac->mac_intrhand[i] != NULL) {
1157 bus_teardown_intr(dev, mac->mac_res_irq[i],
1158 mac->mac_intrhand[i]);
1159 mac->mac_intrhand[i] = NULL;
1160 }
1161 }
1162 bus_release_resources(dev, mac->mac_intr_spec, mac->mac_res_irq);
1163 if (mac->mac_msi != 0)
1164 pci_release_msi(dev);
1165
1166 BWN_LOCK_DESTROY(sc);
1167 return (0);
1168}
1169
1170static int
1171bwn_attach_pre(struct bwn_softc *sc)
1172{
1173 struct ifnet *ifp;
1174 int error = 0;
1175
1176 BWN_LOCK_INIT(sc);
1177 TAILQ_INIT(&sc->sc_maclist);
1178 callout_init_mtx(&sc->sc_rfswitch_ch, &sc->sc_mtx, 0);
1179 callout_init_mtx(&sc->sc_task_ch, &sc->sc_mtx, 0);
1180 callout_init_mtx(&sc->sc_watchdog_ch, &sc->sc_mtx, 0);
1181
1182 sc->sc_tq = taskqueue_create_fast("bwn_taskq", M_NOWAIT,
1183 taskqueue_thread_enqueue, &sc->sc_tq);
1184 taskqueue_start_threads(&sc->sc_tq, 1, PI_NET,
1185 "%s taskq", device_get_nameunit(sc->sc_dev));
1186
1187 ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
1188 if (ifp == NULL) {
1189 device_printf(sc->sc_dev, "can not if_alloc()\n");
1190 error = ENOSPC;
1191 goto fail;
1192 }
1193
1194 /* set these up early for if_printf use */
1195 if_initname(ifp, device_get_name(sc->sc_dev),
1196 device_get_unit(sc->sc_dev));
1197
1198 ifp->if_softc = sc;
1199 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
1200 ifp->if_init = bwn_init;
1201 ifp->if_ioctl = bwn_ioctl;
1202 ifp->if_start = bwn_start;
1203 IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
1204 ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
1205 IFQ_SET_READY(&ifp->if_snd);
1206
1207 return (0);
1208
1209fail: BWN_LOCK_DESTROY(sc);
1210 return (error);
1211}
1212
1213static void
1214bwn_sprom_bugfixes(device_t dev)
1215{
1216#define BWN_ISDEV(_vendor, _device, _subvendor, _subdevice) \
1217 ((siba_get_pci_vendor(dev) == PCI_VENDOR_##_vendor) && \
1218 (siba_get_pci_device(dev) == _device) && \
1219 (siba_get_pci_subvendor(dev) == PCI_VENDOR_##_subvendor) && \
1220 (siba_get_pci_subdevice(dev) == _subdevice))
1221
1222 if (siba_get_pci_subvendor(dev) == PCI_VENDOR_APPLE &&
1223 siba_get_pci_subdevice(dev) == 0x4e &&
1224 siba_get_pci_revid(dev) > 0x40)
1225 siba_sprom_set_bf_lo(dev,
1226 siba_sprom_get_bf_lo(dev) | BWN_BFL_PACTRL);
1227 if (siba_get_pci_subvendor(dev) == SIBA_BOARDVENDOR_DELL &&
1228 siba_get_chipid(dev) == 0x4301 && siba_get_pci_revid(dev) == 0x74)
1229 siba_sprom_set_bf_lo(dev,
1230 siba_sprom_get_bf_lo(dev) | BWN_BFL_BTCOEXIST);
1231 if (siba_get_type(dev) == SIBA_TYPE_PCI) {
1232 if (BWN_ISDEV(BROADCOM, 0x4318, ASUSTEK, 0x100f) ||
1233 BWN_ISDEV(BROADCOM, 0x4320, DELL, 0x0003) ||
1234 BWN_ISDEV(BROADCOM, 0x4320, HP, 0x12f8) ||
1235 BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0013) ||
1236 BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0014) ||
1237 BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0015) ||
1238 BWN_ISDEV(BROADCOM, 0x4320, MOTOROLA, 0x7010))
1239 siba_sprom_set_bf_lo(dev,
1240 siba_sprom_get_bf_lo(dev) & ~BWN_BFL_BTCOEXIST);
1241 }
1242#undef BWN_ISDEV
1243}
1244
1245static int
1246bwn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1247{
1248#define IS_RUNNING(ifp) \
1249 ((ifp->if_flags & IFF_UP) && (ifp->if_drv_flags & IFF_DRV_RUNNING))
1250 struct bwn_softc *sc = ifp->if_softc;
1251 struct ieee80211com *ic = ifp->if_l2com;
1252 struct ifreq *ifr = (struct ifreq *)data;
1253 int error = 0, startall;
1254
1255 switch (cmd) {
1256 case SIOCSIFFLAGS:
1257 startall = 0;
1258 if (IS_RUNNING(ifp)) {
1259 bwn_update_promisc(ifp);
1260 } else if (ifp->if_flags & IFF_UP) {
1261 if ((sc->sc_flags & BWN_FLAG_INVALID) == 0) {
1262 bwn_init(sc);
1263 startall = 1;
1264 }
1265 } else
1266 bwn_stop(sc, 1);
1267 if (startall)
1268 ieee80211_start_all(ic);
1269 break;
1270 case SIOCGIFMEDIA:
1271 error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
1272 break;
1273 case SIOCGIFADDR:
1274 error = ether_ioctl(ifp, cmd, data);
1275 break;
1276 default:
1277 error = EINVAL;
1278 break;
1279 }
1280 return (error);
1281}
1282
1283static void
1284bwn_start(struct ifnet *ifp)
1285{
1286 struct bwn_softc *sc = ifp->if_softc;
1287
1288 BWN_LOCK(sc);
1289 bwn_start_locked(ifp);
1290 BWN_UNLOCK(sc);
1291}
1292
1293static void
1294bwn_start_locked(struct ifnet *ifp)
1295{
1296 struct bwn_softc *sc = ifp->if_softc;
1297 struct bwn_mac *mac = sc->sc_curmac;
1298 struct ieee80211_frame *wh;
1299 struct ieee80211_node *ni;
1300 struct ieee80211_key *k;
1301 struct mbuf *m;
1302
1303 BWN_ASSERT_LOCKED(sc);
1304
1305 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || mac == NULL ||
1306 mac->mac_status < BWN_MAC_STATUS_STARTED)
1307 return;
1308
1309 for (;;) {
1310 IFQ_DRV_DEQUEUE(&ifp->if_snd, m); /* XXX: LOCK */
1311 if (m == NULL)
1312 break;
1313
1314 if (bwn_tx_isfull(sc, m))
1315 break;
1316 ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
1317 if (ni == NULL) {
1318 device_printf(sc->sc_dev, "unexpected NULL ni\n");
1319 m_freem(m);
1320 ifp->if_oerrors++;
1321 continue;
1322 }
1323 KASSERT(ni != NULL, ("%s:%d: fail", __func__, __LINE__));
1324 wh = mtod(m, struct ieee80211_frame *);
1325 if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
1326 k = ieee80211_crypto_encap(ni, m);
1327 if (k == NULL) {
1328 ieee80211_free_node(ni);
1329 m_freem(m);
1330 ifp->if_oerrors++;
1331 continue;
1332 }
1333 }
1334 wh = NULL; /* Catch any invalid use */
1335
1336 if (bwn_tx_start(sc, ni, m) != 0) {
1337 if (ni != NULL)
1338 ieee80211_free_node(ni);
1339 ifp->if_oerrors++;
1340 continue;
1341 }
1342
1343 sc->sc_watchdog_timer = 5;
1344 }
1345}
1346
1347static int
1348bwn_tx_isfull(struct bwn_softc *sc, struct mbuf *m)
1349{
1350 struct bwn_dma_ring *dr;
1351 struct bwn_mac *mac = sc->sc_curmac;
1352 struct bwn_pio_txqueue *tq;
1353 struct ifnet *ifp = sc->sc_ifp;
1354 int pktlen = roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1355
1356 BWN_ASSERT_LOCKED(sc);
1357
1358 if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
1359 dr = bwn_dma_select(mac, M_WME_GETAC(m));
1360 if (dr->dr_stop == 1 ||
1361 bwn_dma_freeslot(dr) < BWN_TX_SLOTS_PER_FRAME) {
1362 dr->dr_stop = 1;
1363 goto full;
1364 }
1365 } else {
1366 tq = bwn_pio_select(mac, M_WME_GETAC(m));
1367 if (tq->tq_free == 0 || pktlen > tq->tq_size ||
1368 pktlen > (tq->tq_size - tq->tq_used)) {
1369 tq->tq_stop = 1;
1370 goto full;
1371 }
1372 }
1373 return (0);
1374full:
1375 IFQ_DRV_PREPEND(&ifp->if_snd, m);
1376 ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1377 return (1);
1378}
1379
1380static int
1381bwn_tx_start(struct bwn_softc *sc, struct ieee80211_node *ni, struct mbuf *m)
1382{
1383 struct bwn_mac *mac = sc->sc_curmac;
1384 int error;
1385
1386 BWN_ASSERT_LOCKED(sc);
1387
1388 if (m->m_pkthdr.len < IEEE80211_MIN_LEN || mac == NULL) {
1389 m_freem(m);
1390 return (ENXIO);
1391 }
1392
1393 error = (mac->mac_flags & BWN_MAC_FLAG_DMA) ?
1394 bwn_dma_tx_start(mac, ni, m) : bwn_pio_tx_start(mac, ni, m);
1395 if (error) {
1396 m_freem(m);
1397 return (error);
1398 }
1399 return (0);
1400}
1401
1402static int
1403bwn_pio_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1404{
1405 struct bwn_pio_txpkt *tp;
1406 struct bwn_pio_txqueue *tq = bwn_pio_select(mac, M_WME_GETAC(m));
1407 struct bwn_softc *sc = mac->mac_sc;
1408 struct bwn_txhdr txhdr;
1409 struct mbuf *m_new;
1410 uint32_t ctl32;
1411 int error;
1412 uint16_t ctl16;
1413
1414 BWN_ASSERT_LOCKED(sc);
1415
1416 /* XXX TODO send packets after DTIM */
1417
1418 KASSERT(!TAILQ_EMPTY(&tq->tq_pktlist), ("%s: fail", __func__));
1419 tp = TAILQ_FIRST(&tq->tq_pktlist);
1420 tp->tp_ni = ni;
1421 tp->tp_m = m;
1422
1423 error = bwn_set_txhdr(mac, ni, m, &txhdr, BWN_PIO_COOKIE(tq, tp));
1424 if (error) {
1425 device_printf(sc->sc_dev, "tx fail\n");
1426 return (error);
1427 }
1428
1429 TAILQ_REMOVE(&tq->tq_pktlist, tp, tp_list);
1430 tq->tq_used += roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1431 tq->tq_free--;
1432
1433 if (siba_get_revid(sc->sc_dev) >= 8) {
1434 /*
1435 * XXX please removes m_defrag(9)
1436 */
1437 m_new = m_defrag(m, M_DONTWAIT);
1438 if (m_new == NULL) {
1439 device_printf(sc->sc_dev,
1440 "%s: can't defrag TX buffer\n",
1441 __func__);
1442 return (ENOBUFS);
1443 }
1444 if (m_new->m_next != NULL)
1445 device_printf(sc->sc_dev,
1446 "TODO: fragmented packets for PIO\n");
1447 tp->tp_m = m_new;
1448
1449 /* send HEADER */
1450 ctl32 = bwn_pio_write_multi_4(mac, tq,
1451 (BWN_PIO_READ_4(mac, tq, BWN_PIO8_TXCTL) |
1452 BWN_PIO8_TXCTL_FRAMEREADY) & ~BWN_PIO8_TXCTL_EOF,
1453 (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1454 /* send BODY */
1455 ctl32 = bwn_pio_write_multi_4(mac, tq, ctl32,
1456 mtod(m_new, const void *), m_new->m_pkthdr.len);
1457 bwn_pio_write_4(mac, tq, BWN_PIO_TXCTL,
1458 ctl32 | BWN_PIO8_TXCTL_EOF);
1459 } else {
1460 ctl16 = bwn_pio_write_multi_2(mac, tq,
1461 (bwn_pio_read_2(mac, tq, BWN_PIO_TXCTL) |
1462 BWN_PIO_TXCTL_FRAMEREADY) & ~BWN_PIO_TXCTL_EOF,
1463 (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1464 ctl16 = bwn_pio_write_mbuf_2(mac, tq, ctl16, m);
1465 BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL,
1466 ctl16 | BWN_PIO_TXCTL_EOF);
1467 }
1468
1469 return (0);
1470}
1471
1472static struct bwn_pio_txqueue *
1473bwn_pio_select(struct bwn_mac *mac, uint8_t prio)
1474{
1475
1476 if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
1477 return (&mac->mac_method.pio.wme[WME_AC_BE]);
1478
1479 switch (prio) {
1480 case 0:
1481 return (&mac->mac_method.pio.wme[WME_AC_BE]);
1482 case 1:
1483 return (&mac->mac_method.pio.wme[WME_AC_BK]);
1484 case 2:
1485 return (&mac->mac_method.pio.wme[WME_AC_VI]);
1486 case 3:
1487 return (&mac->mac_method.pio.wme[WME_AC_VO]);
1488 }
1489 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
1490 return (NULL);
1491}
1492
1493static int
1494bwn_dma_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1495{
1496#define BWN_GET_TXHDRCACHE(slot) \
1497 &(txhdr_cache[(slot / BWN_TX_SLOTS_PER_FRAME) * BWN_HDRSIZE(mac)])
1498 struct bwn_dma *dma = &mac->mac_method.dma;
1499 struct bwn_dma_ring *dr = bwn_dma_select(mac, M_WME_GETAC(m));
1500 struct bwn_dmadesc_generic *desc;
1501 struct bwn_dmadesc_meta *mt;
1502 struct bwn_softc *sc = mac->mac_sc;
1503 struct ifnet *ifp = sc->sc_ifp;
1504 uint8_t *txhdr_cache = (uint8_t *)dr->dr_txhdr_cache;
1505 int error, slot, backup[2] = { dr->dr_curslot, dr->dr_usedslot };
1506
1507 BWN_ASSERT_LOCKED(sc);
1508 KASSERT(!dr->dr_stop, ("%s:%d: fail", __func__, __LINE__));
1509
1510 /* XXX send after DTIM */
1511
1512 slot = bwn_dma_getslot(dr);
1513 dr->getdesc(dr, slot, &desc, &mt);
1514 KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_HEADER,
1515 ("%s:%d: fail", __func__, __LINE__));
1516
1517 error = bwn_set_txhdr(dr->dr_mac, ni, m,
1518 (struct bwn_txhdr *)BWN_GET_TXHDRCACHE(slot),
1519 BWN_DMA_COOKIE(dr, slot));
1520 if (error)
1521 goto fail;
1522 error = bus_dmamap_load(dr->dr_txring_dtag, mt->mt_dmap,
1523 BWN_GET_TXHDRCACHE(slot), BWN_HDRSIZE(mac), bwn_dma_ring_addr,
1524 &mt->mt_paddr, BUS_DMA_NOWAIT);
1525 if (error) {
1526 if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
1527 __func__, error);
1528 goto fail;
1529 }
1530 bus_dmamap_sync(dr->dr_txring_dtag, mt->mt_dmap,
1531 BUS_DMASYNC_PREWRITE);
1532 dr->setdesc(dr, desc, mt->mt_paddr, BWN_HDRSIZE(mac), 1, 0, 0);
1533 bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1534 BUS_DMASYNC_PREWRITE);
1535
1536 slot = bwn_dma_getslot(dr);
1537 dr->getdesc(dr, slot, &desc, &mt);
1538 KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_BODY &&
1539 mt->mt_islast == 1, ("%s:%d: fail", __func__, __LINE__));
1540 mt->mt_m = m;
1541 mt->mt_ni = ni;
1542
1543 error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap, m,
1544 bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1545 if (error && error != EFBIG) {
1546 if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
1547 __func__, error);
1548 goto fail;
1549 }
1550 if (error) { /* error == EFBIG */
1551 struct mbuf *m_new;
1552
1553 m_new = m_defrag(m, M_DONTWAIT);
1554 if (m_new == NULL) {
1555 if_printf(ifp, "%s: can't defrag TX buffer\n",
1556 __func__);
1557 error = ENOBUFS;
1558 goto fail;
1559 } else {
1560 m = m_new;
1561 }
1562
1563 mt->mt_m = m;
1564 error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap,
1565 m, bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1566 if (error) {
1567 if_printf(ifp, "%s: can't load TX buffer (2) %d\n",
1568 __func__, error);
1569 goto fail;
1570 }
1571 }
1572 bus_dmamap_sync(dma->txbuf_dtag, mt->mt_dmap, BUS_DMASYNC_PREWRITE);
1573 dr->setdesc(dr, desc, mt->mt_paddr, m->m_pkthdr.len, 0, 1, 1);
1574 bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1575 BUS_DMASYNC_PREWRITE);
1576
1577 /* XXX send after DTIM */
1578
1579 dr->start_transfer(dr, bwn_dma_nextslot(dr, slot));
1580 return (0);
1581fail:
1582 dr->dr_curslot = backup[0];
1583 dr->dr_usedslot = backup[1];
1584 return (error);
1585#undef BWN_GET_TXHDRCACHE
1586}
1587
1588static void
1589bwn_watchdog(void *arg)
1590{
1591 struct bwn_softc *sc = arg;
1592 struct ifnet *ifp = sc->sc_ifp;
1593
1594 if (sc->sc_watchdog_timer != 0 && --sc->sc_watchdog_timer == 0) {
1595 if_printf(ifp, "device timeout\n");
1596 ifp->if_oerrors++;
1597 }
1598 callout_schedule(&sc->sc_watchdog_ch, hz);
1599}
1600
1601static int
1602bwn_attach_core(struct bwn_mac *mac)
1603{
1604 struct bwn_softc *sc = mac->mac_sc;
1605 int error, have_bg = 0, have_a = 0;
1606 uint32_t high;
1607
1608 KASSERT(siba_get_revid(sc->sc_dev) >= 5,
1609 ("unsupported revision %d", siba_get_revid(sc->sc_dev)));
1610
1611 siba_powerup(sc->sc_dev, 0);
1612
1613 high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH);
1614 bwn_reset_core(mac,
1615 (high & BWN_TGSHIGH_HAVE_2GHZ) ? BWN_TGSLOW_SUPPORT_G : 0);
1616 error = bwn_phy_getinfo(mac, high);
1617 if (error)
1618 goto fail;
1619
1620 have_a = (high & BWN_TGSHIGH_HAVE_5GHZ) ? 1 : 0;
1621 have_bg = (high & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1622 if (siba_get_pci_device(sc->sc_dev) != 0x4312 &&
1623 siba_get_pci_device(sc->sc_dev) != 0x4319 &&
1624 siba_get_pci_device(sc->sc_dev) != 0x4324) {
1625 have_a = have_bg = 0;
1626 if (mac->mac_phy.type == BWN_PHYTYPE_A)
1627 have_a = 1;
1628 else if (mac->mac_phy.type == BWN_PHYTYPE_G ||
1629 mac->mac_phy.type == BWN_PHYTYPE_N ||
1630 mac->mac_phy.type == BWN_PHYTYPE_LP)
1631 have_bg = 1;
1632 else
1633 KASSERT(0 == 1, ("%s: unknown phy type (%d)", __func__,
1634 mac->mac_phy.type));
1635 }
1636 /* XXX turns off PHY A because it's not supported */
1637 if (mac->mac_phy.type != BWN_PHYTYPE_LP &&
1638 mac->mac_phy.type != BWN_PHYTYPE_N) {
1639 have_a = 0;
1640 have_bg = 1;
1641 }
1642
1643 if (mac->mac_phy.type == BWN_PHYTYPE_G) {
1644 mac->mac_phy.attach = bwn_phy_g_attach;
1645 mac->mac_phy.detach = bwn_phy_g_detach;
1646 mac->mac_phy.prepare_hw = bwn_phy_g_prepare_hw;
1647 mac->mac_phy.init_pre = bwn_phy_g_init_pre;
1648 mac->mac_phy.init = bwn_phy_g_init;
1649 mac->mac_phy.exit = bwn_phy_g_exit;
1650 mac->mac_phy.phy_read = bwn_phy_g_read;
1651 mac->mac_phy.phy_write = bwn_phy_g_write;
1652 mac->mac_phy.rf_read = bwn_phy_g_rf_read;
1653 mac->mac_phy.rf_write = bwn_phy_g_rf_write;
1654 mac->mac_phy.use_hwpctl = bwn_phy_g_hwpctl;
1655 mac->mac_phy.rf_onoff = bwn_phy_g_rf_onoff;
1656 mac->mac_phy.switch_analog = bwn_phy_switch_analog;
1657 mac->mac_phy.switch_channel = bwn_phy_g_switch_channel;
1658 mac->mac_phy.get_default_chan = bwn_phy_g_get_default_chan;
1659 mac->mac_phy.set_antenna = bwn_phy_g_set_antenna;
1660 mac->mac_phy.set_im = bwn_phy_g_im;
1661 mac->mac_phy.recalc_txpwr = bwn_phy_g_recalc_txpwr;
1662 mac->mac_phy.set_txpwr = bwn_phy_g_set_txpwr;
1663 mac->mac_phy.task_15s = bwn_phy_g_task_15s;
1664 mac->mac_phy.task_60s = bwn_phy_g_task_60s;
1665 } else if (mac->mac_phy.type == BWN_PHYTYPE_LP) {
1666 mac->mac_phy.init_pre = bwn_phy_lp_init_pre;
1667 mac->mac_phy.init = bwn_phy_lp_init;
1668 mac->mac_phy.phy_read = bwn_phy_lp_read;
1669 mac->mac_phy.phy_write = bwn_phy_lp_write;
1670 mac->mac_phy.phy_maskset = bwn_phy_lp_maskset;
1671 mac->mac_phy.rf_read = bwn_phy_lp_rf_read;
1672 mac->mac_phy.rf_write = bwn_phy_lp_rf_write;
1673 mac->mac_phy.rf_onoff = bwn_phy_lp_rf_onoff;
1674 mac->mac_phy.switch_analog = bwn_phy_lp_switch_analog;
1675 mac->mac_phy.switch_channel = bwn_phy_lp_switch_channel;
1676 mac->mac_phy.get_default_chan = bwn_phy_lp_get_default_chan;
1677 mac->mac_phy.set_antenna = bwn_phy_lp_set_antenna;
1678 mac->mac_phy.task_60s = bwn_phy_lp_task_60s;
1679 } else {
1680 device_printf(sc->sc_dev, "unsupported PHY type (%d)\n",
1681 mac->mac_phy.type);
1682 error = ENXIO;
1683 goto fail;
1684 }
1685
1686 mac->mac_phy.gmode = have_bg;
1687 if (mac->mac_phy.attach != NULL) {
1688 error = mac->mac_phy.attach(mac);
1689 if (error) {
1690 device_printf(sc->sc_dev, "failed\n");
1691 goto fail;
1692 }
1693 }
1694
1695 bwn_reset_core(mac, have_bg ? BWN_TGSLOW_SUPPORT_G : 0);
1696
1697 error = bwn_chiptest(mac);
1698 if (error)
1699 goto fail;
1700 error = bwn_setup_channels(mac, have_bg, have_a);
1701 if (error) {
1702 device_printf(sc->sc_dev, "failed to setup channels\n");
1703 goto fail;
1704 }
1705
1706 if (sc->sc_curmac == NULL)
1707 sc->sc_curmac = mac;
1708
1709 error = bwn_dma_attach(mac);
1710 if (error != 0) {
1711 device_printf(sc->sc_dev, "failed to initialize DMA\n");
1712 goto fail;
1713 }
1714
1715 mac->mac_phy.switch_analog(mac, 0);
1716
1717 siba_dev_down(sc->sc_dev, 0);
1718fail:
1719 siba_powerdown(sc->sc_dev);
1720 return (error);
1721}
1722
1723static void
1724bwn_reset_core(struct bwn_mac *mac, uint32_t flags)
1725{
1726 struct bwn_softc *sc = mac->mac_sc;
1727 uint32_t low, ctl;
1728
1729 flags |= (BWN_TGSLOW_PHYCLOCK_ENABLE | BWN_TGSLOW_PHYRESET);
1730
1731 siba_dev_up(sc->sc_dev, flags);
1732 DELAY(2000);
1733
1734 low = (siba_read_4(sc->sc_dev, SIBA_TGSLOW) | SIBA_TGSLOW_FGC) &
1735 ~BWN_TGSLOW_PHYRESET;
1736 siba_write_4(sc->sc_dev, SIBA_TGSLOW, low);
1737 siba_read_4(sc->sc_dev, SIBA_TGSLOW);
1738 DELAY(1000);
1739 siba_write_4(sc->sc_dev, SIBA_TGSLOW, low & ~SIBA_TGSLOW_FGC);
1740 siba_read_4(sc->sc_dev, SIBA_TGSLOW);
1741 DELAY(1000);
1742
1743 if (mac->mac_phy.switch_analog != NULL)
1744 mac->mac_phy.switch_analog(mac, 1);
1745
1746 ctl = BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GMODE;
1747 if (flags & BWN_TGSLOW_SUPPORT_G)
1748 ctl |= BWN_MACCTL_GMODE;
1749 BWN_WRITE_4(mac, BWN_MACCTL, ctl | BWN_MACCTL_IHR_ON);
1750}
1751
1752static int
1753bwn_phy_getinfo(struct bwn_mac *mac, int tgshigh)
1754{
1755 struct bwn_phy *phy = &mac->mac_phy;
1756 struct bwn_softc *sc = mac->mac_sc;
1757 uint32_t tmp;
1758
1759 /* PHY */
1760 tmp = BWN_READ_2(mac, BWN_PHYVER);
1761 phy->gmode = (tgshigh & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1762 phy->rf_on = 1;
1763 phy->analog = (tmp & BWN_PHYVER_ANALOG) >> 12;
1764 phy->type = (tmp & BWN_PHYVER_TYPE) >> 8;
1765 phy->rev = (tmp & BWN_PHYVER_VERSION);
1766 if ((phy->type == BWN_PHYTYPE_A && phy->rev >= 4) ||
1767 (phy->type == BWN_PHYTYPE_B && phy->rev != 2 &&
1768 phy->rev != 4 && phy->rev != 6 && phy->rev != 7) ||
1769 (phy->type == BWN_PHYTYPE_G && phy->rev > 9) ||
1770 (phy->type == BWN_PHYTYPE_N && phy->rev > 4) ||
1771 (phy->type == BWN_PHYTYPE_LP && phy->rev > 2))
1772 goto unsupphy;
1773
1774 /* RADIO */
1775 if (siba_get_chipid(sc->sc_dev) == 0x4317) {
1776 if (siba_get_chiprev(sc->sc_dev) == 0)
1777 tmp = 0x3205017f;
1778 else if (siba_get_chiprev(sc->sc_dev) == 1)
1779 tmp = 0x4205017f;
1780 else
1781 tmp = 0x5205017f;
1782 } else {
1783 BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1784 tmp = BWN_READ_2(mac, BWN_RFDATALO);
1785 BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1786 tmp |= (uint32_t)BWN_READ_2(mac, BWN_RFDATAHI) << 16;
1787 }
1788 phy->rf_rev = (tmp & 0xf0000000) >> 28;
1789 phy->rf_ver = (tmp & 0x0ffff000) >> 12;
1790 phy->rf_manuf = (tmp & 0x00000fff);
1791 if (phy->rf_manuf != 0x17f) /* 0x17f is broadcom */
1792 goto unsupradio;
1793 if ((phy->type == BWN_PHYTYPE_A && (phy->rf_ver != 0x2060 ||
1794 phy->rf_rev != 1 || phy->rf_manuf != 0x17f)) ||
1795 (phy->type == BWN_PHYTYPE_B && (phy->rf_ver & 0xfff0) != 0x2050) ||
1796 (phy->type == BWN_PHYTYPE_G && phy->rf_ver != 0x2050) ||
1797 (phy->type == BWN_PHYTYPE_N &&
1798 phy->rf_ver != 0x2055 && phy->rf_ver != 0x2056) ||
1799 (phy->type == BWN_PHYTYPE_LP &&
1800 phy->rf_ver != 0x2062 && phy->rf_ver != 0x2063))
1801 goto unsupradio;
1802
1803 return (0);
1804unsupphy:
1805 device_printf(sc->sc_dev, "unsupported PHY (type %#x, rev %#x, "
1806 "analog %#x)\n",
1807 phy->type, phy->rev, phy->analog);
1808 return (ENXIO);
1809unsupradio:
1810 device_printf(sc->sc_dev, "unsupported radio (manuf %#x, ver %#x, "
1811 "rev %#x)\n",
1812 phy->rf_manuf, phy->rf_ver, phy->rf_rev);
1813 return (ENXIO);
1814}
1815
1816static int
1817bwn_chiptest(struct bwn_mac *mac)
1818{
1819#define TESTVAL0 0x55aaaa55
1820#define TESTVAL1 0xaa5555aa
1821 struct bwn_softc *sc = mac->mac_sc;
1822 uint32_t v, backup;
1823
1824 BWN_LOCK(sc);
1825
1826 backup = bwn_shm_read_4(mac, BWN_SHARED, 0);
1827
1828 bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL0);
1829 if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL0)
1830 goto error;
1831 bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL1);
1832 if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL1)
1833 goto error;
1834
1835 bwn_shm_write_4(mac, BWN_SHARED, 0, backup);
1836
1837 if ((siba_get_revid(sc->sc_dev) >= 3) &&
1838 (siba_get_revid(sc->sc_dev) <= 10)) {
1839 BWN_WRITE_2(mac, BWN_TSF_CFP_START, 0xaaaa);
1840 BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0xccccbbbb);
1841 if (BWN_READ_2(mac, BWN_TSF_CFP_START_LOW) != 0xbbbb)
1842 goto error;
1843 if (BWN_READ_2(mac, BWN_TSF_CFP_START_HIGH) != 0xcccc)
1844 goto error;
1845 }
1846 BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0);
1847
1848 v = BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_GMODE;
1849 if (v != (BWN_MACCTL_GMODE | BWN_MACCTL_IHR_ON))
1850 goto error;
1851
1852 BWN_UNLOCK(sc);
1853 return (0);
1854error:
1855 BWN_UNLOCK(sc);
1856 device_printf(sc->sc_dev, "failed to validate the chipaccess\n");
1857 return (ENODEV);
1858}
1859
1860#define IEEE80211_CHAN_HTG (IEEE80211_CHAN_HT | IEEE80211_CHAN_G)
1861#define IEEE80211_CHAN_HTA (IEEE80211_CHAN_HT | IEEE80211_CHAN_A)
1862
1863static int
1864bwn_setup_channels(struct bwn_mac *mac, int have_bg, int have_a)
1865{
1866 struct bwn_softc *sc = mac->mac_sc;
1867 struct ifnet *ifp = sc->sc_ifp;
1868 struct ieee80211com *ic = ifp->if_l2com;
1869
1870 memset(ic->ic_channels, 0, sizeof(ic->ic_channels));
1871 ic->ic_nchans = 0;
1872
1873 if (have_bg)
1874 bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1875 &ic->ic_nchans, &bwn_chantable_bg, IEEE80211_CHAN_G);
1876 if (mac->mac_phy.type == BWN_PHYTYPE_N) {
1877 if (have_a)
1878 bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1879 &ic->ic_nchans, &bwn_chantable_n,
1880 IEEE80211_CHAN_HTA);
1881 } else {
1882 if (have_a)
1883 bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1884 &ic->ic_nchans, &bwn_chantable_a,
1885 IEEE80211_CHAN_A);
1886 }
1887
1888 mac->mac_phy.supports_2ghz = have_bg;
1889 mac->mac_phy.supports_5ghz = have_a;
1890
1891 return (ic->ic_nchans == 0 ? ENXIO : 0);
1892}
1893
1894static uint32_t
1895bwn_shm_read_4(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1896{
1897 uint32_t ret;
1898
1899 BWN_ASSERT_LOCKED(mac->mac_sc);
1900
1901 if (way == BWN_SHARED) {
1902 KASSERT((offset & 0x0001) == 0,
1903 ("%s:%d warn", __func__, __LINE__));
1904 if (offset & 0x0003) {
1905 bwn_shm_ctlword(mac, way, offset >> 2);
1906 ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1907 ret <<= 16;
1908 bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1909 ret |= BWN_READ_2(mac, BWN_SHM_DATA);
1910 goto out;
1911 }
1912 offset >>= 2;
1913 }
1914 bwn_shm_ctlword(mac, way, offset);
1915 ret = BWN_READ_4(mac, BWN_SHM_DATA);
1916out:
1917 return (ret);
1918}
1919
1920static uint16_t
1921bwn_shm_read_2(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1922{
1923 uint16_t ret;
1924
1925 BWN_ASSERT_LOCKED(mac->mac_sc);
1926
1927 if (way == BWN_SHARED) {
1928 KASSERT((offset & 0x0001) == 0,
1929 ("%s:%d warn", __func__, __LINE__));
1930 if (offset & 0x0003) {
1931 bwn_shm_ctlword(mac, way, offset >> 2);
1932 ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1933 goto out;
1934 }
1935 offset >>= 2;
1936 }
1937 bwn_shm_ctlword(mac, way, offset);
1938 ret = BWN_READ_2(mac, BWN_SHM_DATA);
1939out:
1940
1941 return (ret);
1942}
1943
1944static void
1945bwn_shm_ctlword(struct bwn_mac *mac, uint16_t way,
1946 uint16_t offset)
1947{
1948 uint32_t control;
1949
1950 control = way;
1951 control <<= 16;
1952 control |= offset;
1953 BWN_WRITE_4(mac, BWN_SHM_CONTROL, control);
1954}
1955
1956static void
1957bwn_shm_write_4(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1958 uint32_t value)
1959{
1960 BWN_ASSERT_LOCKED(mac->mac_sc);
1961
1962 if (way == BWN_SHARED) {
1963 KASSERT((offset & 0x0001) == 0,
1964 ("%s:%d warn", __func__, __LINE__));
1965 if (offset & 0x0003) {
1966 bwn_shm_ctlword(mac, way, offset >> 2);
1967 BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED,
1968 (value >> 16) & 0xffff);
1969 bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1970 BWN_WRITE_2(mac, BWN_SHM_DATA, value & 0xffff);
1971 return;
1972 }
1973 offset >>= 2;
1974 }
1975 bwn_shm_ctlword(mac, way, offset);
1976 BWN_WRITE_4(mac, BWN_SHM_DATA, value);
1977}
1978
1979static void
1980bwn_shm_write_2(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1981 uint16_t value)
1982{
1983 BWN_ASSERT_LOCKED(mac->mac_sc);
1984
1985 if (way == BWN_SHARED) {
1986 KASSERT((offset & 0x0001) == 0,
1987 ("%s:%d warn", __func__, __LINE__));
1988 if (offset & 0x0003) {
1989 bwn_shm_ctlword(mac, way, offset >> 2);
1990 BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED, value);
1991 return;
1992 }
1993 offset >>= 2;
1994 }
1995 bwn_shm_ctlword(mac, way, offset);
1996 BWN_WRITE_2(mac, BWN_SHM_DATA, value);
1997}
1998
1999static void
2000bwn_addchan(struct ieee80211_channel *c, int freq, int flags, int ieee,
2001 int txpow)
2002{
2003
2004 c->ic_freq = freq;
2005 c->ic_flags = flags;
2006 c->ic_ieee = ieee;
2007 c->ic_minpower = 0;
2008 c->ic_maxpower = 2 * txpow;
2009 c->ic_maxregpower = txpow;
2010}
2011
2012static void
2013bwn_addchannels(struct ieee80211_channel chans[], int maxchans, int *nchans,
2014 const struct bwn_channelinfo *ci, int flags)
2015{
2016 struct ieee80211_channel *c;
2017 int i;
2018
2019 c = &chans[*nchans];
2020
2021 for (i = 0; i < ci->nchannels; i++) {
2022 const struct bwn_channel *hc;
2023
2024 hc = &ci->channels[i];
2025 if (*nchans >= maxchans)
2026 break;
2027 bwn_addchan(c, hc->freq, flags, hc->ieee, hc->maxTxPow);
2028 c++, (*nchans)++;
2029 if (flags == IEEE80211_CHAN_G || flags == IEEE80211_CHAN_HTG) {
2030 /* g channel have a separate b-only entry */
2031 if (*nchans >= maxchans)
2032 break;
2033 c[0] = c[-1];
2034 c[-1].ic_flags = IEEE80211_CHAN_B;
2035 c++, (*nchans)++;
2036 }
2037 if (flags == IEEE80211_CHAN_HTG) {
2038 /* HT g channel have a separate g-only entry */
2039 if (*nchans >= maxchans)
2040 break;
2041 c[-1].ic_flags = IEEE80211_CHAN_G;
2042 c[0] = c[-1];
2043 c[0].ic_flags &= ~IEEE80211_CHAN_HT;
2044 c[0].ic_flags |= IEEE80211_CHAN_HT20; /* HT20 */
2045 c++, (*nchans)++;
2046 }
2047 if (flags == IEEE80211_CHAN_HTA) {
2048 /* HT a channel have a separate a-only entry */
2049 if (*nchans >= maxchans)
2050 break;
2051 c[-1].ic_flags = IEEE80211_CHAN_A;
2052 c[0] = c[-1];
2053 c[0].ic_flags &= ~IEEE80211_CHAN_HT;
2054 c[0].ic_flags |= IEEE80211_CHAN_HT20; /* HT20 */
2055 c++, (*nchans)++;
2056 }
2057 }
2058}
2059
2060static int
2061bwn_phy_g_attach(struct bwn_mac *mac)
2062{
2063 struct bwn_softc *sc = mac->mac_sc;
2064 struct bwn_phy *phy = &mac->mac_phy;
2065 struct bwn_phy_g *pg = &phy->phy_g;
2066 unsigned int i;
2067 int16_t pab0, pab1, pab2;
2068 static int8_t bwn_phy_g_tssi2dbm_table[] = BWN_PHY_G_TSSI2DBM_TABLE;
2069 int8_t bg;
2070
2071 bg = (int8_t)siba_sprom_get_tssi_bg(sc->sc_dev);
2072 pab0 = (int16_t)siba_sprom_get_pa0b0(sc->sc_dev);
2073 pab1 = (int16_t)siba_sprom_get_pa0b1(sc->sc_dev);
2074 pab2 = (int16_t)siba_sprom_get_pa0b2(sc->sc_dev);
2075
2076 if ((siba_get_chipid(sc->sc_dev) == 0x4301) && (phy->rf_ver != 0x2050))
2077 device_printf(sc->sc_dev, "not supported anymore\n");
2078
2079 pg->pg_flags = 0;
2080 if (pab0 == 0 || pab1 == 0 || pab2 == 0 || pab0 == -1 || pab1 == -1 ||
2081 pab2 == -1) {
2082 pg->pg_idletssi = 52;
2083 pg->pg_tssi2dbm = bwn_phy_g_tssi2dbm_table;
2084 return (0);
2085 }
2086
2087 pg->pg_idletssi = (bg == 0 || bg == -1) ? 62 : bg;
2088 pg->pg_tssi2dbm = (uint8_t *)malloc(64, M_DEVBUF, M_NOWAIT | M_ZERO);
2089 if (pg->pg_tssi2dbm == NULL) {
2090 device_printf(sc->sc_dev, "failed to allocate buffer\n");
2091 return (ENOMEM);
2092 }
2093 for (i = 0; i < 64; i++) {
2094 int32_t m1, m2, f, q, delta;
2095 int8_t j = 0;
2096
2097 m1 = BWN_TSSI2DBM(16 * pab0 + i * pab1, 32);
2098 m2 = MAX(BWN_TSSI2DBM(32768 + i * pab2, 256), 1);
2099 f = 256;
2100
2101 do {
2102 if (j > 15) {
2103 device_printf(sc->sc_dev,
2104 "failed to generate tssi2dBm\n");
2105 free(pg->pg_tssi2dbm, M_DEVBUF);
2106 return (ENOMEM);
2107 }
2108 q = BWN_TSSI2DBM(f * 4096 - BWN_TSSI2DBM(m2 * f, 16) *
2109 f, 2048);
2110 delta = abs(q - f);
2111 f = q;
2112 j++;
2113 } while (delta >= 2);
2114
2115 pg->pg_tssi2dbm[i] = MIN(MAX(BWN_TSSI2DBM(m1 * f, 8192), -127),
2116 128);
2117 }
2118
2119 pg->pg_flags |= BWN_PHY_G_FLAG_TSSITABLE_ALLOC;
2120 return (0);
2121}
2122
2123static void
2124bwn_phy_g_detach(struct bwn_mac *mac)
2125{
2126 struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
2127
2128 if (pg->pg_flags & BWN_PHY_G_FLAG_TSSITABLE_ALLOC) {
2129 free(pg->pg_tssi2dbm, M_DEVBUF);
2130 pg->pg_tssi2dbm = NULL;
2131 }
2132 pg->pg_flags = 0;
2133}
2134
2135static void
2136bwn_phy_g_init_pre(struct bwn_mac *mac)
2137{
2138 struct bwn_phy *phy = &mac->mac_phy;
2139 struct bwn_phy_g *pg = &phy->phy_g;
2140 void *tssi2dbm;
2141 int idletssi;
2142 unsigned int i;
2143
2144 tssi2dbm = pg->pg_tssi2dbm;
2145 idletssi = pg->pg_idletssi;
2146
2147 memset(pg, 0, sizeof(*pg));
2148
2149 pg->pg_tssi2dbm = tssi2dbm;
2150 pg->pg_idletssi = idletssi;
2151
2152 memset(pg->pg_minlowsig, 0xff, sizeof(pg->pg_minlowsig));
2153
2154 for (i = 0; i < N(pg->pg_nrssi); i++)
2155 pg->pg_nrssi[i] = -1000;
2156 for (i = 0; i < N(pg->pg_nrssi_lt); i++)
2157 pg->pg_nrssi_lt[i] = i;
2158 pg->pg_lofcal = 0xffff;
2159 pg->pg_initval = 0xffff;
2160 pg->pg_immode = BWN_IMMODE_NONE;
2161 pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_UNKNOWN;
2162 pg->pg_avgtssi = 0xff;
2163
2164 pg->pg_loctl.tx_bias = 0xff;
2165 TAILQ_INIT(&pg->pg_loctl.calib_list);
2166}
2167
2168static int
2169bwn_phy_g_prepare_hw(struct bwn_mac *mac)
2170{
2171 struct bwn_phy *phy = &mac->mac_phy;
2172 struct bwn_phy_g *pg = &phy->phy_g;
2173 struct bwn_softc *sc = mac->mac_sc;
2174 struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2175 static const struct bwn_rfatt rfatt0[] = {
2176 { 3, 0 }, { 1, 0 }, { 5, 0 }, { 7, 0 }, { 9, 0 }, { 2, 0 },
2177 { 0, 0 }, { 4, 0 }, { 6, 0 }, { 8, 0 }, { 1, 1 }, { 2, 1 },
2178 { 3, 1 }, { 4, 1 }
2179 };
2180 static const struct bwn_rfatt rfatt1[] = {
2181 { 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 10, 1 }, { 12, 1 },
2182 { 14, 1 }
2183 };
2184 static const struct bwn_rfatt rfatt2[] = {
2185 { 0, 1 }, { 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 9, 1 },
2186 { 9, 1 }
2187 };
2188 static const struct bwn_bbatt bbatt_0[] = {
2189 { 0 }, { 1 }, { 2 }, { 3 }, { 4 }, { 5 }, { 6 }, { 7 }, { 8 }
2190 };
2191
2192 KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
2193
2194 if (phy->rf_ver == 0x2050 && phy->rf_rev < 6)
2195 pg->pg_bbatt.att = 0;
2196 else
2197 pg->pg_bbatt.att = 2;
2198
2199 /* prepare Radio Attenuation */
2200 pg->pg_rfatt.padmix = 0;
2201
2202 if (siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM &&
2203 siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BCM4309G) {
2204 if (siba_get_pci_revid(sc->sc_dev) < 0x43) {
2205 pg->pg_rfatt.att = 2;
2206 goto done;
2207 } else if (siba_get_pci_revid(sc->sc_dev) < 0x51) {
2208 pg->pg_rfatt.att = 3;
2209 goto done;
2210 }
2211 }
2212
2213 if (phy->type == BWN_PHYTYPE_A) {
2214 pg->pg_rfatt.att = 0x60;
2215 goto done;
2216 }
2217
2218 switch (phy->rf_ver) {
2219 case 0x2050:
2220 switch (phy->rf_rev) {
2221 case 0:
2222 pg->pg_rfatt.att = 5;
2223 goto done;
2224 case 1:
2225 if (phy->type == BWN_PHYTYPE_G) {
2226 if (siba_get_pci_subvendor(sc->sc_dev) ==
2227 SIBA_BOARDVENDOR_BCM &&
2228 siba_get_pci_subdevice(sc->sc_dev) ==
2229 SIBA_BOARD_BCM4309G &&
2230 siba_get_pci_revid(sc->sc_dev) >= 30)
2231 pg->pg_rfatt.att = 3;
2232 else if (siba_get_pci_subvendor(sc->sc_dev) ==
2233 SIBA_BOARDVENDOR_BCM &&
2234 siba_get_pci_subdevice(sc->sc_dev) ==
2235 SIBA_BOARD_BU4306)
2236 pg->pg_rfatt.att = 3;
2237 else
2238 pg->pg_rfatt.att = 1;
2239 } else {
2240 if (siba_get_pci_subvendor(sc->sc_dev) ==
2241 SIBA_BOARDVENDOR_BCM &&
2242 siba_get_pci_subdevice(sc->sc_dev) ==
2243 SIBA_BOARD_BCM4309G &&
2244 siba_get_pci_revid(sc->sc_dev) >= 30)
2245 pg->pg_rfatt.att = 7;
2246 else
2247 pg->pg_rfatt.att = 6;
2248 }
2249 goto done;
2250 case 2:
2251 if (phy->type == BWN_PHYTYPE_G) {
2252 if (siba_get_pci_subvendor(sc->sc_dev) ==
2253 SIBA_BOARDVENDOR_BCM &&
2254 siba_get_pci_subdevice(sc->sc_dev) ==
2255 SIBA_BOARD_BCM4309G &&
2256 siba_get_pci_revid(sc->sc_dev) >= 30)
2257 pg->pg_rfatt.att = 3;
2258 else if (siba_get_pci_subvendor(sc->sc_dev) ==
2259 SIBA_BOARDVENDOR_BCM &&
2260 siba_get_pci_subdevice(sc->sc_dev) ==
2261 SIBA_BOARD_BU4306)
2262 pg->pg_rfatt.att = 5;
2263 else if (siba_get_chipid(sc->sc_dev) == 0x4320)
2264 pg->pg_rfatt.att = 4;
2265 else
2266 pg->pg_rfatt.att = 3;
2267 } else
2268 pg->pg_rfatt.att = 6;
2269 goto done;
2270 case 3:
2271 pg->pg_rfatt.att = 5;
2272 goto done;
2273 case 4:
2274 case 5:
2275 pg->pg_rfatt.att = 1;
2276 goto done;
2277 case 6:
2278 case 7:
2279 pg->pg_rfatt.att = 5;
2280 goto done;
2281 case 8:
2282 pg->pg_rfatt.att = 0xa;
2283 pg->pg_rfatt.padmix = 1;
2284 goto done;
2285 case 9:
2286 default:
2287 pg->pg_rfatt.att = 5;
2288 goto done;
2289 }
2290 break;
2291 case 0x2053:
2292 switch (phy->rf_rev) {
2293 case 1:
2294 pg->pg_rfatt.att = 6;
2295 goto done;
2296 }
2297 break;
2298 }
2299 pg->pg_rfatt.att = 5;
2300done:
2301 pg->pg_txctl = (bwn_phy_g_txctl(mac) << 4);
2302
2303 if (!bwn_has_hwpctl(mac)) {
2304 lo->rfatt.array = rfatt0;
2305 lo->rfatt.len = N(rfatt0);
2306 lo->rfatt.min = 0;
2307 lo->rfatt.max = 9;
2308 goto genbbatt;
2309 }
2310 if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
2311 lo->rfatt.array = rfatt1;
2312 lo->rfatt.len = N(rfatt1);
2313 lo->rfatt.min = 0;
2314 lo->rfatt.max = 14;
2315 goto genbbatt;
2316 }
2317 lo->rfatt.array = rfatt2;
2318 lo->rfatt.len = N(rfatt2);
2319 lo->rfatt.min = 0;
2320 lo->rfatt.max = 9;
2321genbbatt:
2322 lo->bbatt.array = bbatt_0;
2323 lo->bbatt.len = N(bbatt_0);
2324 lo->bbatt.min = 0;
2325 lo->bbatt.max = 8;
2326
2327 BWN_READ_4(mac, BWN_MACCTL);
2328 if (phy->rev == 1) {
2329 phy->gmode = 0;
2330 bwn_reset_core(mac, 0);
2331 bwn_phy_g_init_sub(mac);
2332 phy->gmode = 1;
2333 bwn_reset_core(mac, BWN_TGSLOW_SUPPORT_G);
2334 }
2335 return (0);
2336}
2337
2338static uint16_t
2339bwn_phy_g_txctl(struct bwn_mac *mac)
2340{
2341 struct bwn_phy *phy = &mac->mac_phy;
2342
2343 if (phy->rf_ver != 0x2050)
2344 return (0);
2345 if (phy->rf_rev == 1)
2346 return (BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX);
2347 if (phy->rf_rev < 6)
2348 return (BWN_TXCTL_PA2DB);
2349 if (phy->rf_rev == 8)
2350 return (BWN_TXCTL_TXMIX);
2351 return (0);
2352}
2353
2354static int
2355bwn_phy_g_init(struct bwn_mac *mac)
2356{
2357
2358 bwn_phy_g_init_sub(mac);
2359 return (0);
2360}
2361
2362static void
2363bwn_phy_g_exit(struct bwn_mac *mac)
2364{
2365 struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
2366 struct bwn_lo_calib *cal, *tmp;
2367
2368 if (lo == NULL)
2369 return;
2370 TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
2371 TAILQ_REMOVE(&lo->calib_list, cal, list);
2372 free(cal, M_DEVBUF);
2373 }
2374}
2375
2376static uint16_t
2377bwn_phy_g_read(struct bwn_mac *mac, uint16_t reg)
2378{
2379
2380 BWN_WRITE_2(mac, BWN_PHYCTL, reg);
2381 return (BWN_READ_2(mac, BWN_PHYDATA));
2382}
2383
2384static void
2385bwn_phy_g_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
2386{
2387
2388 BWN_WRITE_2(mac, BWN_PHYCTL, reg);
2389 BWN_WRITE_2(mac, BWN_PHYDATA, value);
2390}
2391
2392static uint16_t
2393bwn_phy_g_rf_read(struct bwn_mac *mac, uint16_t reg)
2394{
2395
2396 KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
2397 BWN_WRITE_2(mac, BWN_RFCTL, reg | 0x80);
2398 return (BWN_READ_2(mac, BWN_RFDATALO));
2399}
2400
2401static void
2402bwn_phy_g_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
2403{
2404
2405 KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
2406 BWN_WRITE_2(mac, BWN_RFCTL, reg);
2407 BWN_WRITE_2(mac, BWN_RFDATALO, value);
2408}
2409
2410static int
2411bwn_phy_g_hwpctl(struct bwn_mac *mac)
2412{
2413
2414 return (mac->mac_phy.rev >= 6);
2415}
2416
2417static void
2418bwn_phy_g_rf_onoff(struct bwn_mac *mac, int on)
2419{
2420 struct bwn_phy *phy = &mac->mac_phy;
2421 struct bwn_phy_g *pg = &phy->phy_g;
2422 unsigned int channel;
2423 uint16_t rfover, rfoverval;
2424
2425 if (on) {
2426 if (phy->rf_on)
2427 return;
2428
2429 BWN_PHY_WRITE(mac, 0x15, 0x8000);
2430 BWN_PHY_WRITE(mac, 0x15, 0xcc00);
2431 BWN_PHY_WRITE(mac, 0x15, (phy->gmode ? 0xc0 : 0x0));
2432 if (pg->pg_flags & BWN_PHY_G_FLAG_RADIOCTX_VALID) {
2433 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
2434 pg->pg_radioctx_over);
2435 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
2436 pg->pg_radioctx_overval);
2437 pg->pg_flags &= ~BWN_PHY_G_FLAG_RADIOCTX_VALID;
2438 }
2439 channel = phy->chan;
2440 bwn_phy_g_switch_chan(mac, 6, 1);
2441 bwn_phy_g_switch_chan(mac, channel, 0);
2442 return;
2443 }
2444
2445 rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
2446 rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
2447 pg->pg_radioctx_over = rfover;
2448 pg->pg_radioctx_overval = rfoverval;
2449 pg->pg_flags |= BWN_PHY_G_FLAG_RADIOCTX_VALID;
2450 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover | 0x008c);
2451 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval & 0xff73);
2452}
2453
2454static int
2455bwn_phy_g_switch_channel(struct bwn_mac *mac, uint32_t newchan)
2456{
2457
2458 if ((newchan < 1) || (newchan > 14))
2459 return (EINVAL);
2460 bwn_phy_g_switch_chan(mac, newchan, 0);
2461
2462 return (0);
2463}
2464
2465static uint32_t
2466bwn_phy_g_get_default_chan(struct bwn_mac *mac)
2467{
2468
2469 return (1);
2470}
2471
2472static void
2473bwn_phy_g_set_antenna(struct bwn_mac *mac, int antenna)
2474{
2475 struct bwn_phy *phy = &mac->mac_phy;
2476 uint64_t hf;
2477 int autodiv = 0;
2478 uint16_t tmp;
2479
2480 if (antenna == BWN_ANTAUTO0 || antenna == BWN_ANTAUTO1)
2481 autodiv = 1;
2482
2483 hf = bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER;
2484 bwn_hf_write(mac, hf);
2485
2486 BWN_PHY_WRITE(mac, BWN_PHY_BBANDCFG,
2487 (BWN_PHY_READ(mac, BWN_PHY_BBANDCFG) & ~BWN_PHY_BBANDCFG_RXANT) |
2488 ((autodiv ? BWN_ANTAUTO1 : antenna)
2489 << BWN_PHY_BBANDCFG_RXANT_SHIFT));
2490
2491 if (autodiv) {
2492 tmp = BWN_PHY_READ(mac, BWN_PHY_ANTDWELL);
2493 if (antenna == BWN_ANTAUTO1)
2494 tmp &= ~BWN_PHY_ANTDWELL_AUTODIV1;
2495 else
2496 tmp |= BWN_PHY_ANTDWELL_AUTODIV1;
2497 BWN_PHY_WRITE(mac, BWN_PHY_ANTDWELL, tmp);
2498 }
2499 tmp = BWN_PHY_READ(mac, BWN_PHY_ANTWRSETT);
2500 if (autodiv)
2501 tmp |= BWN_PHY_ANTWRSETT_ARXDIV;
2502 else
2503 tmp &= ~BWN_PHY_ANTWRSETT_ARXDIV;
2504 BWN_PHY_WRITE(mac, BWN_PHY_ANTWRSETT, tmp);
2505 if (phy->rev >= 2) {
2506 BWN_PHY_WRITE(mac, BWN_PHY_OFDM61,
2507 BWN_PHY_READ(mac, BWN_PHY_OFDM61) | BWN_PHY_OFDM61_10);
2508 BWN_PHY_WRITE(mac, BWN_PHY_DIVSRCHGAINBACK,
2509 (BWN_PHY_READ(mac, BWN_PHY_DIVSRCHGAINBACK) & 0xff00) |
2510 0x15);
2511 if (phy->rev == 2)
2512 BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED, 8);
2513 else
2514 BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED,
2515 (BWN_PHY_READ(mac, BWN_PHY_ADIVRELATED) & 0xff00) |
2516 8);
2517 }
2518 if (phy->rev >= 6)
2519 BWN_PHY_WRITE(mac, BWN_PHY_OFDM9B, 0xdc);
2520
2521 hf |= BWN_HF_UCODE_ANTDIV_HELPER;
2522 bwn_hf_write(mac, hf);
2523}
2524
2525static int
2526bwn_phy_g_im(struct bwn_mac *mac, int mode)
2527{
2528 struct bwn_phy *phy = &mac->mac_phy;
2529 struct bwn_phy_g *pg = &phy->phy_g;
2530
2531 KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2532 KASSERT(mode == BWN_IMMODE_NONE, ("%s: fail", __func__));
2533
2534 if (phy->rev == 0 || !phy->gmode)
2535 return (ENODEV);
2536
2537 pg->pg_aci_wlan_automatic = 0;
2538 return (0);
2539}
2540
2541static int
2542bwn_phy_g_recalc_txpwr(struct bwn_mac *mac, int ignore_tssi)
2543{
2544 struct bwn_phy *phy = &mac->mac_phy;
2545 struct bwn_phy_g *pg = &phy->phy_g;
2546 struct bwn_softc *sc = mac->mac_sc;
2547 unsigned int tssi;
2548 int cck, ofdm;
2549 int power;
2550 int rfatt, bbatt;
2551 unsigned int max;
2552
2553 KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2554
2555 cck = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_CCK);
2556 ofdm = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_OFDM_G);
2557 if (cck < 0 && ofdm < 0) {
2558 if (ignore_tssi == 0)
2559 return (BWN_TXPWR_RES_DONE);
2560 cck = 0;
2561 ofdm = 0;
2562 }
2563 tssi = (cck < 0) ? ofdm : ((ofdm < 0) ? cck : (cck + ofdm) / 2);
2564 if (pg->pg_avgtssi != 0xff)
2565 tssi = (tssi + pg->pg_avgtssi) / 2;
2566 pg->pg_avgtssi = tssi;
2567 KASSERT(tssi < BWN_TSSI_MAX, ("%s:%d: fail", __func__, __LINE__));
2568
2569 max = siba_sprom_get_maxpwr_bg(sc->sc_dev);
2570 if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
2571 max -= 3;
2572 if (max >= 120) {
2573 device_printf(sc->sc_dev, "invalid max TX-power value\n");
2574 max = 80;
2575 siba_sprom_set_maxpwr_bg(sc->sc_dev, max);
2576 }
2577
2578 power = MIN(MAX((phy->txpower < 0) ? 0 : (phy->txpower << 2), 0), max) -
2579 (pg->pg_tssi2dbm[MIN(MAX(pg->pg_idletssi - pg->pg_curtssi +
2580 tssi, 0x00), 0x3f)]);
2581 if (power == 0)
2582 return (BWN_TXPWR_RES_DONE);
2583
2584 rfatt = -((power + 7) / 8);
2585 bbatt = (-(power / 2)) - (4 * rfatt);
2586 if ((rfatt == 0) && (bbatt == 0))
2587 return (BWN_TXPWR_RES_DONE);
2588 pg->pg_bbatt_delta = bbatt;
2589 pg->pg_rfatt_delta = rfatt;
2590 return (BWN_TXPWR_RES_NEED_ADJUST);
2591}
2592
2593static void
2594bwn_phy_g_set_txpwr(struct bwn_mac *mac)
2595{
2596 struct bwn_phy *phy = &mac->mac_phy;
2597 struct bwn_phy_g *pg = &phy->phy_g;
2598 struct bwn_softc *sc = mac->mac_sc;
2599 int rfatt, bbatt;
2600 uint8_t txctl;
2601
2602 bwn_mac_suspend(mac);
2603
2604 BWN_ASSERT_LOCKED(sc);
2605
2606 bbatt = pg->pg_bbatt.att;
2607 bbatt += pg->pg_bbatt_delta;
2608 rfatt = pg->pg_rfatt.att;
2609 rfatt += pg->pg_rfatt_delta;
2610
2611 bwn_phy_g_setatt(mac, &bbatt, &rfatt);
2612 txctl = pg->pg_txctl;
2613 if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 2)) {
2614 if (rfatt <= 1) {
2615 if (txctl == 0) {
2616 txctl = BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX;
2617 rfatt += 2;
2618 bbatt += 2;
2619 } else if (siba_sprom_get_bf_lo(sc->sc_dev) &
2620 BWN_BFL_PACTRL) {
2621 bbatt += 4 * (rfatt - 2);
2622 rfatt = 2;
2623 }
2624 } else if (rfatt > 4 && txctl) {
2625 txctl = 0;
2626 if (bbatt < 3) {
2627 rfatt -= 3;
2628 bbatt += 2;
2629 } else {
2630 rfatt -= 2;
2631 bbatt -= 2;
2632 }
2633 }
2634 }
2635 pg->pg_txctl = txctl;
2636 bwn_phy_g_setatt(mac, &bbatt, &rfatt);
2637 pg->pg_rfatt.att = rfatt;
2638 pg->pg_bbatt.att = bbatt;
2639
2640 DPRINTF(sc, BWN_DEBUG_TXPOW, "%s: adjust TX power\n", __func__);
2641
2642 bwn_phy_lock(mac);
2643 bwn_rf_lock(mac);
2644 bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
2645 pg->pg_txctl);
2646 bwn_rf_unlock(mac);
2647 bwn_phy_unlock(mac);
2648
2649 bwn_mac_enable(mac);
2650}
2651
2652static void
2653bwn_phy_g_task_15s(struct bwn_mac *mac)
2654{
2655 struct bwn_phy *phy = &mac->mac_phy;
2656 struct bwn_phy_g *pg = &phy->phy_g;
2657 struct bwn_softc *sc = mac->mac_sc;
2658 struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2659 unsigned long expire, now;
2660 struct bwn_lo_calib *cal, *tmp;
2661 uint8_t expired = 0;
2662
2663 bwn_mac_suspend(mac);
2664
2665 if (lo == NULL)
2666 goto fail;
2667
2668 BWN_GETTIME(now);
2669 if (bwn_has_hwpctl(mac)) {
2670 expire = now - BWN_LO_PWRVEC_EXPIRE;
2671 if (time_before(lo->pwr_vec_read_time, expire)) {
2672 bwn_lo_get_powervector(mac);
2673 bwn_phy_g_dc_lookup_init(mac, 0);
2674 }
2675 goto fail;
2676 }
2677
2678 expire = now - BWN_LO_CALIB_EXPIRE;
2679 TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
2680 if (!time_before(cal->calib_time, expire))
2681 continue;
2682 if (BWN_BBATTCMP(&cal->bbatt, &pg->pg_bbatt) &&
2683 BWN_RFATTCMP(&cal->rfatt, &pg->pg_rfatt)) {
2684 KASSERT(!expired, ("%s:%d: fail", __func__, __LINE__));
2685 expired = 1;
2686 }
2687
2688 DPRINTF(sc, BWN_DEBUG_LO, "expired BB %u RF %u %u I %d Q %d\n",
2689 cal->bbatt.att, cal->rfatt.att, cal->rfatt.padmix,
2690 cal->ctl.i, cal->ctl.q);
2691
2692 TAILQ_REMOVE(&lo->calib_list, cal, list);
2693 free(cal, M_DEVBUF);
2694 }
2695 if (expired || TAILQ_EMPTY(&lo->calib_list)) {
2696 cal = bwn_lo_calibset(mac, &pg->pg_bbatt,
2697 &pg->pg_rfatt);
2698 if (cal == NULL) {
2699 device_printf(sc->sc_dev,
2700 "failed to recalibrate LO\n");
2701 goto fail;
2702 }
2703 TAILQ_INSERT_TAIL(&lo->calib_list, cal, list);
2704 bwn_lo_write(mac, &cal->ctl);
2705 }
2706
2707fail:
2708 bwn_mac_enable(mac);
2709}
2710
2711static void
2712bwn_phy_g_task_60s(struct bwn_mac *mac)
2713{
2714 struct bwn_phy *phy = &mac->mac_phy;
2715 struct bwn_softc *sc = mac->mac_sc;
2716 uint8_t old = phy->chan;
2717
2718 if (!(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI))
2719 return;
2720
2721 bwn_mac_suspend(mac);
2722 bwn_nrssi_slope_11g(mac);
2723 if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 8)) {
2724 bwn_switch_channel(mac, (old >= 8) ? 1 : 13);
2725 bwn_switch_channel(mac, old);
2726 }
2727 bwn_mac_enable(mac);
2728}
2729
2730static void
2731bwn_phy_switch_analog(struct bwn_mac *mac, int on)
2732{
2733
2734 BWN_WRITE_2(mac, BWN_PHY0, on ? 0 : 0xf4);
2735}
2736
2737static int
2738bwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
2739 const struct ieee80211_bpf_params *params)
2740{
2741 struct ieee80211com *ic = ni->ni_ic;
2742 struct ifnet *ifp = ic->ic_ifp;
2743 struct bwn_softc *sc = ifp->if_softc;
2744 struct bwn_mac *mac = sc->sc_curmac;
2745
2746 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
2747 mac->mac_status < BWN_MAC_STATUS_STARTED) {
2748 ieee80211_free_node(ni);
2749 m_freem(m);
2750 return (ENETDOWN);
2751 }
2752
2753 BWN_LOCK(sc);
2754 if (bwn_tx_isfull(sc, m)) {
2755 ieee80211_free_node(ni);
2756 m_freem(m);
2757 ifp->if_oerrors++;
2758 BWN_UNLOCK(sc);
2759 return (ENOBUFS);
2760 }
2761
2762 if (bwn_tx_start(sc, ni, m) != 0) {
2763 if (ni != NULL)
2764 ieee80211_free_node(ni);
2765 ifp->if_oerrors++;
2766 }
2767 sc->sc_watchdog_timer = 5;
2768 BWN_UNLOCK(sc);
2769 return (0);
2770}
2771
2772/*
2773 * Setup driver-specific state for a newly associated node.
2774 * Note that we're called also on a re-associate, the isnew
2775 * param tells us if this is the first time or not.
2776 */
2777static void
2778bwn_newassoc(struct ieee80211_node *ni, int isnew)
2779{
2780 struct ieee80211vap *vap = ni->ni_vap;
2781
2782 ieee80211_amrr_node_init(&BWN_VAP(vap)->bv_amrr,
2783 &BWN_NODE(ni)->bn_amn, ni);
2784}
2785
2786/*
2787 * Callback from the 802.11 layer to update the slot time
2788 * based on the current setting. We use it to notify the
2789 * firmware of ERP changes and the f/w takes care of things
2790 * like slot time and preamble.
2791 */
2792static void
2793bwn_updateslot(struct ifnet *ifp)
2794{
2795 struct bwn_softc *sc = ifp->if_softc;
2796 struct ieee80211com *ic = ifp->if_l2com;
2797 struct bwn_mac *mac;
2798
2799 BWN_LOCK(sc);
2800 if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
2801 mac = (struct bwn_mac *)sc->sc_curmac;
2802 bwn_set_slot_time(mac,
2803 (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20);
2804 }
2805 BWN_UNLOCK(sc);
2806}
2807
2808/*
2809 * Callback from the 802.11 layer after a promiscuous mode change.
2810 * Note this interface does not check the operating mode as this
2811 * is an internal callback and we are expected to honor the current
2812 * state (e.g. this is used for setting the interface in promiscuous
2813 * mode when operating in hostap mode to do ACS).
2814 */
2815static void
2816bwn_update_promisc(struct ifnet *ifp)
2817{
2818 struct bwn_softc *sc = ifp->if_softc;
2819 struct bwn_mac *mac = sc->sc_curmac;
2820
2821 BWN_LOCK(sc);
2822 mac = sc->sc_curmac;
2823 if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2824 if (ifp->if_flags & IFF_PROMISC)
2825 sc->sc_filters |= BWN_MACCTL_PROMISC;
2826 else
2827 sc->sc_filters &= ~BWN_MACCTL_PROMISC;
2828 bwn_set_opmode(mac);
2829 }
2830 BWN_UNLOCK(sc);
2831}
2832
2833/*
2834 * Callback from the 802.11 layer to update WME parameters.
2835 */
2836static int
2837bwn_wme_update(struct ieee80211com *ic)
2838{
2839 struct bwn_softc *sc = ic->ic_ifp->if_softc;
2840 struct bwn_mac *mac = sc->sc_curmac;
2841 struct wmeParams *wmep;
2842 int i;
2843
2844 BWN_LOCK(sc);
2845 mac = sc->sc_curmac;
2846 if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2847 bwn_mac_suspend(mac);
2848 for (i = 0; i < N(sc->sc_wmeParams); i++) {
2849 wmep = &ic->ic_wme.wme_chanParams.cap_wmeParams[i];
2850 bwn_wme_loadparams(mac, wmep, bwn_wme_shm_offsets[i]);
2851 }
2852 bwn_mac_enable(mac);
2853 }
2854 BWN_UNLOCK(sc);
2855 return (0);
2856}
2857
2858static struct ieee80211_node *
2859bwn_node_alloc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN])
2860{
2861 struct ieee80211com *ic = vap->iv_ic;
2862 struct bwn_softc *sc = ic->ic_ifp->if_softc;
2863 const size_t space = sizeof(struct bwn_node);
2864 struct bwn_node *bn;
2865
2866 bn = malloc(space, M_80211_NODE, M_NOWAIT|M_ZERO);
2867 if (bn == NULL) {
2868 /* XXX stat+msg */
2869 return (NULL);
2870 }
2871 DPRINTF(sc, BWN_DEBUG_NODE, "%s: bn %p\n", __func__, bn);
2872 return (&bn->bn_node);
2873}
2874
2875static void
2876bwn_node_cleanup(struct ieee80211_node *ni)
2877{
2878 struct ieee80211com *ic = ni->ni_ic;
2879 struct bwn_softc *sc = ic->ic_ifp->if_softc;
2880
2881 sc->sc_node_cleanup(ni);
2882}
2883
2884static void
2885bwn_scan_start(struct ieee80211com *ic)
2886{
2887 struct ifnet *ifp = ic->ic_ifp;
2888 struct bwn_softc *sc = ifp->if_softc;
2889 struct bwn_mac *mac;
2890
2891 BWN_LOCK(sc);
2892 mac = sc->sc_curmac;
2893 if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2894 sc->sc_filters |= BWN_MACCTL_BEACON_PROMISC;
2895 bwn_set_opmode(mac);
2896 /* disable CFP update during scan */
2897 bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_SKIP_CFP_UPDATE);
2898 }
2899 BWN_UNLOCK(sc);
2900}
2901
2902static void
2903bwn_scan_end(struct ieee80211com *ic)
2904{
2905 struct ifnet *ifp = ic->ic_ifp;
2906 struct bwn_softc *sc = ifp->if_softc;
2907 struct bwn_mac *mac;
2908
2909 BWN_LOCK(sc);
2910 mac = sc->sc_curmac;
2911 if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2912 sc->sc_filters &= ~BWN_MACCTL_BEACON_PROMISC;
2913 bwn_set_opmode(mac);
2914 bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_SKIP_CFP_UPDATE);
2915 }
2916 BWN_UNLOCK(sc);
2917}
2918
2919static void
2920bwn_set_channel(struct ieee80211com *ic)
2921{
2922 struct ifnet *ifp = ic->ic_ifp;
2923 struct bwn_softc *sc = ifp->if_softc;
2924 struct bwn_mac *mac = sc->sc_curmac;
2925 struct bwn_phy *phy = &mac->mac_phy;
2926 int chan, error;
2927
2928 BWN_LOCK(sc);
2929
2930 error = bwn_switch_band(sc, ic->ic_curchan);
2931 if (error)
2932 goto fail;;
2933 bwn_mac_suspend(mac);
2934 bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
2935 chan = ieee80211_chan2ieee(ic, ic->ic_curchan);
2936 if (chan != phy->chan)
2937 bwn_switch_channel(mac, chan);
2938
2939 /* TX power level */
2940 if (ic->ic_curchan->ic_maxpower != 0 &&
2941 ic->ic_curchan->ic_maxpower != phy->txpower) {
2942 phy->txpower = ic->ic_curchan->ic_maxpower / 2;
2943 bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME |
2944 BWN_TXPWR_IGNORE_TSSI);
2945 }
2946
2947 bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
2948 if (phy->set_antenna)
2949 phy->set_antenna(mac, BWN_ANT_DEFAULT);
2950
2951 if (sc->sc_rf_enabled != phy->rf_on) {
2952 if (sc->sc_rf_enabled) {
2953 bwn_rf_turnon(mac);
2954 if (!(mac->mac_flags & BWN_MAC_FLAG_RADIO_ON))
2955 device_printf(sc->sc_dev,
2956 "please turns on the RF switch\n");
2957 } else
2958 bwn_rf_turnoff(mac);
2959 }
2960
2961 bwn_mac_enable(mac);
2962
2963fail:
2964 /*
2965 * Setup radio tap channel freq and flags
2966 */
2967 sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq =
2968 htole16(ic->ic_curchan->ic_freq);
2969 sc->sc_tx_th.wt_chan_flags = sc->sc_rx_th.wr_chan_flags =
2970 htole16(ic->ic_curchan->ic_flags & 0xffff);
2971
2972 BWN_UNLOCK(sc);
2973}
2974
2975static struct ieee80211vap *
2976bwn_vap_create(struct ieee80211com *ic,
2977 const char name[IFNAMSIZ], int unit, int opmode, int flags,
2978 const uint8_t bssid[IEEE80211_ADDR_LEN],
2979 const uint8_t mac0[IEEE80211_ADDR_LEN])
2980{
2981 struct ifnet *ifp = ic->ic_ifp;
2982 struct bwn_softc *sc = ifp->if_softc;
2983 struct ieee80211vap *vap;
2984 struct bwn_vap *bvp;
2985 uint8_t mac[IEEE80211_ADDR_LEN];
2986
2987 IEEE80211_ADDR_COPY(mac, mac0);
2988 switch (opmode) {
2989 case IEEE80211_M_HOSTAP:
2990 case IEEE80211_M_MBSS:
2991 case IEEE80211_M_STA:
2992 case IEEE80211_M_WDS:
2993 case IEEE80211_M_MONITOR:
2994 case IEEE80211_M_IBSS:
2995 case IEEE80211_M_AHDEMO:
2996 break;
2997 default:
2998 return (NULL);
2999 }
3000
3001 IEEE80211_ADDR_COPY(sc->sc_macaddr, mac0);
3002
3003 bvp = (struct bwn_vap *) malloc(sizeof(struct bwn_vap),
3004 M_80211_VAP, M_NOWAIT | M_ZERO);
3005 if (bvp == NULL) {
3006 device_printf(sc->sc_dev, "failed to allocate a buffer\n");
3007 return (NULL);
3008 }
3009 vap = &bvp->bv_vap;
3010 ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
3011 IEEE80211_ADDR_COPY(vap->iv_myaddr, mac);
3012 /* override with driver methods */
3013 bvp->bv_newstate = vap->iv_newstate;
3014 vap->iv_newstate = bwn_newstate;
3015
3016 /* override max aid so sta's cannot assoc when we're out of sta id's */
3017 vap->iv_max_aid = BWN_STAID_MAX;
3018
3019 ieee80211_amrr_init(&bvp->bv_amrr, vap,
3020 IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD,
3021 IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD,
3022 500 /*ms*/);
3023
3024 /* complete setup */
3025 ieee80211_vap_attach(vap, ieee80211_media_change,
3026 ieee80211_media_status);
3027 return (vap);
3028}
3029
3030static void
3031bwn_vap_delete(struct ieee80211vap *vap)
3032{
3033 struct bwn_vap *bvp = BWN_VAP(vap);
3034
3035 ieee80211_amrr_cleanup(&bvp->bv_amrr);
3036 ieee80211_vap_detach(vap);
3037 free(bvp, M_80211_VAP);
3038}
3039
3040static void
3041bwn_init(void *arg)
3042{
3043 struct bwn_softc *sc = arg;
3044 struct ifnet *ifp = sc->sc_ifp;
3045 struct ieee80211com *ic = ifp->if_l2com;
3046 int error = 0;
3047
3048 DPRINTF(sc, BWN_DEBUG_ANY, "%s: if_flags 0x%x\n",
3049 __func__, ifp->if_flags);
3050
3051 BWN_LOCK(sc);
3052 error = bwn_init_locked(sc);
3053 BWN_UNLOCK(sc);
3054
3055 if (error == 0)
3056 ieee80211_start_all(ic); /* start all vap's */
3057}
3058
3059static int
3060bwn_init_locked(struct bwn_softc *sc)
3061{
3062 struct bwn_mac *mac;
3063 struct ifnet *ifp = sc->sc_ifp;
3064 int error;
3065
3066 BWN_ASSERT_LOCKED(sc);
3067
3068 bzero(sc->sc_bssid, IEEE80211_ADDR_LEN);
3069 sc->sc_flags |= BWN_FLAG_NEED_BEACON_TP;
3070 sc->sc_filters = 0;
3071 bwn_wme_clear(sc);
3072 sc->sc_beacons[0] = sc->sc_beacons[1] = 0;
3073 sc->sc_rf_enabled = 1;
3074
3075 mac = sc->sc_curmac;
3076 if (mac->mac_status == BWN_MAC_STATUS_UNINIT) {
3077 error = bwn_core_init(mac);
3078 if (error != 0)
3079 return (error);
3080 }
3081 if (mac->mac_status == BWN_MAC_STATUS_INITED)
3082 bwn_core_start(mac);
3083
3084 bwn_set_opmode(mac);
3085 bwn_set_pretbtt(mac);
3086 bwn_spu_setdelay(mac, 0);
3087 bwn_set_macaddr(mac);
3088
3089 ifp->if_drv_flags |= IFF_DRV_RUNNING;
3090 callout_reset(&sc->sc_rfswitch_ch, hz, bwn_rfswitch, sc);
3091 callout_reset(&sc->sc_watchdog_ch, hz, bwn_watchdog, sc);
3092
3093 return (0);
3094}
3095
3096static void
3097bwn_stop(struct bwn_softc *sc, int statechg)
3098{
3099
3100 BWN_LOCK(sc);
3101 bwn_stop_locked(sc, statechg);
3102 BWN_UNLOCK(sc);
3103}
3104
3105static void
3106bwn_stop_locked(struct bwn_softc *sc, int statechg)
3107{
3108 struct bwn_mac *mac = sc->sc_curmac;
3109 struct ifnet *ifp = sc->sc_ifp;
3110
3111 BWN_ASSERT_LOCKED(sc);
3112
3113 if (mac->mac_status >= BWN_MAC_STATUS_INITED) {
3114 /* XXX FIXME opmode not based on VAP */
3115 bwn_set_opmode(mac);
3116 bwn_set_macaddr(mac);
3117 }
3118
3119 if (mac->mac_status >= BWN_MAC_STATUS_STARTED)
3120 bwn_core_stop(mac);
3121
3122 callout_stop(&sc->sc_led_blink_ch);
3123 sc->sc_led_blinking = 0;
3124
3125 bwn_core_exit(mac);
3126 sc->sc_rf_enabled = 0;
3127
3128 ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
3129}
3130
3131static void
3132bwn_wme_clear(struct bwn_softc *sc)
3133{
3134#define MS(_v, _f) (((_v) & _f) >> _f##_S)
3135 struct wmeParams *p;
3136 unsigned int i;
3137
3138 KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
3139 ("%s:%d: fail", __func__, __LINE__));
3140
3141 for (i = 0; i < N(sc->sc_wmeParams); i++) {
3142 p = &(sc->sc_wmeParams[i]);
3143
3144 switch (bwn_wme_shm_offsets[i]) {
3145 case BWN_WME_VOICE:
3146 p->wmep_txopLimit = 0;
3147 p->wmep_aifsn = 2;
3148 /* XXX FIXME: log2(cwmin) */
3149 p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3150 p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3151 break;
3152 case BWN_WME_VIDEO:
3153 p->wmep_txopLimit = 0;
3154 p->wmep_aifsn = 2;
3155 /* XXX FIXME: log2(cwmin) */
3156 p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3157 p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3158 break;
3159 case BWN_WME_BESTEFFORT:
3160 p->wmep_txopLimit = 0;
3161 p->wmep_aifsn = 3;
3162 /* XXX FIXME: log2(cwmin) */
3163 p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3164 p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3165 break;
3166 case BWN_WME_BACKGROUND:
3167 p->wmep_txopLimit = 0;
3168 p->wmep_aifsn = 7;
3169 /* XXX FIXME: log2(cwmin) */
3170 p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3171 p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3172 break;
3173 default:
3174 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3175 }
3176 }
3177}
3178
3179static int
3180bwn_core_init(struct bwn_mac *mac)
3181{
3182 struct bwn_softc *sc = mac->mac_sc;
3183 uint64_t hf;
3184 int error;
3185
3186 KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3187 ("%s:%d: fail", __func__, __LINE__));
3188
3189 siba_powerup(sc->sc_dev, 0);
3190 if (!siba_dev_isup(sc->sc_dev))
3191 bwn_reset_core(mac,
3192 mac->mac_phy.gmode ? BWN_TGSLOW_SUPPORT_G : 0);
3193
3194 mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
3195 mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
3196 mac->mac_phy.hwpctl = (bwn_hwpctl) ? 1 : 0;
3197 BWN_GETTIME(mac->mac_phy.nexttime);
3198 mac->mac_phy.txerrors = BWN_TXERROR_MAX;
3199 bzero(&mac->mac_stats, sizeof(mac->mac_stats));
3200 mac->mac_stats.link_noise = -95;
3201 mac->mac_reason_intr = 0;
3202 bzero(mac->mac_reason, sizeof(mac->mac_reason));
3203 mac->mac_intr_mask = BWN_INTR_MASKTEMPLATE;
3204#ifdef BWN_DEBUG
3205 if (sc->sc_debug & BWN_DEBUG_XMIT)
3206 mac->mac_intr_mask &= ~BWN_INTR_PHY_TXERR;
3207#endif
3208 mac->mac_suspended = 1;
3209 mac->mac_task_state = 0;
3210 memset(&mac->mac_noise, 0, sizeof(mac->mac_noise));
3211
3212 mac->mac_phy.init_pre(mac);
3213
3214 siba_pcicore_intr(sc->sc_dev);
3215
3216 siba_fix_imcfglobug(sc->sc_dev);
3217 bwn_bt_disable(mac);
3218 if (mac->mac_phy.prepare_hw) {
3219 error = mac->mac_phy.prepare_hw(mac);
3220 if (error)
3221 goto fail0;
3222 }
3223 error = bwn_chip_init(mac);
3224 if (error)
3225 goto fail0;
3226 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_COREREV,
3227 siba_get_revid(sc->sc_dev));
3228 hf = bwn_hf_read(mac);
3229 if (mac->mac_phy.type == BWN_PHYTYPE_G) {
3230 hf |= BWN_HF_GPHY_SYM_WORKAROUND;
3231 if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
3232 hf |= BWN_HF_PAGAINBOOST_OFDM_ON;
3233 if (mac->mac_phy.rev == 1)
3234 hf |= BWN_HF_GPHY_DC_CANCELFILTER;
3235 }
3236 if (mac->mac_phy.rf_ver == 0x2050) {
3237 if (mac->mac_phy.rf_rev < 6)
3238 hf |= BWN_HF_FORCE_VCO_RECALC;
3239 if (mac->mac_phy.rf_rev == 6)
3240 hf |= BWN_HF_4318_TSSI;
3241 }
3242 if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW)
3243 hf |= BWN_HF_SLOWCLOCK_REQ_OFF;
3244 if ((siba_get_type(sc->sc_dev) == SIBA_TYPE_PCI) &&
3245 (siba_get_pcicore_revid(sc->sc_dev) <= 10))
3246 hf |= BWN_HF_PCI_SLOWCLOCK_WORKAROUND;
3247 hf &= ~BWN_HF_SKIP_CFP_UPDATE;
3248 bwn_hf_write(mac, hf);
3249
3250 bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
3251 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SHORT_RETRY_FALLBACK, 3);
3252 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_LONG_RETRY_FALLBACK, 2);
3253 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_MAXTIME, 1);
3254
3255 bwn_rate_init(mac);
3256 bwn_set_phytxctl(mac);
3257
3258 bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MIN,
3259 (mac->mac_phy.type == BWN_PHYTYPE_B) ? 0x1f : 0xf);
3260 bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MAX, 0x3ff);
3261
3262 if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
3263 bwn_pio_init(mac);
3264 else
3265 bwn_dma_init(mac);
3266 if (error)
3267 goto fail1;
3268 bwn_wme_init(mac);
3269 bwn_spu_setdelay(mac, 1);
3270 bwn_bt_enable(mac);
3271
3272 siba_powerup(sc->sc_dev,
3273 !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW));
3274 bwn_set_macaddr(mac);
3275 bwn_crypt_init(mac);
3276
3277 /* XXX LED initializatin */
3278
3279 mac->mac_status = BWN_MAC_STATUS_INITED;
3280
3281 return (error);
3282
3283fail1:
3284 bwn_chip_exit(mac);
3285fail0:
3286 siba_powerdown(sc->sc_dev);
3287 KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3288 ("%s:%d: fail", __func__, __LINE__));
3289 return (error);
3290}
3291
3292static void
3293bwn_core_start(struct bwn_mac *mac)
3294{
3295 struct bwn_softc *sc = mac->mac_sc;
3296 uint32_t tmp;
3297
3298 KASSERT(mac->mac_status == BWN_MAC_STATUS_INITED,
3299 ("%s:%d: fail", __func__, __LINE__));
3300
3301 if (siba_get_revid(sc->sc_dev) < 5)
3302 return;
3303
3304 while (1) {
3305 tmp = BWN_READ_4(mac, BWN_XMITSTAT_0);
3306 if (!(tmp & 0x00000001))
3307 break;
3308 tmp = BWN_READ_4(mac, BWN_XMITSTAT_1);
3309 }
3310
3311 bwn_mac_enable(mac);
3312 BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
3313 callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
3314
3315 mac->mac_status = BWN_MAC_STATUS_STARTED;
3316}
3317
3318static void
3319bwn_core_exit(struct bwn_mac *mac)
3320{
3321 struct bwn_softc *sc = mac->mac_sc;
3322 uint32_t macctl;
3323
3324 BWN_ASSERT_LOCKED(mac->mac_sc);
3325
3326 KASSERT(mac->mac_status <= BWN_MAC_STATUS_INITED,
3327 ("%s:%d: fail", __func__, __LINE__));
3328
3329 if (mac->mac_status != BWN_MAC_STATUS_INITED)
3330 return;
3331 mac->mac_status = BWN_MAC_STATUS_UNINIT;
3332
3333 macctl = BWN_READ_4(mac, BWN_MACCTL);
3334 macctl &= ~BWN_MACCTL_MCODE_RUN;
3335 macctl |= BWN_MACCTL_MCODE_JMP0;
3336 BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3337
3338 bwn_dma_stop(mac);
3339 bwn_pio_stop(mac);
3340 bwn_chip_exit(mac);
3341 mac->mac_phy.switch_analog(mac, 0);
3342 siba_dev_down(sc->sc_dev, 0);
3343 siba_powerdown(sc->sc_dev);
3344}
3345
3346static void
3347bwn_bt_disable(struct bwn_mac *mac)
3348{
3349 struct bwn_softc *sc = mac->mac_sc;
3350
3351 (void)sc;
3352 /* XXX do nothing yet */
3353}
3354
3355static int
3356bwn_chip_init(struct bwn_mac *mac)
3357{
3358 struct bwn_softc *sc = mac->mac_sc;
3359 struct bwn_phy *phy = &mac->mac_phy;
3360 uint32_t macctl;
3361 int error;
3362
3363 macctl = BWN_MACCTL_IHR_ON | BWN_MACCTL_SHM_ON | BWN_MACCTL_STA;
3364 if (phy->gmode)
3365 macctl |= BWN_MACCTL_GMODE;
3366 BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3367
3368 error = bwn_fw_fillinfo(mac);
3369 if (error)
3370 return (error);
3371 error = bwn_fw_loaducode(mac);
3372 if (error)
3373 return (error);
3374
3375 error = bwn_gpio_init(mac);
3376 if (error)
3377 return (error);
3378
3379 error = bwn_fw_loadinitvals(mac);
3380 if (error) {
3381 siba_gpio_set(sc->sc_dev, 0);
3382 return (error);
3383 }
3384 phy->switch_analog(mac, 1);
3385 error = bwn_phy_init(mac);
3386 if (error) {
3387 siba_gpio_set(sc->sc_dev, 0);
3388 return (error);
3389 }
3390 if (phy->set_im)
3391 phy->set_im(mac, BWN_IMMODE_NONE);
3392 if (phy->set_antenna)
3393 phy->set_antenna(mac, BWN_ANT_DEFAULT);
3394 bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
3395
3396 if (phy->type == BWN_PHYTYPE_B)
3397 BWN_WRITE_2(mac, 0x005e, BWN_READ_2(mac, 0x005e) | 0x0004);
3398 BWN_WRITE_4(mac, 0x0100, 0x01000000);
3399 if (siba_get_revid(sc->sc_dev) < 5)
3400 BWN_WRITE_4(mac, 0x010c, 0x01000000);
3401
3402 BWN_WRITE_4(mac, BWN_MACCTL,
3403 BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_STA);
3404 BWN_WRITE_4(mac, BWN_MACCTL,
3405 BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_STA);
3406 bwn_shm_write_2(mac, BWN_SHARED, 0x0074, 0x0000);
3407
3408 bwn_set_opmode(mac);
3409 if (siba_get_revid(sc->sc_dev) < 3) {
3410 BWN_WRITE_2(mac, 0x060e, 0x0000);
3411 BWN_WRITE_2(mac, 0x0610, 0x8000);
3412 BWN_WRITE_2(mac, 0x0604, 0x0000);
3413 BWN_WRITE_2(mac, 0x0606, 0x0200);
3414 } else {
3415 BWN_WRITE_4(mac, 0x0188, 0x80000000);
3416 BWN_WRITE_4(mac, 0x018c, 0x02000000);
3417 }
3418 BWN_WRITE_4(mac, BWN_INTR_REASON, 0x00004000);
3419 BWN_WRITE_4(mac, BWN_DMA0_INTR_MASK, 0x0001dc00);
3420 BWN_WRITE_4(mac, BWN_DMA1_INTR_MASK, 0x0000dc00);
3421 BWN_WRITE_4(mac, BWN_DMA2_INTR_MASK, 0x0000dc00);
3422 BWN_WRITE_4(mac, BWN_DMA3_INTR_MASK, 0x0001dc00);
3423 BWN_WRITE_4(mac, BWN_DMA4_INTR_MASK, 0x0000dc00);
3424 BWN_WRITE_4(mac, BWN_DMA5_INTR_MASK, 0x0000dc00);
3425 siba_write_4(sc->sc_dev, SIBA_TGSLOW,
3426 siba_read_4(sc->sc_dev, SIBA_TGSLOW) | 0x00100000);
3427 BWN_WRITE_2(mac, BWN_POWERUP_DELAY, siba_get_cc_powerdelay(sc->sc_dev));
3428 return (error);
3429}
3430
3431/* read hostflags */
3432static uint64_t
3433bwn_hf_read(struct bwn_mac *mac)
3434{
3435 uint64_t ret;
3436
3437 ret = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFHI);
3438 ret <<= 16;
3439 ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFMI);
3440 ret <<= 16;
3441 ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO);
3442 return (ret);
3443}
3444
3445static void
3446bwn_hf_write(struct bwn_mac *mac, uint64_t value)
3447{
3448
3449 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFLO,
3450 (value & 0x00000000ffffull));
3451 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFMI,
3452 (value & 0x0000ffff0000ull) >> 16);
3453 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFHI,
3454 (value & 0xffff00000000ULL) >> 32);
3455}
3456
3457static void
3458bwn_set_txretry(struct bwn_mac *mac, int s, int l)
3459{
3460
3461 bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_SHORT_RETRY, MIN(s, 0xf));
3462 bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_LONG_RETRY, MIN(l, 0xf));
3463}
3464
3465static void
3466bwn_rate_init(struct bwn_mac *mac)
3467{
3468
3469 switch (mac->mac_phy.type) {
3470 case BWN_PHYTYPE_A:
3471 case BWN_PHYTYPE_G:
3472 case BWN_PHYTYPE_LP:
3473 case BWN_PHYTYPE_N:
3474 bwn_rate_write(mac, BWN_OFDM_RATE_6MB, 1);
3475 bwn_rate_write(mac, BWN_OFDM_RATE_12MB, 1);
3476 bwn_rate_write(mac, BWN_OFDM_RATE_18MB, 1);
3477 bwn_rate_write(mac, BWN_OFDM_RATE_24MB, 1);
3478 bwn_rate_write(mac, BWN_OFDM_RATE_36MB, 1);
3479 bwn_rate_write(mac, BWN_OFDM_RATE_48MB, 1);
3480 bwn_rate_write(mac, BWN_OFDM_RATE_54MB, 1);
3481 if (mac->mac_phy.type == BWN_PHYTYPE_A)
3482 break;
3483 /* FALLTHROUGH */
3484 case BWN_PHYTYPE_B:
3485 bwn_rate_write(mac, BWN_CCK_RATE_1MB, 0);
3486 bwn_rate_write(mac, BWN_CCK_RATE_2MB, 0);
3487 bwn_rate_write(mac, BWN_CCK_RATE_5MB, 0);
3488 bwn_rate_write(mac, BWN_CCK_RATE_11MB, 0);
3489 break;
3490 default:
3491 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3492 }
3493}
3494
3495static void
3496bwn_rate_write(struct bwn_mac *mac, uint16_t rate, int ofdm)
3497{
3498 uint16_t offset;
3499
3500 if (ofdm) {
3501 offset = 0x480;
3502 offset += (bwn_plcp_getofdm(rate) & 0x000f) * 2;
3503 } else {
3504 offset = 0x4c0;
3505 offset += (bwn_plcp_getcck(rate) & 0x000f) * 2;
3506 }
3507 bwn_shm_write_2(mac, BWN_SHARED, offset + 0x20,
3508 bwn_shm_read_2(mac, BWN_SHARED, offset));
3509}
3510
3511static uint8_t
3512bwn_plcp_getcck(const uint8_t bitrate)
3513{
3514
3515 switch (bitrate) {
3516 case BWN_CCK_RATE_1MB:
3517 return (0x0a);
3518 case BWN_CCK_RATE_2MB:
3519 return (0x14);
3520 case BWN_CCK_RATE_5MB:
3521 return (0x37);
3522 case BWN_CCK_RATE_11MB:
3523 return (0x6e);
3524 }
3525 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3526 return (0);
3527}
3528
3529static uint8_t
3530bwn_plcp_getofdm(const uint8_t bitrate)
3531{
3532
3533 switch (bitrate) {
3534 case BWN_OFDM_RATE_6MB:
3535 return (0xb);
3536 case BWN_OFDM_RATE_9MB:
3537 return (0xf);
3538 case BWN_OFDM_RATE_12MB:
3539 return (0xa);
3540 case BWN_OFDM_RATE_18MB:
3541 return (0xe);
3542 case BWN_OFDM_RATE_24MB:
3543 return (0x9);
3544 case BWN_OFDM_RATE_36MB:
3545 return (0xd);
3546 case BWN_OFDM_RATE_48MB:
3547 return (0x8);
3548 case BWN_OFDM_RATE_54MB:
3549 return (0xc);
3550 }
3551 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3552 return (0);
3553}
3554
3555static void
3556bwn_set_phytxctl(struct bwn_mac *mac)
3557{
3558 uint16_t ctl;
3559
3560 ctl = (BWN_TX_PHY_ENC_CCK | BWN_TX_PHY_ANT01AUTO |
3561 BWN_TX_PHY_TXPWR);
3562 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_BEACON_PHYCTL, ctl);
3563 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, ctl);
3564 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, ctl);
3565}
3566
3567static void
3568bwn_pio_init(struct bwn_mac *mac)
3569{
3570 struct bwn_pio *pio = &mac->mac_method.pio;
3571
3572 BWN_WRITE_4(mac, BWN_MACCTL, BWN_READ_4(mac, BWN_MACCTL)
3573 & ~BWN_MACCTL_BIGENDIAN);
3574 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RX_PADOFFSET, 0);
3575
3576 bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BK], 0);
3577 bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BE], 1);
3578 bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VI], 2);
3579 bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VO], 3);
3580 bwn_pio_set_txqueue(mac, &pio->mcast, 4);
3581 bwn_pio_setupqueue_rx(mac, &pio->rx, 0);
3582}
3583
3584static void
3585bwn_pio_set_txqueue(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3586 int index)
3587{
3588 struct bwn_pio_txpkt *tp;
3589 struct bwn_softc *sc = mac->mac_sc;
3590 unsigned int i;
3591
3592 tq->tq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_TXQOFFSET(mac);
3593 tq->tq_index = index;
3594
3595 tq->tq_free = BWN_PIO_MAX_TXPACKETS;
3596 if (siba_get_revid(sc->sc_dev) >= 8)
3597 tq->tq_size = 1920;
3598 else {
3599 tq->tq_size = bwn_pio_read_2(mac, tq, BWN_PIO_TXQBUFSIZE);
3600 tq->tq_size -= 80;
3601 }
3602
3603 TAILQ_INIT(&tq->tq_pktlist);
3604 for (i = 0; i < N(tq->tq_pkts); i++) {
3605 tp = &(tq->tq_pkts[i]);
3606 tp->tp_index = i;
3607 tp->tp_queue = tq;
3608 TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
3609 }
3610}
3611
3612static uint16_t
3613bwn_pio_idx2base(struct bwn_mac *mac, int index)
3614{
3615 struct bwn_softc *sc = mac->mac_sc;
3616 static const uint16_t bases[] = {
3617 BWN_PIO_BASE0,
3618 BWN_PIO_BASE1,
3619 BWN_PIO_BASE2,
3620 BWN_PIO_BASE3,
3621 BWN_PIO_BASE4,
3622 BWN_PIO_BASE5,
3623 BWN_PIO_BASE6,
3624 BWN_PIO_BASE7,
3625 };
3626 static const uint16_t bases_rev11[] = {
3627 BWN_PIO11_BASE0,
3628 BWN_PIO11_BASE1,
3629 BWN_PIO11_BASE2,
3630 BWN_PIO11_BASE3,
3631 BWN_PIO11_BASE4,
3632 BWN_PIO11_BASE5,
3633 };
3634
3635 if (siba_get_revid(sc->sc_dev) >= 11) {
3636 if (index >= N(bases_rev11))
3637 device_printf(sc->sc_dev, "%s: warning\n", __func__);
3638 return (bases_rev11[index]);
3639 }
3640 if (index >= N(bases))
3641 device_printf(sc->sc_dev, "%s: warning\n", __func__);
3642 return (bases[index]);
3643}
3644
3645static void
3646bwn_pio_setupqueue_rx(struct bwn_mac *mac, struct bwn_pio_rxqueue *prq,
3647 int index)
3648{
3649 struct bwn_softc *sc = mac->mac_sc;
3650
3651 prq->prq_mac = mac;
3652 prq->prq_rev = siba_get_revid(sc->sc_dev);
3653 prq->prq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_RXQOFFSET(mac);
3654 bwn_dma_rxdirectfifo(mac, index, 1);
3655}
3656
3657static void
3658bwn_destroy_pioqueue_tx(struct bwn_pio_txqueue *tq)
3659{
3660 if (tq == NULL)
3661 return;
3662 bwn_pio_cancel_tx_packets(tq);
3663}
3664
3665static void
3666bwn_destroy_queue_tx(struct bwn_pio_txqueue *pio)
3667{
3668
3669 bwn_destroy_pioqueue_tx(pio);
3670}
3671
3672static uint16_t
3673bwn_pio_read_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3674 uint16_t offset)
3675{
3676
3677 return (BWN_READ_2(mac, tq->tq_base + offset));
3678}
3679
3680static void
3681bwn_dma_rxdirectfifo(struct bwn_mac *mac, int idx, uint8_t enable)
3682{
3683 uint32_t ctl;
3684 int type;
3685 uint16_t base;
3686
3687 type = bwn_dma_mask2type(bwn_dma_mask(mac));
3688 base = bwn_dma_base(type, idx);
3689 if (type == BWN_DMA_64BIT) {
3690 ctl = BWN_READ_4(mac, base + BWN_DMA64_RXCTL);
3691 ctl &= ~BWN_DMA64_RXDIRECTFIFO;
3692 if (enable)
3693 ctl |= BWN_DMA64_RXDIRECTFIFO;
3694 BWN_WRITE_4(mac, base + BWN_DMA64_RXCTL, ctl);
3695 } else {
3696 ctl = BWN_READ_4(mac, base + BWN_DMA32_RXCTL);
3697 ctl &= ~BWN_DMA32_RXDIRECTFIFO;
3698 if (enable)
3699 ctl |= BWN_DMA32_RXDIRECTFIFO;
3700 BWN_WRITE_4(mac, base + BWN_DMA32_RXCTL, ctl);
3701 }
3702}
3703
3704static uint64_t
3705bwn_dma_mask(struct bwn_mac *mac)
3706{
3707 uint32_t tmp;
3708 uint16_t base;
3709
3710 tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
3711 if (tmp & SIBA_TGSHIGH_DMA64)
3712 return (BWN_DMA_BIT_MASK(64));
3713 base = bwn_dma_base(0, 0);
3714 BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
3715 tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
3716 if (tmp & BWN_DMA32_TXADDREXT_MASK)
3717 return (BWN_DMA_BIT_MASK(32));
3718
3719 return (BWN_DMA_BIT_MASK(30));
3720}
3721
3722static int
3723bwn_dma_mask2type(uint64_t dmamask)
3724{
3725
3726 if (dmamask == BWN_DMA_BIT_MASK(30))
3727 return (BWN_DMA_30BIT);
3728 if (dmamask == BWN_DMA_BIT_MASK(32))
3729 return (BWN_DMA_32BIT);
3730 if (dmamask == BWN_DMA_BIT_MASK(64))
3731 return (BWN_DMA_64BIT);
3732 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3733 return (BWN_DMA_30BIT);
3734}
3735
3736static void
3737bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *tq)
3738{
3739 struct bwn_pio_txpkt *tp;
3740 unsigned int i;
3741
3742 for (i = 0; i < N(tq->tq_pkts); i++) {
3743 tp = &(tq->tq_pkts[i]);
3744 if (tp->tp_m) {
3745 m_freem(tp->tp_m);
3746 tp->tp_m = NULL;
3747 }
3748 }
3749}
3750
3751static uint16_t
3752bwn_dma_base(int type, int controller_idx)
3753{
3754 static const uint16_t map64[] = {
3755 BWN_DMA64_BASE0,
3756 BWN_DMA64_BASE1,
3757 BWN_DMA64_BASE2,
3758 BWN_DMA64_BASE3,
3759 BWN_DMA64_BASE4,
3760 BWN_DMA64_BASE5,
3761 };
3762 static const uint16_t map32[] = {
3763 BWN_DMA32_BASE0,
3764 BWN_DMA32_BASE1,
3765 BWN_DMA32_BASE2,
3766 BWN_DMA32_BASE3,
3767 BWN_DMA32_BASE4,
3768 BWN_DMA32_BASE5,
3769 };
3770
3771 if (type == BWN_DMA_64BIT) {
3772 KASSERT(controller_idx >= 0 && controller_idx < N(map64),
3773 ("%s:%d: fail", __func__, __LINE__));
3774 return (map64[controller_idx]);
3775 }
3776 KASSERT(controller_idx >= 0 && controller_idx < N(map32),
3777 ("%s:%d: fail", __func__, __LINE__));
3778 return (map32[controller_idx]);
3779}
3780
3781static void
3782bwn_dma_init(struct bwn_mac *mac)
3783{
3784 struct bwn_dma *dma = &mac->mac_method.dma;
3785
3786 /* setup TX DMA channels. */
3787 bwn_dma_setup(dma->wme[WME_AC_BK]);
3788 bwn_dma_setup(dma->wme[WME_AC_BE]);
3789 bwn_dma_setup(dma->wme[WME_AC_VI]);
3790 bwn_dma_setup(dma->wme[WME_AC_VO]);
3791 bwn_dma_setup(dma->mcast);
3792 /* setup RX DMA channel. */
3793 bwn_dma_setup(dma->rx);
3794}
3795
3796static struct bwn_dma_ring *
3797bwn_dma_ringsetup(struct bwn_mac *mac, int controller_index,
3798 int for_tx, int type)
3799{
3800 struct bwn_dma *dma = &mac->mac_method.dma;
3801 struct bwn_dma_ring *dr;
3802 struct bwn_dmadesc_generic *desc;
3803 struct bwn_dmadesc_meta *mt;
3804 struct bwn_softc *sc = mac->mac_sc;
3805 int error, i;
3806
3807 dr = malloc(sizeof(*dr), M_DEVBUF, M_NOWAIT | M_ZERO);
3808 if (dr == NULL)
3809 goto out;
3810 dr->dr_numslots = BWN_RXRING_SLOTS;
3811 if (for_tx)
3812 dr->dr_numslots = BWN_TXRING_SLOTS;
3813
3814 dr->dr_meta = malloc(dr->dr_numslots * sizeof(struct bwn_dmadesc_meta),
3815 M_DEVBUF, M_NOWAIT | M_ZERO);
3816 if (dr->dr_meta == NULL)
3817 goto fail0;
3818
3819 dr->dr_type = type;
3820 dr->dr_mac = mac;
3821 dr->dr_base = bwn_dma_base(type, controller_index);
3822 dr->dr_index = controller_index;
3823 if (type == BWN_DMA_64BIT) {
3824 dr->getdesc = bwn_dma_64_getdesc;
3825 dr->setdesc = bwn_dma_64_setdesc;
3826 dr->start_transfer = bwn_dma_64_start_transfer;
3827 dr->suspend = bwn_dma_64_suspend;
3828 dr->resume = bwn_dma_64_resume;
3829 dr->get_curslot = bwn_dma_64_get_curslot;
3830 dr->set_curslot = bwn_dma_64_set_curslot;
3831 } else {
3832 dr->getdesc = bwn_dma_32_getdesc;
3833 dr->setdesc = bwn_dma_32_setdesc;
3834 dr->start_transfer = bwn_dma_32_start_transfer;
3835 dr->suspend = bwn_dma_32_suspend;
3836 dr->resume = bwn_dma_32_resume;
3837 dr->get_curslot = bwn_dma_32_get_curslot;
3838 dr->set_curslot = bwn_dma_32_set_curslot;
3839 }
3840 if (for_tx) {
3841 dr->dr_tx = 1;
3842 dr->dr_curslot = -1;
3843 } else {
3844 if (dr->dr_index == 0) {
3845 dr->dr_rx_bufsize = BWN_DMA0_RX_BUFFERSIZE;
3846 dr->dr_frameoffset = BWN_DMA0_RX_FRAMEOFFSET;
3847 } else
3848 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3849 }
3850
3851 error = bwn_dma_allocringmemory(dr);
3852 if (error)
3853 goto fail2;
3854
3855 if (for_tx) {
3856 /*
3857 * Assumption: BWN_TXRING_SLOTS can be divided by
3858 * BWN_TX_SLOTS_PER_FRAME
3859 */
3860 KASSERT(BWN_TXRING_SLOTS % BWN_TX_SLOTS_PER_FRAME == 0,
3861 ("%s:%d: fail", __func__, __LINE__));
3862
3863 dr->dr_txhdr_cache =
3864 malloc((dr->dr_numslots / BWN_TX_SLOTS_PER_FRAME) *
3865 BWN_HDRSIZE(mac), M_DEVBUF, M_NOWAIT | M_ZERO);
3866 KASSERT(dr->dr_txhdr_cache != NULL,
3867 ("%s:%d: fail", __func__, __LINE__));
3868
3869 /*
3870 * Create TX ring DMA stuffs
3871 */
3872 error = bus_dma_tag_create(dma->parent_dtag,
3873 BWN_ALIGN, 0,
3874 BUS_SPACE_MAXADDR,
3875 BUS_SPACE_MAXADDR,
3876 NULL, NULL,
3877 BWN_HDRSIZE(mac),
3878 1,
3879 BUS_SPACE_MAXSIZE_32BIT,
3880 0,
3881 NULL, NULL,
3882 &dr->dr_txring_dtag);
3883 if (error) {
3884 device_printf(sc->sc_dev,
3885 "can't create TX ring DMA tag: TODO frees\n");
3886 goto fail1;
3887 }
3888
3889 for (i = 0; i < dr->dr_numslots; i += 2) {
3890 dr->getdesc(dr, i, &desc, &mt);
3891
3892 mt->mt_txtype = BWN_DMADESC_METATYPE_HEADER;
3893 mt->mt_m = NULL;
3894 mt->mt_ni = NULL;
3895 mt->mt_islast = 0;
3896 error = bus_dmamap_create(dr->dr_txring_dtag, 0,
3897 &mt->mt_dmap);
3898 if (error) {
3899 device_printf(sc->sc_dev,
3900 "can't create RX buf DMA map\n");
3901 goto fail1;
3902 }
3903
3904 dr->getdesc(dr, i + 1, &desc, &mt);
3905
3906 mt->mt_txtype = BWN_DMADESC_METATYPE_BODY;
3907 mt->mt_m = NULL;
3908 mt->mt_ni = NULL;
3909 mt->mt_islast = 1;
3910 error = bus_dmamap_create(dma->txbuf_dtag, 0,
3911 &mt->mt_dmap);
3912 if (error) {
3913 device_printf(sc->sc_dev,
3914 "can't create RX buf DMA map\n");
3915 goto fail1;
3916 }
3917 }
3918 } else {
3919 error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3920 &dr->dr_spare_dmap);
3921 if (error) {
3922 device_printf(sc->sc_dev,
3923 "can't create RX buf DMA map\n");
3924 goto out; /* XXX wrong! */
3925 }
3926
3927 for (i = 0; i < dr->dr_numslots; i++) {
3928 dr->getdesc(dr, i, &desc, &mt);
3929
3930 error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3931 &mt->mt_dmap);
3932 if (error) {
3933 device_printf(sc->sc_dev,
3934 "can't create RX buf DMA map\n");
3935 goto out; /* XXX wrong! */
3936 }
3937 error = bwn_dma_newbuf(dr, desc, mt, 1);
3938 if (error) {
3939 device_printf(sc->sc_dev,
3940 "failed to allocate RX buf\n");
3941 goto out; /* XXX wrong! */
3942 }
3943 }
3944
3945 bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
3946 BUS_DMASYNC_PREWRITE);
3947
3948 dr->dr_usedslot = dr->dr_numslots;
3949 }
3950
3951 out:
3952 return (dr);
3953
3954fail2:
3955 free(dr->dr_txhdr_cache, M_DEVBUF);
3956fail1:
3957 free(dr->dr_meta, M_DEVBUF);
3958fail0:
3959 free(dr, M_DEVBUF);
3960 return (NULL);
3961}
3962
3963static void
3964bwn_dma_ringfree(struct bwn_dma_ring **dr)
3965{
3966
3967 if (dr == NULL)
3968 return;
3969
3970 bwn_dma_free_descbufs(*dr);
3971 bwn_dma_free_ringmemory(*dr);
3972
3973 free((*dr)->dr_txhdr_cache, M_DEVBUF);
3974 free((*dr)->dr_meta, M_DEVBUF);
3975 free(*dr, M_DEVBUF);
3976
3977 *dr = NULL;
3978}
3979
3980static void
3981bwn_dma_32_getdesc(struct bwn_dma_ring *dr, int slot,
3982 struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
3983{
3984 struct bwn_dmadesc32 *desc;
3985
3986 *meta = &(dr->dr_meta[slot]);
3987 desc = dr->dr_ring_descbase;
3988 desc = &(desc[slot]);
3989
3990 *gdesc = (struct bwn_dmadesc_generic *)desc;
3991}
3992
3993static void
3994bwn_dma_32_setdesc(struct bwn_dma_ring *dr,
3995 struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
3996 int start, int end, int irq)
3997{
3998 struct bwn_dmadesc32 *descbase = dr->dr_ring_descbase;
3999 struct bwn_softc *sc = dr->dr_mac->mac_sc;
4000 uint32_t addr, addrext, ctl;
4001 int slot;
4002
4003 slot = (int)(&(desc->dma.dma32) - descbase);
4004 KASSERT(slot >= 0 && slot < dr->dr_numslots,
4005 ("%s:%d: fail", __func__, __LINE__));
4006
4007 addr = (uint32_t) (dmaaddr & ~SIBA_DMA_TRANSLATION_MASK);
4008 addrext = (uint32_t) (dmaaddr & SIBA_DMA_TRANSLATION_MASK) >> 30;
4009 addr |= siba_dma_translation(sc->sc_dev);
4010 ctl = bufsize & BWN_DMA32_DCTL_BYTECNT;
4011 if (slot == dr->dr_numslots - 1)
4012 ctl |= BWN_DMA32_DCTL_DTABLEEND;
4013 if (start)
4014 ctl |= BWN_DMA32_DCTL_FRAMESTART;
4015 if (end)
4016 ctl |= BWN_DMA32_DCTL_FRAMEEND;
4017 if (irq)
4018 ctl |= BWN_DMA32_DCTL_IRQ;
4019 ctl |= (addrext << BWN_DMA32_DCTL_ADDREXT_SHIFT)
4020 & BWN_DMA32_DCTL_ADDREXT_MASK;
4021
4022 desc->dma.dma32.control = htole32(ctl);
4023 desc->dma.dma32.address = htole32(addr);
4024}
4025
4026static void
4027bwn_dma_32_start_transfer(struct bwn_dma_ring *dr, int slot)
4028{
4029
4030 BWN_DMA_WRITE(dr, BWN_DMA32_TXINDEX,
4031 (uint32_t)(slot * sizeof(struct bwn_dmadesc32)));
4032}
4033
4034static void
4035bwn_dma_32_suspend(struct bwn_dma_ring *dr)
4036{
4037
4038 BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
4039 BWN_DMA_READ(dr, BWN_DMA32_TXCTL) | BWN_DMA32_TXSUSPEND);
4040}
4041
4042static void
4043bwn_dma_32_resume(struct bwn_dma_ring *dr)
4044{
4045
4046 BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
4047 BWN_DMA_READ(dr, BWN_DMA32_TXCTL) & ~BWN_DMA32_TXSUSPEND);
4048}
4049
4050static int
4051bwn_dma_32_get_curslot(struct bwn_dma_ring *dr)
4052{
4053 uint32_t val;
4054
4055 val = BWN_DMA_READ(dr, BWN_DMA32_RXSTATUS);
4056 val &= BWN_DMA32_RXDPTR;
4057
4058 return (val / sizeof(struct bwn_dmadesc32));
4059}
4060
4061static void
4062bwn_dma_32_set_curslot(struct bwn_dma_ring *dr, int slot)
4063{
4064
4065 BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX,
4066 (uint32_t) (slot * sizeof(struct bwn_dmadesc32)));
4067}
4068
4069static void
4070bwn_dma_64_getdesc(struct bwn_dma_ring *dr, int slot,
4071 struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
4072{
4073 struct bwn_dmadesc64 *desc;
4074
4075 *meta = &(dr->dr_meta[slot]);
4076 desc = dr->dr_ring_descbase;
4077 desc = &(desc[slot]);
4078
4079 *gdesc = (struct bwn_dmadesc_generic *)desc;
4080}
4081
4082static void
4083bwn_dma_64_setdesc(struct bwn_dma_ring *dr,
4084 struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
4085 int start, int end, int irq)
4086{
4087 struct bwn_dmadesc64 *descbase = dr->dr_ring_descbase;
4088 struct bwn_softc *sc = dr->dr_mac->mac_sc;
4089 int slot;
4090 uint32_t ctl0 = 0, ctl1 = 0;
4091 uint32_t addrlo, addrhi;
4092 uint32_t addrext;
4093
4094 slot = (int)(&(desc->dma.dma64) - descbase);
4095 KASSERT(slot >= 0 && slot < dr->dr_numslots,
4096 ("%s:%d: fail", __func__, __LINE__));
4097
4098 addrlo = (uint32_t) (dmaaddr & 0xffffffff);
4099 addrhi = (((uint64_t) dmaaddr >> 32) & ~SIBA_DMA_TRANSLATION_MASK);
4100 addrext = (((uint64_t) dmaaddr >> 32) & SIBA_DMA_TRANSLATION_MASK) >>
4101 30;
4102 addrhi |= (siba_dma_translation(sc->sc_dev) << 1);
4103 if (slot == dr->dr_numslots - 1)
4104 ctl0 |= BWN_DMA64_DCTL0_DTABLEEND;
4105 if (start)
4106 ctl0 |= BWN_DMA64_DCTL0_FRAMESTART;
4107 if (end)
4108 ctl0 |= BWN_DMA64_DCTL0_FRAMEEND;
4109 if (irq)
4110 ctl0 |= BWN_DMA64_DCTL0_IRQ;
4111 ctl1 |= bufsize & BWN_DMA64_DCTL1_BYTECNT;
4112 ctl1 |= (addrext << BWN_DMA64_DCTL1_ADDREXT_SHIFT)
4113 & BWN_DMA64_DCTL1_ADDREXT_MASK;
4114
4115 desc->dma.dma64.control0 = htole32(ctl0);
4116 desc->dma.dma64.control1 = htole32(ctl1);
4117 desc->dma.dma64.address_low = htole32(addrlo);
4118 desc->dma.dma64.address_high = htole32(addrhi);
4119}
4120
4121static void
4122bwn_dma_64_start_transfer(struct bwn_dma_ring *dr, int slot)
4123{
4124
4125 BWN_DMA_WRITE(dr, BWN_DMA64_TXINDEX,
4126 (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4127}
4128
4129static void
4130bwn_dma_64_suspend(struct bwn_dma_ring *dr)
4131{
4132
4133 BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
4134 BWN_DMA_READ(dr, BWN_DMA64_TXCTL) | BWN_DMA64_TXSUSPEND);
4135}
4136
4137static void
4138bwn_dma_64_resume(struct bwn_dma_ring *dr)
4139{
4140
4141 BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
4142 BWN_DMA_READ(dr, BWN_DMA64_TXCTL) & ~BWN_DMA64_TXSUSPEND);
4143}
4144
4145static int
4146bwn_dma_64_get_curslot(struct bwn_dma_ring *dr)
4147{
4148 uint32_t val;
4149
4150 val = BWN_DMA_READ(dr, BWN_DMA64_RXSTATUS);
4151 val &= BWN_DMA64_RXSTATDPTR;
4152
4153 return (val / sizeof(struct bwn_dmadesc64));
4154}
4155
4156static void
4157bwn_dma_64_set_curslot(struct bwn_dma_ring *dr, int slot)
4158{
4159
4160 BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX,
4161 (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4162}
4163
4164static int
4165bwn_dma_allocringmemory(struct bwn_dma_ring *dr)
4166{
4167 struct bwn_mac *mac = dr->dr_mac;
4168 struct bwn_dma *dma = &mac->mac_method.dma;
4169 struct bwn_softc *sc = mac->mac_sc;
4170 int error;
4171
4172 error = bus_dma_tag_create(dma->parent_dtag,
4173 BWN_ALIGN, 0,
4174 BUS_SPACE_MAXADDR,
4175 BUS_SPACE_MAXADDR,
4176 NULL, NULL,
4177 BWN_DMA_RINGMEMSIZE,
4178 1,
4179 BUS_SPACE_MAXSIZE_32BIT,
4180 0,
4181 NULL, NULL,
4182 &dr->dr_ring_dtag);
4183 if (error) {
4184 device_printf(sc->sc_dev,
4185 "can't create TX ring DMA tag: TODO frees\n");
4186 return (-1);
4187 }
4188
4189 error = bus_dmamem_alloc(dr->dr_ring_dtag,
4190 &dr->dr_ring_descbase, BUS_DMA_WAITOK | BUS_DMA_ZERO,
4191 &dr->dr_ring_dmap);
4192 if (error) {
4193 device_printf(sc->sc_dev,
4194 "can't allocate DMA mem: TODO frees\n");
4195 return (-1);
4196 }
4197 error = bus_dmamap_load(dr->dr_ring_dtag, dr->dr_ring_dmap,
4198 dr->dr_ring_descbase, BWN_DMA_RINGMEMSIZE,
4199 bwn_dma_ring_addr, &dr->dr_ring_dmabase, BUS_DMA_NOWAIT);
4200 if (error) {
4201 device_printf(sc->sc_dev,
4202 "can't load DMA mem: TODO free\n");
4203 return (-1);
4204 }
4205
4206 return (0);
4207}
4208
4209static void
4210bwn_dma_setup(struct bwn_dma_ring *dr)
4211{
4212 struct bwn_softc *sc = dr->dr_mac->mac_sc;
4213 uint64_t ring64;
4214 uint32_t addrext, ring32, value;
4215 uint32_t trans = siba_dma_translation(sc->sc_dev);
4216
4217 if (dr->dr_tx) {
4218 dr->dr_curslot = -1;
4219
4220 if (dr->dr_type == BWN_DMA_64BIT) {
4221 ring64 = (uint64_t)(dr->dr_ring_dmabase);
4222 addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK)
4223 >> 30;
4224 value = BWN_DMA64_TXENABLE;
4225 value |= (addrext << BWN_DMA64_TXADDREXT_SHIFT)
4226 & BWN_DMA64_TXADDREXT_MASK;
4227 BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL, value);
4228 BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO,
4229 (ring64 & 0xffffffff));
4230 BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI,
4231 ((ring64 >> 32) &
4232 ~SIBA_DMA_TRANSLATION_MASK) | (trans << 1));
4233 } else {
4234 ring32 = (uint32_t)(dr->dr_ring_dmabase);
4235 addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4236 value = BWN_DMA32_TXENABLE;
4237 value |= (addrext << BWN_DMA32_TXADDREXT_SHIFT)
4238 & BWN_DMA32_TXADDREXT_MASK;
4239 BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL, value);
4240 BWN_DMA_WRITE(dr, BWN_DMA32_TXRING,
4241 (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4242 }
4243 return;
4244 }
4245
4246 /*
4247 * set for RX
4248 */
4249 dr->dr_usedslot = dr->dr_numslots;
4250
4251 if (dr->dr_type == BWN_DMA_64BIT) {
4252 ring64 = (uint64_t)(dr->dr_ring_dmabase);
4253 addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK) >> 30;
4254 value = (dr->dr_frameoffset << BWN_DMA64_RXFROFF_SHIFT);
4255 value |= BWN_DMA64_RXENABLE;
4256 value |= (addrext << BWN_DMA64_RXADDREXT_SHIFT)
4257 & BWN_DMA64_RXADDREXT_MASK;
4258 BWN_DMA_WRITE(dr, BWN_DMA64_RXCTL, value);
4259 BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, (ring64 & 0xffffffff));
4260 BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI,
4261 ((ring64 >> 32) & ~SIBA_DMA_TRANSLATION_MASK)
4262 | (trans << 1));
4263 BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX, dr->dr_numslots *
4264 sizeof(struct bwn_dmadesc64));
4265 } else {
4266 ring32 = (uint32_t)(dr->dr_ring_dmabase);
4267 addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4268 value = (dr->dr_frameoffset << BWN_DMA32_RXFROFF_SHIFT);
4269 value |= BWN_DMA32_RXENABLE;
4270 value |= (addrext << BWN_DMA32_RXADDREXT_SHIFT)
4271 & BWN_DMA32_RXADDREXT_MASK;
4272 BWN_DMA_WRITE(dr, BWN_DMA32_RXCTL, value);
4273 BWN_DMA_WRITE(dr, BWN_DMA32_RXRING,
4274 (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4275 BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX, dr->dr_numslots *
4276 sizeof(struct bwn_dmadesc32));
4277 }
4278}
4279
4280static void
4281bwn_dma_free_ringmemory(struct bwn_dma_ring *dr)
4282{
4283
4284 bus_dmamap_unload(dr->dr_ring_dtag, dr->dr_ring_dmap);
4285 bus_dmamem_free(dr->dr_ring_dtag, dr->dr_ring_descbase,
4286 dr->dr_ring_dmap);
4287}
4288
4289static void
4290bwn_dma_cleanup(struct bwn_dma_ring *dr)
4291{
4292
4293 if (dr->dr_tx) {
4294 bwn_dma_tx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4295 if (dr->dr_type == BWN_DMA_64BIT) {
4296 BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO, 0);
4297 BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI, 0);
4298 } else
4299 BWN_DMA_WRITE(dr, BWN_DMA32_TXRING, 0);
4300 } else {
4301 bwn_dma_rx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4302 if (dr->dr_type == BWN_DMA_64BIT) {
4303 BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, 0);
4304 BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI, 0);
4305 } else
4306 BWN_DMA_WRITE(dr, BWN_DMA32_RXRING, 0);
4307 }
4308}
4309
4310static void
4311bwn_dma_free_descbufs(struct bwn_dma_ring *dr)
4312{
4313 struct bwn_dmadesc_generic *desc;
4314 struct bwn_dmadesc_meta *meta;
4315 struct bwn_mac *mac = dr->dr_mac;
4316 struct bwn_dma *dma = &mac->mac_method.dma;
4317 struct bwn_softc *sc = mac->mac_sc;
4318 int i;
4319
4320 if (!dr->dr_usedslot)
4321 return;
4322 for (i = 0; i < dr->dr_numslots; i++) {
4323 dr->getdesc(dr, i, &desc, &meta);
4324
4325 if (meta->mt_m == NULL) {
4326 if (!dr->dr_tx)
4327 device_printf(sc->sc_dev, "%s: not TX?\n",
4328 __func__);
4329 continue;
4330 }
4331 if (dr->dr_tx) {
4332 if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
4333 bus_dmamap_unload(dr->dr_txring_dtag,
4334 meta->mt_dmap);
4335 else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
4336 bus_dmamap_unload(dma->txbuf_dtag,
4337 meta->mt_dmap);
4338 } else
4339 bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
4340 bwn_dma_free_descbuf(dr, meta);
4341 }
4342}
4343
4344static int
4345bwn_dma_tx_reset(struct bwn_mac *mac, uint16_t base,
4346 int type)
4347{
4348 struct bwn_softc *sc = mac->mac_sc;
4349 uint32_t value;
4350 int i;
4351 uint16_t offset;
4352
4353 for (i = 0; i < 10; i++) {
4354 offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4355 BWN_DMA32_TXSTATUS;
4356 value = BWN_READ_4(mac, base + offset);
4357 if (type == BWN_DMA_64BIT) {
4358 value &= BWN_DMA64_TXSTAT;
4359 if (value == BWN_DMA64_TXSTAT_DISABLED ||
4360 value == BWN_DMA64_TXSTAT_IDLEWAIT ||
4361 value == BWN_DMA64_TXSTAT_STOPPED)
4362 break;
4363 } else {
4364 value &= BWN_DMA32_TXSTATE;
4365 if (value == BWN_DMA32_TXSTAT_DISABLED ||
4366 value == BWN_DMA32_TXSTAT_IDLEWAIT ||
4367 value == BWN_DMA32_TXSTAT_STOPPED)
4368 break;
4369 }
4370 DELAY(1000);
4371 }
4372 offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXCTL : BWN_DMA32_TXCTL;
4373 BWN_WRITE_4(mac, base + offset, 0);
4374 for (i = 0; i < 10; i++) {
4375 offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4376 BWN_DMA32_TXSTATUS;
4377 value = BWN_READ_4(mac, base + offset);
4378 if (type == BWN_DMA_64BIT) {
4379 value &= BWN_DMA64_TXSTAT;
4380 if (value == BWN_DMA64_TXSTAT_DISABLED) {
4381 i = -1;
4382 break;
4383 }
4384 } else {
4385 value &= BWN_DMA32_TXSTATE;
4386 if (value == BWN_DMA32_TXSTAT_DISABLED) {
4387 i = -1;
4388 break;
4389 }
4390 }
4391 DELAY(1000);
4392 }
4393 if (i != -1) {
4394 device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4395 return (ENODEV);
4396 }
4397 DELAY(1000);
4398
4399 return (0);
4400}
4401
4402static int
4403bwn_dma_rx_reset(struct bwn_mac *mac, uint16_t base,
4404 int type)
4405{
4406 struct bwn_softc *sc = mac->mac_sc;
4407 uint32_t value;
4408 int i;
4409 uint16_t offset;
4410
4411 offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXCTL : BWN_DMA32_RXCTL;
4412 BWN_WRITE_4(mac, base + offset, 0);
4413 for (i = 0; i < 10; i++) {
4414 offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXSTATUS :
4415 BWN_DMA32_RXSTATUS;
4416 value = BWN_READ_4(mac, base + offset);
4417 if (type == BWN_DMA_64BIT) {
4418 value &= BWN_DMA64_RXSTAT;
4419 if (value == BWN_DMA64_RXSTAT_DISABLED) {
4420 i = -1;
4421 break;
4422 }
4423 } else {
4424 value &= BWN_DMA32_RXSTATE;
4425 if (value == BWN_DMA32_RXSTAT_DISABLED) {
4426 i = -1;
4427 break;
4428 }
4429 }
4430 DELAY(1000);
4431 }
4432 if (i != -1) {
4433 device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4434 return (ENODEV);
4435 }
4436
4437 return (0);
4438}
4439
4440static void
4441bwn_dma_free_descbuf(struct bwn_dma_ring *dr,
4442 struct bwn_dmadesc_meta *meta)
4443{
4444
4445 if (meta->mt_m != NULL) {
4446 m_freem(meta->mt_m);
4447 meta->mt_m = NULL;
4448 }
4449 if (meta->mt_ni != NULL) {
4450 ieee80211_free_node(meta->mt_ni);
4451 meta->mt_ni = NULL;
4452 }
4453}
4454
4455static void
4456bwn_dma_set_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4457{
4458 struct bwn_rxhdr4 *rxhdr;
4459 unsigned char *frame;
4460
4461 rxhdr = mtod(m, struct bwn_rxhdr4 *);
4462 rxhdr->frame_len = 0;
4463
4464 KASSERT(dr->dr_rx_bufsize >= dr->dr_frameoffset +
4465 sizeof(struct bwn_plcp6) + 2,
4466 ("%s:%d: fail", __func__, __LINE__));
4467 frame = mtod(m, char *) + dr->dr_frameoffset;
4468 memset(frame, 0xff, sizeof(struct bwn_plcp6) + 2 /* padding */);
4469}
4470
4471static uint8_t
4472bwn_dma_check_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4473{
4474 unsigned char *f = mtod(m, char *) + dr->dr_frameoffset;
4475
4476 return ((f[0] & f[1] & f[2] & f[3] & f[4] & f[5] & f[6] & f[7])
4477 == 0xff);
4478}
4479
4480static void
4481bwn_wme_init(struct bwn_mac *mac)
4482{
4483
4484 bwn_wme_load(mac);
4485
4486 /* enable WME support. */
4487 bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_EDCF);
4488 BWN_WRITE_2(mac, BWN_IFSCTL, BWN_READ_2(mac, BWN_IFSCTL) |
4489 BWN_IFSCTL_USE_EDCF);
4490}
4491
4492static void
4493bwn_spu_setdelay(struct bwn_mac *mac, int idle)
4494{
4495 struct bwn_softc *sc = mac->mac_sc;
4496 struct ieee80211com *ic = sc->sc_ifp->if_l2com;
4497 uint16_t delay; /* microsec */
4498
4499 delay = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 3700 : 1050;
4500 if (ic->ic_opmode == IEEE80211_M_IBSS || idle)
4501 delay = 500;
4502 if ((mac->mac_phy.rf_ver == 0x2050) && (mac->mac_phy.rf_rev == 8))
4503 delay = max(delay, (uint16_t)2400);
4504
4505 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SPU_WAKEUP, delay);
4506}
4507
4508static void
4509bwn_bt_enable(struct bwn_mac *mac)
4510{
4511 struct bwn_softc *sc = mac->mac_sc;
4512 uint64_t hf;
4513
4514 if (bwn_bluetooth == 0)
4515 return;
4516 if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCOEXIST) == 0)
4517 return;
4518 if (mac->mac_phy.type != BWN_PHYTYPE_B && !mac->mac_phy.gmode)
4519 return;
4520
4521 hf = bwn_hf_read(mac);
4522 if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCMOD)
4523 hf |= BWN_HF_BT_COEXISTALT;
4524 else
4525 hf |= BWN_HF_BT_COEXIST;
4526 bwn_hf_write(mac, hf);
4527}
4528
4529static void
4530bwn_set_macaddr(struct bwn_mac *mac)
4531{
4532
4533 bwn_mac_write_bssid(mac);
4534 bwn_mac_setfilter(mac, BWN_MACFILTER_SELF, mac->mac_sc->sc_macaddr);
4535}
4536
4537static void
4538bwn_clear_keys(struct bwn_mac *mac)
4539{
4540 int i;
4541
4542 for (i = 0; i < mac->mac_max_nr_keys; i++) {
4543 KASSERT(i >= 0 && i < mac->mac_max_nr_keys,
4544 ("%s:%d: fail", __func__, __LINE__));
4545
4546 bwn_key_dowrite(mac, i, BWN_SEC_ALGO_NONE,
4547 NULL, BWN_SEC_KEYSIZE, NULL);
4548 if ((i <= 3) && !BWN_SEC_NEWAPI(mac)) {
4549 bwn_key_dowrite(mac, i + 4, BWN_SEC_ALGO_NONE,
4550 NULL, BWN_SEC_KEYSIZE, NULL);
4551 }
4552 mac->mac_key[i].keyconf = NULL;
4553 }
4554}
4555
4556static void
4557bwn_crypt_init(struct bwn_mac *mac)
4558{
4559 struct bwn_softc *sc = mac->mac_sc;
4560
4561 mac->mac_max_nr_keys = (siba_get_revid(sc->sc_dev) >= 5) ? 58 : 20;
4562 KASSERT(mac->mac_max_nr_keys <= N(mac->mac_key),
4563 ("%s:%d: fail", __func__, __LINE__));
4564 mac->mac_ktp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_KEY_TABLEP);
4565 mac->mac_ktp *= 2;
4566 if (siba_get_revid(sc->sc_dev) >= 5)
4567 BWN_WRITE_2(mac, BWN_RCMTA_COUNT, mac->mac_max_nr_keys - 8);
4568 bwn_clear_keys(mac);
4569}
4570
4571static void
4572bwn_chip_exit(struct bwn_mac *mac)
4573{
4574 struct bwn_softc *sc = mac->mac_sc;
4575
4576 bwn_phy_exit(mac);
4577 siba_gpio_set(sc->sc_dev, 0);
4578}
4579
4580static int
4581bwn_fw_fillinfo(struct bwn_mac *mac)
4582{
4583 int error;
4584
4585 error = bwn_fw_gets(mac, BWN_FWTYPE_DEFAULT);
4586 if (error == 0)
4587 return (0);
4588 error = bwn_fw_gets(mac, BWN_FWTYPE_OPENSOURCE);
4589 if (error == 0)
4590 return (0);
4591 return (error);
4592}
4593
4594static int
4595bwn_gpio_init(struct bwn_mac *mac)
4596{
4597 struct bwn_softc *sc = mac->mac_sc;
4598 uint32_t mask = 0x1f, set = 0xf, value;
4599
4600 BWN_WRITE_4(mac, BWN_MACCTL,
4601 BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GPOUT_MASK);
4602 BWN_WRITE_2(mac, BWN_GPIO_MASK,
4603 BWN_READ_2(mac, BWN_GPIO_MASK) | 0x000f);
4604
4605 if (siba_get_chipid(sc->sc_dev) == 0x4301) {
4606 mask |= 0x0060;
4607 set |= 0x0060;
4608 }
4609 if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL) {
4610 BWN_WRITE_2(mac, BWN_GPIO_MASK,
4611 BWN_READ_2(mac, BWN_GPIO_MASK) | 0x0200);
4612 mask |= 0x0200;
4613 set |= 0x0200;
4614 }
4615 if (siba_get_revid(sc->sc_dev) >= 2)
4616 mask |= 0x0010;
4617
4618 value = siba_gpio_get(sc->sc_dev);
4619 if (value == -1)
4620 return (0);
4621 siba_gpio_set(sc->sc_dev, (value & mask) | set);
4622
4623 return (0);
4624}
4625
4626static int
4627bwn_fw_loadinitvals(struct bwn_mac *mac)
4628{
4629#define GETFWOFFSET(fwp, offset) \
4630 ((const struct bwn_fwinitvals *)((const char *)fwp.fw->data + offset))
4631 const size_t hdr_len = sizeof(struct bwn_fwhdr);
4632 const struct bwn_fwhdr *hdr;
4633 struct bwn_fw *fw = &mac->mac_fw;
4634 int error;
4635
4636 hdr = (const struct bwn_fwhdr *)(fw->initvals.fw->data);
4637 error = bwn_fwinitvals_write(mac, GETFWOFFSET(fw->initvals, hdr_len),
4638 be32toh(hdr->size), fw->initvals.fw->datasize - hdr_len);
4639 if (error)
4640 return (error);
4641 if (fw->initvals_band.fw) {
4642 hdr = (const struct bwn_fwhdr *)(fw->initvals_band.fw->data);
4643 error = bwn_fwinitvals_write(mac,
4644 GETFWOFFSET(fw->initvals_band, hdr_len),
4645 be32toh(hdr->size),
4646 fw->initvals_band.fw->datasize - hdr_len);
4647 }
4648 return (error);
4649#undef GETFWOFFSET
4650}
4651
4652static int
4653bwn_phy_init(struct bwn_mac *mac)
4654{
4655 struct bwn_softc *sc = mac->mac_sc;
4656 int error;
4657
4658 mac->mac_phy.chan = mac->mac_phy.get_default_chan(mac);
4659 mac->mac_phy.rf_onoff(mac, 1);
4660 error = mac->mac_phy.init(mac);
4661 if (error) {
4662 device_printf(sc->sc_dev, "PHY init failed\n");
4663 goto fail0;
4664 }
4665 error = bwn_switch_channel(mac,
4666 mac->mac_phy.get_default_chan(mac));
4667 if (error) {
4668 device_printf(sc->sc_dev,
4669 "failed to switch default channel\n");
4670 goto fail1;
4671 }
4672 return (0);
4673fail1:
4674 if (mac->mac_phy.exit)
4675 mac->mac_phy.exit(mac);
4676fail0:
4677 mac->mac_phy.rf_onoff(mac, 0);
4678
4679 return (error);
4680}
4681
4682static void
4683bwn_set_txantenna(struct bwn_mac *mac, int antenna)
4684{
4685 uint16_t ant;
4686 uint16_t tmp;
4687
4688 ant = bwn_ant2phy(antenna);
4689
4690 /* For ACK/CTS */
4691 tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL);
4692 tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4693 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, tmp);
4694 /* For Probe Resposes */
4695 tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL);
4696 tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4697 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, tmp);
4698}
4699
4700static void
4701bwn_set_opmode(struct bwn_mac *mac)
4702{
4703 struct bwn_softc *sc = mac->mac_sc;
4704 struct ifnet *ifp = sc->sc_ifp;
4705 struct ieee80211com *ic = ifp->if_l2com;
4706 uint32_t ctl;
4707 uint16_t cfp_pretbtt;
4708
4709 ctl = BWN_READ_4(mac, BWN_MACCTL);
4710 ctl &= ~(BWN_MACCTL_HOSTAP | BWN_MACCTL_PASS_CTL |
4711 BWN_MACCTL_PASS_BADPLCP | BWN_MACCTL_PASS_BADFCS |
4712 BWN_MACCTL_PROMISC | BWN_MACCTL_BEACON_PROMISC);
4713 ctl |= BWN_MACCTL_STA;
4714
4715 if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
4716 ic->ic_opmode == IEEE80211_M_MBSS)
4717 ctl |= BWN_MACCTL_HOSTAP;
4718 else if (ic->ic_opmode == IEEE80211_M_IBSS)
4719 ctl &= ~BWN_MACCTL_STA;
4720 ctl |= sc->sc_filters;
4721
4722 if (siba_get_revid(sc->sc_dev) <= 4)
4723 ctl |= BWN_MACCTL_PROMISC;
4724
4725 BWN_WRITE_4(mac, BWN_MACCTL, ctl);
4726
4727 cfp_pretbtt = 2;
4728 if ((ctl & BWN_MACCTL_STA) && !(ctl & BWN_MACCTL_HOSTAP)) {
4729 if (siba_get_chipid(sc->sc_dev) == 0x4306 &&
4730 siba_get_chiprev(sc->sc_dev) == 3)
4731 cfp_pretbtt = 100;
4732 else
4733 cfp_pretbtt = 50;
4734 }
4735 BWN_WRITE_2(mac, 0x612, cfp_pretbtt);
4736}
4737
4738static int
4739bwn_dma_gettype(struct bwn_mac *mac)
4740{
4741 uint32_t tmp;
4742 uint16_t base;
4743
4744 tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
4745 if (tmp & SIBA_TGSHIGH_DMA64)
4746 return (BWN_DMA_64BIT);
4747 base = bwn_dma_base(0, 0);
4748 BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
4749 tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
4750 if (tmp & BWN_DMA32_TXADDREXT_MASK)
4751 return (BWN_DMA_32BIT);
4752
4753 return (BWN_DMA_30BIT);
4754}
4755
4756static void
4757bwn_dma_ring_addr(void *arg, bus_dma_segment_t *seg, int nseg, int error)
4758{
4759 if (!error) {
4760 KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
4761 *((bus_addr_t *)arg) = seg->ds_addr;
4762 }
4763}
4764
4765static void
4766bwn_phy_g_init_sub(struct bwn_mac *mac)
4767{
4768 struct bwn_phy *phy = &mac->mac_phy;
4769 struct bwn_phy_g *pg = &phy->phy_g;
4770 struct bwn_softc *sc = mac->mac_sc;
4771 uint16_t i, tmp;
4772
4773 if (phy->rev == 1)
4774 bwn_phy_init_b5(mac);
4775 else
4776 bwn_phy_init_b6(mac);
4777
4778 if (phy->rev >= 2 || phy->gmode)
4779 bwn_phy_init_a(mac);
4780
4781 if (phy->rev >= 2) {
4782 BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, 0);
4783 BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, 0);
4784 }
4785 if (phy->rev == 2) {
4786 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
4787 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4788 }
4789 if (phy->rev > 5) {
4790 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x400);
4791 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4792 }
4793 if (phy->gmode || phy->rev >= 2) {
4794 tmp = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
4795 tmp &= BWN_PHYVER_VERSION;
4796 if (tmp == 3 || tmp == 5) {
4797 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc2), 0x1816);
4798 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc3), 0x8006);
4799 }
4800 if (tmp == 5) {
4801 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xcc), 0x00ff,
4802 0x1f00);
4803 }
4804 }
4805 if ((phy->rev <= 2 && phy->gmode) || phy->rev >= 2)
4806 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x7e), 0x78);
4807 if (phy->rf_rev == 8) {
4808 BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x80);
4809 BWN_PHY_SET(mac, BWN_PHY_OFDM(0x3e), 0x4);
4810 }
4811 if (BWN_HAS_LOOPBACK(phy))
4812 bwn_loopback_calcgain(mac);
4813
4814 if (phy->rf_rev != 8) {
4815 if (pg->pg_initval == 0xffff)
4816 pg->pg_initval = bwn_rf_init_bcm2050(mac);
4817 else
4818 BWN_RF_WRITE(mac, 0x0078, pg->pg_initval);
4819 }
4820 bwn_lo_g_init(mac);
4821 if (BWN_HAS_TXMAG(phy)) {
4822 BWN_RF_WRITE(mac, 0x52,
4823 (BWN_RF_READ(mac, 0x52) & 0xff00)
4824 | pg->pg_loctl.tx_bias |
4825 pg->pg_loctl.tx_magn);
4826 } else {
4827 BWN_RF_SETMASK(mac, 0x52, 0xfff0, pg->pg_loctl.tx_bias);
4828 }
4829 if (phy->rev >= 6) {
4830 BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x36), 0x0fff,
4831 (pg->pg_loctl.tx_bias << 12));
4832 }
4833 if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
4834 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8075);
4835 else
4836 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x807f);
4837 if (phy->rev < 2)
4838 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x101);
4839 else
4840 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x202);
4841 if (phy->gmode || phy->rev >= 2) {
4842 bwn_lo_g_adjust(mac);
4843 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
4844 }
4845
4846 if (!(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI)) {
4847 for (i = 0; i < 64; i++) {
4848 BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, i);
4849 BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_DATA,
4850 (uint16_t)MIN(MAX(bwn_nrssi_read(mac, i) - 0xffff,
4851 -32), 31));
4852 }
4853 bwn_nrssi_threshold(mac);
4854 } else if (phy->gmode || phy->rev >= 2) {
4855 if (pg->pg_nrssi[0] == -1000) {
4856 KASSERT(pg->pg_nrssi[1] == -1000,
4857 ("%s:%d: fail", __func__, __LINE__));
4858 bwn_nrssi_slope_11g(mac);
4859 } else
4860 bwn_nrssi_threshold(mac);
4861 }
4862 if (phy->rf_rev == 8)
4863 BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x05), 0x3230);
4864 bwn_phy_hwpctl_init(mac);
4865 if ((siba_get_chipid(sc->sc_dev) == 0x4306
4866 && siba_get_chippkg(sc->sc_dev) == 2) || 0) {
4867 BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0xbfff);
4868 BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xc3), 0x7fff);
4869 }
4870}
4871
4872static uint8_t
4873bwn_has_hwpctl(struct bwn_mac *mac)
4874{
4875
4876 if (mac->mac_phy.hwpctl == 0 || mac->mac_phy.use_hwpctl == NULL)
4877 return (0);
4878 return (mac->mac_phy.use_hwpctl(mac));
4879}
4880
4881static void
4882bwn_phy_init_b5(struct bwn_mac *mac)
4883{
4884 struct bwn_phy *phy = &mac->mac_phy;
4885 struct bwn_phy_g *pg = &phy->phy_g;
4886 struct bwn_softc *sc = mac->mac_sc;
4887 uint16_t offset, value;
4888 uint8_t old_channel;
4889
4890 if (phy->analog == 1)
4891 BWN_RF_SET(mac, 0x007a, 0x0050);
4892 if ((siba_get_pci_subvendor(sc->sc_dev) != SIBA_BOARDVENDOR_BCM) &&
4893 (siba_get_pci_subdevice(sc->sc_dev) != SIBA_BOARD_BU4306)) {
4894 value = 0x2120;
4895 for (offset = 0x00a8; offset < 0x00c7; offset++) {
4896 BWN_PHY_WRITE(mac, offset, value);
4897 value += 0x202;
4898 }
4899 }
4900 BWN_PHY_SETMASK(mac, 0x0035, 0xf0ff, 0x0700);
4901 if (phy->rf_ver == 0x2050)
4902 BWN_PHY_WRITE(mac, 0x0038, 0x0667);
4903
4904 if (phy->gmode || phy->rev >= 2) {
4905 if (phy->rf_ver == 0x2050) {
4906 BWN_RF_SET(mac, 0x007a, 0x0020);
4907 BWN_RF_SET(mac, 0x0051, 0x0004);
4908 }
4909 BWN_WRITE_2(mac, BWN_PHY_RADIO, 0x0000);
4910
4911 BWN_PHY_SET(mac, 0x0802, 0x0100);
4912 BWN_PHY_SET(mac, 0x042b, 0x2000);
4913
4914 BWN_PHY_WRITE(mac, 0x001c, 0x186a);
4915
4916 BWN_PHY_SETMASK(mac, 0x0013, 0x00ff, 0x1900);
4917 BWN_PHY_SETMASK(mac, 0x0035, 0xffc0, 0x0064);
4918 BWN_PHY_SETMASK(mac, 0x005d, 0xff80, 0x000a);
4919 }
4920
4921 if (mac->mac_flags & BWN_MAC_FLAG_BADFRAME_PREEMP)
4922 BWN_PHY_SET(mac, BWN_PHY_RADIO_BITFIELD, (1 << 11));
4923
4924 if (phy->analog == 1) {
4925 BWN_PHY_WRITE(mac, 0x0026, 0xce00);
4926 BWN_PHY_WRITE(mac, 0x0021, 0x3763);
4927 BWN_PHY_WRITE(mac, 0x0022, 0x1bc3);
4928 BWN_PHY_WRITE(mac, 0x0023, 0x06f9);
4929 BWN_PHY_WRITE(mac, 0x0024, 0x037e);
4930 } else
4931 BWN_PHY_WRITE(mac, 0x0026, 0xcc00);
4932 BWN_PHY_WRITE(mac, 0x0030, 0x00c6);
4933 BWN_WRITE_2(mac, 0x03ec, 0x3f22);
4934
4935 if (phy->analog == 1)
4936 BWN_PHY_WRITE(mac, 0x0020, 0x3e1c);
4937 else
4938 BWN_PHY_WRITE(mac, 0x0020, 0x301c);
4939
4940 if (phy->analog == 0)
4941 BWN_WRITE_2(mac, 0x03e4, 0x3000);
4942
4943 old_channel = phy->chan;
4944 bwn_phy_g_switch_chan(mac, 7, 0);
4945
4946 if (phy->rf_ver != 0x2050) {
4947 BWN_RF_WRITE(mac, 0x0075, 0x0080);
4948 BWN_RF_WRITE(mac, 0x0079, 0x0081);
4949 }
4950
4951 BWN_RF_WRITE(mac, 0x0050, 0x0020);
4952 BWN_RF_WRITE(mac, 0x0050, 0x0023);
4953
4954 if (phy->rf_ver == 0x2050) {
4955 BWN_RF_WRITE(mac, 0x0050, 0x0020);
4956 BWN_RF_WRITE(mac, 0x005a, 0x0070);
4957 }
4958
4959 BWN_RF_WRITE(mac, 0x005b, 0x007b);
4960 BWN_RF_WRITE(mac, 0x005c, 0x00b0);
4961 BWN_RF_SET(mac, 0x007a, 0x0007);
4962
4963 bwn_phy_g_switch_chan(mac, old_channel, 0);
4964 BWN_PHY_WRITE(mac, 0x0014, 0x0080);
4965 BWN_PHY_WRITE(mac, 0x0032, 0x00ca);
4966 BWN_PHY_WRITE(mac, 0x002a, 0x88a3);
4967
4968 bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
4969 pg->pg_txctl);
4970
4971 if (phy->rf_ver == 0x2050)
4972 BWN_RF_WRITE(mac, 0x005d, 0x000d);
4973
4974 BWN_WRITE_2(mac, 0x03e4, (BWN_READ_2(mac, 0x03e4) & 0xffc0) | 0x0004);
4975}
4976
4977static void
4978bwn_loopback_calcgain(struct bwn_mac *mac)
4979{
4980 struct bwn_phy *phy = &mac->mac_phy;
4981 struct bwn_phy_g *pg = &phy->phy_g;
4982 struct bwn_softc *sc = mac->mac_sc;
4983 uint16_t backup_phy[16] = { 0 };
4984 uint16_t backup_radio[3];
4985 uint16_t backup_bband;
4986 uint16_t i, j, loop_i_max;
4987 uint16_t trsw_rx;
4988 uint16_t loop1_outer_done, loop1_inner_done;
4989
4990 backup_phy[0] = BWN_PHY_READ(mac, BWN_PHY_CRS0);
4991 backup_phy[1] = BWN_PHY_READ(mac, BWN_PHY_CCKBBANDCFG);
4992 backup_phy[2] = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
4993 backup_phy[3] = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
4994 if (phy->rev != 1) {
4995 backup_phy[4] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
4996 backup_phy[5] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
4997 }
4998 backup_phy[6] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
4999 backup_phy[7] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
5000 backup_phy[8] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
5001 backup_phy[9] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x0a));
5002 backup_phy[10] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x03));
5003 backup_phy[11] = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
5004 backup_phy[12] = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
5005 backup_phy[13] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2b));
5006 backup_phy[14] = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
5007 backup_phy[15] = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5008 backup_bband = pg->pg_bbatt.att;
5009 backup_radio[0] = BWN_RF_READ(mac, 0x52);
5010 backup_radio[1] = BWN_RF_READ(mac, 0x43);
5011 backup_radio[2] = BWN_RF_READ(mac, 0x7a);
5012
5013 BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x3fff);
5014 BWN_PHY_SET(mac, BWN_PHY_CCKBBANDCFG, 0x8000);
5015 BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0002);
5016 BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffd);
5017 BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0001);
5018 BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffe);
5019 if (phy->rev != 1) {
5020 BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0001);
5021 BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffe);
5022 BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0002);
5023 BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffd);
5024 }
5025 BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x000c);
5026 BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x000c);
5027 BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0030);
5028 BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xffcf, 0x10);
5029
5030 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0780);
5031 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5032 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5033
5034 BWN_PHY_SET(mac, BWN_PHY_CCK(0x0a), 0x2000);
5035 if (phy->rev != 1) {
5036 BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0004);
5037 BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffb);
5038 }
5039 BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xff9f, 0x40);
5040
5041 if (phy->rf_rev == 8)
5042 BWN_RF_WRITE(mac, 0x43, 0x000f);
5043 else {
5044 BWN_RF_WRITE(mac, 0x52, 0);
5045 BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x9);
5046 }
5047 bwn_phy_g_set_bbatt(mac, 11);
5048
5049 if (phy->rev >= 3)
5050 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
5051 else
5052 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
5053 BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
5054
5055 BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xffc0, 0x01);
5056 BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xc0ff, 0x800);
5057
5058 BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0100);
5059 BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xcfff);
5060
5061 if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA) {
5062 if (phy->rev >= 7) {
5063 BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0800);
5064 BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x8000);
5065 }
5066 }
5067 BWN_RF_MASK(mac, 0x7a, 0x00f7);
5068
5069 j = 0;
5070 loop_i_max = (phy->rf_rev == 8) ? 15 : 9;
5071 for (i = 0; i < loop_i_max; i++) {
5072 for (j = 0; j < 16; j++) {
5073 BWN_RF_WRITE(mac, 0x43, i);
5074 BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff,
5075 (j << 8));
5076 BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
5077 BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
5078 DELAY(20);
5079 if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
5080 goto done0;
5081 }
5082 }
5083done0:
5084 loop1_outer_done = i;
5085 loop1_inner_done = j;
5086 if (j >= 8) {
5087 BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x30);
5088 trsw_rx = 0x1b;
5089 for (j = j - 8; j < 16; j++) {
5090 BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff, j << 8);
5091 BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
5092 BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
5093 DELAY(20);
5094 trsw_rx -= 3;
5095 if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
5096 goto done1;
5097 }
5098 } else
5099 trsw_rx = 0x18;
5100done1:
5101
5102 if (phy->rev != 1) {
5103 BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, backup_phy[4]);
5104 BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, backup_phy[5]);
5105 }
5106 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), backup_phy[6]);
5107 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), backup_phy[7]);
5108 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), backup_phy[8]);
5109 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x0a), backup_phy[9]);
5110 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x03), backup_phy[10]);
5111 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, backup_phy[11]);
5112 BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, backup_phy[12]);
5113 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), backup_phy[13]);
5114 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, backup_phy[14]);
5115
5116 bwn_phy_g_set_bbatt(mac, backup_bband);
5117
5118 BWN_RF_WRITE(mac, 0x52, backup_radio[0]);
5119 BWN_RF_WRITE(mac, 0x43, backup_radio[1]);
5120 BWN_RF_WRITE(mac, 0x7a, backup_radio[2]);
5121
5122 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2] | 0x0003);
5123 DELAY(10);
5124 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2]);
5125 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, backup_phy[3]);
5126 BWN_PHY_WRITE(mac, BWN_PHY_CRS0, backup_phy[0]);
5127 BWN_PHY_WRITE(mac, BWN_PHY_CCKBBANDCFG, backup_phy[1]);
5128
5129 pg->pg_max_lb_gain =
5130 ((loop1_inner_done * 6) - (loop1_outer_done * 4)) - 11;
5131 pg->pg_trsw_rx_gain = trsw_rx * 2;
5132}
5133
5134static uint16_t
5135bwn_rf_init_bcm2050(struct bwn_mac *mac)
5136{
5137 struct bwn_phy *phy = &mac->mac_phy;
5138 uint32_t tmp1 = 0, tmp2 = 0;
5139 uint16_t rcc, i, j, pgactl, cck0, cck1, cck2, cck3, rfover, rfoverval,
5140 analogover, analogoverval, crs0, classctl, lomask, loctl, syncctl,
5141 radio0, radio1, radio2, reg0, reg1, reg2, radio78, reg, index;
5142 static const uint8_t rcc_table[] = {
5143 0x02, 0x03, 0x01, 0x0f,
5144 0x06, 0x07, 0x05, 0x0f,
5145 0x0a, 0x0b, 0x09, 0x0f,
5146 0x0e, 0x0f, 0x0d, 0x0f,
5147 };
5148
5149 loctl = lomask = reg0 = classctl = crs0 = analogoverval = analogover =
5150 rfoverval = rfover = cck3 = 0;
5151 radio0 = BWN_RF_READ(mac, 0x43);
5152 radio1 = BWN_RF_READ(mac, 0x51);
5153 radio2 = BWN_RF_READ(mac, 0x52);
5154 pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
5155 cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
5156 cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
5157 cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
5158
5159 if (phy->type == BWN_PHYTYPE_B) {
5160 cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
5161 reg0 = BWN_READ_2(mac, 0x3ec);
5162
5163 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0xff);
5164 BWN_WRITE_2(mac, 0x3ec, 0x3f3f);
5165 } else if (phy->gmode || phy->rev >= 2) {
5166 rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
5167 rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
5168 analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
5169 analogoverval = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
5170 crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
5171 classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
5172
5173 BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
5174 BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
5175 BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
5176 BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
5177 if (BWN_HAS_LOOPBACK(phy)) {
5178 lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
5179 loctl = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
5180 if (phy->rev >= 3)
5181 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
5182 else
5183 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
5184 BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
5185 }
5186
5187 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5188 bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5189 BWN_LPD(0, 1, 1)));
5190 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
5191 bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVER, 0));
5192 }
5193 BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2) | 0x8000);
5194
5195 syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
5196 BWN_PHY_MASK(mac, BWN_PHY_SYNCCTL, 0xff7f);
5197 reg1 = BWN_READ_2(mac, 0x3e6);
5198 reg2 = BWN_READ_2(mac, 0x3f4);
5199
5200 if (phy->analog == 0)
5201 BWN_WRITE_2(mac, 0x03e6, 0x0122);
5202 else {
5203 if (phy->analog >= 2)
5204 BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xffbf, 0x40);
5205 BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
5206 (BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000));
5207 }
5208
5209 reg = BWN_RF_READ(mac, 0x60);
5210 index = (reg & 0x001e) >> 1;
5211 rcc = (((rcc_table[index] << 1) | (reg & 0x0001)) | 0x0020);
5212
5213 if (phy->type == BWN_PHYTYPE_B)
5214 BWN_RF_WRITE(mac, 0x78, 0x26);
5215 if (phy->gmode || phy->rev >= 2) {
5216 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5217 bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5218 BWN_LPD(0, 1, 1)));
5219 }
5220 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfaf);
5221 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1403);
5222 if (phy->gmode || phy->rev >= 2) {
5223 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5224 bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5225 BWN_LPD(0, 0, 1)));
5226 }
5227 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfa0);
5228 BWN_RF_SET(mac, 0x51, 0x0004);
5229 if (phy->rf_rev == 8)
5230 BWN_RF_WRITE(mac, 0x43, 0x1f);
5231 else {
5232 BWN_RF_WRITE(mac, 0x52, 0);
5233 BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x0009);
5234 }
5235 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5236
5237 for (i = 0; i < 16; i++) {
5238 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0480);
5239 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5240 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5241 if (phy->gmode || phy->rev >= 2) {
5242 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5243 bwn_rf_2050_rfoverval(mac,
5244 BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5245 }
5246 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5247 DELAY(10);
5248 if (phy->gmode || phy->rev >= 2) {
5249 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5250 bwn_rf_2050_rfoverval(mac,
5251 BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5252 }
5253 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5254 DELAY(10);
5255 if (phy->gmode || phy->rev >= 2) {
5256 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5257 bwn_rf_2050_rfoverval(mac,
5258 BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5259 }
5260 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5261 DELAY(20);
5262 tmp1 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5263 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5264 if (phy->gmode || phy->rev >= 2) {
5265 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5266 bwn_rf_2050_rfoverval(mac,
5267 BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5268 }
5269 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5270 }
5271 DELAY(10);
5272
5273 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5274 tmp1++;
5275 tmp1 >>= 9;
5276
5277 for (i = 0; i < 16; i++) {
5278 radio78 = (BWN_BITREV4(i) << 1) | 0x0020;
5279 BWN_RF_WRITE(mac, 0x78, radio78);
5280 DELAY(10);
5281 for (j = 0; j < 16; j++) {
5282 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0d80);
5283 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5284 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5285 if (phy->gmode || phy->rev >= 2) {
5286 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5287 bwn_rf_2050_rfoverval(mac,
5288 BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5289 }
5290 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5291 DELAY(10);
5292 if (phy->gmode || phy->rev >= 2) {
5293 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5294 bwn_rf_2050_rfoverval(mac,
5295 BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5296 }
5297 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5298 DELAY(10);
5299 if (phy->gmode || phy->rev >= 2) {
5300 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5301 bwn_rf_2050_rfoverval(mac,
5302 BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5303 }
5304 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5305 DELAY(10);
5306 tmp2 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5307 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5308 if (phy->gmode || phy->rev >= 2) {
5309 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5310 bwn_rf_2050_rfoverval(mac,
5311 BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5312 }
5313 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5314 }
5315 tmp2++;
5316 tmp2 >>= 8;
5317 if (tmp1 < tmp2)
5318 break;
5319 }
5320
5321 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pgactl);
5322 BWN_RF_WRITE(mac, 0x51, radio1);
5323 BWN_RF_WRITE(mac, 0x52, radio2);
5324 BWN_RF_WRITE(mac, 0x43, radio0);
5325 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), cck0);
5326 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), cck1);
5327 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), cck2);
5328 BWN_WRITE_2(mac, 0x3e6, reg1);
5329 if (phy->analog != 0)
5330 BWN_WRITE_2(mac, 0x3f4, reg2);
5331 BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, syncctl);
5332 bwn_spu_workaround(mac, phy->chan);
5333 if (phy->type == BWN_PHYTYPE_B) {
5334 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), cck3);
5335 BWN_WRITE_2(mac, 0x3ec, reg0);
5336 } else if (phy->gmode) {
5337 BWN_WRITE_2(mac, BWN_PHY_RADIO,
5338 BWN_READ_2(mac, BWN_PHY_RADIO)
5339 & 0x7fff);
5340 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover);
5341 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval);
5342 BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, analogover);
5343 BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
5344 analogoverval);
5345 BWN_PHY_WRITE(mac, BWN_PHY_CRS0, crs0);
5346 BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, classctl);
5347 if (BWN_HAS_LOOPBACK(phy)) {
5348 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, lomask);
5349 BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, loctl);
5350 }
5351 }
5352
5353 return ((i > 15) ? radio78 : rcc);
5354}
5355
5356static void
5357bwn_phy_init_b6(struct bwn_mac *mac)
5358{
5359 struct bwn_phy *phy = &mac->mac_phy;
5360 struct bwn_phy_g *pg = &phy->phy_g;
5361 struct bwn_softc *sc = mac->mac_sc;
5362 uint16_t offset, val;
5363 uint8_t old_channel;
5364
5365 KASSERT(!(phy->rf_rev == 6 || phy->rf_rev == 7),
5366 ("%s:%d: fail", __func__, __LINE__));
5367
5368 BWN_PHY_WRITE(mac, 0x003e, 0x817a);
5369 BWN_RF_WRITE(mac, 0x007a, BWN_RF_READ(mac, 0x007a) | 0x0058);
5370 if (phy->rf_rev == 4 || phy->rf_rev == 5) {
5371 BWN_RF_WRITE(mac, 0x51, 0x37);
5372 BWN_RF_WRITE(mac, 0x52, 0x70);
5373 BWN_RF_WRITE(mac, 0x53, 0xb3);
5374 BWN_RF_WRITE(mac, 0x54, 0x9b);
5375 BWN_RF_WRITE(mac, 0x5a, 0x88);
5376 BWN_RF_WRITE(mac, 0x5b, 0x88);
5377 BWN_RF_WRITE(mac, 0x5d, 0x88);
5378 BWN_RF_WRITE(mac, 0x5e, 0x88);
5379 BWN_RF_WRITE(mac, 0x7d, 0x88);
5380 bwn_hf_write(mac,
5381 bwn_hf_read(mac) | BWN_HF_TSSI_RESET_PSM_WORKAROUN);
5382 }
5383 if (phy->rf_rev == 8) {
5384 BWN_RF_WRITE(mac, 0x51, 0);
5385 BWN_RF_WRITE(mac, 0x52, 0x40);
5386 BWN_RF_WRITE(mac, 0x53, 0xb7);
5387 BWN_RF_WRITE(mac, 0x54, 0x98);
5388 BWN_RF_WRITE(mac, 0x5a, 0x88);
5389 BWN_RF_WRITE(mac, 0x5b, 0x6b);
5390 BWN_RF_WRITE(mac, 0x5c, 0x0f);
5391 if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_ALTIQ) {
5392 BWN_RF_WRITE(mac, 0x5d, 0xfa);
5393 BWN_RF_WRITE(mac, 0x5e, 0xd8);
5394 } else {
5395 BWN_RF_WRITE(mac, 0x5d, 0xf5);
5396 BWN_RF_WRITE(mac, 0x5e, 0xb8);
5397 }
5398 BWN_RF_WRITE(mac, 0x0073, 0x0003);
5399 BWN_RF_WRITE(mac, 0x007d, 0x00a8);
5400 BWN_RF_WRITE(mac, 0x007c, 0x0001);
5401 BWN_RF_WRITE(mac, 0x007e, 0x0008);
5402 }
5403 for (val = 0x1e1f, offset = 0x0088; offset < 0x0098; offset++) {
5404 BWN_PHY_WRITE(mac, offset, val);
5405 val -= 0x0202;
5406 }
5407 for (val = 0x3e3f, offset = 0x0098; offset < 0x00a8; offset++) {
5408 BWN_PHY_WRITE(mac, offset, val);
5409 val -= 0x0202;
5410 }
5411 for (val = 0x2120, offset = 0x00a8; offset < 0x00c8; offset++) {
5412 BWN_PHY_WRITE(mac, offset, (val & 0x3f3f));
5413 val += 0x0202;
5414 }
5415 if (phy->type == BWN_PHYTYPE_G) {
5416 BWN_RF_SET(mac, 0x007a, 0x0020);
5417 BWN_RF_SET(mac, 0x0051, 0x0004);
5418 BWN_PHY_SET(mac, 0x0802, 0x0100);
5419 BWN_PHY_SET(mac, 0x042b, 0x2000);
5420 BWN_PHY_WRITE(mac, 0x5b, 0);
5421 BWN_PHY_WRITE(mac, 0x5c, 0);
5422 }
5423
5424 old_channel = phy->chan;
5425 bwn_phy_g_switch_chan(mac, (old_channel >= 8) ? 1 : 13, 0);
5426
5427 BWN_RF_WRITE(mac, 0x0050, 0x0020);
5428 BWN_RF_WRITE(mac, 0x0050, 0x0023);
5429 DELAY(40);
5430 if (phy->rf_rev < 6 || phy->rf_rev == 8) {
5431 BWN_RF_WRITE(mac, 0x7c, BWN_RF_READ(mac, 0x7c) | 0x0002);
5432 BWN_RF_WRITE(mac, 0x50, 0x20);
5433 }
5434 if (phy->rf_rev <= 2) {
5435 BWN_RF_WRITE(mac, 0x7c, 0x20);
5436 BWN_RF_WRITE(mac, 0x5a, 0x70);
5437 BWN_RF_WRITE(mac, 0x5b, 0x7b);
5438 BWN_RF_WRITE(mac, 0x5c, 0xb0);
5439 }
5440 BWN_RF_SETMASK(mac, 0x007a, 0x00f8, 0x0007);
5441
5442 bwn_phy_g_switch_chan(mac, old_channel, 0);
5443
5444 BWN_PHY_WRITE(mac, 0x0014, 0x0200);
5445 if (phy->rf_rev >= 6)
5446 BWN_PHY_WRITE(mac, 0x2a, 0x88c2);
5447 else
5448 BWN_PHY_WRITE(mac, 0x2a, 0x8ac0);
5449 BWN_PHY_WRITE(mac, 0x0038, 0x0668);
5450 bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
5451 pg->pg_txctl);
5452 if (phy->rf_rev <= 5)
5453 BWN_PHY_SETMASK(mac, 0x5d, 0xff80, 0x0003);
5454 if (phy->rf_rev <= 2)
5455 BWN_RF_WRITE(mac, 0x005d, 0x000d);
5456
5457 if (phy->analog == 4) {
5458 BWN_WRITE_2(mac, 0x3e4, 9);
5459 BWN_PHY_MASK(mac, 0x61, 0x0fff);
5460 } else
5461 BWN_PHY_SETMASK(mac, 0x0002, 0xffc0, 0x0004);
5462 if (phy->type == BWN_PHYTYPE_B)
5463 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5464 else if (phy->type == BWN_PHYTYPE_G)
5465 BWN_WRITE_2(mac, 0x03e6, 0x0);
5466}
5467
5468static void
5469bwn_phy_init_a(struct bwn_mac *mac)
5470{
5471 struct bwn_phy *phy = &mac->mac_phy;
5472 struct bwn_softc *sc = mac->mac_sc;
5473
5474 KASSERT(phy->type == BWN_PHYTYPE_A || phy->type == BWN_PHYTYPE_G,
5475 ("%s:%d: fail", __func__, __LINE__));
5476
5477 if (phy->rev >= 6) {
5478 if (phy->type == BWN_PHYTYPE_A)
5479 BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x1000);
5480 if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) & BWN_PHY_ENCORE_EN)
5481 BWN_PHY_SET(mac, BWN_PHY_ENCORE, 0x0010);
5482 else
5483 BWN_PHY_MASK(mac, BWN_PHY_ENCORE, ~0x1010);
5484 }
5485
5486 bwn_wa_init(mac);
5487
5488 if (phy->type == BWN_PHYTYPE_G &&
5489 (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL))
5490 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x6e), 0xe000, 0x3cf);
5491}
5492
5493static void
5494bwn_wa_write_noisescale(struct bwn_mac *mac, const uint16_t *nst)
5495{
5496 int i;
5497
5498 for (i = 0; i < BWN_TAB_NOISESCALE_SIZE; i++)
5499 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_NOISESCALE, i, nst[i]);
5500}
5501
5502static void
5503bwn_wa_agc(struct bwn_mac *mac)
5504{
5505 struct bwn_phy *phy = &mac->mac_phy;
5506
5507 if (phy->rev == 1) {
5508 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 0, 254);
5509 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 1, 13);
5510 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 2, 19);
5511 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 3, 25);
5512 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 0, 0x2710);
5513 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 1, 0x9b83);
5514 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 2, 0x9b83);
5515 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 3, 0x0f8d);
5516 BWN_PHY_WRITE(mac, BWN_PHY_LMS, 4);
5517 } else {
5518 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 0, 254);
5519 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 1, 13);
5520 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 2, 19);
5521 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 3, 25);
5522 }
5523
5524 BWN_PHY_SETMASK(mac, BWN_PHY_CCKSHIFTBITS_WA, (uint16_t)~0xff00,
5525 0x5700);
5526 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x007f, 0x000f);
5527 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x3f80, 0x2b80);
5528 BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, 0xf0ff, 0x0300);
5529 BWN_RF_SET(mac, 0x7a, 0x0008);
5530 BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x000f, 0x0008);
5531 BWN_PHY_SETMASK(mac, BWN_PHY_P1P2GAIN, ~0x0f00, 0x0600);
5532 BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x0f00, 0x0700);
5533 BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x0f00, 0x0100);
5534 if (phy->rev == 1)
5535 BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x000f, 0x0007);
5536 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x00ff, 0x001c);
5537 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x3f00, 0x0200);
5538 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), ~0x00ff, 0x001c);
5539 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x00ff, 0x0020);
5540 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x3f00, 0x0200);
5541 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x82), ~0x00ff, 0x002e);
5542 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), (uint16_t)~0xff00, 0x1a00);
5543 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), ~0x00ff, 0x0028);
5544 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), (uint16_t)~0xff00, 0x2c00);
5545 if (phy->rev == 1) {
5546 BWN_PHY_WRITE(mac, BWN_PHY_PEAK_COUNT, 0x092b);
5547 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e, 0x0002);
5548 } else {
5549 BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e);
5550 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x1f), 0x287a);
5551 BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL, ~0x000f, 0x0004);
5552 if (phy->rev >= 6) {
5553 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x22), 0x287a);
5554 BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL,
5555 (uint16_t)~0xf000, 0x3000);
5556 }
5557 }
5558 BWN_PHY_SETMASK(mac, BWN_PHY_DIVSRCHIDX, 0x8080, 0x7874);
5559 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8e), 0x1c00);
5560 if (phy->rev == 1) {
5561 BWN_PHY_SETMASK(mac, BWN_PHY_DIVP1P2GAIN, ~0x0f00, 0x0600);
5562 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8b), 0x005e);
5563 BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, ~0x00ff, 0x001e);
5564 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8d), 0x0002);
5565 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 0, 0);
5566 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 1, 7);
5567 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 2, 16);
5568 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 3, 28);
5569 } else {
5570 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 0, 0);
5571 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 1, 7);
5572 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 2, 16);
5573 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 3, 28);
5574 }
5575 if (phy->rev >= 6) {
5576 BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x0003);
5577 BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x1000);
5578 }
5579 BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
5580}
5581
5582static void
5583bwn_wa_grev1(struct bwn_mac *mac)
5584{
5585 struct bwn_phy *phy = &mac->mac_phy;
5586 int i;
5587 static const uint16_t bwn_tab_finefreqg[] = BWN_TAB_FINEFREQ_G;
5588 static const uint32_t bwn_tab_retard[] = BWN_TAB_RETARD;
5589 static const uint32_t bwn_tab_rotor[] = BWN_TAB_ROTOR;
5590
5591 KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5592
5593 /* init CRSTHRES and ANTDWELL */
5594 if (phy->rev == 1) {
5595 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5596 } else if (phy->rev == 2) {
5597 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5598 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5599 BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5600 } else {
5601 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5602 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5603 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5604 BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5605 }
5606 BWN_PHY_SETMASK(mac, BWN_PHY_CRS0, ~0x03c0, 0xd000);
5607 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x2c), 0x005a);
5608 BWN_PHY_WRITE(mac, BWN_PHY_CCKSHIFTBITS, 0x0026);
5609
5610 /* XXX support PHY-A??? */
5611 for (i = 0; i < N(bwn_tab_finefreqg); i++)
5612 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DACRFPABB, i,
5613 bwn_tab_finefreqg[i]);
5614
5615 /* XXX support PHY-A??? */
5616 if (phy->rev == 1)
5617 for (i = 0; i < N(bwn_tab_noise_g1); i++)
5618 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5619 bwn_tab_noise_g1[i]);
5620 else
5621 for (i = 0; i < N(bwn_tab_noise_g2); i++)
5622 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5623 bwn_tab_noise_g2[i]);
5624
5625
5626 for (i = 0; i < N(bwn_tab_rotor); i++)
5627 bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ROTOR, i,
5628 bwn_tab_rotor[i]);
5629
5630 /* XXX support PHY-A??? */
5631 if (phy->rev >= 6) {
5632 if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5633 BWN_PHY_ENCORE_EN)
5634 bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5635 else
5636 bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5637 } else
5638 bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5639
5640 for (i = 0; i < N(bwn_tab_retard); i++)
5641 bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ADVRETARD, i,
5642 bwn_tab_retard[i]);
5643
5644 if (phy->rev == 1) {
5645 for (i = 0; i < 16; i++)
5646 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1,
5647 i, 0x0020);
5648 } else {
5649 for (i = 0; i < 32; i++)
5650 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5651 }
5652
5653 bwn_wa_agc(mac);
5654}
5655
5656static void
5657bwn_wa_grev26789(struct bwn_mac *mac)
5658{
5659 struct bwn_phy *phy = &mac->mac_phy;
5660 int i;
5661 static const uint16_t bwn_tab_sigmasqr2[] = BWN_TAB_SIGMASQR2;
5662 uint16_t ofdmrev;
5663
5664 KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5665
5666 bwn_gtab_write(mac, BWN_GTAB_ORIGTR, 0, 0xc480);
5667
5668 /* init CRSTHRES and ANTDWELL */
5669 if (phy->rev == 1)
5670 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5671 else if (phy->rev == 2) {
5672 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5673 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5674 BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5675 } else {
5676 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5677 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5678 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5679 BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5680 }
5681
5682 for (i = 0; i < 64; i++)
5683 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_RSSI, i, i);
5684
5685 /* XXX support PHY-A??? */
5686 if (phy->rev == 1)
5687 for (i = 0; i < N(bwn_tab_noise_g1); i++)
5688 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5689 bwn_tab_noise_g1[i]);
5690 else
5691 for (i = 0; i < N(bwn_tab_noise_g2); i++)
5692 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5693 bwn_tab_noise_g2[i]);
5694
5695 /* XXX support PHY-A??? */
5696 if (phy->rev >= 6) {
5697 if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5698 BWN_PHY_ENCORE_EN)
5699 bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5700 else
5701 bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5702 } else
5703 bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5704
5705 for (i = 0; i < N(bwn_tab_sigmasqr2); i++)
5706 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_MINSIGSQ, i,
5707 bwn_tab_sigmasqr2[i]);
5708
5709 if (phy->rev == 1) {
5710 for (i = 0; i < 16; i++)
5711 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1, i,
5712 0x0020);
5713 } else {
5714 for (i = 0; i < 32; i++)
5715 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5716 }
5717
5718 bwn_wa_agc(mac);
5719
5720 ofdmrev = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM) & BWN_PHYVER_VERSION;
5721 if (ofdmrev > 2) {
5722 if (phy->type == BWN_PHYTYPE_A)
5723 BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1808);
5724 else
5725 BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1000);
5726 } else {
5727 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 3, 0x1044);
5728 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 4, 0x7201);
5729 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 6, 0x0040);
5730 }
5731
5732 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 2, 15);
5733 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 3, 20);
5734}
5735
5736static void
5737bwn_wa_init(struct bwn_mac *mac)
5738{
5739 struct bwn_phy *phy = &mac->mac_phy;
5740 struct bwn_softc *sc = mac->mac_sc;
5741
5742 KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5743
5744 switch (phy->rev) {
5745 case 1:
5746 bwn_wa_grev1(mac);
5747 break;
5748 case 2:
5749 case 6:
5750 case 7:
5751 case 8:
5752 case 9:
5753 bwn_wa_grev26789(mac);
5754 break;
5755 default:
5756 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5757 }
5758
5759 if (siba_get_pci_subvendor(sc->sc_dev) != SIBA_BOARDVENDOR_BCM ||
5760 siba_get_pci_subdevice(sc->sc_dev) != SIBA_BOARD_BU4306 ||
5761 siba_get_pci_revid(sc->sc_dev) != 0x17) {
5762 if (phy->rev < 2) {
5763 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 1,
5764 0x0002);
5765 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 2,
5766 0x0001);
5767 } else {
5768 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 1, 0x0002);
5769 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 2, 0x0001);
5770 if ((siba_sprom_get_bf_lo(sc->sc_dev) &
5771 BWN_BFL_EXTLNA) &&
5772 (phy->rev >= 7)) {
5773 BWN_PHY_MASK(mac, BWN_PHY_EXTG(0x11), 0xf7ff);
5774 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5775 0x0020, 0x0001);
5776 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5777 0x0021, 0x0001);
5778 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5779 0x0022, 0x0001);
5780 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5781 0x0023, 0x0000);
5782 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5783 0x0000, 0x0000);
5784 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5785 0x0003, 0x0002);
5786 }
5787 }
5788 }
5789 if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM) {
5790 BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, 0x3120);
5791 BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, 0xc480);
5792 }
5793
5794 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 0, 0);
5795 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 1, 0);
5796}
5797
5798static void
5799bwn_ofdmtab_write_2(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5800 uint16_t value)
5801{
5802 struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5803 uint16_t addr;
5804
5805 addr = table + offset;
5806 if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5807 (addr - 1 != pg->pg_ofdmtab_addr)) {
5808 BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5809 pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5810 }
5811 pg->pg_ofdmtab_addr = addr;
5812 BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5813}
5814
5815static void
5816bwn_ofdmtab_write_4(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5817 uint32_t value)
5818{
5819 struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5820 uint16_t addr;
5821
5822 addr = table + offset;
5823 if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5824 (addr - 1 != pg->pg_ofdmtab_addr)) {
5825 BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5826 pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5827 }
5828 pg->pg_ofdmtab_addr = addr;
5829
5830 BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5831 BWN_PHY_WRITE(mac, BWN_PHY_OTABLEQ, (value >> 16));
5832}
5833
5834static void
5835bwn_gtab_write(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5836 uint16_t value)
5837{
5838
5839 BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, table + offset);
5840 BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, value);
5841}
5842
5843static void
5844bwn_dummy_transmission(struct bwn_mac *mac, int ofdm, int paon)
5845{
5846 struct bwn_phy *phy = &mac->mac_phy;
5847 struct bwn_softc *sc = mac->mac_sc;
5848 unsigned int i, max_loop;
5849 uint16_t value;
5850 uint32_t buffer[5] = {
5851 0x00000000, 0x00d40000, 0x00000000, 0x01000000, 0x00000000
5852 };
5853
5854 if (ofdm) {
5855 max_loop = 0x1e;
5856 buffer[0] = 0x000201cc;
5857 } else {
5858 max_loop = 0xfa;
5859 buffer[0] = 0x000b846e;
5860 }
5861
5862 BWN_ASSERT_LOCKED(mac->mac_sc);
5863
5864 for (i = 0; i < 5; i++)
5865 bwn_ram_write(mac, i * 4, buffer[i]);
5866
5867 BWN_WRITE_2(mac, 0x0568, 0x0000);
5868 BWN_WRITE_2(mac, 0x07c0,
5869 (siba_get_revid(sc->sc_dev) < 11) ? 0x0000 : 0x0100);
5870 value = ((phy->type == BWN_PHYTYPE_A) ? 0x41 : 0x40);
5871 BWN_WRITE_2(mac, 0x050c, value);
5872 if (phy->type == BWN_PHYTYPE_LP)
5873 BWN_WRITE_2(mac, 0x0514, 0x1a02);
5874 BWN_WRITE_2(mac, 0x0508, 0x0000);
5875 BWN_WRITE_2(mac, 0x050a, 0x0000);
5876 BWN_WRITE_2(mac, 0x054c, 0x0000);
5877 BWN_WRITE_2(mac, 0x056a, 0x0014);
5878 BWN_WRITE_2(mac, 0x0568, 0x0826);
5879 BWN_WRITE_2(mac, 0x0500, 0x0000);
5880 if (phy->type == BWN_PHYTYPE_LP)
5881 BWN_WRITE_2(mac, 0x0502, 0x0050);
5882 else
5883 BWN_WRITE_2(mac, 0x0502, 0x0030);
5884
5885 if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5886 BWN_RF_WRITE(mac, 0x0051, 0x0017);
5887 for (i = 0x00; i < max_loop; i++) {
5888 value = BWN_READ_2(mac, 0x050e);
5889 if (value & 0x0080)
5890 break;
5891 DELAY(10);
5892 }
5893 for (i = 0x00; i < 0x0a; i++) {
5894 value = BWN_READ_2(mac, 0x050e);
5895 if (value & 0x0400)
5896 break;
5897 DELAY(10);
5898 }
5899 for (i = 0x00; i < 0x19; i++) {
5900 value = BWN_READ_2(mac, 0x0690);
5901 if (!(value & 0x0100))
5902 break;
5903 DELAY(10);
5904 }
5905 if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5906 BWN_RF_WRITE(mac, 0x0051, 0x0037);
5907}
5908
5909static void
5910bwn_ram_write(struct bwn_mac *mac, uint16_t offset, uint32_t val)
5911{
5912 uint32_t macctl;
5913
5914 KASSERT(offset % 4 == 0, ("%s:%d: fail", __func__, __LINE__));
5915
5916 macctl = BWN_READ_4(mac, BWN_MACCTL);
5917 if (macctl & BWN_MACCTL_BIGENDIAN)
5918 printf("TODO: need swap\n");
5919
5920 BWN_WRITE_4(mac, BWN_RAM_CONTROL, offset);
5921 BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
5922 BWN_WRITE_4(mac, BWN_RAM_DATA, val);
5923}
5924
5925static void
5926bwn_lo_write(struct bwn_mac *mac, struct bwn_loctl *ctl)
5927{
5928 uint16_t value;
5929
5930 KASSERT(mac->mac_phy.type == BWN_PHYTYPE_G,
5931 ("%s:%d: fail", __func__, __LINE__));
5932
5933 value = (uint8_t) (ctl->q);
5934 value |= ((uint8_t) (ctl->i)) << 8;
5935 BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, value);
5936}
5937
5938static uint16_t
5939bwn_lo_calcfeed(struct bwn_mac *mac,
5940 uint16_t lna, uint16_t pga, uint16_t trsw_rx)
5941{
5942 struct bwn_phy *phy = &mac->mac_phy;
5943 struct bwn_softc *sc = mac->mac_sc;
5944 uint16_t rfover;
5945 uint16_t feedthrough;
5946
5947 if (phy->gmode) {
5948 lna <<= BWN_PHY_RFOVERVAL_LNA_SHIFT;
5949 pga <<= BWN_PHY_RFOVERVAL_PGA_SHIFT;
5950
5951 KASSERT((lna & ~BWN_PHY_RFOVERVAL_LNA) == 0,
5952 ("%s:%d: fail", __func__, __LINE__));
5953 KASSERT((pga & ~BWN_PHY_RFOVERVAL_PGA) == 0,
5954 ("%s:%d: fail", __func__, __LINE__));
5955
5956 trsw_rx &= (BWN_PHY_RFOVERVAL_TRSWRX | BWN_PHY_RFOVERVAL_BW);
5957
5958 rfover = BWN_PHY_RFOVERVAL_UNK | pga | lna | trsw_rx;
5959 if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA) &&
5960 phy->rev > 6)
5961 rfover |= BWN_PHY_RFOVERVAL_EXTLNA;
5962
5963 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
5964 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5965 DELAY(10);
5966 rfover |= BWN_PHY_RFOVERVAL_BW_LBW;
5967 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5968 DELAY(10);
5969 rfover |= BWN_PHY_RFOVERVAL_BW_LPF;
5970 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5971 DELAY(10);
5972 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xf300);
5973 } else {
5974 pga |= BWN_PHY_PGACTL_UNKNOWN;
5975 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5976 DELAY(10);
5977 pga |= BWN_PHY_PGACTL_LOWBANDW;
5978 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5979 DELAY(10);
5980 pga |= BWN_PHY_PGACTL_LPF;
5981 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5982 }
5983 DELAY(21);
5984 feedthrough = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5985
5986 return (feedthrough);
5987}
5988
5989static uint16_t
5990bwn_lo_txctl_regtable(struct bwn_mac *mac,
5991 uint16_t *value, uint16_t *pad_mix_gain)
5992{
5993 struct bwn_phy *phy = &mac->mac_phy;
5994 uint16_t reg, v, padmix;
5995
5996 if (phy->type == BWN_PHYTYPE_B) {
5997 v = 0x30;
5998 if (phy->rf_rev <= 5) {
5999 reg = 0x43;
6000 padmix = 0;
6001 } else {
6002 reg = 0x52;
6003 padmix = 5;
6004 }
6005 } else {
6006 if (phy->rev >= 2 && phy->rf_rev == 8) {
6007 reg = 0x43;
6008 v = 0x10;
6009 padmix = 2;
6010 } else {
6011 reg = 0x52;
6012 v = 0x30;
6013 padmix = 5;
6014 }
6015 }
6016 if (value)
6017 *value = v;
6018 if (pad_mix_gain)
6019 *pad_mix_gain = padmix;
6020
6021 return (reg);
6022}
6023
6024static void
6025bwn_lo_measure_txctl_values(struct bwn_mac *mac)
6026{
6027 struct bwn_phy *phy = &mac->mac_phy;
6028 struct bwn_phy_g *pg = &phy->phy_g;
6029 struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6030 uint16_t reg, mask;
6031 uint16_t trsw_rx, pga;
6032 uint16_t rf_pctl_reg;
6033
6034 static const uint8_t tx_bias_values[] = {
6035 0x09, 0x08, 0x0a, 0x01, 0x00,
6036 0x02, 0x05, 0x04, 0x06,
6037 };
6038 static const uint8_t tx_magn_values[] = {
6039 0x70, 0x40,
6040 };
6041
6042 if (!BWN_HAS_LOOPBACK(phy)) {
6043 rf_pctl_reg = 6;
6044 trsw_rx = 2;
6045 pga = 0;
6046 } else {
6047 int lb_gain;
6048
6049 trsw_rx = 0;
6050 lb_gain = pg->pg_max_lb_gain / 2;
6051 if (lb_gain > 10) {
6052 rf_pctl_reg = 0;
6053 pga = abs(10 - lb_gain) / 6;
6054 pga = MIN(MAX(pga, 0), 15);
6055 } else {
6056 int cmp_val;
6057 int tmp;
6058
6059 pga = 0;
6060 cmp_val = 0x24;
6061 if ((phy->rev >= 2) &&
6062 (phy->rf_ver == 0x2050) && (phy->rf_rev == 8))
6063 cmp_val = 0x3c;
6064 tmp = lb_gain;
6065 if ((10 - lb_gain) < cmp_val)
6066 tmp = (10 - lb_gain);
6067 if (tmp < 0)
6068 tmp += 6;
6069 else
6070 tmp += 3;
6071 cmp_val /= 4;
6072 tmp /= 4;
6073 if (tmp >= cmp_val)
6074 rf_pctl_reg = cmp_val;
6075 else
6076 rf_pctl_reg = tmp;
6077 }
6078 }
6079 BWN_RF_SETMASK(mac, 0x43, 0xfff0, rf_pctl_reg);
6080 bwn_phy_g_set_bbatt(mac, 2);
6081
6082 reg = bwn_lo_txctl_regtable(mac, &mask, NULL);
6083 mask = ~mask;
6084 BWN_RF_MASK(mac, reg, mask);
6085
6086 if (BWN_HAS_TXMAG(phy)) {
6087 int i, j;
6088 int feedthrough;
6089 int min_feedth = 0xffff;
6090 uint8_t tx_magn, tx_bias;
6091
6092 for (i = 0; i < N(tx_magn_values); i++) {
6093 tx_magn = tx_magn_values[i];
6094 BWN_RF_SETMASK(mac, 0x52, 0xff0f, tx_magn);
6095 for (j = 0; j < N(tx_bias_values); j++) {
6096 tx_bias = tx_bias_values[j];
6097 BWN_RF_SETMASK(mac, 0x52, 0xfff0, tx_bias);
6098 feedthrough = bwn_lo_calcfeed(mac, 0, pga,
6099 trsw_rx);
6100 if (feedthrough < min_feedth) {
6101 lo->tx_bias = tx_bias;
6102 lo->tx_magn = tx_magn;
6103 min_feedth = feedthrough;
6104 }
6105 if (lo->tx_bias == 0)
6106 break;
6107 }
6108 BWN_RF_WRITE(mac, 0x52,
6109 (BWN_RF_READ(mac, 0x52)
6110 & 0xff00) | lo->tx_bias | lo->
6111 tx_magn);
6112 }
6113 } else {
6114 lo->tx_magn = 0;
6115 lo->tx_bias = 0;
6116 BWN_RF_MASK(mac, 0x52, 0xfff0);
6117 }
6118
6119 BWN_GETTIME(lo->txctl_measured_time);
6120}
6121
6122static void
6123bwn_lo_get_powervector(struct bwn_mac *mac)
6124{
6125 struct bwn_phy *phy = &mac->mac_phy;
6126 struct bwn_phy_g *pg = &phy->phy_g;
6127 struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6128 int i;
6129 uint64_t tmp;
6130 uint64_t power_vector = 0;
6131
6132 for (i = 0; i < 8; i += 2) {
6133 tmp = bwn_shm_read_2(mac, BWN_SHARED, 0x310 + i);
6134 power_vector |= (tmp << (i * 8));
6135 bwn_shm_write_2(mac, BWN_SHARED, 0x310 + i, 0);
6136 }
6137 if (power_vector)
6138 lo->power_vector = power_vector;
6139
6140 BWN_GETTIME(lo->pwr_vec_read_time);
6141}
6142
6143static void
6144bwn_lo_measure_gain_values(struct bwn_mac *mac, int16_t max_rx_gain,
6145 int use_trsw_rx)
6146{
6147 struct bwn_phy *phy = &mac->mac_phy;
6148 struct bwn_phy_g *pg = &phy->phy_g;
6149 uint16_t tmp;
6150
6151 if (max_rx_gain < 0)
6152 max_rx_gain = 0;
6153
6154 if (BWN_HAS_LOOPBACK(phy)) {
6155 int trsw_rx = 0;
6156 int trsw_rx_gain;
6157
6158 if (use_trsw_rx) {
6159 trsw_rx_gain = pg->pg_trsw_rx_gain / 2;
6160 if (max_rx_gain >= trsw_rx_gain) {
6161 trsw_rx_gain = max_rx_gain - trsw_rx_gain;
6162 trsw_rx = 0x20;
6163 }
6164 } else
6165 trsw_rx_gain = max_rx_gain;
6166 if (trsw_rx_gain < 9) {
6167 pg->pg_lna_lod_gain = 0;
6168 } else {
6169 pg->pg_lna_lod_gain = 1;
6170 trsw_rx_gain -= 8;
6171 }
6172 trsw_rx_gain = MIN(MAX(trsw_rx_gain, 0), 0x2d);
6173 pg->pg_pga_gain = trsw_rx_gain / 3;
6174 if (pg->pg_pga_gain >= 5) {
6175 pg->pg_pga_gain -= 5;
6176 pg->pg_lna_gain = 2;
6177 } else
6178 pg->pg_lna_gain = 0;
6179 } else {
6180 pg->pg_lna_gain = 0;
6181 pg->pg_trsw_rx_gain = 0x20;
6182 if (max_rx_gain >= 0x14) {
6183 pg->pg_lna_lod_gain = 1;
6184 pg->pg_pga_gain = 2;
6185 } else if (max_rx_gain >= 0x12) {
6186 pg->pg_lna_lod_gain = 1;
6187 pg->pg_pga_gain = 1;
6188 } else if (max_rx_gain >= 0xf) {
6189 pg->pg_lna_lod_gain = 1;
6190 pg->pg_pga_gain = 0;
6191 } else {
6192 pg->pg_lna_lod_gain = 0;
6193 pg->pg_pga_gain = 0;
6194 }
6195 }
6196
6197 tmp = BWN_RF_READ(mac, 0x7a);
6198 if (pg->pg_lna_lod_gain == 0)
6199 tmp &= ~0x0008;
6200 else
6201 tmp |= 0x0008;
6202 BWN_RF_WRITE(mac, 0x7a, tmp);
6203}
6204
6205static void
6206bwn_lo_save(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6207{
6208 struct bwn_phy *phy = &mac->mac_phy;
6209 struct bwn_phy_g *pg = &phy->phy_g;
6210 struct bwn_softc *sc = mac->mac_sc;
6211 struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6212 struct timespec ts;
6213 uint16_t tmp;
6214
6215 if (bwn_has_hwpctl(mac)) {
6216 sav->phy_lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
6217 sav->phy_extg = BWN_PHY_READ(mac, BWN_PHY_EXTG(0x01));
6218 sav->phy_dacctl_hwpctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6219 sav->phy_cck4 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x14));
6220 sav->phy_hpwr_tssictl = BWN_PHY_READ(mac, BWN_PHY_HPWR_TSSICTL);
6221
6222 BWN_PHY_SET(mac, BWN_PHY_HPWR_TSSICTL, 0x100);
6223 BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x40);
6224 BWN_PHY_SET(mac, BWN_PHY_DACCTL, 0x40);
6225 BWN_PHY_SET(mac, BWN_PHY_CCK(0x14), 0x200);
6226 }
6227 if (phy->type == BWN_PHYTYPE_B &&
6228 phy->rf_ver == 0x2050 && phy->rf_rev < 6) {
6229 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x16), 0x410);
6230 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x17), 0x820);
6231 }
6232 if (phy->rev >= 2) {
6233 sav->phy_analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
6234 sav->phy_analogoverval =
6235 BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
6236 sav->phy_rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
6237 sav->phy_rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
6238 sav->phy_classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
6239 sav->phy_cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x3e));
6240 sav->phy_crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
6241
6242 BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
6243 BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
6244 BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
6245 BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
6246 if (phy->type == BWN_PHYTYPE_G) {
6247 if ((phy->rev >= 7) &&
6248 (siba_sprom_get_bf_lo(sc->sc_dev) &
6249 BWN_BFL_EXTLNA)) {
6250 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x933);
6251 } else {
6252 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x133);
6253 }
6254 } else {
6255 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
6256 }
6257 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), 0);
6258 }
6259 sav->reg0 = BWN_READ_2(mac, 0x3f4);
6260 sav->reg1 = BWN_READ_2(mac, 0x3e2);
6261 sav->rf0 = BWN_RF_READ(mac, 0x43);
6262 sav->rf1 = BWN_RF_READ(mac, 0x7a);
6263 sav->phy_pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
6264 sav->phy_cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2a));
6265 sav->phy_syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
6266 sav->phy_dacctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6267
6268 if (!BWN_HAS_TXMAG(phy)) {
6269 sav->rf2 = BWN_RF_READ(mac, 0x52);
6270 sav->rf2 &= 0x00f0;
6271 }
6272 if (phy->type == BWN_PHYTYPE_B) {
6273 sav->phy_cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
6274 sav->phy_cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x06));
6275 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0x00ff);
6276 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), 0x3f3f);
6277 } else {
6278 BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2)
6279 | 0x8000);
6280 }
6281 BWN_WRITE_2(mac, 0x3f4, BWN_READ_2(mac, 0x3f4)
6282 & 0xf000);
6283
6284 tmp =
6285 (phy->type == BWN_PHYTYPE_G) ? BWN_PHY_LO_MASK : BWN_PHY_CCK(0x2e);
6286 BWN_PHY_WRITE(mac, tmp, 0x007f);
6287
6288 tmp = sav->phy_syncctl;
6289 BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, tmp & 0xff7f);
6290 tmp = sav->rf1;
6291 BWN_RF_WRITE(mac, 0x007a, tmp & 0xfff0);
6292
6293 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), 0x8a3);
6294 if (phy->type == BWN_PHYTYPE_G ||
6295 (phy->type == BWN_PHYTYPE_B &&
6296 phy->rf_ver == 0x2050 && phy->rf_rev >= 6)) {
6297 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1003);
6298 } else
6299 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x0802);
6300 if (phy->rev >= 2)
6301 bwn_dummy_transmission(mac, 0, 1);
6302 bwn_phy_g_switch_chan(mac, 6, 0);
6303 BWN_RF_READ(mac, 0x51);
6304 if (phy->type == BWN_PHYTYPE_G)
6305 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0);
6306
6307 nanouptime(&ts);
6308 if (time_before(lo->txctl_measured_time,
6309 (ts.tv_nsec / 1000000 + ts.tv_sec * 1000) - BWN_LO_TXCTL_EXPIRE))
6310 bwn_lo_measure_txctl_values(mac);
6311
6312 if (phy->type == BWN_PHYTYPE_G && phy->rev >= 3)
6313 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc078);
6314 else {
6315 if (phy->type == BWN_PHYTYPE_B)
6316 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6317 else
6318 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
6319 }
6320}
6321
6322static void
6323bwn_lo_restore(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6324{
6325 struct bwn_phy *phy = &mac->mac_phy;
6326 struct bwn_phy_g *pg = &phy->phy_g;
6327 uint16_t tmp;
6328
6329 if (phy->rev >= 2) {
6330 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
6331 tmp = (pg->pg_pga_gain << 8);
6332 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa0);
6333 DELAY(5);
6334 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa2);
6335 DELAY(2);
6336 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa3);
6337 } else {
6338 tmp = (pg->pg_pga_gain | 0xefa0);
6339 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, tmp);
6340 }
6341 if (phy->type == BWN_PHYTYPE_G) {
6342 if (phy->rev >= 3)
6343 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0xc078);
6344 else
6345 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6346 if (phy->rev >= 2)
6347 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0202);
6348 else
6349 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0101);
6350 }
6351 BWN_WRITE_2(mac, 0x3f4, sav->reg0);
6352 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, sav->phy_pgactl);
6353 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), sav->phy_cck2);
6354 BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, sav->phy_syncctl);
6355 BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl);
6356 BWN_RF_WRITE(mac, 0x43, sav->rf0);
6357 BWN_RF_WRITE(mac, 0x7a, sav->rf1);
6358 if (!BWN_HAS_TXMAG(phy)) {
6359 tmp = sav->rf2;
6360 BWN_RF_SETMASK(mac, 0x52, 0xff0f, tmp);
6361 }
6362 BWN_WRITE_2(mac, 0x3e2, sav->reg1);
6363 if (phy->type == BWN_PHYTYPE_B &&
6364 phy->rf_ver == 0x2050 && phy->rf_rev <= 5) {
6365 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), sav->phy_cck0);
6366 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), sav->phy_cck1);
6367 }
6368 if (phy->rev >= 2) {
6369 BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, sav->phy_analogover);
6370 BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
6371 sav->phy_analogoverval);
6372 BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, sav->phy_classctl);
6373 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, sav->phy_rfover);
6374 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, sav->phy_rfoverval);
6375 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), sav->phy_cck3);
6376 BWN_PHY_WRITE(mac, BWN_PHY_CRS0, sav->phy_crs0);
6377 }
6378 if (bwn_has_hwpctl(mac)) {
6379 tmp = (sav->phy_lomask & 0xbfff);
6380 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, tmp);
6381 BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x01), sav->phy_extg);
6382 BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl_hwpctl);
6383 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x14), sav->phy_cck4);
6384 BWN_PHY_WRITE(mac, BWN_PHY_HPWR_TSSICTL, sav->phy_hpwr_tssictl);
6385 }
6386 bwn_phy_g_switch_chan(mac, sav->old_channel, 1);
6387}
6388
6389static int
6390bwn_lo_probe_loctl(struct bwn_mac *mac,
6391 struct bwn_loctl *probe, struct bwn_lo_g_sm *d)
6392{
6393 struct bwn_phy *phy = &mac->mac_phy;
6394 struct bwn_phy_g *pg = &phy->phy_g;
6395 struct bwn_loctl orig, test;
6396 struct bwn_loctl prev = { -100, -100 };
6397 static const struct bwn_loctl modifiers[] = {
6398 { 1, 1,}, { 1, 0,}, { 1, -1,}, { 0, -1,},
6399 { -1, -1,}, { -1, 0,}, { -1, 1,}, { 0, 1,}
6400 };
6401 int begin, end, lower = 0, i;
6402 uint16_t feedth;
6403
6404 if (d->curstate == 0) {
6405 begin = 1;
6406 end = 8;
6407 } else if (d->curstate % 2 == 0) {
6408 begin = d->curstate - 1;
6409 end = d->curstate + 1;
6410 } else {
6411 begin = d->curstate - 2;
6412 end = d->curstate + 2;
6413 }
6414 if (begin < 1)
6415 begin += 8;
6416 if (end > 8)
6417 end -= 8;
6418
6419 memcpy(&orig, probe, sizeof(struct bwn_loctl));
6420 i = begin;
6421 d->curstate = i;
6422 while (1) {
6423 KASSERT(i >= 1 && i <= 8, ("%s:%d: fail", __func__, __LINE__));
6424 memcpy(&test, &orig, sizeof(struct bwn_loctl));
6425 test.i += modifiers[i - 1].i * d->multipler;
6426 test.q += modifiers[i - 1].q * d->multipler;
6427 if ((test.i != prev.i || test.q != prev.q) &&
6428 (abs(test.i) <= 16 && abs(test.q) <= 16)) {
6429 bwn_lo_write(mac, &test);
6430 feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6431 pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6432 if (feedth < d->feedth) {
6433 memcpy(probe, &test,
6434 sizeof(struct bwn_loctl));
6435 lower = 1;
6436 d->feedth = feedth;
6437 if (d->nmeasure < 2 && !BWN_HAS_LOOPBACK(phy))
6438 break;
6439 }
6440 }
6441 memcpy(&prev, &test, sizeof(prev));
6442 if (i == end)
6443 break;
6444 if (i == 8)
6445 i = 1;
6446 else
6447 i++;
6448 d->curstate = i;
6449 }
6450
6451 return (lower);
6452}
6453
6454static void
6455bwn_lo_probe_sm(struct bwn_mac *mac, struct bwn_loctl *loctl, int *rxgain)
6456{
6457 struct bwn_phy *phy = &mac->mac_phy;
6458 struct bwn_phy_g *pg = &phy->phy_g;
6459 struct bwn_lo_g_sm d;
6460 struct bwn_loctl probe;
6461 int lower, repeat, cnt = 0;
6462 uint16_t feedth;
6463
6464 d.nmeasure = 0;
6465 d.multipler = 1;
6466 if (BWN_HAS_LOOPBACK(phy))
6467 d.multipler = 3;
6468
6469 memcpy(&d.loctl, loctl, sizeof(struct bwn_loctl));
6470 repeat = (BWN_HAS_LOOPBACK(phy)) ? 4 : 1;
6471
6472 do {
6473 bwn_lo_write(mac, &d.loctl);
6474 feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6475 pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6476 if (feedth < 0x258) {
6477 if (feedth >= 0x12c)
6478 *rxgain += 6;
6479 else
6480 *rxgain += 3;
6481 feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6482 pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6483 }
6484 d.feedth = feedth;
6485 d.curstate = 0;
6486 do {
6487 KASSERT(d.curstate >= 0 && d.curstate <= 8,
6488 ("%s:%d: fail", __func__, __LINE__));
6489 memcpy(&probe, &d.loctl,
6490 sizeof(struct bwn_loctl));
6491 lower = bwn_lo_probe_loctl(mac, &probe, &d);
6492 if (!lower)
6493 break;
6494 if ((probe.i == d.loctl.i) && (probe.q == d.loctl.q))
6495 break;
6496 memcpy(&d.loctl, &probe, sizeof(struct bwn_loctl));
6497 d.nmeasure++;
6498 } while (d.nmeasure < 24);
6499 memcpy(loctl, &d.loctl, sizeof(struct bwn_loctl));
6500
6501 if (BWN_HAS_LOOPBACK(phy)) {
6502 if (d.feedth > 0x1194)
6503 *rxgain -= 6;
6504 else if (d.feedth < 0x5dc)
6505 *rxgain += 3;
6506 if (cnt == 0) {
6507 if (d.feedth <= 0x5dc) {
6508 d.multipler = 1;
6509 cnt++;
6510 } else
6511 d.multipler = 2;
6512 } else if (cnt == 2)
6513 d.multipler = 1;
6514 }
6515 bwn_lo_measure_gain_values(mac, *rxgain, BWN_HAS_LOOPBACK(phy));
6516 } while (++cnt < repeat);
6517}
6518
6519static struct bwn_lo_calib *
6520bwn_lo_calibset(struct bwn_mac *mac,
6521 const struct bwn_bbatt *bbatt, const struct bwn_rfatt *rfatt)
6522{
6523 struct bwn_phy *phy = &mac->mac_phy;
6524 struct bwn_phy_g *pg = &phy->phy_g;
6525 struct bwn_loctl loctl = { 0, 0 };
6526 struct bwn_lo_calib *cal;
6527 struct bwn_lo_g_value sval = { 0 };
6528 int rxgain;
6529 uint16_t pad, reg, value;
6530
6531 sval.old_channel = phy->chan;
6532 bwn_mac_suspend(mac);
6533 bwn_lo_save(mac, &sval);
6534
6535 reg = bwn_lo_txctl_regtable(mac, &value, &pad);
6536 BWN_RF_SETMASK(mac, 0x43, 0xfff0, rfatt->att);
6537 BWN_RF_SETMASK(mac, reg, ~value, (rfatt->padmix ? value :0));
6538
6539 rxgain = (rfatt->att * 2) + (bbatt->att / 2);
6540 if (rfatt->padmix)
6541 rxgain -= pad;
6542 if (BWN_HAS_LOOPBACK(phy))
6543 rxgain += pg->pg_max_lb_gain;
6544 bwn_lo_measure_gain_values(mac, rxgain, BWN_HAS_LOOPBACK(phy));
6545 bwn_phy_g_set_bbatt(mac, bbatt->att);
6546 bwn_lo_probe_sm(mac, &loctl, &rxgain);
6547
6548 bwn_lo_restore(mac, &sval);
6549 bwn_mac_enable(mac);
6550
6551 cal = malloc(sizeof(*cal), M_DEVBUF, M_NOWAIT | M_ZERO);
6552 if (!cal) {
6553 device_printf(mac->mac_sc->sc_dev, "out of memory\n");
6554 return (NULL);
6555 }
6556 memcpy(&cal->bbatt, bbatt, sizeof(*bbatt));
6557 memcpy(&cal->rfatt, rfatt, sizeof(*rfatt));
6558 memcpy(&cal->ctl, &loctl, sizeof(loctl));
6559
6560 BWN_GETTIME(cal->calib_time);
6561
6562 return (cal);
6563}
6564
6565static struct bwn_lo_calib *
6566bwn_lo_get_calib(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
6567 const struct bwn_rfatt *rfatt)
6568{
6569 struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
6570 struct bwn_lo_calib *c;
6571
6572 TAILQ_FOREACH(c, &lo->calib_list, list) {
6573 if (!BWN_BBATTCMP(&c->bbatt, bbatt))
6574 continue;
6575 if (!BWN_RFATTCMP(&c->rfatt, rfatt))
6576 continue;
6577 return (c);
6578 }
6579
6580 c = bwn_lo_calibset(mac, bbatt, rfatt);
6581 if (!c)
6582 return (NULL);
6583 TAILQ_INSERT_TAIL(&lo->calib_list, c, list);
6584
6585 return (c);
6586}
6587
6588static void
6589bwn_phy_g_dc_lookup_init(struct bwn_mac *mac, uint8_t update)
6590{
6591 struct bwn_phy *phy = &mac->mac_phy;
6592 struct bwn_phy_g *pg = &phy->phy_g;
6593 struct bwn_softc *sc = mac->mac_sc;
6594 struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6595 const struct bwn_rfatt *rfatt;
6596 const struct bwn_bbatt *bbatt;
6597 uint64_t pvector;
6598 int i;
6599 int rf_offset, bb_offset;
6600 uint8_t changed = 0;
6601
6602 KASSERT(BWN_DC_LT_SIZE == 32, ("%s:%d: fail", __func__, __LINE__));
6603 KASSERT(lo->rfatt.len * lo->bbatt.len <= 64,
6604 ("%s:%d: fail", __func__, __LINE__));
6605
6606 pvector = lo->power_vector;
6607 if (!update && !pvector)
6608 return;
6609
6610 bwn_mac_suspend(mac);
6611
6612 for (i = 0; i < BWN_DC_LT_SIZE * 2; i++) {
6613 struct bwn_lo_calib *cal;
6614 int idx;
6615 uint16_t val;
6616
6617 if (!update && !(pvector & (((uint64_t)1ULL) << i)))
6618 continue;
6619 bb_offset = i / lo->rfatt.len;
6620 rf_offset = i % lo->rfatt.len;
6621 bbatt = &(lo->bbatt.array[bb_offset]);
6622 rfatt = &(lo->rfatt.array[rf_offset]);
6623
6624 cal = bwn_lo_calibset(mac, bbatt, rfatt);
6625 if (!cal) {
6626 device_printf(sc->sc_dev, "LO: Could not "
6627 "calibrate DC table entry\n");
6628 continue;
6629 }
6630 val = (uint8_t)(cal->ctl.q);
6631 val |= ((uint8_t)(cal->ctl.i)) << 4;
6632 free(cal, M_DEVBUF);
6633
6634 idx = i / 2;
6635 if (i % 2)
6636 lo->dc_lt[idx] = (lo->dc_lt[idx] & 0x00ff)
6637 | ((val & 0x00ff) << 8);
6638 else
6639 lo->dc_lt[idx] = (lo->dc_lt[idx] & 0xff00)
6640 | (val & 0x00ff);
6641 changed = 1;
6642 }
6643 if (changed) {
6644 for (i = 0; i < BWN_DC_LT_SIZE; i++)
6645 BWN_PHY_WRITE(mac, 0x3a0 + i, lo->dc_lt[i]);
6646 }
6647 bwn_mac_enable(mac);
6648}
6649
6650static void
6651bwn_lo_fixup_rfatt(struct bwn_rfatt *rf)
6652{
6653
6654 if (!rf->padmix)
6655 return;
6656 if ((rf->att != 1) && (rf->att != 2) && (rf->att != 3))
6657 rf->att = 4;
6658}
6659
6660static void
6661bwn_lo_g_adjust(struct bwn_mac *mac)
6662{
6663 struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
6664 struct bwn_lo_calib *cal;
6665 struct bwn_rfatt rf;
6666
6667 memcpy(&rf, &pg->pg_rfatt, sizeof(rf));
6668 bwn_lo_fixup_rfatt(&rf);
6669
6670 cal = bwn_lo_get_calib(mac, &pg->pg_bbatt, &rf);
6671 if (!cal)
6672 return;
6673 bwn_lo_write(mac, &cal->ctl);
6674}
6675
6676static void
6677bwn_lo_g_init(struct bwn_mac *mac)
6678{
6679
6680 if (!bwn_has_hwpctl(mac))
6681 return;
6682
6683 bwn_lo_get_powervector(mac);
6684 bwn_phy_g_dc_lookup_init(mac, 1);
6685}
6686
6687static void
6688bwn_mac_suspend(struct bwn_mac *mac)
6689{
6690 struct bwn_softc *sc = mac->mac_sc;
6691 int i;
6692 uint32_t tmp;
6693
6694 KASSERT(mac->mac_suspended >= 0,
6695 ("%s:%d: fail", __func__, __LINE__));
6696
6697 if (mac->mac_suspended == 0) {
6698 bwn_psctl(mac, BWN_PS_AWAKE);
6699 BWN_WRITE_4(mac, BWN_MACCTL,
6700 BWN_READ_4(mac, BWN_MACCTL)
6701 & ~BWN_MACCTL_ON);
6702 BWN_READ_4(mac, BWN_MACCTL);
6703 for (i = 35; i; i--) {
6704 tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6705 if (tmp & BWN_INTR_MAC_SUSPENDED)
6706 goto out;
6707 DELAY(10);
6708 }
6709 for (i = 40; i; i--) {
6710 tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6711 if (tmp & BWN_INTR_MAC_SUSPENDED)
6712 goto out;
6713 DELAY(1000);
6714 }
6715 device_printf(sc->sc_dev, "MAC suspend failed\n");
6716 }
6717out:
6718 mac->mac_suspended++;
6719}
6720
6721static void
6722bwn_mac_enable(struct bwn_mac *mac)
6723{
6724 struct bwn_softc *sc = mac->mac_sc;
6725 uint16_t state;
6726
6727 state = bwn_shm_read_2(mac, BWN_SHARED,
6728 BWN_SHARED_UCODESTAT);
6729 if (state != BWN_SHARED_UCODESTAT_SUSPEND &&
6730 state != BWN_SHARED_UCODESTAT_SLEEP)
6731 device_printf(sc->sc_dev, "warn: firmware state (%d)\n", state);
6732
6733 mac->mac_suspended--;
6734 KASSERT(mac->mac_suspended >= 0,
6735 ("%s:%d: fail", __func__, __LINE__));
6736 if (mac->mac_suspended == 0) {
6737 BWN_WRITE_4(mac, BWN_MACCTL,
6738 BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_ON);
6739 BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_MAC_SUSPENDED);
6740 BWN_READ_4(mac, BWN_MACCTL);
6741 BWN_READ_4(mac, BWN_INTR_REASON);
6742 bwn_psctl(mac, 0);
6743 }
6744}
6745
6746static void
6747bwn_psctl(struct bwn_mac *mac, uint32_t flags)
6748{
6749 struct bwn_softc *sc = mac->mac_sc;
6750 int i;
6751 uint16_t ucstat;
6752
6753 KASSERT(!((flags & BWN_PS_ON) && (flags & BWN_PS_OFF)),
6754 ("%s:%d: fail", __func__, __LINE__));
6755 KASSERT(!((flags & BWN_PS_AWAKE) && (flags & BWN_PS_ASLEEP)),
6756 ("%s:%d: fail", __func__, __LINE__));
6757
6758 /* XXX forcibly awake and hwps-off */
6759
6760 BWN_WRITE_4(mac, BWN_MACCTL,
6761 (BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_AWAKE) &
6762 ~BWN_MACCTL_HWPS);
6763 BWN_READ_4(mac, BWN_MACCTL);
6764 if (siba_get_revid(sc->sc_dev) >= 5) {
6765 for (i = 0; i < 100; i++) {
6766 ucstat = bwn_shm_read_2(mac, BWN_SHARED,
6767 BWN_SHARED_UCODESTAT);
6768 if (ucstat != BWN_SHARED_UCODESTAT_SLEEP)
6769 break;
6770 DELAY(10);
6771 }
6772 }
6773}
6774
6775static int16_t
6776bwn_nrssi_read(struct bwn_mac *mac, uint16_t offset)
6777{
6778
6779 BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, offset);
6780 return ((int16_t)BWN_PHY_READ(mac, BWN_PHY_NRSSI_DATA));
6781}
6782
6783static void
6784bwn_nrssi_threshold(struct bwn_mac *mac)
6785{
6786 struct bwn_phy *phy = &mac->mac_phy;
6787 struct bwn_phy_g *pg = &phy->phy_g;
6788 struct bwn_softc *sc = mac->mac_sc;
6789 int32_t a, b;
6790 int16_t tmp16;
6791 uint16_t tmpu16;
6792
6793 KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
6794
6795 if (phy->gmode && (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI)) {
6796 if (!pg->pg_aci_wlan_automatic && pg->pg_aci_enable) {
6797 a = 0x13;
6798 b = 0x12;
6799 } else {
6800 a = 0xe;
6801 b = 0x11;
6802 }
6803
6804 a = a * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6805 a += (pg->pg_nrssi[0] << 6);
6806 a += (a < 32) ? 31 : 32;
6807 a = a >> 6;
6808 a = MIN(MAX(a, -31), 31);
6809
6810 b = b * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6811 b += (pg->pg_nrssi[0] << 6);
6812 if (b < 32)
6813 b += 31;
6814 else
6815 b += 32;
6816 b = b >> 6;
6817 b = MIN(MAX(b, -31), 31);
6818
6819 tmpu16 = BWN_PHY_READ(mac, 0x048a) & 0xf000;
6820 tmpu16 |= ((uint32_t)b & 0x0000003f);
6821 tmpu16 |= (((uint32_t)a & 0x0000003f) << 6);
6822 BWN_PHY_WRITE(mac, 0x048a, tmpu16);
6823 return;
6824 }
6825
6826 tmp16 = bwn_nrssi_read(mac, 0x20);
6827 if (tmp16 >= 0x20)
6828 tmp16 -= 0x40;
6829 BWN_PHY_SETMASK(mac, 0x048a, 0xf000, (tmp16 < 3) ? 0x09eb : 0x0aed);
6830}
6831
6832static void
6833bwn_nrssi_slope_11g(struct bwn_mac *mac)
6834{
6835#define SAVE_RF_MAX 3
6836#define SAVE_PHY_COMM_MAX 4
6837#define SAVE_PHY3_MAX 8
6838 static const uint16_t save_rf_regs[SAVE_RF_MAX] =
6839 { 0x7a, 0x52, 0x43 };
6840 static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] =
6841 { 0x15, 0x5a, 0x59, 0x58 };
6842 static const uint16_t save_phy3_regs[SAVE_PHY3_MAX] = {
6843 0x002e, 0x002f, 0x080f, BWN_PHY_G_LOCTL,
6844 0x0801, 0x0060, 0x0014, 0x0478
6845 };
6846 struct bwn_phy *phy = &mac->mac_phy;
6847 struct bwn_phy_g *pg = &phy->phy_g;
6848 int32_t i, tmp32, phy3_idx = 0;
6849 uint16_t delta, tmp;
6850 uint16_t save_rf[SAVE_RF_MAX];
6851 uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
6852 uint16_t save_phy3[SAVE_PHY3_MAX];
6853 uint16_t ant_div, phy0, chan_ex;
6854 int16_t nrssi0, nrssi1;
6855
6856 KASSERT(phy->type == BWN_PHYTYPE_G,
6857 ("%s:%d: fail", __func__, __LINE__));
6858
6859 if (phy->rf_rev >= 9)
6860 return;
6861 if (phy->rf_rev == 8)
6862 bwn_nrssi_offset(mac);
6863
6864 BWN_PHY_MASK(mac, BWN_PHY_G_CRS, 0x7fff);
6865 BWN_PHY_MASK(mac, 0x0802, 0xfffc);
6866
6867 /*
6868 * Save RF/PHY registers for later restoration
6869 */
6870 ant_div = BWN_READ_2(mac, 0x03e2);
6871 BWN_WRITE_2(mac, 0x03e2, BWN_READ_2(mac, 0x03e2) | 0x8000);
6872 for (i = 0; i < SAVE_RF_MAX; ++i)
6873 save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
6874 for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6875 save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
6876
6877 phy0 = BWN_READ_2(mac, BWN_PHY0);
6878 chan_ex = BWN_READ_2(mac, BWN_CHANNEL_EXT);
6879 if (phy->rev >= 3) {
6880 for (i = 0; i < SAVE_PHY3_MAX; ++i)
6881 save_phy3[i] = BWN_PHY_READ(mac, save_phy3_regs[i]);
6882 BWN_PHY_WRITE(mac, 0x002e, 0);
6883 BWN_PHY_WRITE(mac, BWN_PHY_G_LOCTL, 0);
6884 switch (phy->rev) {
6885 case 4:
6886 case 6:
6887 case 7:
6888 BWN_PHY_SET(mac, 0x0478, 0x0100);
6889 BWN_PHY_SET(mac, 0x0801, 0x0040);
6890 break;
6891 case 3:
6892 case 5:
6893 BWN_PHY_MASK(mac, 0x0801, 0xffbf);
6894 break;
6895 }
6896 BWN_PHY_SET(mac, 0x0060, 0x0040);
6897 BWN_PHY_SET(mac, 0x0014, 0x0200);
6898 }
6899 /*
6900 * Calculate nrssi0
6901 */
6902 BWN_RF_SET(mac, 0x007a, 0x0070);
6903 bwn_set_all_gains(mac, 0, 8, 0);
6904 BWN_RF_MASK(mac, 0x007a, 0x00f7);
6905 if (phy->rev >= 2) {
6906 BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0030);
6907 BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0010);
6908 }
6909 BWN_RF_SET(mac, 0x007a, 0x0080);
6910 DELAY(20);
6911
6912 nrssi0 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6913 if (nrssi0 >= 0x0020)
6914 nrssi0 -= 0x0040;
6915
6916 /*
6917 * Calculate nrssi1
6918 */
6919 BWN_RF_MASK(mac, 0x007a, 0x007f);
6920 if (phy->rev >= 2)
6921 BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
6922
6923 BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
6924 BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000);
6925 BWN_RF_SET(mac, 0x007a, 0x000f);
6926 BWN_PHY_WRITE(mac, 0x0015, 0xf330);
6927 if (phy->rev >= 2) {
6928 BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0020);
6929 BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0020);
6930 }
6931
6932 bwn_set_all_gains(mac, 3, 0, 1);
6933 if (phy->rf_rev == 8) {
6934 BWN_RF_WRITE(mac, 0x0043, 0x001f);
6935 } else {
6936 tmp = BWN_RF_READ(mac, 0x0052) & 0xff0f;
6937 BWN_RF_WRITE(mac, 0x0052, tmp | 0x0060);
6938 tmp = BWN_RF_READ(mac, 0x0043) & 0xfff0;
6939 BWN_RF_WRITE(mac, 0x0043, tmp | 0x0009);
6940 }
6941 BWN_PHY_WRITE(mac, 0x005a, 0x0480);
6942 BWN_PHY_WRITE(mac, 0x0059, 0x0810);
6943 BWN_PHY_WRITE(mac, 0x0058, 0x000d);
6944 DELAY(20);
6945 nrssi1 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6946
6947 /*
6948 * Install calculated narrow RSSI values
6949 */
6950 if (nrssi1 >= 0x0020)
6951 nrssi1 -= 0x0040;
6952 if (nrssi0 == nrssi1)
6953 pg->pg_nrssi_slope = 0x00010000;
6954 else
6955 pg->pg_nrssi_slope = 0x00400000 / (nrssi0 - nrssi1);
6956 if (nrssi0 >= -4) {
6957 pg->pg_nrssi[0] = nrssi1;
6958 pg->pg_nrssi[1] = nrssi0;
6959 }
6960
6961 /*
6962 * Restore saved RF/PHY registers
6963 */
6964 if (phy->rev >= 3) {
6965 for (phy3_idx = 0; phy3_idx < 4; ++phy3_idx) {
6966 BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
6967 save_phy3[phy3_idx]);
6968 }
6969 }
6970 if (phy->rev >= 2) {
6971 BWN_PHY_MASK(mac, 0x0812, 0xffcf);
6972 BWN_PHY_MASK(mac, 0x0811, 0xffcf);
6973 }
6974
6975 for (i = 0; i < SAVE_RF_MAX; ++i)
6976 BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
6977
6978 BWN_WRITE_2(mac, 0x03e2, ant_div);
6979 BWN_WRITE_2(mac, 0x03e6, phy0);
6980 BWN_WRITE_2(mac, BWN_CHANNEL_EXT, chan_ex);
6981
6982 for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6983 BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
6984
6985 bwn_spu_workaround(mac, phy->chan);
6986 BWN_PHY_SET(mac, 0x0802, (0x0001 | 0x0002));
6987 bwn_set_original_gains(mac);
6988 BWN_PHY_SET(mac, BWN_PHY_G_CRS, 0x8000);
6989 if (phy->rev >= 3) {
6990 for (; phy3_idx < SAVE_PHY3_MAX; ++phy3_idx) {
6991 BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
6992 save_phy3[phy3_idx]);
6993 }
6994 }
6995
6996 delta = 0x1f - pg->pg_nrssi[0];
6997 for (i = 0; i < 64; i++) {
6998 tmp32 = (((i - delta) * pg->pg_nrssi_slope) / 0x10000) + 0x3a;
6999 tmp32 = MIN(MAX(tmp32, 0), 0x3f);
7000 pg->pg_nrssi_lt[i] = tmp32;
7001 }
7002
7003 bwn_nrssi_threshold(mac);
7004#undef SAVE_RF_MAX
7005#undef SAVE_PHY_COMM_MAX
7006#undef SAVE_PHY3_MAX
7007}
7008
7009static void
7010bwn_nrssi_offset(struct bwn_mac *mac)
7011{
7012#define SAVE_RF_MAX 2
7013#define SAVE_PHY_COMM_MAX 10
7014#define SAVE_PHY6_MAX 8
7015 static const uint16_t save_rf_regs[SAVE_RF_MAX] =
7016 { 0x7a, 0x43 };
7017 static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] = {
7018 0x0001, 0x0811, 0x0812, 0x0814,
7019 0x0815, 0x005a, 0x0059, 0x0058,
7020 0x000a, 0x0003
7021 };
7022 static const uint16_t save_phy6_regs[SAVE_PHY6_MAX] = {
7023 0x002e, 0x002f, 0x080f, 0x0810,
7024 0x0801, 0x0060, 0x0014, 0x0478
7025 };
7026 struct bwn_phy *phy = &mac->mac_phy;
7027 int i, phy6_idx = 0;
7028 uint16_t save_rf[SAVE_RF_MAX];
7029 uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
7030 uint16_t save_phy6[SAVE_PHY6_MAX];
7031 int16_t nrssi;
7032 uint16_t saved = 0xffff;
7033
7034 for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
7035 save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
7036 for (i = 0; i < SAVE_RF_MAX; ++i)
7037 save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
7038
7039 BWN_PHY_MASK(mac, 0x0429, 0x7fff);
7040 BWN_PHY_SETMASK(mac, 0x0001, 0x3fff, 0x4000);
7041 BWN_PHY_SET(mac, 0x0811, 0x000c);
7042 BWN_PHY_SETMASK(mac, 0x0812, 0xfff3, 0x0004);
7043 BWN_PHY_MASK(mac, 0x0802, ~(0x1 | 0x2));
7044 if (phy->rev >= 6) {
7045 for (i = 0; i < SAVE_PHY6_MAX; ++i)
7046 save_phy6[i] = BWN_PHY_READ(mac, save_phy6_regs[i]);
7047
7048 BWN_PHY_WRITE(mac, 0x002e, 0);
7049 BWN_PHY_WRITE(mac, 0x002f, 0);
7050 BWN_PHY_WRITE(mac, 0x080f, 0);
7051 BWN_PHY_WRITE(mac, 0x0810, 0);
7052 BWN_PHY_SET(mac, 0x0478, 0x0100);
7053 BWN_PHY_SET(mac, 0x0801, 0x0040);
7054 BWN_PHY_SET(mac, 0x0060, 0x0040);
7055 BWN_PHY_SET(mac, 0x0014, 0x0200);
7056 }
7057 BWN_RF_SET(mac, 0x007a, 0x0070);
7058 BWN_RF_SET(mac, 0x007a, 0x0080);
7059 DELAY(30);
7060
7061 nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
7062 if (nrssi >= 0x20)
7063 nrssi -= 0x40;
7064 if (nrssi == 31) {
7065 for (i = 7; i >= 4; i--) {
7066 BWN_RF_WRITE(mac, 0x007b, i);
7067 DELAY(20);
7068 nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) &
7069 0x003f);
7070 if (nrssi >= 0x20)
7071 nrssi -= 0x40;
7072 if (nrssi < 31 && saved == 0xffff)
7073 saved = i;
7074 }
7075 if (saved == 0xffff)
7076 saved = 4;
7077 } else {
7078 BWN_RF_MASK(mac, 0x007a, 0x007f);
7079 if (phy->rev != 1) {
7080 BWN_PHY_SET(mac, 0x0814, 0x0001);
7081 BWN_PHY_MASK(mac, 0x0815, 0xfffe);
7082 }
7083 BWN_PHY_SET(mac, 0x0811, 0x000c);
7084 BWN_PHY_SET(mac, 0x0812, 0x000c);
7085 BWN_PHY_SET(mac, 0x0811, 0x0030);
7086 BWN_PHY_SET(mac, 0x0812, 0x0030);
7087 BWN_PHY_WRITE(mac, 0x005a, 0x0480);
7088 BWN_PHY_WRITE(mac, 0x0059, 0x0810);
7089 BWN_PHY_WRITE(mac, 0x0058, 0x000d);
7090 if (phy->rev == 0)
7091 BWN_PHY_WRITE(mac, 0x0003, 0x0122);
7092 else
7093 BWN_PHY_SET(mac, 0x000a, 0x2000);
7094 if (phy->rev != 1) {
7095 BWN_PHY_SET(mac, 0x0814, 0x0004);
7096 BWN_PHY_MASK(mac, 0x0815, 0xfffb);
7097 }
7098 BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
7099 BWN_RF_SET(mac, 0x007a, 0x000f);
7100 bwn_set_all_gains(mac, 3, 0, 1);
7101 BWN_RF_SETMASK(mac, 0x0043, 0x00f0, 0x000f);
7102 DELAY(30);
7103 nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
7104 if (nrssi >= 0x20)
7105 nrssi -= 0x40;
7106 if (nrssi == -32) {
7107 for (i = 0; i < 4; i++) {
7108 BWN_RF_WRITE(mac, 0x007b, i);
7109 DELAY(20);
7110 nrssi = (int16_t)((BWN_PHY_READ(mac,
7111 0x047f) >> 8) & 0x003f);
7112 if (nrssi >= 0x20)
7113 nrssi -= 0x40;
7114 if (nrssi > -31 && saved == 0xffff)
7115 saved = i;
7116 }
7117 if (saved == 0xffff)
7118 saved = 3;
7119 } else
7120 saved = 0;
7121 }
7122 BWN_RF_WRITE(mac, 0x007b, saved);
7123
7124 /*
7125 * Restore saved RF/PHY registers
7126 */
7127 if (phy->rev >= 6) {
7128 for (phy6_idx = 0; phy6_idx < 4; ++phy6_idx) {
7129 BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
7130 save_phy6[phy6_idx]);
7131 }
7132 }
7133 if (phy->rev != 1) {
7134 for (i = 3; i < 5; i++)
7135 BWN_PHY_WRITE(mac, save_phy_comm_regs[i],
7136 save_phy_comm[i]);
7137 }
7138 for (i = 5; i < SAVE_PHY_COMM_MAX; i++)
7139 BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
7140
7141 for (i = SAVE_RF_MAX - 1; i >= 0; --i)
7142 BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
7143
7144 BWN_PHY_WRITE(mac, 0x0802, BWN_PHY_READ(mac, 0x0802) | 0x1 | 0x2);
7145 BWN_PHY_SET(mac, 0x0429, 0x8000);
7146 bwn_set_original_gains(mac);
7147 if (phy->rev >= 6) {
7148 for (; phy6_idx < SAVE_PHY6_MAX; ++phy6_idx) {
7149 BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
7150 save_phy6[phy6_idx]);
7151 }
7152 }
7153
7154 BWN_PHY_WRITE(mac, save_phy_comm_regs[0], save_phy_comm[0]);
7155 BWN_PHY_WRITE(mac, save_phy_comm_regs[2], save_phy_comm[2]);
7156 BWN_PHY_WRITE(mac, save_phy_comm_regs[1], save_phy_comm[1]);
7157}
7158
7159static void
7160bwn_set_all_gains(struct bwn_mac *mac, int16_t first, int16_t second,
7161 int16_t third)
7162{
7163 struct bwn_phy *phy = &mac->mac_phy;
7164 uint16_t i;
7165 uint16_t start = 0x08, end = 0x18;
7166 uint16_t tmp;
7167 uint16_t table;
7168
7169 if (phy->rev <= 1) {
7170 start = 0x10;
7171 end = 0x20;
7172 }
7173
7174 table = BWN_OFDMTAB_GAINX;
7175 if (phy->rev <= 1)
7176 table = BWN_OFDMTAB_GAINX_R1;
7177 for (i = 0; i < 4; i++)
7178 bwn_ofdmtab_write_2(mac, table, i, first);
7179
7180 for (i = start; i < end; i++)
7181 bwn_ofdmtab_write_2(mac, table, i, second);
7182
7183 if (third != -1) {
7184 tmp = ((uint16_t) third << 14) | ((uint16_t) third << 6);
7185 BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, tmp);
7186 BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, tmp);
7187 BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, tmp);
7188 }
7189 bwn_dummy_transmission(mac, 0, 1);
7190}
7191
7192static void
7193bwn_set_original_gains(struct bwn_mac *mac)
7194{
7195 struct bwn_phy *phy = &mac->mac_phy;
7196 uint16_t i, tmp;
7197 uint16_t table;
7198 uint16_t start = 0x0008, end = 0x0018;
7199
7200 if (phy->rev <= 1) {
7201 start = 0x0010;
7202 end = 0x0020;
7203 }
7204
7205 table = BWN_OFDMTAB_GAINX;
7206 if (phy->rev <= 1)
7207 table = BWN_OFDMTAB_GAINX_R1;
7208 for (i = 0; i < 4; i++) {
7209 tmp = (i & 0xfffc);
7210 tmp |= (i & 0x0001) << 1;
7211 tmp |= (i & 0x0002) >> 1;
7212
7213 bwn_ofdmtab_write_2(mac, table, i, tmp);
7214 }
7215
7216 for (i = start; i < end; i++)
7217 bwn_ofdmtab_write_2(mac, table, i, i - start);
7218
7219 BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, 0x4040);
7220 BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, 0x4040);
7221 BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, 0x4000);
7222 bwn_dummy_transmission(mac, 0, 1);
7223}
7224
7225static void
7226bwn_phy_hwpctl_init(struct bwn_mac *mac)
7227{
7228 struct bwn_phy *phy = &mac->mac_phy;
7229 struct bwn_phy_g *pg = &phy->phy_g;
7230 struct bwn_rfatt old_rfatt, rfatt;
7231 struct bwn_bbatt old_bbatt, bbatt;
7232 struct bwn_softc *sc = mac->mac_sc;
7233 uint8_t old_txctl = 0;
7234
7235 KASSERT(phy->type == BWN_PHYTYPE_G,
7236 ("%s:%d: fail", __func__, __LINE__));
7237
7238 if ((siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM) &&
7239 (siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306))
7240 return;
7241
7242 BWN_PHY_WRITE(mac, 0x0028, 0x8018);
7243
7244 BWN_WRITE_2(mac, BWN_PHY0, BWN_READ_2(mac, BWN_PHY0) & 0xffdf);
7245
7246 if (!phy->gmode)
7247 return;
7248 bwn_hwpctl_early_init(mac);
7249 if (pg->pg_curtssi == 0) {
7250 if (phy->rf_ver == 0x2050 && phy->analog == 0) {
7251 BWN_RF_SETMASK(mac, 0x0076, 0x00f7, 0x0084);
7252 } else {
7253 memcpy(&old_rfatt, &pg->pg_rfatt, sizeof(old_rfatt));
7254 memcpy(&old_bbatt, &pg->pg_bbatt, sizeof(old_bbatt));
7255 old_txctl = pg->pg_txctl;
7256
7257 bbatt.att = 11;
7258 if (phy->rf_rev == 8) {
7259 rfatt.att = 15;
7260 rfatt.padmix = 1;
7261 } else {
7262 rfatt.att = 9;
7263 rfatt.padmix = 0;
7264 }
7265 bwn_phy_g_set_txpwr_sub(mac, &bbatt, &rfatt, 0);
7266 }
7267 bwn_dummy_transmission(mac, 0, 1);
7268 pg->pg_curtssi = BWN_PHY_READ(mac, BWN_PHY_TSSI);
7269 if (phy->rf_ver == 0x2050 && phy->analog == 0)
7270 BWN_RF_MASK(mac, 0x0076, 0xff7b);
7271 else
7272 bwn_phy_g_set_txpwr_sub(mac, &old_bbatt,
7273 &old_rfatt, old_txctl);
7274 }
7275 bwn_hwpctl_init_gphy(mac);
7276
7277 /* clear TSSI */
7278 bwn_shm_write_2(mac, BWN_SHARED, 0x0058, 0x7f7f);
7279 bwn_shm_write_2(mac, BWN_SHARED, 0x005a, 0x7f7f);
7280 bwn_shm_write_2(mac, BWN_SHARED, 0x0070, 0x7f7f);
7281 bwn_shm_write_2(mac, BWN_SHARED, 0x0072, 0x7f7f);
7282}
7283
7284static void
7285bwn_hwpctl_early_init(struct bwn_mac *mac)
7286{
7287 struct bwn_phy *phy = &mac->mac_phy;
7288
7289 if (!bwn_has_hwpctl(mac)) {
7290 BWN_PHY_WRITE(mac, 0x047a, 0xc111);
7291 return;
7292 }
7293
7294 BWN_PHY_MASK(mac, 0x0036, 0xfeff);
7295 BWN_PHY_WRITE(mac, 0x002f, 0x0202);
7296 BWN_PHY_SET(mac, 0x047c, 0x0002);
7297 BWN_PHY_SET(mac, 0x047a, 0xf000);
7298 if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
7299 BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7300 BWN_PHY_SET(mac, 0x005d, 0x8000);
7301 BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7302 BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7303 BWN_PHY_SET(mac, 0x0036, 0x0400);
7304 } else {
7305 BWN_PHY_SET(mac, 0x0036, 0x0200);
7306 BWN_PHY_SET(mac, 0x0036, 0x0400);
7307 BWN_PHY_MASK(mac, 0x005d, 0x7fff);
7308 BWN_PHY_MASK(mac, 0x004f, 0xfffe);
7309 BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7310 BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7311 BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7312 }
7313}
7314
7315static void
7316bwn_hwpctl_init_gphy(struct bwn_mac *mac)
7317{
7318 struct bwn_phy *phy = &mac->mac_phy;
7319 struct bwn_phy_g *pg = &phy->phy_g;
7320 struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7321 int i;
7322 uint16_t nr_written = 0, tmp, value;
7323 uint8_t rf, bb;
7324
7325 if (!bwn_has_hwpctl(mac)) {
7326 bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_HW_POWERCTL);
7327 return;
7328 }
7329
7330 BWN_PHY_SETMASK(mac, 0x0036, 0xffc0,
7331 (pg->pg_idletssi - pg->pg_curtssi));
7332 BWN_PHY_SETMASK(mac, 0x0478, 0xff00,
7333 (pg->pg_idletssi - pg->pg_curtssi));
7334
7335 for (i = 0; i < 32; i++)
7336 bwn_ofdmtab_write_2(mac, 0x3c20, i, pg->pg_tssi2dbm[i]);
7337 for (i = 32; i < 64; i++)
7338 bwn_ofdmtab_write_2(mac, 0x3c00, i - 32, pg->pg_tssi2dbm[i]);
7339 for (i = 0; i < 64; i += 2) {
7340 value = (uint16_t) pg->pg_tssi2dbm[i];
7341 value |= ((uint16_t) pg->pg_tssi2dbm[i + 1]) << 8;
7342 BWN_PHY_WRITE(mac, 0x380 + (i / 2), value);
7343 }
7344
7345 for (rf = 0; rf < lo->rfatt.len; rf++) {
7346 for (bb = 0; bb < lo->bbatt.len; bb++) {
7347 if (nr_written >= 0x40)
7348 return;
7349 tmp = lo->bbatt.array[bb].att;
7350 tmp <<= 8;
7351 if (phy->rf_rev == 8)
7352 tmp |= 0x50;
7353 else
7354 tmp |= 0x40;
7355 tmp |= lo->rfatt.array[rf].att;
7356 BWN_PHY_WRITE(mac, 0x3c0 + nr_written, tmp);
7357 nr_written++;
7358 }
7359 }
7360
7361 BWN_PHY_MASK(mac, 0x0060, 0xffbf);
7362 BWN_PHY_WRITE(mac, 0x0014, 0x0000);
7363
7364 KASSERT(phy->rev >= 6, ("%s:%d: fail", __func__, __LINE__));
7365 BWN_PHY_SET(mac, 0x0478, 0x0800);
7366 BWN_PHY_MASK(mac, 0x0478, 0xfeff);
7367 BWN_PHY_MASK(mac, 0x0801, 0xffbf);
7368
7369 bwn_phy_g_dc_lookup_init(mac, 1);
7370 bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_HW_POWERCTL);
7371}
7372
7373static void
7374bwn_phy_g_switch_chan(struct bwn_mac *mac, int channel, uint8_t spu)
7375{
7376 struct bwn_softc *sc = mac->mac_sc;
7377
7378 if (spu != 0)
7379 bwn_spu_workaround(mac, channel);
7380
7381 BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7382
7383 if (channel == 14) {
7384 if (siba_sprom_get_ccode(sc->sc_dev) == SIBA_CCODE_JAPAN)
7385 bwn_hf_write(mac,
7386 bwn_hf_read(mac) & ~BWN_HF_JAPAN_CHAN14_OFF);
7387 else
7388 bwn_hf_write(mac,
7389 bwn_hf_read(mac) | BWN_HF_JAPAN_CHAN14_OFF);
7390 BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7391 BWN_READ_2(mac, BWN_CHANNEL_EXT) | (1 << 11));
7392 return;
7393 }
7394
7395 BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7396 BWN_READ_2(mac, BWN_CHANNEL_EXT) & 0xf7bf);
7397}
7398
7399static uint16_t
7400bwn_phy_g_chan2freq(uint8_t channel)
7401{
7402 static const uint8_t bwn_phy_g_rf_channels[] = BWN_PHY_G_RF_CHANNELS;
7403
7404 KASSERT(channel >= 1 && channel <= 14,
7405 ("%s:%d: fail", __func__, __LINE__));
7406
7407 return (bwn_phy_g_rf_channels[channel - 1]);
7408}
7409
7410static void
7411bwn_phy_g_set_txpwr_sub(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
7412 const struct bwn_rfatt *rfatt, uint8_t txctl)
7413{
7414 struct bwn_phy *phy = &mac->mac_phy;
7415 struct bwn_phy_g *pg = &phy->phy_g;
7416 struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7417 uint16_t bb, rf;
7418 uint16_t tx_bias, tx_magn;
7419
7420 bb = bbatt->att;
7421 rf = rfatt->att;
7422 tx_bias = lo->tx_bias;
7423 tx_magn = lo->tx_magn;
7424 if (tx_bias == 0xff)
7425 tx_bias = 0;
7426
7427 pg->pg_txctl = txctl;
7428 memmove(&pg->pg_rfatt, rfatt, sizeof(*rfatt));
7429 pg->pg_rfatt.padmix = (txctl & BWN_TXCTL_TXMIX) ? 1 : 0;
7430 memmove(&pg->pg_bbatt, bbatt, sizeof(*bbatt));
7431 bwn_phy_g_set_bbatt(mac, bb);
7432 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RADIO_ATT, rf);
7433 if (phy->rf_ver == 0x2050 && phy->rf_rev == 8)
7434 BWN_RF_WRITE(mac, 0x43, (rf & 0x000f) | (txctl & 0x0070));
7435 else {
7436 BWN_RF_SETMASK(mac, 0x43, 0xfff0, (rf & 0x000f));
7437 BWN_RF_SETMASK(mac, 0x52, ~0x0070, (txctl & 0x0070));
7438 }
7439 if (BWN_HAS_TXMAG(phy))
7440 BWN_RF_WRITE(mac, 0x52, tx_magn | tx_bias);
7441 else
7442 BWN_RF_SETMASK(mac, 0x52, 0xfff0, (tx_bias & 0x000f));
7443 bwn_lo_g_adjust(mac);
7444}
7445
7446static void
7447bwn_phy_g_set_bbatt(struct bwn_mac *mac,
7448 uint16_t bbatt)
7449{
7450 struct bwn_phy *phy = &mac->mac_phy;
7451
7452 if (phy->analog == 0) {
7453 BWN_WRITE_2(mac, BWN_PHY0,
7454 (BWN_READ_2(mac, BWN_PHY0) & 0xfff0) | bbatt);
7455 return;
7456 }
7457 if (phy->analog > 1) {
7458 BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xffc3, bbatt << 2);
7459 return;
7460 }
7461 BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xff87, bbatt << 3);
7462}
7463
7464static uint16_t
7465bwn_rf_2050_rfoverval(struct bwn_mac *mac, uint16_t reg, uint32_t lpd)
7466{
7467 struct bwn_phy *phy = &mac->mac_phy;
7468 struct bwn_phy_g *pg = &phy->phy_g;
7469 struct bwn_softc *sc = mac->mac_sc;
7470 int max_lb_gain;
7471 uint16_t extlna;
7472 uint16_t i;
7473
7474 if (phy->gmode == 0)
7475 return (0);
7476
7477 if (BWN_HAS_LOOPBACK(phy)) {
7478 max_lb_gain = pg->pg_max_lb_gain;
7479 max_lb_gain += (phy->rf_rev == 8) ? 0x3e : 0x26;
7480 if (max_lb_gain >= 0x46) {
7481 extlna = 0x3000;
7482 max_lb_gain -= 0x46;
7483 } else if (max_lb_gain >= 0x3a) {
7484 extlna = 0x1000;
7485 max_lb_gain -= 0x3a;
7486 } else if (max_lb_gain >= 0x2e) {
7487 extlna = 0x2000;
7488 max_lb_gain -= 0x2e;
7489 } else {
7490 extlna = 0;
7491 max_lb_gain -= 0x10;
7492 }
7493
7494 for (i = 0; i < 16; i++) {
7495 max_lb_gain -= (i * 6);
7496 if (max_lb_gain < 6)
7497 break;
7498 }
7499
7500 if ((phy->rev < 7) ||
7501 !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA)) {
7502 if (reg == BWN_PHY_RFOVER) {
7503 return (0x1b3);
7504 } else if (reg == BWN_PHY_RFOVERVAL) {
7505 extlna |= (i << 8);
7506 switch (lpd) {
7507 case BWN_LPD(0, 1, 1):
7508 return (0x0f92);
7509 case BWN_LPD(0, 0, 1):
7510 case BWN_LPD(1, 0, 1):
7511 return (0x0092 | extlna);
7512 case BWN_LPD(1, 0, 0):
7513 return (0x0093 | extlna);
7514 }
7515 KASSERT(0 == 1,
7516 ("%s:%d: fail", __func__, __LINE__));
7517 }
7518 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7519 } else {
7520 if (reg == BWN_PHY_RFOVER)
7521 return (0x9b3);
7522 if (reg == BWN_PHY_RFOVERVAL) {
7523 if (extlna)
7524 extlna |= 0x8000;
7525 extlna |= (i << 8);
7526 switch (lpd) {
7527 case BWN_LPD(0, 1, 1):
7528 return (0x8f92);
7529 case BWN_LPD(0, 0, 1):
7530 return (0x8092 | extlna);
7531 case BWN_LPD(1, 0, 1):
7532 return (0x2092 | extlna);
7533 case BWN_LPD(1, 0, 0):
7534 return (0x2093 | extlna);
7535 }
7536 KASSERT(0 == 1,
7537 ("%s:%d: fail", __func__, __LINE__));
7538 }
7539 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7540 }
7541 return (0);
7542 }
7543
7544 if ((phy->rev < 7) ||
7545 !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA)) {
7546 if (reg == BWN_PHY_RFOVER) {
7547 return (0x1b3);
7548 } else if (reg == BWN_PHY_RFOVERVAL) {
7549 switch (lpd) {
7550 case BWN_LPD(0, 1, 1):
7551 return (0x0fb2);
7552 case BWN_LPD(0, 0, 1):
7553 return (0x00b2);
7554 case BWN_LPD(1, 0, 1):
7555 return (0x30b2);
7556 case BWN_LPD(1, 0, 0):
7557 return (0x30b3);
7558 }
7559 KASSERT(0 == 1,
7560 ("%s:%d: fail", __func__, __LINE__));
7561 }
7562 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7563 } else {
7564 if (reg == BWN_PHY_RFOVER) {
7565 return (0x9b3);
7566 } else if (reg == BWN_PHY_RFOVERVAL) {
7567 switch (lpd) {
7568 case BWN_LPD(0, 1, 1):
7569 return (0x8fb2);
7570 case BWN_LPD(0, 0, 1):
7571 return (0x80b2);
7572 case BWN_LPD(1, 0, 1):
7573 return (0x20b2);
7574 case BWN_LPD(1, 0, 0):
7575 return (0x20b3);
7576 }
7577 KASSERT(0 == 1,
7578 ("%s:%d: fail", __func__, __LINE__));
7579 }
7580 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7581 }
7582 return (0);
7583}
7584
7585static void
7586bwn_spu_workaround(struct bwn_mac *mac, uint8_t channel)
7587{
7588
7589 if (mac->mac_phy.rf_ver != 0x2050 || mac->mac_phy.rf_rev >= 6)
7590 return;
7591 BWN_WRITE_2(mac, BWN_CHANNEL, (channel <= 10) ?
7592 bwn_phy_g_chan2freq(channel + 4) : bwn_phy_g_chan2freq(1));
7593 DELAY(1000);
7594 BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7595}
7596
7597static int
7598bwn_fw_gets(struct bwn_mac *mac, enum bwn_fwtype type)
7599{
7600 struct bwn_softc *sc = mac->mac_sc;
7601 struct bwn_fw *fw = &mac->mac_fw;
7602 const uint8_t rev = siba_get_revid(sc->sc_dev);
7603 const char *filename;
7604 uint32_t high;
7605 int error;
7606
7607 /* microcode */
7608 if (rev >= 5 && rev <= 10)
7609 filename = "ucode5";
7610 else if (rev >= 11 && rev <= 12)
7611 filename = "ucode11";
7612 else if (rev == 13)
7613 filename = "ucode13";
7614 else if (rev == 14)
7615 filename = "ucode14";
7616 else if (rev >= 15)
7617 filename = "ucode15";
7618 else {
7619 device_printf(sc->sc_dev, "no ucode for rev %d\n", rev);
7620 bwn_release_firmware(mac);
7621 return (EOPNOTSUPP);
7622 }
7623 error = bwn_fw_get(mac, type, filename, &fw->ucode);
7624 if (error) {
7625 bwn_release_firmware(mac);
7626 return (error);
7627 }
7628
7629 /* PCM */
7630 KASSERT(fw->no_pcmfile == 0, ("%s:%d fail", __func__, __LINE__));
7631 if (rev >= 5 && rev <= 10) {
7632 error = bwn_fw_get(mac, type, "pcm5", &fw->pcm);
7633 if (error == ENOENT)
7634 fw->no_pcmfile = 1;
7635 else if (error) {
7636 bwn_release_firmware(mac);
7637 return (error);
7638 }
7639 } else if (rev < 11) {
7640 device_printf(sc->sc_dev, "no PCM for rev %d\n", rev);
7641 return (EOPNOTSUPP);
7642 }
7643
7644 /* initvals */
7645 high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH);
7646 switch (mac->mac_phy.type) {
7647 case BWN_PHYTYPE_A:
7648 if (rev < 5 || rev > 10)
7649 goto fail1;
7650 if (high & BWN_TGSHIGH_HAVE_2GHZ)
7651 filename = "a0g1initvals5";
7652 else
7653 filename = "a0g0initvals5";
7654 break;
7655 case BWN_PHYTYPE_G:
7656 if (rev >= 5 && rev <= 10)
7657 filename = "b0g0initvals5";
7658 else if (rev >= 13)
7659 filename = "b0g0initvals13";
7660 else
7661 goto fail1;
7662 break;
7663 case BWN_PHYTYPE_LP:
7664 if (rev == 13)
7665 filename = "lp0initvals13";
7666 else if (rev == 14)
7667 filename = "lp0initvals14";
7668 else if (rev >= 15)
7669 filename = "lp0initvals15";
7670 else
7671 goto fail1;
7672 break;
7673 case BWN_PHYTYPE_N:
7674 if (rev >= 11 && rev <= 12)
7675 filename = "n0initvals11";
7676 else
7677 goto fail1;
7678 break;
7679 default:
7680 goto fail1;
7681 }
7682 error = bwn_fw_get(mac, type, filename, &fw->initvals);
7683 if (error) {
7684 bwn_release_firmware(mac);
7685 return (error);
7686 }
7687
7688 /* bandswitch initvals */
7689 switch (mac->mac_phy.type) {
7690 case BWN_PHYTYPE_A:
7691 if (rev >= 5 && rev <= 10) {
7692 if (high & BWN_TGSHIGH_HAVE_2GHZ)
7693 filename = "a0g1bsinitvals5";
7694 else
7695 filename = "a0g0bsinitvals5";
7696 } else if (rev >= 11)
7697 filename = NULL;
7698 else
7699 goto fail1;
7700 break;
7701 case BWN_PHYTYPE_G:
7702 if (rev >= 5 && rev <= 10)
7703 filename = "b0g0bsinitvals5";
7704 else if (rev >= 11)
7705 filename = NULL;
7706 else
7707 goto fail1;
7708 break;
7709 case BWN_PHYTYPE_LP:
7710 if (rev == 13)
7711 filename = "lp0bsinitvals13";
7712 else if (rev == 14)
7713 filename = "lp0bsinitvals14";
7714 else if (rev >= 15)
7715 filename = "lp0bsinitvals15";
7716 else
7717 goto fail1;
7718 break;
7719 case BWN_PHYTYPE_N:
7720 if (rev >= 11 && rev <= 12)
7721 filename = "n0bsinitvals11";
7722 else
7723 goto fail1;
7724 break;
7725 default:
7726 goto fail1;
7727 }
7728 error = bwn_fw_get(mac, type, filename, &fw->initvals_band);
7729 if (error) {
7730 bwn_release_firmware(mac);
7731 return (error);
7732 }
7733 return (0);
7734fail1:
7735 device_printf(sc->sc_dev, "no INITVALS for rev %d\n", rev);
7736 bwn_release_firmware(mac);
7737 return (EOPNOTSUPP);
7738}
7739
7740static int
7741bwn_fw_get(struct bwn_mac *mac, enum bwn_fwtype type,
7742 const char *name, struct bwn_fwfile *bfw)
7743{
7744 const struct bwn_fwhdr *hdr;
7745 struct bwn_softc *sc = mac->mac_sc;
7746 const struct firmware *fw;
7747 char namebuf[64];
7748
7749 if (name == NULL) {
7750 bwn_do_release_fw(bfw);
7751 return (0);
7752 }
7753 if (bfw->filename != NULL) {
7754 if (bfw->type == type && (strcmp(bfw->filename, name) == 0))
7755 return (0);
7756 bwn_do_release_fw(bfw);
7757 }
7758
7759 snprintf(namebuf, sizeof(namebuf), "bwn%s_v4_%s%s",
7760 (type == BWN_FWTYPE_OPENSOURCE) ? "-open" : "",
7761 (mac->mac_phy.type == BWN_PHYTYPE_LP) ? "lp_" : "", name);
7762 /* XXX Sleeping on "fwload" with the non-sleepable locks held */
7763 fw = firmware_get(namebuf);
7764 if (fw == NULL) {
7765 device_printf(sc->sc_dev, "the fw file(%s) not found\n",
7766 namebuf);
7767 return (ENOENT);
7768 }
7769 if (fw->datasize < sizeof(struct bwn_fwhdr))
7770 goto fail;
7771 hdr = (const struct bwn_fwhdr *)(fw->data);
7772 switch (hdr->type) {
7773 case BWN_FWTYPE_UCODE:
7774 case BWN_FWTYPE_PCM:
7775 if (be32toh(hdr->size) !=
7776 (fw->datasize - sizeof(struct bwn_fwhdr)))
7777 goto fail;
7778 /* FALLTHROUGH */
7779 case BWN_FWTYPE_IV:
7780 if (hdr->ver != 1)
7781 goto fail;
7782 break;
7783 default:
7784 goto fail;
7785 }
7786 bfw->filename = name;
7787 bfw->fw = fw;
7788 bfw->type = type;
7789 return (0);
7790fail:
7791 device_printf(sc->sc_dev, "the fw file(%s) format error\n", namebuf);
7792 if (fw != NULL)
7793 firmware_put(fw, FIRMWARE_UNLOAD);
7794 return (EPROTO);
7795}
7796
7797static void
7798bwn_release_firmware(struct bwn_mac *mac)
7799{
7800
7801 bwn_do_release_fw(&mac->mac_fw.ucode);
7802 bwn_do_release_fw(&mac->mac_fw.pcm);
7803 bwn_do_release_fw(&mac->mac_fw.initvals);
7804 bwn_do_release_fw(&mac->mac_fw.initvals_band);
7805}
7806
7807static void
7808bwn_do_release_fw(struct bwn_fwfile *bfw)
7809{
7810
7811 if (bfw->fw != NULL)
7812 firmware_put(bfw->fw, FIRMWARE_UNLOAD);
7813 bfw->fw = NULL;
7814 bfw->filename = NULL;
7815}
7816
7817static int
7818bwn_fw_loaducode(struct bwn_mac *mac)
7819{
7820#define GETFWOFFSET(fwp, offset) \
7821 ((const uint32_t *)((const char *)fwp.fw->data + offset))
7822#define GETFWSIZE(fwp, offset) \
7823 ((fwp.fw->datasize - offset) / sizeof(uint32_t))
7824 struct bwn_softc *sc = mac->mac_sc;
7825 const uint32_t *data;
7826 unsigned int i;
7827 uint32_t ctl;
7828 uint16_t date, fwcaps, time;
7829 int error = 0;
7830
7831 ctl = BWN_READ_4(mac, BWN_MACCTL);
7832 ctl |= BWN_MACCTL_MCODE_JMP0;
7833 KASSERT(!(ctl & BWN_MACCTL_MCODE_RUN), ("%s:%d: fail", __func__,
7834 __LINE__));
7835 BWN_WRITE_4(mac, BWN_MACCTL, ctl);
7836 for (i = 0; i < 64; i++)
7837 bwn_shm_write_2(mac, BWN_SCRATCH, i, 0);
7838 for (i = 0; i < 4096; i += 2)
7839 bwn_shm_write_2(mac, BWN_SHARED, i, 0);
7840
7841 data = GETFWOFFSET(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7842 bwn_shm_ctlword(mac, BWN_UCODE | BWN_SHARED_AUTOINC, 0x0000);
7843 for (i = 0; i < GETFWSIZE(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7844 i++) {
7845 BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7846 DELAY(10);
7847 }
7848
7849 if (mac->mac_fw.pcm.fw) {
7850 data = GETFWOFFSET(mac->mac_fw.pcm, sizeof(struct bwn_fwhdr));
7851 bwn_shm_ctlword(mac, BWN_HW, 0x01ea);
7852 BWN_WRITE_4(mac, BWN_SHM_DATA, 0x00004000);
7853 bwn_shm_ctlword(mac, BWN_HW, 0x01eb);
7854 for (i = 0; i < GETFWSIZE(mac->mac_fw.pcm,
7855 sizeof(struct bwn_fwhdr)); i++) {
7856 BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7857 DELAY(10);
7858 }
7859 }
7860
7861 BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_ALL);
7862 BWN_WRITE_4(mac, BWN_MACCTL,
7863 (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_JMP0) |
7864 BWN_MACCTL_MCODE_RUN);
7865
7866 for (i = 0; i < 21; i++) {
7867 if (BWN_READ_4(mac, BWN_INTR_REASON) == BWN_INTR_MAC_SUSPENDED)
7868 break;
7869 if (i >= 20) {
7870 device_printf(sc->sc_dev, "ucode timeout\n");
7871 error = ENXIO;
7872 goto error;
7873 }
7874 DELAY(50000);
7875 }
7876 BWN_READ_4(mac, BWN_INTR_REASON);
7877
7878 mac->mac_fw.rev = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_REV);
7879 if (mac->mac_fw.rev <= 0x128) {
7880 device_printf(sc->sc_dev, "the firmware is too old\n");
7881 error = EOPNOTSUPP;
7882 goto error;
7883 }
7884 mac->mac_fw.patch = bwn_shm_read_2(mac, BWN_SHARED,
7885 BWN_SHARED_UCODE_PATCH);
7886 date = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_DATE);
7887 mac->mac_fw.opensource = (date == 0xffff);
7888 if (bwn_wme != 0)
7889 mac->mac_flags |= BWN_MAC_FLAG_WME;
7890 mac->mac_flags |= BWN_MAC_FLAG_HWCRYPTO;
7891
7892 time = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_TIME);
7893 if (mac->mac_fw.opensource == 0) {
7894 device_printf(sc->sc_dev,
7895 "firmware version (rev %u patch %u date %#x time %#x)\n",
7896 mac->mac_fw.rev, mac->mac_fw.patch, date, time);
7897 if (mac->mac_fw.no_pcmfile)
7898 device_printf(sc->sc_dev,
7899 "no HW crypto acceleration due to pcm5\n");
7900 } else {
7901 mac->mac_fw.patch = time;
7902 fwcaps = bwn_fwcaps_read(mac);
7903 if (!(fwcaps & BWN_FWCAPS_HWCRYPTO) || mac->mac_fw.no_pcmfile) {
7904 device_printf(sc->sc_dev,
7905 "disabling HW crypto acceleration\n");
7906 mac->mac_flags &= ~BWN_MAC_FLAG_HWCRYPTO;
7907 }
7908 if (!(fwcaps & BWN_FWCAPS_WME)) {
7909 device_printf(sc->sc_dev, "disabling WME support\n");
7910 mac->mac_flags &= ~BWN_MAC_FLAG_WME;
7911 }
7912 }
7913
7914 if (BWN_ISOLDFMT(mac))
7915 device_printf(sc->sc_dev, "using old firmware image\n");
7916
7917 return (0);
7918
7919error:
7920 BWN_WRITE_4(mac, BWN_MACCTL,
7921 (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_RUN) |
7922 BWN_MACCTL_MCODE_JMP0);
7923
7924 return (error);
7925#undef GETFWSIZE
7926#undef GETFWOFFSET
7927}
7928
7929/* OpenFirmware only */
7930static uint16_t
7931bwn_fwcaps_read(struct bwn_mac *mac)
7932{
7933
7934 KASSERT(mac->mac_fw.opensource == 1,
7935 ("%s:%d: fail", __func__, __LINE__));
7936 return (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_FWCAPS));
7937}
7938
7939static int
7940bwn_fwinitvals_write(struct bwn_mac *mac, const struct bwn_fwinitvals *ivals,
7941 size_t count, size_t array_size)
7942{
7943#define GET_NEXTIV16(iv) \
7944 ((const struct bwn_fwinitvals *)((const uint8_t *)(iv) + \
7945 sizeof(uint16_t) + sizeof(uint16_t)))
7946#define GET_NEXTIV32(iv) \
7947 ((const struct bwn_fwinitvals *)((const uint8_t *)(iv) + \
7948 sizeof(uint16_t) + sizeof(uint32_t)))
7949 struct bwn_softc *sc = mac->mac_sc;
7950 const struct bwn_fwinitvals *iv;
7951 uint16_t offset;
7952 size_t i;
7953 uint8_t bit32;
7954
7955 KASSERT(sizeof(struct bwn_fwinitvals) == 6,
7956 ("%s:%d: fail", __func__, __LINE__));
7957 iv = ivals;
7958 for (i = 0; i < count; i++) {
7959 if (array_size < sizeof(iv->offset_size))
7960 goto fail;
7961 array_size -= sizeof(iv->offset_size);
7962 offset = be16toh(iv->offset_size);
7963 bit32 = (offset & BWN_FWINITVALS_32BIT) ? 1 : 0;
7964 offset &= BWN_FWINITVALS_OFFSET_MASK;
7965 if (offset >= 0x1000)
7966 goto fail;
7967 if (bit32) {
7968 if (array_size < sizeof(iv->data.d32))
7969 goto fail;
7970 array_size -= sizeof(iv->data.d32);
7971 BWN_WRITE_4(mac, offset, be32toh(iv->data.d32));
7972 iv = GET_NEXTIV32(iv);
7973 } else {
7974
7975 if (array_size < sizeof(iv->data.d16))
7976 goto fail;
7977 array_size -= sizeof(iv->data.d16);
7978 BWN_WRITE_2(mac, offset, be16toh(iv->data.d16));
7979
7980 iv = GET_NEXTIV16(iv);
7981 }
7982 }
7983 if (array_size != 0)
7984 goto fail;
7985 return (0);
7986fail:
7987 device_printf(sc->sc_dev, "initvals: invalid format\n");
7988 return (EPROTO);
7989#undef GET_NEXTIV16
7990#undef GET_NEXTIV32
7991}
7992
7993static int
7994bwn_switch_channel(struct bwn_mac *mac, int chan)
7995{
7996 struct bwn_phy *phy = &(mac->mac_phy);
7997 struct bwn_softc *sc = mac->mac_sc;
7998 struct ifnet *ifp = sc->sc_ifp;
7999 struct ieee80211com *ic = ifp->if_l2com;
8000 uint16_t channelcookie, savedcookie;
8001 int error;
8002
8003 if (chan == 0xffff)
8004 chan = phy->get_default_chan(mac);
8005
8006 channelcookie = chan;
8007 if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan))
8008 channelcookie |= 0x100;
8009 savedcookie = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_CHAN);
8010 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, channelcookie);
8011 error = phy->switch_channel(mac, chan);
8012 if (error)
8013 goto fail;
8014
8015 mac->mac_phy.chan = chan;
8016 DELAY(8000);
8017 return (0);
8018fail:
8019 device_printf(sc->sc_dev, "failed to switch channel\n");
8020 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, savedcookie);
8021 return (error);
8022}
8023
8024static uint16_t
8025bwn_ant2phy(int antenna)
8026{
8027
8028 switch (antenna) {
8029 case BWN_ANT0:
8030 return (BWN_TX_PHY_ANT0);
8031 case BWN_ANT1:
8032 return (BWN_TX_PHY_ANT1);
8033 case BWN_ANT2:
8034 return (BWN_TX_PHY_ANT2);
8035 case BWN_ANT3:
8036 return (BWN_TX_PHY_ANT3);
8037 case BWN_ANTAUTO:
8038 return (BWN_TX_PHY_ANT01AUTO);
8039 }
8040 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8041 return (0);
8042}
8043
8044static void
8045bwn_wme_load(struct bwn_mac *mac)
8046{
8047 struct bwn_softc *sc = mac->mac_sc;
8048 int i;
8049
8050 KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
8051 ("%s:%d: fail", __func__, __LINE__));
8052
8053 bwn_mac_suspend(mac);
8054 for (i = 0; i < N(sc->sc_wmeParams); i++)
8055 bwn_wme_loadparams(mac, &(sc->sc_wmeParams[i]),
8056 bwn_wme_shm_offsets[i]);
8057 bwn_mac_enable(mac);
8058}
8059
8060static void
8061bwn_wme_loadparams(struct bwn_mac *mac,
8062 const struct wmeParams *p, uint16_t shm_offset)
8063{
8064#define SM(_v, _f) (((_v) << _f##_S) & _f)
8065 struct bwn_softc *sc = mac->mac_sc;
8066 uint16_t params[BWN_NR_WMEPARAMS];
8067 int slot, tmp;
8068 unsigned int i;
8069
8070 slot = BWN_READ_2(mac, BWN_RNG) &
8071 SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8072
8073 memset(&params, 0, sizeof(params));
8074
8075 DPRINTF(sc, BWN_DEBUG_WME, "wmep_txopLimit %d wmep_logcwmin %d "
8076 "wmep_logcwmax %d wmep_aifsn %d\n", p->wmep_txopLimit,
8077 p->wmep_logcwmin, p->wmep_logcwmax, p->wmep_aifsn);
8078
8079 params[BWN_WMEPARAM_TXOP] = p->wmep_txopLimit * 32;
8080 params[BWN_WMEPARAM_CWMIN] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8081 params[BWN_WMEPARAM_CWMAX] = SM(p->wmep_logcwmax, WME_PARAM_LOGCWMAX);
8082 params[BWN_WMEPARAM_CWCUR] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8083 params[BWN_WMEPARAM_AIFS] = p->wmep_aifsn;
8084 params[BWN_WMEPARAM_BSLOTS] = slot;
8085 params[BWN_WMEPARAM_REGGAP] = slot + p->wmep_aifsn;
8086
8087 for (i = 0; i < N(params); i++) {
8088 if (i == BWN_WMEPARAM_STATUS) {
8089 tmp = bwn_shm_read_2(mac, BWN_SHARED,
8090 shm_offset + (i * 2));
8091 tmp |= 0x100;
8092 bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
8093 tmp);
8094 } else {
8095 bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
8096 params[i]);
8097 }
8098 }
8099}
8100
8101static void
8102bwn_mac_write_bssid(struct bwn_mac *mac)
8103{
8104 struct bwn_softc *sc = mac->mac_sc;
8105 uint32_t tmp;
8106 int i;
8107 uint8_t mac_bssid[IEEE80211_ADDR_LEN * 2];
8108
8109 bwn_mac_setfilter(mac, BWN_MACFILTER_BSSID, sc->sc_bssid);
8110 memcpy(mac_bssid, sc->sc_macaddr, IEEE80211_ADDR_LEN);
8111 memcpy(mac_bssid + IEEE80211_ADDR_LEN, sc->sc_bssid,
8112 IEEE80211_ADDR_LEN);
8113
8114 for (i = 0; i < N(mac_bssid); i += sizeof(uint32_t)) {
8115 tmp = (uint32_t) (mac_bssid[i + 0]);
8116 tmp |= (uint32_t) (mac_bssid[i + 1]) << 8;
8117 tmp |= (uint32_t) (mac_bssid[i + 2]) << 16;
8118 tmp |= (uint32_t) (mac_bssid[i + 3]) << 24;
8119 bwn_ram_write(mac, 0x20 + i, tmp);
8120 }
8121}
8122
8123static void
8124bwn_mac_setfilter(struct bwn_mac *mac, uint16_t offset,
8125 const uint8_t *macaddr)
8126{
8127 static const uint8_t zero[IEEE80211_ADDR_LEN] = { 0 };
8128 uint16_t data;
8129
8130 if (!mac)
8131 macaddr = zero;
8132
8133 offset |= 0x0020;
8134 BWN_WRITE_2(mac, BWN_MACFILTER_CONTROL, offset);
8135
8136 data = macaddr[0];
8137 data |= macaddr[1] << 8;
8138 BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8139 data = macaddr[2];
8140 data |= macaddr[3] << 8;
8141 BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8142 data = macaddr[4];
8143 data |= macaddr[5] << 8;
8144 BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8145}
8146
8147static void
8148bwn_key_dowrite(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8149 const uint8_t *key, size_t key_len, const uint8_t *mac_addr)
8150{
8151 uint8_t buf[BWN_SEC_KEYSIZE] = { 0, };
8152 uint8_t per_sta_keys_start = 8;
8153
8154 if (BWN_SEC_NEWAPI(mac))
8155 per_sta_keys_start = 4;
8156
8157 KASSERT(index < mac->mac_max_nr_keys,
8158 ("%s:%d: fail", __func__, __LINE__));
8159 KASSERT(key_len <= BWN_SEC_KEYSIZE,
8160 ("%s:%d: fail", __func__, __LINE__));
8161
8162 if (index >= per_sta_keys_start)
8163 bwn_key_macwrite(mac, index, NULL);
8164 if (key)
8165 memcpy(buf, key, key_len);
8166 bwn_key_write(mac, index, algorithm, buf);
8167 if (index >= per_sta_keys_start)
8168 bwn_key_macwrite(mac, index, mac_addr);
8169
8170 mac->mac_key[index].algorithm = algorithm;
8171}
8172
8173static void
8174bwn_key_macwrite(struct bwn_mac *mac, uint8_t index, const uint8_t *addr)
8175{
8176 struct bwn_softc *sc = mac->mac_sc;
8177 uint32_t addrtmp[2] = { 0, 0 };
8178 uint8_t start = 8;
8179
8180 if (BWN_SEC_NEWAPI(mac))
8181 start = 4;
8182
8183 KASSERT(index >= start,
8184 ("%s:%d: fail", __func__, __LINE__));
8185 index -= start;
8186
8187 if (addr) {
8188 addrtmp[0] = addr[0];
8189 addrtmp[0] |= ((uint32_t) (addr[1]) << 8);
8190 addrtmp[0] |= ((uint32_t) (addr[2]) << 16);
8191 addrtmp[0] |= ((uint32_t) (addr[3]) << 24);
8192 addrtmp[1] = addr[4];
8193 addrtmp[1] |= ((uint32_t) (addr[5]) << 8);
8194 }
8195
8196 if (siba_get_revid(sc->sc_dev) >= 5) {
8197 bwn_shm_write_4(mac, BWN_RCMTA, (index * 2) + 0, addrtmp[0]);
8198 bwn_shm_write_2(mac, BWN_RCMTA, (index * 2) + 1, addrtmp[1]);
8199 } else {
8200 if (index >= 8) {
8201 bwn_shm_write_4(mac, BWN_SHARED,
8202 BWN_SHARED_PSM + (index * 6) + 0, addrtmp[0]);
8203 bwn_shm_write_2(mac, BWN_SHARED,
8204 BWN_SHARED_PSM + (index * 6) + 4, addrtmp[1]);
8205 }
8206 }
8207}
8208
8209static void
8210bwn_key_write(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8211 const uint8_t *key)
8212{
8213 unsigned int i;
8214 uint32_t offset;
8215 uint16_t kidx, value;
8216
8217 kidx = BWN_SEC_KEY2FW(mac, index);
8218 bwn_shm_write_2(mac, BWN_SHARED,
8219 BWN_SHARED_KEYIDX_BLOCK + (kidx * 2), (kidx << 4) | algorithm);
8220
8221 offset = mac->mac_ktp + (index * BWN_SEC_KEYSIZE);
8222 for (i = 0; i < BWN_SEC_KEYSIZE; i += 2) {
8223 value = key[i];
8224 value |= (uint16_t)(key[i + 1]) << 8;
8225 bwn_shm_write_2(mac, BWN_SHARED, offset + i, value);
8226 }
8227}
8228
8229static void
8230bwn_phy_exit(struct bwn_mac *mac)
8231{
8232
8233 mac->mac_phy.rf_onoff(mac, 0);
8234 if (mac->mac_phy.exit != NULL)
8235 mac->mac_phy.exit(mac);
8236}
8237
8238static void
8239bwn_dma_free(struct bwn_mac *mac)
8240{
8241 struct bwn_dma *dma;
8242
8243 if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
8244 return;
8245 dma = &mac->mac_method.dma;
8246
8247 bwn_dma_ringfree(&dma->rx);
8248 bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
8249 bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
8250 bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
8251 bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
8252 bwn_dma_ringfree(&dma->mcast);
8253}
8254
8255static void
8256bwn_core_stop(struct bwn_mac *mac)
8257{
8258 struct bwn_softc *sc = mac->mac_sc;
8259
8260 BWN_ASSERT_LOCKED(sc);
8261
8262 if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8263 return;
8264
8265 callout_stop(&sc->sc_rfswitch_ch);
8266 callout_stop(&sc->sc_task_ch);
8267 callout_stop(&sc->sc_watchdog_ch);
8268 sc->sc_watchdog_timer = 0;
8269 BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8270 BWN_READ_4(mac, BWN_INTR_MASK);
8271 bwn_mac_suspend(mac);
8272
8273 mac->mac_status = BWN_MAC_STATUS_INITED;
8274}
8275
8276static int
8277bwn_switch_band(struct bwn_softc *sc, struct ieee80211_channel *chan)
8278{
8279 struct bwn_mac *up_dev = NULL;
8280 struct bwn_mac *down_dev;
8281 struct bwn_mac *mac;
8282 int err, status;
8283 uint8_t gmode;
8284
8285 BWN_ASSERT_LOCKED(sc);
8286
8287 TAILQ_FOREACH(mac, &sc->sc_maclist, mac_list) {
8288 if (IEEE80211_IS_CHAN_2GHZ(chan) &&
8289 mac->mac_phy.supports_2ghz) {
8290 up_dev = mac;
8291 gmode = 1;
8292 } else if (IEEE80211_IS_CHAN_5GHZ(chan) &&
8293 mac->mac_phy.supports_5ghz) {
8294 up_dev = mac;
8295 gmode = 0;
8296 } else {
8297 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8298 return (EINVAL);
8299 }
8300 if (up_dev != NULL)
8301 break;
8302 }
8303 if (up_dev == NULL) {
8304 device_printf(sc->sc_dev, "Could not find a device\n");
8305 return (ENODEV);
8306 }
8307 if (up_dev == sc->sc_curmac && sc->sc_curmac->mac_phy.gmode == gmode)
8308 return (0);
8309
8310 device_printf(sc->sc_dev, "switching to %s-GHz band\n",
8311 IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8312
8313 down_dev = sc->sc_curmac;;
8314 status = down_dev->mac_status;
8315 if (status >= BWN_MAC_STATUS_STARTED)
8316 bwn_core_stop(down_dev);
8317 if (status >= BWN_MAC_STATUS_INITED)
8318 bwn_core_exit(down_dev);
8319
8320 if (down_dev != up_dev)
8321 bwn_phy_reset(down_dev);
8322
8323 up_dev->mac_phy.gmode = gmode;
8324 if (status >= BWN_MAC_STATUS_INITED) {
8325 err = bwn_core_init(up_dev);
8326 if (err) {
8327 device_printf(sc->sc_dev,
8328 "fatal: failed to initialize for %s-GHz\n",
8329 IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8330 goto fail;
8331 }
8332 }
8333 if (status >= BWN_MAC_STATUS_STARTED)
8334 bwn_core_start(up_dev);
8335 KASSERT(up_dev->mac_status == status, ("%s: fail", __func__));
8336 sc->sc_curmac = up_dev;
8337
8338 return (0);
8339fail:
8340 sc->sc_curmac = NULL;
8341 return (err);
8342}
8343
8344static void
8345bwn_rf_turnon(struct bwn_mac *mac)
8346{
8347
8348 bwn_mac_suspend(mac);
8349 mac->mac_phy.rf_onoff(mac, 1);
8350 mac->mac_phy.rf_on = 1;
8351 bwn_mac_enable(mac);
8352}
8353
8354static void
8355bwn_rf_turnoff(struct bwn_mac *mac)
8356{
8357
8358 bwn_mac_suspend(mac);
8359 mac->mac_phy.rf_onoff(mac, 0);
8360 mac->mac_phy.rf_on = 0;
8361 bwn_mac_enable(mac);
8362}
8363
8364static void
8365bwn_phy_reset(struct bwn_mac *mac)
8366{
8367 struct bwn_softc *sc = mac->mac_sc;
8368
8369 siba_write_4(sc->sc_dev, SIBA_TGSLOW,
8370 ((siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~BWN_TGSLOW_SUPPORT_G) |
8371 BWN_TGSLOW_PHYRESET) | SIBA_TGSLOW_FGC);
8372 DELAY(1000);
8373 siba_write_4(sc->sc_dev, SIBA_TGSLOW,
8374 (siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~SIBA_TGSLOW_FGC) |
8375 BWN_TGSLOW_PHYRESET);
8376 DELAY(1000);
8377}
8378
8379static int
8380bwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
8381{
8382 struct bwn_vap *bvp = BWN_VAP(vap);
8383 struct ieee80211com *ic= vap->iv_ic;
8384 struct ifnet *ifp = ic->ic_ifp;
8385 enum ieee80211_state ostate = vap->iv_state;
8386 struct bwn_softc *sc = ifp->if_softc;
8387 struct bwn_mac *mac = sc->sc_curmac;
8388 int error;
8389
8390 DPRINTF(sc, BWN_DEBUG_STATE, "%s: %s -> %s\n", __func__,
8391 ieee80211_state_name[vap->iv_state],
8392 ieee80211_state_name[nstate]);
8393
8394 error = bvp->bv_newstate(vap, nstate, arg);
8395 if (error != 0)
8396 return (error);
8397
8398 BWN_LOCK(sc);
8399
8400 bwn_led_newstate(mac, nstate);
8401
8402 /*
8403 * Clear the BSSID when we stop a STA
8404 */
8405 if (vap->iv_opmode == IEEE80211_M_STA) {
8406 if (ostate == IEEE80211_S_RUN && nstate != IEEE80211_S_RUN) {
8407 /*
8408 * Clear out the BSSID. If we reassociate to
8409 * the same AP, this will reinialize things
8410 * correctly...
8411 */
8412 if (ic->ic_opmode == IEEE80211_M_STA &&
8413 (sc->sc_flags & BWN_FLAG_INVALID) == 0) {
8414 memset(sc->sc_bssid, 0, IEEE80211_ADDR_LEN);
8415 bwn_set_macaddr(mac);
8416 }
8417 }
8418 }
8419
8420 if (vap->iv_opmode == IEEE80211_M_MONITOR ||
8421 vap->iv_opmode == IEEE80211_M_AHDEMO) {
8422 /* XXX nothing to do? */
8423 } else if (nstate == IEEE80211_S_RUN) {
8424 memcpy(sc->sc_bssid, vap->iv_bss->ni_bssid, IEEE80211_ADDR_LEN);
8425 memcpy(sc->sc_macaddr, IF_LLADDR(ifp), IEEE80211_ADDR_LEN);
8426 bwn_set_opmode(mac);
8427 bwn_set_pretbtt(mac);
8428 bwn_spu_setdelay(mac, 0);
8429 bwn_set_macaddr(mac);
8430 }
8431
8432 BWN_UNLOCK(sc);
8433
8434 return (error);
8435}
8436
8437static void
8438bwn_set_pretbtt(struct bwn_mac *mac)
8439{
8440 struct bwn_softc *sc = mac->mac_sc;
8441 struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8442 uint16_t pretbtt;
8443
8444 if (ic->ic_opmode == IEEE80211_M_IBSS)
8445 pretbtt = 2;
8446 else
8447 pretbtt = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 120 : 250;
8448 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PRETBTT, pretbtt);
8449 BWN_WRITE_2(mac, BWN_TSF_CFP_PRETBTT, pretbtt);
8450}
8451
8452static int
8453bwn_intr(void *arg)
8454{
8455 struct bwn_mac *mac = arg;
8456 struct bwn_softc *sc = mac->mac_sc;
8457 uint32_t reason;
8458
8459 if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
8460 (sc->sc_flags & BWN_FLAG_INVALID))
8461 return (FILTER_STRAY);
8462
8463 reason = BWN_READ_4(mac, BWN_INTR_REASON);
8464 if (reason == 0xffffffff) /* shared IRQ */
8465 return (FILTER_STRAY);
8466 reason &= mac->mac_intr_mask;
8467 if (reason == 0)
8468 return (FILTER_HANDLED);
8469
8470 mac->mac_reason[0] = BWN_READ_4(mac, BWN_DMA0_REASON) & 0x0001dc00;
8471 mac->mac_reason[1] = BWN_READ_4(mac, BWN_DMA1_REASON) & 0x0000dc00;
8472 mac->mac_reason[2] = BWN_READ_4(mac, BWN_DMA2_REASON) & 0x0000dc00;
8473 mac->mac_reason[3] = BWN_READ_4(mac, BWN_DMA3_REASON) & 0x0001dc00;
8474 mac->mac_reason[4] = BWN_READ_4(mac, BWN_DMA4_REASON) & 0x0000dc00;
8475 BWN_WRITE_4(mac, BWN_INTR_REASON, reason);
8476 BWN_WRITE_4(mac, BWN_DMA0_REASON, mac->mac_reason[0]);
8477 BWN_WRITE_4(mac, BWN_DMA1_REASON, mac->mac_reason[1]);
8478 BWN_WRITE_4(mac, BWN_DMA2_REASON, mac->mac_reason[2]);
8479 BWN_WRITE_4(mac, BWN_DMA3_REASON, mac->mac_reason[3]);
8480 BWN_WRITE_4(mac, BWN_DMA4_REASON, mac->mac_reason[4]);
8481
8482 /* Disable interrupts. */
8483 BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8484
8485 mac->mac_reason_intr = reason;
8486
8487 BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8488 BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8489
8490 taskqueue_enqueue_fast(sc->sc_tq, &mac->mac_intrtask);
8491 return (FILTER_HANDLED);
8492}
8493
8494static void
8495bwn_intrtask(void *arg, int npending)
8496{
8497 struct bwn_mac *mac = arg;
8498 struct bwn_softc *sc = mac->mac_sc;
8499 struct ifnet *ifp = sc->sc_ifp;
8500 uint32_t merged = 0;
8501 int i, tx = 0, rx = 0;
8502
8503 BWN_LOCK(sc);
8504 if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
8505 (sc->sc_flags & BWN_FLAG_INVALID)) {
8506 BWN_UNLOCK(sc);
8507 return;
8508 }
8509
8510 for (i = 0; i < N(mac->mac_reason); i++)
8511 merged |= mac->mac_reason[i];
8512
8513 if (mac->mac_reason_intr & BWN_INTR_MAC_TXERR)
8514 device_printf(sc->sc_dev, "MAC trans error\n");
8515
8516 if (mac->mac_reason_intr & BWN_INTR_PHY_TXERR) {
8517 DPRINTF(sc, BWN_DEBUG_INTR, "%s: PHY trans error\n", __func__);
8518 mac->mac_phy.txerrors--;
8519 if (mac->mac_phy.txerrors == 0) {
8520 mac->mac_phy.txerrors = BWN_TXERROR_MAX;
8521 bwn_restart(mac, "PHY TX errors");
8522 }
8523 }
8524
8525 if (merged & (BWN_DMAINTR_FATALMASK | BWN_DMAINTR_NONFATALMASK)) {
8526 if (merged & BWN_DMAINTR_FATALMASK) {
8527 device_printf(sc->sc_dev,
8528 "Fatal DMA error: %#x %#x %#x %#x %#x %#x\n",
8529 mac->mac_reason[0], mac->mac_reason[1],
8530 mac->mac_reason[2], mac->mac_reason[3],
8531 mac->mac_reason[4], mac->mac_reason[5]);
8532 bwn_restart(mac, "DMA error");
8533 BWN_UNLOCK(sc);
8534 return;
8535 }
8536 if (merged & BWN_DMAINTR_NONFATALMASK) {
8537 device_printf(sc->sc_dev,
8538 "DMA error: %#x %#x %#x %#x %#x %#x\n",
8539 mac->mac_reason[0], mac->mac_reason[1],
8540 mac->mac_reason[2], mac->mac_reason[3],
8541 mac->mac_reason[4], mac->mac_reason[5]);
8542 }
8543 }
8544
8545 if (mac->mac_reason_intr & BWN_INTR_UCODE_DEBUG)
8546 bwn_intr_ucode_debug(mac);
8547 if (mac->mac_reason_intr & BWN_INTR_TBTT_INDI)
8548 bwn_intr_tbtt_indication(mac);
8549 if (mac->mac_reason_intr & BWN_INTR_ATIM_END)
8550 bwn_intr_atim_end(mac);
8551 if (mac->mac_reason_intr & BWN_INTR_BEACON)
8552 bwn_intr_beacon(mac);
8553 if (mac->mac_reason_intr & BWN_INTR_PMQ)
8554 bwn_intr_pmq(mac);
8555 if (mac->mac_reason_intr & BWN_INTR_NOISESAMPLE_OK)
8556 bwn_intr_noise(mac);
8557
8558 if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
8559 if (mac->mac_reason[0] & BWN_DMAINTR_RX_DONE) {
8560 bwn_dma_rx(mac->mac_method.dma.rx);
8561 rx = 1;
8562 }
8563 } else
8564 rx = bwn_pio_rx(&mac->mac_method.pio.rx);
8565
8566 KASSERT(!(mac->mac_reason[1] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8567 KASSERT(!(mac->mac_reason[2] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8568 KASSERT(!(mac->mac_reason[3] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8569 KASSERT(!(mac->mac_reason[4] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8570 KASSERT(!(mac->mac_reason[5] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8571
8572 if (mac->mac_reason_intr & BWN_INTR_TX_OK) {
8573 bwn_intr_txeof(mac);
8574 tx = 1;
8575 }
8576
8577 BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
8578
8579 if (sc->sc_blink_led != NULL && sc->sc_led_blink) {
8580 int evt = BWN_LED_EVENT_NONE;
8581
8582 if (tx && rx) {
8583 if (sc->sc_rx_rate > sc->sc_tx_rate)
8584 evt = BWN_LED_EVENT_RX;
8585 else
8586 evt = BWN_LED_EVENT_TX;
8587 } else if (tx) {
8588 evt = BWN_LED_EVENT_TX;
8589 } else if (rx) {
8590 evt = BWN_LED_EVENT_RX;
8591 } else if (rx == 0) {
8592 evt = BWN_LED_EVENT_POLL;
8593 }
8594
8595 if (evt != BWN_LED_EVENT_NONE)
8596 bwn_led_event(mac, evt);
8597 }
8598
8599 if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0) {
8600 if (!IFQ_IS_EMPTY(&ifp->if_snd))
8601 bwn_start_locked(ifp);
8602 }
8603
8604 BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8605 BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8606
8607 BWN_UNLOCK(sc);
8608}
8609
8610static void
8611bwn_restart(struct bwn_mac *mac, const char *msg)
8612{
8613 struct bwn_softc *sc = mac->mac_sc;
8614 struct ifnet *ifp = sc->sc_ifp;
8615 struct ieee80211com *ic = ifp->if_l2com;
8616
8617 if (mac->mac_status < BWN_MAC_STATUS_INITED)
8618 return;
8619
8620 device_printf(sc->sc_dev, "HW reset: %s\n", msg);
8621 ieee80211_runtask(ic, &mac->mac_hwreset);
8622}
8623
8624static void
8625bwn_intr_ucode_debug(struct bwn_mac *mac)
8626{
8627 struct bwn_softc *sc = mac->mac_sc;
8628 uint16_t reason;
8629
8630 if (mac->mac_fw.opensource == 0)
8631 return;
8632
8633 reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG);
8634 switch (reason) {
8635 case BWN_DEBUGINTR_PANIC:
8636 bwn_handle_fwpanic(mac);
8637 break;
8638 case BWN_DEBUGINTR_DUMP_SHM:
8639 device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_SHM\n");
8640 break;
8641 case BWN_DEBUGINTR_DUMP_REGS:
8642 device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_REGS\n");
8643 break;
8644 case BWN_DEBUGINTR_MARKER:
8645 device_printf(sc->sc_dev, "BWN_DEBUGINTR_MARKER\n");
8646 break;
8647 default:
8648 device_printf(sc->sc_dev,
8649 "ucode debug unknown reason: %#x\n", reason);
8650 }
8651
8652 bwn_shm_write_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG,
8653 BWN_DEBUGINTR_ACK);
8654}
8655
8656static void
8657bwn_intr_tbtt_indication(struct bwn_mac *mac)
8658{
8659 struct bwn_softc *sc = mac->mac_sc;
8660 struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8661
8662 if (ic->ic_opmode != IEEE80211_M_HOSTAP)
8663 bwn_psctl(mac, 0);
8664 if (ic->ic_opmode == IEEE80211_M_IBSS)
8665 mac->mac_flags |= BWN_MAC_FLAG_DFQVALID;
8666}
8667
8668static void
8669bwn_intr_atim_end(struct bwn_mac *mac)
8670{
8671
8672 if (mac->mac_flags & BWN_MAC_FLAG_DFQVALID) {
8673 BWN_WRITE_4(mac, BWN_MACCMD,
8674 BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_DFQ_VALID);
8675 mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
8676 }
8677}
8678
8679static void
8680bwn_intr_beacon(struct bwn_mac *mac)
8681{
8682 struct bwn_softc *sc = mac->mac_sc;
8683 struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8684 uint32_t cmd, beacon0, beacon1;
8685
8686 if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
8687 ic->ic_opmode == IEEE80211_M_MBSS)
8688 return;
8689
8690 mac->mac_intr_mask &= ~BWN_INTR_BEACON;
8691
8692 cmd = BWN_READ_4(mac, BWN_MACCMD);
8693 beacon0 = (cmd & BWN_MACCMD_BEACON0_VALID);
8694 beacon1 = (cmd & BWN_MACCMD_BEACON1_VALID);
8695
8696 if (beacon0 && beacon1) {
8697 BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_BEACON);
8698 mac->mac_intr_mask |= BWN_INTR_BEACON;
8699 return;
8700 }
8701
8702 if (sc->sc_flags & BWN_FLAG_NEED_BEACON_TP) {
8703 sc->sc_flags &= ~BWN_FLAG_NEED_BEACON_TP;
8704 bwn_load_beacon0(mac);
8705 bwn_load_beacon1(mac);
8706 cmd = BWN_READ_4(mac, BWN_MACCMD);
8707 cmd |= BWN_MACCMD_BEACON0_VALID;
8708 BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8709 } else {
8710 if (!beacon0) {
8711 bwn_load_beacon0(mac);
8712 cmd = BWN_READ_4(mac, BWN_MACCMD);
8713 cmd |= BWN_MACCMD_BEACON0_VALID;
8714 BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8715 } else if (!beacon1) {
8716 bwn_load_beacon1(mac);
8717 cmd = BWN_READ_4(mac, BWN_MACCMD);
8718 cmd |= BWN_MACCMD_BEACON1_VALID;
8719 BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8720 }
8721 }
8722}
8723
8724static void
8725bwn_intr_pmq(struct bwn_mac *mac)
8726{
8727 uint32_t tmp;
8728
8729 while (1) {
8730 tmp = BWN_READ_4(mac, BWN_PS_STATUS);
8731 if (!(tmp & 0x00000008))
8732 break;
8733 }
8734 BWN_WRITE_2(mac, BWN_PS_STATUS, 0x0002);
8735}
8736
8737static void
8738bwn_intr_noise(struct bwn_mac *mac)
8739{
8740 struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
8741 uint16_t tmp;
8742 uint8_t noise[4];
8743 uint8_t i, j;
8744 int32_t average;
8745
8746 if (mac->mac_phy.type != BWN_PHYTYPE_G)
8747 return;
8748
8749 KASSERT(mac->mac_noise.noi_running, ("%s: fail", __func__));
8750 *((uint32_t *)noise) = htole32(bwn_jssi_read(mac));
8751 if (noise[0] == 0x7f || noise[1] == 0x7f || noise[2] == 0x7f ||
8752 noise[3] == 0x7f)
8753 goto new;
8754
8755 KASSERT(mac->mac_noise.noi_nsamples < 8,
8756 ("%s:%d: fail", __func__, __LINE__));
8757 i = mac->mac_noise.noi_nsamples;
8758 noise[0] = MIN(MAX(noise[0], 0), N(pg->pg_nrssi_lt) - 1);
8759 noise[1] = MIN(MAX(noise[1], 0), N(pg->pg_nrssi_lt) - 1);
8760 noise[2] = MIN(MAX(noise[2], 0), N(pg->pg_nrssi_lt) - 1);
8761 noise[3] = MIN(MAX(noise[3], 0), N(pg->pg_nrssi_lt) - 1);
8762 mac->mac_noise.noi_samples[i][0] = pg->pg_nrssi_lt[noise[0]];
8763 mac->mac_noise.noi_samples[i][1] = pg->pg_nrssi_lt[noise[1]];
8764 mac->mac_noise.noi_samples[i][2] = pg->pg_nrssi_lt[noise[2]];
8765 mac->mac_noise.noi_samples[i][3] = pg->pg_nrssi_lt[noise[3]];
8766 mac->mac_noise.noi_nsamples++;
8767 if (mac->mac_noise.noi_nsamples == 8) {
8768 average = 0;
8769 for (i = 0; i < 8; i++) {
8770 for (j = 0; j < 4; j++)
8771 average += mac->mac_noise.noi_samples[i][j];
8772 }
8773 average = (((average / 32) * 125) + 64) / 128;
8774 tmp = (bwn_shm_read_2(mac, BWN_SHARED, 0x40c) / 128) & 0x1f;
8775 if (tmp >= 8)
8776 average += 2;
8777 else
8778 average -= 25;
8779 average -= (tmp == 8) ? 72 : 48;
8780
8781 mac->mac_stats.link_noise = average;
8782 mac->mac_noise.noi_running = 0;
8783 return;
8784 }
8785new:
8786 bwn_noise_gensample(mac);
8787}
8788
8789static int
8790bwn_pio_rx(struct bwn_pio_rxqueue *prq)
8791{
8792 struct bwn_mac *mac = prq->prq_mac;
8793 struct bwn_softc *sc = mac->mac_sc;
8794 unsigned int i;
8795
8796 BWN_ASSERT_LOCKED(sc);
8797
8798 if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8799 return (0);
8800
8801 for (i = 0; i < 5000; i++) {
8802 if (bwn_pio_rxeof(prq) == 0)
8803 break;
8804 }
8805 if (i >= 5000)
8806 device_printf(sc->sc_dev, "too many RX frames in PIO mode\n");
8807 return ((i > 0) ? 1 : 0);
8808}
8809
8810static void
8811bwn_dma_rx(struct bwn_dma_ring *dr)
8812{
8813 int slot, curslot;
8814
8815 KASSERT(!dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
8816 curslot = dr->get_curslot(dr);
8817 KASSERT(curslot >= 0 && curslot < dr->dr_numslots,
8818 ("%s:%d: fail", __func__, __LINE__));
8819
8820 slot = dr->dr_curslot;
8821 for (; slot != curslot; slot = bwn_dma_nextslot(dr, slot))
8822 bwn_dma_rxeof(dr, &slot);
8823
8824 bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
8825 BUS_DMASYNC_PREWRITE);
8826
8827 dr->set_curslot(dr, slot);
8828 dr->dr_curslot = slot;
8829}
8830
8831static void
8832bwn_intr_txeof(struct bwn_mac *mac)
8833{
8834 struct bwn_txstatus stat;
8835 uint32_t stat0, stat1;
8836 uint16_t tmp;
8837
8838 BWN_ASSERT_LOCKED(mac->mac_sc);
8839
8840 while (1) {
8841 stat0 = BWN_READ_4(mac, BWN_XMITSTAT_0);
8842 if (!(stat0 & 0x00000001))
8843 break;
8844 stat1 = BWN_READ_4(mac, BWN_XMITSTAT_1);
8845
8846 stat.cookie = (stat0 >> 16);
8847 stat.seq = (stat1 & 0x0000ffff);
8848 stat.phy_stat = ((stat1 & 0x00ff0000) >> 16);
8849 tmp = (stat0 & 0x0000ffff);
8850 stat.framecnt = ((tmp & 0xf000) >> 12);
8851 stat.rtscnt = ((tmp & 0x0f00) >> 8);
8852 stat.sreason = ((tmp & 0x001c) >> 2);
8853 stat.pm = (tmp & 0x0080) ? 1 : 0;
8854 stat.im = (tmp & 0x0040) ? 1 : 0;
8855 stat.ampdu = (tmp & 0x0020) ? 1 : 0;
8856 stat.ack = (tmp & 0x0002) ? 1 : 0;
8857
8858 bwn_handle_txeof(mac, &stat);
8859 }
8860}
8861
8862static void
8863bwn_hwreset(void *arg, int npending)
8864{
8865 struct bwn_mac *mac = arg;
8866 struct bwn_softc *sc = mac->mac_sc;
8867 int error = 0;
8868 int prev_status;
8869
8870 BWN_LOCK(sc);
8871
8872 prev_status = mac->mac_status;
8873 if (prev_status >= BWN_MAC_STATUS_STARTED)
8874 bwn_core_stop(mac);
8875 if (prev_status >= BWN_MAC_STATUS_INITED)
8876 bwn_core_exit(mac);
8877
8878 if (prev_status >= BWN_MAC_STATUS_INITED) {
8879 error = bwn_core_init(mac);
8880 if (error)
8881 goto out;
8882 }
8883 if (prev_status >= BWN_MAC_STATUS_STARTED)
8884 bwn_core_start(mac);
8885out:
8886 if (error) {
8887 device_printf(sc->sc_dev, "%s: failed (%d)\n", __func__, error);
8888 sc->sc_curmac = NULL;
8889 }
8890 BWN_UNLOCK(sc);
8891}
8892
8893static void
8894bwn_handle_fwpanic(struct bwn_mac *mac)
8895{
8896 struct bwn_softc *sc = mac->mac_sc;
8897 uint16_t reason;
8898
8899 reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_FWPANIC_REASON_REG);
8900 device_printf(sc->sc_dev,"fw panic (%u)\n", reason);
8901
8902 if (reason == BWN_FWPANIC_RESTART)
8903 bwn_restart(mac, "ucode panic");
8904}
8905
8906static void
8907bwn_load_beacon0(struct bwn_mac *mac)
8908{
8909
8910 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8911}
8912
8913static void
8914bwn_load_beacon1(struct bwn_mac *mac)
8915{
8916
8917 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8918}
8919
8920static uint32_t
8921bwn_jssi_read(struct bwn_mac *mac)
8922{
8923 uint32_t val = 0;
8924
8925 val = bwn_shm_read_2(mac, BWN_SHARED, 0x08a);
8926 val <<= 16;
8927 val |= bwn_shm_read_2(mac, BWN_SHARED, 0x088);
8928
8929 return (val);
8930}
8931
8932static void
8933bwn_noise_gensample(struct bwn_mac *mac)
8934{
8935 uint32_t jssi = 0x7f7f7f7f;
8936
8937 bwn_shm_write_2(mac, BWN_SHARED, 0x088, (jssi & 0x0000ffff));
8938 bwn_shm_write_2(mac, BWN_SHARED, 0x08a, (jssi & 0xffff0000) >> 16);
8939 BWN_WRITE_4(mac, BWN_MACCMD,
8940 BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_BGNOISE);
8941}
8942
8943static int
8944bwn_dma_freeslot(struct bwn_dma_ring *dr)
8945{
8946 BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8947
8948 return (dr->dr_numslots - dr->dr_usedslot);
8949}
8950
8951static int
8952bwn_dma_nextslot(struct bwn_dma_ring *dr, int slot)
8953{
8954 BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8955
8956 KASSERT(slot >= -1 && slot <= dr->dr_numslots - 1,
8957 ("%s:%d: fail", __func__, __LINE__));
8958 if (slot == dr->dr_numslots - 1)
8959 return (0);
8960 return (slot + 1);
8961}
8962
8963static void
8964bwn_dma_rxeof(struct bwn_dma_ring *dr, int *slot)
8965{
8966 struct bwn_mac *mac = dr->dr_mac;
8967 struct bwn_softc *sc = mac->mac_sc;
8968 struct bwn_dma *dma = &mac->mac_method.dma;
8969 struct bwn_dmadesc_generic *desc;
8970 struct bwn_dmadesc_meta *meta;
8971 struct bwn_rxhdr4 *rxhdr;
8972 struct ifnet *ifp = sc->sc_ifp;
8973 struct mbuf *m;
8974 uint32_t macstat;
8975 int32_t tmp;
8976 int cnt = 0;
8977 uint16_t len;
8978
8979 dr->getdesc(dr, *slot, &desc, &meta);
8980
8981 bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap, BUS_DMASYNC_POSTREAD);
8982 m = meta->mt_m;
8983
8984 if (bwn_dma_newbuf(dr, desc, meta, 0)) {
8985 ifp->if_ierrors++;
8986 return;
8987 }
8988
8989 rxhdr = mtod(m, struct bwn_rxhdr4 *);
8990 len = le16toh(rxhdr->frame_len);
8991 if (len <= 0) {
8992 ifp->if_ierrors++;
8993 return;
8994 }
8995 if (bwn_dma_check_redzone(dr, m)) {
8996 device_printf(sc->sc_dev, "redzone error.\n");
8997 bwn_dma_set_redzone(dr, m);
8998 bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
8999 BUS_DMASYNC_PREWRITE);
9000 return;
9001 }
9002 if (len > dr->dr_rx_bufsize) {
9003 tmp = len;
9004 while (1) {
9005 dr->getdesc(dr, *slot, &desc, &meta);
9006 bwn_dma_set_redzone(dr, meta->mt_m);
9007 bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
9008 BUS_DMASYNC_PREWRITE);
9009 *slot = bwn_dma_nextslot(dr, *slot);
9010 cnt++;
9011 tmp -= dr->dr_rx_bufsize;
9012 if (tmp <= 0)
9013 break;
9014 }
9015 device_printf(sc->sc_dev, "too small buffer "
9016 "(len %u buffer %u dropped %d)\n",
9017 len, dr->dr_rx_bufsize, cnt);
9018 return;
9019 }
9020 macstat = le32toh(rxhdr->mac_status);
9021 if (macstat & BWN_RX_MAC_FCSERR) {
9022 if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
9023 device_printf(sc->sc_dev, "RX drop\n");
9024 return;
9025 }
9026 }
9027
9028 m->m_pkthdr.rcvif = ifp;
9029 m->m_len = m->m_pkthdr.len = len + dr->dr_frameoffset;
9030 m_adj(m, dr->dr_frameoffset);
9031
9032 bwn_rxeof(dr->dr_mac, m, rxhdr);
9033}
9034
9035static void
9036bwn_handle_txeof(struct bwn_mac *mac, const struct bwn_txstatus *status)
9037{
9038 struct bwn_dma_ring *dr;
9039 struct bwn_dmadesc_generic *desc;
9040 struct bwn_dmadesc_meta *meta;
9041 struct bwn_node *bn;
9042 struct bwn_pio_txqueue *tq;
9043 struct bwn_pio_txpkt *tp = NULL;
9044 struct bwn_softc *sc = mac->mac_sc;
9045 struct bwn_stats *stats = &mac->mac_stats;
9046 struct ieee80211_node *ni;
9047 int slot;
9048
9049 BWN_ASSERT_LOCKED(mac->mac_sc);
9050
9051 if (status->im)
9052 device_printf(sc->sc_dev, "TODO: STATUS IM\n");
9053 if (status->ampdu)
9054 device_printf(sc->sc_dev, "TODO: STATUS AMPDU\n");
9055 if (status->rtscnt) {
9056 if (status->rtscnt == 0xf)
9057 stats->rtsfail++;
9058 else
9059 stats->rts++;
9060 }
9061
9062 if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
9063 if (status->ack) {
9064 dr = bwn_dma_parse_cookie(mac, status,
9065 status->cookie, &slot);
9066 if (dr == NULL) {
9067 device_printf(sc->sc_dev,
9068 "failed to parse cookie\n");
9069 return;
9070 }
9071 while (1) {
9072 dr->getdesc(dr, slot, &desc, &meta);
9073 if (meta->mt_islast) {
9074 ni = meta->mt_ni;
9075 bn = (struct bwn_node *)ni;
9076 ieee80211_amrr_tx_complete(&bn->bn_amn,
9077 status->ack, 0);
9078 break;
9079 }
9080 slot = bwn_dma_nextslot(dr, slot);
9081 }
9082 }
9083 bwn_dma_handle_txeof(mac, status);
9084 } else {
9085 if (status->ack) {
9086 tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9087 if (tq == NULL) {
9088 device_printf(sc->sc_dev,
9089 "failed to parse cookie\n");
9090 return;
9091 }
9092 ni = tp->tp_ni;
9093 bn = (struct bwn_node *)ni;
9094 ieee80211_amrr_tx_complete(&bn->bn_amn, status->ack, 0);
9095 }
9096 bwn_pio_handle_txeof(mac, status);
9097 }
9098
9099 bwn_phy_txpower_check(mac, 0);
9100}
9101
9102static uint8_t
9103bwn_pio_rxeof(struct bwn_pio_rxqueue *prq)
9104{
9105 struct bwn_mac *mac = prq->prq_mac;
9106 struct bwn_softc *sc = mac->mac_sc;
9107 struct bwn_rxhdr4 rxhdr;
9108 struct ifnet *ifp = sc->sc_ifp;
9109 struct mbuf *m;
9110 uint32_t ctl32, macstat, v32;
9111 unsigned int i, padding;
9112 uint16_t ctl16, len, v16;
9113 unsigned char *mp;
9114 char *data;
9115
9116 memset(&rxhdr, 0, sizeof(rxhdr));
9117
9118 if (prq->prq_rev >= 8) {
9119 ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
9120 if (!(ctl32 & BWN_PIO8_RXCTL_FRAMEREADY))
9121 return (0);
9122 bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9123 BWN_PIO8_RXCTL_FRAMEREADY);
9124 for (i = 0; i < 10; i++) {
9125 ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
9126 if (ctl32 & BWN_PIO8_RXCTL_DATAREADY)
9127 goto ready;
9128 DELAY(10);
9129 }
9130 } else {
9131 ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
9132 if (!(ctl16 & BWN_PIO_RXCTL_FRAMEREADY))
9133 return (0);
9134 bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL,
9135 BWN_PIO_RXCTL_FRAMEREADY);
9136 for (i = 0; i < 10; i++) {
9137 ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
9138 if (ctl16 & BWN_PIO_RXCTL_DATAREADY)
9139 goto ready;
9140 DELAY(10);
9141 }
9142 }
9143 device_printf(sc->sc_dev, "%s: timed out\n", __func__);
9144 return (1);
9145ready:
9146 if (prq->prq_rev >= 8)
9147 siba_read_multi_4(sc->sc_dev, &rxhdr, sizeof(rxhdr),
9148 prq->prq_base + BWN_PIO8_RXDATA);
9149 else
9150 siba_read_multi_2(sc->sc_dev, &rxhdr, sizeof(rxhdr),
9151 prq->prq_base + BWN_PIO_RXDATA);
9152 len = le16toh(rxhdr.frame_len);
9153 if (len > 0x700) {
9154 device_printf(sc->sc_dev, "%s: len is too big\n", __func__);
9155 goto error;
9156 }
9157 if (len == 0) {
9158 device_printf(sc->sc_dev, "%s: len is 0\n", __func__);
9159 goto error;
9160 }
9161
9162 macstat = le32toh(rxhdr.mac_status);
9163 if (macstat & BWN_RX_MAC_FCSERR) {
9164 if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
9165 device_printf(sc->sc_dev, "%s: FCS error", __func__);
9166 goto error;
9167 }
9168 }
9169
9170 padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9171 KASSERT(len + padding <= MCLBYTES, ("too big..\n"));
9172 m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
9173 if (m == NULL) {
9174 device_printf(sc->sc_dev, "%s: out of memory", __func__);
9175 goto error;
9176 }
9177 mp = mtod(m, unsigned char *);
9178 if (prq->prq_rev >= 8) {
9179 siba_read_multi_4(sc->sc_dev, mp + padding, (len & ~3),
9180 prq->prq_base + BWN_PIO8_RXDATA);
9181 if (len & 3) {
9182 v32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXDATA);
9183 data = &(mp[len + padding - 1]);
9184 switch (len & 3) {
9185 case 3:
9186 *data = (v32 >> 16);
9187 data--;
9188 case 2:
9189 *data = (v32 >> 8);
9190 data--;
9191 case 1:
9192 *data = v32;
9193 }
9194 }
9195 } else {
9196 siba_read_multi_2(sc->sc_dev, mp + padding, (len & ~1),
9197 prq->prq_base + BWN_PIO_RXDATA);
9198 if (len & 1) {
9199 v16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXDATA);
9200 mp[len + padding - 1] = v16;
9201 }
9202 }
9203
9204 m->m_pkthdr.rcvif = ifp;
9205 m->m_len = m->m_pkthdr.len = len + padding;
9206
9207 bwn_rxeof(prq->prq_mac, m, &rxhdr);
9208
9209 return (1);
9210error:
9211 if (prq->prq_rev >= 8)
9212 bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9213 BWN_PIO8_RXCTL_DATAREADY);
9214 else
9215 bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL, BWN_PIO_RXCTL_DATAREADY);
9216 return (1);
9217}
9218
9219static int
9220bwn_dma_newbuf(struct bwn_dma_ring *dr, struct bwn_dmadesc_generic *desc,
9221 struct bwn_dmadesc_meta *meta, int init)
9222{
9223 struct bwn_mac *mac = dr->dr_mac;
9224 struct bwn_dma *dma = &mac->mac_method.dma;
9225 struct bwn_rxhdr4 *hdr;
9226 bus_dmamap_t map;
9227 bus_addr_t paddr;
9228 struct mbuf *m;
9229 int error;
9230
9231 m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
9232 if (m == NULL) {
9233 error = ENOBUFS;
9234
9235 /*
9236 * If the NIC is up and running, we need to:
9237 * - Clear RX buffer's header.
9238 * - Restore RX descriptor settings.
9239 */
9240 if (init)
9241 return (error);
9242 else
9243 goto back;
9244 }
9245 m->m_len = m->m_pkthdr.len = MCLBYTES;
9246
9247 bwn_dma_set_redzone(dr, m);
9248
9249 /*
9250 * Try to load RX buf into temporary DMA map
9251 */
9252 error = bus_dmamap_load_mbuf(dma->rxbuf_dtag, dr->dr_spare_dmap, m,
9253 bwn_dma_buf_addr, &paddr, BUS_DMA_NOWAIT);
9254 if (error) {
9255 m_freem(m);
9256
9257 /*
9258 * See the comment above
9259 */
9260 if (init)
9261 return (error);
9262 else
9263 goto back;
9264 }
9265
9266 if (!init)
9267 bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
9268 meta->mt_m = m;
9269 meta->mt_paddr = paddr;
9270
9271 /*
9272 * Swap RX buf's DMA map with the loaded temporary one
9273 */
9274 map = meta->mt_dmap;
9275 meta->mt_dmap = dr->dr_spare_dmap;
9276 dr->dr_spare_dmap = map;
9277
9278back:
9279 /*
9280 * Clear RX buf header
9281 */
9282 hdr = mtod(meta->mt_m, struct bwn_rxhdr4 *);
9283 bzero(hdr, sizeof(*hdr));
9284 bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
9285 BUS_DMASYNC_PREWRITE);
9286
9287 /*
9288 * Setup RX buf descriptor
9289 */
9290 dr->setdesc(dr, desc, paddr, meta->mt_m->m_len -
9291 sizeof(*hdr), 0, 0, 0);
9292 return (error);
9293}
9294
9295static void
9296bwn_dma_buf_addr(void *arg, bus_dma_segment_t *seg, int nseg,
9297 bus_size_t mapsz __unused, int error)
9298{
9299
9300 if (!error) {
9301 KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
9302 *((bus_addr_t *)arg) = seg->ds_addr;
9303 }
9304}
9305
9306static int
9307bwn_hwrate2ieeerate(int rate)
9308{
9309
9310 switch (rate) {
9311 case BWN_CCK_RATE_1MB:
9312 return (2);
9313 case BWN_CCK_RATE_2MB:
9314 return (4);
9315 case BWN_CCK_RATE_5MB:
9316 return (11);
9317 case BWN_CCK_RATE_11MB:
9318 return (22);
9319 case BWN_OFDM_RATE_6MB:
9320 return (12);
9321 case BWN_OFDM_RATE_9MB:
9322 return (18);
9323 case BWN_OFDM_RATE_12MB:
9324 return (24);
9325 case BWN_OFDM_RATE_18MB:
9326 return (36);
9327 case BWN_OFDM_RATE_24MB:
9328 return (48);
9329 case BWN_OFDM_RATE_36MB:
9330 return (72);
9331 case BWN_OFDM_RATE_48MB:
9332 return (96);
9333 case BWN_OFDM_RATE_54MB:
9334 return (108);
9335 default:
9336 printf("Ooops\n");
9337 return (0);
9338 }
9339}
9340
9341static void
9342bwn_rxeof(struct bwn_mac *mac, struct mbuf *m, const void *_rxhdr)
9343{
9344 const struct bwn_rxhdr4 *rxhdr = _rxhdr;
9345 struct bwn_plcp6 *plcp;
9346 struct bwn_softc *sc = mac->mac_sc;
9347 struct ieee80211_frame_min *wh;
9348 struct ieee80211_node *ni;
9349 struct ifnet *ifp = sc->sc_ifp;
9350 struct ieee80211com *ic = ifp->if_l2com;
9351 uint32_t macstat;
9352 int padding, rate, rssi = 0, noise = 0, type;
9353 uint16_t phytype, phystat0, phystat3, chanstat;
9354 unsigned char *mp = mtod(m, unsigned char *);
9355 static int rx_mac_dec_rpt = 0;
9356
9357 BWN_ASSERT_LOCKED(sc);
9358
9359 phystat0 = le16toh(rxhdr->phy_status0);
9360 phystat3 = le16toh(rxhdr->phy_status3);
9361 macstat = le32toh(rxhdr->mac_status);
9362 chanstat = le16toh(rxhdr->channel);
9363 phytype = chanstat & BWN_RX_CHAN_PHYTYPE;
9364
9365 if (macstat & BWN_RX_MAC_FCSERR)
9366 device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_FCS_CRC\n");
9367 if (phystat0 & (BWN_RX_PHYST0_PLCPHCF | BWN_RX_PHYST0_PLCPFV))
9368 device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_PLCP_CRC\n");
9369 if (macstat & BWN_RX_MAC_DECERR)
9370 goto drop;
9371
9372 padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9373 if (m->m_pkthdr.len < (sizeof(struct bwn_plcp6) + padding)) {
9374 device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9375 m->m_pkthdr.len);
9376 goto drop;
9377 }
9378 plcp = (struct bwn_plcp6 *)(mp + padding);
9379 m_adj(m, sizeof(struct bwn_plcp6) + padding);
9380 if (m->m_pkthdr.len < IEEE80211_MIN_LEN) {
9381 device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9382 m->m_pkthdr.len);
9383 goto drop;
9384 }
9385 wh = mtod(m, struct ieee80211_frame_min *);
9386
9387 if (macstat & BWN_RX_MAC_DEC && rx_mac_dec_rpt++ < 50)
9388 device_printf(sc->sc_dev,
9389 "RX decryption attempted (old %d keyidx %#x)\n",
9390 BWN_ISOLDFMT(mac),
9391 (macstat & BWN_RX_MAC_KEYIDX) >> BWN_RX_MAC_KEYIDX_SHIFT);
9392
9393 /* XXX calculating RSSI & noise & antenna */
9394
9395 if (phystat0 & BWN_RX_PHYST0_OFDM)
9396 rate = bwn_plcp_get_ofdmrate(mac, plcp,
9397 phytype == BWN_PHYTYPE_A);
9398 else
9399 rate = bwn_plcp_get_cckrate(mac, plcp);
9400 if (rate == -1) {
9401 if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADPLCP))
9402 goto drop;
9403 }
9404 sc->sc_rx_rate = bwn_hwrate2ieeerate(rate);
9405
9406 /* RX radio tap */
9407 if (ieee80211_radiotap_active(ic))
9408 bwn_rx_radiotap(mac, m, rxhdr, plcp, rate, rssi, noise);
9409 m_adj(m, -IEEE80211_CRC_LEN);
9410
9411 rssi = rxhdr->phy.abg.rssi; /* XXX incorrect RSSI calculation? */
9412 noise = mac->mac_stats.link_noise;
9413
9414 BWN_UNLOCK(sc);
9415
9416 ni = ieee80211_find_rxnode(ic, wh);
9417 if (ni != NULL) {
9418 type = ieee80211_input(ni, m, rssi, noise);
9419 ieee80211_free_node(ni);
9420 } else
9421 type = ieee80211_input_all(ic, m, rssi, noise);
9422
9423 BWN_LOCK(sc);
9424 return;
9425drop:
9426 device_printf(sc->sc_dev, "%s: dropped\n", __func__);
9427}
9428
9429static void
9430bwn_dma_handle_txeof(struct bwn_mac *mac,
9431 const struct bwn_txstatus *status)
9432{
9433 struct bwn_dma *dma = &mac->mac_method.dma;
9434 struct bwn_dma_ring *dr;
9435 struct bwn_dmadesc_generic *desc;
9436 struct bwn_dmadesc_meta *meta;
9437 struct bwn_softc *sc = mac->mac_sc;
9438 struct ieee80211_node *ni;
9439 struct ifnet *ifp = sc->sc_ifp;
9440 struct mbuf *m;
9441 int slot;
9442
9443 BWN_ASSERT_LOCKED(sc);
9444
9445 dr = bwn_dma_parse_cookie(mac, status, status->cookie, &slot);
9446 if (dr == NULL) {
9447 device_printf(sc->sc_dev, "failed to parse cookie\n");
9448 return;
9449 }
9450 KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
9451
9452 while (1) {
9453 KASSERT(slot >= 0 && slot < dr->dr_numslots,
9454 ("%s:%d: fail", __func__, __LINE__));
9455 dr->getdesc(dr, slot, &desc, &meta);
9456
9457 if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
9458 bus_dmamap_unload(dr->dr_txring_dtag, meta->mt_dmap);
9459 else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
9460 bus_dmamap_unload(dma->txbuf_dtag, meta->mt_dmap);
9461
9462 if (meta->mt_islast) {
9463 KASSERT(meta->mt_m != NULL,
9464 ("%s:%d: fail", __func__, __LINE__));
9465
9466 ni = meta->mt_ni;
9467 m = meta->mt_m;
9468 if (ni != NULL) {
9469 /*
9470 * Do any tx complete callback. Note this must
9471 * be done before releasing the node reference.
9472 */
9473 if (m->m_flags & M_TXCB)
9474 ieee80211_process_callback(ni, m, 0);
9475 ieee80211_free_node(ni);
9476 meta->mt_ni = NULL;
9477 }
9478 m_freem(m);
9479 meta->mt_m = NULL;
9480 } else {
9481 KASSERT(meta->mt_m == NULL,
9482 ("%s:%d: fail", __func__, __LINE__));
9483 }
9484
9485 dr->dr_usedslot--;
9486 if (meta->mt_islast) {
9487 ifp->if_opackets++;
9488 break;
9489 }
9490 slot = bwn_dma_nextslot(dr, slot);
9491 }
9492 sc->sc_watchdog_timer = 0;
9493 if (dr->dr_stop) {
9494 KASSERT(bwn_dma_freeslot(dr) >= BWN_TX_SLOTS_PER_FRAME,
9495 ("%s:%d: fail", __func__, __LINE__));
9496 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
9497 dr->dr_stop = 0;
9498 }
9499}
9500
9501static void
9502bwn_pio_handle_txeof(struct bwn_mac *mac,
9503 const struct bwn_txstatus *status)
9504{
9505 struct bwn_pio_txqueue *tq;
9506 struct bwn_pio_txpkt *tp = NULL;
9507 struct bwn_softc *sc = mac->mac_sc;
9508 struct ifnet *ifp = sc->sc_ifp;
9509
9510 BWN_ASSERT_LOCKED(sc);
9511
9512 tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9513 if (tq == NULL)
9514 return;
9515
9516 tq->tq_used -= roundup(tp->tp_m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
9517 tq->tq_free++;
9518
9519 if (tp->tp_ni != NULL) {
9520 /*
9521 * Do any tx complete callback. Note this must
9522 * be done before releasing the node reference.
9523 */
9524 if (tp->tp_m->m_flags & M_TXCB)
9525 ieee80211_process_callback(tp->tp_ni, tp->tp_m, 0);
9526 ieee80211_free_node(tp->tp_ni);
9527 tp->tp_ni = NULL;
9528 }
9529 m_freem(tp->tp_m);
9530 tp->tp_m = NULL;
9531 TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
9532
9533 ifp->if_opackets++;
9534
9535 sc->sc_watchdog_timer = 0;
9536 if (tq->tq_stop) {
9537 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
9538 tq->tq_stop = 0;
9539 }
9540}
9541
9542static void
9543bwn_phy_txpower_check(struct bwn_mac *mac, uint32_t flags)
9544{
9545 struct bwn_softc *sc = mac->mac_sc;
9546 struct bwn_phy *phy = &mac->mac_phy;
9547 struct ifnet *ifp = sc->sc_ifp;
9548 struct ieee80211com *ic = ifp->if_l2com;
9549 unsigned long now;
9550 int result;
9551
9552 BWN_GETTIME(now);
9553
9554 if (!(flags & BWN_TXPWR_IGNORE_TIME) && time_before(now, phy->nexttime))
9555 return;
9556 phy->nexttime = now + 2 * 1000;
9557
9558 if (siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM &&
9559 siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306)
9560 return;
9561
9562 if (phy->recalc_txpwr != NULL) {
9563 result = phy->recalc_txpwr(mac,
9564 (flags & BWN_TXPWR_IGNORE_TSSI) ? 1 : 0);
9565 if (result == BWN_TXPWR_RES_DONE)
9566 return;
9567 KASSERT(result == BWN_TXPWR_RES_NEED_ADJUST,
9568 ("%s: fail", __func__));
9569 KASSERT(phy->set_txpwr != NULL, ("%s: fail", __func__));
9570
9571 ieee80211_runtask(ic, &mac->mac_txpower);
9572 }
9573}
9574
9575static uint16_t
9576bwn_pio_rx_read_2(struct bwn_pio_rxqueue *prq, uint16_t offset)
9577{
9578
9579 return (BWN_READ_2(prq->prq_mac, prq->prq_base + offset));
9580}
9581
9582static uint32_t
9583bwn_pio_rx_read_4(struct bwn_pio_rxqueue *prq, uint16_t offset)
9584{
9585
9586 return (BWN_READ_4(prq->prq_mac, prq->prq_base + offset));
9587}
9588
9589static void
9590bwn_pio_rx_write_2(struct bwn_pio_rxqueue *prq, uint16_t offset, uint16_t value)
9591{
9592
9593 BWN_WRITE_2(prq->prq_mac, prq->prq_base + offset, value);
9594}
9595
9596static void
9597bwn_pio_rx_write_4(struct bwn_pio_rxqueue *prq, uint16_t offset, uint32_t value)
9598{
9599
9600 BWN_WRITE_4(prq->prq_mac, prq->prq_base + offset, value);
9601}
9602
9603static int
9604bwn_ieeerate2hwrate(struct bwn_softc *sc, int rate)
9605{
9606
9607 switch (rate) {
9608 /* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
9609 case 12:
9610 return (BWN_OFDM_RATE_6MB);
9611 case 18:
9612 return (BWN_OFDM_RATE_9MB);
9613 case 24:
9614 return (BWN_OFDM_RATE_12MB);
9615 case 36:
9616 return (BWN_OFDM_RATE_18MB);
9617 case 48:
9618 return (BWN_OFDM_RATE_24MB);
9619 case 72:
9620 return (BWN_OFDM_RATE_36MB);
9621 case 96:
9622 return (BWN_OFDM_RATE_48MB);
9623 case 108:
9624 return (BWN_OFDM_RATE_54MB);
9625 /* CCK rates (NB: not IEEE std, device-specific) */
9626 case 2:
9627 return (BWN_CCK_RATE_1MB);
9628 case 4:
9629 return (BWN_CCK_RATE_2MB);
9630 case 11:
9631 return (BWN_CCK_RATE_5MB);
9632 case 22:
9633 return (BWN_CCK_RATE_11MB);
9634 }
9635
9636 device_printf(sc->sc_dev, "unsupported rate %d\n", rate);
9637 return (BWN_CCK_RATE_1MB);
9638}
9639
9640static int
9641bwn_set_txhdr(struct bwn_mac *mac, struct ieee80211_node *ni,
9642 struct mbuf *m, struct bwn_txhdr *txhdr, uint16_t cookie)
9643{
9644 const struct bwn_phy *phy = &mac->mac_phy;
9645 struct bwn_softc *sc = mac->mac_sc;
9646 struct ieee80211_frame *wh;
9647 struct ieee80211_frame *protwh;
9648 struct ieee80211_frame_cts *cts;
9649 struct ieee80211_frame_rts *rts;
9650 const struct ieee80211_txparam *tp;
9651 struct ieee80211vap *vap = ni->ni_vap;
9652 struct ifnet *ifp = sc->sc_ifp;
9653 struct ieee80211com *ic = ifp->if_l2com;
9654 struct mbuf *mprot;
9655 unsigned int len;
9656 uint32_t macctl = 0;
9657 int protdur, rts_rate, rts_rate_fb, ismcast, isshort, rix, type;
9658 uint16_t phyctl = 0;
9659 uint8_t rate, rate_fb;
9660
9661 wh = mtod(m, struct ieee80211_frame *);
9662 memset(txhdr, 0, sizeof(*txhdr));
9663
9664 type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
9665 ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
9666 isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0;
9667
9668 /*
9669 * Find TX rate
9670 */
9671 tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)];
9672 if (type != IEEE80211_FC0_TYPE_DATA || (m->m_flags & M_EAPOL))
9673 rate = rate_fb = tp->mgmtrate;
9674 else if (ismcast)
9675 rate = rate_fb = tp->mcastrate;
9676 else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
9677 rate = rate_fb = tp->ucastrate;
9678 else {
9679 rix = ieee80211_amrr_choose(ni, &BWN_NODE(ni)->bn_amn);
9680 rate = ni->ni_txrate;
9681
9682 if (rix > 0)
9683 rate_fb = ni->ni_rates.rs_rates[rix - 1] &
9684 IEEE80211_RATE_VAL;
9685 else
9686 rate_fb = rate;
9687 }
9688
9689 sc->sc_tx_rate = rate;
9690
9691 rate = bwn_ieeerate2hwrate(sc, rate);
9692 rate_fb = bwn_ieeerate2hwrate(sc, rate_fb);
9693
9694 txhdr->phyrate = (BWN_ISOFDMRATE(rate)) ? bwn_plcp_getofdm(rate) :
9695 bwn_plcp_getcck(rate);
9696 bcopy(wh->i_fc, txhdr->macfc, sizeof(txhdr->macfc));
9697 bcopy(wh->i_addr1, txhdr->addr1, IEEE80211_ADDR_LEN);
9698
9699 if ((rate_fb == rate) ||
9700 (*(u_int16_t *)wh->i_dur & htole16(0x8000)) ||
9701 (*(u_int16_t *)wh->i_dur == htole16(0)))
9702 txhdr->dur_fb = *(u_int16_t *)wh->i_dur;
9703 else
9704 txhdr->dur_fb = ieee80211_compute_duration(ic->ic_rt,
9705 m->m_pkthdr.len, rate, isshort);
9706
9707 /* XXX TX encryption */
9708 bwn_plcp_genhdr(BWN_ISOLDFMT(mac) ?
9709 (struct bwn_plcp4 *)(&txhdr->body.old.plcp) :
9710 (struct bwn_plcp4 *)(&txhdr->body.new.plcp),
9711 m->m_pkthdr.len + IEEE80211_CRC_LEN, rate);
9712 bwn_plcp_genhdr((struct bwn_plcp4 *)(&txhdr->plcp_fb),
9713 m->m_pkthdr.len + IEEE80211_CRC_LEN, rate_fb);
9714
9715 txhdr->eftypes |= (BWN_ISOFDMRATE(rate_fb)) ? BWN_TX_EFT_FB_OFDM :
9716 BWN_TX_EFT_FB_CCK;
9717 txhdr->chan = phy->chan;
9718 phyctl |= (BWN_ISOFDMRATE(rate)) ? BWN_TX_PHY_ENC_OFDM :
9719 BWN_TX_PHY_ENC_CCK;
9720 if (isshort && (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9721 rate == BWN_CCK_RATE_11MB))
9722 phyctl |= BWN_TX_PHY_SHORTPRMBL;
9723
9724 /* XXX TX antenna selection */
9725
9726 switch (bwn_antenna_sanitize(mac, 0)) {
9727 case 0:
9728 phyctl |= BWN_TX_PHY_ANT01AUTO;
9729 break;
9730 case 1:
9731 phyctl |= BWN_TX_PHY_ANT0;
9732 break;
9733 case 2:
9734 phyctl |= BWN_TX_PHY_ANT1;
9735 break;
9736 case 3:
9737 phyctl |= BWN_TX_PHY_ANT2;
9738 break;
9739 case 4:
9740 phyctl |= BWN_TX_PHY_ANT3;
9741 break;
9742 default:
9743 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9744 }
9745
9746 if (!ismcast)
9747 macctl |= BWN_TX_MAC_ACK;
9748
9749 macctl |= (BWN_TX_MAC_HWSEQ | BWN_TX_MAC_START_MSDU);
9750 if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
9751 m->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold)
9752 macctl |= BWN_TX_MAC_LONGFRAME;
9753
9754 if (ic->ic_flags & IEEE80211_F_USEPROT) {
9755 /* XXX RTS rate is always 1MB??? */
9756 rts_rate = BWN_CCK_RATE_1MB;
9757 rts_rate_fb = bwn_get_fbrate(rts_rate);
9758
9759 protdur = ieee80211_compute_duration(ic->ic_rt,
9760 m->m_pkthdr.len, rate, isshort) +
9761 + ieee80211_ack_duration(ic->ic_rt, rate, isshort);
9762
9763 if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) {
9764 cts = (struct ieee80211_frame_cts *)(BWN_ISOLDFMT(mac) ?
9765 (txhdr->body.old.rts_frame) :
9766 (txhdr->body.new.rts_frame));
9767 mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr,
9768 protdur);
9769 KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9770 bcopy(mtod(mprot, uint8_t *), (uint8_t *)cts,
9771 mprot->m_pkthdr.len);
9772 m_freem(mprot);
9773 macctl |= BWN_TX_MAC_SEND_CTSTOSELF;
9774 len = sizeof(struct ieee80211_frame_cts);
9775 } else {
9776 rts = (struct ieee80211_frame_rts *)(BWN_ISOLDFMT(mac) ?
9777 (txhdr->body.old.rts_frame) :
9778 (txhdr->body.new.rts_frame));
9779 protdur += ieee80211_ack_duration(ic->ic_rt, rate,
9780 isshort);
9781 mprot = ieee80211_alloc_rts(ic, wh->i_addr1,
9782 wh->i_addr2, protdur);
9783 KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9784 bcopy(mtod(mprot, uint8_t *), (uint8_t *)rts,
9785 mprot->m_pkthdr.len);
9786 m_freem(mprot);
9787 macctl |= BWN_TX_MAC_SEND_RTSCTS;
9788 len = sizeof(struct ieee80211_frame_rts);
9789 }
9790 len += IEEE80211_CRC_LEN;
9791 bwn_plcp_genhdr((struct bwn_plcp4 *)((BWN_ISOLDFMT(mac)) ?
9792 &txhdr->body.old.rts_plcp :
9793 &txhdr->body.new.rts_plcp), len, rts_rate);
9794 bwn_plcp_genhdr((struct bwn_plcp4 *)&txhdr->rts_plcp_fb, len,
9795 rts_rate_fb);
9796
9797 protwh = (struct ieee80211_frame *)(BWN_ISOLDFMT(mac) ?
9798 (&txhdr->body.old.rts_frame) :
9799 (&txhdr->body.new.rts_frame));
9800 txhdr->rts_dur_fb = *(u_int16_t *)protwh->i_dur;
9801
9802 if (BWN_ISOFDMRATE(rts_rate)) {
9803 txhdr->eftypes |= BWN_TX_EFT_RTS_OFDM;
9804 txhdr->phyrate_rts = bwn_plcp_getofdm(rts_rate);
9805 } else {
9806 txhdr->eftypes |= BWN_TX_EFT_RTS_CCK;
9807 txhdr->phyrate_rts = bwn_plcp_getcck(rts_rate);
9808 }
9809 txhdr->eftypes |= (BWN_ISOFDMRATE(rts_rate_fb)) ?
9810 BWN_TX_EFT_RTS_FBOFDM : BWN_TX_EFT_RTS_FBCCK;
9811 }
9812
9813 if (BWN_ISOLDFMT(mac))
9814 txhdr->body.old.cookie = htole16(cookie);
9815 else
9816 txhdr->body.new.cookie = htole16(cookie);
9817
9818 txhdr->macctl = htole32(macctl);
9819 txhdr->phyctl = htole16(phyctl);
9820
9821 /*
9822 * TX radio tap
9823 */
9824 if (ieee80211_radiotap_active_vap(vap)) {
9825 sc->sc_tx_th.wt_flags = 0;
9826 if (wh->i_fc[1] & IEEE80211_FC1_WEP)
9827 sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP;
9828 if (isshort &&
9829 (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9830 rate == BWN_CCK_RATE_11MB))
9831 sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
9832 sc->sc_tx_th.wt_rate = rate;
9833
9834 ieee80211_radiotap_tx(vap, m);
9835 }
9836
9837 return (0);
9838}
9839
9840static void
9841bwn_plcp_genhdr(struct bwn_plcp4 *plcp, const uint16_t octets,
9842 const uint8_t rate)
9843{
9844 uint32_t d, plen;
9845 uint8_t *raw = plcp->o.raw;
9846
9847 if (BWN_ISOFDMRATE(rate)) {
9848 d = bwn_plcp_getofdm(rate);
9849 KASSERT(!(octets & 0xf000),
9850 ("%s:%d: fail", __func__, __LINE__));
9851 d |= (octets << 5);
9852 plcp->o.data = htole32(d);
9853 } else {
9854 plen = octets * 16 / rate;
9855 if ((octets * 16 % rate) > 0) {
9856 plen++;
9857 if ((rate == BWN_CCK_RATE_11MB)
9858 && ((octets * 8 % 11) < 4)) {
9859 raw[1] = 0x84;
9860 } else
9861 raw[1] = 0x04;
9862 } else
9863 raw[1] = 0x04;
9864 plcp->o.data |= htole32(plen << 16);
9865 raw[0] = bwn_plcp_getcck(rate);
9866 }
9867}
9868
9869static uint8_t
9870bwn_antenna_sanitize(struct bwn_mac *mac, uint8_t n)
9871{
9872 struct bwn_softc *sc = mac->mac_sc;
9873 uint8_t mask;
9874
9875 if (n == 0)
9876 return (0);
9877 if (mac->mac_phy.gmode)
9878 mask = siba_sprom_get_ant_bg(sc->sc_dev);
9879 else
9880 mask = siba_sprom_get_ant_a(sc->sc_dev);
9881 if (!(mask & (1 << (n - 1))))
9882 return (0);
9883 return (n);
9884}
9885
9886static uint8_t
9887bwn_get_fbrate(uint8_t bitrate)
9888{
9889 switch (bitrate) {
9890 case BWN_CCK_RATE_1MB:
9891 return (BWN_CCK_RATE_1MB);
9892 case BWN_CCK_RATE_2MB:
9893 return (BWN_CCK_RATE_1MB);
9894 case BWN_CCK_RATE_5MB:
9895 return (BWN_CCK_RATE_2MB);
9896 case BWN_CCK_RATE_11MB:
9897 return (BWN_CCK_RATE_5MB);
9898 case BWN_OFDM_RATE_6MB:
9899 return (BWN_CCK_RATE_5MB);
9900 case BWN_OFDM_RATE_9MB:
9901 return (BWN_OFDM_RATE_6MB);
9902 case BWN_OFDM_RATE_12MB:
9903 return (BWN_OFDM_RATE_9MB);
9904 case BWN_OFDM_RATE_18MB:
9905 return (BWN_OFDM_RATE_12MB);
9906 case BWN_OFDM_RATE_24MB:
9907 return (BWN_OFDM_RATE_18MB);
9908 case BWN_OFDM_RATE_36MB:
9909 return (BWN_OFDM_RATE_24MB);
9910 case BWN_OFDM_RATE_48MB:
9911 return (BWN_OFDM_RATE_36MB);
9912 case BWN_OFDM_RATE_54MB:
9913 return (BWN_OFDM_RATE_48MB);
9914 }
9915 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9916 return (0);
9917}
9918
9919static uint32_t
9920bwn_pio_write_multi_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9921 uint32_t ctl, const void *_data, int len)
9922{
9923 struct bwn_softc *sc = mac->mac_sc;
9924 uint32_t value = 0;
9925 const uint8_t *data = _data;
9926
9927 ctl |= BWN_PIO8_TXCTL_0_7 | BWN_PIO8_TXCTL_8_15 |
9928 BWN_PIO8_TXCTL_16_23 | BWN_PIO8_TXCTL_24_31;
9929 bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9930
9931 siba_write_multi_4(sc->sc_dev, data, (len & ~3),
9932 tq->tq_base + BWN_PIO8_TXDATA);
9933 if (len & 3) {
9934 ctl &= ~(BWN_PIO8_TXCTL_8_15 | BWN_PIO8_TXCTL_16_23 |
9935 BWN_PIO8_TXCTL_24_31);
9936 data = &(data[len - 1]);
9937 switch (len & 3) {
9938 case 3:
9939 ctl |= BWN_PIO8_TXCTL_16_23;
9940 value |= (uint32_t)(*data) << 16;
9941 data--;
9942 case 2:
9943 ctl |= BWN_PIO8_TXCTL_8_15;
9944 value |= (uint32_t)(*data) << 8;
9945 data--;
9946 case 1:
9947 value |= (uint32_t)(*data);
9948 }
9949 bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9950 bwn_pio_write_4(mac, tq, BWN_PIO8_TXDATA, value);
9951 }
9952
9953 return (ctl);
9954}
9955
9956static void
9957bwn_pio_write_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9958 uint16_t offset, uint32_t value)
9959{
9960
9961 BWN_WRITE_4(mac, tq->tq_base + offset, value);
9962}
9963
9964static uint16_t
9965bwn_pio_write_multi_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9966 uint16_t ctl, const void *_data, int len)
9967{
9968 struct bwn_softc *sc = mac->mac_sc;
9969 const uint8_t *data = _data;
9970
9971 ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
9972 BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9973
9974 siba_write_multi_2(sc->sc_dev, data, (len & ~1),
9975 tq->tq_base + BWN_PIO_TXDATA);
9976 if (len & 1) {
9977 ctl &= ~BWN_PIO_TXCTL_WRITEHI;
9978 BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9979 BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data[len - 1]);
9980 }
9981
9982 return (ctl);
9983}
9984
9985static uint16_t
9986bwn_pio_write_mbuf_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9987 uint16_t ctl, struct mbuf *m0)
9988{
9989 int i, j = 0;
9990 uint16_t data = 0;
9991 const uint8_t *buf;
9992 struct mbuf *m = m0;
9993
9994 ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
9995 BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9996
9997 for (; m != NULL; m = m->m_next) {
9998 buf = mtod(m, const uint8_t *);
9999 for (i = 0; i < m->m_len; i++) {
10000 if (!((j++) % 2))
10001 data |= buf[i];
10002 else {
10003 data |= (buf[i] << 8);
10004 BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
10005 data = 0;
10006 }
10007 }
10008 }
10009 if (m0->m_pkthdr.len % 2) {
10010 ctl &= ~BWN_PIO_TXCTL_WRITEHI;
10011 BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
10012 BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
10013 }
10014
10015 return (ctl);
10016}
10017
10018static void
10019bwn_set_slot_time(struct bwn_mac *mac, uint16_t time)
10020{
10021
10022 if (mac->mac_phy.type != BWN_PHYTYPE_G)
10023 return;
10024 BWN_WRITE_2(mac, 0x684, 510 + time);
10025 bwn_shm_write_2(mac, BWN_SHARED, 0x0010, time);
10026}
10027
10028static struct bwn_dma_ring *
10029bwn_dma_select(struct bwn_mac *mac, uint8_t prio)
10030{
10031
10032 if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
10033 return (mac->mac_method.dma.wme[WME_AC_BE]);
10034
10035 switch (prio) {
10036 case 3:
10037 return (mac->mac_method.dma.wme[WME_AC_VO]);
10038 case 2:
10039 return (mac->mac_method.dma.wme[WME_AC_VI]);
10040 case 0:
10041 return (mac->mac_method.dma.wme[WME_AC_BE]);
10042 case 1:
10043 return (mac->mac_method.dma.wme[WME_AC_BK]);
10044 }
10045 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
10046 return (NULL);
10047}
10048
10049static int
10050bwn_dma_getslot(struct bwn_dma_ring *dr)
10051{
10052 int slot;
10053
10054 BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
10055
10056 KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
10057 KASSERT(!(dr->dr_stop), ("%s:%d: fail", __func__, __LINE__));
10058 KASSERT(bwn_dma_freeslot(dr) != 0, ("%s:%d: fail", __func__, __LINE__));
10059
10060 slot = bwn_dma_nextslot(dr, dr->dr_curslot);
10061 KASSERT(!(slot & ~0x0fff), ("%s:%d: fail", __func__, __LINE__));
10062 dr->dr_curslot = slot;
10063 dr->dr_usedslot++;
10064
10065 return (slot);
10066}
10067
10068static int
10069bwn_phy_shm_tssi_read(struct bwn_mac *mac, uint16_t shm_offset)
10070{
10071 const uint8_t ofdm = (shm_offset != BWN_SHARED_TSSI_CCK);
10072 unsigned int a, b, c, d;
10073 unsigned int avg;
10074 uint32_t tmp;
10075
10076 tmp = bwn_shm_read_4(mac, BWN_SHARED, shm_offset);
10077 a = tmp & 0xff;
10078 b = (tmp >> 8) & 0xff;
10079 c = (tmp >> 16) & 0xff;
10080 d = (tmp >> 24) & 0xff;
10081 if (a == 0 || a == BWN_TSSI_MAX || b == 0 || b == BWN_TSSI_MAX ||
10082 c == 0 || c == BWN_TSSI_MAX || d == 0 || d == BWN_TSSI_MAX)
10083 return (ENOENT);
10084 bwn_shm_write_4(mac, BWN_SHARED, shm_offset,
10085 BWN_TSSI_MAX | (BWN_TSSI_MAX << 8) |
10086 (BWN_TSSI_MAX << 16) | (BWN_TSSI_MAX << 24));
10087
10088 if (ofdm) {
10089 a = (a + 32) & 0x3f;
10090 b = (b + 32) & 0x3f;
10091 c = (c + 32) & 0x3f;
10092 d = (d + 32) & 0x3f;
10093 }
10094
10095 avg = (a + b + c + d + 2) / 4;
10096 if (ofdm) {
10097 if (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO)
10098 & BWN_HF_4DB_CCK_POWERBOOST)
10099 avg = (avg >= 13) ? (avg - 13) : 0;
10100 }
10101 return (avg);
10102}
10103
10104static void
10105bwn_phy_g_setatt(struct bwn_mac *mac, int *bbattp, int *rfattp)
10106{
10107 struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
10108 int rfatt = *rfattp;
10109 int bbatt = *bbattp;
10110
10111 while (1) {
10112 if (rfatt > lo->rfatt.max && bbatt > lo->bbatt.max - 4)
10113 break;
10114 if (rfatt < lo->rfatt.min && bbatt < lo->bbatt.min + 4)
10115 break;
10116 if (bbatt > lo->bbatt.max && rfatt > lo->rfatt.max - 1)
10117 break;
10118 if (bbatt < lo->bbatt.min && rfatt < lo->rfatt.min + 1)
10119 break;
10120 if (bbatt > lo->bbatt.max) {
10121 bbatt -= 4;
10122 rfatt += 1;
10123 continue;
10124 }
10125 if (bbatt < lo->bbatt.min) {
10126 bbatt += 4;
10127 rfatt -= 1;
10128 continue;
10129 }
10130 if (rfatt > lo->rfatt.max) {
10131 rfatt -= 1;
10132 bbatt += 4;
10133 continue;
10134 }
10135 if (rfatt < lo->rfatt.min) {
10136 rfatt += 1;
10137 bbatt -= 4;
10138 continue;
10139 }
10140 break;
10141 }
10142
10143 *rfattp = MIN(MAX(rfatt, lo->rfatt.min), lo->rfatt.max);
10144 *bbattp = MIN(MAX(bbatt, lo->bbatt.min), lo->bbatt.max);
10145}
10146
10147static void
10148bwn_phy_lock(struct bwn_mac *mac)
10149{
10150 struct bwn_softc *sc = mac->mac_sc;
10151 struct ieee80211com *ic = sc->sc_ifp->if_l2com;
10152
10153 KASSERT(siba_get_revid(sc->sc_dev) >= 3,
10154 ("%s: unsupported rev %d", __func__, siba_get_revid(sc->sc_dev)));
10155
10156 if (ic->ic_opmode != IEEE80211_M_HOSTAP)
10157 bwn_psctl(mac, BWN_PS_AWAKE);
10158}
10159
10160static void
10161bwn_phy_unlock(struct bwn_mac *mac)
10162{
10163 struct bwn_softc *sc = mac->mac_sc;
10164 struct ieee80211com *ic = sc->sc_ifp->if_l2com;
10165
10166 KASSERT(siba_get_revid(sc->sc_dev) >= 3,
10167 ("%s: unsupported rev %d", __func__, siba_get_revid(sc->sc_dev)));
10168
10169 if (ic->ic_opmode != IEEE80211_M_HOSTAP)
10170 bwn_psctl(mac, 0);
10171}
10172
10173static void
10174bwn_rf_lock(struct bwn_mac *mac)
10175{
10176
10177 BWN_WRITE_4(mac, BWN_MACCTL,
10178 BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_RADIO_LOCK);
10179 BWN_READ_4(mac, BWN_MACCTL);
10180 DELAY(10);
10181}
10182
10183static void
10184bwn_rf_unlock(struct bwn_mac *mac)
10185{
10186
10187 BWN_READ_2(mac, BWN_PHYVER);
10188 BWN_WRITE_4(mac, BWN_MACCTL,
10189 BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_RADIO_LOCK);
10190}
10191
10192static struct bwn_pio_txqueue *
10193bwn_pio_parse_cookie(struct bwn_mac *mac, uint16_t cookie,
10194 struct bwn_pio_txpkt **pack)
10195{
10196 struct bwn_pio *pio = &mac->mac_method.pio;
10197 struct bwn_pio_txqueue *tq = NULL;
10198 unsigned int index;
10199
10200 switch (cookie & 0xf000) {
10201 case 0x1000:
10202 tq = &pio->wme[WME_AC_BK];
10203 break;
10204 case 0x2000:
10205 tq = &pio->wme[WME_AC_BE];
10206 break;
10207 case 0x3000:
10208 tq = &pio->wme[WME_AC_VI];
10209 break;
10210 case 0x4000:
10211 tq = &pio->wme[WME_AC_VO];
10212 break;
10213 case 0x5000:
10214 tq = &pio->mcast;
10215 break;
10216 }
10217 KASSERT(tq != NULL, ("%s:%d: fail", __func__, __LINE__));
10218 if (tq == NULL)
10219 return (NULL);
10220 index = (cookie & 0x0fff);
10221 KASSERT(index < N(tq->tq_pkts), ("%s:%d: fail", __func__, __LINE__));
10222 if (index >= N(tq->tq_pkts))
10223 return (NULL);
10224 *pack = &tq->tq_pkts[index];
10225 KASSERT(*pack != NULL, ("%s:%d: fail", __func__, __LINE__));
10226 return (tq);
10227}
10228
10229static void
10230bwn_txpwr(void *arg, int npending)
10231{
10232 struct bwn_mac *mac = arg;
10233 struct bwn_softc *sc = mac->mac_sc;
10234
10235 BWN_LOCK(sc);
10236 if (mac && mac->mac_status >= BWN_MAC_STATUS_STARTED &&
10237 mac->mac_phy.set_txpwr != NULL)
10238 mac->mac_phy.set_txpwr(mac);
10239 BWN_UNLOCK(sc);
10240}
10241
10242static void
10243bwn_task_15s(struct bwn_mac *mac)
10244{
10245 uint16_t reg;
10246
10247 if (mac->mac_fw.opensource) {
10248 reg = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG);
10249 if (reg) {
10250 bwn_restart(mac, "fw watchdog");
10251 return;
10252 }
10253 bwn_shm_write_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG, 1);
10254 }
10255 if (mac->mac_phy.task_15s)
10256 mac->mac_phy.task_15s(mac);
10257
10258 mac->mac_phy.txerrors = BWN_TXERROR_MAX;
10259}
10260
10261static void
10262bwn_task_30s(struct bwn_mac *mac)
10263{
10264
10265 if (mac->mac_phy.type != BWN_PHYTYPE_G || mac->mac_noise.noi_running)
10266 return;
10267 mac->mac_noise.noi_running = 1;
10268 mac->mac_noise.noi_nsamples = 0;
10269
10270 bwn_noise_gensample(mac);
10271}
10272
10273static void
10274bwn_task_60s(struct bwn_mac *mac)
10275{
10276
10277 if (mac->mac_phy.task_60s)
10278 mac->mac_phy.task_60s(mac);
10279 bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME);
10280}
10281
10282static void
10283bwn_tasks(void *arg)
10284{
10285 struct bwn_mac *mac = arg;
10286 struct bwn_softc *sc = mac->mac_sc;
10287
10288 BWN_ASSERT_LOCKED(sc);
10289 if (mac->mac_status != BWN_MAC_STATUS_STARTED)
10290 return;
10291
10292 if (mac->mac_task_state % 4 == 0)
10293 bwn_task_60s(mac);
10294 if (mac->mac_task_state % 2 == 0)
10295 bwn_task_30s(mac);
10296 bwn_task_15s(mac);
10297
10298 mac->mac_task_state++;
10299 callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
10300}
10301
10302static int
10303bwn_plcp_get_ofdmrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp, uint8_t a)
10304{
10305 struct bwn_softc *sc = mac->mac_sc;
10306
10307 KASSERT(a == 0, ("not support APHY\n"));
10308
10309 switch (plcp->o.raw[0] & 0xf) {
10310 case 0xb:
10311 return (BWN_OFDM_RATE_6MB);
10312 case 0xf:
10313 return (BWN_OFDM_RATE_9MB);
10314 case 0xa:
10315 return (BWN_OFDM_RATE_12MB);
10316 case 0xe:
10317 return (BWN_OFDM_RATE_18MB);
10318 case 0x9:
10319 return (BWN_OFDM_RATE_24MB);
10320 case 0xd:
10321 return (BWN_OFDM_RATE_36MB);
10322 case 0x8:
10323 return (BWN_OFDM_RATE_48MB);
10324 case 0xc:
10325 return (BWN_OFDM_RATE_54MB);
10326 }
10327 device_printf(sc->sc_dev, "incorrect OFDM rate %d\n",
10328 plcp->o.raw[0] & 0xf);
10329 return (-1);
10330}
10331
10332static int
10333bwn_plcp_get_cckrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp)
10334{
10335 struct bwn_softc *sc = mac->mac_sc;
10336
10337 switch (plcp->o.raw[0]) {
10338 case 0x0a:
10339 return (BWN_CCK_RATE_1MB);
10340 case 0x14:
10341 return (BWN_CCK_RATE_2MB);
10342 case 0x37:
10343 return (BWN_CCK_RATE_5MB);
10344 case 0x6e:
10345 return (BWN_CCK_RATE_11MB);
10346 }
10347 device_printf(sc->sc_dev, "incorrect CCK rate %d\n", plcp->o.raw[0]);
10348 return (-1);
10349}
10350
10351static void
10352bwn_rx_radiotap(struct bwn_mac *mac, struct mbuf *m,
10353 const struct bwn_rxhdr4 *rxhdr, struct bwn_plcp6 *plcp, int rate,
10354 int rssi, int noise)
10355{
10356 struct bwn_softc *sc = mac->mac_sc;
10357 const struct ieee80211_frame_min *wh;
10358 uint64_t tsf;
10359 uint16_t low_mactime_now;
10360
10361 if (htole16(rxhdr->phy_status0) & BWN_RX_PHYST0_SHORTPRMBL)
10362 sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
10363
10364 wh = mtod(m, const struct ieee80211_frame_min *);
10365 if (wh->i_fc[1] & IEEE80211_FC1_WEP)
10366 sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_WEP;
10367
10368 bwn_tsf_read(mac, &tsf);
10369 low_mactime_now = tsf;
10370 tsf = tsf & ~0xffffULL;
10371 tsf += le16toh(rxhdr->mac_time);
10372 if (low_mactime_now < le16toh(rxhdr->mac_time))
10373 tsf -= 0x10000;
10374
10375 sc->sc_rx_th.wr_tsf = tsf;
10376 sc->sc_rx_th.wr_rate = rate;
10377 sc->sc_rx_th.wr_antsignal = rssi;
10378 sc->sc_rx_th.wr_antnoise = noise;
10379}
10380
10381static void
10382bwn_tsf_read(struct bwn_mac *mac, uint64_t *tsf)
10383{
10384 uint32_t low, high;
10385
10386 KASSERT(siba_get_revid(mac->mac_sc->sc_dev) >= 3,
10387 ("%s:%d: fail", __func__, __LINE__));
10388
10389 low = BWN_READ_4(mac, BWN_REV3PLUS_TSF_LOW);
10390 high = BWN_READ_4(mac, BWN_REV3PLUS_TSF_HIGH);
10391 *tsf = high;
10392 *tsf <<= 32;
10393 *tsf |= low;
10394}
10395
10396static int
10397bwn_dma_attach(struct bwn_mac *mac)
10398{
10399 struct bwn_dma *dma = &mac->mac_method.dma;
10400 struct bwn_softc *sc = mac->mac_sc;
10401 bus_addr_t lowaddr = 0;
10402 int error;
10403
10404 if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
10405 return (0);
10406
10407 KASSERT(siba_get_revid(sc->sc_dev) >= 5, ("%s: fail", __func__));
10408
10409 mac->mac_flags |= BWN_MAC_FLAG_DMA;
10410
10411 dma->dmatype = bwn_dma_gettype(mac);
10412 if (dma->dmatype == BWN_DMA_30BIT)
10413 lowaddr = BWN_BUS_SPACE_MAXADDR_30BIT;
10414 else if (dma->dmatype == BWN_DMA_32BIT)
10415 lowaddr = BUS_SPACE_MAXADDR_32BIT;
10416 else
10417 lowaddr = BUS_SPACE_MAXADDR;
10418
10419 /*
10420 * Create top level DMA tag
10421 */
10422 error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), /* parent */
10423 BWN_ALIGN, 0, /* alignment, bounds */
10424 lowaddr, /* lowaddr */
10425 BUS_SPACE_MAXADDR, /* highaddr */
10426 NULL, NULL, /* filter, filterarg */
10427 MAXBSIZE, /* maxsize */
10428 BUS_SPACE_UNRESTRICTED, /* nsegments */
10429 BUS_SPACE_MAXSIZE, /* maxsegsize */
10430 0, /* flags */
10431 NULL, NULL, /* lockfunc, lockarg */
10432 &dma->parent_dtag);
10433 if (error) {
10434 device_printf(sc->sc_dev, "can't create parent DMA tag\n");
10435 return (error);
10436 }
10437
10438 /*
10439 * Create TX/RX mbuf DMA tag
10440 */
10441 error = bus_dma_tag_create(dma->parent_dtag,
10442 1,
10443 0,
10444 BUS_SPACE_MAXADDR,
10445 BUS_SPACE_MAXADDR,
10446 NULL, NULL,
10447 MCLBYTES,
10448 1,
10449 BUS_SPACE_MAXSIZE_32BIT,
10450 0,
10451 NULL, NULL,
10452 &dma->rxbuf_dtag);
10453 if (error) {
10454 device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10455 goto fail0;
10456 }
10457 error = bus_dma_tag_create(dma->parent_dtag,
10458 1,
10459 0,
10460 BUS_SPACE_MAXADDR,
10461 BUS_SPACE_MAXADDR,
10462 NULL, NULL,
10463 MCLBYTES,
10464 1,
10465 BUS_SPACE_MAXSIZE_32BIT,
10466 0,
10467 NULL, NULL,
10468 &dma->txbuf_dtag);
10469 if (error) {
10470 device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10471 goto fail1;
10472 }
10473
10474 dma->wme[WME_AC_BK] = bwn_dma_ringsetup(mac, 0, 1, dma->dmatype);
10475 if (!dma->wme[WME_AC_BK])
10476 goto fail2;
10477
10478 dma->wme[WME_AC_BE] = bwn_dma_ringsetup(mac, 1, 1, dma->dmatype);
10479 if (!dma->wme[WME_AC_BE])
10480 goto fail3;
10481
10482 dma->wme[WME_AC_VI] = bwn_dma_ringsetup(mac, 2, 1, dma->dmatype);
10483 if (!dma->wme[WME_AC_VI])
10484 goto fail4;
10485
10486 dma->wme[WME_AC_VO] = bwn_dma_ringsetup(mac, 3, 1, dma->dmatype);
10487 if (!dma->wme[WME_AC_VO])
10488 goto fail5;
10489
10490 dma->mcast = bwn_dma_ringsetup(mac, 4, 1, dma->dmatype);
10491 if (!dma->mcast)
10492 goto fail6;
10493 dma->rx = bwn_dma_ringsetup(mac, 0, 0, dma->dmatype);
10494 if (!dma->rx)
10495 goto fail7;
10496
10497 return (error);
10498
10499fail7: bwn_dma_ringfree(&dma->mcast);
10500fail6: bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
10501fail5: bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
10502fail4: bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
10503fail3: bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
10504fail2: bus_dma_tag_destroy(dma->txbuf_dtag);
10505fail1: bus_dma_tag_destroy(dma->rxbuf_dtag);
10506fail0: bus_dma_tag_destroy(dma->parent_dtag);
10507 return (error);
10508}
10509
10510static struct bwn_dma_ring *
10511bwn_dma_parse_cookie(struct bwn_mac *mac, const struct bwn_txstatus *status,
10512 uint16_t cookie, int *slot)
10513{
10514 struct bwn_dma *dma = &mac->mac_method.dma;
10515 struct bwn_dma_ring *dr;
10516 struct bwn_softc *sc = mac->mac_sc;
10517
10518 BWN_ASSERT_LOCKED(mac->mac_sc);
10519
10520 switch (cookie & 0xf000) {
10521 case 0x1000:
10522 dr = dma->wme[WME_AC_BK];
10523 break;
10524 case 0x2000:
10525 dr = dma->wme[WME_AC_BE];
10526 break;
10527 case 0x3000:
10528 dr = dma->wme[WME_AC_VI];
10529 break;
10530 case 0x4000:
10531 dr = dma->wme[WME_AC_VO];
10532 break;
10533 case 0x5000:
10534 dr = dma->mcast;
10535 break;
10536 default:
10537 dr = NULL;
10538 KASSERT(0 == 1,
10539 ("invalid cookie value %d", cookie & 0xf000));
10540 }
10541 *slot = (cookie & 0x0fff);
10542 if (*slot < 0 || *slot >= dr->dr_numslots) {
10543 /*
10544 * XXX FIXME: sometimes H/W returns TX DONE events duplicately
10545 * that it occurs events which have same H/W sequence numbers.
10546 * When it's occurred just prints a WARNING msgs and ignores.
10547 */
10548 KASSERT(status->seq == dma->lastseq,
10549 ("%s:%d: fail", __func__, __LINE__));
10550 device_printf(sc->sc_dev,
10551 "out of slot ranges (0 < %d < %d)\n", *slot,
10552 dr->dr_numslots);
10553 return (NULL);
10554 }
10555 dma->lastseq = status->seq;
10556 return (dr);
10557}
10558
10559static void
10560bwn_dma_stop(struct bwn_mac *mac)
10561{
10562 struct bwn_dma *dma;
10563
10564 if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
10565 return;
10566 dma = &mac->mac_method.dma;
10567
10568 bwn_dma_ringstop(&dma->rx);
10569 bwn_dma_ringstop(&dma->wme[WME_AC_BK]);
10570 bwn_dma_ringstop(&dma->wme[WME_AC_BE]);
10571 bwn_dma_ringstop(&dma->wme[WME_AC_VI]);
10572 bwn_dma_ringstop(&dma->wme[WME_AC_VO]);
10573 bwn_dma_ringstop(&dma->mcast);
10574}
10575
10576static void
10577bwn_dma_ringstop(struct bwn_dma_ring **dr)
10578{
10579
10580 if (dr == NULL)
10581 return;
10582
10583 bwn_dma_cleanup(*dr);
10584}
10585
10586static void
10587bwn_pio_stop(struct bwn_mac *mac)
10588{
10589 struct bwn_pio *pio;
10590
10591 if (mac->mac_flags & BWN_MAC_FLAG_DMA)
10592 return;
10593 pio = &mac->mac_method.pio;
10594
10595 bwn_destroy_queue_tx(&pio->mcast);
10596 bwn_destroy_queue_tx(&pio->wme[WME_AC_VO]);
10597 bwn_destroy_queue_tx(&pio->wme[WME_AC_VI]);
10598 bwn_destroy_queue_tx(&pio->wme[WME_AC_BE]);
10599 bwn_destroy_queue_tx(&pio->wme[WME_AC_BK]);
10600}
10601
10602static void
10603bwn_led_attach(struct bwn_mac *mac)
10604{
10605 struct bwn_softc *sc = mac->mac_sc;
10606 const uint8_t *led_act = NULL;
10607 uint16_t val[BWN_LED_MAX];
10608 int i;
10609
10610 sc->sc_led_idle = (2350 * hz) / 1000;
10611 sc->sc_led_blink = 1;
10612
10613 for (i = 0; i < N(bwn_vendor_led_act); ++i) {
10614 if (siba_get_pci_subvendor(sc->sc_dev) ==
10615 bwn_vendor_led_act[i].vid) {
10616 led_act = bwn_vendor_led_act[i].led_act;
10617 break;
10618 }
10619 }
10620 if (led_act == NULL)
10621 led_act = bwn_default_led_act;
10622
10623 val[0] = siba_sprom_get_gpio0(sc->sc_dev);
10624 val[1] = siba_sprom_get_gpio1(sc->sc_dev);
10625 val[2] = siba_sprom_get_gpio2(sc->sc_dev);
10626 val[3] = siba_sprom_get_gpio3(sc->sc_dev);
10627
10628 for (i = 0; i < BWN_LED_MAX; ++i) {
10629 struct bwn_led *led = &sc->sc_leds[i];
10630
10631 if (val[i] == 0xff) {
10632 led->led_act = led_act[i];
10633 } else {
10634 if (val[i] & BWN_LED_ACT_LOW)
10635 led->led_flags |= BWN_LED_F_ACTLOW;
10636 led->led_act = val[i] & BWN_LED_ACT_MASK;
10637 }
10638 led->led_mask = (1 << i);
10639
10640 if (led->led_act == BWN_LED_ACT_BLINK_SLOW ||
10641 led->led_act == BWN_LED_ACT_BLINK_POLL ||
10642 led->led_act == BWN_LED_ACT_BLINK) {
10643 led->led_flags |= BWN_LED_F_BLINK;
10644 if (led->led_act == BWN_LED_ACT_BLINK_POLL)
10645 led->led_flags |= BWN_LED_F_POLLABLE;
10646 else if (led->led_act == BWN_LED_ACT_BLINK_SLOW)
10647 led->led_flags |= BWN_LED_F_SLOW;
10648
10649 if (sc->sc_blink_led == NULL) {
10650 sc->sc_blink_led = led;
10651 if (led->led_flags & BWN_LED_F_SLOW)
10652 BWN_LED_SLOWDOWN(sc->sc_led_idle);
10653 }
10654 }
10655
10656 DPRINTF(sc, BWN_DEBUG_LED,
10657 "%dth led, act %d, lowact %d\n", i,
10658 led->led_act, led->led_flags & BWN_LED_F_ACTLOW);
10659 }
10660 callout_init_mtx(&sc->sc_led_blink_ch, &sc->sc_mtx, 0);
10661}
10662
10663static __inline uint16_t
10664bwn_led_onoff(const struct bwn_led *led, uint16_t val, int on)
10665{
10666
10667 if (led->led_flags & BWN_LED_F_ACTLOW)
10668 on = !on;
10669 if (on)
10670 val |= led->led_mask;
10671 else
10672 val &= ~led->led_mask;
10673 return val;
10674}
10675
10676static void
10677bwn_led_newstate(struct bwn_mac *mac, enum ieee80211_state nstate)
10678{
10679 struct bwn_softc *sc = mac->mac_sc;
10680 struct ifnet *ifp = sc->sc_ifp;
10681 struct ieee80211com *ic = ifp->if_l2com;
10682 uint16_t val;
10683 int i;
10684
10685 if (nstate == IEEE80211_S_INIT) {
10686 callout_stop(&sc->sc_led_blink_ch);
10687 sc->sc_led_blinking = 0;
10688 }
10689
10690 if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
10691 return;
10692
10693 val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10694 for (i = 0; i < BWN_LED_MAX; ++i) {
10695 struct bwn_led *led = &sc->sc_leds[i];
10696 int on;
10697
10698 if (led->led_act == BWN_LED_ACT_UNKN ||
10699 led->led_act == BWN_LED_ACT_NULL)
10700 continue;
10701
10702 if ((led->led_flags & BWN_LED_F_BLINK) &&
10703 nstate != IEEE80211_S_INIT)
10704 continue;
10705
10706 switch (led->led_act) {
10707 case BWN_LED_ACT_ON: /* Always on */
10708 on = 1;
10709 break;
10710 case BWN_LED_ACT_OFF: /* Always off */
10711 case BWN_LED_ACT_5GHZ: /* TODO: 11A */
10712 on = 0;
10713 break;
10714 default:
10715 on = 1;
10716 switch (nstate) {
10717 case IEEE80211_S_INIT:
10718 on = 0;
10719 break;
10720 case IEEE80211_S_RUN:
10721 if (led->led_act == BWN_LED_ACT_11G &&
10722 ic->ic_curmode != IEEE80211_MODE_11G)
10723 on = 0;
10724 break;
10725 default:
10726 if (led->led_act == BWN_LED_ACT_ASSOC)
10727 on = 0;
10728 break;
10729 }
10730 break;
10731 }
10732
10733 val = bwn_led_onoff(led, val, on);
10734 }
10735 BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10736}
10737
10738static void
10739bwn_led_event(struct bwn_mac *mac, int event)
10740{
10741 struct bwn_softc *sc = mac->mac_sc;
10742 struct bwn_led *led = sc->sc_blink_led;
10743 int rate;
10744
10745 if (event == BWN_LED_EVENT_POLL) {
10746 if ((led->led_flags & BWN_LED_F_POLLABLE) == 0)
10747 return;
10748 if (ticks - sc->sc_led_ticks < sc->sc_led_idle)
10749 return;
10750 }
10751
10752 sc->sc_led_ticks = ticks;
10753 if (sc->sc_led_blinking)
10754 return;
10755
10756 switch (event) {
10757 case BWN_LED_EVENT_RX:
10758 rate = sc->sc_rx_rate;
10759 break;
10760 case BWN_LED_EVENT_TX:
10761 rate = sc->sc_tx_rate;
10762 break;
10763 case BWN_LED_EVENT_POLL:
10764 rate = 0;
10765 break;
10766 default:
10767 panic("unknown LED event %d\n", event);
10768 break;
10769 }
10770 bwn_led_blink_start(mac, bwn_led_duration[rate].on_dur,
10771 bwn_led_duration[rate].off_dur);
10772}
10773
10774static void
10775bwn_led_blink_start(struct bwn_mac *mac, int on_dur, int off_dur)
10776{
10777 struct bwn_softc *sc = mac->mac_sc;
10778 struct bwn_led *led = sc->sc_blink_led;
10779 uint16_t val;
10780
10781 val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10782 val = bwn_led_onoff(led, val, 1);
10783 BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10784
10785 if (led->led_flags & BWN_LED_F_SLOW) {
10786 BWN_LED_SLOWDOWN(on_dur);
10787 BWN_LED_SLOWDOWN(off_dur);
10788 }
10789
10790 sc->sc_led_blinking = 1;
10791 sc->sc_led_blink_offdur = off_dur;
10792
10793 callout_reset(&sc->sc_led_blink_ch, on_dur, bwn_led_blink_next, mac);
10794}
10795
10796static void
10797bwn_led_blink_next(void *arg)
10798{
10799 struct bwn_mac *mac = arg;
10800 struct bwn_softc *sc = mac->mac_sc;
10801 uint16_t val;
10802
10803 val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10804 val = bwn_led_onoff(sc->sc_blink_led, val, 0);
10805 BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10806
10807 callout_reset(&sc->sc_led_blink_ch, sc->sc_led_blink_offdur,
10808 bwn_led_blink_end, mac);
10809}
10810
10811static void
10812bwn_led_blink_end(void *arg)
10813{
10814 struct bwn_mac *mac = arg;
10815 struct bwn_softc *sc = mac->mac_sc;
10816
10817 sc->sc_led_blinking = 0;
10818}
10819
10820static int
10821bwn_suspend(device_t dev)
10822{
10823 struct bwn_softc *sc = device_get_softc(dev);
10824
10825 bwn_stop(sc, 1);
10826 return (0);
10827}
10828
10829static int
10830bwn_resume(device_t dev)
10831{
10832 struct bwn_softc *sc = device_get_softc(dev);
10833 struct ifnet *ifp = sc->sc_ifp;
10834
10835 if (ifp->if_flags & IFF_UP)
10836 bwn_init(sc);
10837 return (0);
10838}
10839
10840static void
10841bwn_rfswitch(void *arg)
10842{
10843 struct bwn_softc *sc = arg;
10844 struct bwn_mac *mac = sc->sc_curmac;
10845 int cur = 0, prev = 0;
10846
10847 KASSERT(mac->mac_status >= BWN_MAC_STATUS_STARTED,
10848 ("%s: invalid MAC status %d", __func__, mac->mac_status));
10849
10850 if (mac->mac_phy.rf_rev >= 3 || mac->mac_phy.type == BWN_PHYTYPE_LP) {
10851 if (!(BWN_READ_4(mac, BWN_RF_HWENABLED_HI)
10852 & BWN_RF_HWENABLED_HI_MASK))
10853 cur = 1;
10854 } else {
10855 if (BWN_READ_2(mac, BWN_RF_HWENABLED_LO)
10856 & BWN_RF_HWENABLED_LO_MASK)
10857 cur = 1;
10858 }
10859
10860 if (mac->mac_flags & BWN_MAC_FLAG_RADIO_ON)
10861 prev = 1;
10862
10863 if (cur != prev) {
10864 if (cur)
10865 mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
10866 else
10867 mac->mac_flags &= ~BWN_MAC_FLAG_RADIO_ON;
10868
10869 device_printf(sc->sc_dev,
10870 "status of RF switch is changed to %s\n",
10871 cur ? "ON" : "OFF");
10872 if (cur != mac->mac_phy.rf_on) {
10873 if (cur)
10874 bwn_rf_turnon(mac);
10875 else
10876 bwn_rf_turnoff(mac);
10877 }
10878 }
10879
10880 callout_schedule(&sc->sc_rfswitch_ch, hz);
10881}
10882
10883static void
10884bwn_phy_lp_init_pre(struct bwn_mac *mac)
10885{
10886 struct bwn_phy *phy = &mac->mac_phy;
10887 struct bwn_phy_lp *plp = &phy->phy_lp;
10888
10889 plp->plp_antenna = BWN_ANT_DEFAULT;
10890}
10891
10892static int
10893bwn_phy_lp_init(struct bwn_mac *mac)
10894{
10895 static const struct bwn_stxtable tables[] = {
10896 { 2, 6, 0x3d, 3, 0x01 }, { 1, 12, 0x4c, 1, 0x01 },
10897 { 1, 8, 0x50, 0, 0x7f }, { 0, 8, 0x44, 0, 0xff },
10898 { 1, 0, 0x4a, 0, 0xff }, { 0, 4, 0x4d, 0, 0xff },
10899 { 1, 4, 0x4e, 0, 0xff }, { 0, 12, 0x4f, 0, 0x0f },
10900 { 1, 0, 0x4f, 4, 0x0f }, { 3, 0, 0x49, 0, 0x0f },
10901 { 4, 3, 0x46, 4, 0x07 }, { 3, 15, 0x46, 0, 0x01 },
10902 { 4, 0, 0x46, 1, 0x07 }, { 3, 8, 0x48, 4, 0x07 },
10903 { 3, 11, 0x48, 0, 0x0f }, { 3, 4, 0x49, 4, 0x0f },
10904 { 2, 15, 0x45, 0, 0x01 }, { 5, 13, 0x52, 4, 0x07 },
10905 { 6, 0, 0x52, 7, 0x01 }, { 5, 3, 0x41, 5, 0x07 },
10906 { 5, 6, 0x41, 0, 0x0f }, { 5, 10, 0x42, 5, 0x07 },
10907 { 4, 15, 0x42, 0, 0x01 }, { 5, 0, 0x42, 1, 0x07 },
10908 { 4, 11, 0x43, 4, 0x0f }, { 4, 7, 0x43, 0, 0x0f },
10909 { 4, 6, 0x45, 1, 0x01 }, { 2, 7, 0x40, 4, 0x0f },
10910 { 2, 11, 0x40, 0, 0x0f }
10911 };
10912 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
10913 struct bwn_softc *sc = mac->mac_sc;
10914 const struct bwn_stxtable *st;
10915 struct ifnet *ifp = sc->sc_ifp;
10916 struct ieee80211com *ic = ifp->if_l2com;
10917 int i, error;
10918 uint16_t tmp;
10919
10920 bwn_phy_lp_readsprom(mac); /* XXX bad place */
10921 bwn_phy_lp_bbinit(mac);
10922
10923 /* initialize RF */
10924 BWN_PHY_SET(mac, BWN_PHY_4WIRECTL, 0x2);
10925 DELAY(1);
10926 BWN_PHY_MASK(mac, BWN_PHY_4WIRECTL, 0xfffd);
10927 DELAY(1);
10928
10929 if (mac->mac_phy.rf_ver == 0x2062)
10930 bwn_phy_lp_b2062_init(mac);
10931 else {
10932 bwn_phy_lp_b2063_init(mac);
10933
10934 /* synchronize stx table. */
10935 for (i = 0; i < N(tables); i++) {
10936 st = &tables[i];
10937 tmp = BWN_RF_READ(mac, st->st_rfaddr);
10938 tmp >>= st->st_rfshift;
10939 tmp <<= st->st_physhift;
10940 BWN_PHY_SETMASK(mac,
10941 BWN_PHY_OFDM(0xf2 + st->st_phyoffset),
10942 ~(st->st_mask << st->st_physhift), tmp);
10943 }
10944
10945 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf0), 0x5f80);
10946 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf1), 0);
10947 }
10948
10949 /* calibrate RC */
10950 if (mac->mac_phy.rev >= 2)
10951 bwn_phy_lp_rxcal_r2(mac);
10952 else if (!plp->plp_rccap) {
10953 if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
10954 bwn_phy_lp_rccal_r12(mac);
10955 } else
10956 bwn_phy_lp_set_rccap(mac);
10957
10958 error = bwn_phy_lp_switch_channel(mac, 7);
10959 if (error)
10960 device_printf(sc->sc_dev,
10961 "failed to change channel 7 (%d)\n", error);
10962 bwn_phy_lp_txpctl_init(mac);
10963 bwn_phy_lp_calib(mac);
10964 return (0);
10965}
10966
10967static uint16_t
10968bwn_phy_lp_read(struct bwn_mac *mac, uint16_t reg)
10969{
10970
10971 BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10972 return (BWN_READ_2(mac, BWN_PHYDATA));
10973}
10974
10975static void
10976bwn_phy_lp_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
10977{
10978
10979 BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10980 BWN_WRITE_2(mac, BWN_PHYDATA, value);
10981}
10982
10983static void
10984bwn_phy_lp_maskset(struct bwn_mac *mac, uint16_t reg, uint16_t mask,
10985 uint16_t set)
10986{
10987
10988 BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10989 BWN_WRITE_2(mac, BWN_PHYDATA,
10990 (BWN_READ_2(mac, BWN_PHYDATA) & mask) | set);
10991}
10992
10993static uint16_t
10994bwn_phy_lp_rf_read(struct bwn_mac *mac, uint16_t reg)
10995{
10996
10997 KASSERT(reg != 1, ("unaccessible register %d", reg));
10998 if (mac->mac_phy.rev < 2 && reg != 0x4001)
10999 reg |= 0x100;
11000 if (mac->mac_phy.rev >= 2)
11001 reg |= 0x200;
11002 BWN_WRITE_2(mac, BWN_RFCTL, reg);
11003 return BWN_READ_2(mac, BWN_RFDATALO);
11004}
11005
11006static void
11007bwn_phy_lp_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
11008{
11009
11010 KASSERT(reg != 1, ("unaccessible register %d", reg));
11011 BWN_WRITE_2(mac, BWN_RFCTL, reg);
11012 BWN_WRITE_2(mac, BWN_RFDATALO, value);
11013}
11014
11015static void
11016bwn_phy_lp_rf_onoff(struct bwn_mac *mac, int on)
11017{
11018
11019 if (on) {
11020 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xe0ff);
11021 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2,
11022 (mac->mac_phy.rev >= 2) ? 0xf7f7 : 0xffe7);
11023 return;
11024 }
11025
11026 if (mac->mac_phy.rev >= 2) {
11027 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x83ff);
11028 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
11029 BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0x80ff);
11030 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xdfff);
11031 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0808);
11032 return;
11033 }
11034
11035 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xe0ff);
11036 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
11037 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfcff);
11038 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0018);
11039}
11040
11041static int
11042bwn_phy_lp_switch_channel(struct bwn_mac *mac, uint32_t chan)
11043{
11044 struct bwn_phy *phy = &mac->mac_phy;
11045 struct bwn_phy_lp *plp = &phy->phy_lp;
11046 int error;
11047
11048 if (phy->rf_ver == 0x2063) {
11049 error = bwn_phy_lp_b2063_switch_channel(mac, chan);
11050 if (error)
11051 return (error);
11052 } else {
11053 error = bwn_phy_lp_b2062_switch_channel(mac, chan);
11054 if (error)
11055 return (error);
11056 bwn_phy_lp_set_anafilter(mac, chan);
11057 bwn_phy_lp_set_gaintbl(mac, ieee80211_ieee2mhz(chan, 0));
11058 }
11059
11060 plp->plp_chan = chan;
11061 BWN_WRITE_2(mac, BWN_CHANNEL, chan);
11062 return (0);
11063}
11064
11065static uint32_t
11066bwn_phy_lp_get_default_chan(struct bwn_mac *mac)
11067{
11068 struct bwn_softc *sc = mac->mac_sc;
11069 struct ifnet *ifp = sc->sc_ifp;
11070 struct ieee80211com *ic = ifp->if_l2com;
11071
11072 return (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? 1 : 36);
11073}
11074
11075static void
11076bwn_phy_lp_set_antenna(struct bwn_mac *mac, int antenna)
11077{
11078 struct bwn_phy *phy = &mac->mac_phy;
11079 struct bwn_phy_lp *plp = &phy->phy_lp;
11080
11081 if (phy->rev >= 2 || antenna > BWN_ANTAUTO1)
11082 return;
11083
11084 bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER);
11085 BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffd, antenna & 0x2);
11086 BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffe, antenna & 0x1);
11087 bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_UCODE_ANTDIV_HELPER);
11088 plp->plp_antenna = antenna;
11089}
11090
11091static void
11092bwn_phy_lp_task_60s(struct bwn_mac *mac)
11093{
11094
11095 bwn_phy_lp_calib(mac);
11096}
11097
11098static void
11099bwn_phy_lp_readsprom(struct bwn_mac *mac)
11100{
11101 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11102 struct bwn_softc *sc = mac->mac_sc;
11103 struct ifnet *ifp = sc->sc_ifp;
11104 struct ieee80211com *ic = ifp->if_l2com;
11105
11106 if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11107 plp->plp_txisoband_m = siba_sprom_get_tri2g(sc->sc_dev);
11108 plp->plp_bxarch = siba_sprom_get_bxa2g(sc->sc_dev);
11109 plp->plp_rxpwroffset = siba_sprom_get_rxpo2g(sc->sc_dev);
11110 plp->plp_rssivf = siba_sprom_get_rssismf2g(sc->sc_dev);
11111 plp->plp_rssivc = siba_sprom_get_rssismc2g(sc->sc_dev);
11112 plp->plp_rssigs = siba_sprom_get_rssisav2g(sc->sc_dev);
11113 return;
11114 }
11115
11116 plp->plp_txisoband_l = siba_sprom_get_tri5gl(sc->sc_dev);
11117 plp->plp_txisoband_m = siba_sprom_get_tri5g(sc->sc_dev);
11118 plp->plp_txisoband_h = siba_sprom_get_tri5gh(sc->sc_dev);
11119 plp->plp_bxarch = siba_sprom_get_bxa5g(sc->sc_dev);
11120 plp->plp_rxpwroffset = siba_sprom_get_rxpo5g(sc->sc_dev);
11121 plp->plp_rssivf = siba_sprom_get_rssismf5g(sc->sc_dev);
11122 plp->plp_rssivc = siba_sprom_get_rssismc5g(sc->sc_dev);
11123 plp->plp_rssigs = siba_sprom_get_rssisav5g(sc->sc_dev);
11124}
11125
11126static void
11127bwn_phy_lp_bbinit(struct bwn_mac *mac)
11128{
11129
11130 bwn_phy_lp_tblinit(mac);
11131 if (mac->mac_phy.rev >= 2)
11132 bwn_phy_lp_bbinit_r2(mac);
11133 else
11134 bwn_phy_lp_bbinit_r01(mac);
11135}
11136
11137static void
11138bwn_phy_lp_txpctl_init(struct bwn_mac *mac)
11139{
11140 struct bwn_txgain gain_2ghz = { 4, 12, 12, 0 };
11141 struct bwn_txgain gain_5ghz = { 7, 15, 14, 0 };
11142 struct bwn_softc *sc = mac->mac_sc;
11143 struct ifnet *ifp = sc->sc_ifp;
11144 struct ieee80211com *ic = ifp->if_l2com;
11145
11146 bwn_phy_lp_set_txgain(mac,
11147 IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? &gain_2ghz : &gain_5ghz);
11148 bwn_phy_lp_set_bbmult(mac, 150);
11149}
11150
11151static void
11152bwn_phy_lp_calib(struct bwn_mac *mac)
11153{
11154 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11155 struct bwn_softc *sc = mac->mac_sc;
11156 struct ifnet *ifp = sc->sc_ifp;
11157 struct ieee80211com *ic = ifp->if_l2com;
11158 const struct bwn_rxcompco *rc = NULL;
11159 struct bwn_txgain ogain;
11160 int i, omode, oafeovr, orf, obbmult;
11161 uint8_t mode, fc = 0;
11162
11163 if (plp->plp_chanfullcal != plp->plp_chan) {
11164 plp->plp_chanfullcal = plp->plp_chan;
11165 fc = 1;
11166 }
11167
11168 bwn_mac_suspend(mac);
11169
11170 /* BlueTooth Coexistance Override */
11171 BWN_WRITE_2(mac, BWN_BTCOEX_CTL, 0x3);
11172 BWN_WRITE_2(mac, BWN_BTCOEX_TXCTL, 0xff);
11173
11174 if (mac->mac_phy.rev >= 2)
11175 bwn_phy_lp_digflt_save(mac);
11176 bwn_phy_lp_get_txpctlmode(mac);
11177 mode = plp->plp_txpctlmode;
11178 bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11179 if (mac->mac_phy.rev == 0 && mode != BWN_PHYLP_TXPCTL_OFF)
11180 bwn_phy_lp_bugfix(mac);
11181 if (mac->mac_phy.rev >= 2 && fc == 1) {
11182 bwn_phy_lp_get_txpctlmode(mac);
11183 omode = plp->plp_txpctlmode;
11184 oafeovr = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40;
11185 if (oafeovr)
11186 ogain = bwn_phy_lp_get_txgain(mac);
11187 orf = BWN_PHY_READ(mac, BWN_PHY_RF_PWR_OVERRIDE) & 0xff;
11188 obbmult = bwn_phy_lp_get_bbmult(mac);
11189 bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11190 if (oafeovr)
11191 bwn_phy_lp_set_txgain(mac, &ogain);
11192 bwn_phy_lp_set_bbmult(mac, obbmult);
11193 bwn_phy_lp_set_txpctlmode(mac, omode);
11194 BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00, orf);
11195 }
11196 bwn_phy_lp_set_txpctlmode(mac, mode);
11197 if (mac->mac_phy.rev >= 2)
11198 bwn_phy_lp_digflt_restore(mac);
11199
11200 /* do RX IQ Calculation; assumes that noise is true. */
11201 if (siba_get_chipid(sc->sc_dev) == 0x5354) {
11202 for (i = 0; i < N(bwn_rxcompco_5354); i++) {
11203 if (bwn_rxcompco_5354[i].rc_chan == plp->plp_chan)
11204 rc = &bwn_rxcompco_5354[i];
11205 }
11206 } else if (mac->mac_phy.rev >= 2)
11207 rc = &bwn_rxcompco_r2;
11208 else {
11209 for (i = 0; i < N(bwn_rxcompco_r12); i++) {
11210 if (bwn_rxcompco_r12[i].rc_chan == plp->plp_chan)
11211 rc = &bwn_rxcompco_r12[i];
11212 }
11213 }
11214 if (rc == NULL)
11215 goto fail;
11216
11217 BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, rc->rc_c1);
11218 BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, rc->rc_c0 << 8);
11219
11220 bwn_phy_lp_set_trsw_over(mac, 1 /* TX */, 0 /* RX */);
11221
11222 if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11223 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
11224 BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7, 0);
11225 } else {
11226 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
11227 BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf, 0);
11228 }
11229
11230 bwn_phy_lp_set_rxgain(mac, 0x2d5d);
11231 BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11232 BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
11233 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
11234 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
11235 bwn_phy_lp_set_deaf(mac, 0);
11236 /* XXX no checking return value? */
11237 (void)bwn_phy_lp_calc_rx_iq_comp(mac, 0xfff0);
11238 bwn_phy_lp_clear_deaf(mac, 0);
11239 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffc);
11240 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfff7);
11241 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffdf);
11242
11243 /* disable RX GAIN override. */
11244 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffe);
11245 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffef);
11246 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffbf);
11247 if (mac->mac_phy.rev >= 2) {
11248 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11249 if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11250 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfbff);
11251 BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xe5), 0xfff7);
11252 }
11253 } else {
11254 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfdff);
11255 }
11256
11257 BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11258 BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xf7ff);
11259fail:
11260 bwn_mac_enable(mac);
11261}
11262
11263static void
11264bwn_phy_lp_switch_analog(struct bwn_mac *mac, int on)
11265{
11266
11267 if (on) {
11268 BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfff8);
11269 return;
11270 }
11271
11272 BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVRVAL, 0x0007);
11273 BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x0007);
11274}
11275
11276static int
11277bwn_phy_lp_b2063_switch_channel(struct bwn_mac *mac, uint8_t chan)
11278{
11279 static const struct bwn_b206x_chan *bc = NULL;
11280 struct bwn_softc *sc = mac->mac_sc;
11281 uint32_t count, freqref, freqvco, freqxtal, val[3], timeout, timeoutref,
11282 tmp[6];
11283 uint16_t old, scale, tmp16;
11284 int i, div;
11285
11286 for (i = 0; i < N(bwn_b2063_chantable); i++) {
11287 if (bwn_b2063_chantable[i].bc_chan == chan) {
11288 bc = &bwn_b2063_chantable[i];
11289 break;
11290 }
11291 }
11292 if (bc == NULL)
11293 return (EINVAL);
11294
11295 BWN_RF_WRITE(mac, BWN_B2063_LOGEN_VCOBUF1, bc->bc_data[0]);
11296 BWN_RF_WRITE(mac, BWN_B2063_LOGEN_MIXER2, bc->bc_data[1]);
11297 BWN_RF_WRITE(mac, BWN_B2063_LOGEN_BUF2, bc->bc_data[2]);
11298 BWN_RF_WRITE(mac, BWN_B2063_LOGEN_RCCR1, bc->bc_data[3]);
11299 BWN_RF_WRITE(mac, BWN_B2063_A_RX_1ST3, bc->bc_data[4]);
11300 BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND1, bc->bc_data[5]);
11301 BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND4, bc->bc_data[6]);
11302 BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND7, bc->bc_data[7]);
11303 BWN_RF_WRITE(mac, BWN_B2063_A_RX_PS6, bc->bc_data[8]);
11304 BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL2, bc->bc_data[9]);
11305 BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL5, bc->bc_data[10]);
11306 BWN_RF_WRITE(mac, BWN_B2063_PA_CTL11, bc->bc_data[11]);
11307
11308 old = BWN_RF_READ(mac, BWN_B2063_COM15);
11309 BWN_RF_SET(mac, BWN_B2063_COM15, 0x1e);
11310
11311 freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
11312 freqvco = bc->bc_freq << ((bc->bc_freq > 4000) ? 1 : 2);
11313 freqref = freqxtal * 3;
11314 div = (freqxtal <= 26000000 ? 1 : 2);
11315 timeout = ((((8 * freqxtal) / (div * 5000000)) + 1) >> 1) - 1;
11316 timeoutref = ((((8 * freqxtal) / (div * (timeout + 1))) +
11317 999999) / 1000000) + 1;
11318
11319 BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB3, 0x2);
11320 BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB6,
11321 0xfff8, timeout >> 2);
11322 BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11323 0xff9f,timeout << 5);
11324 BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB5, timeoutref);
11325
11326 val[0] = bwn_phy_lp_roundup(freqxtal, 1000000, 16);
11327 val[1] = bwn_phy_lp_roundup(freqxtal, 1000000 * div, 16);
11328 val[2] = bwn_phy_lp_roundup(freqvco, 3, 16);
11329
11330 count = (bwn_phy_lp_roundup(val[2], val[1] + 16, 16) * (timeout + 1) *
11331 (timeoutref + 1)) - 1;
11332 BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11333 0xf0, count >> 8);
11334 BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB8, count & 0xff);
11335
11336 tmp[0] = ((val[2] * 62500) / freqref) << 4;
11337 tmp[1] = ((val[2] * 62500) % freqref) << 4;
11338 while (tmp[1] >= freqref) {
11339 tmp[0]++;
11340 tmp[1] -= freqref;
11341 }
11342 BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG1, 0xffe0, tmp[0] >> 4);
11343 BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfe0f, tmp[0] << 4);
11344 BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfff0, tmp[0] >> 16);
11345 BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG3, (tmp[1] >> 8) & 0xff);
11346 BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG4, tmp[1] & 0xff);
11347
11348 BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF1, 0xb9);
11349 BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF2, 0x88);
11350 BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF3, 0x28);
11351 BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF4, 0x63);
11352
11353 tmp[2] = ((41 * (val[2] - 3000)) /1200) + 27;
11354 tmp[3] = bwn_phy_lp_roundup(132000 * tmp[0], 8451, 16);
11355
11356 if ((tmp[3] + tmp[2] - 1) / tmp[2] > 60) {
11357 scale = 1;
11358 tmp[4] = ((tmp[3] + tmp[2]) / (tmp[2] << 1)) - 8;
11359 } else {
11360 scale = 0;
11361 tmp[4] = ((tmp[3] + (tmp[2] >> 1)) / tmp[2]) - 8;
11362 }
11363 BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffc0, tmp[4]);
11364 BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffbf, scale << 6);
11365
11366 tmp[5] = bwn_phy_lp_roundup(100 * val[0], val[2], 16) * (tmp[4] * 8) *
11367 (scale + 1);
11368 if (tmp[5] > 150)
11369 tmp[5] = 0;
11370
11371 BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffe0, tmp[5]);
11372 BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffdf, scale << 5);
11373
11374 BWN_RF_SETMASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfffb, 0x4);
11375 if (freqxtal > 26000000)
11376 BWN_RF_SET(mac, BWN_B2063_JTAG_XTAL_12, 0x2);
11377 else
11378 BWN_RF_MASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfd);
11379
11380 if (val[0] == 45)
11381 BWN_RF_SET(mac, BWN_B2063_JTAG_VCO1, 0x2);
11382 else
11383 BWN_RF_MASK(mac, BWN_B2063_JTAG_VCO1, 0xfd);
11384
11385 BWN_RF_SET(mac, BWN_B2063_PLL_SP2, 0x3);
11386 DELAY(1);
11387 BWN_RF_MASK(mac, BWN_B2063_PLL_SP2, 0xfffc);
11388
11389 /* VCO Calibration */
11390 BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, ~0x40);
11391 tmp16 = BWN_RF_READ(mac, BWN_B2063_JTAG_CALNRST) & 0xf8;
11392 BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16);
11393 DELAY(1);
11394 BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x4);
11395 DELAY(1);
11396 BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x6);
11397 DELAY(1);
11398 BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x7);
11399 DELAY(300);
11400 BWN_RF_SET(mac, BWN_B2063_PLL_SP1, 0x40);
11401
11402 BWN_RF_WRITE(mac, BWN_B2063_COM15, old);
11403 return (0);
11404}
11405
11406static int
11407bwn_phy_lp_b2062_switch_channel(struct bwn_mac *mac, uint8_t chan)
11408{
11409 struct bwn_softc *sc = mac->mac_sc;
11410 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11411 const struct bwn_b206x_chan *bc = NULL;
11412 uint32_t freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
11413 uint32_t tmp[9];
11414 int i;
11415
11416 for (i = 0; i < N(bwn_b2062_chantable); i++) {
11417 if (bwn_b2062_chantable[i].bc_chan == chan) {
11418 bc = &bwn_b2062_chantable[i];
11419 break;
11420 }
11421 }
11422
11423 if (bc == NULL)
11424 return (EINVAL);
11425
11426 BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL14, 0x04);
11427 BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE0, bc->bc_data[0]);
11428 BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE2, bc->bc_data[1]);
11429 BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE3, bc->bc_data[2]);
11430 BWN_RF_WRITE(mac, BWN_B2062_N_TX_TUNE, bc->bc_data[3]);
11431 BWN_RF_WRITE(mac, BWN_B2062_S_LGENG_CTL1, bc->bc_data[4]);
11432 BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL5, bc->bc_data[5]);
11433 BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL6, bc->bc_data[6]);
11434 BWN_RF_WRITE(mac, BWN_B2062_N_TX_PGA, bc->bc_data[7]);
11435 BWN_RF_WRITE(mac, BWN_B2062_N_TX_PAD, bc->bc_data[8]);
11436
11437 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xcc);
11438 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0x07);
11439 bwn_phy_lp_b2062_reset_pllbias(mac);
11440 tmp[0] = freqxtal / 1000;
11441 tmp[1] = plp->plp_div * 1000;
11442 tmp[2] = tmp[1] * ieee80211_ieee2mhz(chan, 0);
11443 if (ieee80211_ieee2mhz(chan, 0) < 4000)
11444 tmp[2] *= 2;
11445 tmp[3] = 48 * tmp[0];
11446 tmp[5] = tmp[2] / tmp[3];
11447 tmp[6] = tmp[2] % tmp[3];
11448 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL26, tmp[5]);
11449 tmp[4] = tmp[6] * 0x100;
11450 tmp[5] = tmp[4] / tmp[3];
11451 tmp[6] = tmp[4] % tmp[3];
11452 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL27, tmp[5]);
11453 tmp[4] = tmp[6] * 0x100;
11454 tmp[5] = tmp[4] / tmp[3];
11455 tmp[6] = tmp[4] % tmp[3];
11456 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL28, tmp[5]);
11457 tmp[4] = tmp[6] * 0x100;
11458 tmp[5] = tmp[4] / tmp[3];
11459 tmp[6] = tmp[4] % tmp[3];
11460 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL29,
11461 tmp[5] + ((2 * tmp[6]) / tmp[3]));
11462 tmp[7] = BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL19);
11463 tmp[8] = ((2 * tmp[2] * (tmp[7] + 1)) + (3 * tmp[0])) / (6 * tmp[0]);
11464 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL23, (tmp[8] >> 8) + 16);
11465 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL24, tmp[8] & 0xff);
11466
11467 bwn_phy_lp_b2062_vco_calib(mac);
11468 if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11469 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xfc);
11470 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0);
11471 bwn_phy_lp_b2062_reset_pllbias(mac);
11472 bwn_phy_lp_b2062_vco_calib(mac);
11473 if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11474 BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11475 return (EIO);
11476 }
11477 }
11478 BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11479 return (0);
11480}
11481
11482static void
11483bwn_phy_lp_set_anafilter(struct bwn_mac *mac, uint8_t channel)
11484{
11485 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11486 uint16_t tmp = (channel == 14);
11487
11488 if (mac->mac_phy.rev < 2) {
11489 BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xfcff, tmp << 9);
11490 if ((mac->mac_phy.rev == 1) && (plp->plp_rccap))
11491 bwn_phy_lp_set_rccap(mac);
11492 return;
11493 }
11494
11495 BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, 0x3f);
11496}
11497
11498static void
11499bwn_phy_lp_set_gaintbl(struct bwn_mac *mac, uint32_t freq)
11500{
11501 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11502 struct bwn_softc *sc = mac->mac_sc;
11503 struct ifnet *ifp = sc->sc_ifp;
11504 struct ieee80211com *ic = ifp->if_l2com;
11505 uint16_t iso, tmp[3];
11506
11507 KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
11508
11509 if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
11510 iso = plp->plp_txisoband_m;
11511 else if (freq <= 5320)
11512 iso = plp->plp_txisoband_l;
11513 else if (freq <= 5700)
11514 iso = plp->plp_txisoband_m;
11515 else
11516 iso = plp->plp_txisoband_h;
11517
11518 tmp[0] = ((iso - 26) / 12) << 12;
11519 tmp[1] = tmp[0] + 0x1000;
11520 tmp[2] = tmp[0] + 0x2000;
11521
11522 bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), 3, tmp);
11523 bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), 3, tmp);
11524}
11525
11526static void
11527bwn_phy_lp_digflt_save(struct bwn_mac *mac)
11528{
11529 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11530 int i;
11531 static const uint16_t addr[] = {
11532 BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11533 BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11534 BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11535 BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11536 BWN_PHY_OFDM(0xcf),
11537 };
11538 static const uint16_t val[] = {
11539 0xde5e, 0xe832, 0xe331, 0x4d26,
11540 0x0026, 0x1420, 0x0020, 0xfe08,
11541 0x0008,
11542 };
11543
11544 for (i = 0; i < N(addr); i++) {
11545 plp->plp_digfilt[i] = BWN_PHY_READ(mac, addr[i]);
11546 BWN_PHY_WRITE(mac, addr[i], val[i]);
11547 }
11548}
11549
11550static void
11551bwn_phy_lp_get_txpctlmode(struct bwn_mac *mac)
11552{
11553 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11554 struct bwn_softc *sc = mac->mac_sc;
11555 uint16_t ctl;
11556
11557 ctl = BWN_PHY_READ(mac, BWN_PHY_TX_PWR_CTL_CMD);
11558 switch (ctl & BWN_PHY_TX_PWR_CTL_CMD_MODE) {
11559 case BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF:
11560 plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_OFF;
11561 break;
11562 case BWN_PHY_TX_PWR_CTL_CMD_MODE_SW:
11563 plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_SW;
11564 break;
11565 case BWN_PHY_TX_PWR_CTL_CMD_MODE_HW:
11566 plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_HW;
11567 break;
11568 default:
11569 plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_UNKNOWN;
11570 device_printf(sc->sc_dev, "unknown command mode\n");
11571 break;
11572 }
11573}
11574
11575static void
11576bwn_phy_lp_set_txpctlmode(struct bwn_mac *mac, uint8_t mode)
11577{
11578 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11579 uint16_t ctl;
11580 uint8_t old;
11581
11582 bwn_phy_lp_get_txpctlmode(mac);
11583 old = plp->plp_txpctlmode;
11584 if (old == mode)
11585 return;
11586 plp->plp_txpctlmode = mode;
11587
11588 if (old != BWN_PHYLP_TXPCTL_ON_HW && mode == BWN_PHYLP_TXPCTL_ON_HW) {
11589 BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD, 0xff80,
11590 plp->plp_tssiidx);
11591 BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_NNUM,
11592 0x8fff, ((uint16_t)plp->plp_tssinpt << 16));
11593
11594 /* disable TX GAIN override */
11595 if (mac->mac_phy.rev < 2)
11596 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11597 else {
11598 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xff7f);
11599 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xbfff);
11600 }
11601 BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xffbf);
11602
11603 plp->plp_txpwridx = -1;
11604 }
11605 if (mac->mac_phy.rev >= 2) {
11606 if (mode == BWN_PHYLP_TXPCTL_ON_HW)
11607 BWN_PHY_SET(mac, BWN_PHY_OFDM(0xd0), 0x2);
11608 else
11609 BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xd0), 0xfffd);
11610 }
11611
11612 /* writes TX Power Control mode */
11613 switch (plp->plp_txpctlmode) {
11614 case BWN_PHYLP_TXPCTL_OFF:
11615 ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF;
11616 break;
11617 case BWN_PHYLP_TXPCTL_ON_HW:
11618 ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_HW;
11619 break;
11620 case BWN_PHYLP_TXPCTL_ON_SW:
11621 ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_SW;
11622 break;
11623 default:
11624 ctl = 0;
11625 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
11626 }
11627 BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD,
11628 (uint16_t)~BWN_PHY_TX_PWR_CTL_CMD_MODE, ctl);
11629}
11630
11631static void
11632bwn_phy_lp_bugfix(struct bwn_mac *mac)
11633{
11634 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11635 struct bwn_softc *sc = mac->mac_sc;
11636 const unsigned int size = 256;
11637 struct bwn_txgain tg;
11638 uint32_t rxcomp, txgain, coeff, rfpwr, *tabs;
11639 uint16_t tssinpt, tssiidx, value[2];
11640 uint8_t mode;
11641 int8_t txpwridx;
11642
11643 tabs = (uint32_t *)malloc(sizeof(uint32_t) * size, M_DEVBUF,
11644 M_NOWAIT | M_ZERO);
11645 if (tabs == NULL) {
11646 device_printf(sc->sc_dev, "failed to allocate buffer.\n");
11647 return;
11648 }
11649
11650 bwn_phy_lp_get_txpctlmode(mac);
11651 mode = plp->plp_txpctlmode;
11652 txpwridx = plp->plp_txpwridx;
11653 tssinpt = plp->plp_tssinpt;
11654 tssiidx = plp->plp_tssiidx;
11655
11656 bwn_tab_read_multi(mac,
11657 (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11658 BWN_TAB_4(7, 0x140), size, tabs);
11659
11660 bwn_phy_lp_tblinit(mac);
11661 bwn_phy_lp_bbinit(mac);
11662 bwn_phy_lp_txpctl_init(mac);
11663 bwn_phy_lp_rf_onoff(mac, 1);
11664 bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11665
11666 bwn_tab_write_multi(mac,
11667 (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11668 BWN_TAB_4(7, 0x140), size, tabs);
11669
11670 BWN_WRITE_2(mac, BWN_CHANNEL, plp->plp_chan);
11671 plp->plp_tssinpt = tssinpt;
11672 plp->plp_tssiidx = tssiidx;
11673 bwn_phy_lp_set_anafilter(mac, plp->plp_chan);
11674 if (txpwridx != -1) {
11675 /* set TX power by index */
11676 plp->plp_txpwridx = txpwridx;
11677 bwn_phy_lp_get_txpctlmode(mac);
11678 if (plp->plp_txpctlmode != BWN_PHYLP_TXPCTL_OFF)
11679 bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_ON_SW);
11680 if (mac->mac_phy.rev >= 2) {
11681 rxcomp = bwn_tab_read(mac,
11682 BWN_TAB_4(7, txpwridx + 320));
11683 txgain = bwn_tab_read(mac,
11684 BWN_TAB_4(7, txpwridx + 192));
11685 tg.tg_pad = (txgain >> 16) & 0xff;
11686 tg.tg_gm = txgain & 0xff;
11687 tg.tg_pga = (txgain >> 8) & 0xff;
11688 tg.tg_dac = (rxcomp >> 28) & 0xff;
11689 bwn_phy_lp_set_txgain(mac, &tg);
11690 } else {
11691 rxcomp = bwn_tab_read(mac,
11692 BWN_TAB_4(10, txpwridx + 320));
11693 txgain = bwn_tab_read(mac,
11694 BWN_TAB_4(10, txpwridx + 192));
11695 BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
11696 0xf800, (txgain >> 4) & 0x7fff);
11697 bwn_phy_lp_set_txgain_dac(mac, txgain & 0x7);
11698 bwn_phy_lp_set_txgain_pa(mac, (txgain >> 24) & 0x7f);
11699 }
11700 bwn_phy_lp_set_bbmult(mac, (rxcomp >> 20) & 0xff);
11701
11702 /* set TX IQCC */
11703 value[0] = (rxcomp >> 10) & 0x3ff;
11704 value[1] = rxcomp & 0x3ff;
11705 bwn_tab_write_multi(mac, BWN_TAB_2(0, 80), 2, value);
11706
11707 coeff = bwn_tab_read(mac,
11708 (mac->mac_phy.rev >= 2) ? BWN_TAB_4(7, txpwridx + 448) :
11709 BWN_TAB_4(10, txpwridx + 448));
11710 bwn_tab_write(mac, BWN_TAB_2(0, 85), coeff & 0xffff);
11711 if (mac->mac_phy.rev >= 2) {
11712 rfpwr = bwn_tab_read(mac,
11713 BWN_TAB_4(7, txpwridx + 576));
11714 BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00,
11715 rfpwr & 0xffff);
11716 }
11717 bwn_phy_lp_set_txgain_override(mac);
11718 }
11719 if (plp->plp_rccap)
11720 bwn_phy_lp_set_rccap(mac);
11721 bwn_phy_lp_set_antenna(mac, plp->plp_antenna);
11722 bwn_phy_lp_set_txpctlmode(mac, mode);
11723 free(tabs, M_DEVBUF);
11724}
11725
11726static void
11727bwn_phy_lp_digflt_restore(struct bwn_mac *mac)
11728{
11729 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11730 int i;
11731 static const uint16_t addr[] = {
11732 BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11733 BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11734 BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11735 BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11736 BWN_PHY_OFDM(0xcf),
11737 };
11738
11739 for (i = 0; i < N(addr); i++)
11740 BWN_PHY_WRITE(mac, addr[i], plp->plp_digfilt[i]);
11741}
11742
11743static void
11744bwn_phy_lp_tblinit(struct bwn_mac *mac)
11745{
11746 uint32_t freq = ieee80211_ieee2mhz(bwn_phy_lp_get_default_chan(mac), 0);
11747
11748 if (mac->mac_phy.rev < 2) {
11749 bwn_phy_lp_tblinit_r01(mac);
11750 bwn_phy_lp_tblinit_txgain(mac);
11751 bwn_phy_lp_set_gaintbl(mac, freq);
11752 return;
11753 }
11754
11755 bwn_phy_lp_tblinit_r2(mac);
11756 bwn_phy_lp_tblinit_txgain(mac);
11757}
11758
11759struct bwn_wpair {
11760 uint16_t reg;
11761 uint16_t value;
11762};
11763
11764struct bwn_smpair {
11765 uint16_t offset;
11766 uint16_t mask;
11767 uint16_t set;
11768};
11769
11770static void
11771bwn_phy_lp_bbinit_r2(struct bwn_mac *mac)
11772{
11773 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11774 struct bwn_softc *sc = mac->mac_sc;
11775 struct ifnet *ifp = sc->sc_ifp;
11776 struct ieee80211com *ic = ifp->if_l2com;
11777 static const struct bwn_wpair v1[] = {
11778 { BWN_PHY_AFE_DAC_CTL, 0x50 },
11779 { BWN_PHY_AFE_CTL, 0x8800 },
11780 { BWN_PHY_AFE_CTL_OVR, 0 },
11781 { BWN_PHY_AFE_CTL_OVRVAL, 0 },
11782 { BWN_PHY_RF_OVERRIDE_0, 0 },
11783 { BWN_PHY_RF_OVERRIDE_2, 0 },
11784 { BWN_PHY_OFDM(0xf9), 0 },
11785 { BWN_PHY_TR_LOOKUP_1, 0 }
11786 };
11787 static const struct bwn_smpair v2[] = {
11788 { BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0xb4 },
11789 { BWN_PHY_DCOFFSETTRANSIENT, 0xf8ff, 0x200 },
11790 { BWN_PHY_DCOFFSETTRANSIENT, 0xff00, 0x7f },
11791 { BWN_PHY_GAINDIRECTMISMATCH, 0xff0f, 0x40 },
11792 { BWN_PHY_PREAMBLECONFIRMTO, 0xff00, 0x2 }
11793 };
11794 static const struct bwn_smpair v3[] = {
11795 { BWN_PHY_OFDM(0xfe), 0xffe0, 0x1f },
11796 { BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11797 { BWN_PHY_OFDM(0x100), 0xff00, 0x19 },
11798 { BWN_PHY_OFDM(0xff), 0x03ff, 0x3c00 },
11799 { BWN_PHY_OFDM(0xfe), 0xfc1f, 0x3e0 },
11800 { BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11801 { BWN_PHY_OFDM(0x100), 0x00ff, 0x1900 },
11802 { BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800 },
11803 { BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x12 },
11804 { BWN_PHY_GAINMISMATCH, 0x0fff, 0x9000 },
11805
11806 };
11807 int i;
11808
11809 for (i = 0; i < N(v1); i++)
11810 BWN_PHY_WRITE(mac, v1[i].reg, v1[i].value);
11811 BWN_PHY_SET(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x10);
11812 for (i = 0; i < N(v2); i++)
11813 BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask, v2[i].set);
11814
11815 BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x4000);
11816 BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x2000);
11817 BWN_PHY_SET(mac, BWN_PHY_OFDM(0x10a), 0x1);
11818 if (siba_get_pci_revid(sc->sc_dev) >= 0x18) {
11819 bwn_tab_write(mac, BWN_TAB_4(17, 65), 0xec);
11820 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x14);
11821 } else {
11822 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x10);
11823 }
11824 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0xff00, 0xf4);
11825 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0x00ff, 0xf100);
11826 BWN_PHY_WRITE(mac, BWN_PHY_CLIPTHRESH, 0x48);
11827 BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0xff00, 0x46);
11828 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe4), 0xff00, 0x10);
11829 BWN_PHY_SETMASK(mac, BWN_PHY_PWR_THRESH1, 0xfff0, 0x9);
11830 BWN_PHY_MASK(mac, BWN_PHY_GAINDIRECTMISMATCH, ~0xf);
11831 BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5500);
11832 BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0xa0);
11833 BWN_PHY_SETMASK(mac, BWN_PHY_GAINDIRECTMISMATCH, 0xe0ff, 0x300);
11834 BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2a00);
11835 if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11836 (siba_get_chiprev(sc->sc_dev) == 0)) {
11837 BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11838 BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xa);
11839 } else {
11840 BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x1e00);
11841 BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xd);
11842 }
11843 for (i = 0; i < N(v3); i++)
11844 BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask, v3[i].set);
11845 if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11846 (siba_get_chiprev(sc->sc_dev) == 0)) {
11847 bwn_tab_write(mac, BWN_TAB_2(0x08, 0x14), 0);
11848 bwn_tab_write(mac, BWN_TAB_2(0x08, 0x12), 0x40);
11849 }
11850
11851 if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11852 BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x40);
11853 BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0xb00);
11854 BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x6);
11855 BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0x9d00);
11856 BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0xff00, 0xa1);
11857 BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
11858 } else
11859 BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x40);
11860
11861 BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0xff00, 0xb3);
11862 BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00);
11863 BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB, 0xff00, plp->plp_rxpwroffset);
11864 BWN_PHY_SET(mac, BWN_PHY_RESET_CTL, 0x44);
11865 BWN_PHY_WRITE(mac, BWN_PHY_RESET_CTL, 0x80);
11866 BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, 0xa954);
11867 BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_1,
11868 0x2000 | ((uint16_t)plp->plp_rssigs << 10) |
11869 ((uint16_t)plp->plp_rssivc << 4) | plp->plp_rssivf);
11870
11871 if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11872 (siba_get_chiprev(sc->sc_dev) == 0)) {
11873 BWN_PHY_SET(mac, BWN_PHY_AFE_ADC_CTL_0, 0x1c);
11874 BWN_PHY_SETMASK(mac, BWN_PHY_AFE_CTL, 0x00ff, 0x8800);
11875 BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_1, 0xfc3c, 0x0400);
11876 }
11877
11878 bwn_phy_lp_digflt_save(mac);
11879}
11880
11881static void
11882bwn_phy_lp_bbinit_r01(struct bwn_mac *mac)
11883{
11884 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11885 struct bwn_softc *sc = mac->mac_sc;
11886 struct ifnet *ifp = sc->sc_ifp;
11887 struct ieee80211com *ic = ifp->if_l2com;
11888 static const struct bwn_smpair v1[] = {
11889 { BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x0005 },
11890 { BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0x0180 },
11891 { BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x3c00 },
11892 { BWN_PHY_GAINDIRECTMISMATCH, 0xfff0, 0x0005 },
11893 { BWN_PHY_GAIN_MISMATCH_LIMIT, 0xffc0, 0x001a },
11894 { BWN_PHY_CRS_ED_THRESH, 0xff00, 0x00b3 },
11895 { BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00 }
11896 };
11897 static const struct bwn_smpair v2[] = {
11898 { BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11899 { BWN_PHY_TR_LOOKUP_1, 0x3f00, 0x0900 },
11900 { BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11901 { BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11902 { BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x000a },
11903 { BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0400 },
11904 { BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x000a },
11905 { BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0b00 },
11906 { BWN_PHY_TR_LOOKUP_5, 0xffc0, 0x000a },
11907 { BWN_PHY_TR_LOOKUP_5, 0xc0ff, 0x0900 },
11908 { BWN_PHY_TR_LOOKUP_6, 0xffc0, 0x000a },
11909 { BWN_PHY_TR_LOOKUP_6, 0xc0ff, 0x0b00 },
11910 { BWN_PHY_TR_LOOKUP_7, 0xffc0, 0x000a },
11911 { BWN_PHY_TR_LOOKUP_7, 0xc0ff, 0x0900 },
11912 { BWN_PHY_TR_LOOKUP_8, 0xffc0, 0x000a },
11913 { BWN_PHY_TR_LOOKUP_8, 0xc0ff, 0x0b00 }
11914 };
11915 static const struct bwn_smpair v3[] = {
11916 { BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0001 },
11917 { BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0400 },
11918 { BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0001 },
11919 { BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0500 },
11920 { BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11921 { BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0800 },
11922 { BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11923 { BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0a00 }
11924 };
11925 static const struct bwn_smpair v4[] = {
11926 { BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0004 },
11927 { BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0800 },
11928 { BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0004 },
11929 { BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0c00 },
11930 { BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11931 { BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0100 },
11932 { BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11933 { BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0300 }
11934 };
11935 static const struct bwn_smpair v5[] = {
11936 { BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11937 { BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0900 },
11938 { BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11939 { BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11940 { BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0006 },
11941 { BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0500 },
11942 { BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0006 },
11943 { BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0700 }
11944 };
11945 int i;
11946 uint16_t tmp, tmp2;
11947
11948 BWN_PHY_MASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf7ff);
11949 BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL, 0);
11950 BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, 0);
11951 BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, 0);
11952 BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0);
11953 BWN_PHY_SET(mac, BWN_PHY_AFE_DAC_CTL, 0x0004);
11954 BWN_PHY_SETMASK(mac, BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0x0078);
11955 BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800);
11956 BWN_PHY_WRITE(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x0016);
11957 BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_0, 0xfff8, 0x0004);
11958 BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5400);
11959 BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2400);
11960 BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11961 BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0x0006);
11962 BWN_PHY_MASK(mac, BWN_PHY_RX_RADIO_CTL, 0xfffe);
11963 for (i = 0; i < N(v1); i++)
11964 BWN_PHY_SETMASK(mac, v1[i].offset, v1[i].mask, v1[i].set);
11965 BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB,
11966 0xff00, plp->plp_rxpwroffset);
11967 if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM) &&
11968 ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ||
11969 (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_LDO_PAREF))) {
11970 siba_cc_pmu_set_ldovolt(sc->sc_dev, SIBA_LDO_PAREF, 0x28);
11971 siba_cc_pmu_set_ldoparef(sc->sc_dev, 1);
11972 if (mac->mac_phy.rev == 0)
11973 BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT,
11974 0xffcf, 0x0010);
11975 bwn_tab_write(mac, BWN_TAB_2(11, 7), 60);
11976 } else {
11977 siba_cc_pmu_set_ldoparef(sc->sc_dev, 0);
11978 BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT, 0xffcf, 0x0020);
11979 bwn_tab_write(mac, BWN_TAB_2(11, 7), 100);
11980 }
11981 tmp = plp->plp_rssivf | plp->plp_rssivc << 4 | 0xa000;
11982 BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, tmp);
11983 if (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_RSSIINV)
11984 BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x0aaa);
11985 else
11986 BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x02aa);
11987 bwn_tab_write(mac, BWN_TAB_2(11, 1), 24);
11988 BWN_PHY_SETMASK(mac, BWN_PHY_RX_RADIO_CTL,
11989 0xfff9, (plp->plp_bxarch << 1));
11990 if (mac->mac_phy.rev == 1 &&
11991 (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_FEM_BT)) {
11992 for (i = 0; i < N(v2); i++)
11993 BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask,
11994 v2[i].set);
11995 } else if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ||
11996 (siba_get_pci_subdevice(sc->sc_dev) == 0x048a) ||
11997 ((mac->mac_phy.rev == 0) &&
11998 (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM))) {
11999 for (i = 0; i < N(v3); i++)
12000 BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask,
12001 v3[i].set);
12002 } else if (mac->mac_phy.rev == 1 ||
12003 (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM)) {
12004 for (i = 0; i < N(v4); i++)
12005 BWN_PHY_SETMASK(mac, v4[i].offset, v4[i].mask,
12006 v4[i].set);
12007 } else {
12008 for (i = 0; i < N(v5); i++)
12009 BWN_PHY_SETMASK(mac, v5[i].offset, v5[i].mask,
12010 v5[i].set);
12011 }
12012 if (mac->mac_phy.rev == 1 &&
12013 (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_LDO_PAREF)) {
12014 BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_5, BWN_PHY_TR_LOOKUP_1);
12015 BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_6, BWN_PHY_TR_LOOKUP_2);
12016 BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_7, BWN_PHY_TR_LOOKUP_3);
12017 BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_8, BWN_PHY_TR_LOOKUP_4);
12018 }
12019 if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_FEM_BT) &&
12020 (siba_get_chipid(sc->sc_dev) == 0x5354) &&
12021 (siba_get_chippkg(sc->sc_dev) == SIBA_CHIPPACK_BCM4712S)) {
12022 BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0006);
12023 BWN_PHY_WRITE(mac, BWN_PHY_GPIO_SELECT, 0x0005);
12024 BWN_PHY_WRITE(mac, BWN_PHY_GPIO_OUTEN, 0xffff);
12025 bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_PR45960W);
12026 }
12027 if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12028 BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x8000);
12029 BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0040);
12030 BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0xa400);
12031 BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0x0b00);
12032 BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x0007);
12033 BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xfff8, 0x0003);
12034 BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xffc7, 0x0020);
12035 BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
12036 } else {
12037 BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0x7fff);
12038 BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xffbf);
12039 }
12040 if (mac->mac_phy.rev == 1) {
12041 tmp = BWN_PHY_READ(mac, BWN_PHY_CLIPCTRTHRESH);
12042 tmp2 = (tmp & 0x03e0) >> 5;
12043 tmp2 |= tmp2 << 5;
12044 BWN_PHY_WRITE(mac, BWN_PHY_4C3, tmp2);
12045 tmp = BWN_PHY_READ(mac, BWN_PHY_GAINDIRECTMISMATCH);
12046 tmp2 = (tmp & 0x1f00) >> 8;
12047 tmp2 |= tmp2 << 5;
12048 BWN_PHY_WRITE(mac, BWN_PHY_4C4, tmp2);
12049 tmp = BWN_PHY_READ(mac, BWN_PHY_VERYLOWGAINDB);
12050 tmp2 = tmp & 0x00ff;
12051 tmp2 |= tmp << 8;
12052 BWN_PHY_WRITE(mac, BWN_PHY_4C5, tmp2);
12053 }
12054}
12055
12056struct bwn_b2062_freq {
12057 uint16_t freq;
12058 uint8_t value[6];
12059};
12060
12061static void
12062bwn_phy_lp_b2062_init(struct bwn_mac *mac)
12063{
12064#define CALC_CTL7(freq, div) \
12065 (((800000000 * (div) + (freq)) / (2 * (freq)) - 8) & 0xff)
12066#define CALC_CTL18(freq, div) \
12067 ((((100 * (freq) + 16000000 * (div)) / (32000000 * (div))) - 1) & 0xff)
12068#define CALC_CTL19(freq, div) \
12069 ((((2 * (freq) + 1000000 * (div)) / (2000000 * (div))) - 1) & 0xff)
12070 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12071 struct bwn_softc *sc = mac->mac_sc;
12072 struct ifnet *ifp = sc->sc_ifp;
12073 struct ieee80211com *ic = ifp->if_l2com;
12074 static const struct bwn_b2062_freq freqdata_tab[] = {
12075 { 12000, { 6, 6, 6, 6, 10, 6 } },
12076 { 13000, { 4, 4, 4, 4, 11, 7 } },
12077 { 14400, { 3, 3, 3, 3, 12, 7 } },
12078 { 16200, { 3, 3, 3, 3, 13, 8 } },
12079 { 18000, { 2, 2, 2, 2, 14, 8 } },
12080 { 19200, { 1, 1, 1, 1, 14, 9 } }
12081 };
12082 static const struct bwn_wpair v1[] = {
12083 { BWN_B2062_N_TXCTL3, 0 },
12084 { BWN_B2062_N_TXCTL4, 0 },
12085 { BWN_B2062_N_TXCTL5, 0 },
12086 { BWN_B2062_N_TXCTL6, 0 },
12087 { BWN_B2062_N_PDNCTL0, 0x40 },
12088 { BWN_B2062_N_PDNCTL0, 0 },
12089 { BWN_B2062_N_CALIB_TS, 0x10 },
12090 { BWN_B2062_N_CALIB_TS, 0 }
12091 };
12092 const struct bwn_b2062_freq *f = NULL;
12093 uint32_t xtalfreq, ref;
12094 unsigned int i;
12095
12096 bwn_phy_lp_b2062_tblinit(mac);
12097
12098 for (i = 0; i < N(v1); i++)
12099 BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12100 if (mac->mac_phy.rev > 0)
12101 BWN_RF_WRITE(mac, BWN_B2062_S_BG_CTL1,
12102 (BWN_RF_READ(mac, BWN_B2062_N_COM2) >> 1) | 0x80);
12103 if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12104 BWN_RF_SET(mac, BWN_B2062_N_TSSI_CTL0, 0x1);
12105 else
12106 BWN_RF_MASK(mac, BWN_B2062_N_TSSI_CTL0, ~0x1);
12107
12108 KASSERT(siba_get_cc_caps(sc->sc_dev) & SIBA_CC_CAPS_PMU,
12109 ("%s:%d: fail", __func__, __LINE__));
12110 xtalfreq = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
12111 KASSERT(xtalfreq != 0, ("%s:%d: fail", __func__, __LINE__));
12112
12113 if (xtalfreq <= 30000000) {
12114 plp->plp_div = 1;
12115 BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL1, 0xfffb);
12116 } else {
12117 plp->plp_div = 2;
12118 BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL1, 0x4);
12119 }
12120
12121 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL7,
12122 CALC_CTL7(xtalfreq, plp->plp_div));
12123 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL18,
12124 CALC_CTL18(xtalfreq, plp->plp_div));
12125 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL19,
12126 CALC_CTL19(xtalfreq, plp->plp_div));
12127
12128 ref = (1000 * plp->plp_div + 2 * xtalfreq) / (2000 * plp->plp_div);
12129 ref &= 0xffff;
12130 for (i = 0; i < N(freqdata_tab); i++) {
12131 if (ref < freqdata_tab[i].freq) {
12132 f = &freqdata_tab[i];
12133 break;
12134 }
12135 }
12136 if (f == NULL)
12137 f = &freqdata_tab[N(freqdata_tab) - 1];
12138 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL8,
12139 ((uint16_t)(f->value[1]) << 4) | f->value[0]);
12140 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL9,
12141 ((uint16_t)(f->value[3]) << 4) | f->value[2]);
12142 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL10, f->value[4]);
12143 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL11, f->value[5]);
12144#undef CALC_CTL7
12145#undef CALC_CTL18
12146#undef CALC_CTL19
12147}
12148
12149static void
12150bwn_phy_lp_b2063_init(struct bwn_mac *mac)
12151{
12152
12153 bwn_phy_lp_b2063_tblinit(mac);
12154 BWN_RF_WRITE(mac, BWN_B2063_LOGEN_SP5, 0);
12155 BWN_RF_SET(mac, BWN_B2063_COM8, 0x38);
12156 BWN_RF_WRITE(mac, BWN_B2063_REG_SP1, 0x56);
12157 BWN_RF_MASK(mac, BWN_B2063_RX_BB_CTL2, ~0x2);
12158 BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0);
12159 BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP6, 0x20);
12160 BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP9, 0x40);
12161 if (mac->mac_phy.rev == 2) {
12162 BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0xa0);
12163 BWN_RF_WRITE(mac, BWN_B2063_PA_SP4, 0xa0);
12164 BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x18);
12165 } else {
12166 BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0x20);
12167 BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x20);
12168 }
12169}
12170
12171static void
12172bwn_phy_lp_rxcal_r2(struct bwn_mac *mac)
12173{
12174 struct bwn_softc *sc = mac->mac_sc;
12175 static const struct bwn_wpair v1[] = {
12176 { BWN_B2063_RX_BB_SP8, 0x0 },
12177 { BWN_B2063_RC_CALIB_CTL1, 0x7e },
12178 { BWN_B2063_RC_CALIB_CTL1, 0x7c },
12179 { BWN_B2063_RC_CALIB_CTL2, 0x15 },
12180 { BWN_B2063_RC_CALIB_CTL3, 0x70 },
12181 { BWN_B2063_RC_CALIB_CTL4, 0x52 },
12182 { BWN_B2063_RC_CALIB_CTL5, 0x1 },
12183 { BWN_B2063_RC_CALIB_CTL1, 0x7d }
12184 };
12185 static const struct bwn_wpair v2[] = {
12186 { BWN_B2063_TX_BB_SP3, 0x0 },
12187 { BWN_B2063_RC_CALIB_CTL1, 0x7e },
12188 { BWN_B2063_RC_CALIB_CTL1, 0x7c },
12189 { BWN_B2063_RC_CALIB_CTL2, 0x55 },
12190 { BWN_B2063_RC_CALIB_CTL3, 0x76 }
12191 };
12192 uint32_t freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
12193 int i;
12194 uint8_t tmp;
12195
12196 tmp = BWN_RF_READ(mac, BWN_B2063_RX_BB_SP8) & 0xff;
12197
12198 for (i = 0; i < 2; i++)
12199 BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12200 BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, 0xf7);
12201 for (i = 2; i < N(v1); i++)
12202 BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12203 for (i = 0; i < 10000; i++) {
12204 if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12205 break;
12206 DELAY(1000);
12207 }
12208
12209 if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12210 BWN_RF_WRITE(mac, BWN_B2063_RX_BB_SP8, tmp);
12211
12212 tmp = BWN_RF_READ(mac, BWN_B2063_TX_BB_SP3) & 0xff;
12213
12214 for (i = 0; i < N(v2); i++)
12215 BWN_RF_WRITE(mac, v2[i].reg, v2[i].value);
12216 if (freqxtal == 24000000) {
12217 BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0xfc);
12218 BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x0);
12219 } else {
12220 BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0x13);
12221 BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x1);
12222 }
12223 BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0x7d);
12224 for (i = 0; i < 10000; i++) {
12225 if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12226 break;
12227 DELAY(1000);
12228 }
12229 if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12230 BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, tmp);
12231 BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL1, 0x7e);
12232}
12233
12234static void
12235bwn_phy_lp_rccal_r12(struct bwn_mac *mac)
12236{
12237 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12238 struct bwn_softc *sc = mac->mac_sc;
12239 struct bwn_phy_lp_iq_est ie;
12240 struct bwn_txgain tx_gains;
12241 static const uint32_t pwrtbl[21] = {
12242 0x10000, 0x10557, 0x10e2d, 0x113e0, 0x10f22, 0x0ff64,
12243 0x0eda2, 0x0e5d4, 0x0efd1, 0x0fbe8, 0x0b7b8, 0x04b35,
12244 0x01a5e, 0x00a0b, 0x00444, 0x001fd, 0x000ff, 0x00088,
12245 0x0004c, 0x0002c, 0x0001a,
12246 };
12247 uint32_t npwr, ipwr, sqpwr, tmp;
12248 int loopback, i, j, sum, error;
12249 uint16_t save[7];
12250 uint8_t txo, bbmult, txpctlmode;
12251
12252 error = bwn_phy_lp_switch_channel(mac, 7);
12253 if (error)
12254 device_printf(sc->sc_dev,
12255 "failed to change channel to 7 (%d)\n", error);
12256 txo = (BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40) ? 1 : 0;
12257 bbmult = bwn_phy_lp_get_bbmult(mac);
12258 if (txo)
12259 tx_gains = bwn_phy_lp_get_txgain(mac);
12260
12261 save[0] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_0);
12262 save[1] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_VAL_0);
12263 save[2] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR);
12264 save[3] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVRVAL);
12265 save[4] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2);
12266 save[5] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2_VAL);
12267 save[6] = BWN_PHY_READ(mac, BWN_PHY_LP_PHY_CTL);
12268
12269 bwn_phy_lp_get_txpctlmode(mac);
12270 txpctlmode = plp->plp_txpctlmode;
12271 bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
12272
12273 /* disable CRS */
12274 bwn_phy_lp_set_deaf(mac, 1);
12275 bwn_phy_lp_set_trsw_over(mac, 0, 1);
12276 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffb);
12277 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x4);
12278 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7);
12279 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
12280 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x10);
12281 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12282 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf);
12283 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
12284 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffbf);
12285 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12286 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x7);
12287 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x38);
12288 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f);
12289 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x100);
12290 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfdff);
12291 BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL0, 0);
12292 BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL1, 1);
12293 BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL2, 0x20);
12294 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfbff);
12295 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xf7ff);
12296 BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0);
12297 BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, 0x45af);
12298 BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0x3ff);
12299
12300 loopback = bwn_phy_lp_loopback(mac);
12301 if (loopback == -1)
12302 goto done;
12303 bwn_phy_lp_set_rxgain_idx(mac, loopback);
12304 BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xffbf, 0x40);
12305 BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfff8, 0x1);
12306 BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xffc7, 0x8);
12307 BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f, 0xc0);
12308
12309 tmp = 0;
12310 memset(&ie, 0, sizeof(ie));
12311 for (i = 128; i <= 159; i++) {
12312 BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2, i);
12313 sum = 0;
12314 for (j = 5; j <= 25; j++) {
12315 bwn_phy_lp_ddfs_turnon(mac, 1, 1, j, j, 0);
12316 if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
12317 goto done;
12318 sqpwr = ie.ie_ipwr + ie.ie_qpwr;
12319 ipwr = ((pwrtbl[j - 5] >> 3) + 1) >> 1;
12320 npwr = bwn_phy_lp_roundup(sqpwr, (j == 5) ? sqpwr : 0,
12321 12);
12322 sum += ((ipwr - npwr) * (ipwr - npwr));
12323 if ((i == 128) || (sum < tmp)) {
12324 plp->plp_rccap = i;
12325 tmp = sum;
12326 }
12327 }
12328 }
12329 bwn_phy_lp_ddfs_turnoff(mac);
12330done:
12331 /* restore CRS */
12332 bwn_phy_lp_clear_deaf(mac, 1);
12333 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xff80);
12334 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfc00);
12335
12336 BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_VAL_0, save[1]);
12337 BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, save[0]);
12338 BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVRVAL, save[3]);
12339 BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, save[2]);
12340 BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2_VAL, save[5]);
12341 BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, save[4]);
12342 BWN_PHY_WRITE(mac, BWN_PHY_LP_PHY_CTL, save[6]);
12343
12344 bwn_phy_lp_set_bbmult(mac, bbmult);
12345 if (txo)
12346 bwn_phy_lp_set_txgain(mac, &tx_gains);
12347 bwn_phy_lp_set_txpctlmode(mac, txpctlmode);
12348 if (plp->plp_rccap)
12349 bwn_phy_lp_set_rccap(mac);
12350}
12351
12352static void
12353bwn_phy_lp_set_rccap(struct bwn_mac *mac)
12354{
12355 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12356 uint8_t rc_cap = (plp->plp_rccap & 0x1f) >> 1;
12357
12358 if (mac->mac_phy.rev == 1)
12359 rc_cap = MIN(rc_cap + 5, 15);
12360
12361 BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2,
12362 MAX(plp->plp_rccap - 4, 0x80));
12363 BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, rc_cap | 0x80);
12364 BWN_RF_WRITE(mac, BWN_B2062_S_RXG_CNT16,
12365 ((plp->plp_rccap & 0x1f) >> 2) | 0x80);
12366}
12367
12368static uint32_t
12369bwn_phy_lp_roundup(uint32_t value, uint32_t div, uint8_t pre)
12370{
12371 uint32_t i, q, r;
12372
12373 if (div == 0)
12374 return (0);
12375
12376 for (i = 0, q = value / div, r = value % div; i < pre; i++) {
12377 q <<= 1;
12378 if (r << 1 >= div) {
12379 q++;
12380 r = (r << 1) - div;
12381 }
12382 }
12383 if (r << 1 >= div)
12384 q++;
12385 return (q);
12386}
12387
12388static void
12389bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *mac)
12390{
12391 struct bwn_softc *sc = mac->mac_sc;
12392
12393 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0xff);
12394 DELAY(20);
12395 if (siba_get_chipid(sc->sc_dev) == 0x5354) {
12396 BWN_RF_WRITE(mac, BWN_B2062_N_COM1, 4);
12397 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 4);
12398 } else {
12399 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0);
12400 }
12401 DELAY(5);
12402}
12403
12404static void
12405bwn_phy_lp_b2062_vco_calib(struct bwn_mac *mac)
12406{
12407
12408 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x42);
12409 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x62);
12410 DELAY(200);
12411}
12412
12413static void
12414bwn_phy_lp_b2062_tblinit(struct bwn_mac *mac)
12415{
12416#define FLAG_A 0x01
12417#define FLAG_G 0x02
12418 struct bwn_softc *sc = mac->mac_sc;
12419 struct ifnet *ifp = sc->sc_ifp;
12420 struct ieee80211com *ic = ifp->if_l2com;
12421 static const struct bwn_b206x_rfinit_entry bwn_b2062_init_tab[] = {
12422 { BWN_B2062_N_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12423 { BWN_B2062_N_PDNCTL1, 0x0, 0xca, FLAG_G, },
12424 { BWN_B2062_N_PDNCTL3, 0x0, 0x0, FLAG_A | FLAG_G, },
12425 { BWN_B2062_N_PDNCTL4, 0x15, 0x2a, FLAG_A | FLAG_G, },
12426 { BWN_B2062_N_LGENC, 0xDB, 0xff, FLAG_A, },
12427 { BWN_B2062_N_LGENATUNE0, 0xdd, 0x0, FLAG_A | FLAG_G, },
12428 { BWN_B2062_N_LGENATUNE2, 0xdd, 0x0, FLAG_A | FLAG_G, },
12429 { BWN_B2062_N_LGENATUNE3, 0x77, 0xB5, FLAG_A | FLAG_G, },
12430 { BWN_B2062_N_LGENACTL3, 0x0, 0xff, FLAG_A | FLAG_G, },
12431 { BWN_B2062_N_LGENACTL7, 0x33, 0x33, FLAG_A | FLAG_G, },
12432 { BWN_B2062_N_RXA_CTL1, 0x0, 0x0, FLAG_G, },
12433 { BWN_B2062_N_RXBB_CTL0, 0x82, 0x80, FLAG_A | FLAG_G, },
12434 { BWN_B2062_N_RXBB_GAIN1, 0x4, 0x4, FLAG_A | FLAG_G, },
12435 { BWN_B2062_N_RXBB_GAIN2, 0x0, 0x0, FLAG_A | FLAG_G, },
12436 { BWN_B2062_N_TXCTL4, 0x3, 0x3, FLAG_A | FLAG_G, },
12437 { BWN_B2062_N_TXCTL5, 0x2, 0x2, FLAG_A | FLAG_G, },
12438 { BWN_B2062_N_TX_TUNE, 0x88, 0x1b, FLAG_A | FLAG_G, },
12439 { BWN_B2062_S_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12440 { BWN_B2062_S_PDS_CTL0, 0xff, 0xff, FLAG_A | FLAG_G, },
12441 { BWN_B2062_S_LGENG_CTL0, 0xf8, 0xd8, FLAG_A | FLAG_G, },
12442 { BWN_B2062_S_LGENG_CTL1, 0x3c, 0x24, FLAG_A | FLAG_G, },
12443 { BWN_B2062_S_LGENG_CTL8, 0x88, 0x80, FLAG_A | FLAG_G, },
12444 { BWN_B2062_S_LGENG_CTL10, 0x88, 0x80, FLAG_A | FLAG_G, },
12445 { BWN_B2062_S_RFPLLCTL0, 0x98, 0x98, FLAG_A | FLAG_G, },
12446 { BWN_B2062_S_RFPLLCTL1, 0x10, 0x10, FLAG_A | FLAG_G, },
12447 { BWN_B2062_S_RFPLLCTL5, 0x43, 0x43, FLAG_A | FLAG_G, },
12448 { BWN_B2062_S_RFPLLCTL6, 0x47, 0x47, FLAG_A | FLAG_G, },
12449 { BWN_B2062_S_RFPLLCTL7, 0xc, 0xc, FLAG_A | FLAG_G, },
12450 { BWN_B2062_S_RFPLLCTL8, 0x11, 0x11, FLAG_A | FLAG_G, },
12451 { BWN_B2062_S_RFPLLCTL9, 0x11, 0x11, FLAG_A | FLAG_G, },
12452 { BWN_B2062_S_RFPLLCTL10, 0xe, 0xe, FLAG_A | FLAG_G, },
12453 { BWN_B2062_S_RFPLLCTL11, 0x8, 0x8, FLAG_A | FLAG_G, },
12454 { BWN_B2062_S_RFPLLCTL12, 0x33, 0x33, FLAG_A | FLAG_G, },
12455 { BWN_B2062_S_RFPLLCTL13, 0xa, 0xa, FLAG_A | FLAG_G, },
12456 { BWN_B2062_S_RFPLLCTL14, 0x6, 0x6, FLAG_A | FLAG_G, },
12457 { BWN_B2062_S_RFPLLCTL18, 0x3e, 0x3e, FLAG_A | FLAG_G, },
12458 { BWN_B2062_S_RFPLLCTL19, 0x13, 0x13, FLAG_A | FLAG_G, },
12459 { BWN_B2062_S_RFPLLCTL21, 0x62, 0x62, FLAG_A | FLAG_G, },
12460 { BWN_B2062_S_RFPLLCTL22, 0x7, 0x7, FLAG_A | FLAG_G, },
12461 { BWN_B2062_S_RFPLLCTL23, 0x16, 0x16, FLAG_A | FLAG_G, },
12462 { BWN_B2062_S_RFPLLCTL24, 0x5c, 0x5c, FLAG_A | FLAG_G, },
12463 { BWN_B2062_S_RFPLLCTL25, 0x95, 0x95, FLAG_A | FLAG_G, },
12464 { BWN_B2062_S_RFPLLCTL30, 0xa0, 0xa0, FLAG_A | FLAG_G, },
12465 { BWN_B2062_S_RFPLLCTL31, 0x4, 0x4, FLAG_A | FLAG_G, },
12466 { BWN_B2062_S_RFPLLCTL33, 0xcc, 0xcc, FLAG_A | FLAG_G, },
12467 { BWN_B2062_S_RFPLLCTL34, 0x7, 0x7, FLAG_A | FLAG_G, },
12468 { BWN_B2062_S_RXG_CNT8, 0xf, 0xf, FLAG_A, },
12469 };
12470 const struct bwn_b206x_rfinit_entry *br;
12471 unsigned int i;
12472
12473 for (i = 0; i < N(bwn_b2062_init_tab); i++) {
12474 br = &bwn_b2062_init_tab[i];
12475 if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12476 if (br->br_flags & FLAG_G)
12477 BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12478 } else {
12479 if (br->br_flags & FLAG_A)
12480 BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12481 }
12482 }
12483#undef FLAG_A
12484#undef FLAG_B
12485}
12486
12487static void
12488bwn_phy_lp_b2063_tblinit(struct bwn_mac *mac)
12489{
12490#define FLAG_A 0x01
12491#define FLAG_G 0x02
12492 struct bwn_softc *sc = mac->mac_sc;
12493 struct ifnet *ifp = sc->sc_ifp;
12494 struct ieee80211com *ic = ifp->if_l2com;
12495 static const struct bwn_b206x_rfinit_entry bwn_b2063_init_tab[] = {
12496 { BWN_B2063_COM1, 0x0, 0x0, FLAG_G, },
12497 { BWN_B2063_COM10, 0x1, 0x0, FLAG_A, },
12498 { BWN_B2063_COM16, 0x0, 0x0, FLAG_G, },
12499 { BWN_B2063_COM17, 0x0, 0x0, FLAG_G, },
12500 { BWN_B2063_COM18, 0x0, 0x0, FLAG_G, },
12501 { BWN_B2063_COM19, 0x0, 0x0, FLAG_G, },
12502 { BWN_B2063_COM20, 0x0, 0x0, FLAG_G, },
12503 { BWN_B2063_COM21, 0x0, 0x0, FLAG_G, },
12504 { BWN_B2063_COM22, 0x0, 0x0, FLAG_G, },
12505 { BWN_B2063_COM23, 0x0, 0x0, FLAG_G, },
12506 { BWN_B2063_COM24, 0x0, 0x0, FLAG_G, },
12507 { BWN_B2063_LOGEN_SP1, 0xe8, 0xd4, FLAG_A | FLAG_G, },
12508 { BWN_B2063_LOGEN_SP2, 0xa7, 0x53, FLAG_A | FLAG_G, },
12509 { BWN_B2063_LOGEN_SP4, 0xf0, 0xf, FLAG_A | FLAG_G, },
12510 { BWN_B2063_G_RX_SP1, 0x1f, 0x5e, FLAG_G, },
12511 { BWN_B2063_G_RX_SP2, 0x7f, 0x7e, FLAG_G, },
12512 { BWN_B2063_G_RX_SP3, 0x30, 0xf0, FLAG_G, },
12513 { BWN_B2063_G_RX_SP7, 0x7f, 0x7f, FLAG_A | FLAG_G, },
12514 { BWN_B2063_G_RX_SP10, 0xc, 0xc, FLAG_A | FLAG_G, },
12515 { BWN_B2063_A_RX_SP1, 0x3c, 0x3f, FLAG_A, },
12516 { BWN_B2063_A_RX_SP2, 0xfc, 0xfe, FLAG_A, },
12517 { BWN_B2063_A_RX_SP7, 0x8, 0x8, FLAG_A | FLAG_G, },
12518 { BWN_B2063_RX_BB_SP4, 0x60, 0x60, FLAG_A | FLAG_G, },
12519 { BWN_B2063_RX_BB_SP8, 0x30, 0x30, FLAG_A | FLAG_G, },
12520 { BWN_B2063_TX_RF_SP3, 0xc, 0xb, FLAG_A | FLAG_G, },
12521 { BWN_B2063_TX_RF_SP4, 0x10, 0xf, FLAG_A | FLAG_G, },
12522 { BWN_B2063_PA_SP1, 0x3d, 0xfd, FLAG_A | FLAG_G, },
12523 { BWN_B2063_TX_BB_SP1, 0x2, 0x2, FLAG_A | FLAG_G, },
12524 { BWN_B2063_BANDGAP_CTL1, 0x56, 0x56, FLAG_A | FLAG_G, },
12525 { BWN_B2063_JTAG_VCO2, 0xF7, 0xF7, FLAG_A | FLAG_G, },
12526 { BWN_B2063_G_RX_MIX3, 0x71, 0x71, FLAG_A | FLAG_G, },
12527 { BWN_B2063_G_RX_MIX4, 0x71, 0x71, FLAG_A | FLAG_G, },
12528 { BWN_B2063_A_RX_1ST2, 0xf0, 0x30, FLAG_A, },
12529 { BWN_B2063_A_RX_PS6, 0x77, 0x77, FLAG_A | FLAG_G, },
12530 { BWN_B2063_A_RX_MIX4, 0x3, 0x3, FLAG_A | FLAG_G, },
12531 { BWN_B2063_A_RX_MIX5, 0xf, 0xf, FLAG_A | FLAG_G, },
12532 { BWN_B2063_A_RX_MIX6, 0xf, 0xf, FLAG_A | FLAG_G, },
12533 { BWN_B2063_RX_TIA_CTL1, 0x77, 0x77, FLAG_A | FLAG_G, },
12534 { BWN_B2063_RX_TIA_CTL3, 0x77, 0x77, FLAG_A | FLAG_G, },
12535 { BWN_B2063_RX_BB_CTL2, 0x4, 0x4, FLAG_A | FLAG_G, },
12536 { BWN_B2063_PA_CTL1, 0x0, 0x4, FLAG_A, },
12537 { BWN_B2063_VREG_CTL1, 0x3, 0x3, FLAG_A | FLAG_G, },
12538 };
12539 const struct bwn_b206x_rfinit_entry *br;
12540 unsigned int i;
12541
12542 for (i = 0; i < N(bwn_b2063_init_tab); i++) {
12543 br = &bwn_b2063_init_tab[i];
12544 if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12545 if (br->br_flags & FLAG_G)
12546 BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12547 } else {
12548 if (br->br_flags & FLAG_A)
12549 BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12550 }
12551 }
12552#undef FLAG_A
12553#undef FLAG_B
12554}
12555
12556static void
12557bwn_tab_read_multi(struct bwn_mac *mac, uint32_t typenoffset,
12558 int count, void *_data)
12559{
12560 unsigned int i;
12561 uint32_t offset, type;
12562 uint8_t *data = _data;
12563
12564 type = BWN_TAB_GETTYPE(typenoffset);
12565 offset = BWN_TAB_GETOFFSET(typenoffset);
12566 KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12567
12568 BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12569
12570 for (i = 0; i < count; i++) {
12571 switch (type) {
12572 case BWN_TAB_8BIT:
12573 *data = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
12574 data++;
12575 break;
12576 case BWN_TAB_16BIT:
12577 *((uint16_t *)data) = BWN_PHY_READ(mac,
12578 BWN_PHY_TABLEDATALO);
12579 data += 2;
12580 break;
12581 case BWN_TAB_32BIT:
12582 *((uint32_t *)data) = BWN_PHY_READ(mac,
12583 BWN_PHY_TABLEDATAHI);
12584 *((uint32_t *)data) <<= 16;
12585 *((uint32_t *)data) |= BWN_PHY_READ(mac,
12586 BWN_PHY_TABLEDATALO);
12587 data += 4;
12588 break;
12589 default:
12590 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12591 }
12592 }
12593}
12594
12595static void
12596bwn_tab_write_multi(struct bwn_mac *mac, uint32_t typenoffset,
12597 int count, const void *_data)
12598{
12599 uint32_t offset, type, value;
12600 const uint8_t *data = _data;
12601 unsigned int i;
12602
12603 type = BWN_TAB_GETTYPE(typenoffset);
12604 offset = BWN_TAB_GETOFFSET(typenoffset);
12605 KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12606
12607 BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12608
12609 for (i = 0; i < count; i++) {
12610 switch (type) {
12611 case BWN_TAB_8BIT:
12612 value = *data;
12613 data++;
12614 KASSERT(!(value & ~0xff),
12615 ("%s:%d: fail", __func__, __LINE__));
12616 BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12617 break;
12618 case BWN_TAB_16BIT:
12619 value = *((const uint16_t *)data);
12620 data += 2;
12621 KASSERT(!(value & ~0xffff),
12622 ("%s:%d: fail", __func__, __LINE__));
12623 BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12624 break;
12625 case BWN_TAB_32BIT:
12626 value = *((const uint32_t *)data);
12627 data += 4;
12628 BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
12629 BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12630 break;
12631 default:
12632 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12633 }
12634 }
12635}
12636
12637static struct bwn_txgain
12638bwn_phy_lp_get_txgain(struct bwn_mac *mac)
12639{
12640 struct bwn_txgain tg;
12641 uint16_t tmp;
12642
12643 tg.tg_dac = (BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0x380) >> 7;
12644 if (mac->mac_phy.rev < 2) {
12645 tmp = BWN_PHY_READ(mac,
12646 BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL) & 0x7ff;
12647 tg.tg_gm = tmp & 0x0007;
12648 tg.tg_pga = (tmp & 0x0078) >> 3;
12649 tg.tg_pad = (tmp & 0x780) >> 7;
12650 return (tg);
12651 }
12652
12653 tmp = BWN_PHY_READ(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL);
12654 tg.tg_pad = BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0xff;
12655 tg.tg_gm = tmp & 0xff;
12656 tg.tg_pga = (tmp >> 8) & 0xff;
12657 return (tg);
12658}
12659
12660static uint8_t
12661bwn_phy_lp_get_bbmult(struct bwn_mac *mac)
12662{
12663
12664 return (bwn_tab_read(mac, BWN_TAB_2(0, 87)) & 0xff00) >> 8;
12665}
12666
12667static void
12668bwn_phy_lp_set_txgain(struct bwn_mac *mac, struct bwn_txgain *tg)
12669{
12670 uint16_t pa;
12671
12672 if (mac->mac_phy.rev < 2) {
12673 BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0xf800,
12674 (tg->tg_pad << 7) | (tg->tg_pga << 3) | tg->tg_gm);
12675 bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12676 bwn_phy_lp_set_txgain_override(mac);
12677 return;
12678 }
12679
12680 pa = bwn_phy_lp_get_pa_gain(mac);
12681 BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
12682 (tg->tg_pga << 8) | tg->tg_gm);
12683 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0x8000,
12684 tg->tg_pad | (pa << 6));
12685 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xfc), (tg->tg_pga << 8) | tg->tg_gm);
12686 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x8000,
12687 tg->tg_pad | (pa << 8));
12688 bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12689 bwn_phy_lp_set_txgain_override(mac);
12690}
12691
12692static void
12693bwn_phy_lp_set_bbmult(struct bwn_mac *mac, uint8_t bbmult)
12694{
12695
12696 bwn_tab_write(mac, BWN_TAB_2(0, 87), (uint16_t)bbmult << 8);
12697}
12698
12699static void
12700bwn_phy_lp_set_trsw_over(struct bwn_mac *mac, uint8_t tx, uint8_t rx)
12701{
12702 uint16_t trsw = (tx << 1) | rx;
12703
12704 BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffc, trsw);
12705 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x3);
12706}
12707
12708static void
12709bwn_phy_lp_set_rxgain(struct bwn_mac *mac, uint32_t gain)
12710{
12711 struct bwn_softc *sc = mac->mac_sc;
12712 struct ifnet *ifp = sc->sc_ifp;
12713 struct ieee80211com *ic = ifp->if_l2com;
12714 uint16_t ext_lna, high_gain, lna, low_gain, trsw, tmp;
12715
12716 if (mac->mac_phy.rev < 2) {
12717 trsw = gain & 0x1;
12718 lna = (gain & 0xfffc) | ((gain & 0xc) >> 2);
12719 ext_lna = (gain & 2) >> 1;
12720
12721 BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12722 BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12723 0xfbff, ext_lna << 10);
12724 BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12725 0xf7ff, ext_lna << 11);
12726 BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, lna);
12727 } else {
12728 low_gain = gain & 0xffff;
12729 high_gain = (gain >> 16) & 0xf;
12730 ext_lna = (gain >> 21) & 0x1;
12731 trsw = ~(gain >> 20) & 0x1;
12732
12733 BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12734 BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12735 0xfdff, ext_lna << 9);
12736 BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12737 0xfbff, ext_lna << 10);
12738 BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, low_gain);
12739 BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff0, high_gain);
12740 if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12741 tmp = (gain >> 2) & 0x3;
12742 BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12743 0xe7ff, tmp<<11);
12744 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe6), 0xffe7,
12745 tmp << 3);
12746 }
12747 }
12748
12749 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1);
12750 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12751 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12752 if (mac->mac_phy.rev >= 2) {
12753 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
12754 if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12755 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x400);
12756 BWN_PHY_SET(mac, BWN_PHY_OFDM(0xe5), 0x8);
12757 }
12758 return;
12759 }
12760 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x200);
12761}
12762
12763static void
12764bwn_phy_lp_set_deaf(struct bwn_mac *mac, uint8_t user)
12765{
12766 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12767
12768 if (user)
12769 plp->plp_crsusr_off = 1;
12770 else
12771 plp->plp_crssys_off = 1;
12772
12773 BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x80);
12774}
12775
12776static void
12777bwn_phy_lp_clear_deaf(struct bwn_mac *mac, uint8_t user)
12778{
12779 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12780 struct bwn_softc *sc = mac->mac_sc;
12781 struct ifnet *ifp = sc->sc_ifp;
12782 struct ieee80211com *ic = ifp->if_l2com;
12783
12784 if (user)
12785 plp->plp_crsusr_off = 0;
12786 else
12787 plp->plp_crssys_off = 0;
12788
12789 if (plp->plp_crsusr_off || plp->plp_crssys_off)
12790 return;
12791
12792 if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12793 BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x60);
12794 else
12795 BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x20);
12796}
12797
12798static unsigned int
12799bwn_sqrt(struct bwn_mac *mac, unsigned int x)
12800{
12801 /* Table holding (10 * sqrt(x)) for x between 1 and 256. */
12802 static uint8_t sqrt_table[256] = {
12803 10, 14, 17, 20, 22, 24, 26, 28,
12804 30, 31, 33, 34, 36, 37, 38, 40,
12805 41, 42, 43, 44, 45, 46, 47, 48,
12806 50, 50, 51, 52, 53, 54, 55, 56,
12807 57, 58, 59, 60, 60, 61, 62, 63,
12808 64, 64, 65, 66, 67, 67, 68, 69,
12809 70, 70, 71, 72, 72, 73, 74, 74,
12810 75, 76, 76, 77, 78, 78, 79, 80,
12811 80, 81, 81, 82, 83, 83, 84, 84,
12812 85, 86, 86, 87, 87, 88, 88, 89,
12813 90, 90, 91, 91, 92, 92, 93, 93,
12814 94, 94, 95, 95, 96, 96, 97, 97,
12815 98, 98, 99, 100, 100, 100, 101, 101,
12816 102, 102, 103, 103, 104, 104, 105, 105,
12817 106, 106, 107, 107, 108, 108, 109, 109,
12818 110, 110, 110, 111, 111, 112, 112, 113,
12819 113, 114, 114, 114, 115, 115, 116, 116,
12820 117, 117, 117, 118, 118, 119, 119, 120,
12821 120, 120, 121, 121, 122, 122, 122, 123,
12822 123, 124, 124, 124, 125, 125, 126, 126,
12823 126, 127, 127, 128, 128, 128, 129, 129,
12824 130, 130, 130, 131, 131, 131, 132, 132,
12825 133, 133, 133, 134, 134, 134, 135, 135,
12826 136, 136, 136, 137, 137, 137, 138, 138,
12827 138, 139, 139, 140, 140, 140, 141, 141,
12828 141, 142, 142, 142, 143, 143, 143, 144,
12829 144, 144, 145, 145, 145, 146, 146, 146,
12830 147, 147, 147, 148, 148, 148, 149, 149,
12831 150, 150, 150, 150, 151, 151, 151, 152,
12832 152, 152, 153, 153, 153, 154, 154, 154,
12833 155, 155, 155, 156, 156, 156, 157, 157,
12834 157, 158, 158, 158, 159, 159, 159, 160
12835 };
12836
12837 if (x == 0)
12838 return (0);
12839 if (x >= 256) {
12840 unsigned int tmp;
12841
12842 for (tmp = 0; x >= (2 * tmp) + 1; x -= (2 * tmp++) + 1)
12843 /* do nothing */ ;
12844 return (tmp);
12845 }
12846 return (sqrt_table[x - 1] / 10);
12847}
12848
12849static int
12850bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *mac, uint16_t sample)
12851{
12852#define CALC_COEFF(_v, _x, _y, _z) do { \
12853 int _t; \
12854 _t = _x - 20; \
12855 if (_t >= 0) { \
12856 _v = ((_y << (30 - _x)) + (_z >> (1 + _t))) / (_z >> _t); \
12857 } else { \
12858 _v = ((_y << (30 - _x)) + (_z << (-1 - _t))) / (_z << -_t); \
12859 } \
12860} while (0)
12861#define CALC_COEFF2(_v, _x, _y, _z) do { \
12862 int _t; \
12863 _t = _x - 11; \
12864 if (_t >= 0) \
12865 tmp[3] = (_y << (31 - _x)) / (_z >> _t); \
12866 else \
12867 tmp[3] = (_y << (31 - _x)) / (_z << -_t); \
12868} while (0)
12869 struct bwn_phy_lp_iq_est ie;
12870 uint16_t v0, v1;
12871 int tmp[2], ret;
12872
12873 v1 = BWN_PHY_READ(mac, BWN_PHY_RX_COMP_COEFF_S);
12874 v0 = v1 >> 8;
12875 v1 |= 0xff;
12876
12877 BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, 0x00c0);
12878 BWN_PHY_MASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff);
12879
12880 ret = bwn_phy_lp_rx_iq_est(mac, sample, 32, &ie);
12881 if (ret == 0)
12882 goto done;
12883
12884 if (ie.ie_ipwr + ie.ie_qpwr < 2) {
12885 ret = 0;
12886 goto done;
12887 }
12888
12889 CALC_COEFF(tmp[0], bwn_nbits(ie.ie_iqprod), ie.ie_iqprod, ie.ie_ipwr);
12890 CALC_COEFF2(tmp[1], bwn_nbits(ie.ie_qpwr), ie.ie_qpwr, ie.ie_ipwr);
12891
12892 tmp[1] = -bwn_sqrt(mac, tmp[1] - (tmp[0] * tmp[0]));
12893 v0 = tmp[0] >> 3;
12894 v1 = tmp[1] >> 4;
12895done:
12896 BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, v1);
12897 BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, v0 << 8);
12898 return ret;
12899#undef CALC_COEFF
12900#undef CALC_COEFF2
12901}
12902
12903static void
12904bwn_phy_lp_tblinit_r01(struct bwn_mac *mac)
12905{
12906 static const uint16_t noisescale[] = {
12907 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12908 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa400, 0xa4a4, 0xa4a4,
12909 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12910 0xa4a4, 0xa4a4, 0x00a4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12911 0x0000, 0x0000, 0x4c00, 0x2d36, 0x0000, 0x0000, 0x4c00, 0x2d36,
12912 };
12913 static const uint16_t crsgainnft[] = {
12914 0x0366, 0x036a, 0x036f, 0x0364, 0x0367, 0x036d, 0x0374, 0x037f,
12915 0x036f, 0x037b, 0x038a, 0x0378, 0x0367, 0x036d, 0x0375, 0x0381,
12916 0x0374, 0x0381, 0x0392, 0x03a9, 0x03c4, 0x03e1, 0x0001, 0x001f,
12917 0x0040, 0x005e, 0x007f, 0x009e, 0x00bd, 0x00dd, 0x00fd, 0x011d,
12918 0x013d,
12919 };
12920 static const uint16_t filterctl[] = {
12921 0xa0fc, 0x10fc, 0x10db, 0x20b7, 0xff93, 0x10bf, 0x109b, 0x2077,
12922 0xff53, 0x0127,
12923 };
12924 static const uint32_t psctl[] = {
12925 0x00010000, 0x000000a0, 0x00040000, 0x00000048, 0x08080101,
12926 0x00000080, 0x08080101, 0x00000040, 0x08080101, 0x000000c0,
12927 0x08a81501, 0x000000c0, 0x0fe8fd01, 0x000000c0, 0x08300105,
12928 0x000000c0, 0x08080201, 0x000000c0, 0x08280205, 0x000000c0,
12929 0xe80802fe, 0x000000c7, 0x28080206, 0x000000c0, 0x08080202,
12930 0x000000c0, 0x0ba87602, 0x000000c0, 0x1068013d, 0x000000c0,
12931 0x10280105, 0x000000c0, 0x08880102, 0x000000c0, 0x08280106,
12932 0x000000c0, 0xe80801fd, 0x000000c7, 0xa8080115, 0x000000c0,
12933 };
12934 static const uint16_t ofdmcckgain_r0[] = {
12935 0x0001, 0x0001, 0x0001, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12936 0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12937 0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12938 0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12939 0x755d,
12940 };
12941 static const uint16_t ofdmcckgain_r1[] = {
12942 0x5000, 0x6000, 0x7000, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12943 0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12944 0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12945 0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12946 0x755d,
12947 };
12948 static const uint16_t gaindelta[] = {
12949 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12950 0x0000,
12951 };
12952 static const uint32_t txpwrctl[] = {
12953 0x00000050, 0x0000004f, 0x0000004e, 0x0000004d, 0x0000004c,
12954 0x0000004b, 0x0000004a, 0x00000049, 0x00000048, 0x00000047,
12955 0x00000046, 0x00000045, 0x00000044, 0x00000043, 0x00000042,
12956 0x00000041, 0x00000040, 0x0000003f, 0x0000003e, 0x0000003d,
12957 0x0000003c, 0x0000003b, 0x0000003a, 0x00000039, 0x00000038,
12958 0x00000037, 0x00000036, 0x00000035, 0x00000034, 0x00000033,
12959 0x00000032, 0x00000031, 0x00000030, 0x0000002f, 0x0000002e,
12960 0x0000002d, 0x0000002c, 0x0000002b, 0x0000002a, 0x00000029,
12961 0x00000028, 0x00000027, 0x00000026, 0x00000025, 0x00000024,
12962 0x00000023, 0x00000022, 0x00000021, 0x00000020, 0x0000001f,
12963 0x0000001e, 0x0000001d, 0x0000001c, 0x0000001b, 0x0000001a,
12964 0x00000019, 0x00000018, 0x00000017, 0x00000016, 0x00000015,
12965 0x00000014, 0x00000013, 0x00000012, 0x00000011, 0x00000000,
12966 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12967 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12968 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12969 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12970 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12971 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12972 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12973 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12974 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12975 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12976 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12977 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12978 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12979 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12980 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12981 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12982 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12983 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12984 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12985 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12986 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12987 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12988 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12989 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12990 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12991 0x00000000, 0x00000000, 0x000075a0, 0x000075a0, 0x000075a1,
12992 0x000075a1, 0x000075a2, 0x000075a2, 0x000075a3, 0x000075a3,
12993 0x000074b0, 0x000074b0, 0x000074b1, 0x000074b1, 0x000074b2,
12994 0x000074b2, 0x000074b3, 0x000074b3, 0x00006d20, 0x00006d20,
12995 0x00006d21, 0x00006d21, 0x00006d22, 0x00006d22, 0x00006d23,
12996 0x00006d23, 0x00004660, 0x00004660, 0x00004661, 0x00004661,
12997 0x00004662, 0x00004662, 0x00004663, 0x00004663, 0x00003e60,
12998 0x00003e60, 0x00003e61, 0x00003e61, 0x00003e62, 0x00003e62,
12999 0x00003e63, 0x00003e63, 0x00003660, 0x00003660, 0x00003661,
13000 0x00003661, 0x00003662, 0x00003662, 0x00003663, 0x00003663,
13001 0x00002e60, 0x00002e60, 0x00002e61, 0x00002e61, 0x00002e62,
13002 0x00002e62, 0x00002e63, 0x00002e63, 0x00002660, 0x00002660,
13003 0x00002661, 0x00002661, 0x00002662, 0x00002662, 0x00002663,
13004 0x00002663, 0x000025e0, 0x000025e0, 0x000025e1, 0x000025e1,
13005 0x000025e2, 0x000025e2, 0x000025e3, 0x000025e3, 0x00001de0,
13006 0x00001de0, 0x00001de1, 0x00001de1, 0x00001de2, 0x00001de2,
13007 0x00001de3, 0x00001de3, 0x00001d60, 0x00001d60, 0x00001d61,
13008 0x00001d61, 0x00001d62, 0x00001d62, 0x00001d63, 0x00001d63,
13009 0x00001560, 0x00001560, 0x00001561, 0x00001561, 0x00001562,
13010 0x00001562, 0x00001563, 0x00001563, 0x00000d60, 0x00000d60,
13011 0x00000d61, 0x00000d61, 0x00000d62, 0x00000d62, 0x00000d63,
13012 0x00000d63, 0x00000ce0, 0x00000ce0, 0x00000ce1, 0x00000ce1,
13013 0x00000ce2, 0x00000ce2, 0x00000ce3, 0x00000ce3, 0x00000e10,
13014 0x00000e10, 0x00000e11, 0x00000e11, 0x00000e12, 0x00000e12,
13015 0x00000e13, 0x00000e13, 0x00000bf0, 0x00000bf0, 0x00000bf1,
13016 0x00000bf1, 0x00000bf2, 0x00000bf2, 0x00000bf3, 0x00000bf3,
13017 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13018 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13019 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13020 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13021 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13022 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13023 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13024 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13025 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13026 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13027 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13028 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13029 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13030 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13031 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13032 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13033 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13034 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13035 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13036 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13037 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13038 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13039 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13040 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13041 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13042 0x04000000, 0x04200000, 0x04000000, 0x000000ff, 0x000002fc,
13043 0x0000fa08, 0x00000305, 0x00000206, 0x00000304, 0x0000fb04,
13044 0x0000fcff, 0x000005fb, 0x0000fd01, 0x00000401, 0x00000006,
13045 0x0000ff03, 0x000007fc, 0x0000fc08, 0x00000203, 0x0000fffb,
13046 0x00000600, 0x0000fa01, 0x0000fc03, 0x0000fe06, 0x0000fe00,
13047 0x00000102, 0x000007fd, 0x000004fb, 0x000006ff, 0x000004fd,
13048 0x0000fdfa, 0x000007fb, 0x0000fdfa, 0x0000fa06, 0x00000500,
13049 0x0000f902, 0x000007fa, 0x0000fafa, 0x00000500, 0x000007fa,
13050 0x00000700, 0x00000305, 0x000004ff, 0x00000801, 0x00000503,
13051 0x000005f9, 0x00000404, 0x0000fb08, 0x000005fd, 0x00000501,
13052 0x00000405, 0x0000fb03, 0x000007fc, 0x00000403, 0x00000303,
13053 0x00000402, 0x0000faff, 0x0000fe05, 0x000005fd, 0x0000fe01,
13054 0x000007fa, 0x00000202, 0x00000504, 0x00000102, 0x000008fe,
13055 0x0000fa04, 0x0000fafc, 0x0000fe08, 0x000000f9, 0x000002fa,
13056 0x000003fe, 0x00000304, 0x000004f9, 0x00000100, 0x0000fd06,
13057 0x000008fc, 0x00000701, 0x00000504, 0x0000fdfe, 0x0000fdfc,
13058 0x000003fe, 0x00000704, 0x000002fc, 0x000004f9, 0x0000fdfd,
13059 0x0000fa07, 0x00000205, 0x000003fd, 0x000005fb, 0x000004f9,
13060 0x00000804, 0x0000fc06, 0x0000fcf9, 0x00000100, 0x0000fe05,
13061 0x00000408, 0x0000fb02, 0x00000304, 0x000006fe, 0x000004fa,
13062 0x00000305, 0x000008fc, 0x00000102, 0x000001fd, 0x000004fc,
13063 0x0000fe03, 0x00000701, 0x000001fb, 0x000001f9, 0x00000206,
13064 0x000006fd, 0x00000508, 0x00000700, 0x00000304, 0x000005fe,
13065 0x000005ff, 0x0000fa04, 0x00000303, 0x0000fefb, 0x000007f9,
13066 0x0000fefc, 0x000004fd, 0x000005fc, 0x0000fffd, 0x0000fc08,
13067 0x0000fbf9, 0x0000fd07, 0x000008fb, 0x0000fe02, 0x000006fb,
13068 0x00000702,
13069 };
13070
13071 KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13072
13073 bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13074 bwn_tab_sigsq_tbl);
13075 bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13076 bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(crsgainnft), crsgainnft);
13077 bwn_tab_write_multi(mac, BWN_TAB_2(8, 0), N(filterctl), filterctl);
13078 bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(psctl), psctl);
13079 bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13080 bwn_tab_pllfrac_tbl);
13081 bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13082 bwn_tabl_iqlocal_tbl);
13083 if (mac->mac_phy.rev == 0) {
13084 bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r0),
13085 ofdmcckgain_r0);
13086 bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r0),
13087 ofdmcckgain_r0);
13088 } else {
13089 bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r1),
13090 ofdmcckgain_r1);
13091 bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r1),
13092 ofdmcckgain_r1);
13093 }
13094 bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(gaindelta), gaindelta);
13095 bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(txpwrctl), txpwrctl);
13096}
13097
13098static void
13099bwn_phy_lp_tblinit_r2(struct bwn_mac *mac)
13100{
13101 struct bwn_softc *sc = mac->mac_sc;
13102 int i;
13103 static const uint16_t noisescale[] = {
13104 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13105 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13106 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13107 0x00a4, 0x00a4, 0x0000, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13108 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13109 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13110 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4
13111 };
13112 static const uint32_t filterctl[] = {
13113 0x000141fc, 0x000021fc, 0x000021b7, 0x0000416f, 0x0001ff27,
13114 0x0000217f, 0x00002137, 0x000040ef, 0x0001fea7, 0x0000024f
13115 };
13116 static const uint32_t psctl[] = {
13117 0x00e38e08, 0x00e08e38, 0x00000000, 0x00000000, 0x00000000,
13118 0x00002080, 0x00006180, 0x00003002, 0x00000040, 0x00002042,
13119 0x00180047, 0x00080043, 0x00000041, 0x000020c1, 0x00046006,
13120 0x00042002, 0x00040000, 0x00002003, 0x00180006, 0x00080002
13121 };
13122 static const uint32_t gainidx[] = {
13123 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13124 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13125 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13126 0x00000000, 0x00000000, 0x00000000, 0x10000001, 0x00000000,
13127 0x20000082, 0x00000000, 0x40000104, 0x00000000, 0x60004207,
13128 0x00000001, 0x7000838a, 0x00000001, 0xd021050d, 0x00000001,
13129 0xe041c683, 0x00000001, 0x50828805, 0x00000000, 0x80e34288,
13130 0x00000000, 0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000,
13131 0x12064711, 0x00000001, 0xb0a18612, 0x00000010, 0xe1024794,
13132 0x00000010, 0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011,
13133 0xc1848a9c, 0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21,
13134 0x00000019, 0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019,
13135 0xb36811a6, 0x00000019, 0xf3e89227, 0x00000019, 0x0408d329,
13136 0x0000001a, 0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a,
13137 0x54aa152c, 0x0000001a, 0x64ca55ad, 0x0000001a, 0x00000000,
13138 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13139 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13140 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13141 0x00000000, 0x00000000, 0x10000001, 0x00000000, 0x20000082,
13142 0x00000000, 0x40000104, 0x00000000, 0x60004207, 0x00000001,
13143 0x7000838a, 0x00000001, 0xd021050d, 0x00000001, 0xe041c683,
13144 0x00000001, 0x50828805, 0x00000000, 0x80e34288, 0x00000000,
13145 0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000, 0x12064711,
13146 0x00000001, 0xb0a18612, 0x00000010, 0xe1024794, 0x00000010,
13147 0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011, 0xc1848a9c,
13148 0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21, 0x00000019,
13149 0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019, 0xb36811a6,
13150 0x00000019, 0xf3e89227, 0x00000019, 0x0408d329, 0x0000001a,
13151 0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a, 0x54aa152c,
13152 0x0000001a, 0x64ca55ad, 0x0000001a
13153 };
13154 static const uint16_t auxgainidx[] = {
13155 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13156 0x0000, 0x0001, 0x0002, 0x0004, 0x0016, 0x0000, 0x0000, 0x0000,
13157 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002,
13158 0x0004, 0x0016
13159 };
13160 static const uint16_t swctl[] = {
13161 0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13162 0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13163 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
13164 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018,
13165 0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13166 0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13167 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
13168 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018
13169 };
13170 static const uint8_t hf[] = {
13171 0x4b, 0x36, 0x24, 0x18, 0x49, 0x34, 0x23, 0x17, 0x48,
13172 0x33, 0x23, 0x17, 0x48, 0x33, 0x23, 0x17
13173 };
13174 static const uint32_t gainval[] = {
13175 0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13176 0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13177 0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13178 0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13179 0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13180 0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13181 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13182 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13183 0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13184 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13185 0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13186 0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13187 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000009,
13188 0x000000f1, 0x00000000, 0x00000000
13189 };
13190 static const uint16_t gain[] = {
13191 0x0000, 0x0400, 0x0800, 0x0802, 0x0804, 0x0806, 0x0807, 0x0808,
13192 0x080a, 0x080b, 0x080c, 0x080e, 0x080f, 0x0810, 0x0812, 0x0813,
13193 0x0814, 0x0816, 0x0817, 0x081a, 0x081b, 0x081f, 0x0820, 0x0824,
13194 0x0830, 0x0834, 0x0837, 0x083b, 0x083f, 0x0840, 0x0844, 0x0857,
13195 0x085b, 0x085f, 0x08d7, 0x08db, 0x08df, 0x0957, 0x095b, 0x095f,
13196 0x0b57, 0x0b5b, 0x0b5f, 0x0f5f, 0x135f, 0x175f, 0x0000, 0x0000,
13197 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13198 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13199 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13200 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13201 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13202 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13203 };
13204 static const uint32_t papdeps[] = {
13205 0x00000000, 0x00013ffc, 0x0001dff3, 0x0001bff0, 0x00023fe9,
13206 0x00021fdf, 0x00028fdf, 0x00033fd2, 0x00039fcb, 0x00043fc7,
13207 0x0004efc2, 0x00055fb5, 0x0005cfb0, 0x00063fa8, 0x00068fa3,
13208 0x00071f98, 0x0007ef92, 0x00084f8b, 0x0008df82, 0x00097f77,
13209 0x0009df69, 0x000a3f62, 0x000adf57, 0x000b6f4c, 0x000bff41,
13210 0x000c9f39, 0x000cff30, 0x000dbf27, 0x000e4f1e, 0x000edf16,
13211 0x000f7f13, 0x00102f11, 0x00110f10, 0x0011df11, 0x0012ef15,
13212 0x00143f1c, 0x00158f27, 0x00172f35, 0x00193f47, 0x001baf5f,
13213 0x001e6f7e, 0x0021cfa4, 0x0025bfd2, 0x002a2008, 0x002fb047,
13214 0x00360090, 0x003d40e0, 0x0045c135, 0x004fb189, 0x005ae1d7,
13215 0x0067221d, 0x0075025a, 0x007ff291, 0x007ff2bf, 0x007ff2e3,
13216 0x007ff2ff, 0x007ff315, 0x007ff329, 0x007ff33f, 0x007ff356,
13217 0x007ff36e, 0x007ff39c, 0x007ff441, 0x007ff506
13218 };
13219 static const uint32_t papdmult[] = {
13220 0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13221 0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13222 0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13223 0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13224 0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13225 0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13226 0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13227 0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13228 0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13229 0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13230 0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13231 0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13232 0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13233 };
13234 static const uint32_t gainidx_a0[] = {
13235 0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13236 0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13237 0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13238 0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13239 0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13240 0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13241 0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13242 0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13243 0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13244 0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13245 0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13246 0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13247 0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13248 };
13249 static const uint16_t auxgainidx_a0[] = {
13250 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13251 0x0000, 0x0000, 0x0000, 0x0002, 0x0014, 0x0000, 0x0000, 0x0000,
13252 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13253 0x0002, 0x0014
13254 };
13255 static const uint32_t gainval_a0[] = {
13256 0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13257 0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13258 0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13259 0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13260 0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13261 0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13262 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13263 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13264 0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13265 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13266 0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13267 0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13268 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000f,
13269 0x000000f7, 0x00000000, 0x00000000
13270 };
13271 static const uint16_t gain_a0[] = {
13272 0x0000, 0x0002, 0x0004, 0x0006, 0x0007, 0x0008, 0x000a, 0x000b,
13273 0x000c, 0x000e, 0x000f, 0x0010, 0x0012, 0x0013, 0x0014, 0x0016,
13274 0x0017, 0x001a, 0x001b, 0x001f, 0x0020, 0x0024, 0x0030, 0x0034,
13275 0x0037, 0x003b, 0x003f, 0x0040, 0x0044, 0x0057, 0x005b, 0x005f,
13276 0x00d7, 0x00db, 0x00df, 0x0157, 0x015b, 0x015f, 0x0357, 0x035b,
13277 0x035f, 0x075f, 0x0b5f, 0x0f5f, 0x0000, 0x0000, 0x0000, 0x0000,
13278 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13279 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13280 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13281 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13282 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13283 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13284 };
13285
13286 KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13287
13288 for (i = 0; i < 704; i++)
13289 bwn_tab_write(mac, BWN_TAB_4(7, i), 0);
13290
13291 bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13292 bwn_tab_sigsq_tbl);
13293 bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13294 bwn_tab_write_multi(mac, BWN_TAB_4(11, 0), N(filterctl), filterctl);
13295 bwn_tab_write_multi(mac, BWN_TAB_4(12, 0), N(psctl), psctl);
13296 bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx), gainidx);
13297 bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx), auxgainidx);
13298 bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(swctl), swctl);
13299 bwn_tab_write_multi(mac, BWN_TAB_1(16, 0), N(hf), hf);
13300 bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval), gainval);
13301 bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain), gain);
13302 bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13303 bwn_tab_pllfrac_tbl);
13304 bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13305 bwn_tabl_iqlocal_tbl);
13306 bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(papdeps), papdeps);
13307 bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(papdmult), papdmult);
13308
13309 if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
13310 (siba_get_chiprev(sc->sc_dev) == 0)) {
13311 bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx_a0),
13312 gainidx_a0);
13313 bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx_a0),
13314 auxgainidx_a0);
13315 bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval_a0),
13316 gainval_a0);
13317 bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain_a0), gain_a0);
13318 }
13319}
13320
13321static void
13322bwn_phy_lp_tblinit_txgain(struct bwn_mac *mac)
13323{
13324 struct bwn_softc *sc = mac->mac_sc;
13325 struct ifnet *ifp = sc->sc_ifp;
13326 struct ieee80211com *ic = ifp->if_l2com;
13327 static struct bwn_txgain_entry txgain_r2[] = {
13328 { 255, 255, 203, 0, 152 }, { 255, 255, 203, 0, 147 },
13329 { 255, 255, 203, 0, 143 }, { 255, 255, 203, 0, 139 },
13330 { 255, 255, 203, 0, 135 }, { 255, 255, 203, 0, 131 },
13331 { 255, 255, 203, 0, 128 }, { 255, 255, 203, 0, 124 },
13332 { 255, 255, 203, 0, 121 }, { 255, 255, 203, 0, 117 },
13333 { 255, 255, 203, 0, 114 }, { 255, 255, 203, 0, 111 },
13334 { 255, 255, 203, 0, 107 }, { 255, 255, 203, 0, 104 },
13335 { 255, 255, 203, 0, 101 }, { 255, 255, 203, 0, 99 },
13336 { 255, 255, 203, 0, 96 }, { 255, 255, 203, 0, 93 },
13337 { 255, 255, 203, 0, 90 }, { 255, 255, 203, 0, 88 },
13338 { 255, 255, 203, 0, 85 }, { 255, 255, 203, 0, 83 },
13339 { 255, 255, 203, 0, 81 }, { 255, 255, 203, 0, 78 },
13340 { 255, 255, 203, 0, 76 }, { 255, 255, 203, 0, 74 },
13341 { 255, 255, 203, 0, 72 }, { 255, 255, 203, 0, 70 },
13342 { 255, 255, 203, 0, 68 }, { 255, 255, 203, 0, 66 },
13343 { 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13344 { 255, 255, 192, 0, 64 }, { 255, 255, 186, 0, 64 },
13345 { 255, 255, 181, 0, 64 }, { 255, 255, 176, 0, 64 },
13346 { 255, 255, 171, 0, 64 }, { 255, 255, 166, 0, 64 },
13347 { 255, 255, 161, 0, 64 }, { 255, 255, 157, 0, 64 },
13348 { 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13349 { 255, 255, 144, 0, 64 }, { 255, 255, 140, 0, 64 },
13350 { 255, 255, 136, 0, 64 }, { 255, 255, 132, 0, 64 },
13351 { 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13352 { 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13353 { 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13354 { 255, 255, 108, 0, 64 }, { 255, 255, 105, 0, 64 },
13355 { 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13356 { 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13357 { 255, 255, 91, 0, 64 }, { 255, 255, 88, 0, 64 },
13358 { 255, 255, 86, 0, 64 }, { 255, 255, 83, 0, 64 },
13359 { 255, 255, 81, 0, 64 }, { 255, 255, 79, 0, 64 },
13360 { 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13361 { 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13362 { 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13363 { 255, 255, 64, 0, 64 }, { 255, 248, 64, 0, 64 },
13364 { 255, 248, 62, 0, 64 }, { 255, 241, 62, 0, 64 },
13365 { 255, 241, 60, 0, 64 }, { 255, 234, 60, 0, 64 },
13366 { 255, 234, 59, 0, 64 }, { 255, 227, 59, 0, 64 },
13367 { 255, 227, 57, 0, 64 }, { 255, 221, 57, 0, 64 },
13368 { 255, 221, 55, 0, 64 }, { 255, 215, 55, 0, 64 },
13369 { 255, 215, 54, 0, 64 }, { 255, 208, 54, 0, 64 },
13370 { 255, 208, 52, 0, 64 }, { 255, 203, 52, 0, 64 },
13371 { 255, 203, 51, 0, 64 }, { 255, 197, 51, 0, 64 },
13372 { 255, 197, 49, 0, 64 }, { 255, 191, 49, 0, 64 },
13373 { 255, 191, 48, 0, 64 }, { 255, 186, 48, 0, 64 },
13374 { 255, 186, 47, 0, 64 }, { 255, 181, 47, 0, 64 },
13375 { 255, 181, 45, 0, 64 }, { 255, 175, 45, 0, 64 },
13376 { 255, 175, 44, 0, 64 }, { 255, 170, 44, 0, 64 },
13377 { 255, 170, 43, 0, 64 }, { 255, 166, 43, 0, 64 },
13378 { 255, 166, 42, 0, 64 }, { 255, 161, 42, 0, 64 },
13379 { 255, 161, 40, 0, 64 }, { 255, 156, 40, 0, 64 },
13380 { 255, 156, 39, 0, 64 }, { 255, 152, 39, 0, 64 },
13381 { 255, 152, 38, 0, 64 }, { 255, 148, 38, 0, 64 },
13382 { 255, 148, 37, 0, 64 }, { 255, 143, 37, 0, 64 },
13383 { 255, 143, 36, 0, 64 }, { 255, 139, 36, 0, 64 },
13384 { 255, 139, 35, 0, 64 }, { 255, 135, 35, 0, 64 },
13385 { 255, 135, 34, 0, 64 }, { 255, 132, 34, 0, 64 },
13386 { 255, 132, 33, 0, 64 }, { 255, 128, 33, 0, 64 },
13387 { 255, 128, 32, 0, 64 }, { 255, 124, 32, 0, 64 },
13388 { 255, 124, 31, 0, 64 }, { 255, 121, 31, 0, 64 },
13389 { 255, 121, 30, 0, 64 }, { 255, 117, 30, 0, 64 },
13390 { 255, 117, 29, 0, 64 }, { 255, 114, 29, 0, 64 },
13391 { 255, 114, 29, 0, 64 }, { 255, 111, 29, 0, 64 },
13392 };
13393 static struct bwn_txgain_entry txgain_2ghz_r2[] = {
13394 { 7, 99, 255, 0, 64 }, { 7, 96, 255, 0, 64 },
13395 { 7, 93, 255, 0, 64 }, { 7, 90, 255, 0, 64 },
13396 { 7, 88, 255, 0, 64 }, { 7, 85, 255, 0, 64 },
13397 { 7, 83, 255, 0, 64 }, { 7, 81, 255, 0, 64 },
13398 { 7, 78, 255, 0, 64 }, { 7, 76, 255, 0, 64 },
13399 { 7, 74, 255, 0, 64 }, { 7, 72, 255, 0, 64 },
13400 { 7, 70, 255, 0, 64 }, { 7, 68, 255, 0, 64 },
13401 { 7, 66, 255, 0, 64 }, { 7, 64, 255, 0, 64 },
13402 { 7, 64, 255, 0, 64 }, { 7, 62, 255, 0, 64 },
13403 { 7, 62, 248, 0, 64 }, { 7, 60, 248, 0, 64 },
13404 { 7, 60, 241, 0, 64 }, { 7, 59, 241, 0, 64 },
13405 { 7, 59, 234, 0, 64 }, { 7, 57, 234, 0, 64 },
13406 { 7, 57, 227, 0, 64 }, { 7, 55, 227, 0, 64 },
13407 { 7, 55, 221, 0, 64 }, { 7, 54, 221, 0, 64 },
13408 { 7, 54, 215, 0, 64 }, { 7, 52, 215, 0, 64 },
13409 { 7, 52, 208, 0, 64 }, { 7, 51, 208, 0, 64 },
13410 { 7, 51, 203, 0, 64 }, { 7, 49, 203, 0, 64 },
13411 { 7, 49, 197, 0, 64 }, { 7, 48, 197, 0, 64 },
13412 { 7, 48, 191, 0, 64 }, { 7, 47, 191, 0, 64 },
13413 { 7, 47, 186, 0, 64 }, { 7, 45, 186, 0, 64 },
13414 { 7, 45, 181, 0, 64 }, { 7, 44, 181, 0, 64 },
13415 { 7, 44, 175, 0, 64 }, { 7, 43, 175, 0, 64 },
13416 { 7, 43, 170, 0, 64 }, { 7, 42, 170, 0, 64 },
13417 { 7, 42, 166, 0, 64 }, { 7, 40, 166, 0, 64 },
13418 { 7, 40, 161, 0, 64 }, { 7, 39, 161, 0, 64 },
13419 { 7, 39, 156, 0, 64 }, { 7, 38, 156, 0, 64 },
13420 { 7, 38, 152, 0, 64 }, { 7, 37, 152, 0, 64 },
13421 { 7, 37, 148, 0, 64 }, { 7, 36, 148, 0, 64 },
13422 { 7, 36, 143, 0, 64 }, { 7, 35, 143, 0, 64 },
13423 { 7, 35, 139, 0, 64 }, { 7, 34, 139, 0, 64 },
13424 { 7, 34, 135, 0, 64 }, { 7, 33, 135, 0, 64 },
13425 { 7, 33, 132, 0, 64 }, { 7, 32, 132, 0, 64 },
13426 { 7, 32, 128, 0, 64 }, { 7, 31, 128, 0, 64 },
13427 { 7, 31, 124, 0, 64 }, { 7, 30, 124, 0, 64 },
13428 { 7, 30, 121, 0, 64 }, { 7, 29, 121, 0, 64 },
13429 { 7, 29, 117, 0, 64 }, { 7, 29, 117, 0, 64 },
13430 { 7, 29, 114, 0, 64 }, { 7, 28, 114, 0, 64 },
13431 { 7, 28, 111, 0, 64 }, { 7, 27, 111, 0, 64 },
13432 { 7, 27, 108, 0, 64 }, { 7, 26, 108, 0, 64 },
13433 { 7, 26, 104, 0, 64 }, { 7, 25, 104, 0, 64 },
13434 { 7, 25, 102, 0, 64 }, { 7, 25, 102, 0, 64 },
13435 { 7, 25, 99, 0, 64 }, { 7, 24, 99, 0, 64 },
13436 { 7, 24, 96, 0, 64 }, { 7, 23, 96, 0, 64 },
13437 { 7, 23, 93, 0, 64 }, { 7, 23, 93, 0, 64 },
13438 { 7, 23, 90, 0, 64 }, { 7, 22, 90, 0, 64 },
13439 { 7, 22, 88, 0, 64 }, { 7, 21, 88, 0, 64 },
13440 { 7, 21, 85, 0, 64 }, { 7, 21, 85, 0, 64 },
13441 { 7, 21, 83, 0, 64 }, { 7, 20, 83, 0, 64 },
13442 { 7, 20, 81, 0, 64 }, { 7, 20, 81, 0, 64 },
13443 { 7, 20, 78, 0, 64 }, { 7, 19, 78, 0, 64 },
13444 { 7, 19, 76, 0, 64 }, { 7, 19, 76, 0, 64 },
13445 { 7, 19, 74, 0, 64 }, { 7, 18, 74, 0, 64 },
13446 { 7, 18, 72, 0, 64 }, { 7, 18, 72, 0, 64 },
13447 { 7, 18, 70, 0, 64 }, { 7, 17, 70, 0, 64 },
13448 { 7, 17, 68, 0, 64 }, { 7, 17, 68, 0, 64 },
13449 { 7, 17, 66, 0, 64 }, { 7, 16, 66, 0, 64 },
13450 { 7, 16, 64, 0, 64 }, { 7, 16, 64, 0, 64 },
13451 { 7, 16, 62, 0, 64 }, { 7, 15, 62, 0, 64 },
13452 { 7, 15, 60, 0, 64 }, { 7, 15, 60, 0, 64 },
13453 { 7, 15, 59, 0, 64 }, { 7, 14, 59, 0, 64 },
13454 { 7, 14, 57, 0, 64 }, { 7, 14, 57, 0, 64 },
13455 { 7, 14, 55, 0, 64 }, { 7, 14, 55, 0, 64 },
13456 { 7, 14, 54, 0, 64 }, { 7, 13, 54, 0, 64 },
13457 { 7, 13, 52, 0, 64 }, { 7, 13, 52, 0, 64 },
13458 };
13459 static struct bwn_txgain_entry txgain_5ghz_r2[] = {
13460 { 255, 255, 255, 0, 152 }, { 255, 255, 255, 0, 147 },
13461 { 255, 255, 255, 0, 143 }, { 255, 255, 255, 0, 139 },
13462 { 255, 255, 255, 0, 135 }, { 255, 255, 255, 0, 131 },
13463 { 255, 255, 255, 0, 128 }, { 255, 255, 255, 0, 124 },
13464 { 255, 255, 255, 0, 121 }, { 255, 255, 255, 0, 117 },
13465 { 255, 255, 255, 0, 114 }, { 255, 255, 255, 0, 111 },
13466 { 255, 255, 255, 0, 107 }, { 255, 255, 255, 0, 104 },
13467 { 255, 255, 255, 0, 101 }, { 255, 255, 255, 0, 99 },
13468 { 255, 255, 255, 0, 96 }, { 255, 255, 255, 0, 93 },
13469 { 255, 255, 255, 0, 90 }, { 255, 255, 255, 0, 88 },
13470 { 255, 255, 255, 0, 85 }, { 255, 255, 255, 0, 83 },
13471 { 255, 255, 255, 0, 81 }, { 255, 255, 255, 0, 78 },
13472 { 255, 255, 255, 0, 76 }, { 255, 255, 255, 0, 74 },
13473 { 255, 255, 255, 0, 72 }, { 255, 255, 255, 0, 70 },
13474 { 255, 255, 255, 0, 68 }, { 255, 255, 255, 0, 66 },
13475 { 255, 255, 255, 0, 64 }, { 255, 255, 248, 0, 64 },
13476 { 255, 255, 241, 0, 64 }, { 255, 255, 234, 0, 64 },
13477 { 255, 255, 227, 0, 64 }, { 255, 255, 221, 0, 64 },
13478 { 255, 255, 215, 0, 64 }, { 255, 255, 208, 0, 64 },
13479 { 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13480 { 255, 255, 191, 0, 64 }, { 255, 255, 186, 0, 64 },
13481 { 255, 255, 181, 0, 64 }, { 255, 255, 175, 0, 64 },
13482 { 255, 255, 170, 0, 64 }, { 255, 255, 166, 0, 64 },
13483 { 255, 255, 161, 0, 64 }, { 255, 255, 156, 0, 64 },
13484 { 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13485 { 255, 255, 143, 0, 64 }, { 255, 255, 139, 0, 64 },
13486 { 255, 255, 135, 0, 64 }, { 255, 255, 132, 0, 64 },
13487 { 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13488 { 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13489 { 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13490 { 255, 255, 108, 0, 64 }, { 255, 255, 104, 0, 64 },
13491 { 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13492 { 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13493 { 255, 255, 90, 0, 64 }, { 255, 255, 88, 0, 64 },
13494 { 255, 255, 85, 0, 64 }, { 255, 255, 83, 0, 64 },
13495 { 255, 255, 81, 0, 64 }, { 255, 255, 78, 0, 64 },
13496 { 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13497 { 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13498 { 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13499 { 255, 255, 64, 0, 64 }, { 255, 255, 64, 0, 64 },
13500 { 255, 255, 62, 0, 64 }, { 255, 248, 62, 0, 64 },
13501 { 255, 248, 60, 0, 64 }, { 255, 241, 60, 0, 64 },
13502 { 255, 241, 59, 0, 64 }, { 255, 234, 59, 0, 64 },
13503 { 255, 234, 57, 0, 64 }, { 255, 227, 57, 0, 64 },
13504 { 255, 227, 55, 0, 64 }, { 255, 221, 55, 0, 64 },
13505 { 255, 221, 54, 0, 64 }, { 255, 215, 54, 0, 64 },
13506 { 255, 215, 52, 0, 64 }, { 255, 208, 52, 0, 64 },
13507 { 255, 208, 51, 0, 64 }, { 255, 203, 51, 0, 64 },
13508 { 255, 203, 49, 0, 64 }, { 255, 197, 49, 0, 64 },
13509 { 255, 197, 48, 0, 64 }, { 255, 191, 48, 0, 64 },
13510 { 255, 191, 47, 0, 64 }, { 255, 186, 47, 0, 64 },
13511 { 255, 186, 45, 0, 64 }, { 255, 181, 45, 0, 64 },
13512 { 255, 181, 44, 0, 64 }, { 255, 175, 44, 0, 64 },
13513 { 255, 175, 43, 0, 64 }, { 255, 170, 43, 0, 64 },
13514 { 255, 170, 42, 0, 64 }, { 255, 166, 42, 0, 64 },
13515 { 255, 166, 40, 0, 64 }, { 255, 161, 40, 0, 64 },
13516 { 255, 161, 39, 0, 64 }, { 255, 156, 39, 0, 64 },
13517 { 255, 156, 38, 0, 64 }, { 255, 152, 38, 0, 64 },
13518 { 255, 152, 37, 0, 64 }, { 255, 148, 37, 0, 64 },
13519 { 255, 148, 36, 0, 64 }, { 255, 143, 36, 0, 64 },
13520 { 255, 143, 35, 0, 64 }, { 255, 139, 35, 0, 64 },
13521 { 255, 139, 34, 0, 64 }, { 255, 135, 34, 0, 64 },
13522 { 255, 135, 33, 0, 64 }, { 255, 132, 33, 0, 64 },
13523 { 255, 132, 32, 0, 64 }, { 255, 128, 32, 0, 64 }
13524 };
13525 static struct bwn_txgain_entry txgain_r0[] = {
13526 { 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13527 { 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13528 { 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13529 { 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13530 { 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13531 { 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13532 { 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13533 { 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13534 { 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13535 { 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13536 { 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13537 { 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13538 { 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13539 { 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13540 { 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13541 { 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13542 { 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13543 { 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13544 { 7, 15, 13, 0, 70 }, { 7, 15, 13, 0, 68 },
13545 { 7, 15, 13, 0, 66 }, { 7, 15, 13, 0, 64 },
13546 { 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13547 { 7, 15, 13, 0, 59 }, { 7, 15, 13, 0, 57 },
13548 { 7, 15, 12, 0, 71 }, { 7, 15, 12, 0, 69 },
13549 { 7, 15, 12, 0, 67 }, { 7, 15, 12, 0, 65 },
13550 { 7, 15, 12, 0, 63 }, { 7, 15, 12, 0, 62 },
13551 { 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 58 },
13552 { 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 70 },
13553 { 7, 15, 11, 0, 68 }, { 7, 15, 11, 0, 66 },
13554 { 7, 15, 11, 0, 65 }, { 7, 15, 11, 0, 63 },
13555 { 7, 15, 11, 0, 61 }, { 7, 15, 11, 0, 59 },
13556 { 7, 15, 11, 0, 58 }, { 7, 15, 10, 0, 71 },
13557 { 7, 15, 10, 0, 69 }, { 7, 15, 10, 0, 67 },
13558 { 7, 15, 10, 0, 65 }, { 7, 15, 10, 0, 63 },
13559 { 7, 15, 10, 0, 61 }, { 7, 15, 10, 0, 60 },
13560 { 7, 15, 10, 0, 58 }, { 7, 15, 10, 0, 56 },
13561 { 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13562 { 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13563 { 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 60 },
13564 { 7, 15, 9, 0, 59 }, { 7, 14, 9, 0, 72 },
13565 { 7, 14, 9, 0, 70 }, { 7, 14, 9, 0, 68 },
13566 { 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 64 },
13567 { 7, 14, 9, 0, 62 }, { 7, 14, 9, 0, 60 },
13568 { 7, 14, 9, 0, 59 }, { 7, 13, 9, 0, 72 },
13569 { 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13570 { 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13571 { 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13572 { 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13573 { 7, 13, 8, 0, 72 }, { 7, 13, 8, 0, 70 },
13574 { 7, 13, 8, 0, 68 }, { 7, 13, 8, 0, 66 },
13575 { 7, 13, 8, 0, 64 }, { 7, 13, 8, 0, 62 },
13576 { 7, 13, 8, 0, 60 }, { 7, 13, 8, 0, 59 },
13577 { 7, 12, 8, 0, 72 }, { 7, 12, 8, 0, 70 },
13578 { 7, 12, 8, 0, 68 }, { 7, 12, 8, 0, 66 },
13579 { 7, 12, 8, 0, 64 }, { 7, 12, 8, 0, 62 },
13580 { 7, 12, 8, 0, 61 }, { 7, 12, 8, 0, 59 },
13581 { 7, 12, 7, 0, 73 }, { 7, 12, 7, 0, 71 },
13582 { 7, 12, 7, 0, 69 }, { 7, 12, 7, 0, 67 },
13583 { 7, 12, 7, 0, 65 }, { 7, 12, 7, 0, 63 },
13584 { 7, 12, 7, 0, 61 }, { 7, 12, 7, 0, 59 },
13585 { 7, 11, 7, 0, 72 }, { 7, 11, 7, 0, 70 },
13586 { 7, 11, 7, 0, 68 }, { 7, 11, 7, 0, 66 },
13587 { 7, 11, 7, 0, 65 }, { 7, 11, 7, 0, 63 },
13588 { 7, 11, 7, 0, 61 }, { 7, 11, 7, 0, 59 },
13589 { 7, 11, 6, 0, 73 }, { 7, 11, 6, 0, 71 }
13590 };
13591 static struct bwn_txgain_entry txgain_2ghz_r0[] = {
13592 { 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13593 { 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13594 { 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13595 { 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13596 { 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13597 { 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13598 { 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13599 { 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13600 { 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13601 { 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13602 { 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13603 { 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13604 { 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13605 { 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13606 { 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13607 { 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13608 { 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13609 { 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13610 { 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13611 { 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13612 { 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13613 { 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13614 { 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13615 { 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13616 { 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13617 { 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13618 { 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13619 { 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13620 { 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13621 { 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13622 { 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13623 { 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13624 { 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13625 { 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 },
13626 { 4, 10, 6, 0, 59 }, { 4, 10, 5, 0, 72 },
13627 { 4, 10, 5, 0, 70 }, { 4, 10, 5, 0, 68 },
13628 { 4, 10, 5, 0, 66 }, { 4, 10, 5, 0, 64 },
13629 { 4, 10, 5, 0, 62 }, { 4, 10, 5, 0, 60 },
13630 { 4, 10, 5, 0, 59 }, { 4, 9, 5, 0, 70 },
13631 { 4, 9, 5, 0, 68 }, { 4, 9, 5, 0, 66 },
13632 { 4, 9, 5, 0, 64 }, { 4, 9, 5, 0, 63 },
13633 { 4, 9, 5, 0, 61 }, { 4, 9, 5, 0, 59 },
13634 { 4, 9, 4, 0, 71 }, { 4, 9, 4, 0, 69 },
13635 { 4, 9, 4, 0, 67 }, { 4, 9, 4, 0, 65 },
13636 { 4, 9, 4, 0, 63 }, { 4, 9, 4, 0, 62 },
13637 { 4, 9, 4, 0, 60 }, { 4, 9, 4, 0, 58 },
13638 { 4, 8, 4, 0, 70 }, { 4, 8, 4, 0, 68 },
13639 { 4, 8, 4, 0, 66 }, { 4, 8, 4, 0, 65 },
13640 { 4, 8, 4, 0, 63 }, { 4, 8, 4, 0, 61 },
13641 { 4, 8, 4, 0, 59 }, { 4, 7, 4, 0, 68 },
13642 { 4, 7, 4, 0, 66 }, { 4, 7, 4, 0, 64 },
13643 { 4, 7, 4, 0, 62 }, { 4, 7, 4, 0, 61 },
13644 { 4, 7, 4, 0, 59 }, { 4, 7, 3, 0, 67 },
13645 { 4, 7, 3, 0, 65 }, { 4, 7, 3, 0, 63 },
13646 { 4, 7, 3, 0, 62 }, { 4, 7, 3, 0, 60 },
13647 { 4, 6, 3, 0, 65 }, { 4, 6, 3, 0, 63 },
13648 { 4, 6, 3, 0, 61 }, { 4, 6, 3, 0, 60 },
13649 { 4, 6, 3, 0, 58 }, { 4, 5, 3, 0, 68 },
13650 { 4, 5, 3, 0, 66 }, { 4, 5, 3, 0, 64 },
13651 { 4, 5, 3, 0, 62 }, { 4, 5, 3, 0, 60 },
13652 { 4, 5, 3, 0, 59 }, { 4, 5, 3, 0, 57 },
13653 { 4, 4, 2, 0, 83 }, { 4, 4, 2, 0, 81 },
13654 { 4, 4, 2, 0, 78 }, { 4, 4, 2, 0, 76 },
13655 { 4, 4, 2, 0, 74 }, { 4, 4, 2, 0, 72 }
13656 };
13657 static struct bwn_txgain_entry txgain_5ghz_r0[] = {
13658 { 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13659 { 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13660 { 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13661 { 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13662 { 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13663 { 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13664 { 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13665 { 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13666 { 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13667 { 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13668 { 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13669 { 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13670 { 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13671 { 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13672 { 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13673 { 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13674 { 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13675 { 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13676 { 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13677 { 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13678 { 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13679 { 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13680 { 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13681 { 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13682 { 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13683 { 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13684 { 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13685 { 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13686 { 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13687 { 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13688 { 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13689 { 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13690 { 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13691 { 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13692 { 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13693 { 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13694 { 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13695 { 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13696 { 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13697 { 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13698 { 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13699 { 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13700 { 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13701 { 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13702 { 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13703 { 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13704 { 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13705 { 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13706 { 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13707 { 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13708 { 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13709 { 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13710 { 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13711 { 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13712 { 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13713 { 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13714 { 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13715 { 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13716 { 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13717 { 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13718 { 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13719 { 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13720 { 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13721 { 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13722 };
13723 static struct bwn_txgain_entry txgain_r1[] = {
13724 { 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13725 { 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13726 { 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13727 { 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13728 { 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13729 { 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13730 { 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13731 { 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13732 { 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13733 { 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13734 { 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13735 { 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13736 { 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13737 { 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13738 { 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13739 { 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13740 { 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13741 { 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13742 { 7, 15, 13, 0, 70 }, { 7, 15, 14, 0, 68 },
13743 { 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13744 { 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13745 { 7, 15, 14, 0, 59 }, { 7, 15, 14, 0, 57 },
13746 { 7, 15, 13, 0, 72 }, { 7, 15, 13, 0, 70 },
13747 { 7, 15, 13, 0, 68 }, { 7, 15, 13, 0, 66 },
13748 { 7, 15, 13, 0, 64 }, { 7, 15, 13, 0, 62 },
13749 { 7, 15, 13, 0, 60 }, { 7, 15, 13, 0, 59 },
13750 { 7, 15, 13, 0, 57 }, { 7, 15, 12, 0, 71 },
13751 { 7, 15, 12, 0, 69 }, { 7, 15, 12, 0, 67 },
13752 { 7, 15, 12, 0, 65 }, { 7, 15, 12, 0, 63 },
13753 { 7, 15, 12, 0, 62 }, { 7, 15, 12, 0, 60 },
13754 { 7, 15, 12, 0, 58 }, { 7, 15, 12, 0, 57 },
13755 { 7, 15, 11, 0, 70 }, { 7, 15, 11, 0, 68 },
13756 { 7, 15, 11, 0, 66 }, { 7, 15, 11, 0, 65 },
13757 { 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13758 { 7, 15, 11, 0, 59 }, { 7, 15, 11, 0, 58 },
13759 { 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13760 { 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13761 { 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13762 { 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13763 { 7, 15, 10, 0, 56 }, { 7, 15, 9, 0, 70 },
13764 { 7, 15, 9, 0, 68 }, { 7, 15, 9, 0, 66 },
13765 { 7, 15, 9, 0, 64 }, { 7, 15, 9, 0, 62 },
13766 { 7, 15, 9, 0, 60 }, { 7, 15, 9, 0, 59 },
13767 { 7, 14, 9, 0, 72 }, { 7, 14, 9, 0, 70 },
13768 { 7, 14, 9, 0, 68 }, { 7, 14, 9, 0, 66 },
13769 { 7, 14, 9, 0, 64 }, { 7, 14, 9, 0, 62 },
13770 { 7, 14, 9, 0, 60 }, { 7, 14, 9, 0, 59 },
13771 { 7, 13, 9, 0, 72 }, { 7, 13, 9, 0, 70 },
13772 { 7, 13, 9, 0, 68 }, { 7, 13, 9, 0, 66 },
13773 { 7, 13, 9, 0, 64 }, { 7, 13, 9, 0, 63 },
13774 { 7, 13, 9, 0, 61 }, { 7, 13, 9, 0, 59 },
13775 { 7, 13, 9, 0, 57 }, { 7, 13, 8, 0, 72 },
13776 { 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13777 { 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13778 { 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13779 { 7, 13, 8, 0, 59 }, { 7, 12, 8, 0, 72 },
13780 { 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13781 { 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13782 { 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13783 { 7, 12, 8, 0, 59 }, { 7, 12, 7, 0, 73 },
13784 { 7, 12, 7, 0, 71 }, { 7, 12, 7, 0, 69 },
13785 { 7, 12, 7, 0, 67 }, { 7, 12, 7, 0, 65 },
13786 { 7, 12, 7, 0, 63 }, { 7, 12, 7, 0, 61 },
13787 { 7, 12, 7, 0, 59 }, { 7, 11, 7, 0, 72 },
13788 { 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13789 { 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 65 },
13790 { 7, 11, 7, 0, 63 }, { 7, 11, 7, 0, 61 },
13791 { 7, 11, 7, 0, 59 }, { 7, 11, 6, 0, 73 },
13792 { 7, 11, 6, 0, 71 }
13793 };
13794 static struct bwn_txgain_entry txgain_2ghz_r1[] = {
13795 { 4, 15, 15, 0, 90 }, { 4, 15, 15, 0, 88 },
13796 { 4, 15, 15, 0, 85 }, { 4, 15, 15, 0, 83 },
13797 { 4, 15, 15, 0, 81 }, { 4, 15, 15, 0, 78 },
13798 { 4, 15, 15, 0, 76 }, { 4, 15, 15, 0, 74 },
13799 { 4, 15, 15, 0, 72 }, { 4, 15, 15, 0, 70 },
13800 { 4, 15, 15, 0, 68 }, { 4, 15, 15, 0, 66 },
13801 { 4, 15, 15, 0, 64 }, { 4, 15, 15, 0, 62 },
13802 { 4, 15, 15, 0, 60 }, { 4, 15, 15, 0, 59 },
13803 { 4, 15, 14, 0, 72 }, { 4, 15, 14, 0, 70 },
13804 { 4, 15, 14, 0, 68 }, { 4, 15, 14, 0, 66 },
13805 { 4, 15, 14, 0, 64 }, { 4, 15, 14, 0, 62 },
13806 { 4, 15, 14, 0, 60 }, { 4, 15, 14, 0, 59 },
13807 { 4, 15, 13, 0, 72 }, { 4, 15, 13, 0, 70 },
13808 { 4, 15, 13, 0, 68 }, { 4, 15, 13, 0, 66 },
13809 { 4, 15, 13, 0, 64 }, { 4, 15, 13, 0, 62 },
13810 { 4, 15, 13, 0, 60 }, { 4, 15, 13, 0, 59 },
13811 { 4, 15, 12, 0, 72 }, { 4, 15, 12, 0, 70 },
13812 { 4, 15, 12, 0, 68 }, { 4, 15, 12, 0, 66 },
13813 { 4, 15, 12, 0, 64 }, { 4, 15, 12, 0, 62 },
13814 { 4, 15, 12, 0, 60 }, { 4, 15, 12, 0, 59 },
13815 { 4, 15, 11, 0, 72 }, { 4, 15, 11, 0, 70 },
13816 { 4, 15, 11, 0, 68 }, { 4, 15, 11, 0, 66 },
13817 { 4, 15, 11, 0, 64 }, { 4, 15, 11, 0, 62 },
13818 { 4, 15, 11, 0, 60 }, { 4, 15, 11, 0, 59 },
13819 { 4, 15, 10, 0, 72 }, { 4, 15, 10, 0, 70 },
13820 { 4, 15, 10, 0, 68 }, { 4, 15, 10, 0, 66 },
13821 { 4, 15, 10, 0, 64 }, { 4, 15, 10, 0, 62 },
13822 { 4, 15, 10, 0, 60 }, { 4, 15, 10, 0, 59 },
13823 { 4, 15, 9, 0, 72 }, { 4, 15, 9, 0, 70 },
13824 { 4, 15, 9, 0, 68 }, { 4, 15, 9, 0, 66 },
13825 { 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13826 { 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13827 { 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13828 { 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13829 { 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13830 { 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13831 { 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13832 { 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13833 { 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13834 { 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13835 { 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13836 { 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13837 { 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13838 { 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13839 { 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13840 { 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13841 { 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13842 { 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13843 { 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13844 { 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13845 { 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13846 { 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13847 { 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13848 { 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13849 { 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13850 { 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13851 { 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13852 { 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13853 { 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13854 { 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13855 { 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13856 { 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13857 { 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13858 { 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 }
13859 };
13860 static struct bwn_txgain_entry txgain_5ghz_r1[] = {
13861 { 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13862 { 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13863 { 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13864 { 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13865 { 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13866 { 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13867 { 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13868 { 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13869 { 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13870 { 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13871 { 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13872 { 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13873 { 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13874 { 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13875 { 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13876 { 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13877 { 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13878 { 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13879 { 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13880 { 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13881 { 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13882 { 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13883 { 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13884 { 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13885 { 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13886 { 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13887 { 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13888 { 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13889 { 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13890 { 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13891 { 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13892 { 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13893 { 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13894 { 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13895 { 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13896 { 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13897 { 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13898 { 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13899 { 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13900 { 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13901 { 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13902 { 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13903 { 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13904 { 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13905 { 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13906 { 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13907 { 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13908 { 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13909 { 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13910 { 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13911 { 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13912 { 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13913 { 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13914 { 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13915 { 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13916 { 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13917 { 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13918 { 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13919 { 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13920 { 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13921 { 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13922 { 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13923 { 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13924 { 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13925 };
13926
13927 if (mac->mac_phy.rev != 0 && mac->mac_phy.rev != 1) {
13928 if (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA)
13929 bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r2);
13930 else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13931 bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13932 txgain_2ghz_r2);
13933 else
13934 bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13935 txgain_5ghz_r2);
13936 return;
13937 }
13938
13939 if (mac->mac_phy.rev == 0) {
13940 if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA) ||
13941 (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_HGPA))
13942 bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r0);
13943 else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13944 bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13945 txgain_2ghz_r0);
13946 else
13947 bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13948 txgain_5ghz_r0);
13949 return;
13950 }
13951
13952 if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA) ||
13953 (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_HGPA))
13954 bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r1);
13955 else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13956 bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_2ghz_r1);
13957 else
13958 bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_5ghz_r1);
13959}
13960
13961static void
13962bwn_tab_write(struct bwn_mac *mac, uint32_t typeoffset, uint32_t value)
13963{
13964 uint32_t offset, type;
13965
13966 type = BWN_TAB_GETTYPE(typeoffset);
13967 offset = BWN_TAB_GETOFFSET(typeoffset);
13968 KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
13969
13970 switch (type) {
13971 case BWN_TAB_8BIT:
13972 KASSERT(!(value & ~0xff), ("%s:%d: fail", __func__, __LINE__));
13973 BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13974 BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13975 break;
13976 case BWN_TAB_16BIT:
13977 KASSERT(!(value & ~0xffff),
13978 ("%s:%d: fail", __func__, __LINE__));
13979 BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13980 BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13981 break;
13982 case BWN_TAB_32BIT:
13983 BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13984 BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
13985 BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13986 break;
13987 default:
13988 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
13989 }
13990}
13991
13992static int
13993bwn_phy_lp_loopback(struct bwn_mac *mac)
13994{
13995 struct bwn_phy_lp_iq_est ie;
13996 int i, index = -1;
13997 uint32_t tmp;
13998
13999 memset(&ie, 0, sizeof(ie));
14000
14001 bwn_phy_lp_set_trsw_over(mac, 1, 1);
14002 BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 1);
14003 BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
14004 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
14005 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
14006 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
14007 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x8);
14008 BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, 0x80);
14009 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x80);
14010 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x80);
14011 for (i = 0; i < 32; i++) {
14012 bwn_phy_lp_set_rxgain_idx(mac, i);
14013 bwn_phy_lp_ddfs_turnon(mac, 1, 1, 5, 5, 0);
14014 if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
14015 continue;
14016 tmp = (ie.ie_ipwr + ie.ie_qpwr) / 1000;
14017 if ((tmp > 4000) && (tmp < 10000)) {
14018 index = i;
14019 break;
14020 }
14021 }
14022 bwn_phy_lp_ddfs_turnoff(mac);
14023 return (index);
14024}
14025
14026static void
14027bwn_phy_lp_set_rxgain_idx(struct bwn_mac *mac, uint16_t idx)
14028{
14029
14030 bwn_phy_lp_set_rxgain(mac, bwn_tab_read(mac, BWN_TAB_2(12, idx)));
14031}
14032
14033static void
14034bwn_phy_lp_ddfs_turnon(struct bwn_mac *mac, int i_on, int q_on,
14035 int incr1, int incr2, int scale_idx)
14036{
14037
14038 bwn_phy_lp_ddfs_turnoff(mac);
14039 BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0xff80);
14040 BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0x80ff);
14041 BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0xff80, incr1);
14042 BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0x80ff, incr2 << 8);
14043 BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff7, i_on << 3);
14044 BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xffef, q_on << 4);
14045 BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xff9f, scale_idx << 5);
14046 BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffb);
14047 BWN_PHY_SET(mac, BWN_PHY_AFE_DDFS, 0x2);
14048 BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x20);
14049}
14050
14051static uint8_t
14052bwn_phy_lp_rx_iq_est(struct bwn_mac *mac, uint16_t sample, uint8_t time,
14053 struct bwn_phy_lp_iq_est *ie)
14054{
14055 int i;
14056
14057 BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfff7);
14058 BWN_PHY_WRITE(mac, BWN_PHY_IQ_NUM_SMPLS_ADDR, sample);
14059 BWN_PHY_SETMASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xff00, time);
14060 BWN_PHY_MASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xfeff);
14061 BWN_PHY_SET(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0x200);
14062
14063 for (i = 0; i < 500; i++) {
14064 if (!(BWN_PHY_READ(mac,
14065 BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200))
14066 break;
14067 DELAY(1000);
14068 }
14069 if ((BWN_PHY_READ(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200)) {
14070 BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
14071 return 0;
14072 }
14073
14074 ie->ie_iqprod = BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_HI_ADDR);
14075 ie->ie_iqprod <<= 16;
14076 ie->ie_iqprod |= BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_LO_ADDR);
14077 ie->ie_ipwr = BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_HI_ADDR);
14078 ie->ie_ipwr <<= 16;
14079 ie->ie_ipwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_LO_ADDR);
14080 ie->ie_qpwr = BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_HI_ADDR);
14081 ie->ie_qpwr <<= 16;
14082 ie->ie_qpwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_LO_ADDR);
14083
14084 BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
14085 return 1;
14086}
14087
14088static uint32_t
14089bwn_tab_read(struct bwn_mac *mac, uint32_t typeoffset)
14090{
14091 uint32_t offset, type, value;
14092
14093 type = BWN_TAB_GETTYPE(typeoffset);
14094 offset = BWN_TAB_GETOFFSET(typeoffset);
14095 KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
14096
14097 switch (type) {
14098 case BWN_TAB_8BIT:
14099 BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14100 value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
14101 break;
14102 case BWN_TAB_16BIT:
14103 BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14104 value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
14105 break;
14106 case BWN_TAB_32BIT:
14107 BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14108 value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATAHI);
14109 value <<= 16;
14110 value |= BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
14111 break;
14112 default:
14113 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
14114 value = 0;
14115 }
14116
14117 return (value);
14118}
14119
14120static void
14121bwn_phy_lp_ddfs_turnoff(struct bwn_mac *mac)
14122{
14123
14124 BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffd);
14125 BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0xffdf);
14126}
14127
14128static void
14129bwn_phy_lp_set_txgain_dac(struct bwn_mac *mac, uint16_t dac)
14130{
14131 uint16_t ctl;
14132
14133 ctl = BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0xc7f;
14134 ctl |= dac << 7;
14135 BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf000, ctl);
14136}
14137
14138static void
14139bwn_phy_lp_set_txgain_pa(struct bwn_mac *mac, uint16_t gain)
14140{
14141
14142 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0xe03f, gain << 6);
14143 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x80ff, gain << 8);
14144}
14145
14146static void
14147bwn_phy_lp_set_txgain_override(struct bwn_mac *mac)
14148{
14149
14150 if (mac->mac_phy.rev < 2)
14151 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
14152 else {
14153 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x80);
14154 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x4000);
14155 }
14156 BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x40);
14157}
14158
14159static uint16_t
14160bwn_phy_lp_get_pa_gain(struct bwn_mac *mac)
14161{
14162
14163 return BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0x7f;
14164}
14165
14166static uint8_t
14167bwn_nbits(int32_t val)
14168{
14169 uint32_t tmp;
14170 uint8_t nbits = 0;
14171
14172 for (tmp = abs(val); tmp != 0; tmp >>= 1)
14173 nbits++;
14174 return (nbits);
14175}
14176
14177static void
14178bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *mac, int offset, int count,
14179 struct bwn_txgain_entry *table)
14180{
14181 int i;
14182
14183 for (i = offset; i < count; i++)
14184 bwn_phy_lp_gaintbl_write(mac, i, table[i]);
14185}
14186
14187static void
14188bwn_phy_lp_gaintbl_write(struct bwn_mac *mac, int offset,
14189 struct bwn_txgain_entry data)
14190{
14191
14192 if (mac->mac_phy.rev >= 2)
14193 bwn_phy_lp_gaintbl_write_r2(mac, offset, data);
14194 else
14195 bwn_phy_lp_gaintbl_write_r01(mac, offset, data);
14196}
14197
14198static void
14199bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *mac, int offset,
14200 struct bwn_txgain_entry te)
14201{
14202 struct bwn_softc *sc = mac->mac_sc;
14203 struct ifnet *ifp = sc->sc_ifp;
14204 struct ieee80211com *ic = ifp->if_l2com;
14205 uint32_t tmp;
14206
14207 KASSERT(mac->mac_phy.rev >= 2, ("%s:%d: fail", __func__, __LINE__));
14208
14209 tmp = (te.te_pad << 16) | (te.te_pga << 8) | te.te_gm;
14210 if (mac->mac_phy.rev >= 3) {
14211 tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14212 (0x10 << 24) : (0x70 << 24));
14213 } else {
14214 tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14215 (0x14 << 24) : (0x7f << 24));
14216 }
14217 bwn_tab_write(mac, BWN_TAB_4(7, 0xc0 + offset), tmp);
14218 bwn_tab_write(mac, BWN_TAB_4(7, 0x140 + offset),
14219 te.te_bbmult << 20 | te.te_dac << 28);
14220}
14221
14222static void
14223bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *mac, int offset,
14224 struct bwn_txgain_entry te)
14225{
14226
14227 KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
14228
14229 bwn_tab_write(mac, BWN_TAB_4(10, 0xc0 + offset),
14230 (te.te_pad << 11) | (te.te_pga << 7) | (te.te_gm << 4) |
14231 te.te_dac);
14232 bwn_tab_write(mac, BWN_TAB_4(10, 0x140 + offset), te.te_bbmult << 20);
14233}
14234
14235static void
14236bwn_sysctl_node(struct bwn_softc *sc)
14237{
14238 device_t dev = sc->sc_dev;
14239 struct bwn_mac *mac;
14240 struct bwn_stats *stats;
14241
14242 /* XXX assume that count of MAC is only 1. */
14243
14244 if ((mac = sc->sc_curmac) == NULL)
14245 return;
14246 stats = &mac->mac_stats;
14247
14248 SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14249 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14250 "linknoise", CTLFLAG_RW, &stats->rts, 0, "Noise level");
14251 SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14252 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14253 "rts", CTLFLAG_RW, &stats->rts, 0, "RTS");
14254 SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14255 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14256 "rtsfail", CTLFLAG_RW, &stats->rtsfail, 0, "RTS failed to send");
14257
14258#ifdef BWN_DEBUG
14259 SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14260 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14261 "debug", CTLFLAG_RW, &sc->sc_debug, 0, "Debug flags");
14262#endif
14263}
14264
14265static device_method_t bwn_methods[] = {
14266 /* Device interface */
14267 DEVMETHOD(device_probe, bwn_probe),
14268 DEVMETHOD(device_attach, bwn_attach),
14269 DEVMETHOD(device_detach, bwn_detach),
14270 DEVMETHOD(device_suspend, bwn_suspend),
14271 DEVMETHOD(device_resume, bwn_resume),
14272 KOBJMETHOD_END
14273};
14274static driver_t bwn_driver = {
14275 "bwn",
14276 bwn_methods,
14277 sizeof(struct bwn_softc)
14278};
14279static devclass_t bwn_devclass;
14280DRIVER_MODULE(bwn, siba_bwn, bwn_driver, bwn_devclass, 0, 0);
14281MODULE_DEPEND(bwn, siba_bwn, 1, 1, 1);
14282MODULE_DEPEND(bwn, wlan, 1, 1, 1); /* 802.11 media layer */
14283MODULE_DEPEND(bwn, firmware, 1, 1, 1); /* firmware support */
14284MODULE_DEPEND(bwn, wlan_amrr, 1, 1, 1);
1081 /* call MI attach routine. */
1082 ieee80211_ifattach(ic,
1083 bwn_is_valid_ether_addr(siba_sprom_get_mac_80211a(sc->sc_dev)) ?
1084 siba_sprom_get_mac_80211a(sc->sc_dev) :
1085 siba_sprom_get_mac_80211bg(sc->sc_dev));
1086
1087 ic->ic_headroom = sizeof(struct bwn_txhdr);
1088
1089 /* override default methods */
1090 ic->ic_raw_xmit = bwn_raw_xmit;
1091 ic->ic_newassoc = bwn_newassoc;
1092 ic->ic_updateslot = bwn_updateslot;
1093 ic->ic_update_promisc = bwn_update_promisc;
1094 ic->ic_wme.wme_update = bwn_wme_update;
1095
1096 ic->ic_node_alloc = bwn_node_alloc;
1097 sc->sc_node_cleanup = ic->ic_node_cleanup;
1098 ic->ic_node_cleanup = bwn_node_cleanup;
1099
1100 ic->ic_scan_start = bwn_scan_start;
1101 ic->ic_scan_end = bwn_scan_end;
1102 ic->ic_set_channel = bwn_set_channel;
1103
1104 ic->ic_vap_create = bwn_vap_create;
1105 ic->ic_vap_delete = bwn_vap_delete;
1106
1107 ieee80211_radiotap_attach(ic,
1108 &sc->sc_tx_th.wt_ihdr, sizeof(sc->sc_tx_th),
1109 BWN_TX_RADIOTAP_PRESENT,
1110 &sc->sc_rx_th.wr_ihdr, sizeof(sc->sc_rx_th),
1111 BWN_RX_RADIOTAP_PRESENT);
1112
1113 bwn_sysctl_node(sc);
1114
1115 if (bootverbose)
1116 ieee80211_announce(ic);
1117 return (0);
1118}
1119
1120static void
1121bwn_phy_detach(struct bwn_mac *mac)
1122{
1123
1124 if (mac->mac_phy.detach != NULL)
1125 mac->mac_phy.detach(mac);
1126}
1127
1128static int
1129bwn_detach(device_t dev)
1130{
1131 struct bwn_softc *sc = device_get_softc(dev);
1132 struct bwn_mac *mac = sc->sc_curmac;
1133 struct ifnet *ifp = sc->sc_ifp;
1134 struct ieee80211com *ic = ifp->if_l2com;
1135 int i;
1136
1137 sc->sc_flags |= BWN_FLAG_INVALID;
1138
1139 if (device_is_attached(sc->sc_dev)) {
1140 bwn_stop(sc, 1);
1141 bwn_dma_free(mac);
1142 callout_drain(&sc->sc_led_blink_ch);
1143 callout_drain(&sc->sc_rfswitch_ch);
1144 callout_drain(&sc->sc_task_ch);
1145 callout_drain(&sc->sc_watchdog_ch);
1146 bwn_phy_detach(mac);
1147 if (ifp != NULL) {
1148 ieee80211_draintask(ic, &mac->mac_hwreset);
1149 ieee80211_draintask(ic, &mac->mac_txpower);
1150 ieee80211_ifdetach(ic);
1151 if_free(ifp);
1152 }
1153 }
1154 taskqueue_drain(sc->sc_tq, &mac->mac_intrtask);
1155 taskqueue_free(sc->sc_tq);
1156
1157 for (i = 0; i < BWN_MSI_MESSAGES; i++) {
1158 if (mac->mac_intrhand[i] != NULL) {
1159 bus_teardown_intr(dev, mac->mac_res_irq[i],
1160 mac->mac_intrhand[i]);
1161 mac->mac_intrhand[i] = NULL;
1162 }
1163 }
1164 bus_release_resources(dev, mac->mac_intr_spec, mac->mac_res_irq);
1165 if (mac->mac_msi != 0)
1166 pci_release_msi(dev);
1167
1168 BWN_LOCK_DESTROY(sc);
1169 return (0);
1170}
1171
1172static int
1173bwn_attach_pre(struct bwn_softc *sc)
1174{
1175 struct ifnet *ifp;
1176 int error = 0;
1177
1178 BWN_LOCK_INIT(sc);
1179 TAILQ_INIT(&sc->sc_maclist);
1180 callout_init_mtx(&sc->sc_rfswitch_ch, &sc->sc_mtx, 0);
1181 callout_init_mtx(&sc->sc_task_ch, &sc->sc_mtx, 0);
1182 callout_init_mtx(&sc->sc_watchdog_ch, &sc->sc_mtx, 0);
1183
1184 sc->sc_tq = taskqueue_create_fast("bwn_taskq", M_NOWAIT,
1185 taskqueue_thread_enqueue, &sc->sc_tq);
1186 taskqueue_start_threads(&sc->sc_tq, 1, PI_NET,
1187 "%s taskq", device_get_nameunit(sc->sc_dev));
1188
1189 ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
1190 if (ifp == NULL) {
1191 device_printf(sc->sc_dev, "can not if_alloc()\n");
1192 error = ENOSPC;
1193 goto fail;
1194 }
1195
1196 /* set these up early for if_printf use */
1197 if_initname(ifp, device_get_name(sc->sc_dev),
1198 device_get_unit(sc->sc_dev));
1199
1200 ifp->if_softc = sc;
1201 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
1202 ifp->if_init = bwn_init;
1203 ifp->if_ioctl = bwn_ioctl;
1204 ifp->if_start = bwn_start;
1205 IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
1206 ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
1207 IFQ_SET_READY(&ifp->if_snd);
1208
1209 return (0);
1210
1211fail: BWN_LOCK_DESTROY(sc);
1212 return (error);
1213}
1214
1215static void
1216bwn_sprom_bugfixes(device_t dev)
1217{
1218#define BWN_ISDEV(_vendor, _device, _subvendor, _subdevice) \
1219 ((siba_get_pci_vendor(dev) == PCI_VENDOR_##_vendor) && \
1220 (siba_get_pci_device(dev) == _device) && \
1221 (siba_get_pci_subvendor(dev) == PCI_VENDOR_##_subvendor) && \
1222 (siba_get_pci_subdevice(dev) == _subdevice))
1223
1224 if (siba_get_pci_subvendor(dev) == PCI_VENDOR_APPLE &&
1225 siba_get_pci_subdevice(dev) == 0x4e &&
1226 siba_get_pci_revid(dev) > 0x40)
1227 siba_sprom_set_bf_lo(dev,
1228 siba_sprom_get_bf_lo(dev) | BWN_BFL_PACTRL);
1229 if (siba_get_pci_subvendor(dev) == SIBA_BOARDVENDOR_DELL &&
1230 siba_get_chipid(dev) == 0x4301 && siba_get_pci_revid(dev) == 0x74)
1231 siba_sprom_set_bf_lo(dev,
1232 siba_sprom_get_bf_lo(dev) | BWN_BFL_BTCOEXIST);
1233 if (siba_get_type(dev) == SIBA_TYPE_PCI) {
1234 if (BWN_ISDEV(BROADCOM, 0x4318, ASUSTEK, 0x100f) ||
1235 BWN_ISDEV(BROADCOM, 0x4320, DELL, 0x0003) ||
1236 BWN_ISDEV(BROADCOM, 0x4320, HP, 0x12f8) ||
1237 BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0013) ||
1238 BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0014) ||
1239 BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0015) ||
1240 BWN_ISDEV(BROADCOM, 0x4320, MOTOROLA, 0x7010))
1241 siba_sprom_set_bf_lo(dev,
1242 siba_sprom_get_bf_lo(dev) & ~BWN_BFL_BTCOEXIST);
1243 }
1244#undef BWN_ISDEV
1245}
1246
1247static int
1248bwn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1249{
1250#define IS_RUNNING(ifp) \
1251 ((ifp->if_flags & IFF_UP) && (ifp->if_drv_flags & IFF_DRV_RUNNING))
1252 struct bwn_softc *sc = ifp->if_softc;
1253 struct ieee80211com *ic = ifp->if_l2com;
1254 struct ifreq *ifr = (struct ifreq *)data;
1255 int error = 0, startall;
1256
1257 switch (cmd) {
1258 case SIOCSIFFLAGS:
1259 startall = 0;
1260 if (IS_RUNNING(ifp)) {
1261 bwn_update_promisc(ifp);
1262 } else if (ifp->if_flags & IFF_UP) {
1263 if ((sc->sc_flags & BWN_FLAG_INVALID) == 0) {
1264 bwn_init(sc);
1265 startall = 1;
1266 }
1267 } else
1268 bwn_stop(sc, 1);
1269 if (startall)
1270 ieee80211_start_all(ic);
1271 break;
1272 case SIOCGIFMEDIA:
1273 error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
1274 break;
1275 case SIOCGIFADDR:
1276 error = ether_ioctl(ifp, cmd, data);
1277 break;
1278 default:
1279 error = EINVAL;
1280 break;
1281 }
1282 return (error);
1283}
1284
1285static void
1286bwn_start(struct ifnet *ifp)
1287{
1288 struct bwn_softc *sc = ifp->if_softc;
1289
1290 BWN_LOCK(sc);
1291 bwn_start_locked(ifp);
1292 BWN_UNLOCK(sc);
1293}
1294
1295static void
1296bwn_start_locked(struct ifnet *ifp)
1297{
1298 struct bwn_softc *sc = ifp->if_softc;
1299 struct bwn_mac *mac = sc->sc_curmac;
1300 struct ieee80211_frame *wh;
1301 struct ieee80211_node *ni;
1302 struct ieee80211_key *k;
1303 struct mbuf *m;
1304
1305 BWN_ASSERT_LOCKED(sc);
1306
1307 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || mac == NULL ||
1308 mac->mac_status < BWN_MAC_STATUS_STARTED)
1309 return;
1310
1311 for (;;) {
1312 IFQ_DRV_DEQUEUE(&ifp->if_snd, m); /* XXX: LOCK */
1313 if (m == NULL)
1314 break;
1315
1316 if (bwn_tx_isfull(sc, m))
1317 break;
1318 ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
1319 if (ni == NULL) {
1320 device_printf(sc->sc_dev, "unexpected NULL ni\n");
1321 m_freem(m);
1322 ifp->if_oerrors++;
1323 continue;
1324 }
1325 KASSERT(ni != NULL, ("%s:%d: fail", __func__, __LINE__));
1326 wh = mtod(m, struct ieee80211_frame *);
1327 if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
1328 k = ieee80211_crypto_encap(ni, m);
1329 if (k == NULL) {
1330 ieee80211_free_node(ni);
1331 m_freem(m);
1332 ifp->if_oerrors++;
1333 continue;
1334 }
1335 }
1336 wh = NULL; /* Catch any invalid use */
1337
1338 if (bwn_tx_start(sc, ni, m) != 0) {
1339 if (ni != NULL)
1340 ieee80211_free_node(ni);
1341 ifp->if_oerrors++;
1342 continue;
1343 }
1344
1345 sc->sc_watchdog_timer = 5;
1346 }
1347}
1348
1349static int
1350bwn_tx_isfull(struct bwn_softc *sc, struct mbuf *m)
1351{
1352 struct bwn_dma_ring *dr;
1353 struct bwn_mac *mac = sc->sc_curmac;
1354 struct bwn_pio_txqueue *tq;
1355 struct ifnet *ifp = sc->sc_ifp;
1356 int pktlen = roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1357
1358 BWN_ASSERT_LOCKED(sc);
1359
1360 if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
1361 dr = bwn_dma_select(mac, M_WME_GETAC(m));
1362 if (dr->dr_stop == 1 ||
1363 bwn_dma_freeslot(dr) < BWN_TX_SLOTS_PER_FRAME) {
1364 dr->dr_stop = 1;
1365 goto full;
1366 }
1367 } else {
1368 tq = bwn_pio_select(mac, M_WME_GETAC(m));
1369 if (tq->tq_free == 0 || pktlen > tq->tq_size ||
1370 pktlen > (tq->tq_size - tq->tq_used)) {
1371 tq->tq_stop = 1;
1372 goto full;
1373 }
1374 }
1375 return (0);
1376full:
1377 IFQ_DRV_PREPEND(&ifp->if_snd, m);
1378 ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1379 return (1);
1380}
1381
1382static int
1383bwn_tx_start(struct bwn_softc *sc, struct ieee80211_node *ni, struct mbuf *m)
1384{
1385 struct bwn_mac *mac = sc->sc_curmac;
1386 int error;
1387
1388 BWN_ASSERT_LOCKED(sc);
1389
1390 if (m->m_pkthdr.len < IEEE80211_MIN_LEN || mac == NULL) {
1391 m_freem(m);
1392 return (ENXIO);
1393 }
1394
1395 error = (mac->mac_flags & BWN_MAC_FLAG_DMA) ?
1396 bwn_dma_tx_start(mac, ni, m) : bwn_pio_tx_start(mac, ni, m);
1397 if (error) {
1398 m_freem(m);
1399 return (error);
1400 }
1401 return (0);
1402}
1403
1404static int
1405bwn_pio_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1406{
1407 struct bwn_pio_txpkt *tp;
1408 struct bwn_pio_txqueue *tq = bwn_pio_select(mac, M_WME_GETAC(m));
1409 struct bwn_softc *sc = mac->mac_sc;
1410 struct bwn_txhdr txhdr;
1411 struct mbuf *m_new;
1412 uint32_t ctl32;
1413 int error;
1414 uint16_t ctl16;
1415
1416 BWN_ASSERT_LOCKED(sc);
1417
1418 /* XXX TODO send packets after DTIM */
1419
1420 KASSERT(!TAILQ_EMPTY(&tq->tq_pktlist), ("%s: fail", __func__));
1421 tp = TAILQ_FIRST(&tq->tq_pktlist);
1422 tp->tp_ni = ni;
1423 tp->tp_m = m;
1424
1425 error = bwn_set_txhdr(mac, ni, m, &txhdr, BWN_PIO_COOKIE(tq, tp));
1426 if (error) {
1427 device_printf(sc->sc_dev, "tx fail\n");
1428 return (error);
1429 }
1430
1431 TAILQ_REMOVE(&tq->tq_pktlist, tp, tp_list);
1432 tq->tq_used += roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1433 tq->tq_free--;
1434
1435 if (siba_get_revid(sc->sc_dev) >= 8) {
1436 /*
1437 * XXX please removes m_defrag(9)
1438 */
1439 m_new = m_defrag(m, M_DONTWAIT);
1440 if (m_new == NULL) {
1441 device_printf(sc->sc_dev,
1442 "%s: can't defrag TX buffer\n",
1443 __func__);
1444 return (ENOBUFS);
1445 }
1446 if (m_new->m_next != NULL)
1447 device_printf(sc->sc_dev,
1448 "TODO: fragmented packets for PIO\n");
1449 tp->tp_m = m_new;
1450
1451 /* send HEADER */
1452 ctl32 = bwn_pio_write_multi_4(mac, tq,
1453 (BWN_PIO_READ_4(mac, tq, BWN_PIO8_TXCTL) |
1454 BWN_PIO8_TXCTL_FRAMEREADY) & ~BWN_PIO8_TXCTL_EOF,
1455 (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1456 /* send BODY */
1457 ctl32 = bwn_pio_write_multi_4(mac, tq, ctl32,
1458 mtod(m_new, const void *), m_new->m_pkthdr.len);
1459 bwn_pio_write_4(mac, tq, BWN_PIO_TXCTL,
1460 ctl32 | BWN_PIO8_TXCTL_EOF);
1461 } else {
1462 ctl16 = bwn_pio_write_multi_2(mac, tq,
1463 (bwn_pio_read_2(mac, tq, BWN_PIO_TXCTL) |
1464 BWN_PIO_TXCTL_FRAMEREADY) & ~BWN_PIO_TXCTL_EOF,
1465 (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1466 ctl16 = bwn_pio_write_mbuf_2(mac, tq, ctl16, m);
1467 BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL,
1468 ctl16 | BWN_PIO_TXCTL_EOF);
1469 }
1470
1471 return (0);
1472}
1473
1474static struct bwn_pio_txqueue *
1475bwn_pio_select(struct bwn_mac *mac, uint8_t prio)
1476{
1477
1478 if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
1479 return (&mac->mac_method.pio.wme[WME_AC_BE]);
1480
1481 switch (prio) {
1482 case 0:
1483 return (&mac->mac_method.pio.wme[WME_AC_BE]);
1484 case 1:
1485 return (&mac->mac_method.pio.wme[WME_AC_BK]);
1486 case 2:
1487 return (&mac->mac_method.pio.wme[WME_AC_VI]);
1488 case 3:
1489 return (&mac->mac_method.pio.wme[WME_AC_VO]);
1490 }
1491 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
1492 return (NULL);
1493}
1494
1495static int
1496bwn_dma_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1497{
1498#define BWN_GET_TXHDRCACHE(slot) \
1499 &(txhdr_cache[(slot / BWN_TX_SLOTS_PER_FRAME) * BWN_HDRSIZE(mac)])
1500 struct bwn_dma *dma = &mac->mac_method.dma;
1501 struct bwn_dma_ring *dr = bwn_dma_select(mac, M_WME_GETAC(m));
1502 struct bwn_dmadesc_generic *desc;
1503 struct bwn_dmadesc_meta *mt;
1504 struct bwn_softc *sc = mac->mac_sc;
1505 struct ifnet *ifp = sc->sc_ifp;
1506 uint8_t *txhdr_cache = (uint8_t *)dr->dr_txhdr_cache;
1507 int error, slot, backup[2] = { dr->dr_curslot, dr->dr_usedslot };
1508
1509 BWN_ASSERT_LOCKED(sc);
1510 KASSERT(!dr->dr_stop, ("%s:%d: fail", __func__, __LINE__));
1511
1512 /* XXX send after DTIM */
1513
1514 slot = bwn_dma_getslot(dr);
1515 dr->getdesc(dr, slot, &desc, &mt);
1516 KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_HEADER,
1517 ("%s:%d: fail", __func__, __LINE__));
1518
1519 error = bwn_set_txhdr(dr->dr_mac, ni, m,
1520 (struct bwn_txhdr *)BWN_GET_TXHDRCACHE(slot),
1521 BWN_DMA_COOKIE(dr, slot));
1522 if (error)
1523 goto fail;
1524 error = bus_dmamap_load(dr->dr_txring_dtag, mt->mt_dmap,
1525 BWN_GET_TXHDRCACHE(slot), BWN_HDRSIZE(mac), bwn_dma_ring_addr,
1526 &mt->mt_paddr, BUS_DMA_NOWAIT);
1527 if (error) {
1528 if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
1529 __func__, error);
1530 goto fail;
1531 }
1532 bus_dmamap_sync(dr->dr_txring_dtag, mt->mt_dmap,
1533 BUS_DMASYNC_PREWRITE);
1534 dr->setdesc(dr, desc, mt->mt_paddr, BWN_HDRSIZE(mac), 1, 0, 0);
1535 bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1536 BUS_DMASYNC_PREWRITE);
1537
1538 slot = bwn_dma_getslot(dr);
1539 dr->getdesc(dr, slot, &desc, &mt);
1540 KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_BODY &&
1541 mt->mt_islast == 1, ("%s:%d: fail", __func__, __LINE__));
1542 mt->mt_m = m;
1543 mt->mt_ni = ni;
1544
1545 error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap, m,
1546 bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1547 if (error && error != EFBIG) {
1548 if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
1549 __func__, error);
1550 goto fail;
1551 }
1552 if (error) { /* error == EFBIG */
1553 struct mbuf *m_new;
1554
1555 m_new = m_defrag(m, M_DONTWAIT);
1556 if (m_new == NULL) {
1557 if_printf(ifp, "%s: can't defrag TX buffer\n",
1558 __func__);
1559 error = ENOBUFS;
1560 goto fail;
1561 } else {
1562 m = m_new;
1563 }
1564
1565 mt->mt_m = m;
1566 error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap,
1567 m, bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1568 if (error) {
1569 if_printf(ifp, "%s: can't load TX buffer (2) %d\n",
1570 __func__, error);
1571 goto fail;
1572 }
1573 }
1574 bus_dmamap_sync(dma->txbuf_dtag, mt->mt_dmap, BUS_DMASYNC_PREWRITE);
1575 dr->setdesc(dr, desc, mt->mt_paddr, m->m_pkthdr.len, 0, 1, 1);
1576 bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1577 BUS_DMASYNC_PREWRITE);
1578
1579 /* XXX send after DTIM */
1580
1581 dr->start_transfer(dr, bwn_dma_nextslot(dr, slot));
1582 return (0);
1583fail:
1584 dr->dr_curslot = backup[0];
1585 dr->dr_usedslot = backup[1];
1586 return (error);
1587#undef BWN_GET_TXHDRCACHE
1588}
1589
1590static void
1591bwn_watchdog(void *arg)
1592{
1593 struct bwn_softc *sc = arg;
1594 struct ifnet *ifp = sc->sc_ifp;
1595
1596 if (sc->sc_watchdog_timer != 0 && --sc->sc_watchdog_timer == 0) {
1597 if_printf(ifp, "device timeout\n");
1598 ifp->if_oerrors++;
1599 }
1600 callout_schedule(&sc->sc_watchdog_ch, hz);
1601}
1602
1603static int
1604bwn_attach_core(struct bwn_mac *mac)
1605{
1606 struct bwn_softc *sc = mac->mac_sc;
1607 int error, have_bg = 0, have_a = 0;
1608 uint32_t high;
1609
1610 KASSERT(siba_get_revid(sc->sc_dev) >= 5,
1611 ("unsupported revision %d", siba_get_revid(sc->sc_dev)));
1612
1613 siba_powerup(sc->sc_dev, 0);
1614
1615 high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH);
1616 bwn_reset_core(mac,
1617 (high & BWN_TGSHIGH_HAVE_2GHZ) ? BWN_TGSLOW_SUPPORT_G : 0);
1618 error = bwn_phy_getinfo(mac, high);
1619 if (error)
1620 goto fail;
1621
1622 have_a = (high & BWN_TGSHIGH_HAVE_5GHZ) ? 1 : 0;
1623 have_bg = (high & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1624 if (siba_get_pci_device(sc->sc_dev) != 0x4312 &&
1625 siba_get_pci_device(sc->sc_dev) != 0x4319 &&
1626 siba_get_pci_device(sc->sc_dev) != 0x4324) {
1627 have_a = have_bg = 0;
1628 if (mac->mac_phy.type == BWN_PHYTYPE_A)
1629 have_a = 1;
1630 else if (mac->mac_phy.type == BWN_PHYTYPE_G ||
1631 mac->mac_phy.type == BWN_PHYTYPE_N ||
1632 mac->mac_phy.type == BWN_PHYTYPE_LP)
1633 have_bg = 1;
1634 else
1635 KASSERT(0 == 1, ("%s: unknown phy type (%d)", __func__,
1636 mac->mac_phy.type));
1637 }
1638 /* XXX turns off PHY A because it's not supported */
1639 if (mac->mac_phy.type != BWN_PHYTYPE_LP &&
1640 mac->mac_phy.type != BWN_PHYTYPE_N) {
1641 have_a = 0;
1642 have_bg = 1;
1643 }
1644
1645 if (mac->mac_phy.type == BWN_PHYTYPE_G) {
1646 mac->mac_phy.attach = bwn_phy_g_attach;
1647 mac->mac_phy.detach = bwn_phy_g_detach;
1648 mac->mac_phy.prepare_hw = bwn_phy_g_prepare_hw;
1649 mac->mac_phy.init_pre = bwn_phy_g_init_pre;
1650 mac->mac_phy.init = bwn_phy_g_init;
1651 mac->mac_phy.exit = bwn_phy_g_exit;
1652 mac->mac_phy.phy_read = bwn_phy_g_read;
1653 mac->mac_phy.phy_write = bwn_phy_g_write;
1654 mac->mac_phy.rf_read = bwn_phy_g_rf_read;
1655 mac->mac_phy.rf_write = bwn_phy_g_rf_write;
1656 mac->mac_phy.use_hwpctl = bwn_phy_g_hwpctl;
1657 mac->mac_phy.rf_onoff = bwn_phy_g_rf_onoff;
1658 mac->mac_phy.switch_analog = bwn_phy_switch_analog;
1659 mac->mac_phy.switch_channel = bwn_phy_g_switch_channel;
1660 mac->mac_phy.get_default_chan = bwn_phy_g_get_default_chan;
1661 mac->mac_phy.set_antenna = bwn_phy_g_set_antenna;
1662 mac->mac_phy.set_im = bwn_phy_g_im;
1663 mac->mac_phy.recalc_txpwr = bwn_phy_g_recalc_txpwr;
1664 mac->mac_phy.set_txpwr = bwn_phy_g_set_txpwr;
1665 mac->mac_phy.task_15s = bwn_phy_g_task_15s;
1666 mac->mac_phy.task_60s = bwn_phy_g_task_60s;
1667 } else if (mac->mac_phy.type == BWN_PHYTYPE_LP) {
1668 mac->mac_phy.init_pre = bwn_phy_lp_init_pre;
1669 mac->mac_phy.init = bwn_phy_lp_init;
1670 mac->mac_phy.phy_read = bwn_phy_lp_read;
1671 mac->mac_phy.phy_write = bwn_phy_lp_write;
1672 mac->mac_phy.phy_maskset = bwn_phy_lp_maskset;
1673 mac->mac_phy.rf_read = bwn_phy_lp_rf_read;
1674 mac->mac_phy.rf_write = bwn_phy_lp_rf_write;
1675 mac->mac_phy.rf_onoff = bwn_phy_lp_rf_onoff;
1676 mac->mac_phy.switch_analog = bwn_phy_lp_switch_analog;
1677 mac->mac_phy.switch_channel = bwn_phy_lp_switch_channel;
1678 mac->mac_phy.get_default_chan = bwn_phy_lp_get_default_chan;
1679 mac->mac_phy.set_antenna = bwn_phy_lp_set_antenna;
1680 mac->mac_phy.task_60s = bwn_phy_lp_task_60s;
1681 } else {
1682 device_printf(sc->sc_dev, "unsupported PHY type (%d)\n",
1683 mac->mac_phy.type);
1684 error = ENXIO;
1685 goto fail;
1686 }
1687
1688 mac->mac_phy.gmode = have_bg;
1689 if (mac->mac_phy.attach != NULL) {
1690 error = mac->mac_phy.attach(mac);
1691 if (error) {
1692 device_printf(sc->sc_dev, "failed\n");
1693 goto fail;
1694 }
1695 }
1696
1697 bwn_reset_core(mac, have_bg ? BWN_TGSLOW_SUPPORT_G : 0);
1698
1699 error = bwn_chiptest(mac);
1700 if (error)
1701 goto fail;
1702 error = bwn_setup_channels(mac, have_bg, have_a);
1703 if (error) {
1704 device_printf(sc->sc_dev, "failed to setup channels\n");
1705 goto fail;
1706 }
1707
1708 if (sc->sc_curmac == NULL)
1709 sc->sc_curmac = mac;
1710
1711 error = bwn_dma_attach(mac);
1712 if (error != 0) {
1713 device_printf(sc->sc_dev, "failed to initialize DMA\n");
1714 goto fail;
1715 }
1716
1717 mac->mac_phy.switch_analog(mac, 0);
1718
1719 siba_dev_down(sc->sc_dev, 0);
1720fail:
1721 siba_powerdown(sc->sc_dev);
1722 return (error);
1723}
1724
1725static void
1726bwn_reset_core(struct bwn_mac *mac, uint32_t flags)
1727{
1728 struct bwn_softc *sc = mac->mac_sc;
1729 uint32_t low, ctl;
1730
1731 flags |= (BWN_TGSLOW_PHYCLOCK_ENABLE | BWN_TGSLOW_PHYRESET);
1732
1733 siba_dev_up(sc->sc_dev, flags);
1734 DELAY(2000);
1735
1736 low = (siba_read_4(sc->sc_dev, SIBA_TGSLOW) | SIBA_TGSLOW_FGC) &
1737 ~BWN_TGSLOW_PHYRESET;
1738 siba_write_4(sc->sc_dev, SIBA_TGSLOW, low);
1739 siba_read_4(sc->sc_dev, SIBA_TGSLOW);
1740 DELAY(1000);
1741 siba_write_4(sc->sc_dev, SIBA_TGSLOW, low & ~SIBA_TGSLOW_FGC);
1742 siba_read_4(sc->sc_dev, SIBA_TGSLOW);
1743 DELAY(1000);
1744
1745 if (mac->mac_phy.switch_analog != NULL)
1746 mac->mac_phy.switch_analog(mac, 1);
1747
1748 ctl = BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GMODE;
1749 if (flags & BWN_TGSLOW_SUPPORT_G)
1750 ctl |= BWN_MACCTL_GMODE;
1751 BWN_WRITE_4(mac, BWN_MACCTL, ctl | BWN_MACCTL_IHR_ON);
1752}
1753
1754static int
1755bwn_phy_getinfo(struct bwn_mac *mac, int tgshigh)
1756{
1757 struct bwn_phy *phy = &mac->mac_phy;
1758 struct bwn_softc *sc = mac->mac_sc;
1759 uint32_t tmp;
1760
1761 /* PHY */
1762 tmp = BWN_READ_2(mac, BWN_PHYVER);
1763 phy->gmode = (tgshigh & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1764 phy->rf_on = 1;
1765 phy->analog = (tmp & BWN_PHYVER_ANALOG) >> 12;
1766 phy->type = (tmp & BWN_PHYVER_TYPE) >> 8;
1767 phy->rev = (tmp & BWN_PHYVER_VERSION);
1768 if ((phy->type == BWN_PHYTYPE_A && phy->rev >= 4) ||
1769 (phy->type == BWN_PHYTYPE_B && phy->rev != 2 &&
1770 phy->rev != 4 && phy->rev != 6 && phy->rev != 7) ||
1771 (phy->type == BWN_PHYTYPE_G && phy->rev > 9) ||
1772 (phy->type == BWN_PHYTYPE_N && phy->rev > 4) ||
1773 (phy->type == BWN_PHYTYPE_LP && phy->rev > 2))
1774 goto unsupphy;
1775
1776 /* RADIO */
1777 if (siba_get_chipid(sc->sc_dev) == 0x4317) {
1778 if (siba_get_chiprev(sc->sc_dev) == 0)
1779 tmp = 0x3205017f;
1780 else if (siba_get_chiprev(sc->sc_dev) == 1)
1781 tmp = 0x4205017f;
1782 else
1783 tmp = 0x5205017f;
1784 } else {
1785 BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1786 tmp = BWN_READ_2(mac, BWN_RFDATALO);
1787 BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1788 tmp |= (uint32_t)BWN_READ_2(mac, BWN_RFDATAHI) << 16;
1789 }
1790 phy->rf_rev = (tmp & 0xf0000000) >> 28;
1791 phy->rf_ver = (tmp & 0x0ffff000) >> 12;
1792 phy->rf_manuf = (tmp & 0x00000fff);
1793 if (phy->rf_manuf != 0x17f) /* 0x17f is broadcom */
1794 goto unsupradio;
1795 if ((phy->type == BWN_PHYTYPE_A && (phy->rf_ver != 0x2060 ||
1796 phy->rf_rev != 1 || phy->rf_manuf != 0x17f)) ||
1797 (phy->type == BWN_PHYTYPE_B && (phy->rf_ver & 0xfff0) != 0x2050) ||
1798 (phy->type == BWN_PHYTYPE_G && phy->rf_ver != 0x2050) ||
1799 (phy->type == BWN_PHYTYPE_N &&
1800 phy->rf_ver != 0x2055 && phy->rf_ver != 0x2056) ||
1801 (phy->type == BWN_PHYTYPE_LP &&
1802 phy->rf_ver != 0x2062 && phy->rf_ver != 0x2063))
1803 goto unsupradio;
1804
1805 return (0);
1806unsupphy:
1807 device_printf(sc->sc_dev, "unsupported PHY (type %#x, rev %#x, "
1808 "analog %#x)\n",
1809 phy->type, phy->rev, phy->analog);
1810 return (ENXIO);
1811unsupradio:
1812 device_printf(sc->sc_dev, "unsupported radio (manuf %#x, ver %#x, "
1813 "rev %#x)\n",
1814 phy->rf_manuf, phy->rf_ver, phy->rf_rev);
1815 return (ENXIO);
1816}
1817
1818static int
1819bwn_chiptest(struct bwn_mac *mac)
1820{
1821#define TESTVAL0 0x55aaaa55
1822#define TESTVAL1 0xaa5555aa
1823 struct bwn_softc *sc = mac->mac_sc;
1824 uint32_t v, backup;
1825
1826 BWN_LOCK(sc);
1827
1828 backup = bwn_shm_read_4(mac, BWN_SHARED, 0);
1829
1830 bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL0);
1831 if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL0)
1832 goto error;
1833 bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL1);
1834 if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL1)
1835 goto error;
1836
1837 bwn_shm_write_4(mac, BWN_SHARED, 0, backup);
1838
1839 if ((siba_get_revid(sc->sc_dev) >= 3) &&
1840 (siba_get_revid(sc->sc_dev) <= 10)) {
1841 BWN_WRITE_2(mac, BWN_TSF_CFP_START, 0xaaaa);
1842 BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0xccccbbbb);
1843 if (BWN_READ_2(mac, BWN_TSF_CFP_START_LOW) != 0xbbbb)
1844 goto error;
1845 if (BWN_READ_2(mac, BWN_TSF_CFP_START_HIGH) != 0xcccc)
1846 goto error;
1847 }
1848 BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0);
1849
1850 v = BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_GMODE;
1851 if (v != (BWN_MACCTL_GMODE | BWN_MACCTL_IHR_ON))
1852 goto error;
1853
1854 BWN_UNLOCK(sc);
1855 return (0);
1856error:
1857 BWN_UNLOCK(sc);
1858 device_printf(sc->sc_dev, "failed to validate the chipaccess\n");
1859 return (ENODEV);
1860}
1861
1862#define IEEE80211_CHAN_HTG (IEEE80211_CHAN_HT | IEEE80211_CHAN_G)
1863#define IEEE80211_CHAN_HTA (IEEE80211_CHAN_HT | IEEE80211_CHAN_A)
1864
1865static int
1866bwn_setup_channels(struct bwn_mac *mac, int have_bg, int have_a)
1867{
1868 struct bwn_softc *sc = mac->mac_sc;
1869 struct ifnet *ifp = sc->sc_ifp;
1870 struct ieee80211com *ic = ifp->if_l2com;
1871
1872 memset(ic->ic_channels, 0, sizeof(ic->ic_channels));
1873 ic->ic_nchans = 0;
1874
1875 if (have_bg)
1876 bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1877 &ic->ic_nchans, &bwn_chantable_bg, IEEE80211_CHAN_G);
1878 if (mac->mac_phy.type == BWN_PHYTYPE_N) {
1879 if (have_a)
1880 bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1881 &ic->ic_nchans, &bwn_chantable_n,
1882 IEEE80211_CHAN_HTA);
1883 } else {
1884 if (have_a)
1885 bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1886 &ic->ic_nchans, &bwn_chantable_a,
1887 IEEE80211_CHAN_A);
1888 }
1889
1890 mac->mac_phy.supports_2ghz = have_bg;
1891 mac->mac_phy.supports_5ghz = have_a;
1892
1893 return (ic->ic_nchans == 0 ? ENXIO : 0);
1894}
1895
1896static uint32_t
1897bwn_shm_read_4(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1898{
1899 uint32_t ret;
1900
1901 BWN_ASSERT_LOCKED(mac->mac_sc);
1902
1903 if (way == BWN_SHARED) {
1904 KASSERT((offset & 0x0001) == 0,
1905 ("%s:%d warn", __func__, __LINE__));
1906 if (offset & 0x0003) {
1907 bwn_shm_ctlword(mac, way, offset >> 2);
1908 ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1909 ret <<= 16;
1910 bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1911 ret |= BWN_READ_2(mac, BWN_SHM_DATA);
1912 goto out;
1913 }
1914 offset >>= 2;
1915 }
1916 bwn_shm_ctlword(mac, way, offset);
1917 ret = BWN_READ_4(mac, BWN_SHM_DATA);
1918out:
1919 return (ret);
1920}
1921
1922static uint16_t
1923bwn_shm_read_2(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1924{
1925 uint16_t ret;
1926
1927 BWN_ASSERT_LOCKED(mac->mac_sc);
1928
1929 if (way == BWN_SHARED) {
1930 KASSERT((offset & 0x0001) == 0,
1931 ("%s:%d warn", __func__, __LINE__));
1932 if (offset & 0x0003) {
1933 bwn_shm_ctlword(mac, way, offset >> 2);
1934 ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1935 goto out;
1936 }
1937 offset >>= 2;
1938 }
1939 bwn_shm_ctlword(mac, way, offset);
1940 ret = BWN_READ_2(mac, BWN_SHM_DATA);
1941out:
1942
1943 return (ret);
1944}
1945
1946static void
1947bwn_shm_ctlword(struct bwn_mac *mac, uint16_t way,
1948 uint16_t offset)
1949{
1950 uint32_t control;
1951
1952 control = way;
1953 control <<= 16;
1954 control |= offset;
1955 BWN_WRITE_4(mac, BWN_SHM_CONTROL, control);
1956}
1957
1958static void
1959bwn_shm_write_4(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1960 uint32_t value)
1961{
1962 BWN_ASSERT_LOCKED(mac->mac_sc);
1963
1964 if (way == BWN_SHARED) {
1965 KASSERT((offset & 0x0001) == 0,
1966 ("%s:%d warn", __func__, __LINE__));
1967 if (offset & 0x0003) {
1968 bwn_shm_ctlword(mac, way, offset >> 2);
1969 BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED,
1970 (value >> 16) & 0xffff);
1971 bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1972 BWN_WRITE_2(mac, BWN_SHM_DATA, value & 0xffff);
1973 return;
1974 }
1975 offset >>= 2;
1976 }
1977 bwn_shm_ctlword(mac, way, offset);
1978 BWN_WRITE_4(mac, BWN_SHM_DATA, value);
1979}
1980
1981static void
1982bwn_shm_write_2(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1983 uint16_t value)
1984{
1985 BWN_ASSERT_LOCKED(mac->mac_sc);
1986
1987 if (way == BWN_SHARED) {
1988 KASSERT((offset & 0x0001) == 0,
1989 ("%s:%d warn", __func__, __LINE__));
1990 if (offset & 0x0003) {
1991 bwn_shm_ctlword(mac, way, offset >> 2);
1992 BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED, value);
1993 return;
1994 }
1995 offset >>= 2;
1996 }
1997 bwn_shm_ctlword(mac, way, offset);
1998 BWN_WRITE_2(mac, BWN_SHM_DATA, value);
1999}
2000
2001static void
2002bwn_addchan(struct ieee80211_channel *c, int freq, int flags, int ieee,
2003 int txpow)
2004{
2005
2006 c->ic_freq = freq;
2007 c->ic_flags = flags;
2008 c->ic_ieee = ieee;
2009 c->ic_minpower = 0;
2010 c->ic_maxpower = 2 * txpow;
2011 c->ic_maxregpower = txpow;
2012}
2013
2014static void
2015bwn_addchannels(struct ieee80211_channel chans[], int maxchans, int *nchans,
2016 const struct bwn_channelinfo *ci, int flags)
2017{
2018 struct ieee80211_channel *c;
2019 int i;
2020
2021 c = &chans[*nchans];
2022
2023 for (i = 0; i < ci->nchannels; i++) {
2024 const struct bwn_channel *hc;
2025
2026 hc = &ci->channels[i];
2027 if (*nchans >= maxchans)
2028 break;
2029 bwn_addchan(c, hc->freq, flags, hc->ieee, hc->maxTxPow);
2030 c++, (*nchans)++;
2031 if (flags == IEEE80211_CHAN_G || flags == IEEE80211_CHAN_HTG) {
2032 /* g channel have a separate b-only entry */
2033 if (*nchans >= maxchans)
2034 break;
2035 c[0] = c[-1];
2036 c[-1].ic_flags = IEEE80211_CHAN_B;
2037 c++, (*nchans)++;
2038 }
2039 if (flags == IEEE80211_CHAN_HTG) {
2040 /* HT g channel have a separate g-only entry */
2041 if (*nchans >= maxchans)
2042 break;
2043 c[-1].ic_flags = IEEE80211_CHAN_G;
2044 c[0] = c[-1];
2045 c[0].ic_flags &= ~IEEE80211_CHAN_HT;
2046 c[0].ic_flags |= IEEE80211_CHAN_HT20; /* HT20 */
2047 c++, (*nchans)++;
2048 }
2049 if (flags == IEEE80211_CHAN_HTA) {
2050 /* HT a channel have a separate a-only entry */
2051 if (*nchans >= maxchans)
2052 break;
2053 c[-1].ic_flags = IEEE80211_CHAN_A;
2054 c[0] = c[-1];
2055 c[0].ic_flags &= ~IEEE80211_CHAN_HT;
2056 c[0].ic_flags |= IEEE80211_CHAN_HT20; /* HT20 */
2057 c++, (*nchans)++;
2058 }
2059 }
2060}
2061
2062static int
2063bwn_phy_g_attach(struct bwn_mac *mac)
2064{
2065 struct bwn_softc *sc = mac->mac_sc;
2066 struct bwn_phy *phy = &mac->mac_phy;
2067 struct bwn_phy_g *pg = &phy->phy_g;
2068 unsigned int i;
2069 int16_t pab0, pab1, pab2;
2070 static int8_t bwn_phy_g_tssi2dbm_table[] = BWN_PHY_G_TSSI2DBM_TABLE;
2071 int8_t bg;
2072
2073 bg = (int8_t)siba_sprom_get_tssi_bg(sc->sc_dev);
2074 pab0 = (int16_t)siba_sprom_get_pa0b0(sc->sc_dev);
2075 pab1 = (int16_t)siba_sprom_get_pa0b1(sc->sc_dev);
2076 pab2 = (int16_t)siba_sprom_get_pa0b2(sc->sc_dev);
2077
2078 if ((siba_get_chipid(sc->sc_dev) == 0x4301) && (phy->rf_ver != 0x2050))
2079 device_printf(sc->sc_dev, "not supported anymore\n");
2080
2081 pg->pg_flags = 0;
2082 if (pab0 == 0 || pab1 == 0 || pab2 == 0 || pab0 == -1 || pab1 == -1 ||
2083 pab2 == -1) {
2084 pg->pg_idletssi = 52;
2085 pg->pg_tssi2dbm = bwn_phy_g_tssi2dbm_table;
2086 return (0);
2087 }
2088
2089 pg->pg_idletssi = (bg == 0 || bg == -1) ? 62 : bg;
2090 pg->pg_tssi2dbm = (uint8_t *)malloc(64, M_DEVBUF, M_NOWAIT | M_ZERO);
2091 if (pg->pg_tssi2dbm == NULL) {
2092 device_printf(sc->sc_dev, "failed to allocate buffer\n");
2093 return (ENOMEM);
2094 }
2095 for (i = 0; i < 64; i++) {
2096 int32_t m1, m2, f, q, delta;
2097 int8_t j = 0;
2098
2099 m1 = BWN_TSSI2DBM(16 * pab0 + i * pab1, 32);
2100 m2 = MAX(BWN_TSSI2DBM(32768 + i * pab2, 256), 1);
2101 f = 256;
2102
2103 do {
2104 if (j > 15) {
2105 device_printf(sc->sc_dev,
2106 "failed to generate tssi2dBm\n");
2107 free(pg->pg_tssi2dbm, M_DEVBUF);
2108 return (ENOMEM);
2109 }
2110 q = BWN_TSSI2DBM(f * 4096 - BWN_TSSI2DBM(m2 * f, 16) *
2111 f, 2048);
2112 delta = abs(q - f);
2113 f = q;
2114 j++;
2115 } while (delta >= 2);
2116
2117 pg->pg_tssi2dbm[i] = MIN(MAX(BWN_TSSI2DBM(m1 * f, 8192), -127),
2118 128);
2119 }
2120
2121 pg->pg_flags |= BWN_PHY_G_FLAG_TSSITABLE_ALLOC;
2122 return (0);
2123}
2124
2125static void
2126bwn_phy_g_detach(struct bwn_mac *mac)
2127{
2128 struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
2129
2130 if (pg->pg_flags & BWN_PHY_G_FLAG_TSSITABLE_ALLOC) {
2131 free(pg->pg_tssi2dbm, M_DEVBUF);
2132 pg->pg_tssi2dbm = NULL;
2133 }
2134 pg->pg_flags = 0;
2135}
2136
2137static void
2138bwn_phy_g_init_pre(struct bwn_mac *mac)
2139{
2140 struct bwn_phy *phy = &mac->mac_phy;
2141 struct bwn_phy_g *pg = &phy->phy_g;
2142 void *tssi2dbm;
2143 int idletssi;
2144 unsigned int i;
2145
2146 tssi2dbm = pg->pg_tssi2dbm;
2147 idletssi = pg->pg_idletssi;
2148
2149 memset(pg, 0, sizeof(*pg));
2150
2151 pg->pg_tssi2dbm = tssi2dbm;
2152 pg->pg_idletssi = idletssi;
2153
2154 memset(pg->pg_minlowsig, 0xff, sizeof(pg->pg_minlowsig));
2155
2156 for (i = 0; i < N(pg->pg_nrssi); i++)
2157 pg->pg_nrssi[i] = -1000;
2158 for (i = 0; i < N(pg->pg_nrssi_lt); i++)
2159 pg->pg_nrssi_lt[i] = i;
2160 pg->pg_lofcal = 0xffff;
2161 pg->pg_initval = 0xffff;
2162 pg->pg_immode = BWN_IMMODE_NONE;
2163 pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_UNKNOWN;
2164 pg->pg_avgtssi = 0xff;
2165
2166 pg->pg_loctl.tx_bias = 0xff;
2167 TAILQ_INIT(&pg->pg_loctl.calib_list);
2168}
2169
2170static int
2171bwn_phy_g_prepare_hw(struct bwn_mac *mac)
2172{
2173 struct bwn_phy *phy = &mac->mac_phy;
2174 struct bwn_phy_g *pg = &phy->phy_g;
2175 struct bwn_softc *sc = mac->mac_sc;
2176 struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2177 static const struct bwn_rfatt rfatt0[] = {
2178 { 3, 0 }, { 1, 0 }, { 5, 0 }, { 7, 0 }, { 9, 0 }, { 2, 0 },
2179 { 0, 0 }, { 4, 0 }, { 6, 0 }, { 8, 0 }, { 1, 1 }, { 2, 1 },
2180 { 3, 1 }, { 4, 1 }
2181 };
2182 static const struct bwn_rfatt rfatt1[] = {
2183 { 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 10, 1 }, { 12, 1 },
2184 { 14, 1 }
2185 };
2186 static const struct bwn_rfatt rfatt2[] = {
2187 { 0, 1 }, { 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 9, 1 },
2188 { 9, 1 }
2189 };
2190 static const struct bwn_bbatt bbatt_0[] = {
2191 { 0 }, { 1 }, { 2 }, { 3 }, { 4 }, { 5 }, { 6 }, { 7 }, { 8 }
2192 };
2193
2194 KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
2195
2196 if (phy->rf_ver == 0x2050 && phy->rf_rev < 6)
2197 pg->pg_bbatt.att = 0;
2198 else
2199 pg->pg_bbatt.att = 2;
2200
2201 /* prepare Radio Attenuation */
2202 pg->pg_rfatt.padmix = 0;
2203
2204 if (siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM &&
2205 siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BCM4309G) {
2206 if (siba_get_pci_revid(sc->sc_dev) < 0x43) {
2207 pg->pg_rfatt.att = 2;
2208 goto done;
2209 } else if (siba_get_pci_revid(sc->sc_dev) < 0x51) {
2210 pg->pg_rfatt.att = 3;
2211 goto done;
2212 }
2213 }
2214
2215 if (phy->type == BWN_PHYTYPE_A) {
2216 pg->pg_rfatt.att = 0x60;
2217 goto done;
2218 }
2219
2220 switch (phy->rf_ver) {
2221 case 0x2050:
2222 switch (phy->rf_rev) {
2223 case 0:
2224 pg->pg_rfatt.att = 5;
2225 goto done;
2226 case 1:
2227 if (phy->type == BWN_PHYTYPE_G) {
2228 if (siba_get_pci_subvendor(sc->sc_dev) ==
2229 SIBA_BOARDVENDOR_BCM &&
2230 siba_get_pci_subdevice(sc->sc_dev) ==
2231 SIBA_BOARD_BCM4309G &&
2232 siba_get_pci_revid(sc->sc_dev) >= 30)
2233 pg->pg_rfatt.att = 3;
2234 else if (siba_get_pci_subvendor(sc->sc_dev) ==
2235 SIBA_BOARDVENDOR_BCM &&
2236 siba_get_pci_subdevice(sc->sc_dev) ==
2237 SIBA_BOARD_BU4306)
2238 pg->pg_rfatt.att = 3;
2239 else
2240 pg->pg_rfatt.att = 1;
2241 } else {
2242 if (siba_get_pci_subvendor(sc->sc_dev) ==
2243 SIBA_BOARDVENDOR_BCM &&
2244 siba_get_pci_subdevice(sc->sc_dev) ==
2245 SIBA_BOARD_BCM4309G &&
2246 siba_get_pci_revid(sc->sc_dev) >= 30)
2247 pg->pg_rfatt.att = 7;
2248 else
2249 pg->pg_rfatt.att = 6;
2250 }
2251 goto done;
2252 case 2:
2253 if (phy->type == BWN_PHYTYPE_G) {
2254 if (siba_get_pci_subvendor(sc->sc_dev) ==
2255 SIBA_BOARDVENDOR_BCM &&
2256 siba_get_pci_subdevice(sc->sc_dev) ==
2257 SIBA_BOARD_BCM4309G &&
2258 siba_get_pci_revid(sc->sc_dev) >= 30)
2259 pg->pg_rfatt.att = 3;
2260 else if (siba_get_pci_subvendor(sc->sc_dev) ==
2261 SIBA_BOARDVENDOR_BCM &&
2262 siba_get_pci_subdevice(sc->sc_dev) ==
2263 SIBA_BOARD_BU4306)
2264 pg->pg_rfatt.att = 5;
2265 else if (siba_get_chipid(sc->sc_dev) == 0x4320)
2266 pg->pg_rfatt.att = 4;
2267 else
2268 pg->pg_rfatt.att = 3;
2269 } else
2270 pg->pg_rfatt.att = 6;
2271 goto done;
2272 case 3:
2273 pg->pg_rfatt.att = 5;
2274 goto done;
2275 case 4:
2276 case 5:
2277 pg->pg_rfatt.att = 1;
2278 goto done;
2279 case 6:
2280 case 7:
2281 pg->pg_rfatt.att = 5;
2282 goto done;
2283 case 8:
2284 pg->pg_rfatt.att = 0xa;
2285 pg->pg_rfatt.padmix = 1;
2286 goto done;
2287 case 9:
2288 default:
2289 pg->pg_rfatt.att = 5;
2290 goto done;
2291 }
2292 break;
2293 case 0x2053:
2294 switch (phy->rf_rev) {
2295 case 1:
2296 pg->pg_rfatt.att = 6;
2297 goto done;
2298 }
2299 break;
2300 }
2301 pg->pg_rfatt.att = 5;
2302done:
2303 pg->pg_txctl = (bwn_phy_g_txctl(mac) << 4);
2304
2305 if (!bwn_has_hwpctl(mac)) {
2306 lo->rfatt.array = rfatt0;
2307 lo->rfatt.len = N(rfatt0);
2308 lo->rfatt.min = 0;
2309 lo->rfatt.max = 9;
2310 goto genbbatt;
2311 }
2312 if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
2313 lo->rfatt.array = rfatt1;
2314 lo->rfatt.len = N(rfatt1);
2315 lo->rfatt.min = 0;
2316 lo->rfatt.max = 14;
2317 goto genbbatt;
2318 }
2319 lo->rfatt.array = rfatt2;
2320 lo->rfatt.len = N(rfatt2);
2321 lo->rfatt.min = 0;
2322 lo->rfatt.max = 9;
2323genbbatt:
2324 lo->bbatt.array = bbatt_0;
2325 lo->bbatt.len = N(bbatt_0);
2326 lo->bbatt.min = 0;
2327 lo->bbatt.max = 8;
2328
2329 BWN_READ_4(mac, BWN_MACCTL);
2330 if (phy->rev == 1) {
2331 phy->gmode = 0;
2332 bwn_reset_core(mac, 0);
2333 bwn_phy_g_init_sub(mac);
2334 phy->gmode = 1;
2335 bwn_reset_core(mac, BWN_TGSLOW_SUPPORT_G);
2336 }
2337 return (0);
2338}
2339
2340static uint16_t
2341bwn_phy_g_txctl(struct bwn_mac *mac)
2342{
2343 struct bwn_phy *phy = &mac->mac_phy;
2344
2345 if (phy->rf_ver != 0x2050)
2346 return (0);
2347 if (phy->rf_rev == 1)
2348 return (BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX);
2349 if (phy->rf_rev < 6)
2350 return (BWN_TXCTL_PA2DB);
2351 if (phy->rf_rev == 8)
2352 return (BWN_TXCTL_TXMIX);
2353 return (0);
2354}
2355
2356static int
2357bwn_phy_g_init(struct bwn_mac *mac)
2358{
2359
2360 bwn_phy_g_init_sub(mac);
2361 return (0);
2362}
2363
2364static void
2365bwn_phy_g_exit(struct bwn_mac *mac)
2366{
2367 struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
2368 struct bwn_lo_calib *cal, *tmp;
2369
2370 if (lo == NULL)
2371 return;
2372 TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
2373 TAILQ_REMOVE(&lo->calib_list, cal, list);
2374 free(cal, M_DEVBUF);
2375 }
2376}
2377
2378static uint16_t
2379bwn_phy_g_read(struct bwn_mac *mac, uint16_t reg)
2380{
2381
2382 BWN_WRITE_2(mac, BWN_PHYCTL, reg);
2383 return (BWN_READ_2(mac, BWN_PHYDATA));
2384}
2385
2386static void
2387bwn_phy_g_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
2388{
2389
2390 BWN_WRITE_2(mac, BWN_PHYCTL, reg);
2391 BWN_WRITE_2(mac, BWN_PHYDATA, value);
2392}
2393
2394static uint16_t
2395bwn_phy_g_rf_read(struct bwn_mac *mac, uint16_t reg)
2396{
2397
2398 KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
2399 BWN_WRITE_2(mac, BWN_RFCTL, reg | 0x80);
2400 return (BWN_READ_2(mac, BWN_RFDATALO));
2401}
2402
2403static void
2404bwn_phy_g_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
2405{
2406
2407 KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
2408 BWN_WRITE_2(mac, BWN_RFCTL, reg);
2409 BWN_WRITE_2(mac, BWN_RFDATALO, value);
2410}
2411
2412static int
2413bwn_phy_g_hwpctl(struct bwn_mac *mac)
2414{
2415
2416 return (mac->mac_phy.rev >= 6);
2417}
2418
2419static void
2420bwn_phy_g_rf_onoff(struct bwn_mac *mac, int on)
2421{
2422 struct bwn_phy *phy = &mac->mac_phy;
2423 struct bwn_phy_g *pg = &phy->phy_g;
2424 unsigned int channel;
2425 uint16_t rfover, rfoverval;
2426
2427 if (on) {
2428 if (phy->rf_on)
2429 return;
2430
2431 BWN_PHY_WRITE(mac, 0x15, 0x8000);
2432 BWN_PHY_WRITE(mac, 0x15, 0xcc00);
2433 BWN_PHY_WRITE(mac, 0x15, (phy->gmode ? 0xc0 : 0x0));
2434 if (pg->pg_flags & BWN_PHY_G_FLAG_RADIOCTX_VALID) {
2435 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
2436 pg->pg_radioctx_over);
2437 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
2438 pg->pg_radioctx_overval);
2439 pg->pg_flags &= ~BWN_PHY_G_FLAG_RADIOCTX_VALID;
2440 }
2441 channel = phy->chan;
2442 bwn_phy_g_switch_chan(mac, 6, 1);
2443 bwn_phy_g_switch_chan(mac, channel, 0);
2444 return;
2445 }
2446
2447 rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
2448 rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
2449 pg->pg_radioctx_over = rfover;
2450 pg->pg_radioctx_overval = rfoverval;
2451 pg->pg_flags |= BWN_PHY_G_FLAG_RADIOCTX_VALID;
2452 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover | 0x008c);
2453 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval & 0xff73);
2454}
2455
2456static int
2457bwn_phy_g_switch_channel(struct bwn_mac *mac, uint32_t newchan)
2458{
2459
2460 if ((newchan < 1) || (newchan > 14))
2461 return (EINVAL);
2462 bwn_phy_g_switch_chan(mac, newchan, 0);
2463
2464 return (0);
2465}
2466
2467static uint32_t
2468bwn_phy_g_get_default_chan(struct bwn_mac *mac)
2469{
2470
2471 return (1);
2472}
2473
2474static void
2475bwn_phy_g_set_antenna(struct bwn_mac *mac, int antenna)
2476{
2477 struct bwn_phy *phy = &mac->mac_phy;
2478 uint64_t hf;
2479 int autodiv = 0;
2480 uint16_t tmp;
2481
2482 if (antenna == BWN_ANTAUTO0 || antenna == BWN_ANTAUTO1)
2483 autodiv = 1;
2484
2485 hf = bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER;
2486 bwn_hf_write(mac, hf);
2487
2488 BWN_PHY_WRITE(mac, BWN_PHY_BBANDCFG,
2489 (BWN_PHY_READ(mac, BWN_PHY_BBANDCFG) & ~BWN_PHY_BBANDCFG_RXANT) |
2490 ((autodiv ? BWN_ANTAUTO1 : antenna)
2491 << BWN_PHY_BBANDCFG_RXANT_SHIFT));
2492
2493 if (autodiv) {
2494 tmp = BWN_PHY_READ(mac, BWN_PHY_ANTDWELL);
2495 if (antenna == BWN_ANTAUTO1)
2496 tmp &= ~BWN_PHY_ANTDWELL_AUTODIV1;
2497 else
2498 tmp |= BWN_PHY_ANTDWELL_AUTODIV1;
2499 BWN_PHY_WRITE(mac, BWN_PHY_ANTDWELL, tmp);
2500 }
2501 tmp = BWN_PHY_READ(mac, BWN_PHY_ANTWRSETT);
2502 if (autodiv)
2503 tmp |= BWN_PHY_ANTWRSETT_ARXDIV;
2504 else
2505 tmp &= ~BWN_PHY_ANTWRSETT_ARXDIV;
2506 BWN_PHY_WRITE(mac, BWN_PHY_ANTWRSETT, tmp);
2507 if (phy->rev >= 2) {
2508 BWN_PHY_WRITE(mac, BWN_PHY_OFDM61,
2509 BWN_PHY_READ(mac, BWN_PHY_OFDM61) | BWN_PHY_OFDM61_10);
2510 BWN_PHY_WRITE(mac, BWN_PHY_DIVSRCHGAINBACK,
2511 (BWN_PHY_READ(mac, BWN_PHY_DIVSRCHGAINBACK) & 0xff00) |
2512 0x15);
2513 if (phy->rev == 2)
2514 BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED, 8);
2515 else
2516 BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED,
2517 (BWN_PHY_READ(mac, BWN_PHY_ADIVRELATED) & 0xff00) |
2518 8);
2519 }
2520 if (phy->rev >= 6)
2521 BWN_PHY_WRITE(mac, BWN_PHY_OFDM9B, 0xdc);
2522
2523 hf |= BWN_HF_UCODE_ANTDIV_HELPER;
2524 bwn_hf_write(mac, hf);
2525}
2526
2527static int
2528bwn_phy_g_im(struct bwn_mac *mac, int mode)
2529{
2530 struct bwn_phy *phy = &mac->mac_phy;
2531 struct bwn_phy_g *pg = &phy->phy_g;
2532
2533 KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2534 KASSERT(mode == BWN_IMMODE_NONE, ("%s: fail", __func__));
2535
2536 if (phy->rev == 0 || !phy->gmode)
2537 return (ENODEV);
2538
2539 pg->pg_aci_wlan_automatic = 0;
2540 return (0);
2541}
2542
2543static int
2544bwn_phy_g_recalc_txpwr(struct bwn_mac *mac, int ignore_tssi)
2545{
2546 struct bwn_phy *phy = &mac->mac_phy;
2547 struct bwn_phy_g *pg = &phy->phy_g;
2548 struct bwn_softc *sc = mac->mac_sc;
2549 unsigned int tssi;
2550 int cck, ofdm;
2551 int power;
2552 int rfatt, bbatt;
2553 unsigned int max;
2554
2555 KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2556
2557 cck = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_CCK);
2558 ofdm = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_OFDM_G);
2559 if (cck < 0 && ofdm < 0) {
2560 if (ignore_tssi == 0)
2561 return (BWN_TXPWR_RES_DONE);
2562 cck = 0;
2563 ofdm = 0;
2564 }
2565 tssi = (cck < 0) ? ofdm : ((ofdm < 0) ? cck : (cck + ofdm) / 2);
2566 if (pg->pg_avgtssi != 0xff)
2567 tssi = (tssi + pg->pg_avgtssi) / 2;
2568 pg->pg_avgtssi = tssi;
2569 KASSERT(tssi < BWN_TSSI_MAX, ("%s:%d: fail", __func__, __LINE__));
2570
2571 max = siba_sprom_get_maxpwr_bg(sc->sc_dev);
2572 if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
2573 max -= 3;
2574 if (max >= 120) {
2575 device_printf(sc->sc_dev, "invalid max TX-power value\n");
2576 max = 80;
2577 siba_sprom_set_maxpwr_bg(sc->sc_dev, max);
2578 }
2579
2580 power = MIN(MAX((phy->txpower < 0) ? 0 : (phy->txpower << 2), 0), max) -
2581 (pg->pg_tssi2dbm[MIN(MAX(pg->pg_idletssi - pg->pg_curtssi +
2582 tssi, 0x00), 0x3f)]);
2583 if (power == 0)
2584 return (BWN_TXPWR_RES_DONE);
2585
2586 rfatt = -((power + 7) / 8);
2587 bbatt = (-(power / 2)) - (4 * rfatt);
2588 if ((rfatt == 0) && (bbatt == 0))
2589 return (BWN_TXPWR_RES_DONE);
2590 pg->pg_bbatt_delta = bbatt;
2591 pg->pg_rfatt_delta = rfatt;
2592 return (BWN_TXPWR_RES_NEED_ADJUST);
2593}
2594
2595static void
2596bwn_phy_g_set_txpwr(struct bwn_mac *mac)
2597{
2598 struct bwn_phy *phy = &mac->mac_phy;
2599 struct bwn_phy_g *pg = &phy->phy_g;
2600 struct bwn_softc *sc = mac->mac_sc;
2601 int rfatt, bbatt;
2602 uint8_t txctl;
2603
2604 bwn_mac_suspend(mac);
2605
2606 BWN_ASSERT_LOCKED(sc);
2607
2608 bbatt = pg->pg_bbatt.att;
2609 bbatt += pg->pg_bbatt_delta;
2610 rfatt = pg->pg_rfatt.att;
2611 rfatt += pg->pg_rfatt_delta;
2612
2613 bwn_phy_g_setatt(mac, &bbatt, &rfatt);
2614 txctl = pg->pg_txctl;
2615 if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 2)) {
2616 if (rfatt <= 1) {
2617 if (txctl == 0) {
2618 txctl = BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX;
2619 rfatt += 2;
2620 bbatt += 2;
2621 } else if (siba_sprom_get_bf_lo(sc->sc_dev) &
2622 BWN_BFL_PACTRL) {
2623 bbatt += 4 * (rfatt - 2);
2624 rfatt = 2;
2625 }
2626 } else if (rfatt > 4 && txctl) {
2627 txctl = 0;
2628 if (bbatt < 3) {
2629 rfatt -= 3;
2630 bbatt += 2;
2631 } else {
2632 rfatt -= 2;
2633 bbatt -= 2;
2634 }
2635 }
2636 }
2637 pg->pg_txctl = txctl;
2638 bwn_phy_g_setatt(mac, &bbatt, &rfatt);
2639 pg->pg_rfatt.att = rfatt;
2640 pg->pg_bbatt.att = bbatt;
2641
2642 DPRINTF(sc, BWN_DEBUG_TXPOW, "%s: adjust TX power\n", __func__);
2643
2644 bwn_phy_lock(mac);
2645 bwn_rf_lock(mac);
2646 bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
2647 pg->pg_txctl);
2648 bwn_rf_unlock(mac);
2649 bwn_phy_unlock(mac);
2650
2651 bwn_mac_enable(mac);
2652}
2653
2654static void
2655bwn_phy_g_task_15s(struct bwn_mac *mac)
2656{
2657 struct bwn_phy *phy = &mac->mac_phy;
2658 struct bwn_phy_g *pg = &phy->phy_g;
2659 struct bwn_softc *sc = mac->mac_sc;
2660 struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2661 unsigned long expire, now;
2662 struct bwn_lo_calib *cal, *tmp;
2663 uint8_t expired = 0;
2664
2665 bwn_mac_suspend(mac);
2666
2667 if (lo == NULL)
2668 goto fail;
2669
2670 BWN_GETTIME(now);
2671 if (bwn_has_hwpctl(mac)) {
2672 expire = now - BWN_LO_PWRVEC_EXPIRE;
2673 if (time_before(lo->pwr_vec_read_time, expire)) {
2674 bwn_lo_get_powervector(mac);
2675 bwn_phy_g_dc_lookup_init(mac, 0);
2676 }
2677 goto fail;
2678 }
2679
2680 expire = now - BWN_LO_CALIB_EXPIRE;
2681 TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
2682 if (!time_before(cal->calib_time, expire))
2683 continue;
2684 if (BWN_BBATTCMP(&cal->bbatt, &pg->pg_bbatt) &&
2685 BWN_RFATTCMP(&cal->rfatt, &pg->pg_rfatt)) {
2686 KASSERT(!expired, ("%s:%d: fail", __func__, __LINE__));
2687 expired = 1;
2688 }
2689
2690 DPRINTF(sc, BWN_DEBUG_LO, "expired BB %u RF %u %u I %d Q %d\n",
2691 cal->bbatt.att, cal->rfatt.att, cal->rfatt.padmix,
2692 cal->ctl.i, cal->ctl.q);
2693
2694 TAILQ_REMOVE(&lo->calib_list, cal, list);
2695 free(cal, M_DEVBUF);
2696 }
2697 if (expired || TAILQ_EMPTY(&lo->calib_list)) {
2698 cal = bwn_lo_calibset(mac, &pg->pg_bbatt,
2699 &pg->pg_rfatt);
2700 if (cal == NULL) {
2701 device_printf(sc->sc_dev,
2702 "failed to recalibrate LO\n");
2703 goto fail;
2704 }
2705 TAILQ_INSERT_TAIL(&lo->calib_list, cal, list);
2706 bwn_lo_write(mac, &cal->ctl);
2707 }
2708
2709fail:
2710 bwn_mac_enable(mac);
2711}
2712
2713static void
2714bwn_phy_g_task_60s(struct bwn_mac *mac)
2715{
2716 struct bwn_phy *phy = &mac->mac_phy;
2717 struct bwn_softc *sc = mac->mac_sc;
2718 uint8_t old = phy->chan;
2719
2720 if (!(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI))
2721 return;
2722
2723 bwn_mac_suspend(mac);
2724 bwn_nrssi_slope_11g(mac);
2725 if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 8)) {
2726 bwn_switch_channel(mac, (old >= 8) ? 1 : 13);
2727 bwn_switch_channel(mac, old);
2728 }
2729 bwn_mac_enable(mac);
2730}
2731
2732static void
2733bwn_phy_switch_analog(struct bwn_mac *mac, int on)
2734{
2735
2736 BWN_WRITE_2(mac, BWN_PHY0, on ? 0 : 0xf4);
2737}
2738
2739static int
2740bwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
2741 const struct ieee80211_bpf_params *params)
2742{
2743 struct ieee80211com *ic = ni->ni_ic;
2744 struct ifnet *ifp = ic->ic_ifp;
2745 struct bwn_softc *sc = ifp->if_softc;
2746 struct bwn_mac *mac = sc->sc_curmac;
2747
2748 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
2749 mac->mac_status < BWN_MAC_STATUS_STARTED) {
2750 ieee80211_free_node(ni);
2751 m_freem(m);
2752 return (ENETDOWN);
2753 }
2754
2755 BWN_LOCK(sc);
2756 if (bwn_tx_isfull(sc, m)) {
2757 ieee80211_free_node(ni);
2758 m_freem(m);
2759 ifp->if_oerrors++;
2760 BWN_UNLOCK(sc);
2761 return (ENOBUFS);
2762 }
2763
2764 if (bwn_tx_start(sc, ni, m) != 0) {
2765 if (ni != NULL)
2766 ieee80211_free_node(ni);
2767 ifp->if_oerrors++;
2768 }
2769 sc->sc_watchdog_timer = 5;
2770 BWN_UNLOCK(sc);
2771 return (0);
2772}
2773
2774/*
2775 * Setup driver-specific state for a newly associated node.
2776 * Note that we're called also on a re-associate, the isnew
2777 * param tells us if this is the first time or not.
2778 */
2779static void
2780bwn_newassoc(struct ieee80211_node *ni, int isnew)
2781{
2782 struct ieee80211vap *vap = ni->ni_vap;
2783
2784 ieee80211_amrr_node_init(&BWN_VAP(vap)->bv_amrr,
2785 &BWN_NODE(ni)->bn_amn, ni);
2786}
2787
2788/*
2789 * Callback from the 802.11 layer to update the slot time
2790 * based on the current setting. We use it to notify the
2791 * firmware of ERP changes and the f/w takes care of things
2792 * like slot time and preamble.
2793 */
2794static void
2795bwn_updateslot(struct ifnet *ifp)
2796{
2797 struct bwn_softc *sc = ifp->if_softc;
2798 struct ieee80211com *ic = ifp->if_l2com;
2799 struct bwn_mac *mac;
2800
2801 BWN_LOCK(sc);
2802 if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
2803 mac = (struct bwn_mac *)sc->sc_curmac;
2804 bwn_set_slot_time(mac,
2805 (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20);
2806 }
2807 BWN_UNLOCK(sc);
2808}
2809
2810/*
2811 * Callback from the 802.11 layer after a promiscuous mode change.
2812 * Note this interface does not check the operating mode as this
2813 * is an internal callback and we are expected to honor the current
2814 * state (e.g. this is used for setting the interface in promiscuous
2815 * mode when operating in hostap mode to do ACS).
2816 */
2817static void
2818bwn_update_promisc(struct ifnet *ifp)
2819{
2820 struct bwn_softc *sc = ifp->if_softc;
2821 struct bwn_mac *mac = sc->sc_curmac;
2822
2823 BWN_LOCK(sc);
2824 mac = sc->sc_curmac;
2825 if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2826 if (ifp->if_flags & IFF_PROMISC)
2827 sc->sc_filters |= BWN_MACCTL_PROMISC;
2828 else
2829 sc->sc_filters &= ~BWN_MACCTL_PROMISC;
2830 bwn_set_opmode(mac);
2831 }
2832 BWN_UNLOCK(sc);
2833}
2834
2835/*
2836 * Callback from the 802.11 layer to update WME parameters.
2837 */
2838static int
2839bwn_wme_update(struct ieee80211com *ic)
2840{
2841 struct bwn_softc *sc = ic->ic_ifp->if_softc;
2842 struct bwn_mac *mac = sc->sc_curmac;
2843 struct wmeParams *wmep;
2844 int i;
2845
2846 BWN_LOCK(sc);
2847 mac = sc->sc_curmac;
2848 if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2849 bwn_mac_suspend(mac);
2850 for (i = 0; i < N(sc->sc_wmeParams); i++) {
2851 wmep = &ic->ic_wme.wme_chanParams.cap_wmeParams[i];
2852 bwn_wme_loadparams(mac, wmep, bwn_wme_shm_offsets[i]);
2853 }
2854 bwn_mac_enable(mac);
2855 }
2856 BWN_UNLOCK(sc);
2857 return (0);
2858}
2859
2860static struct ieee80211_node *
2861bwn_node_alloc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN])
2862{
2863 struct ieee80211com *ic = vap->iv_ic;
2864 struct bwn_softc *sc = ic->ic_ifp->if_softc;
2865 const size_t space = sizeof(struct bwn_node);
2866 struct bwn_node *bn;
2867
2868 bn = malloc(space, M_80211_NODE, M_NOWAIT|M_ZERO);
2869 if (bn == NULL) {
2870 /* XXX stat+msg */
2871 return (NULL);
2872 }
2873 DPRINTF(sc, BWN_DEBUG_NODE, "%s: bn %p\n", __func__, bn);
2874 return (&bn->bn_node);
2875}
2876
2877static void
2878bwn_node_cleanup(struct ieee80211_node *ni)
2879{
2880 struct ieee80211com *ic = ni->ni_ic;
2881 struct bwn_softc *sc = ic->ic_ifp->if_softc;
2882
2883 sc->sc_node_cleanup(ni);
2884}
2885
2886static void
2887bwn_scan_start(struct ieee80211com *ic)
2888{
2889 struct ifnet *ifp = ic->ic_ifp;
2890 struct bwn_softc *sc = ifp->if_softc;
2891 struct bwn_mac *mac;
2892
2893 BWN_LOCK(sc);
2894 mac = sc->sc_curmac;
2895 if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2896 sc->sc_filters |= BWN_MACCTL_BEACON_PROMISC;
2897 bwn_set_opmode(mac);
2898 /* disable CFP update during scan */
2899 bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_SKIP_CFP_UPDATE);
2900 }
2901 BWN_UNLOCK(sc);
2902}
2903
2904static void
2905bwn_scan_end(struct ieee80211com *ic)
2906{
2907 struct ifnet *ifp = ic->ic_ifp;
2908 struct bwn_softc *sc = ifp->if_softc;
2909 struct bwn_mac *mac;
2910
2911 BWN_LOCK(sc);
2912 mac = sc->sc_curmac;
2913 if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2914 sc->sc_filters &= ~BWN_MACCTL_BEACON_PROMISC;
2915 bwn_set_opmode(mac);
2916 bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_SKIP_CFP_UPDATE);
2917 }
2918 BWN_UNLOCK(sc);
2919}
2920
2921static void
2922bwn_set_channel(struct ieee80211com *ic)
2923{
2924 struct ifnet *ifp = ic->ic_ifp;
2925 struct bwn_softc *sc = ifp->if_softc;
2926 struct bwn_mac *mac = sc->sc_curmac;
2927 struct bwn_phy *phy = &mac->mac_phy;
2928 int chan, error;
2929
2930 BWN_LOCK(sc);
2931
2932 error = bwn_switch_band(sc, ic->ic_curchan);
2933 if (error)
2934 goto fail;;
2935 bwn_mac_suspend(mac);
2936 bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
2937 chan = ieee80211_chan2ieee(ic, ic->ic_curchan);
2938 if (chan != phy->chan)
2939 bwn_switch_channel(mac, chan);
2940
2941 /* TX power level */
2942 if (ic->ic_curchan->ic_maxpower != 0 &&
2943 ic->ic_curchan->ic_maxpower != phy->txpower) {
2944 phy->txpower = ic->ic_curchan->ic_maxpower / 2;
2945 bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME |
2946 BWN_TXPWR_IGNORE_TSSI);
2947 }
2948
2949 bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
2950 if (phy->set_antenna)
2951 phy->set_antenna(mac, BWN_ANT_DEFAULT);
2952
2953 if (sc->sc_rf_enabled != phy->rf_on) {
2954 if (sc->sc_rf_enabled) {
2955 bwn_rf_turnon(mac);
2956 if (!(mac->mac_flags & BWN_MAC_FLAG_RADIO_ON))
2957 device_printf(sc->sc_dev,
2958 "please turns on the RF switch\n");
2959 } else
2960 bwn_rf_turnoff(mac);
2961 }
2962
2963 bwn_mac_enable(mac);
2964
2965fail:
2966 /*
2967 * Setup radio tap channel freq and flags
2968 */
2969 sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq =
2970 htole16(ic->ic_curchan->ic_freq);
2971 sc->sc_tx_th.wt_chan_flags = sc->sc_rx_th.wr_chan_flags =
2972 htole16(ic->ic_curchan->ic_flags & 0xffff);
2973
2974 BWN_UNLOCK(sc);
2975}
2976
2977static struct ieee80211vap *
2978bwn_vap_create(struct ieee80211com *ic,
2979 const char name[IFNAMSIZ], int unit, int opmode, int flags,
2980 const uint8_t bssid[IEEE80211_ADDR_LEN],
2981 const uint8_t mac0[IEEE80211_ADDR_LEN])
2982{
2983 struct ifnet *ifp = ic->ic_ifp;
2984 struct bwn_softc *sc = ifp->if_softc;
2985 struct ieee80211vap *vap;
2986 struct bwn_vap *bvp;
2987 uint8_t mac[IEEE80211_ADDR_LEN];
2988
2989 IEEE80211_ADDR_COPY(mac, mac0);
2990 switch (opmode) {
2991 case IEEE80211_M_HOSTAP:
2992 case IEEE80211_M_MBSS:
2993 case IEEE80211_M_STA:
2994 case IEEE80211_M_WDS:
2995 case IEEE80211_M_MONITOR:
2996 case IEEE80211_M_IBSS:
2997 case IEEE80211_M_AHDEMO:
2998 break;
2999 default:
3000 return (NULL);
3001 }
3002
3003 IEEE80211_ADDR_COPY(sc->sc_macaddr, mac0);
3004
3005 bvp = (struct bwn_vap *) malloc(sizeof(struct bwn_vap),
3006 M_80211_VAP, M_NOWAIT | M_ZERO);
3007 if (bvp == NULL) {
3008 device_printf(sc->sc_dev, "failed to allocate a buffer\n");
3009 return (NULL);
3010 }
3011 vap = &bvp->bv_vap;
3012 ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
3013 IEEE80211_ADDR_COPY(vap->iv_myaddr, mac);
3014 /* override with driver methods */
3015 bvp->bv_newstate = vap->iv_newstate;
3016 vap->iv_newstate = bwn_newstate;
3017
3018 /* override max aid so sta's cannot assoc when we're out of sta id's */
3019 vap->iv_max_aid = BWN_STAID_MAX;
3020
3021 ieee80211_amrr_init(&bvp->bv_amrr, vap,
3022 IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD,
3023 IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD,
3024 500 /*ms*/);
3025
3026 /* complete setup */
3027 ieee80211_vap_attach(vap, ieee80211_media_change,
3028 ieee80211_media_status);
3029 return (vap);
3030}
3031
3032static void
3033bwn_vap_delete(struct ieee80211vap *vap)
3034{
3035 struct bwn_vap *bvp = BWN_VAP(vap);
3036
3037 ieee80211_amrr_cleanup(&bvp->bv_amrr);
3038 ieee80211_vap_detach(vap);
3039 free(bvp, M_80211_VAP);
3040}
3041
3042static void
3043bwn_init(void *arg)
3044{
3045 struct bwn_softc *sc = arg;
3046 struct ifnet *ifp = sc->sc_ifp;
3047 struct ieee80211com *ic = ifp->if_l2com;
3048 int error = 0;
3049
3050 DPRINTF(sc, BWN_DEBUG_ANY, "%s: if_flags 0x%x\n",
3051 __func__, ifp->if_flags);
3052
3053 BWN_LOCK(sc);
3054 error = bwn_init_locked(sc);
3055 BWN_UNLOCK(sc);
3056
3057 if (error == 0)
3058 ieee80211_start_all(ic); /* start all vap's */
3059}
3060
3061static int
3062bwn_init_locked(struct bwn_softc *sc)
3063{
3064 struct bwn_mac *mac;
3065 struct ifnet *ifp = sc->sc_ifp;
3066 int error;
3067
3068 BWN_ASSERT_LOCKED(sc);
3069
3070 bzero(sc->sc_bssid, IEEE80211_ADDR_LEN);
3071 sc->sc_flags |= BWN_FLAG_NEED_BEACON_TP;
3072 sc->sc_filters = 0;
3073 bwn_wme_clear(sc);
3074 sc->sc_beacons[0] = sc->sc_beacons[1] = 0;
3075 sc->sc_rf_enabled = 1;
3076
3077 mac = sc->sc_curmac;
3078 if (mac->mac_status == BWN_MAC_STATUS_UNINIT) {
3079 error = bwn_core_init(mac);
3080 if (error != 0)
3081 return (error);
3082 }
3083 if (mac->mac_status == BWN_MAC_STATUS_INITED)
3084 bwn_core_start(mac);
3085
3086 bwn_set_opmode(mac);
3087 bwn_set_pretbtt(mac);
3088 bwn_spu_setdelay(mac, 0);
3089 bwn_set_macaddr(mac);
3090
3091 ifp->if_drv_flags |= IFF_DRV_RUNNING;
3092 callout_reset(&sc->sc_rfswitch_ch, hz, bwn_rfswitch, sc);
3093 callout_reset(&sc->sc_watchdog_ch, hz, bwn_watchdog, sc);
3094
3095 return (0);
3096}
3097
3098static void
3099bwn_stop(struct bwn_softc *sc, int statechg)
3100{
3101
3102 BWN_LOCK(sc);
3103 bwn_stop_locked(sc, statechg);
3104 BWN_UNLOCK(sc);
3105}
3106
3107static void
3108bwn_stop_locked(struct bwn_softc *sc, int statechg)
3109{
3110 struct bwn_mac *mac = sc->sc_curmac;
3111 struct ifnet *ifp = sc->sc_ifp;
3112
3113 BWN_ASSERT_LOCKED(sc);
3114
3115 if (mac->mac_status >= BWN_MAC_STATUS_INITED) {
3116 /* XXX FIXME opmode not based on VAP */
3117 bwn_set_opmode(mac);
3118 bwn_set_macaddr(mac);
3119 }
3120
3121 if (mac->mac_status >= BWN_MAC_STATUS_STARTED)
3122 bwn_core_stop(mac);
3123
3124 callout_stop(&sc->sc_led_blink_ch);
3125 sc->sc_led_blinking = 0;
3126
3127 bwn_core_exit(mac);
3128 sc->sc_rf_enabled = 0;
3129
3130 ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
3131}
3132
3133static void
3134bwn_wme_clear(struct bwn_softc *sc)
3135{
3136#define MS(_v, _f) (((_v) & _f) >> _f##_S)
3137 struct wmeParams *p;
3138 unsigned int i;
3139
3140 KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
3141 ("%s:%d: fail", __func__, __LINE__));
3142
3143 for (i = 0; i < N(sc->sc_wmeParams); i++) {
3144 p = &(sc->sc_wmeParams[i]);
3145
3146 switch (bwn_wme_shm_offsets[i]) {
3147 case BWN_WME_VOICE:
3148 p->wmep_txopLimit = 0;
3149 p->wmep_aifsn = 2;
3150 /* XXX FIXME: log2(cwmin) */
3151 p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3152 p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3153 break;
3154 case BWN_WME_VIDEO:
3155 p->wmep_txopLimit = 0;
3156 p->wmep_aifsn = 2;
3157 /* XXX FIXME: log2(cwmin) */
3158 p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3159 p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3160 break;
3161 case BWN_WME_BESTEFFORT:
3162 p->wmep_txopLimit = 0;
3163 p->wmep_aifsn = 3;
3164 /* XXX FIXME: log2(cwmin) */
3165 p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3166 p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3167 break;
3168 case BWN_WME_BACKGROUND:
3169 p->wmep_txopLimit = 0;
3170 p->wmep_aifsn = 7;
3171 /* XXX FIXME: log2(cwmin) */
3172 p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3173 p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3174 break;
3175 default:
3176 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3177 }
3178 }
3179}
3180
3181static int
3182bwn_core_init(struct bwn_mac *mac)
3183{
3184 struct bwn_softc *sc = mac->mac_sc;
3185 uint64_t hf;
3186 int error;
3187
3188 KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3189 ("%s:%d: fail", __func__, __LINE__));
3190
3191 siba_powerup(sc->sc_dev, 0);
3192 if (!siba_dev_isup(sc->sc_dev))
3193 bwn_reset_core(mac,
3194 mac->mac_phy.gmode ? BWN_TGSLOW_SUPPORT_G : 0);
3195
3196 mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
3197 mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
3198 mac->mac_phy.hwpctl = (bwn_hwpctl) ? 1 : 0;
3199 BWN_GETTIME(mac->mac_phy.nexttime);
3200 mac->mac_phy.txerrors = BWN_TXERROR_MAX;
3201 bzero(&mac->mac_stats, sizeof(mac->mac_stats));
3202 mac->mac_stats.link_noise = -95;
3203 mac->mac_reason_intr = 0;
3204 bzero(mac->mac_reason, sizeof(mac->mac_reason));
3205 mac->mac_intr_mask = BWN_INTR_MASKTEMPLATE;
3206#ifdef BWN_DEBUG
3207 if (sc->sc_debug & BWN_DEBUG_XMIT)
3208 mac->mac_intr_mask &= ~BWN_INTR_PHY_TXERR;
3209#endif
3210 mac->mac_suspended = 1;
3211 mac->mac_task_state = 0;
3212 memset(&mac->mac_noise, 0, sizeof(mac->mac_noise));
3213
3214 mac->mac_phy.init_pre(mac);
3215
3216 siba_pcicore_intr(sc->sc_dev);
3217
3218 siba_fix_imcfglobug(sc->sc_dev);
3219 bwn_bt_disable(mac);
3220 if (mac->mac_phy.prepare_hw) {
3221 error = mac->mac_phy.prepare_hw(mac);
3222 if (error)
3223 goto fail0;
3224 }
3225 error = bwn_chip_init(mac);
3226 if (error)
3227 goto fail0;
3228 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_COREREV,
3229 siba_get_revid(sc->sc_dev));
3230 hf = bwn_hf_read(mac);
3231 if (mac->mac_phy.type == BWN_PHYTYPE_G) {
3232 hf |= BWN_HF_GPHY_SYM_WORKAROUND;
3233 if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
3234 hf |= BWN_HF_PAGAINBOOST_OFDM_ON;
3235 if (mac->mac_phy.rev == 1)
3236 hf |= BWN_HF_GPHY_DC_CANCELFILTER;
3237 }
3238 if (mac->mac_phy.rf_ver == 0x2050) {
3239 if (mac->mac_phy.rf_rev < 6)
3240 hf |= BWN_HF_FORCE_VCO_RECALC;
3241 if (mac->mac_phy.rf_rev == 6)
3242 hf |= BWN_HF_4318_TSSI;
3243 }
3244 if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW)
3245 hf |= BWN_HF_SLOWCLOCK_REQ_OFF;
3246 if ((siba_get_type(sc->sc_dev) == SIBA_TYPE_PCI) &&
3247 (siba_get_pcicore_revid(sc->sc_dev) <= 10))
3248 hf |= BWN_HF_PCI_SLOWCLOCK_WORKAROUND;
3249 hf &= ~BWN_HF_SKIP_CFP_UPDATE;
3250 bwn_hf_write(mac, hf);
3251
3252 bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
3253 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SHORT_RETRY_FALLBACK, 3);
3254 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_LONG_RETRY_FALLBACK, 2);
3255 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_MAXTIME, 1);
3256
3257 bwn_rate_init(mac);
3258 bwn_set_phytxctl(mac);
3259
3260 bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MIN,
3261 (mac->mac_phy.type == BWN_PHYTYPE_B) ? 0x1f : 0xf);
3262 bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MAX, 0x3ff);
3263
3264 if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
3265 bwn_pio_init(mac);
3266 else
3267 bwn_dma_init(mac);
3268 if (error)
3269 goto fail1;
3270 bwn_wme_init(mac);
3271 bwn_spu_setdelay(mac, 1);
3272 bwn_bt_enable(mac);
3273
3274 siba_powerup(sc->sc_dev,
3275 !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW));
3276 bwn_set_macaddr(mac);
3277 bwn_crypt_init(mac);
3278
3279 /* XXX LED initializatin */
3280
3281 mac->mac_status = BWN_MAC_STATUS_INITED;
3282
3283 return (error);
3284
3285fail1:
3286 bwn_chip_exit(mac);
3287fail0:
3288 siba_powerdown(sc->sc_dev);
3289 KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3290 ("%s:%d: fail", __func__, __LINE__));
3291 return (error);
3292}
3293
3294static void
3295bwn_core_start(struct bwn_mac *mac)
3296{
3297 struct bwn_softc *sc = mac->mac_sc;
3298 uint32_t tmp;
3299
3300 KASSERT(mac->mac_status == BWN_MAC_STATUS_INITED,
3301 ("%s:%d: fail", __func__, __LINE__));
3302
3303 if (siba_get_revid(sc->sc_dev) < 5)
3304 return;
3305
3306 while (1) {
3307 tmp = BWN_READ_4(mac, BWN_XMITSTAT_0);
3308 if (!(tmp & 0x00000001))
3309 break;
3310 tmp = BWN_READ_4(mac, BWN_XMITSTAT_1);
3311 }
3312
3313 bwn_mac_enable(mac);
3314 BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
3315 callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
3316
3317 mac->mac_status = BWN_MAC_STATUS_STARTED;
3318}
3319
3320static void
3321bwn_core_exit(struct bwn_mac *mac)
3322{
3323 struct bwn_softc *sc = mac->mac_sc;
3324 uint32_t macctl;
3325
3326 BWN_ASSERT_LOCKED(mac->mac_sc);
3327
3328 KASSERT(mac->mac_status <= BWN_MAC_STATUS_INITED,
3329 ("%s:%d: fail", __func__, __LINE__));
3330
3331 if (mac->mac_status != BWN_MAC_STATUS_INITED)
3332 return;
3333 mac->mac_status = BWN_MAC_STATUS_UNINIT;
3334
3335 macctl = BWN_READ_4(mac, BWN_MACCTL);
3336 macctl &= ~BWN_MACCTL_MCODE_RUN;
3337 macctl |= BWN_MACCTL_MCODE_JMP0;
3338 BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3339
3340 bwn_dma_stop(mac);
3341 bwn_pio_stop(mac);
3342 bwn_chip_exit(mac);
3343 mac->mac_phy.switch_analog(mac, 0);
3344 siba_dev_down(sc->sc_dev, 0);
3345 siba_powerdown(sc->sc_dev);
3346}
3347
3348static void
3349bwn_bt_disable(struct bwn_mac *mac)
3350{
3351 struct bwn_softc *sc = mac->mac_sc;
3352
3353 (void)sc;
3354 /* XXX do nothing yet */
3355}
3356
3357static int
3358bwn_chip_init(struct bwn_mac *mac)
3359{
3360 struct bwn_softc *sc = mac->mac_sc;
3361 struct bwn_phy *phy = &mac->mac_phy;
3362 uint32_t macctl;
3363 int error;
3364
3365 macctl = BWN_MACCTL_IHR_ON | BWN_MACCTL_SHM_ON | BWN_MACCTL_STA;
3366 if (phy->gmode)
3367 macctl |= BWN_MACCTL_GMODE;
3368 BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3369
3370 error = bwn_fw_fillinfo(mac);
3371 if (error)
3372 return (error);
3373 error = bwn_fw_loaducode(mac);
3374 if (error)
3375 return (error);
3376
3377 error = bwn_gpio_init(mac);
3378 if (error)
3379 return (error);
3380
3381 error = bwn_fw_loadinitvals(mac);
3382 if (error) {
3383 siba_gpio_set(sc->sc_dev, 0);
3384 return (error);
3385 }
3386 phy->switch_analog(mac, 1);
3387 error = bwn_phy_init(mac);
3388 if (error) {
3389 siba_gpio_set(sc->sc_dev, 0);
3390 return (error);
3391 }
3392 if (phy->set_im)
3393 phy->set_im(mac, BWN_IMMODE_NONE);
3394 if (phy->set_antenna)
3395 phy->set_antenna(mac, BWN_ANT_DEFAULT);
3396 bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
3397
3398 if (phy->type == BWN_PHYTYPE_B)
3399 BWN_WRITE_2(mac, 0x005e, BWN_READ_2(mac, 0x005e) | 0x0004);
3400 BWN_WRITE_4(mac, 0x0100, 0x01000000);
3401 if (siba_get_revid(sc->sc_dev) < 5)
3402 BWN_WRITE_4(mac, 0x010c, 0x01000000);
3403
3404 BWN_WRITE_4(mac, BWN_MACCTL,
3405 BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_STA);
3406 BWN_WRITE_4(mac, BWN_MACCTL,
3407 BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_STA);
3408 bwn_shm_write_2(mac, BWN_SHARED, 0x0074, 0x0000);
3409
3410 bwn_set_opmode(mac);
3411 if (siba_get_revid(sc->sc_dev) < 3) {
3412 BWN_WRITE_2(mac, 0x060e, 0x0000);
3413 BWN_WRITE_2(mac, 0x0610, 0x8000);
3414 BWN_WRITE_2(mac, 0x0604, 0x0000);
3415 BWN_WRITE_2(mac, 0x0606, 0x0200);
3416 } else {
3417 BWN_WRITE_4(mac, 0x0188, 0x80000000);
3418 BWN_WRITE_4(mac, 0x018c, 0x02000000);
3419 }
3420 BWN_WRITE_4(mac, BWN_INTR_REASON, 0x00004000);
3421 BWN_WRITE_4(mac, BWN_DMA0_INTR_MASK, 0x0001dc00);
3422 BWN_WRITE_4(mac, BWN_DMA1_INTR_MASK, 0x0000dc00);
3423 BWN_WRITE_4(mac, BWN_DMA2_INTR_MASK, 0x0000dc00);
3424 BWN_WRITE_4(mac, BWN_DMA3_INTR_MASK, 0x0001dc00);
3425 BWN_WRITE_4(mac, BWN_DMA4_INTR_MASK, 0x0000dc00);
3426 BWN_WRITE_4(mac, BWN_DMA5_INTR_MASK, 0x0000dc00);
3427 siba_write_4(sc->sc_dev, SIBA_TGSLOW,
3428 siba_read_4(sc->sc_dev, SIBA_TGSLOW) | 0x00100000);
3429 BWN_WRITE_2(mac, BWN_POWERUP_DELAY, siba_get_cc_powerdelay(sc->sc_dev));
3430 return (error);
3431}
3432
3433/* read hostflags */
3434static uint64_t
3435bwn_hf_read(struct bwn_mac *mac)
3436{
3437 uint64_t ret;
3438
3439 ret = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFHI);
3440 ret <<= 16;
3441 ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFMI);
3442 ret <<= 16;
3443 ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO);
3444 return (ret);
3445}
3446
3447static void
3448bwn_hf_write(struct bwn_mac *mac, uint64_t value)
3449{
3450
3451 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFLO,
3452 (value & 0x00000000ffffull));
3453 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFMI,
3454 (value & 0x0000ffff0000ull) >> 16);
3455 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFHI,
3456 (value & 0xffff00000000ULL) >> 32);
3457}
3458
3459static void
3460bwn_set_txretry(struct bwn_mac *mac, int s, int l)
3461{
3462
3463 bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_SHORT_RETRY, MIN(s, 0xf));
3464 bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_LONG_RETRY, MIN(l, 0xf));
3465}
3466
3467static void
3468bwn_rate_init(struct bwn_mac *mac)
3469{
3470
3471 switch (mac->mac_phy.type) {
3472 case BWN_PHYTYPE_A:
3473 case BWN_PHYTYPE_G:
3474 case BWN_PHYTYPE_LP:
3475 case BWN_PHYTYPE_N:
3476 bwn_rate_write(mac, BWN_OFDM_RATE_6MB, 1);
3477 bwn_rate_write(mac, BWN_OFDM_RATE_12MB, 1);
3478 bwn_rate_write(mac, BWN_OFDM_RATE_18MB, 1);
3479 bwn_rate_write(mac, BWN_OFDM_RATE_24MB, 1);
3480 bwn_rate_write(mac, BWN_OFDM_RATE_36MB, 1);
3481 bwn_rate_write(mac, BWN_OFDM_RATE_48MB, 1);
3482 bwn_rate_write(mac, BWN_OFDM_RATE_54MB, 1);
3483 if (mac->mac_phy.type == BWN_PHYTYPE_A)
3484 break;
3485 /* FALLTHROUGH */
3486 case BWN_PHYTYPE_B:
3487 bwn_rate_write(mac, BWN_CCK_RATE_1MB, 0);
3488 bwn_rate_write(mac, BWN_CCK_RATE_2MB, 0);
3489 bwn_rate_write(mac, BWN_CCK_RATE_5MB, 0);
3490 bwn_rate_write(mac, BWN_CCK_RATE_11MB, 0);
3491 break;
3492 default:
3493 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3494 }
3495}
3496
3497static void
3498bwn_rate_write(struct bwn_mac *mac, uint16_t rate, int ofdm)
3499{
3500 uint16_t offset;
3501
3502 if (ofdm) {
3503 offset = 0x480;
3504 offset += (bwn_plcp_getofdm(rate) & 0x000f) * 2;
3505 } else {
3506 offset = 0x4c0;
3507 offset += (bwn_plcp_getcck(rate) & 0x000f) * 2;
3508 }
3509 bwn_shm_write_2(mac, BWN_SHARED, offset + 0x20,
3510 bwn_shm_read_2(mac, BWN_SHARED, offset));
3511}
3512
3513static uint8_t
3514bwn_plcp_getcck(const uint8_t bitrate)
3515{
3516
3517 switch (bitrate) {
3518 case BWN_CCK_RATE_1MB:
3519 return (0x0a);
3520 case BWN_CCK_RATE_2MB:
3521 return (0x14);
3522 case BWN_CCK_RATE_5MB:
3523 return (0x37);
3524 case BWN_CCK_RATE_11MB:
3525 return (0x6e);
3526 }
3527 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3528 return (0);
3529}
3530
3531static uint8_t
3532bwn_plcp_getofdm(const uint8_t bitrate)
3533{
3534
3535 switch (bitrate) {
3536 case BWN_OFDM_RATE_6MB:
3537 return (0xb);
3538 case BWN_OFDM_RATE_9MB:
3539 return (0xf);
3540 case BWN_OFDM_RATE_12MB:
3541 return (0xa);
3542 case BWN_OFDM_RATE_18MB:
3543 return (0xe);
3544 case BWN_OFDM_RATE_24MB:
3545 return (0x9);
3546 case BWN_OFDM_RATE_36MB:
3547 return (0xd);
3548 case BWN_OFDM_RATE_48MB:
3549 return (0x8);
3550 case BWN_OFDM_RATE_54MB:
3551 return (0xc);
3552 }
3553 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3554 return (0);
3555}
3556
3557static void
3558bwn_set_phytxctl(struct bwn_mac *mac)
3559{
3560 uint16_t ctl;
3561
3562 ctl = (BWN_TX_PHY_ENC_CCK | BWN_TX_PHY_ANT01AUTO |
3563 BWN_TX_PHY_TXPWR);
3564 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_BEACON_PHYCTL, ctl);
3565 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, ctl);
3566 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, ctl);
3567}
3568
3569static void
3570bwn_pio_init(struct bwn_mac *mac)
3571{
3572 struct bwn_pio *pio = &mac->mac_method.pio;
3573
3574 BWN_WRITE_4(mac, BWN_MACCTL, BWN_READ_4(mac, BWN_MACCTL)
3575 & ~BWN_MACCTL_BIGENDIAN);
3576 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RX_PADOFFSET, 0);
3577
3578 bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BK], 0);
3579 bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BE], 1);
3580 bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VI], 2);
3581 bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VO], 3);
3582 bwn_pio_set_txqueue(mac, &pio->mcast, 4);
3583 bwn_pio_setupqueue_rx(mac, &pio->rx, 0);
3584}
3585
3586static void
3587bwn_pio_set_txqueue(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3588 int index)
3589{
3590 struct bwn_pio_txpkt *tp;
3591 struct bwn_softc *sc = mac->mac_sc;
3592 unsigned int i;
3593
3594 tq->tq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_TXQOFFSET(mac);
3595 tq->tq_index = index;
3596
3597 tq->tq_free = BWN_PIO_MAX_TXPACKETS;
3598 if (siba_get_revid(sc->sc_dev) >= 8)
3599 tq->tq_size = 1920;
3600 else {
3601 tq->tq_size = bwn_pio_read_2(mac, tq, BWN_PIO_TXQBUFSIZE);
3602 tq->tq_size -= 80;
3603 }
3604
3605 TAILQ_INIT(&tq->tq_pktlist);
3606 for (i = 0; i < N(tq->tq_pkts); i++) {
3607 tp = &(tq->tq_pkts[i]);
3608 tp->tp_index = i;
3609 tp->tp_queue = tq;
3610 TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
3611 }
3612}
3613
3614static uint16_t
3615bwn_pio_idx2base(struct bwn_mac *mac, int index)
3616{
3617 struct bwn_softc *sc = mac->mac_sc;
3618 static const uint16_t bases[] = {
3619 BWN_PIO_BASE0,
3620 BWN_PIO_BASE1,
3621 BWN_PIO_BASE2,
3622 BWN_PIO_BASE3,
3623 BWN_PIO_BASE4,
3624 BWN_PIO_BASE5,
3625 BWN_PIO_BASE6,
3626 BWN_PIO_BASE7,
3627 };
3628 static const uint16_t bases_rev11[] = {
3629 BWN_PIO11_BASE0,
3630 BWN_PIO11_BASE1,
3631 BWN_PIO11_BASE2,
3632 BWN_PIO11_BASE3,
3633 BWN_PIO11_BASE4,
3634 BWN_PIO11_BASE5,
3635 };
3636
3637 if (siba_get_revid(sc->sc_dev) >= 11) {
3638 if (index >= N(bases_rev11))
3639 device_printf(sc->sc_dev, "%s: warning\n", __func__);
3640 return (bases_rev11[index]);
3641 }
3642 if (index >= N(bases))
3643 device_printf(sc->sc_dev, "%s: warning\n", __func__);
3644 return (bases[index]);
3645}
3646
3647static void
3648bwn_pio_setupqueue_rx(struct bwn_mac *mac, struct bwn_pio_rxqueue *prq,
3649 int index)
3650{
3651 struct bwn_softc *sc = mac->mac_sc;
3652
3653 prq->prq_mac = mac;
3654 prq->prq_rev = siba_get_revid(sc->sc_dev);
3655 prq->prq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_RXQOFFSET(mac);
3656 bwn_dma_rxdirectfifo(mac, index, 1);
3657}
3658
3659static void
3660bwn_destroy_pioqueue_tx(struct bwn_pio_txqueue *tq)
3661{
3662 if (tq == NULL)
3663 return;
3664 bwn_pio_cancel_tx_packets(tq);
3665}
3666
3667static void
3668bwn_destroy_queue_tx(struct bwn_pio_txqueue *pio)
3669{
3670
3671 bwn_destroy_pioqueue_tx(pio);
3672}
3673
3674static uint16_t
3675bwn_pio_read_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3676 uint16_t offset)
3677{
3678
3679 return (BWN_READ_2(mac, tq->tq_base + offset));
3680}
3681
3682static void
3683bwn_dma_rxdirectfifo(struct bwn_mac *mac, int idx, uint8_t enable)
3684{
3685 uint32_t ctl;
3686 int type;
3687 uint16_t base;
3688
3689 type = bwn_dma_mask2type(bwn_dma_mask(mac));
3690 base = bwn_dma_base(type, idx);
3691 if (type == BWN_DMA_64BIT) {
3692 ctl = BWN_READ_4(mac, base + BWN_DMA64_RXCTL);
3693 ctl &= ~BWN_DMA64_RXDIRECTFIFO;
3694 if (enable)
3695 ctl |= BWN_DMA64_RXDIRECTFIFO;
3696 BWN_WRITE_4(mac, base + BWN_DMA64_RXCTL, ctl);
3697 } else {
3698 ctl = BWN_READ_4(mac, base + BWN_DMA32_RXCTL);
3699 ctl &= ~BWN_DMA32_RXDIRECTFIFO;
3700 if (enable)
3701 ctl |= BWN_DMA32_RXDIRECTFIFO;
3702 BWN_WRITE_4(mac, base + BWN_DMA32_RXCTL, ctl);
3703 }
3704}
3705
3706static uint64_t
3707bwn_dma_mask(struct bwn_mac *mac)
3708{
3709 uint32_t tmp;
3710 uint16_t base;
3711
3712 tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
3713 if (tmp & SIBA_TGSHIGH_DMA64)
3714 return (BWN_DMA_BIT_MASK(64));
3715 base = bwn_dma_base(0, 0);
3716 BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
3717 tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
3718 if (tmp & BWN_DMA32_TXADDREXT_MASK)
3719 return (BWN_DMA_BIT_MASK(32));
3720
3721 return (BWN_DMA_BIT_MASK(30));
3722}
3723
3724static int
3725bwn_dma_mask2type(uint64_t dmamask)
3726{
3727
3728 if (dmamask == BWN_DMA_BIT_MASK(30))
3729 return (BWN_DMA_30BIT);
3730 if (dmamask == BWN_DMA_BIT_MASK(32))
3731 return (BWN_DMA_32BIT);
3732 if (dmamask == BWN_DMA_BIT_MASK(64))
3733 return (BWN_DMA_64BIT);
3734 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3735 return (BWN_DMA_30BIT);
3736}
3737
3738static void
3739bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *tq)
3740{
3741 struct bwn_pio_txpkt *tp;
3742 unsigned int i;
3743
3744 for (i = 0; i < N(tq->tq_pkts); i++) {
3745 tp = &(tq->tq_pkts[i]);
3746 if (tp->tp_m) {
3747 m_freem(tp->tp_m);
3748 tp->tp_m = NULL;
3749 }
3750 }
3751}
3752
3753static uint16_t
3754bwn_dma_base(int type, int controller_idx)
3755{
3756 static const uint16_t map64[] = {
3757 BWN_DMA64_BASE0,
3758 BWN_DMA64_BASE1,
3759 BWN_DMA64_BASE2,
3760 BWN_DMA64_BASE3,
3761 BWN_DMA64_BASE4,
3762 BWN_DMA64_BASE5,
3763 };
3764 static const uint16_t map32[] = {
3765 BWN_DMA32_BASE0,
3766 BWN_DMA32_BASE1,
3767 BWN_DMA32_BASE2,
3768 BWN_DMA32_BASE3,
3769 BWN_DMA32_BASE4,
3770 BWN_DMA32_BASE5,
3771 };
3772
3773 if (type == BWN_DMA_64BIT) {
3774 KASSERT(controller_idx >= 0 && controller_idx < N(map64),
3775 ("%s:%d: fail", __func__, __LINE__));
3776 return (map64[controller_idx]);
3777 }
3778 KASSERT(controller_idx >= 0 && controller_idx < N(map32),
3779 ("%s:%d: fail", __func__, __LINE__));
3780 return (map32[controller_idx]);
3781}
3782
3783static void
3784bwn_dma_init(struct bwn_mac *mac)
3785{
3786 struct bwn_dma *dma = &mac->mac_method.dma;
3787
3788 /* setup TX DMA channels. */
3789 bwn_dma_setup(dma->wme[WME_AC_BK]);
3790 bwn_dma_setup(dma->wme[WME_AC_BE]);
3791 bwn_dma_setup(dma->wme[WME_AC_VI]);
3792 bwn_dma_setup(dma->wme[WME_AC_VO]);
3793 bwn_dma_setup(dma->mcast);
3794 /* setup RX DMA channel. */
3795 bwn_dma_setup(dma->rx);
3796}
3797
3798static struct bwn_dma_ring *
3799bwn_dma_ringsetup(struct bwn_mac *mac, int controller_index,
3800 int for_tx, int type)
3801{
3802 struct bwn_dma *dma = &mac->mac_method.dma;
3803 struct bwn_dma_ring *dr;
3804 struct bwn_dmadesc_generic *desc;
3805 struct bwn_dmadesc_meta *mt;
3806 struct bwn_softc *sc = mac->mac_sc;
3807 int error, i;
3808
3809 dr = malloc(sizeof(*dr), M_DEVBUF, M_NOWAIT | M_ZERO);
3810 if (dr == NULL)
3811 goto out;
3812 dr->dr_numslots = BWN_RXRING_SLOTS;
3813 if (for_tx)
3814 dr->dr_numslots = BWN_TXRING_SLOTS;
3815
3816 dr->dr_meta = malloc(dr->dr_numslots * sizeof(struct bwn_dmadesc_meta),
3817 M_DEVBUF, M_NOWAIT | M_ZERO);
3818 if (dr->dr_meta == NULL)
3819 goto fail0;
3820
3821 dr->dr_type = type;
3822 dr->dr_mac = mac;
3823 dr->dr_base = bwn_dma_base(type, controller_index);
3824 dr->dr_index = controller_index;
3825 if (type == BWN_DMA_64BIT) {
3826 dr->getdesc = bwn_dma_64_getdesc;
3827 dr->setdesc = bwn_dma_64_setdesc;
3828 dr->start_transfer = bwn_dma_64_start_transfer;
3829 dr->suspend = bwn_dma_64_suspend;
3830 dr->resume = bwn_dma_64_resume;
3831 dr->get_curslot = bwn_dma_64_get_curslot;
3832 dr->set_curslot = bwn_dma_64_set_curslot;
3833 } else {
3834 dr->getdesc = bwn_dma_32_getdesc;
3835 dr->setdesc = bwn_dma_32_setdesc;
3836 dr->start_transfer = bwn_dma_32_start_transfer;
3837 dr->suspend = bwn_dma_32_suspend;
3838 dr->resume = bwn_dma_32_resume;
3839 dr->get_curslot = bwn_dma_32_get_curslot;
3840 dr->set_curslot = bwn_dma_32_set_curslot;
3841 }
3842 if (for_tx) {
3843 dr->dr_tx = 1;
3844 dr->dr_curslot = -1;
3845 } else {
3846 if (dr->dr_index == 0) {
3847 dr->dr_rx_bufsize = BWN_DMA0_RX_BUFFERSIZE;
3848 dr->dr_frameoffset = BWN_DMA0_RX_FRAMEOFFSET;
3849 } else
3850 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3851 }
3852
3853 error = bwn_dma_allocringmemory(dr);
3854 if (error)
3855 goto fail2;
3856
3857 if (for_tx) {
3858 /*
3859 * Assumption: BWN_TXRING_SLOTS can be divided by
3860 * BWN_TX_SLOTS_PER_FRAME
3861 */
3862 KASSERT(BWN_TXRING_SLOTS % BWN_TX_SLOTS_PER_FRAME == 0,
3863 ("%s:%d: fail", __func__, __LINE__));
3864
3865 dr->dr_txhdr_cache =
3866 malloc((dr->dr_numslots / BWN_TX_SLOTS_PER_FRAME) *
3867 BWN_HDRSIZE(mac), M_DEVBUF, M_NOWAIT | M_ZERO);
3868 KASSERT(dr->dr_txhdr_cache != NULL,
3869 ("%s:%d: fail", __func__, __LINE__));
3870
3871 /*
3872 * Create TX ring DMA stuffs
3873 */
3874 error = bus_dma_tag_create(dma->parent_dtag,
3875 BWN_ALIGN, 0,
3876 BUS_SPACE_MAXADDR,
3877 BUS_SPACE_MAXADDR,
3878 NULL, NULL,
3879 BWN_HDRSIZE(mac),
3880 1,
3881 BUS_SPACE_MAXSIZE_32BIT,
3882 0,
3883 NULL, NULL,
3884 &dr->dr_txring_dtag);
3885 if (error) {
3886 device_printf(sc->sc_dev,
3887 "can't create TX ring DMA tag: TODO frees\n");
3888 goto fail1;
3889 }
3890
3891 for (i = 0; i < dr->dr_numslots; i += 2) {
3892 dr->getdesc(dr, i, &desc, &mt);
3893
3894 mt->mt_txtype = BWN_DMADESC_METATYPE_HEADER;
3895 mt->mt_m = NULL;
3896 mt->mt_ni = NULL;
3897 mt->mt_islast = 0;
3898 error = bus_dmamap_create(dr->dr_txring_dtag, 0,
3899 &mt->mt_dmap);
3900 if (error) {
3901 device_printf(sc->sc_dev,
3902 "can't create RX buf DMA map\n");
3903 goto fail1;
3904 }
3905
3906 dr->getdesc(dr, i + 1, &desc, &mt);
3907
3908 mt->mt_txtype = BWN_DMADESC_METATYPE_BODY;
3909 mt->mt_m = NULL;
3910 mt->mt_ni = NULL;
3911 mt->mt_islast = 1;
3912 error = bus_dmamap_create(dma->txbuf_dtag, 0,
3913 &mt->mt_dmap);
3914 if (error) {
3915 device_printf(sc->sc_dev,
3916 "can't create RX buf DMA map\n");
3917 goto fail1;
3918 }
3919 }
3920 } else {
3921 error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3922 &dr->dr_spare_dmap);
3923 if (error) {
3924 device_printf(sc->sc_dev,
3925 "can't create RX buf DMA map\n");
3926 goto out; /* XXX wrong! */
3927 }
3928
3929 for (i = 0; i < dr->dr_numslots; i++) {
3930 dr->getdesc(dr, i, &desc, &mt);
3931
3932 error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3933 &mt->mt_dmap);
3934 if (error) {
3935 device_printf(sc->sc_dev,
3936 "can't create RX buf DMA map\n");
3937 goto out; /* XXX wrong! */
3938 }
3939 error = bwn_dma_newbuf(dr, desc, mt, 1);
3940 if (error) {
3941 device_printf(sc->sc_dev,
3942 "failed to allocate RX buf\n");
3943 goto out; /* XXX wrong! */
3944 }
3945 }
3946
3947 bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
3948 BUS_DMASYNC_PREWRITE);
3949
3950 dr->dr_usedslot = dr->dr_numslots;
3951 }
3952
3953 out:
3954 return (dr);
3955
3956fail2:
3957 free(dr->dr_txhdr_cache, M_DEVBUF);
3958fail1:
3959 free(dr->dr_meta, M_DEVBUF);
3960fail0:
3961 free(dr, M_DEVBUF);
3962 return (NULL);
3963}
3964
3965static void
3966bwn_dma_ringfree(struct bwn_dma_ring **dr)
3967{
3968
3969 if (dr == NULL)
3970 return;
3971
3972 bwn_dma_free_descbufs(*dr);
3973 bwn_dma_free_ringmemory(*dr);
3974
3975 free((*dr)->dr_txhdr_cache, M_DEVBUF);
3976 free((*dr)->dr_meta, M_DEVBUF);
3977 free(*dr, M_DEVBUF);
3978
3979 *dr = NULL;
3980}
3981
3982static void
3983bwn_dma_32_getdesc(struct bwn_dma_ring *dr, int slot,
3984 struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
3985{
3986 struct bwn_dmadesc32 *desc;
3987
3988 *meta = &(dr->dr_meta[slot]);
3989 desc = dr->dr_ring_descbase;
3990 desc = &(desc[slot]);
3991
3992 *gdesc = (struct bwn_dmadesc_generic *)desc;
3993}
3994
3995static void
3996bwn_dma_32_setdesc(struct bwn_dma_ring *dr,
3997 struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
3998 int start, int end, int irq)
3999{
4000 struct bwn_dmadesc32 *descbase = dr->dr_ring_descbase;
4001 struct bwn_softc *sc = dr->dr_mac->mac_sc;
4002 uint32_t addr, addrext, ctl;
4003 int slot;
4004
4005 slot = (int)(&(desc->dma.dma32) - descbase);
4006 KASSERT(slot >= 0 && slot < dr->dr_numslots,
4007 ("%s:%d: fail", __func__, __LINE__));
4008
4009 addr = (uint32_t) (dmaaddr & ~SIBA_DMA_TRANSLATION_MASK);
4010 addrext = (uint32_t) (dmaaddr & SIBA_DMA_TRANSLATION_MASK) >> 30;
4011 addr |= siba_dma_translation(sc->sc_dev);
4012 ctl = bufsize & BWN_DMA32_DCTL_BYTECNT;
4013 if (slot == dr->dr_numslots - 1)
4014 ctl |= BWN_DMA32_DCTL_DTABLEEND;
4015 if (start)
4016 ctl |= BWN_DMA32_DCTL_FRAMESTART;
4017 if (end)
4018 ctl |= BWN_DMA32_DCTL_FRAMEEND;
4019 if (irq)
4020 ctl |= BWN_DMA32_DCTL_IRQ;
4021 ctl |= (addrext << BWN_DMA32_DCTL_ADDREXT_SHIFT)
4022 & BWN_DMA32_DCTL_ADDREXT_MASK;
4023
4024 desc->dma.dma32.control = htole32(ctl);
4025 desc->dma.dma32.address = htole32(addr);
4026}
4027
4028static void
4029bwn_dma_32_start_transfer(struct bwn_dma_ring *dr, int slot)
4030{
4031
4032 BWN_DMA_WRITE(dr, BWN_DMA32_TXINDEX,
4033 (uint32_t)(slot * sizeof(struct bwn_dmadesc32)));
4034}
4035
4036static void
4037bwn_dma_32_suspend(struct bwn_dma_ring *dr)
4038{
4039
4040 BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
4041 BWN_DMA_READ(dr, BWN_DMA32_TXCTL) | BWN_DMA32_TXSUSPEND);
4042}
4043
4044static void
4045bwn_dma_32_resume(struct bwn_dma_ring *dr)
4046{
4047
4048 BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
4049 BWN_DMA_READ(dr, BWN_DMA32_TXCTL) & ~BWN_DMA32_TXSUSPEND);
4050}
4051
4052static int
4053bwn_dma_32_get_curslot(struct bwn_dma_ring *dr)
4054{
4055 uint32_t val;
4056
4057 val = BWN_DMA_READ(dr, BWN_DMA32_RXSTATUS);
4058 val &= BWN_DMA32_RXDPTR;
4059
4060 return (val / sizeof(struct bwn_dmadesc32));
4061}
4062
4063static void
4064bwn_dma_32_set_curslot(struct bwn_dma_ring *dr, int slot)
4065{
4066
4067 BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX,
4068 (uint32_t) (slot * sizeof(struct bwn_dmadesc32)));
4069}
4070
4071static void
4072bwn_dma_64_getdesc(struct bwn_dma_ring *dr, int slot,
4073 struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
4074{
4075 struct bwn_dmadesc64 *desc;
4076
4077 *meta = &(dr->dr_meta[slot]);
4078 desc = dr->dr_ring_descbase;
4079 desc = &(desc[slot]);
4080
4081 *gdesc = (struct bwn_dmadesc_generic *)desc;
4082}
4083
4084static void
4085bwn_dma_64_setdesc(struct bwn_dma_ring *dr,
4086 struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
4087 int start, int end, int irq)
4088{
4089 struct bwn_dmadesc64 *descbase = dr->dr_ring_descbase;
4090 struct bwn_softc *sc = dr->dr_mac->mac_sc;
4091 int slot;
4092 uint32_t ctl0 = 0, ctl1 = 0;
4093 uint32_t addrlo, addrhi;
4094 uint32_t addrext;
4095
4096 slot = (int)(&(desc->dma.dma64) - descbase);
4097 KASSERT(slot >= 0 && slot < dr->dr_numslots,
4098 ("%s:%d: fail", __func__, __LINE__));
4099
4100 addrlo = (uint32_t) (dmaaddr & 0xffffffff);
4101 addrhi = (((uint64_t) dmaaddr >> 32) & ~SIBA_DMA_TRANSLATION_MASK);
4102 addrext = (((uint64_t) dmaaddr >> 32) & SIBA_DMA_TRANSLATION_MASK) >>
4103 30;
4104 addrhi |= (siba_dma_translation(sc->sc_dev) << 1);
4105 if (slot == dr->dr_numslots - 1)
4106 ctl0 |= BWN_DMA64_DCTL0_DTABLEEND;
4107 if (start)
4108 ctl0 |= BWN_DMA64_DCTL0_FRAMESTART;
4109 if (end)
4110 ctl0 |= BWN_DMA64_DCTL0_FRAMEEND;
4111 if (irq)
4112 ctl0 |= BWN_DMA64_DCTL0_IRQ;
4113 ctl1 |= bufsize & BWN_DMA64_DCTL1_BYTECNT;
4114 ctl1 |= (addrext << BWN_DMA64_DCTL1_ADDREXT_SHIFT)
4115 & BWN_DMA64_DCTL1_ADDREXT_MASK;
4116
4117 desc->dma.dma64.control0 = htole32(ctl0);
4118 desc->dma.dma64.control1 = htole32(ctl1);
4119 desc->dma.dma64.address_low = htole32(addrlo);
4120 desc->dma.dma64.address_high = htole32(addrhi);
4121}
4122
4123static void
4124bwn_dma_64_start_transfer(struct bwn_dma_ring *dr, int slot)
4125{
4126
4127 BWN_DMA_WRITE(dr, BWN_DMA64_TXINDEX,
4128 (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4129}
4130
4131static void
4132bwn_dma_64_suspend(struct bwn_dma_ring *dr)
4133{
4134
4135 BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
4136 BWN_DMA_READ(dr, BWN_DMA64_TXCTL) | BWN_DMA64_TXSUSPEND);
4137}
4138
4139static void
4140bwn_dma_64_resume(struct bwn_dma_ring *dr)
4141{
4142
4143 BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
4144 BWN_DMA_READ(dr, BWN_DMA64_TXCTL) & ~BWN_DMA64_TXSUSPEND);
4145}
4146
4147static int
4148bwn_dma_64_get_curslot(struct bwn_dma_ring *dr)
4149{
4150 uint32_t val;
4151
4152 val = BWN_DMA_READ(dr, BWN_DMA64_RXSTATUS);
4153 val &= BWN_DMA64_RXSTATDPTR;
4154
4155 return (val / sizeof(struct bwn_dmadesc64));
4156}
4157
4158static void
4159bwn_dma_64_set_curslot(struct bwn_dma_ring *dr, int slot)
4160{
4161
4162 BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX,
4163 (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4164}
4165
4166static int
4167bwn_dma_allocringmemory(struct bwn_dma_ring *dr)
4168{
4169 struct bwn_mac *mac = dr->dr_mac;
4170 struct bwn_dma *dma = &mac->mac_method.dma;
4171 struct bwn_softc *sc = mac->mac_sc;
4172 int error;
4173
4174 error = bus_dma_tag_create(dma->parent_dtag,
4175 BWN_ALIGN, 0,
4176 BUS_SPACE_MAXADDR,
4177 BUS_SPACE_MAXADDR,
4178 NULL, NULL,
4179 BWN_DMA_RINGMEMSIZE,
4180 1,
4181 BUS_SPACE_MAXSIZE_32BIT,
4182 0,
4183 NULL, NULL,
4184 &dr->dr_ring_dtag);
4185 if (error) {
4186 device_printf(sc->sc_dev,
4187 "can't create TX ring DMA tag: TODO frees\n");
4188 return (-1);
4189 }
4190
4191 error = bus_dmamem_alloc(dr->dr_ring_dtag,
4192 &dr->dr_ring_descbase, BUS_DMA_WAITOK | BUS_DMA_ZERO,
4193 &dr->dr_ring_dmap);
4194 if (error) {
4195 device_printf(sc->sc_dev,
4196 "can't allocate DMA mem: TODO frees\n");
4197 return (-1);
4198 }
4199 error = bus_dmamap_load(dr->dr_ring_dtag, dr->dr_ring_dmap,
4200 dr->dr_ring_descbase, BWN_DMA_RINGMEMSIZE,
4201 bwn_dma_ring_addr, &dr->dr_ring_dmabase, BUS_DMA_NOWAIT);
4202 if (error) {
4203 device_printf(sc->sc_dev,
4204 "can't load DMA mem: TODO free\n");
4205 return (-1);
4206 }
4207
4208 return (0);
4209}
4210
4211static void
4212bwn_dma_setup(struct bwn_dma_ring *dr)
4213{
4214 struct bwn_softc *sc = dr->dr_mac->mac_sc;
4215 uint64_t ring64;
4216 uint32_t addrext, ring32, value;
4217 uint32_t trans = siba_dma_translation(sc->sc_dev);
4218
4219 if (dr->dr_tx) {
4220 dr->dr_curslot = -1;
4221
4222 if (dr->dr_type == BWN_DMA_64BIT) {
4223 ring64 = (uint64_t)(dr->dr_ring_dmabase);
4224 addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK)
4225 >> 30;
4226 value = BWN_DMA64_TXENABLE;
4227 value |= (addrext << BWN_DMA64_TXADDREXT_SHIFT)
4228 & BWN_DMA64_TXADDREXT_MASK;
4229 BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL, value);
4230 BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO,
4231 (ring64 & 0xffffffff));
4232 BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI,
4233 ((ring64 >> 32) &
4234 ~SIBA_DMA_TRANSLATION_MASK) | (trans << 1));
4235 } else {
4236 ring32 = (uint32_t)(dr->dr_ring_dmabase);
4237 addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4238 value = BWN_DMA32_TXENABLE;
4239 value |= (addrext << BWN_DMA32_TXADDREXT_SHIFT)
4240 & BWN_DMA32_TXADDREXT_MASK;
4241 BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL, value);
4242 BWN_DMA_WRITE(dr, BWN_DMA32_TXRING,
4243 (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4244 }
4245 return;
4246 }
4247
4248 /*
4249 * set for RX
4250 */
4251 dr->dr_usedslot = dr->dr_numslots;
4252
4253 if (dr->dr_type == BWN_DMA_64BIT) {
4254 ring64 = (uint64_t)(dr->dr_ring_dmabase);
4255 addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK) >> 30;
4256 value = (dr->dr_frameoffset << BWN_DMA64_RXFROFF_SHIFT);
4257 value |= BWN_DMA64_RXENABLE;
4258 value |= (addrext << BWN_DMA64_RXADDREXT_SHIFT)
4259 & BWN_DMA64_RXADDREXT_MASK;
4260 BWN_DMA_WRITE(dr, BWN_DMA64_RXCTL, value);
4261 BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, (ring64 & 0xffffffff));
4262 BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI,
4263 ((ring64 >> 32) & ~SIBA_DMA_TRANSLATION_MASK)
4264 | (trans << 1));
4265 BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX, dr->dr_numslots *
4266 sizeof(struct bwn_dmadesc64));
4267 } else {
4268 ring32 = (uint32_t)(dr->dr_ring_dmabase);
4269 addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4270 value = (dr->dr_frameoffset << BWN_DMA32_RXFROFF_SHIFT);
4271 value |= BWN_DMA32_RXENABLE;
4272 value |= (addrext << BWN_DMA32_RXADDREXT_SHIFT)
4273 & BWN_DMA32_RXADDREXT_MASK;
4274 BWN_DMA_WRITE(dr, BWN_DMA32_RXCTL, value);
4275 BWN_DMA_WRITE(dr, BWN_DMA32_RXRING,
4276 (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4277 BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX, dr->dr_numslots *
4278 sizeof(struct bwn_dmadesc32));
4279 }
4280}
4281
4282static void
4283bwn_dma_free_ringmemory(struct bwn_dma_ring *dr)
4284{
4285
4286 bus_dmamap_unload(dr->dr_ring_dtag, dr->dr_ring_dmap);
4287 bus_dmamem_free(dr->dr_ring_dtag, dr->dr_ring_descbase,
4288 dr->dr_ring_dmap);
4289}
4290
4291static void
4292bwn_dma_cleanup(struct bwn_dma_ring *dr)
4293{
4294
4295 if (dr->dr_tx) {
4296 bwn_dma_tx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4297 if (dr->dr_type == BWN_DMA_64BIT) {
4298 BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO, 0);
4299 BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI, 0);
4300 } else
4301 BWN_DMA_WRITE(dr, BWN_DMA32_TXRING, 0);
4302 } else {
4303 bwn_dma_rx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4304 if (dr->dr_type == BWN_DMA_64BIT) {
4305 BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, 0);
4306 BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI, 0);
4307 } else
4308 BWN_DMA_WRITE(dr, BWN_DMA32_RXRING, 0);
4309 }
4310}
4311
4312static void
4313bwn_dma_free_descbufs(struct bwn_dma_ring *dr)
4314{
4315 struct bwn_dmadesc_generic *desc;
4316 struct bwn_dmadesc_meta *meta;
4317 struct bwn_mac *mac = dr->dr_mac;
4318 struct bwn_dma *dma = &mac->mac_method.dma;
4319 struct bwn_softc *sc = mac->mac_sc;
4320 int i;
4321
4322 if (!dr->dr_usedslot)
4323 return;
4324 for (i = 0; i < dr->dr_numslots; i++) {
4325 dr->getdesc(dr, i, &desc, &meta);
4326
4327 if (meta->mt_m == NULL) {
4328 if (!dr->dr_tx)
4329 device_printf(sc->sc_dev, "%s: not TX?\n",
4330 __func__);
4331 continue;
4332 }
4333 if (dr->dr_tx) {
4334 if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
4335 bus_dmamap_unload(dr->dr_txring_dtag,
4336 meta->mt_dmap);
4337 else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
4338 bus_dmamap_unload(dma->txbuf_dtag,
4339 meta->mt_dmap);
4340 } else
4341 bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
4342 bwn_dma_free_descbuf(dr, meta);
4343 }
4344}
4345
4346static int
4347bwn_dma_tx_reset(struct bwn_mac *mac, uint16_t base,
4348 int type)
4349{
4350 struct bwn_softc *sc = mac->mac_sc;
4351 uint32_t value;
4352 int i;
4353 uint16_t offset;
4354
4355 for (i = 0; i < 10; i++) {
4356 offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4357 BWN_DMA32_TXSTATUS;
4358 value = BWN_READ_4(mac, base + offset);
4359 if (type == BWN_DMA_64BIT) {
4360 value &= BWN_DMA64_TXSTAT;
4361 if (value == BWN_DMA64_TXSTAT_DISABLED ||
4362 value == BWN_DMA64_TXSTAT_IDLEWAIT ||
4363 value == BWN_DMA64_TXSTAT_STOPPED)
4364 break;
4365 } else {
4366 value &= BWN_DMA32_TXSTATE;
4367 if (value == BWN_DMA32_TXSTAT_DISABLED ||
4368 value == BWN_DMA32_TXSTAT_IDLEWAIT ||
4369 value == BWN_DMA32_TXSTAT_STOPPED)
4370 break;
4371 }
4372 DELAY(1000);
4373 }
4374 offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXCTL : BWN_DMA32_TXCTL;
4375 BWN_WRITE_4(mac, base + offset, 0);
4376 for (i = 0; i < 10; i++) {
4377 offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4378 BWN_DMA32_TXSTATUS;
4379 value = BWN_READ_4(mac, base + offset);
4380 if (type == BWN_DMA_64BIT) {
4381 value &= BWN_DMA64_TXSTAT;
4382 if (value == BWN_DMA64_TXSTAT_DISABLED) {
4383 i = -1;
4384 break;
4385 }
4386 } else {
4387 value &= BWN_DMA32_TXSTATE;
4388 if (value == BWN_DMA32_TXSTAT_DISABLED) {
4389 i = -1;
4390 break;
4391 }
4392 }
4393 DELAY(1000);
4394 }
4395 if (i != -1) {
4396 device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4397 return (ENODEV);
4398 }
4399 DELAY(1000);
4400
4401 return (0);
4402}
4403
4404static int
4405bwn_dma_rx_reset(struct bwn_mac *mac, uint16_t base,
4406 int type)
4407{
4408 struct bwn_softc *sc = mac->mac_sc;
4409 uint32_t value;
4410 int i;
4411 uint16_t offset;
4412
4413 offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXCTL : BWN_DMA32_RXCTL;
4414 BWN_WRITE_4(mac, base + offset, 0);
4415 for (i = 0; i < 10; i++) {
4416 offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXSTATUS :
4417 BWN_DMA32_RXSTATUS;
4418 value = BWN_READ_4(mac, base + offset);
4419 if (type == BWN_DMA_64BIT) {
4420 value &= BWN_DMA64_RXSTAT;
4421 if (value == BWN_DMA64_RXSTAT_DISABLED) {
4422 i = -1;
4423 break;
4424 }
4425 } else {
4426 value &= BWN_DMA32_RXSTATE;
4427 if (value == BWN_DMA32_RXSTAT_DISABLED) {
4428 i = -1;
4429 break;
4430 }
4431 }
4432 DELAY(1000);
4433 }
4434 if (i != -1) {
4435 device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4436 return (ENODEV);
4437 }
4438
4439 return (0);
4440}
4441
4442static void
4443bwn_dma_free_descbuf(struct bwn_dma_ring *dr,
4444 struct bwn_dmadesc_meta *meta)
4445{
4446
4447 if (meta->mt_m != NULL) {
4448 m_freem(meta->mt_m);
4449 meta->mt_m = NULL;
4450 }
4451 if (meta->mt_ni != NULL) {
4452 ieee80211_free_node(meta->mt_ni);
4453 meta->mt_ni = NULL;
4454 }
4455}
4456
4457static void
4458bwn_dma_set_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4459{
4460 struct bwn_rxhdr4 *rxhdr;
4461 unsigned char *frame;
4462
4463 rxhdr = mtod(m, struct bwn_rxhdr4 *);
4464 rxhdr->frame_len = 0;
4465
4466 KASSERT(dr->dr_rx_bufsize >= dr->dr_frameoffset +
4467 sizeof(struct bwn_plcp6) + 2,
4468 ("%s:%d: fail", __func__, __LINE__));
4469 frame = mtod(m, char *) + dr->dr_frameoffset;
4470 memset(frame, 0xff, sizeof(struct bwn_plcp6) + 2 /* padding */);
4471}
4472
4473static uint8_t
4474bwn_dma_check_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4475{
4476 unsigned char *f = mtod(m, char *) + dr->dr_frameoffset;
4477
4478 return ((f[0] & f[1] & f[2] & f[3] & f[4] & f[5] & f[6] & f[7])
4479 == 0xff);
4480}
4481
4482static void
4483bwn_wme_init(struct bwn_mac *mac)
4484{
4485
4486 bwn_wme_load(mac);
4487
4488 /* enable WME support. */
4489 bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_EDCF);
4490 BWN_WRITE_2(mac, BWN_IFSCTL, BWN_READ_2(mac, BWN_IFSCTL) |
4491 BWN_IFSCTL_USE_EDCF);
4492}
4493
4494static void
4495bwn_spu_setdelay(struct bwn_mac *mac, int idle)
4496{
4497 struct bwn_softc *sc = mac->mac_sc;
4498 struct ieee80211com *ic = sc->sc_ifp->if_l2com;
4499 uint16_t delay; /* microsec */
4500
4501 delay = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 3700 : 1050;
4502 if (ic->ic_opmode == IEEE80211_M_IBSS || idle)
4503 delay = 500;
4504 if ((mac->mac_phy.rf_ver == 0x2050) && (mac->mac_phy.rf_rev == 8))
4505 delay = max(delay, (uint16_t)2400);
4506
4507 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SPU_WAKEUP, delay);
4508}
4509
4510static void
4511bwn_bt_enable(struct bwn_mac *mac)
4512{
4513 struct bwn_softc *sc = mac->mac_sc;
4514 uint64_t hf;
4515
4516 if (bwn_bluetooth == 0)
4517 return;
4518 if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCOEXIST) == 0)
4519 return;
4520 if (mac->mac_phy.type != BWN_PHYTYPE_B && !mac->mac_phy.gmode)
4521 return;
4522
4523 hf = bwn_hf_read(mac);
4524 if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCMOD)
4525 hf |= BWN_HF_BT_COEXISTALT;
4526 else
4527 hf |= BWN_HF_BT_COEXIST;
4528 bwn_hf_write(mac, hf);
4529}
4530
4531static void
4532bwn_set_macaddr(struct bwn_mac *mac)
4533{
4534
4535 bwn_mac_write_bssid(mac);
4536 bwn_mac_setfilter(mac, BWN_MACFILTER_SELF, mac->mac_sc->sc_macaddr);
4537}
4538
4539static void
4540bwn_clear_keys(struct bwn_mac *mac)
4541{
4542 int i;
4543
4544 for (i = 0; i < mac->mac_max_nr_keys; i++) {
4545 KASSERT(i >= 0 && i < mac->mac_max_nr_keys,
4546 ("%s:%d: fail", __func__, __LINE__));
4547
4548 bwn_key_dowrite(mac, i, BWN_SEC_ALGO_NONE,
4549 NULL, BWN_SEC_KEYSIZE, NULL);
4550 if ((i <= 3) && !BWN_SEC_NEWAPI(mac)) {
4551 bwn_key_dowrite(mac, i + 4, BWN_SEC_ALGO_NONE,
4552 NULL, BWN_SEC_KEYSIZE, NULL);
4553 }
4554 mac->mac_key[i].keyconf = NULL;
4555 }
4556}
4557
4558static void
4559bwn_crypt_init(struct bwn_mac *mac)
4560{
4561 struct bwn_softc *sc = mac->mac_sc;
4562
4563 mac->mac_max_nr_keys = (siba_get_revid(sc->sc_dev) >= 5) ? 58 : 20;
4564 KASSERT(mac->mac_max_nr_keys <= N(mac->mac_key),
4565 ("%s:%d: fail", __func__, __LINE__));
4566 mac->mac_ktp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_KEY_TABLEP);
4567 mac->mac_ktp *= 2;
4568 if (siba_get_revid(sc->sc_dev) >= 5)
4569 BWN_WRITE_2(mac, BWN_RCMTA_COUNT, mac->mac_max_nr_keys - 8);
4570 bwn_clear_keys(mac);
4571}
4572
4573static void
4574bwn_chip_exit(struct bwn_mac *mac)
4575{
4576 struct bwn_softc *sc = mac->mac_sc;
4577
4578 bwn_phy_exit(mac);
4579 siba_gpio_set(sc->sc_dev, 0);
4580}
4581
4582static int
4583bwn_fw_fillinfo(struct bwn_mac *mac)
4584{
4585 int error;
4586
4587 error = bwn_fw_gets(mac, BWN_FWTYPE_DEFAULT);
4588 if (error == 0)
4589 return (0);
4590 error = bwn_fw_gets(mac, BWN_FWTYPE_OPENSOURCE);
4591 if (error == 0)
4592 return (0);
4593 return (error);
4594}
4595
4596static int
4597bwn_gpio_init(struct bwn_mac *mac)
4598{
4599 struct bwn_softc *sc = mac->mac_sc;
4600 uint32_t mask = 0x1f, set = 0xf, value;
4601
4602 BWN_WRITE_4(mac, BWN_MACCTL,
4603 BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GPOUT_MASK);
4604 BWN_WRITE_2(mac, BWN_GPIO_MASK,
4605 BWN_READ_2(mac, BWN_GPIO_MASK) | 0x000f);
4606
4607 if (siba_get_chipid(sc->sc_dev) == 0x4301) {
4608 mask |= 0x0060;
4609 set |= 0x0060;
4610 }
4611 if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL) {
4612 BWN_WRITE_2(mac, BWN_GPIO_MASK,
4613 BWN_READ_2(mac, BWN_GPIO_MASK) | 0x0200);
4614 mask |= 0x0200;
4615 set |= 0x0200;
4616 }
4617 if (siba_get_revid(sc->sc_dev) >= 2)
4618 mask |= 0x0010;
4619
4620 value = siba_gpio_get(sc->sc_dev);
4621 if (value == -1)
4622 return (0);
4623 siba_gpio_set(sc->sc_dev, (value & mask) | set);
4624
4625 return (0);
4626}
4627
4628static int
4629bwn_fw_loadinitvals(struct bwn_mac *mac)
4630{
4631#define GETFWOFFSET(fwp, offset) \
4632 ((const struct bwn_fwinitvals *)((const char *)fwp.fw->data + offset))
4633 const size_t hdr_len = sizeof(struct bwn_fwhdr);
4634 const struct bwn_fwhdr *hdr;
4635 struct bwn_fw *fw = &mac->mac_fw;
4636 int error;
4637
4638 hdr = (const struct bwn_fwhdr *)(fw->initvals.fw->data);
4639 error = bwn_fwinitvals_write(mac, GETFWOFFSET(fw->initvals, hdr_len),
4640 be32toh(hdr->size), fw->initvals.fw->datasize - hdr_len);
4641 if (error)
4642 return (error);
4643 if (fw->initvals_band.fw) {
4644 hdr = (const struct bwn_fwhdr *)(fw->initvals_band.fw->data);
4645 error = bwn_fwinitvals_write(mac,
4646 GETFWOFFSET(fw->initvals_band, hdr_len),
4647 be32toh(hdr->size),
4648 fw->initvals_band.fw->datasize - hdr_len);
4649 }
4650 return (error);
4651#undef GETFWOFFSET
4652}
4653
4654static int
4655bwn_phy_init(struct bwn_mac *mac)
4656{
4657 struct bwn_softc *sc = mac->mac_sc;
4658 int error;
4659
4660 mac->mac_phy.chan = mac->mac_phy.get_default_chan(mac);
4661 mac->mac_phy.rf_onoff(mac, 1);
4662 error = mac->mac_phy.init(mac);
4663 if (error) {
4664 device_printf(sc->sc_dev, "PHY init failed\n");
4665 goto fail0;
4666 }
4667 error = bwn_switch_channel(mac,
4668 mac->mac_phy.get_default_chan(mac));
4669 if (error) {
4670 device_printf(sc->sc_dev,
4671 "failed to switch default channel\n");
4672 goto fail1;
4673 }
4674 return (0);
4675fail1:
4676 if (mac->mac_phy.exit)
4677 mac->mac_phy.exit(mac);
4678fail0:
4679 mac->mac_phy.rf_onoff(mac, 0);
4680
4681 return (error);
4682}
4683
4684static void
4685bwn_set_txantenna(struct bwn_mac *mac, int antenna)
4686{
4687 uint16_t ant;
4688 uint16_t tmp;
4689
4690 ant = bwn_ant2phy(antenna);
4691
4692 /* For ACK/CTS */
4693 tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL);
4694 tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4695 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, tmp);
4696 /* For Probe Resposes */
4697 tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL);
4698 tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4699 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, tmp);
4700}
4701
4702static void
4703bwn_set_opmode(struct bwn_mac *mac)
4704{
4705 struct bwn_softc *sc = mac->mac_sc;
4706 struct ifnet *ifp = sc->sc_ifp;
4707 struct ieee80211com *ic = ifp->if_l2com;
4708 uint32_t ctl;
4709 uint16_t cfp_pretbtt;
4710
4711 ctl = BWN_READ_4(mac, BWN_MACCTL);
4712 ctl &= ~(BWN_MACCTL_HOSTAP | BWN_MACCTL_PASS_CTL |
4713 BWN_MACCTL_PASS_BADPLCP | BWN_MACCTL_PASS_BADFCS |
4714 BWN_MACCTL_PROMISC | BWN_MACCTL_BEACON_PROMISC);
4715 ctl |= BWN_MACCTL_STA;
4716
4717 if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
4718 ic->ic_opmode == IEEE80211_M_MBSS)
4719 ctl |= BWN_MACCTL_HOSTAP;
4720 else if (ic->ic_opmode == IEEE80211_M_IBSS)
4721 ctl &= ~BWN_MACCTL_STA;
4722 ctl |= sc->sc_filters;
4723
4724 if (siba_get_revid(sc->sc_dev) <= 4)
4725 ctl |= BWN_MACCTL_PROMISC;
4726
4727 BWN_WRITE_4(mac, BWN_MACCTL, ctl);
4728
4729 cfp_pretbtt = 2;
4730 if ((ctl & BWN_MACCTL_STA) && !(ctl & BWN_MACCTL_HOSTAP)) {
4731 if (siba_get_chipid(sc->sc_dev) == 0x4306 &&
4732 siba_get_chiprev(sc->sc_dev) == 3)
4733 cfp_pretbtt = 100;
4734 else
4735 cfp_pretbtt = 50;
4736 }
4737 BWN_WRITE_2(mac, 0x612, cfp_pretbtt);
4738}
4739
4740static int
4741bwn_dma_gettype(struct bwn_mac *mac)
4742{
4743 uint32_t tmp;
4744 uint16_t base;
4745
4746 tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
4747 if (tmp & SIBA_TGSHIGH_DMA64)
4748 return (BWN_DMA_64BIT);
4749 base = bwn_dma_base(0, 0);
4750 BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
4751 tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
4752 if (tmp & BWN_DMA32_TXADDREXT_MASK)
4753 return (BWN_DMA_32BIT);
4754
4755 return (BWN_DMA_30BIT);
4756}
4757
4758static void
4759bwn_dma_ring_addr(void *arg, bus_dma_segment_t *seg, int nseg, int error)
4760{
4761 if (!error) {
4762 KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
4763 *((bus_addr_t *)arg) = seg->ds_addr;
4764 }
4765}
4766
4767static void
4768bwn_phy_g_init_sub(struct bwn_mac *mac)
4769{
4770 struct bwn_phy *phy = &mac->mac_phy;
4771 struct bwn_phy_g *pg = &phy->phy_g;
4772 struct bwn_softc *sc = mac->mac_sc;
4773 uint16_t i, tmp;
4774
4775 if (phy->rev == 1)
4776 bwn_phy_init_b5(mac);
4777 else
4778 bwn_phy_init_b6(mac);
4779
4780 if (phy->rev >= 2 || phy->gmode)
4781 bwn_phy_init_a(mac);
4782
4783 if (phy->rev >= 2) {
4784 BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, 0);
4785 BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, 0);
4786 }
4787 if (phy->rev == 2) {
4788 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
4789 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4790 }
4791 if (phy->rev > 5) {
4792 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x400);
4793 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4794 }
4795 if (phy->gmode || phy->rev >= 2) {
4796 tmp = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
4797 tmp &= BWN_PHYVER_VERSION;
4798 if (tmp == 3 || tmp == 5) {
4799 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc2), 0x1816);
4800 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc3), 0x8006);
4801 }
4802 if (tmp == 5) {
4803 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xcc), 0x00ff,
4804 0x1f00);
4805 }
4806 }
4807 if ((phy->rev <= 2 && phy->gmode) || phy->rev >= 2)
4808 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x7e), 0x78);
4809 if (phy->rf_rev == 8) {
4810 BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x80);
4811 BWN_PHY_SET(mac, BWN_PHY_OFDM(0x3e), 0x4);
4812 }
4813 if (BWN_HAS_LOOPBACK(phy))
4814 bwn_loopback_calcgain(mac);
4815
4816 if (phy->rf_rev != 8) {
4817 if (pg->pg_initval == 0xffff)
4818 pg->pg_initval = bwn_rf_init_bcm2050(mac);
4819 else
4820 BWN_RF_WRITE(mac, 0x0078, pg->pg_initval);
4821 }
4822 bwn_lo_g_init(mac);
4823 if (BWN_HAS_TXMAG(phy)) {
4824 BWN_RF_WRITE(mac, 0x52,
4825 (BWN_RF_READ(mac, 0x52) & 0xff00)
4826 | pg->pg_loctl.tx_bias |
4827 pg->pg_loctl.tx_magn);
4828 } else {
4829 BWN_RF_SETMASK(mac, 0x52, 0xfff0, pg->pg_loctl.tx_bias);
4830 }
4831 if (phy->rev >= 6) {
4832 BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x36), 0x0fff,
4833 (pg->pg_loctl.tx_bias << 12));
4834 }
4835 if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
4836 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8075);
4837 else
4838 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x807f);
4839 if (phy->rev < 2)
4840 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x101);
4841 else
4842 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x202);
4843 if (phy->gmode || phy->rev >= 2) {
4844 bwn_lo_g_adjust(mac);
4845 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
4846 }
4847
4848 if (!(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI)) {
4849 for (i = 0; i < 64; i++) {
4850 BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, i);
4851 BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_DATA,
4852 (uint16_t)MIN(MAX(bwn_nrssi_read(mac, i) - 0xffff,
4853 -32), 31));
4854 }
4855 bwn_nrssi_threshold(mac);
4856 } else if (phy->gmode || phy->rev >= 2) {
4857 if (pg->pg_nrssi[0] == -1000) {
4858 KASSERT(pg->pg_nrssi[1] == -1000,
4859 ("%s:%d: fail", __func__, __LINE__));
4860 bwn_nrssi_slope_11g(mac);
4861 } else
4862 bwn_nrssi_threshold(mac);
4863 }
4864 if (phy->rf_rev == 8)
4865 BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x05), 0x3230);
4866 bwn_phy_hwpctl_init(mac);
4867 if ((siba_get_chipid(sc->sc_dev) == 0x4306
4868 && siba_get_chippkg(sc->sc_dev) == 2) || 0) {
4869 BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0xbfff);
4870 BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xc3), 0x7fff);
4871 }
4872}
4873
4874static uint8_t
4875bwn_has_hwpctl(struct bwn_mac *mac)
4876{
4877
4878 if (mac->mac_phy.hwpctl == 0 || mac->mac_phy.use_hwpctl == NULL)
4879 return (0);
4880 return (mac->mac_phy.use_hwpctl(mac));
4881}
4882
4883static void
4884bwn_phy_init_b5(struct bwn_mac *mac)
4885{
4886 struct bwn_phy *phy = &mac->mac_phy;
4887 struct bwn_phy_g *pg = &phy->phy_g;
4888 struct bwn_softc *sc = mac->mac_sc;
4889 uint16_t offset, value;
4890 uint8_t old_channel;
4891
4892 if (phy->analog == 1)
4893 BWN_RF_SET(mac, 0x007a, 0x0050);
4894 if ((siba_get_pci_subvendor(sc->sc_dev) != SIBA_BOARDVENDOR_BCM) &&
4895 (siba_get_pci_subdevice(sc->sc_dev) != SIBA_BOARD_BU4306)) {
4896 value = 0x2120;
4897 for (offset = 0x00a8; offset < 0x00c7; offset++) {
4898 BWN_PHY_WRITE(mac, offset, value);
4899 value += 0x202;
4900 }
4901 }
4902 BWN_PHY_SETMASK(mac, 0x0035, 0xf0ff, 0x0700);
4903 if (phy->rf_ver == 0x2050)
4904 BWN_PHY_WRITE(mac, 0x0038, 0x0667);
4905
4906 if (phy->gmode || phy->rev >= 2) {
4907 if (phy->rf_ver == 0x2050) {
4908 BWN_RF_SET(mac, 0x007a, 0x0020);
4909 BWN_RF_SET(mac, 0x0051, 0x0004);
4910 }
4911 BWN_WRITE_2(mac, BWN_PHY_RADIO, 0x0000);
4912
4913 BWN_PHY_SET(mac, 0x0802, 0x0100);
4914 BWN_PHY_SET(mac, 0x042b, 0x2000);
4915
4916 BWN_PHY_WRITE(mac, 0x001c, 0x186a);
4917
4918 BWN_PHY_SETMASK(mac, 0x0013, 0x00ff, 0x1900);
4919 BWN_PHY_SETMASK(mac, 0x0035, 0xffc0, 0x0064);
4920 BWN_PHY_SETMASK(mac, 0x005d, 0xff80, 0x000a);
4921 }
4922
4923 if (mac->mac_flags & BWN_MAC_FLAG_BADFRAME_PREEMP)
4924 BWN_PHY_SET(mac, BWN_PHY_RADIO_BITFIELD, (1 << 11));
4925
4926 if (phy->analog == 1) {
4927 BWN_PHY_WRITE(mac, 0x0026, 0xce00);
4928 BWN_PHY_WRITE(mac, 0x0021, 0x3763);
4929 BWN_PHY_WRITE(mac, 0x0022, 0x1bc3);
4930 BWN_PHY_WRITE(mac, 0x0023, 0x06f9);
4931 BWN_PHY_WRITE(mac, 0x0024, 0x037e);
4932 } else
4933 BWN_PHY_WRITE(mac, 0x0026, 0xcc00);
4934 BWN_PHY_WRITE(mac, 0x0030, 0x00c6);
4935 BWN_WRITE_2(mac, 0x03ec, 0x3f22);
4936
4937 if (phy->analog == 1)
4938 BWN_PHY_WRITE(mac, 0x0020, 0x3e1c);
4939 else
4940 BWN_PHY_WRITE(mac, 0x0020, 0x301c);
4941
4942 if (phy->analog == 0)
4943 BWN_WRITE_2(mac, 0x03e4, 0x3000);
4944
4945 old_channel = phy->chan;
4946 bwn_phy_g_switch_chan(mac, 7, 0);
4947
4948 if (phy->rf_ver != 0x2050) {
4949 BWN_RF_WRITE(mac, 0x0075, 0x0080);
4950 BWN_RF_WRITE(mac, 0x0079, 0x0081);
4951 }
4952
4953 BWN_RF_WRITE(mac, 0x0050, 0x0020);
4954 BWN_RF_WRITE(mac, 0x0050, 0x0023);
4955
4956 if (phy->rf_ver == 0x2050) {
4957 BWN_RF_WRITE(mac, 0x0050, 0x0020);
4958 BWN_RF_WRITE(mac, 0x005a, 0x0070);
4959 }
4960
4961 BWN_RF_WRITE(mac, 0x005b, 0x007b);
4962 BWN_RF_WRITE(mac, 0x005c, 0x00b0);
4963 BWN_RF_SET(mac, 0x007a, 0x0007);
4964
4965 bwn_phy_g_switch_chan(mac, old_channel, 0);
4966 BWN_PHY_WRITE(mac, 0x0014, 0x0080);
4967 BWN_PHY_WRITE(mac, 0x0032, 0x00ca);
4968 BWN_PHY_WRITE(mac, 0x002a, 0x88a3);
4969
4970 bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
4971 pg->pg_txctl);
4972
4973 if (phy->rf_ver == 0x2050)
4974 BWN_RF_WRITE(mac, 0x005d, 0x000d);
4975
4976 BWN_WRITE_2(mac, 0x03e4, (BWN_READ_2(mac, 0x03e4) & 0xffc0) | 0x0004);
4977}
4978
4979static void
4980bwn_loopback_calcgain(struct bwn_mac *mac)
4981{
4982 struct bwn_phy *phy = &mac->mac_phy;
4983 struct bwn_phy_g *pg = &phy->phy_g;
4984 struct bwn_softc *sc = mac->mac_sc;
4985 uint16_t backup_phy[16] = { 0 };
4986 uint16_t backup_radio[3];
4987 uint16_t backup_bband;
4988 uint16_t i, j, loop_i_max;
4989 uint16_t trsw_rx;
4990 uint16_t loop1_outer_done, loop1_inner_done;
4991
4992 backup_phy[0] = BWN_PHY_READ(mac, BWN_PHY_CRS0);
4993 backup_phy[1] = BWN_PHY_READ(mac, BWN_PHY_CCKBBANDCFG);
4994 backup_phy[2] = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
4995 backup_phy[3] = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
4996 if (phy->rev != 1) {
4997 backup_phy[4] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
4998 backup_phy[5] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
4999 }
5000 backup_phy[6] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
5001 backup_phy[7] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
5002 backup_phy[8] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
5003 backup_phy[9] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x0a));
5004 backup_phy[10] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x03));
5005 backup_phy[11] = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
5006 backup_phy[12] = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
5007 backup_phy[13] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2b));
5008 backup_phy[14] = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
5009 backup_phy[15] = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5010 backup_bband = pg->pg_bbatt.att;
5011 backup_radio[0] = BWN_RF_READ(mac, 0x52);
5012 backup_radio[1] = BWN_RF_READ(mac, 0x43);
5013 backup_radio[2] = BWN_RF_READ(mac, 0x7a);
5014
5015 BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x3fff);
5016 BWN_PHY_SET(mac, BWN_PHY_CCKBBANDCFG, 0x8000);
5017 BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0002);
5018 BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffd);
5019 BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0001);
5020 BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffe);
5021 if (phy->rev != 1) {
5022 BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0001);
5023 BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffe);
5024 BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0002);
5025 BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffd);
5026 }
5027 BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x000c);
5028 BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x000c);
5029 BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0030);
5030 BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xffcf, 0x10);
5031
5032 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0780);
5033 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5034 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5035
5036 BWN_PHY_SET(mac, BWN_PHY_CCK(0x0a), 0x2000);
5037 if (phy->rev != 1) {
5038 BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0004);
5039 BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffb);
5040 }
5041 BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xff9f, 0x40);
5042
5043 if (phy->rf_rev == 8)
5044 BWN_RF_WRITE(mac, 0x43, 0x000f);
5045 else {
5046 BWN_RF_WRITE(mac, 0x52, 0);
5047 BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x9);
5048 }
5049 bwn_phy_g_set_bbatt(mac, 11);
5050
5051 if (phy->rev >= 3)
5052 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
5053 else
5054 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
5055 BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
5056
5057 BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xffc0, 0x01);
5058 BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xc0ff, 0x800);
5059
5060 BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0100);
5061 BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xcfff);
5062
5063 if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA) {
5064 if (phy->rev >= 7) {
5065 BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0800);
5066 BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x8000);
5067 }
5068 }
5069 BWN_RF_MASK(mac, 0x7a, 0x00f7);
5070
5071 j = 0;
5072 loop_i_max = (phy->rf_rev == 8) ? 15 : 9;
5073 for (i = 0; i < loop_i_max; i++) {
5074 for (j = 0; j < 16; j++) {
5075 BWN_RF_WRITE(mac, 0x43, i);
5076 BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff,
5077 (j << 8));
5078 BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
5079 BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
5080 DELAY(20);
5081 if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
5082 goto done0;
5083 }
5084 }
5085done0:
5086 loop1_outer_done = i;
5087 loop1_inner_done = j;
5088 if (j >= 8) {
5089 BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x30);
5090 trsw_rx = 0x1b;
5091 for (j = j - 8; j < 16; j++) {
5092 BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff, j << 8);
5093 BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
5094 BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
5095 DELAY(20);
5096 trsw_rx -= 3;
5097 if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
5098 goto done1;
5099 }
5100 } else
5101 trsw_rx = 0x18;
5102done1:
5103
5104 if (phy->rev != 1) {
5105 BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, backup_phy[4]);
5106 BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, backup_phy[5]);
5107 }
5108 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), backup_phy[6]);
5109 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), backup_phy[7]);
5110 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), backup_phy[8]);
5111 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x0a), backup_phy[9]);
5112 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x03), backup_phy[10]);
5113 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, backup_phy[11]);
5114 BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, backup_phy[12]);
5115 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), backup_phy[13]);
5116 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, backup_phy[14]);
5117
5118 bwn_phy_g_set_bbatt(mac, backup_bband);
5119
5120 BWN_RF_WRITE(mac, 0x52, backup_radio[0]);
5121 BWN_RF_WRITE(mac, 0x43, backup_radio[1]);
5122 BWN_RF_WRITE(mac, 0x7a, backup_radio[2]);
5123
5124 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2] | 0x0003);
5125 DELAY(10);
5126 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2]);
5127 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, backup_phy[3]);
5128 BWN_PHY_WRITE(mac, BWN_PHY_CRS0, backup_phy[0]);
5129 BWN_PHY_WRITE(mac, BWN_PHY_CCKBBANDCFG, backup_phy[1]);
5130
5131 pg->pg_max_lb_gain =
5132 ((loop1_inner_done * 6) - (loop1_outer_done * 4)) - 11;
5133 pg->pg_trsw_rx_gain = trsw_rx * 2;
5134}
5135
5136static uint16_t
5137bwn_rf_init_bcm2050(struct bwn_mac *mac)
5138{
5139 struct bwn_phy *phy = &mac->mac_phy;
5140 uint32_t tmp1 = 0, tmp2 = 0;
5141 uint16_t rcc, i, j, pgactl, cck0, cck1, cck2, cck3, rfover, rfoverval,
5142 analogover, analogoverval, crs0, classctl, lomask, loctl, syncctl,
5143 radio0, radio1, radio2, reg0, reg1, reg2, radio78, reg, index;
5144 static const uint8_t rcc_table[] = {
5145 0x02, 0x03, 0x01, 0x0f,
5146 0x06, 0x07, 0x05, 0x0f,
5147 0x0a, 0x0b, 0x09, 0x0f,
5148 0x0e, 0x0f, 0x0d, 0x0f,
5149 };
5150
5151 loctl = lomask = reg0 = classctl = crs0 = analogoverval = analogover =
5152 rfoverval = rfover = cck3 = 0;
5153 radio0 = BWN_RF_READ(mac, 0x43);
5154 radio1 = BWN_RF_READ(mac, 0x51);
5155 radio2 = BWN_RF_READ(mac, 0x52);
5156 pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
5157 cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
5158 cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
5159 cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
5160
5161 if (phy->type == BWN_PHYTYPE_B) {
5162 cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
5163 reg0 = BWN_READ_2(mac, 0x3ec);
5164
5165 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0xff);
5166 BWN_WRITE_2(mac, 0x3ec, 0x3f3f);
5167 } else if (phy->gmode || phy->rev >= 2) {
5168 rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
5169 rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
5170 analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
5171 analogoverval = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
5172 crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
5173 classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
5174
5175 BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
5176 BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
5177 BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
5178 BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
5179 if (BWN_HAS_LOOPBACK(phy)) {
5180 lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
5181 loctl = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
5182 if (phy->rev >= 3)
5183 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
5184 else
5185 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
5186 BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
5187 }
5188
5189 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5190 bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5191 BWN_LPD(0, 1, 1)));
5192 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
5193 bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVER, 0));
5194 }
5195 BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2) | 0x8000);
5196
5197 syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
5198 BWN_PHY_MASK(mac, BWN_PHY_SYNCCTL, 0xff7f);
5199 reg1 = BWN_READ_2(mac, 0x3e6);
5200 reg2 = BWN_READ_2(mac, 0x3f4);
5201
5202 if (phy->analog == 0)
5203 BWN_WRITE_2(mac, 0x03e6, 0x0122);
5204 else {
5205 if (phy->analog >= 2)
5206 BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xffbf, 0x40);
5207 BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
5208 (BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000));
5209 }
5210
5211 reg = BWN_RF_READ(mac, 0x60);
5212 index = (reg & 0x001e) >> 1;
5213 rcc = (((rcc_table[index] << 1) | (reg & 0x0001)) | 0x0020);
5214
5215 if (phy->type == BWN_PHYTYPE_B)
5216 BWN_RF_WRITE(mac, 0x78, 0x26);
5217 if (phy->gmode || phy->rev >= 2) {
5218 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5219 bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5220 BWN_LPD(0, 1, 1)));
5221 }
5222 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfaf);
5223 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1403);
5224 if (phy->gmode || phy->rev >= 2) {
5225 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5226 bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5227 BWN_LPD(0, 0, 1)));
5228 }
5229 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfa0);
5230 BWN_RF_SET(mac, 0x51, 0x0004);
5231 if (phy->rf_rev == 8)
5232 BWN_RF_WRITE(mac, 0x43, 0x1f);
5233 else {
5234 BWN_RF_WRITE(mac, 0x52, 0);
5235 BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x0009);
5236 }
5237 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5238
5239 for (i = 0; i < 16; i++) {
5240 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0480);
5241 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5242 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5243 if (phy->gmode || phy->rev >= 2) {
5244 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5245 bwn_rf_2050_rfoverval(mac,
5246 BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5247 }
5248 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5249 DELAY(10);
5250 if (phy->gmode || phy->rev >= 2) {
5251 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5252 bwn_rf_2050_rfoverval(mac,
5253 BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5254 }
5255 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5256 DELAY(10);
5257 if (phy->gmode || phy->rev >= 2) {
5258 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5259 bwn_rf_2050_rfoverval(mac,
5260 BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5261 }
5262 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5263 DELAY(20);
5264 tmp1 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5265 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5266 if (phy->gmode || phy->rev >= 2) {
5267 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5268 bwn_rf_2050_rfoverval(mac,
5269 BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5270 }
5271 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5272 }
5273 DELAY(10);
5274
5275 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5276 tmp1++;
5277 tmp1 >>= 9;
5278
5279 for (i = 0; i < 16; i++) {
5280 radio78 = (BWN_BITREV4(i) << 1) | 0x0020;
5281 BWN_RF_WRITE(mac, 0x78, radio78);
5282 DELAY(10);
5283 for (j = 0; j < 16; j++) {
5284 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0d80);
5285 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5286 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5287 if (phy->gmode || phy->rev >= 2) {
5288 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5289 bwn_rf_2050_rfoverval(mac,
5290 BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5291 }
5292 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5293 DELAY(10);
5294 if (phy->gmode || phy->rev >= 2) {
5295 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5296 bwn_rf_2050_rfoverval(mac,
5297 BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5298 }
5299 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5300 DELAY(10);
5301 if (phy->gmode || phy->rev >= 2) {
5302 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5303 bwn_rf_2050_rfoverval(mac,
5304 BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5305 }
5306 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5307 DELAY(10);
5308 tmp2 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5309 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5310 if (phy->gmode || phy->rev >= 2) {
5311 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5312 bwn_rf_2050_rfoverval(mac,
5313 BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5314 }
5315 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5316 }
5317 tmp2++;
5318 tmp2 >>= 8;
5319 if (tmp1 < tmp2)
5320 break;
5321 }
5322
5323 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pgactl);
5324 BWN_RF_WRITE(mac, 0x51, radio1);
5325 BWN_RF_WRITE(mac, 0x52, radio2);
5326 BWN_RF_WRITE(mac, 0x43, radio0);
5327 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), cck0);
5328 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), cck1);
5329 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), cck2);
5330 BWN_WRITE_2(mac, 0x3e6, reg1);
5331 if (phy->analog != 0)
5332 BWN_WRITE_2(mac, 0x3f4, reg2);
5333 BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, syncctl);
5334 bwn_spu_workaround(mac, phy->chan);
5335 if (phy->type == BWN_PHYTYPE_B) {
5336 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), cck3);
5337 BWN_WRITE_2(mac, 0x3ec, reg0);
5338 } else if (phy->gmode) {
5339 BWN_WRITE_2(mac, BWN_PHY_RADIO,
5340 BWN_READ_2(mac, BWN_PHY_RADIO)
5341 & 0x7fff);
5342 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover);
5343 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval);
5344 BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, analogover);
5345 BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
5346 analogoverval);
5347 BWN_PHY_WRITE(mac, BWN_PHY_CRS0, crs0);
5348 BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, classctl);
5349 if (BWN_HAS_LOOPBACK(phy)) {
5350 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, lomask);
5351 BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, loctl);
5352 }
5353 }
5354
5355 return ((i > 15) ? radio78 : rcc);
5356}
5357
5358static void
5359bwn_phy_init_b6(struct bwn_mac *mac)
5360{
5361 struct bwn_phy *phy = &mac->mac_phy;
5362 struct bwn_phy_g *pg = &phy->phy_g;
5363 struct bwn_softc *sc = mac->mac_sc;
5364 uint16_t offset, val;
5365 uint8_t old_channel;
5366
5367 KASSERT(!(phy->rf_rev == 6 || phy->rf_rev == 7),
5368 ("%s:%d: fail", __func__, __LINE__));
5369
5370 BWN_PHY_WRITE(mac, 0x003e, 0x817a);
5371 BWN_RF_WRITE(mac, 0x007a, BWN_RF_READ(mac, 0x007a) | 0x0058);
5372 if (phy->rf_rev == 4 || phy->rf_rev == 5) {
5373 BWN_RF_WRITE(mac, 0x51, 0x37);
5374 BWN_RF_WRITE(mac, 0x52, 0x70);
5375 BWN_RF_WRITE(mac, 0x53, 0xb3);
5376 BWN_RF_WRITE(mac, 0x54, 0x9b);
5377 BWN_RF_WRITE(mac, 0x5a, 0x88);
5378 BWN_RF_WRITE(mac, 0x5b, 0x88);
5379 BWN_RF_WRITE(mac, 0x5d, 0x88);
5380 BWN_RF_WRITE(mac, 0x5e, 0x88);
5381 BWN_RF_WRITE(mac, 0x7d, 0x88);
5382 bwn_hf_write(mac,
5383 bwn_hf_read(mac) | BWN_HF_TSSI_RESET_PSM_WORKAROUN);
5384 }
5385 if (phy->rf_rev == 8) {
5386 BWN_RF_WRITE(mac, 0x51, 0);
5387 BWN_RF_WRITE(mac, 0x52, 0x40);
5388 BWN_RF_WRITE(mac, 0x53, 0xb7);
5389 BWN_RF_WRITE(mac, 0x54, 0x98);
5390 BWN_RF_WRITE(mac, 0x5a, 0x88);
5391 BWN_RF_WRITE(mac, 0x5b, 0x6b);
5392 BWN_RF_WRITE(mac, 0x5c, 0x0f);
5393 if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_ALTIQ) {
5394 BWN_RF_WRITE(mac, 0x5d, 0xfa);
5395 BWN_RF_WRITE(mac, 0x5e, 0xd8);
5396 } else {
5397 BWN_RF_WRITE(mac, 0x5d, 0xf5);
5398 BWN_RF_WRITE(mac, 0x5e, 0xb8);
5399 }
5400 BWN_RF_WRITE(mac, 0x0073, 0x0003);
5401 BWN_RF_WRITE(mac, 0x007d, 0x00a8);
5402 BWN_RF_WRITE(mac, 0x007c, 0x0001);
5403 BWN_RF_WRITE(mac, 0x007e, 0x0008);
5404 }
5405 for (val = 0x1e1f, offset = 0x0088; offset < 0x0098; offset++) {
5406 BWN_PHY_WRITE(mac, offset, val);
5407 val -= 0x0202;
5408 }
5409 for (val = 0x3e3f, offset = 0x0098; offset < 0x00a8; offset++) {
5410 BWN_PHY_WRITE(mac, offset, val);
5411 val -= 0x0202;
5412 }
5413 for (val = 0x2120, offset = 0x00a8; offset < 0x00c8; offset++) {
5414 BWN_PHY_WRITE(mac, offset, (val & 0x3f3f));
5415 val += 0x0202;
5416 }
5417 if (phy->type == BWN_PHYTYPE_G) {
5418 BWN_RF_SET(mac, 0x007a, 0x0020);
5419 BWN_RF_SET(mac, 0x0051, 0x0004);
5420 BWN_PHY_SET(mac, 0x0802, 0x0100);
5421 BWN_PHY_SET(mac, 0x042b, 0x2000);
5422 BWN_PHY_WRITE(mac, 0x5b, 0);
5423 BWN_PHY_WRITE(mac, 0x5c, 0);
5424 }
5425
5426 old_channel = phy->chan;
5427 bwn_phy_g_switch_chan(mac, (old_channel >= 8) ? 1 : 13, 0);
5428
5429 BWN_RF_WRITE(mac, 0x0050, 0x0020);
5430 BWN_RF_WRITE(mac, 0x0050, 0x0023);
5431 DELAY(40);
5432 if (phy->rf_rev < 6 || phy->rf_rev == 8) {
5433 BWN_RF_WRITE(mac, 0x7c, BWN_RF_READ(mac, 0x7c) | 0x0002);
5434 BWN_RF_WRITE(mac, 0x50, 0x20);
5435 }
5436 if (phy->rf_rev <= 2) {
5437 BWN_RF_WRITE(mac, 0x7c, 0x20);
5438 BWN_RF_WRITE(mac, 0x5a, 0x70);
5439 BWN_RF_WRITE(mac, 0x5b, 0x7b);
5440 BWN_RF_WRITE(mac, 0x5c, 0xb0);
5441 }
5442 BWN_RF_SETMASK(mac, 0x007a, 0x00f8, 0x0007);
5443
5444 bwn_phy_g_switch_chan(mac, old_channel, 0);
5445
5446 BWN_PHY_WRITE(mac, 0x0014, 0x0200);
5447 if (phy->rf_rev >= 6)
5448 BWN_PHY_WRITE(mac, 0x2a, 0x88c2);
5449 else
5450 BWN_PHY_WRITE(mac, 0x2a, 0x8ac0);
5451 BWN_PHY_WRITE(mac, 0x0038, 0x0668);
5452 bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
5453 pg->pg_txctl);
5454 if (phy->rf_rev <= 5)
5455 BWN_PHY_SETMASK(mac, 0x5d, 0xff80, 0x0003);
5456 if (phy->rf_rev <= 2)
5457 BWN_RF_WRITE(mac, 0x005d, 0x000d);
5458
5459 if (phy->analog == 4) {
5460 BWN_WRITE_2(mac, 0x3e4, 9);
5461 BWN_PHY_MASK(mac, 0x61, 0x0fff);
5462 } else
5463 BWN_PHY_SETMASK(mac, 0x0002, 0xffc0, 0x0004);
5464 if (phy->type == BWN_PHYTYPE_B)
5465 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5466 else if (phy->type == BWN_PHYTYPE_G)
5467 BWN_WRITE_2(mac, 0x03e6, 0x0);
5468}
5469
5470static void
5471bwn_phy_init_a(struct bwn_mac *mac)
5472{
5473 struct bwn_phy *phy = &mac->mac_phy;
5474 struct bwn_softc *sc = mac->mac_sc;
5475
5476 KASSERT(phy->type == BWN_PHYTYPE_A || phy->type == BWN_PHYTYPE_G,
5477 ("%s:%d: fail", __func__, __LINE__));
5478
5479 if (phy->rev >= 6) {
5480 if (phy->type == BWN_PHYTYPE_A)
5481 BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x1000);
5482 if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) & BWN_PHY_ENCORE_EN)
5483 BWN_PHY_SET(mac, BWN_PHY_ENCORE, 0x0010);
5484 else
5485 BWN_PHY_MASK(mac, BWN_PHY_ENCORE, ~0x1010);
5486 }
5487
5488 bwn_wa_init(mac);
5489
5490 if (phy->type == BWN_PHYTYPE_G &&
5491 (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL))
5492 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x6e), 0xe000, 0x3cf);
5493}
5494
5495static void
5496bwn_wa_write_noisescale(struct bwn_mac *mac, const uint16_t *nst)
5497{
5498 int i;
5499
5500 for (i = 0; i < BWN_TAB_NOISESCALE_SIZE; i++)
5501 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_NOISESCALE, i, nst[i]);
5502}
5503
5504static void
5505bwn_wa_agc(struct bwn_mac *mac)
5506{
5507 struct bwn_phy *phy = &mac->mac_phy;
5508
5509 if (phy->rev == 1) {
5510 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 0, 254);
5511 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 1, 13);
5512 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 2, 19);
5513 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 3, 25);
5514 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 0, 0x2710);
5515 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 1, 0x9b83);
5516 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 2, 0x9b83);
5517 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 3, 0x0f8d);
5518 BWN_PHY_WRITE(mac, BWN_PHY_LMS, 4);
5519 } else {
5520 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 0, 254);
5521 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 1, 13);
5522 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 2, 19);
5523 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 3, 25);
5524 }
5525
5526 BWN_PHY_SETMASK(mac, BWN_PHY_CCKSHIFTBITS_WA, (uint16_t)~0xff00,
5527 0x5700);
5528 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x007f, 0x000f);
5529 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x3f80, 0x2b80);
5530 BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, 0xf0ff, 0x0300);
5531 BWN_RF_SET(mac, 0x7a, 0x0008);
5532 BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x000f, 0x0008);
5533 BWN_PHY_SETMASK(mac, BWN_PHY_P1P2GAIN, ~0x0f00, 0x0600);
5534 BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x0f00, 0x0700);
5535 BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x0f00, 0x0100);
5536 if (phy->rev == 1)
5537 BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x000f, 0x0007);
5538 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x00ff, 0x001c);
5539 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x3f00, 0x0200);
5540 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), ~0x00ff, 0x001c);
5541 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x00ff, 0x0020);
5542 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x3f00, 0x0200);
5543 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x82), ~0x00ff, 0x002e);
5544 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), (uint16_t)~0xff00, 0x1a00);
5545 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), ~0x00ff, 0x0028);
5546 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), (uint16_t)~0xff00, 0x2c00);
5547 if (phy->rev == 1) {
5548 BWN_PHY_WRITE(mac, BWN_PHY_PEAK_COUNT, 0x092b);
5549 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e, 0x0002);
5550 } else {
5551 BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e);
5552 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x1f), 0x287a);
5553 BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL, ~0x000f, 0x0004);
5554 if (phy->rev >= 6) {
5555 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x22), 0x287a);
5556 BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL,
5557 (uint16_t)~0xf000, 0x3000);
5558 }
5559 }
5560 BWN_PHY_SETMASK(mac, BWN_PHY_DIVSRCHIDX, 0x8080, 0x7874);
5561 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8e), 0x1c00);
5562 if (phy->rev == 1) {
5563 BWN_PHY_SETMASK(mac, BWN_PHY_DIVP1P2GAIN, ~0x0f00, 0x0600);
5564 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8b), 0x005e);
5565 BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, ~0x00ff, 0x001e);
5566 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8d), 0x0002);
5567 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 0, 0);
5568 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 1, 7);
5569 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 2, 16);
5570 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 3, 28);
5571 } else {
5572 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 0, 0);
5573 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 1, 7);
5574 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 2, 16);
5575 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 3, 28);
5576 }
5577 if (phy->rev >= 6) {
5578 BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x0003);
5579 BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x1000);
5580 }
5581 BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
5582}
5583
5584static void
5585bwn_wa_grev1(struct bwn_mac *mac)
5586{
5587 struct bwn_phy *phy = &mac->mac_phy;
5588 int i;
5589 static const uint16_t bwn_tab_finefreqg[] = BWN_TAB_FINEFREQ_G;
5590 static const uint32_t bwn_tab_retard[] = BWN_TAB_RETARD;
5591 static const uint32_t bwn_tab_rotor[] = BWN_TAB_ROTOR;
5592
5593 KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5594
5595 /* init CRSTHRES and ANTDWELL */
5596 if (phy->rev == 1) {
5597 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5598 } else if (phy->rev == 2) {
5599 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5600 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5601 BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5602 } else {
5603 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5604 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5605 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5606 BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5607 }
5608 BWN_PHY_SETMASK(mac, BWN_PHY_CRS0, ~0x03c0, 0xd000);
5609 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x2c), 0x005a);
5610 BWN_PHY_WRITE(mac, BWN_PHY_CCKSHIFTBITS, 0x0026);
5611
5612 /* XXX support PHY-A??? */
5613 for (i = 0; i < N(bwn_tab_finefreqg); i++)
5614 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DACRFPABB, i,
5615 bwn_tab_finefreqg[i]);
5616
5617 /* XXX support PHY-A??? */
5618 if (phy->rev == 1)
5619 for (i = 0; i < N(bwn_tab_noise_g1); i++)
5620 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5621 bwn_tab_noise_g1[i]);
5622 else
5623 for (i = 0; i < N(bwn_tab_noise_g2); i++)
5624 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5625 bwn_tab_noise_g2[i]);
5626
5627
5628 for (i = 0; i < N(bwn_tab_rotor); i++)
5629 bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ROTOR, i,
5630 bwn_tab_rotor[i]);
5631
5632 /* XXX support PHY-A??? */
5633 if (phy->rev >= 6) {
5634 if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5635 BWN_PHY_ENCORE_EN)
5636 bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5637 else
5638 bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5639 } else
5640 bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5641
5642 for (i = 0; i < N(bwn_tab_retard); i++)
5643 bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ADVRETARD, i,
5644 bwn_tab_retard[i]);
5645
5646 if (phy->rev == 1) {
5647 for (i = 0; i < 16; i++)
5648 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1,
5649 i, 0x0020);
5650 } else {
5651 for (i = 0; i < 32; i++)
5652 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5653 }
5654
5655 bwn_wa_agc(mac);
5656}
5657
5658static void
5659bwn_wa_grev26789(struct bwn_mac *mac)
5660{
5661 struct bwn_phy *phy = &mac->mac_phy;
5662 int i;
5663 static const uint16_t bwn_tab_sigmasqr2[] = BWN_TAB_SIGMASQR2;
5664 uint16_t ofdmrev;
5665
5666 KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5667
5668 bwn_gtab_write(mac, BWN_GTAB_ORIGTR, 0, 0xc480);
5669
5670 /* init CRSTHRES and ANTDWELL */
5671 if (phy->rev == 1)
5672 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5673 else if (phy->rev == 2) {
5674 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5675 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5676 BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5677 } else {
5678 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5679 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5680 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5681 BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5682 }
5683
5684 for (i = 0; i < 64; i++)
5685 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_RSSI, i, i);
5686
5687 /* XXX support PHY-A??? */
5688 if (phy->rev == 1)
5689 for (i = 0; i < N(bwn_tab_noise_g1); i++)
5690 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5691 bwn_tab_noise_g1[i]);
5692 else
5693 for (i = 0; i < N(bwn_tab_noise_g2); i++)
5694 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5695 bwn_tab_noise_g2[i]);
5696
5697 /* XXX support PHY-A??? */
5698 if (phy->rev >= 6) {
5699 if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5700 BWN_PHY_ENCORE_EN)
5701 bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5702 else
5703 bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5704 } else
5705 bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5706
5707 for (i = 0; i < N(bwn_tab_sigmasqr2); i++)
5708 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_MINSIGSQ, i,
5709 bwn_tab_sigmasqr2[i]);
5710
5711 if (phy->rev == 1) {
5712 for (i = 0; i < 16; i++)
5713 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1, i,
5714 0x0020);
5715 } else {
5716 for (i = 0; i < 32; i++)
5717 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5718 }
5719
5720 bwn_wa_agc(mac);
5721
5722 ofdmrev = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM) & BWN_PHYVER_VERSION;
5723 if (ofdmrev > 2) {
5724 if (phy->type == BWN_PHYTYPE_A)
5725 BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1808);
5726 else
5727 BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1000);
5728 } else {
5729 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 3, 0x1044);
5730 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 4, 0x7201);
5731 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 6, 0x0040);
5732 }
5733
5734 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 2, 15);
5735 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 3, 20);
5736}
5737
5738static void
5739bwn_wa_init(struct bwn_mac *mac)
5740{
5741 struct bwn_phy *phy = &mac->mac_phy;
5742 struct bwn_softc *sc = mac->mac_sc;
5743
5744 KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5745
5746 switch (phy->rev) {
5747 case 1:
5748 bwn_wa_grev1(mac);
5749 break;
5750 case 2:
5751 case 6:
5752 case 7:
5753 case 8:
5754 case 9:
5755 bwn_wa_grev26789(mac);
5756 break;
5757 default:
5758 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5759 }
5760
5761 if (siba_get_pci_subvendor(sc->sc_dev) != SIBA_BOARDVENDOR_BCM ||
5762 siba_get_pci_subdevice(sc->sc_dev) != SIBA_BOARD_BU4306 ||
5763 siba_get_pci_revid(sc->sc_dev) != 0x17) {
5764 if (phy->rev < 2) {
5765 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 1,
5766 0x0002);
5767 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 2,
5768 0x0001);
5769 } else {
5770 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 1, 0x0002);
5771 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 2, 0x0001);
5772 if ((siba_sprom_get_bf_lo(sc->sc_dev) &
5773 BWN_BFL_EXTLNA) &&
5774 (phy->rev >= 7)) {
5775 BWN_PHY_MASK(mac, BWN_PHY_EXTG(0x11), 0xf7ff);
5776 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5777 0x0020, 0x0001);
5778 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5779 0x0021, 0x0001);
5780 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5781 0x0022, 0x0001);
5782 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5783 0x0023, 0x0000);
5784 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5785 0x0000, 0x0000);
5786 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5787 0x0003, 0x0002);
5788 }
5789 }
5790 }
5791 if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM) {
5792 BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, 0x3120);
5793 BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, 0xc480);
5794 }
5795
5796 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 0, 0);
5797 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 1, 0);
5798}
5799
5800static void
5801bwn_ofdmtab_write_2(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5802 uint16_t value)
5803{
5804 struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5805 uint16_t addr;
5806
5807 addr = table + offset;
5808 if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5809 (addr - 1 != pg->pg_ofdmtab_addr)) {
5810 BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5811 pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5812 }
5813 pg->pg_ofdmtab_addr = addr;
5814 BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5815}
5816
5817static void
5818bwn_ofdmtab_write_4(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5819 uint32_t value)
5820{
5821 struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5822 uint16_t addr;
5823
5824 addr = table + offset;
5825 if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5826 (addr - 1 != pg->pg_ofdmtab_addr)) {
5827 BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5828 pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5829 }
5830 pg->pg_ofdmtab_addr = addr;
5831
5832 BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5833 BWN_PHY_WRITE(mac, BWN_PHY_OTABLEQ, (value >> 16));
5834}
5835
5836static void
5837bwn_gtab_write(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5838 uint16_t value)
5839{
5840
5841 BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, table + offset);
5842 BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, value);
5843}
5844
5845static void
5846bwn_dummy_transmission(struct bwn_mac *mac, int ofdm, int paon)
5847{
5848 struct bwn_phy *phy = &mac->mac_phy;
5849 struct bwn_softc *sc = mac->mac_sc;
5850 unsigned int i, max_loop;
5851 uint16_t value;
5852 uint32_t buffer[5] = {
5853 0x00000000, 0x00d40000, 0x00000000, 0x01000000, 0x00000000
5854 };
5855
5856 if (ofdm) {
5857 max_loop = 0x1e;
5858 buffer[0] = 0x000201cc;
5859 } else {
5860 max_loop = 0xfa;
5861 buffer[0] = 0x000b846e;
5862 }
5863
5864 BWN_ASSERT_LOCKED(mac->mac_sc);
5865
5866 for (i = 0; i < 5; i++)
5867 bwn_ram_write(mac, i * 4, buffer[i]);
5868
5869 BWN_WRITE_2(mac, 0x0568, 0x0000);
5870 BWN_WRITE_2(mac, 0x07c0,
5871 (siba_get_revid(sc->sc_dev) < 11) ? 0x0000 : 0x0100);
5872 value = ((phy->type == BWN_PHYTYPE_A) ? 0x41 : 0x40);
5873 BWN_WRITE_2(mac, 0x050c, value);
5874 if (phy->type == BWN_PHYTYPE_LP)
5875 BWN_WRITE_2(mac, 0x0514, 0x1a02);
5876 BWN_WRITE_2(mac, 0x0508, 0x0000);
5877 BWN_WRITE_2(mac, 0x050a, 0x0000);
5878 BWN_WRITE_2(mac, 0x054c, 0x0000);
5879 BWN_WRITE_2(mac, 0x056a, 0x0014);
5880 BWN_WRITE_2(mac, 0x0568, 0x0826);
5881 BWN_WRITE_2(mac, 0x0500, 0x0000);
5882 if (phy->type == BWN_PHYTYPE_LP)
5883 BWN_WRITE_2(mac, 0x0502, 0x0050);
5884 else
5885 BWN_WRITE_2(mac, 0x0502, 0x0030);
5886
5887 if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5888 BWN_RF_WRITE(mac, 0x0051, 0x0017);
5889 for (i = 0x00; i < max_loop; i++) {
5890 value = BWN_READ_2(mac, 0x050e);
5891 if (value & 0x0080)
5892 break;
5893 DELAY(10);
5894 }
5895 for (i = 0x00; i < 0x0a; i++) {
5896 value = BWN_READ_2(mac, 0x050e);
5897 if (value & 0x0400)
5898 break;
5899 DELAY(10);
5900 }
5901 for (i = 0x00; i < 0x19; i++) {
5902 value = BWN_READ_2(mac, 0x0690);
5903 if (!(value & 0x0100))
5904 break;
5905 DELAY(10);
5906 }
5907 if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5908 BWN_RF_WRITE(mac, 0x0051, 0x0037);
5909}
5910
5911static void
5912bwn_ram_write(struct bwn_mac *mac, uint16_t offset, uint32_t val)
5913{
5914 uint32_t macctl;
5915
5916 KASSERT(offset % 4 == 0, ("%s:%d: fail", __func__, __LINE__));
5917
5918 macctl = BWN_READ_4(mac, BWN_MACCTL);
5919 if (macctl & BWN_MACCTL_BIGENDIAN)
5920 printf("TODO: need swap\n");
5921
5922 BWN_WRITE_4(mac, BWN_RAM_CONTROL, offset);
5923 BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
5924 BWN_WRITE_4(mac, BWN_RAM_DATA, val);
5925}
5926
5927static void
5928bwn_lo_write(struct bwn_mac *mac, struct bwn_loctl *ctl)
5929{
5930 uint16_t value;
5931
5932 KASSERT(mac->mac_phy.type == BWN_PHYTYPE_G,
5933 ("%s:%d: fail", __func__, __LINE__));
5934
5935 value = (uint8_t) (ctl->q);
5936 value |= ((uint8_t) (ctl->i)) << 8;
5937 BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, value);
5938}
5939
5940static uint16_t
5941bwn_lo_calcfeed(struct bwn_mac *mac,
5942 uint16_t lna, uint16_t pga, uint16_t trsw_rx)
5943{
5944 struct bwn_phy *phy = &mac->mac_phy;
5945 struct bwn_softc *sc = mac->mac_sc;
5946 uint16_t rfover;
5947 uint16_t feedthrough;
5948
5949 if (phy->gmode) {
5950 lna <<= BWN_PHY_RFOVERVAL_LNA_SHIFT;
5951 pga <<= BWN_PHY_RFOVERVAL_PGA_SHIFT;
5952
5953 KASSERT((lna & ~BWN_PHY_RFOVERVAL_LNA) == 0,
5954 ("%s:%d: fail", __func__, __LINE__));
5955 KASSERT((pga & ~BWN_PHY_RFOVERVAL_PGA) == 0,
5956 ("%s:%d: fail", __func__, __LINE__));
5957
5958 trsw_rx &= (BWN_PHY_RFOVERVAL_TRSWRX | BWN_PHY_RFOVERVAL_BW);
5959
5960 rfover = BWN_PHY_RFOVERVAL_UNK | pga | lna | trsw_rx;
5961 if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA) &&
5962 phy->rev > 6)
5963 rfover |= BWN_PHY_RFOVERVAL_EXTLNA;
5964
5965 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
5966 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5967 DELAY(10);
5968 rfover |= BWN_PHY_RFOVERVAL_BW_LBW;
5969 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5970 DELAY(10);
5971 rfover |= BWN_PHY_RFOVERVAL_BW_LPF;
5972 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5973 DELAY(10);
5974 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xf300);
5975 } else {
5976 pga |= BWN_PHY_PGACTL_UNKNOWN;
5977 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5978 DELAY(10);
5979 pga |= BWN_PHY_PGACTL_LOWBANDW;
5980 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5981 DELAY(10);
5982 pga |= BWN_PHY_PGACTL_LPF;
5983 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5984 }
5985 DELAY(21);
5986 feedthrough = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5987
5988 return (feedthrough);
5989}
5990
5991static uint16_t
5992bwn_lo_txctl_regtable(struct bwn_mac *mac,
5993 uint16_t *value, uint16_t *pad_mix_gain)
5994{
5995 struct bwn_phy *phy = &mac->mac_phy;
5996 uint16_t reg, v, padmix;
5997
5998 if (phy->type == BWN_PHYTYPE_B) {
5999 v = 0x30;
6000 if (phy->rf_rev <= 5) {
6001 reg = 0x43;
6002 padmix = 0;
6003 } else {
6004 reg = 0x52;
6005 padmix = 5;
6006 }
6007 } else {
6008 if (phy->rev >= 2 && phy->rf_rev == 8) {
6009 reg = 0x43;
6010 v = 0x10;
6011 padmix = 2;
6012 } else {
6013 reg = 0x52;
6014 v = 0x30;
6015 padmix = 5;
6016 }
6017 }
6018 if (value)
6019 *value = v;
6020 if (pad_mix_gain)
6021 *pad_mix_gain = padmix;
6022
6023 return (reg);
6024}
6025
6026static void
6027bwn_lo_measure_txctl_values(struct bwn_mac *mac)
6028{
6029 struct bwn_phy *phy = &mac->mac_phy;
6030 struct bwn_phy_g *pg = &phy->phy_g;
6031 struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6032 uint16_t reg, mask;
6033 uint16_t trsw_rx, pga;
6034 uint16_t rf_pctl_reg;
6035
6036 static const uint8_t tx_bias_values[] = {
6037 0x09, 0x08, 0x0a, 0x01, 0x00,
6038 0x02, 0x05, 0x04, 0x06,
6039 };
6040 static const uint8_t tx_magn_values[] = {
6041 0x70, 0x40,
6042 };
6043
6044 if (!BWN_HAS_LOOPBACK(phy)) {
6045 rf_pctl_reg = 6;
6046 trsw_rx = 2;
6047 pga = 0;
6048 } else {
6049 int lb_gain;
6050
6051 trsw_rx = 0;
6052 lb_gain = pg->pg_max_lb_gain / 2;
6053 if (lb_gain > 10) {
6054 rf_pctl_reg = 0;
6055 pga = abs(10 - lb_gain) / 6;
6056 pga = MIN(MAX(pga, 0), 15);
6057 } else {
6058 int cmp_val;
6059 int tmp;
6060
6061 pga = 0;
6062 cmp_val = 0x24;
6063 if ((phy->rev >= 2) &&
6064 (phy->rf_ver == 0x2050) && (phy->rf_rev == 8))
6065 cmp_val = 0x3c;
6066 tmp = lb_gain;
6067 if ((10 - lb_gain) < cmp_val)
6068 tmp = (10 - lb_gain);
6069 if (tmp < 0)
6070 tmp += 6;
6071 else
6072 tmp += 3;
6073 cmp_val /= 4;
6074 tmp /= 4;
6075 if (tmp >= cmp_val)
6076 rf_pctl_reg = cmp_val;
6077 else
6078 rf_pctl_reg = tmp;
6079 }
6080 }
6081 BWN_RF_SETMASK(mac, 0x43, 0xfff0, rf_pctl_reg);
6082 bwn_phy_g_set_bbatt(mac, 2);
6083
6084 reg = bwn_lo_txctl_regtable(mac, &mask, NULL);
6085 mask = ~mask;
6086 BWN_RF_MASK(mac, reg, mask);
6087
6088 if (BWN_HAS_TXMAG(phy)) {
6089 int i, j;
6090 int feedthrough;
6091 int min_feedth = 0xffff;
6092 uint8_t tx_magn, tx_bias;
6093
6094 for (i = 0; i < N(tx_magn_values); i++) {
6095 tx_magn = tx_magn_values[i];
6096 BWN_RF_SETMASK(mac, 0x52, 0xff0f, tx_magn);
6097 for (j = 0; j < N(tx_bias_values); j++) {
6098 tx_bias = tx_bias_values[j];
6099 BWN_RF_SETMASK(mac, 0x52, 0xfff0, tx_bias);
6100 feedthrough = bwn_lo_calcfeed(mac, 0, pga,
6101 trsw_rx);
6102 if (feedthrough < min_feedth) {
6103 lo->tx_bias = tx_bias;
6104 lo->tx_magn = tx_magn;
6105 min_feedth = feedthrough;
6106 }
6107 if (lo->tx_bias == 0)
6108 break;
6109 }
6110 BWN_RF_WRITE(mac, 0x52,
6111 (BWN_RF_READ(mac, 0x52)
6112 & 0xff00) | lo->tx_bias | lo->
6113 tx_magn);
6114 }
6115 } else {
6116 lo->tx_magn = 0;
6117 lo->tx_bias = 0;
6118 BWN_RF_MASK(mac, 0x52, 0xfff0);
6119 }
6120
6121 BWN_GETTIME(lo->txctl_measured_time);
6122}
6123
6124static void
6125bwn_lo_get_powervector(struct bwn_mac *mac)
6126{
6127 struct bwn_phy *phy = &mac->mac_phy;
6128 struct bwn_phy_g *pg = &phy->phy_g;
6129 struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6130 int i;
6131 uint64_t tmp;
6132 uint64_t power_vector = 0;
6133
6134 for (i = 0; i < 8; i += 2) {
6135 tmp = bwn_shm_read_2(mac, BWN_SHARED, 0x310 + i);
6136 power_vector |= (tmp << (i * 8));
6137 bwn_shm_write_2(mac, BWN_SHARED, 0x310 + i, 0);
6138 }
6139 if (power_vector)
6140 lo->power_vector = power_vector;
6141
6142 BWN_GETTIME(lo->pwr_vec_read_time);
6143}
6144
6145static void
6146bwn_lo_measure_gain_values(struct bwn_mac *mac, int16_t max_rx_gain,
6147 int use_trsw_rx)
6148{
6149 struct bwn_phy *phy = &mac->mac_phy;
6150 struct bwn_phy_g *pg = &phy->phy_g;
6151 uint16_t tmp;
6152
6153 if (max_rx_gain < 0)
6154 max_rx_gain = 0;
6155
6156 if (BWN_HAS_LOOPBACK(phy)) {
6157 int trsw_rx = 0;
6158 int trsw_rx_gain;
6159
6160 if (use_trsw_rx) {
6161 trsw_rx_gain = pg->pg_trsw_rx_gain / 2;
6162 if (max_rx_gain >= trsw_rx_gain) {
6163 trsw_rx_gain = max_rx_gain - trsw_rx_gain;
6164 trsw_rx = 0x20;
6165 }
6166 } else
6167 trsw_rx_gain = max_rx_gain;
6168 if (trsw_rx_gain < 9) {
6169 pg->pg_lna_lod_gain = 0;
6170 } else {
6171 pg->pg_lna_lod_gain = 1;
6172 trsw_rx_gain -= 8;
6173 }
6174 trsw_rx_gain = MIN(MAX(trsw_rx_gain, 0), 0x2d);
6175 pg->pg_pga_gain = trsw_rx_gain / 3;
6176 if (pg->pg_pga_gain >= 5) {
6177 pg->pg_pga_gain -= 5;
6178 pg->pg_lna_gain = 2;
6179 } else
6180 pg->pg_lna_gain = 0;
6181 } else {
6182 pg->pg_lna_gain = 0;
6183 pg->pg_trsw_rx_gain = 0x20;
6184 if (max_rx_gain >= 0x14) {
6185 pg->pg_lna_lod_gain = 1;
6186 pg->pg_pga_gain = 2;
6187 } else if (max_rx_gain >= 0x12) {
6188 pg->pg_lna_lod_gain = 1;
6189 pg->pg_pga_gain = 1;
6190 } else if (max_rx_gain >= 0xf) {
6191 pg->pg_lna_lod_gain = 1;
6192 pg->pg_pga_gain = 0;
6193 } else {
6194 pg->pg_lna_lod_gain = 0;
6195 pg->pg_pga_gain = 0;
6196 }
6197 }
6198
6199 tmp = BWN_RF_READ(mac, 0x7a);
6200 if (pg->pg_lna_lod_gain == 0)
6201 tmp &= ~0x0008;
6202 else
6203 tmp |= 0x0008;
6204 BWN_RF_WRITE(mac, 0x7a, tmp);
6205}
6206
6207static void
6208bwn_lo_save(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6209{
6210 struct bwn_phy *phy = &mac->mac_phy;
6211 struct bwn_phy_g *pg = &phy->phy_g;
6212 struct bwn_softc *sc = mac->mac_sc;
6213 struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6214 struct timespec ts;
6215 uint16_t tmp;
6216
6217 if (bwn_has_hwpctl(mac)) {
6218 sav->phy_lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
6219 sav->phy_extg = BWN_PHY_READ(mac, BWN_PHY_EXTG(0x01));
6220 sav->phy_dacctl_hwpctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6221 sav->phy_cck4 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x14));
6222 sav->phy_hpwr_tssictl = BWN_PHY_READ(mac, BWN_PHY_HPWR_TSSICTL);
6223
6224 BWN_PHY_SET(mac, BWN_PHY_HPWR_TSSICTL, 0x100);
6225 BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x40);
6226 BWN_PHY_SET(mac, BWN_PHY_DACCTL, 0x40);
6227 BWN_PHY_SET(mac, BWN_PHY_CCK(0x14), 0x200);
6228 }
6229 if (phy->type == BWN_PHYTYPE_B &&
6230 phy->rf_ver == 0x2050 && phy->rf_rev < 6) {
6231 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x16), 0x410);
6232 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x17), 0x820);
6233 }
6234 if (phy->rev >= 2) {
6235 sav->phy_analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
6236 sav->phy_analogoverval =
6237 BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
6238 sav->phy_rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
6239 sav->phy_rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
6240 sav->phy_classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
6241 sav->phy_cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x3e));
6242 sav->phy_crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
6243
6244 BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
6245 BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
6246 BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
6247 BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
6248 if (phy->type == BWN_PHYTYPE_G) {
6249 if ((phy->rev >= 7) &&
6250 (siba_sprom_get_bf_lo(sc->sc_dev) &
6251 BWN_BFL_EXTLNA)) {
6252 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x933);
6253 } else {
6254 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x133);
6255 }
6256 } else {
6257 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
6258 }
6259 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), 0);
6260 }
6261 sav->reg0 = BWN_READ_2(mac, 0x3f4);
6262 sav->reg1 = BWN_READ_2(mac, 0x3e2);
6263 sav->rf0 = BWN_RF_READ(mac, 0x43);
6264 sav->rf1 = BWN_RF_READ(mac, 0x7a);
6265 sav->phy_pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
6266 sav->phy_cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2a));
6267 sav->phy_syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
6268 sav->phy_dacctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6269
6270 if (!BWN_HAS_TXMAG(phy)) {
6271 sav->rf2 = BWN_RF_READ(mac, 0x52);
6272 sav->rf2 &= 0x00f0;
6273 }
6274 if (phy->type == BWN_PHYTYPE_B) {
6275 sav->phy_cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
6276 sav->phy_cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x06));
6277 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0x00ff);
6278 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), 0x3f3f);
6279 } else {
6280 BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2)
6281 | 0x8000);
6282 }
6283 BWN_WRITE_2(mac, 0x3f4, BWN_READ_2(mac, 0x3f4)
6284 & 0xf000);
6285
6286 tmp =
6287 (phy->type == BWN_PHYTYPE_G) ? BWN_PHY_LO_MASK : BWN_PHY_CCK(0x2e);
6288 BWN_PHY_WRITE(mac, tmp, 0x007f);
6289
6290 tmp = sav->phy_syncctl;
6291 BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, tmp & 0xff7f);
6292 tmp = sav->rf1;
6293 BWN_RF_WRITE(mac, 0x007a, tmp & 0xfff0);
6294
6295 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), 0x8a3);
6296 if (phy->type == BWN_PHYTYPE_G ||
6297 (phy->type == BWN_PHYTYPE_B &&
6298 phy->rf_ver == 0x2050 && phy->rf_rev >= 6)) {
6299 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1003);
6300 } else
6301 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x0802);
6302 if (phy->rev >= 2)
6303 bwn_dummy_transmission(mac, 0, 1);
6304 bwn_phy_g_switch_chan(mac, 6, 0);
6305 BWN_RF_READ(mac, 0x51);
6306 if (phy->type == BWN_PHYTYPE_G)
6307 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0);
6308
6309 nanouptime(&ts);
6310 if (time_before(lo->txctl_measured_time,
6311 (ts.tv_nsec / 1000000 + ts.tv_sec * 1000) - BWN_LO_TXCTL_EXPIRE))
6312 bwn_lo_measure_txctl_values(mac);
6313
6314 if (phy->type == BWN_PHYTYPE_G && phy->rev >= 3)
6315 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc078);
6316 else {
6317 if (phy->type == BWN_PHYTYPE_B)
6318 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6319 else
6320 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
6321 }
6322}
6323
6324static void
6325bwn_lo_restore(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6326{
6327 struct bwn_phy *phy = &mac->mac_phy;
6328 struct bwn_phy_g *pg = &phy->phy_g;
6329 uint16_t tmp;
6330
6331 if (phy->rev >= 2) {
6332 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
6333 tmp = (pg->pg_pga_gain << 8);
6334 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa0);
6335 DELAY(5);
6336 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa2);
6337 DELAY(2);
6338 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa3);
6339 } else {
6340 tmp = (pg->pg_pga_gain | 0xefa0);
6341 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, tmp);
6342 }
6343 if (phy->type == BWN_PHYTYPE_G) {
6344 if (phy->rev >= 3)
6345 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0xc078);
6346 else
6347 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6348 if (phy->rev >= 2)
6349 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0202);
6350 else
6351 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0101);
6352 }
6353 BWN_WRITE_2(mac, 0x3f4, sav->reg0);
6354 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, sav->phy_pgactl);
6355 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), sav->phy_cck2);
6356 BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, sav->phy_syncctl);
6357 BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl);
6358 BWN_RF_WRITE(mac, 0x43, sav->rf0);
6359 BWN_RF_WRITE(mac, 0x7a, sav->rf1);
6360 if (!BWN_HAS_TXMAG(phy)) {
6361 tmp = sav->rf2;
6362 BWN_RF_SETMASK(mac, 0x52, 0xff0f, tmp);
6363 }
6364 BWN_WRITE_2(mac, 0x3e2, sav->reg1);
6365 if (phy->type == BWN_PHYTYPE_B &&
6366 phy->rf_ver == 0x2050 && phy->rf_rev <= 5) {
6367 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), sav->phy_cck0);
6368 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), sav->phy_cck1);
6369 }
6370 if (phy->rev >= 2) {
6371 BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, sav->phy_analogover);
6372 BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
6373 sav->phy_analogoverval);
6374 BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, sav->phy_classctl);
6375 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, sav->phy_rfover);
6376 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, sav->phy_rfoverval);
6377 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), sav->phy_cck3);
6378 BWN_PHY_WRITE(mac, BWN_PHY_CRS0, sav->phy_crs0);
6379 }
6380 if (bwn_has_hwpctl(mac)) {
6381 tmp = (sav->phy_lomask & 0xbfff);
6382 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, tmp);
6383 BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x01), sav->phy_extg);
6384 BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl_hwpctl);
6385 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x14), sav->phy_cck4);
6386 BWN_PHY_WRITE(mac, BWN_PHY_HPWR_TSSICTL, sav->phy_hpwr_tssictl);
6387 }
6388 bwn_phy_g_switch_chan(mac, sav->old_channel, 1);
6389}
6390
6391static int
6392bwn_lo_probe_loctl(struct bwn_mac *mac,
6393 struct bwn_loctl *probe, struct bwn_lo_g_sm *d)
6394{
6395 struct bwn_phy *phy = &mac->mac_phy;
6396 struct bwn_phy_g *pg = &phy->phy_g;
6397 struct bwn_loctl orig, test;
6398 struct bwn_loctl prev = { -100, -100 };
6399 static const struct bwn_loctl modifiers[] = {
6400 { 1, 1,}, { 1, 0,}, { 1, -1,}, { 0, -1,},
6401 { -1, -1,}, { -1, 0,}, { -1, 1,}, { 0, 1,}
6402 };
6403 int begin, end, lower = 0, i;
6404 uint16_t feedth;
6405
6406 if (d->curstate == 0) {
6407 begin = 1;
6408 end = 8;
6409 } else if (d->curstate % 2 == 0) {
6410 begin = d->curstate - 1;
6411 end = d->curstate + 1;
6412 } else {
6413 begin = d->curstate - 2;
6414 end = d->curstate + 2;
6415 }
6416 if (begin < 1)
6417 begin += 8;
6418 if (end > 8)
6419 end -= 8;
6420
6421 memcpy(&orig, probe, sizeof(struct bwn_loctl));
6422 i = begin;
6423 d->curstate = i;
6424 while (1) {
6425 KASSERT(i >= 1 && i <= 8, ("%s:%d: fail", __func__, __LINE__));
6426 memcpy(&test, &orig, sizeof(struct bwn_loctl));
6427 test.i += modifiers[i - 1].i * d->multipler;
6428 test.q += modifiers[i - 1].q * d->multipler;
6429 if ((test.i != prev.i || test.q != prev.q) &&
6430 (abs(test.i) <= 16 && abs(test.q) <= 16)) {
6431 bwn_lo_write(mac, &test);
6432 feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6433 pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6434 if (feedth < d->feedth) {
6435 memcpy(probe, &test,
6436 sizeof(struct bwn_loctl));
6437 lower = 1;
6438 d->feedth = feedth;
6439 if (d->nmeasure < 2 && !BWN_HAS_LOOPBACK(phy))
6440 break;
6441 }
6442 }
6443 memcpy(&prev, &test, sizeof(prev));
6444 if (i == end)
6445 break;
6446 if (i == 8)
6447 i = 1;
6448 else
6449 i++;
6450 d->curstate = i;
6451 }
6452
6453 return (lower);
6454}
6455
6456static void
6457bwn_lo_probe_sm(struct bwn_mac *mac, struct bwn_loctl *loctl, int *rxgain)
6458{
6459 struct bwn_phy *phy = &mac->mac_phy;
6460 struct bwn_phy_g *pg = &phy->phy_g;
6461 struct bwn_lo_g_sm d;
6462 struct bwn_loctl probe;
6463 int lower, repeat, cnt = 0;
6464 uint16_t feedth;
6465
6466 d.nmeasure = 0;
6467 d.multipler = 1;
6468 if (BWN_HAS_LOOPBACK(phy))
6469 d.multipler = 3;
6470
6471 memcpy(&d.loctl, loctl, sizeof(struct bwn_loctl));
6472 repeat = (BWN_HAS_LOOPBACK(phy)) ? 4 : 1;
6473
6474 do {
6475 bwn_lo_write(mac, &d.loctl);
6476 feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6477 pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6478 if (feedth < 0x258) {
6479 if (feedth >= 0x12c)
6480 *rxgain += 6;
6481 else
6482 *rxgain += 3;
6483 feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6484 pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6485 }
6486 d.feedth = feedth;
6487 d.curstate = 0;
6488 do {
6489 KASSERT(d.curstate >= 0 && d.curstate <= 8,
6490 ("%s:%d: fail", __func__, __LINE__));
6491 memcpy(&probe, &d.loctl,
6492 sizeof(struct bwn_loctl));
6493 lower = bwn_lo_probe_loctl(mac, &probe, &d);
6494 if (!lower)
6495 break;
6496 if ((probe.i == d.loctl.i) && (probe.q == d.loctl.q))
6497 break;
6498 memcpy(&d.loctl, &probe, sizeof(struct bwn_loctl));
6499 d.nmeasure++;
6500 } while (d.nmeasure < 24);
6501 memcpy(loctl, &d.loctl, sizeof(struct bwn_loctl));
6502
6503 if (BWN_HAS_LOOPBACK(phy)) {
6504 if (d.feedth > 0x1194)
6505 *rxgain -= 6;
6506 else if (d.feedth < 0x5dc)
6507 *rxgain += 3;
6508 if (cnt == 0) {
6509 if (d.feedth <= 0x5dc) {
6510 d.multipler = 1;
6511 cnt++;
6512 } else
6513 d.multipler = 2;
6514 } else if (cnt == 2)
6515 d.multipler = 1;
6516 }
6517 bwn_lo_measure_gain_values(mac, *rxgain, BWN_HAS_LOOPBACK(phy));
6518 } while (++cnt < repeat);
6519}
6520
6521static struct bwn_lo_calib *
6522bwn_lo_calibset(struct bwn_mac *mac,
6523 const struct bwn_bbatt *bbatt, const struct bwn_rfatt *rfatt)
6524{
6525 struct bwn_phy *phy = &mac->mac_phy;
6526 struct bwn_phy_g *pg = &phy->phy_g;
6527 struct bwn_loctl loctl = { 0, 0 };
6528 struct bwn_lo_calib *cal;
6529 struct bwn_lo_g_value sval = { 0 };
6530 int rxgain;
6531 uint16_t pad, reg, value;
6532
6533 sval.old_channel = phy->chan;
6534 bwn_mac_suspend(mac);
6535 bwn_lo_save(mac, &sval);
6536
6537 reg = bwn_lo_txctl_regtable(mac, &value, &pad);
6538 BWN_RF_SETMASK(mac, 0x43, 0xfff0, rfatt->att);
6539 BWN_RF_SETMASK(mac, reg, ~value, (rfatt->padmix ? value :0));
6540
6541 rxgain = (rfatt->att * 2) + (bbatt->att / 2);
6542 if (rfatt->padmix)
6543 rxgain -= pad;
6544 if (BWN_HAS_LOOPBACK(phy))
6545 rxgain += pg->pg_max_lb_gain;
6546 bwn_lo_measure_gain_values(mac, rxgain, BWN_HAS_LOOPBACK(phy));
6547 bwn_phy_g_set_bbatt(mac, bbatt->att);
6548 bwn_lo_probe_sm(mac, &loctl, &rxgain);
6549
6550 bwn_lo_restore(mac, &sval);
6551 bwn_mac_enable(mac);
6552
6553 cal = malloc(sizeof(*cal), M_DEVBUF, M_NOWAIT | M_ZERO);
6554 if (!cal) {
6555 device_printf(mac->mac_sc->sc_dev, "out of memory\n");
6556 return (NULL);
6557 }
6558 memcpy(&cal->bbatt, bbatt, sizeof(*bbatt));
6559 memcpy(&cal->rfatt, rfatt, sizeof(*rfatt));
6560 memcpy(&cal->ctl, &loctl, sizeof(loctl));
6561
6562 BWN_GETTIME(cal->calib_time);
6563
6564 return (cal);
6565}
6566
6567static struct bwn_lo_calib *
6568bwn_lo_get_calib(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
6569 const struct bwn_rfatt *rfatt)
6570{
6571 struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
6572 struct bwn_lo_calib *c;
6573
6574 TAILQ_FOREACH(c, &lo->calib_list, list) {
6575 if (!BWN_BBATTCMP(&c->bbatt, bbatt))
6576 continue;
6577 if (!BWN_RFATTCMP(&c->rfatt, rfatt))
6578 continue;
6579 return (c);
6580 }
6581
6582 c = bwn_lo_calibset(mac, bbatt, rfatt);
6583 if (!c)
6584 return (NULL);
6585 TAILQ_INSERT_TAIL(&lo->calib_list, c, list);
6586
6587 return (c);
6588}
6589
6590static void
6591bwn_phy_g_dc_lookup_init(struct bwn_mac *mac, uint8_t update)
6592{
6593 struct bwn_phy *phy = &mac->mac_phy;
6594 struct bwn_phy_g *pg = &phy->phy_g;
6595 struct bwn_softc *sc = mac->mac_sc;
6596 struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6597 const struct bwn_rfatt *rfatt;
6598 const struct bwn_bbatt *bbatt;
6599 uint64_t pvector;
6600 int i;
6601 int rf_offset, bb_offset;
6602 uint8_t changed = 0;
6603
6604 KASSERT(BWN_DC_LT_SIZE == 32, ("%s:%d: fail", __func__, __LINE__));
6605 KASSERT(lo->rfatt.len * lo->bbatt.len <= 64,
6606 ("%s:%d: fail", __func__, __LINE__));
6607
6608 pvector = lo->power_vector;
6609 if (!update && !pvector)
6610 return;
6611
6612 bwn_mac_suspend(mac);
6613
6614 for (i = 0; i < BWN_DC_LT_SIZE * 2; i++) {
6615 struct bwn_lo_calib *cal;
6616 int idx;
6617 uint16_t val;
6618
6619 if (!update && !(pvector & (((uint64_t)1ULL) << i)))
6620 continue;
6621 bb_offset = i / lo->rfatt.len;
6622 rf_offset = i % lo->rfatt.len;
6623 bbatt = &(lo->bbatt.array[bb_offset]);
6624 rfatt = &(lo->rfatt.array[rf_offset]);
6625
6626 cal = bwn_lo_calibset(mac, bbatt, rfatt);
6627 if (!cal) {
6628 device_printf(sc->sc_dev, "LO: Could not "
6629 "calibrate DC table entry\n");
6630 continue;
6631 }
6632 val = (uint8_t)(cal->ctl.q);
6633 val |= ((uint8_t)(cal->ctl.i)) << 4;
6634 free(cal, M_DEVBUF);
6635
6636 idx = i / 2;
6637 if (i % 2)
6638 lo->dc_lt[idx] = (lo->dc_lt[idx] & 0x00ff)
6639 | ((val & 0x00ff) << 8);
6640 else
6641 lo->dc_lt[idx] = (lo->dc_lt[idx] & 0xff00)
6642 | (val & 0x00ff);
6643 changed = 1;
6644 }
6645 if (changed) {
6646 for (i = 0; i < BWN_DC_LT_SIZE; i++)
6647 BWN_PHY_WRITE(mac, 0x3a0 + i, lo->dc_lt[i]);
6648 }
6649 bwn_mac_enable(mac);
6650}
6651
6652static void
6653bwn_lo_fixup_rfatt(struct bwn_rfatt *rf)
6654{
6655
6656 if (!rf->padmix)
6657 return;
6658 if ((rf->att != 1) && (rf->att != 2) && (rf->att != 3))
6659 rf->att = 4;
6660}
6661
6662static void
6663bwn_lo_g_adjust(struct bwn_mac *mac)
6664{
6665 struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
6666 struct bwn_lo_calib *cal;
6667 struct bwn_rfatt rf;
6668
6669 memcpy(&rf, &pg->pg_rfatt, sizeof(rf));
6670 bwn_lo_fixup_rfatt(&rf);
6671
6672 cal = bwn_lo_get_calib(mac, &pg->pg_bbatt, &rf);
6673 if (!cal)
6674 return;
6675 bwn_lo_write(mac, &cal->ctl);
6676}
6677
6678static void
6679bwn_lo_g_init(struct bwn_mac *mac)
6680{
6681
6682 if (!bwn_has_hwpctl(mac))
6683 return;
6684
6685 bwn_lo_get_powervector(mac);
6686 bwn_phy_g_dc_lookup_init(mac, 1);
6687}
6688
6689static void
6690bwn_mac_suspend(struct bwn_mac *mac)
6691{
6692 struct bwn_softc *sc = mac->mac_sc;
6693 int i;
6694 uint32_t tmp;
6695
6696 KASSERT(mac->mac_suspended >= 0,
6697 ("%s:%d: fail", __func__, __LINE__));
6698
6699 if (mac->mac_suspended == 0) {
6700 bwn_psctl(mac, BWN_PS_AWAKE);
6701 BWN_WRITE_4(mac, BWN_MACCTL,
6702 BWN_READ_4(mac, BWN_MACCTL)
6703 & ~BWN_MACCTL_ON);
6704 BWN_READ_4(mac, BWN_MACCTL);
6705 for (i = 35; i; i--) {
6706 tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6707 if (tmp & BWN_INTR_MAC_SUSPENDED)
6708 goto out;
6709 DELAY(10);
6710 }
6711 for (i = 40; i; i--) {
6712 tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6713 if (tmp & BWN_INTR_MAC_SUSPENDED)
6714 goto out;
6715 DELAY(1000);
6716 }
6717 device_printf(sc->sc_dev, "MAC suspend failed\n");
6718 }
6719out:
6720 mac->mac_suspended++;
6721}
6722
6723static void
6724bwn_mac_enable(struct bwn_mac *mac)
6725{
6726 struct bwn_softc *sc = mac->mac_sc;
6727 uint16_t state;
6728
6729 state = bwn_shm_read_2(mac, BWN_SHARED,
6730 BWN_SHARED_UCODESTAT);
6731 if (state != BWN_SHARED_UCODESTAT_SUSPEND &&
6732 state != BWN_SHARED_UCODESTAT_SLEEP)
6733 device_printf(sc->sc_dev, "warn: firmware state (%d)\n", state);
6734
6735 mac->mac_suspended--;
6736 KASSERT(mac->mac_suspended >= 0,
6737 ("%s:%d: fail", __func__, __LINE__));
6738 if (mac->mac_suspended == 0) {
6739 BWN_WRITE_4(mac, BWN_MACCTL,
6740 BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_ON);
6741 BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_MAC_SUSPENDED);
6742 BWN_READ_4(mac, BWN_MACCTL);
6743 BWN_READ_4(mac, BWN_INTR_REASON);
6744 bwn_psctl(mac, 0);
6745 }
6746}
6747
6748static void
6749bwn_psctl(struct bwn_mac *mac, uint32_t flags)
6750{
6751 struct bwn_softc *sc = mac->mac_sc;
6752 int i;
6753 uint16_t ucstat;
6754
6755 KASSERT(!((flags & BWN_PS_ON) && (flags & BWN_PS_OFF)),
6756 ("%s:%d: fail", __func__, __LINE__));
6757 KASSERT(!((flags & BWN_PS_AWAKE) && (flags & BWN_PS_ASLEEP)),
6758 ("%s:%d: fail", __func__, __LINE__));
6759
6760 /* XXX forcibly awake and hwps-off */
6761
6762 BWN_WRITE_4(mac, BWN_MACCTL,
6763 (BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_AWAKE) &
6764 ~BWN_MACCTL_HWPS);
6765 BWN_READ_4(mac, BWN_MACCTL);
6766 if (siba_get_revid(sc->sc_dev) >= 5) {
6767 for (i = 0; i < 100; i++) {
6768 ucstat = bwn_shm_read_2(mac, BWN_SHARED,
6769 BWN_SHARED_UCODESTAT);
6770 if (ucstat != BWN_SHARED_UCODESTAT_SLEEP)
6771 break;
6772 DELAY(10);
6773 }
6774 }
6775}
6776
6777static int16_t
6778bwn_nrssi_read(struct bwn_mac *mac, uint16_t offset)
6779{
6780
6781 BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, offset);
6782 return ((int16_t)BWN_PHY_READ(mac, BWN_PHY_NRSSI_DATA));
6783}
6784
6785static void
6786bwn_nrssi_threshold(struct bwn_mac *mac)
6787{
6788 struct bwn_phy *phy = &mac->mac_phy;
6789 struct bwn_phy_g *pg = &phy->phy_g;
6790 struct bwn_softc *sc = mac->mac_sc;
6791 int32_t a, b;
6792 int16_t tmp16;
6793 uint16_t tmpu16;
6794
6795 KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
6796
6797 if (phy->gmode && (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI)) {
6798 if (!pg->pg_aci_wlan_automatic && pg->pg_aci_enable) {
6799 a = 0x13;
6800 b = 0x12;
6801 } else {
6802 a = 0xe;
6803 b = 0x11;
6804 }
6805
6806 a = a * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6807 a += (pg->pg_nrssi[0] << 6);
6808 a += (a < 32) ? 31 : 32;
6809 a = a >> 6;
6810 a = MIN(MAX(a, -31), 31);
6811
6812 b = b * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6813 b += (pg->pg_nrssi[0] << 6);
6814 if (b < 32)
6815 b += 31;
6816 else
6817 b += 32;
6818 b = b >> 6;
6819 b = MIN(MAX(b, -31), 31);
6820
6821 tmpu16 = BWN_PHY_READ(mac, 0x048a) & 0xf000;
6822 tmpu16 |= ((uint32_t)b & 0x0000003f);
6823 tmpu16 |= (((uint32_t)a & 0x0000003f) << 6);
6824 BWN_PHY_WRITE(mac, 0x048a, tmpu16);
6825 return;
6826 }
6827
6828 tmp16 = bwn_nrssi_read(mac, 0x20);
6829 if (tmp16 >= 0x20)
6830 tmp16 -= 0x40;
6831 BWN_PHY_SETMASK(mac, 0x048a, 0xf000, (tmp16 < 3) ? 0x09eb : 0x0aed);
6832}
6833
6834static void
6835bwn_nrssi_slope_11g(struct bwn_mac *mac)
6836{
6837#define SAVE_RF_MAX 3
6838#define SAVE_PHY_COMM_MAX 4
6839#define SAVE_PHY3_MAX 8
6840 static const uint16_t save_rf_regs[SAVE_RF_MAX] =
6841 { 0x7a, 0x52, 0x43 };
6842 static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] =
6843 { 0x15, 0x5a, 0x59, 0x58 };
6844 static const uint16_t save_phy3_regs[SAVE_PHY3_MAX] = {
6845 0x002e, 0x002f, 0x080f, BWN_PHY_G_LOCTL,
6846 0x0801, 0x0060, 0x0014, 0x0478
6847 };
6848 struct bwn_phy *phy = &mac->mac_phy;
6849 struct bwn_phy_g *pg = &phy->phy_g;
6850 int32_t i, tmp32, phy3_idx = 0;
6851 uint16_t delta, tmp;
6852 uint16_t save_rf[SAVE_RF_MAX];
6853 uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
6854 uint16_t save_phy3[SAVE_PHY3_MAX];
6855 uint16_t ant_div, phy0, chan_ex;
6856 int16_t nrssi0, nrssi1;
6857
6858 KASSERT(phy->type == BWN_PHYTYPE_G,
6859 ("%s:%d: fail", __func__, __LINE__));
6860
6861 if (phy->rf_rev >= 9)
6862 return;
6863 if (phy->rf_rev == 8)
6864 bwn_nrssi_offset(mac);
6865
6866 BWN_PHY_MASK(mac, BWN_PHY_G_CRS, 0x7fff);
6867 BWN_PHY_MASK(mac, 0x0802, 0xfffc);
6868
6869 /*
6870 * Save RF/PHY registers for later restoration
6871 */
6872 ant_div = BWN_READ_2(mac, 0x03e2);
6873 BWN_WRITE_2(mac, 0x03e2, BWN_READ_2(mac, 0x03e2) | 0x8000);
6874 for (i = 0; i < SAVE_RF_MAX; ++i)
6875 save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
6876 for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6877 save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
6878
6879 phy0 = BWN_READ_2(mac, BWN_PHY0);
6880 chan_ex = BWN_READ_2(mac, BWN_CHANNEL_EXT);
6881 if (phy->rev >= 3) {
6882 for (i = 0; i < SAVE_PHY3_MAX; ++i)
6883 save_phy3[i] = BWN_PHY_READ(mac, save_phy3_regs[i]);
6884 BWN_PHY_WRITE(mac, 0x002e, 0);
6885 BWN_PHY_WRITE(mac, BWN_PHY_G_LOCTL, 0);
6886 switch (phy->rev) {
6887 case 4:
6888 case 6:
6889 case 7:
6890 BWN_PHY_SET(mac, 0x0478, 0x0100);
6891 BWN_PHY_SET(mac, 0x0801, 0x0040);
6892 break;
6893 case 3:
6894 case 5:
6895 BWN_PHY_MASK(mac, 0x0801, 0xffbf);
6896 break;
6897 }
6898 BWN_PHY_SET(mac, 0x0060, 0x0040);
6899 BWN_PHY_SET(mac, 0x0014, 0x0200);
6900 }
6901 /*
6902 * Calculate nrssi0
6903 */
6904 BWN_RF_SET(mac, 0x007a, 0x0070);
6905 bwn_set_all_gains(mac, 0, 8, 0);
6906 BWN_RF_MASK(mac, 0x007a, 0x00f7);
6907 if (phy->rev >= 2) {
6908 BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0030);
6909 BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0010);
6910 }
6911 BWN_RF_SET(mac, 0x007a, 0x0080);
6912 DELAY(20);
6913
6914 nrssi0 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6915 if (nrssi0 >= 0x0020)
6916 nrssi0 -= 0x0040;
6917
6918 /*
6919 * Calculate nrssi1
6920 */
6921 BWN_RF_MASK(mac, 0x007a, 0x007f);
6922 if (phy->rev >= 2)
6923 BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
6924
6925 BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
6926 BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000);
6927 BWN_RF_SET(mac, 0x007a, 0x000f);
6928 BWN_PHY_WRITE(mac, 0x0015, 0xf330);
6929 if (phy->rev >= 2) {
6930 BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0020);
6931 BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0020);
6932 }
6933
6934 bwn_set_all_gains(mac, 3, 0, 1);
6935 if (phy->rf_rev == 8) {
6936 BWN_RF_WRITE(mac, 0x0043, 0x001f);
6937 } else {
6938 tmp = BWN_RF_READ(mac, 0x0052) & 0xff0f;
6939 BWN_RF_WRITE(mac, 0x0052, tmp | 0x0060);
6940 tmp = BWN_RF_READ(mac, 0x0043) & 0xfff0;
6941 BWN_RF_WRITE(mac, 0x0043, tmp | 0x0009);
6942 }
6943 BWN_PHY_WRITE(mac, 0x005a, 0x0480);
6944 BWN_PHY_WRITE(mac, 0x0059, 0x0810);
6945 BWN_PHY_WRITE(mac, 0x0058, 0x000d);
6946 DELAY(20);
6947 nrssi1 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6948
6949 /*
6950 * Install calculated narrow RSSI values
6951 */
6952 if (nrssi1 >= 0x0020)
6953 nrssi1 -= 0x0040;
6954 if (nrssi0 == nrssi1)
6955 pg->pg_nrssi_slope = 0x00010000;
6956 else
6957 pg->pg_nrssi_slope = 0x00400000 / (nrssi0 - nrssi1);
6958 if (nrssi0 >= -4) {
6959 pg->pg_nrssi[0] = nrssi1;
6960 pg->pg_nrssi[1] = nrssi0;
6961 }
6962
6963 /*
6964 * Restore saved RF/PHY registers
6965 */
6966 if (phy->rev >= 3) {
6967 for (phy3_idx = 0; phy3_idx < 4; ++phy3_idx) {
6968 BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
6969 save_phy3[phy3_idx]);
6970 }
6971 }
6972 if (phy->rev >= 2) {
6973 BWN_PHY_MASK(mac, 0x0812, 0xffcf);
6974 BWN_PHY_MASK(mac, 0x0811, 0xffcf);
6975 }
6976
6977 for (i = 0; i < SAVE_RF_MAX; ++i)
6978 BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
6979
6980 BWN_WRITE_2(mac, 0x03e2, ant_div);
6981 BWN_WRITE_2(mac, 0x03e6, phy0);
6982 BWN_WRITE_2(mac, BWN_CHANNEL_EXT, chan_ex);
6983
6984 for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6985 BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
6986
6987 bwn_spu_workaround(mac, phy->chan);
6988 BWN_PHY_SET(mac, 0x0802, (0x0001 | 0x0002));
6989 bwn_set_original_gains(mac);
6990 BWN_PHY_SET(mac, BWN_PHY_G_CRS, 0x8000);
6991 if (phy->rev >= 3) {
6992 for (; phy3_idx < SAVE_PHY3_MAX; ++phy3_idx) {
6993 BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
6994 save_phy3[phy3_idx]);
6995 }
6996 }
6997
6998 delta = 0x1f - pg->pg_nrssi[0];
6999 for (i = 0; i < 64; i++) {
7000 tmp32 = (((i - delta) * pg->pg_nrssi_slope) / 0x10000) + 0x3a;
7001 tmp32 = MIN(MAX(tmp32, 0), 0x3f);
7002 pg->pg_nrssi_lt[i] = tmp32;
7003 }
7004
7005 bwn_nrssi_threshold(mac);
7006#undef SAVE_RF_MAX
7007#undef SAVE_PHY_COMM_MAX
7008#undef SAVE_PHY3_MAX
7009}
7010
7011static void
7012bwn_nrssi_offset(struct bwn_mac *mac)
7013{
7014#define SAVE_RF_MAX 2
7015#define SAVE_PHY_COMM_MAX 10
7016#define SAVE_PHY6_MAX 8
7017 static const uint16_t save_rf_regs[SAVE_RF_MAX] =
7018 { 0x7a, 0x43 };
7019 static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] = {
7020 0x0001, 0x0811, 0x0812, 0x0814,
7021 0x0815, 0x005a, 0x0059, 0x0058,
7022 0x000a, 0x0003
7023 };
7024 static const uint16_t save_phy6_regs[SAVE_PHY6_MAX] = {
7025 0x002e, 0x002f, 0x080f, 0x0810,
7026 0x0801, 0x0060, 0x0014, 0x0478
7027 };
7028 struct bwn_phy *phy = &mac->mac_phy;
7029 int i, phy6_idx = 0;
7030 uint16_t save_rf[SAVE_RF_MAX];
7031 uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
7032 uint16_t save_phy6[SAVE_PHY6_MAX];
7033 int16_t nrssi;
7034 uint16_t saved = 0xffff;
7035
7036 for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
7037 save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
7038 for (i = 0; i < SAVE_RF_MAX; ++i)
7039 save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
7040
7041 BWN_PHY_MASK(mac, 0x0429, 0x7fff);
7042 BWN_PHY_SETMASK(mac, 0x0001, 0x3fff, 0x4000);
7043 BWN_PHY_SET(mac, 0x0811, 0x000c);
7044 BWN_PHY_SETMASK(mac, 0x0812, 0xfff3, 0x0004);
7045 BWN_PHY_MASK(mac, 0x0802, ~(0x1 | 0x2));
7046 if (phy->rev >= 6) {
7047 for (i = 0; i < SAVE_PHY6_MAX; ++i)
7048 save_phy6[i] = BWN_PHY_READ(mac, save_phy6_regs[i]);
7049
7050 BWN_PHY_WRITE(mac, 0x002e, 0);
7051 BWN_PHY_WRITE(mac, 0x002f, 0);
7052 BWN_PHY_WRITE(mac, 0x080f, 0);
7053 BWN_PHY_WRITE(mac, 0x0810, 0);
7054 BWN_PHY_SET(mac, 0x0478, 0x0100);
7055 BWN_PHY_SET(mac, 0x0801, 0x0040);
7056 BWN_PHY_SET(mac, 0x0060, 0x0040);
7057 BWN_PHY_SET(mac, 0x0014, 0x0200);
7058 }
7059 BWN_RF_SET(mac, 0x007a, 0x0070);
7060 BWN_RF_SET(mac, 0x007a, 0x0080);
7061 DELAY(30);
7062
7063 nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
7064 if (nrssi >= 0x20)
7065 nrssi -= 0x40;
7066 if (nrssi == 31) {
7067 for (i = 7; i >= 4; i--) {
7068 BWN_RF_WRITE(mac, 0x007b, i);
7069 DELAY(20);
7070 nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) &
7071 0x003f);
7072 if (nrssi >= 0x20)
7073 nrssi -= 0x40;
7074 if (nrssi < 31 && saved == 0xffff)
7075 saved = i;
7076 }
7077 if (saved == 0xffff)
7078 saved = 4;
7079 } else {
7080 BWN_RF_MASK(mac, 0x007a, 0x007f);
7081 if (phy->rev != 1) {
7082 BWN_PHY_SET(mac, 0x0814, 0x0001);
7083 BWN_PHY_MASK(mac, 0x0815, 0xfffe);
7084 }
7085 BWN_PHY_SET(mac, 0x0811, 0x000c);
7086 BWN_PHY_SET(mac, 0x0812, 0x000c);
7087 BWN_PHY_SET(mac, 0x0811, 0x0030);
7088 BWN_PHY_SET(mac, 0x0812, 0x0030);
7089 BWN_PHY_WRITE(mac, 0x005a, 0x0480);
7090 BWN_PHY_WRITE(mac, 0x0059, 0x0810);
7091 BWN_PHY_WRITE(mac, 0x0058, 0x000d);
7092 if (phy->rev == 0)
7093 BWN_PHY_WRITE(mac, 0x0003, 0x0122);
7094 else
7095 BWN_PHY_SET(mac, 0x000a, 0x2000);
7096 if (phy->rev != 1) {
7097 BWN_PHY_SET(mac, 0x0814, 0x0004);
7098 BWN_PHY_MASK(mac, 0x0815, 0xfffb);
7099 }
7100 BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
7101 BWN_RF_SET(mac, 0x007a, 0x000f);
7102 bwn_set_all_gains(mac, 3, 0, 1);
7103 BWN_RF_SETMASK(mac, 0x0043, 0x00f0, 0x000f);
7104 DELAY(30);
7105 nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
7106 if (nrssi >= 0x20)
7107 nrssi -= 0x40;
7108 if (nrssi == -32) {
7109 for (i = 0; i < 4; i++) {
7110 BWN_RF_WRITE(mac, 0x007b, i);
7111 DELAY(20);
7112 nrssi = (int16_t)((BWN_PHY_READ(mac,
7113 0x047f) >> 8) & 0x003f);
7114 if (nrssi >= 0x20)
7115 nrssi -= 0x40;
7116 if (nrssi > -31 && saved == 0xffff)
7117 saved = i;
7118 }
7119 if (saved == 0xffff)
7120 saved = 3;
7121 } else
7122 saved = 0;
7123 }
7124 BWN_RF_WRITE(mac, 0x007b, saved);
7125
7126 /*
7127 * Restore saved RF/PHY registers
7128 */
7129 if (phy->rev >= 6) {
7130 for (phy6_idx = 0; phy6_idx < 4; ++phy6_idx) {
7131 BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
7132 save_phy6[phy6_idx]);
7133 }
7134 }
7135 if (phy->rev != 1) {
7136 for (i = 3; i < 5; i++)
7137 BWN_PHY_WRITE(mac, save_phy_comm_regs[i],
7138 save_phy_comm[i]);
7139 }
7140 for (i = 5; i < SAVE_PHY_COMM_MAX; i++)
7141 BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
7142
7143 for (i = SAVE_RF_MAX - 1; i >= 0; --i)
7144 BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
7145
7146 BWN_PHY_WRITE(mac, 0x0802, BWN_PHY_READ(mac, 0x0802) | 0x1 | 0x2);
7147 BWN_PHY_SET(mac, 0x0429, 0x8000);
7148 bwn_set_original_gains(mac);
7149 if (phy->rev >= 6) {
7150 for (; phy6_idx < SAVE_PHY6_MAX; ++phy6_idx) {
7151 BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
7152 save_phy6[phy6_idx]);
7153 }
7154 }
7155
7156 BWN_PHY_WRITE(mac, save_phy_comm_regs[0], save_phy_comm[0]);
7157 BWN_PHY_WRITE(mac, save_phy_comm_regs[2], save_phy_comm[2]);
7158 BWN_PHY_WRITE(mac, save_phy_comm_regs[1], save_phy_comm[1]);
7159}
7160
7161static void
7162bwn_set_all_gains(struct bwn_mac *mac, int16_t first, int16_t second,
7163 int16_t third)
7164{
7165 struct bwn_phy *phy = &mac->mac_phy;
7166 uint16_t i;
7167 uint16_t start = 0x08, end = 0x18;
7168 uint16_t tmp;
7169 uint16_t table;
7170
7171 if (phy->rev <= 1) {
7172 start = 0x10;
7173 end = 0x20;
7174 }
7175
7176 table = BWN_OFDMTAB_GAINX;
7177 if (phy->rev <= 1)
7178 table = BWN_OFDMTAB_GAINX_R1;
7179 for (i = 0; i < 4; i++)
7180 bwn_ofdmtab_write_2(mac, table, i, first);
7181
7182 for (i = start; i < end; i++)
7183 bwn_ofdmtab_write_2(mac, table, i, second);
7184
7185 if (third != -1) {
7186 tmp = ((uint16_t) third << 14) | ((uint16_t) third << 6);
7187 BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, tmp);
7188 BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, tmp);
7189 BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, tmp);
7190 }
7191 bwn_dummy_transmission(mac, 0, 1);
7192}
7193
7194static void
7195bwn_set_original_gains(struct bwn_mac *mac)
7196{
7197 struct bwn_phy *phy = &mac->mac_phy;
7198 uint16_t i, tmp;
7199 uint16_t table;
7200 uint16_t start = 0x0008, end = 0x0018;
7201
7202 if (phy->rev <= 1) {
7203 start = 0x0010;
7204 end = 0x0020;
7205 }
7206
7207 table = BWN_OFDMTAB_GAINX;
7208 if (phy->rev <= 1)
7209 table = BWN_OFDMTAB_GAINX_R1;
7210 for (i = 0; i < 4; i++) {
7211 tmp = (i & 0xfffc);
7212 tmp |= (i & 0x0001) << 1;
7213 tmp |= (i & 0x0002) >> 1;
7214
7215 bwn_ofdmtab_write_2(mac, table, i, tmp);
7216 }
7217
7218 for (i = start; i < end; i++)
7219 bwn_ofdmtab_write_2(mac, table, i, i - start);
7220
7221 BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, 0x4040);
7222 BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, 0x4040);
7223 BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, 0x4000);
7224 bwn_dummy_transmission(mac, 0, 1);
7225}
7226
7227static void
7228bwn_phy_hwpctl_init(struct bwn_mac *mac)
7229{
7230 struct bwn_phy *phy = &mac->mac_phy;
7231 struct bwn_phy_g *pg = &phy->phy_g;
7232 struct bwn_rfatt old_rfatt, rfatt;
7233 struct bwn_bbatt old_bbatt, bbatt;
7234 struct bwn_softc *sc = mac->mac_sc;
7235 uint8_t old_txctl = 0;
7236
7237 KASSERT(phy->type == BWN_PHYTYPE_G,
7238 ("%s:%d: fail", __func__, __LINE__));
7239
7240 if ((siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM) &&
7241 (siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306))
7242 return;
7243
7244 BWN_PHY_WRITE(mac, 0x0028, 0x8018);
7245
7246 BWN_WRITE_2(mac, BWN_PHY0, BWN_READ_2(mac, BWN_PHY0) & 0xffdf);
7247
7248 if (!phy->gmode)
7249 return;
7250 bwn_hwpctl_early_init(mac);
7251 if (pg->pg_curtssi == 0) {
7252 if (phy->rf_ver == 0x2050 && phy->analog == 0) {
7253 BWN_RF_SETMASK(mac, 0x0076, 0x00f7, 0x0084);
7254 } else {
7255 memcpy(&old_rfatt, &pg->pg_rfatt, sizeof(old_rfatt));
7256 memcpy(&old_bbatt, &pg->pg_bbatt, sizeof(old_bbatt));
7257 old_txctl = pg->pg_txctl;
7258
7259 bbatt.att = 11;
7260 if (phy->rf_rev == 8) {
7261 rfatt.att = 15;
7262 rfatt.padmix = 1;
7263 } else {
7264 rfatt.att = 9;
7265 rfatt.padmix = 0;
7266 }
7267 bwn_phy_g_set_txpwr_sub(mac, &bbatt, &rfatt, 0);
7268 }
7269 bwn_dummy_transmission(mac, 0, 1);
7270 pg->pg_curtssi = BWN_PHY_READ(mac, BWN_PHY_TSSI);
7271 if (phy->rf_ver == 0x2050 && phy->analog == 0)
7272 BWN_RF_MASK(mac, 0x0076, 0xff7b);
7273 else
7274 bwn_phy_g_set_txpwr_sub(mac, &old_bbatt,
7275 &old_rfatt, old_txctl);
7276 }
7277 bwn_hwpctl_init_gphy(mac);
7278
7279 /* clear TSSI */
7280 bwn_shm_write_2(mac, BWN_SHARED, 0x0058, 0x7f7f);
7281 bwn_shm_write_2(mac, BWN_SHARED, 0x005a, 0x7f7f);
7282 bwn_shm_write_2(mac, BWN_SHARED, 0x0070, 0x7f7f);
7283 bwn_shm_write_2(mac, BWN_SHARED, 0x0072, 0x7f7f);
7284}
7285
7286static void
7287bwn_hwpctl_early_init(struct bwn_mac *mac)
7288{
7289 struct bwn_phy *phy = &mac->mac_phy;
7290
7291 if (!bwn_has_hwpctl(mac)) {
7292 BWN_PHY_WRITE(mac, 0x047a, 0xc111);
7293 return;
7294 }
7295
7296 BWN_PHY_MASK(mac, 0x0036, 0xfeff);
7297 BWN_PHY_WRITE(mac, 0x002f, 0x0202);
7298 BWN_PHY_SET(mac, 0x047c, 0x0002);
7299 BWN_PHY_SET(mac, 0x047a, 0xf000);
7300 if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
7301 BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7302 BWN_PHY_SET(mac, 0x005d, 0x8000);
7303 BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7304 BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7305 BWN_PHY_SET(mac, 0x0036, 0x0400);
7306 } else {
7307 BWN_PHY_SET(mac, 0x0036, 0x0200);
7308 BWN_PHY_SET(mac, 0x0036, 0x0400);
7309 BWN_PHY_MASK(mac, 0x005d, 0x7fff);
7310 BWN_PHY_MASK(mac, 0x004f, 0xfffe);
7311 BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7312 BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7313 BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7314 }
7315}
7316
7317static void
7318bwn_hwpctl_init_gphy(struct bwn_mac *mac)
7319{
7320 struct bwn_phy *phy = &mac->mac_phy;
7321 struct bwn_phy_g *pg = &phy->phy_g;
7322 struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7323 int i;
7324 uint16_t nr_written = 0, tmp, value;
7325 uint8_t rf, bb;
7326
7327 if (!bwn_has_hwpctl(mac)) {
7328 bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_HW_POWERCTL);
7329 return;
7330 }
7331
7332 BWN_PHY_SETMASK(mac, 0x0036, 0xffc0,
7333 (pg->pg_idletssi - pg->pg_curtssi));
7334 BWN_PHY_SETMASK(mac, 0x0478, 0xff00,
7335 (pg->pg_idletssi - pg->pg_curtssi));
7336
7337 for (i = 0; i < 32; i++)
7338 bwn_ofdmtab_write_2(mac, 0x3c20, i, pg->pg_tssi2dbm[i]);
7339 for (i = 32; i < 64; i++)
7340 bwn_ofdmtab_write_2(mac, 0x3c00, i - 32, pg->pg_tssi2dbm[i]);
7341 for (i = 0; i < 64; i += 2) {
7342 value = (uint16_t) pg->pg_tssi2dbm[i];
7343 value |= ((uint16_t) pg->pg_tssi2dbm[i + 1]) << 8;
7344 BWN_PHY_WRITE(mac, 0x380 + (i / 2), value);
7345 }
7346
7347 for (rf = 0; rf < lo->rfatt.len; rf++) {
7348 for (bb = 0; bb < lo->bbatt.len; bb++) {
7349 if (nr_written >= 0x40)
7350 return;
7351 tmp = lo->bbatt.array[bb].att;
7352 tmp <<= 8;
7353 if (phy->rf_rev == 8)
7354 tmp |= 0x50;
7355 else
7356 tmp |= 0x40;
7357 tmp |= lo->rfatt.array[rf].att;
7358 BWN_PHY_WRITE(mac, 0x3c0 + nr_written, tmp);
7359 nr_written++;
7360 }
7361 }
7362
7363 BWN_PHY_MASK(mac, 0x0060, 0xffbf);
7364 BWN_PHY_WRITE(mac, 0x0014, 0x0000);
7365
7366 KASSERT(phy->rev >= 6, ("%s:%d: fail", __func__, __LINE__));
7367 BWN_PHY_SET(mac, 0x0478, 0x0800);
7368 BWN_PHY_MASK(mac, 0x0478, 0xfeff);
7369 BWN_PHY_MASK(mac, 0x0801, 0xffbf);
7370
7371 bwn_phy_g_dc_lookup_init(mac, 1);
7372 bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_HW_POWERCTL);
7373}
7374
7375static void
7376bwn_phy_g_switch_chan(struct bwn_mac *mac, int channel, uint8_t spu)
7377{
7378 struct bwn_softc *sc = mac->mac_sc;
7379
7380 if (spu != 0)
7381 bwn_spu_workaround(mac, channel);
7382
7383 BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7384
7385 if (channel == 14) {
7386 if (siba_sprom_get_ccode(sc->sc_dev) == SIBA_CCODE_JAPAN)
7387 bwn_hf_write(mac,
7388 bwn_hf_read(mac) & ~BWN_HF_JAPAN_CHAN14_OFF);
7389 else
7390 bwn_hf_write(mac,
7391 bwn_hf_read(mac) | BWN_HF_JAPAN_CHAN14_OFF);
7392 BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7393 BWN_READ_2(mac, BWN_CHANNEL_EXT) | (1 << 11));
7394 return;
7395 }
7396
7397 BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7398 BWN_READ_2(mac, BWN_CHANNEL_EXT) & 0xf7bf);
7399}
7400
7401static uint16_t
7402bwn_phy_g_chan2freq(uint8_t channel)
7403{
7404 static const uint8_t bwn_phy_g_rf_channels[] = BWN_PHY_G_RF_CHANNELS;
7405
7406 KASSERT(channel >= 1 && channel <= 14,
7407 ("%s:%d: fail", __func__, __LINE__));
7408
7409 return (bwn_phy_g_rf_channels[channel - 1]);
7410}
7411
7412static void
7413bwn_phy_g_set_txpwr_sub(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
7414 const struct bwn_rfatt *rfatt, uint8_t txctl)
7415{
7416 struct bwn_phy *phy = &mac->mac_phy;
7417 struct bwn_phy_g *pg = &phy->phy_g;
7418 struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7419 uint16_t bb, rf;
7420 uint16_t tx_bias, tx_magn;
7421
7422 bb = bbatt->att;
7423 rf = rfatt->att;
7424 tx_bias = lo->tx_bias;
7425 tx_magn = lo->tx_magn;
7426 if (tx_bias == 0xff)
7427 tx_bias = 0;
7428
7429 pg->pg_txctl = txctl;
7430 memmove(&pg->pg_rfatt, rfatt, sizeof(*rfatt));
7431 pg->pg_rfatt.padmix = (txctl & BWN_TXCTL_TXMIX) ? 1 : 0;
7432 memmove(&pg->pg_bbatt, bbatt, sizeof(*bbatt));
7433 bwn_phy_g_set_bbatt(mac, bb);
7434 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RADIO_ATT, rf);
7435 if (phy->rf_ver == 0x2050 && phy->rf_rev == 8)
7436 BWN_RF_WRITE(mac, 0x43, (rf & 0x000f) | (txctl & 0x0070));
7437 else {
7438 BWN_RF_SETMASK(mac, 0x43, 0xfff0, (rf & 0x000f));
7439 BWN_RF_SETMASK(mac, 0x52, ~0x0070, (txctl & 0x0070));
7440 }
7441 if (BWN_HAS_TXMAG(phy))
7442 BWN_RF_WRITE(mac, 0x52, tx_magn | tx_bias);
7443 else
7444 BWN_RF_SETMASK(mac, 0x52, 0xfff0, (tx_bias & 0x000f));
7445 bwn_lo_g_adjust(mac);
7446}
7447
7448static void
7449bwn_phy_g_set_bbatt(struct bwn_mac *mac,
7450 uint16_t bbatt)
7451{
7452 struct bwn_phy *phy = &mac->mac_phy;
7453
7454 if (phy->analog == 0) {
7455 BWN_WRITE_2(mac, BWN_PHY0,
7456 (BWN_READ_2(mac, BWN_PHY0) & 0xfff0) | bbatt);
7457 return;
7458 }
7459 if (phy->analog > 1) {
7460 BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xffc3, bbatt << 2);
7461 return;
7462 }
7463 BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xff87, bbatt << 3);
7464}
7465
7466static uint16_t
7467bwn_rf_2050_rfoverval(struct bwn_mac *mac, uint16_t reg, uint32_t lpd)
7468{
7469 struct bwn_phy *phy = &mac->mac_phy;
7470 struct bwn_phy_g *pg = &phy->phy_g;
7471 struct bwn_softc *sc = mac->mac_sc;
7472 int max_lb_gain;
7473 uint16_t extlna;
7474 uint16_t i;
7475
7476 if (phy->gmode == 0)
7477 return (0);
7478
7479 if (BWN_HAS_LOOPBACK(phy)) {
7480 max_lb_gain = pg->pg_max_lb_gain;
7481 max_lb_gain += (phy->rf_rev == 8) ? 0x3e : 0x26;
7482 if (max_lb_gain >= 0x46) {
7483 extlna = 0x3000;
7484 max_lb_gain -= 0x46;
7485 } else if (max_lb_gain >= 0x3a) {
7486 extlna = 0x1000;
7487 max_lb_gain -= 0x3a;
7488 } else if (max_lb_gain >= 0x2e) {
7489 extlna = 0x2000;
7490 max_lb_gain -= 0x2e;
7491 } else {
7492 extlna = 0;
7493 max_lb_gain -= 0x10;
7494 }
7495
7496 for (i = 0; i < 16; i++) {
7497 max_lb_gain -= (i * 6);
7498 if (max_lb_gain < 6)
7499 break;
7500 }
7501
7502 if ((phy->rev < 7) ||
7503 !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA)) {
7504 if (reg == BWN_PHY_RFOVER) {
7505 return (0x1b3);
7506 } else if (reg == BWN_PHY_RFOVERVAL) {
7507 extlna |= (i << 8);
7508 switch (lpd) {
7509 case BWN_LPD(0, 1, 1):
7510 return (0x0f92);
7511 case BWN_LPD(0, 0, 1):
7512 case BWN_LPD(1, 0, 1):
7513 return (0x0092 | extlna);
7514 case BWN_LPD(1, 0, 0):
7515 return (0x0093 | extlna);
7516 }
7517 KASSERT(0 == 1,
7518 ("%s:%d: fail", __func__, __LINE__));
7519 }
7520 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7521 } else {
7522 if (reg == BWN_PHY_RFOVER)
7523 return (0x9b3);
7524 if (reg == BWN_PHY_RFOVERVAL) {
7525 if (extlna)
7526 extlna |= 0x8000;
7527 extlna |= (i << 8);
7528 switch (lpd) {
7529 case BWN_LPD(0, 1, 1):
7530 return (0x8f92);
7531 case BWN_LPD(0, 0, 1):
7532 return (0x8092 | extlna);
7533 case BWN_LPD(1, 0, 1):
7534 return (0x2092 | extlna);
7535 case BWN_LPD(1, 0, 0):
7536 return (0x2093 | extlna);
7537 }
7538 KASSERT(0 == 1,
7539 ("%s:%d: fail", __func__, __LINE__));
7540 }
7541 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7542 }
7543 return (0);
7544 }
7545
7546 if ((phy->rev < 7) ||
7547 !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA)) {
7548 if (reg == BWN_PHY_RFOVER) {
7549 return (0x1b3);
7550 } else if (reg == BWN_PHY_RFOVERVAL) {
7551 switch (lpd) {
7552 case BWN_LPD(0, 1, 1):
7553 return (0x0fb2);
7554 case BWN_LPD(0, 0, 1):
7555 return (0x00b2);
7556 case BWN_LPD(1, 0, 1):
7557 return (0x30b2);
7558 case BWN_LPD(1, 0, 0):
7559 return (0x30b3);
7560 }
7561 KASSERT(0 == 1,
7562 ("%s:%d: fail", __func__, __LINE__));
7563 }
7564 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7565 } else {
7566 if (reg == BWN_PHY_RFOVER) {
7567 return (0x9b3);
7568 } else if (reg == BWN_PHY_RFOVERVAL) {
7569 switch (lpd) {
7570 case BWN_LPD(0, 1, 1):
7571 return (0x8fb2);
7572 case BWN_LPD(0, 0, 1):
7573 return (0x80b2);
7574 case BWN_LPD(1, 0, 1):
7575 return (0x20b2);
7576 case BWN_LPD(1, 0, 0):
7577 return (0x20b3);
7578 }
7579 KASSERT(0 == 1,
7580 ("%s:%d: fail", __func__, __LINE__));
7581 }
7582 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7583 }
7584 return (0);
7585}
7586
7587static void
7588bwn_spu_workaround(struct bwn_mac *mac, uint8_t channel)
7589{
7590
7591 if (mac->mac_phy.rf_ver != 0x2050 || mac->mac_phy.rf_rev >= 6)
7592 return;
7593 BWN_WRITE_2(mac, BWN_CHANNEL, (channel <= 10) ?
7594 bwn_phy_g_chan2freq(channel + 4) : bwn_phy_g_chan2freq(1));
7595 DELAY(1000);
7596 BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7597}
7598
7599static int
7600bwn_fw_gets(struct bwn_mac *mac, enum bwn_fwtype type)
7601{
7602 struct bwn_softc *sc = mac->mac_sc;
7603 struct bwn_fw *fw = &mac->mac_fw;
7604 const uint8_t rev = siba_get_revid(sc->sc_dev);
7605 const char *filename;
7606 uint32_t high;
7607 int error;
7608
7609 /* microcode */
7610 if (rev >= 5 && rev <= 10)
7611 filename = "ucode5";
7612 else if (rev >= 11 && rev <= 12)
7613 filename = "ucode11";
7614 else if (rev == 13)
7615 filename = "ucode13";
7616 else if (rev == 14)
7617 filename = "ucode14";
7618 else if (rev >= 15)
7619 filename = "ucode15";
7620 else {
7621 device_printf(sc->sc_dev, "no ucode for rev %d\n", rev);
7622 bwn_release_firmware(mac);
7623 return (EOPNOTSUPP);
7624 }
7625 error = bwn_fw_get(mac, type, filename, &fw->ucode);
7626 if (error) {
7627 bwn_release_firmware(mac);
7628 return (error);
7629 }
7630
7631 /* PCM */
7632 KASSERT(fw->no_pcmfile == 0, ("%s:%d fail", __func__, __LINE__));
7633 if (rev >= 5 && rev <= 10) {
7634 error = bwn_fw_get(mac, type, "pcm5", &fw->pcm);
7635 if (error == ENOENT)
7636 fw->no_pcmfile = 1;
7637 else if (error) {
7638 bwn_release_firmware(mac);
7639 return (error);
7640 }
7641 } else if (rev < 11) {
7642 device_printf(sc->sc_dev, "no PCM for rev %d\n", rev);
7643 return (EOPNOTSUPP);
7644 }
7645
7646 /* initvals */
7647 high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH);
7648 switch (mac->mac_phy.type) {
7649 case BWN_PHYTYPE_A:
7650 if (rev < 5 || rev > 10)
7651 goto fail1;
7652 if (high & BWN_TGSHIGH_HAVE_2GHZ)
7653 filename = "a0g1initvals5";
7654 else
7655 filename = "a0g0initvals5";
7656 break;
7657 case BWN_PHYTYPE_G:
7658 if (rev >= 5 && rev <= 10)
7659 filename = "b0g0initvals5";
7660 else if (rev >= 13)
7661 filename = "b0g0initvals13";
7662 else
7663 goto fail1;
7664 break;
7665 case BWN_PHYTYPE_LP:
7666 if (rev == 13)
7667 filename = "lp0initvals13";
7668 else if (rev == 14)
7669 filename = "lp0initvals14";
7670 else if (rev >= 15)
7671 filename = "lp0initvals15";
7672 else
7673 goto fail1;
7674 break;
7675 case BWN_PHYTYPE_N:
7676 if (rev >= 11 && rev <= 12)
7677 filename = "n0initvals11";
7678 else
7679 goto fail1;
7680 break;
7681 default:
7682 goto fail1;
7683 }
7684 error = bwn_fw_get(mac, type, filename, &fw->initvals);
7685 if (error) {
7686 bwn_release_firmware(mac);
7687 return (error);
7688 }
7689
7690 /* bandswitch initvals */
7691 switch (mac->mac_phy.type) {
7692 case BWN_PHYTYPE_A:
7693 if (rev >= 5 && rev <= 10) {
7694 if (high & BWN_TGSHIGH_HAVE_2GHZ)
7695 filename = "a0g1bsinitvals5";
7696 else
7697 filename = "a0g0bsinitvals5";
7698 } else if (rev >= 11)
7699 filename = NULL;
7700 else
7701 goto fail1;
7702 break;
7703 case BWN_PHYTYPE_G:
7704 if (rev >= 5 && rev <= 10)
7705 filename = "b0g0bsinitvals5";
7706 else if (rev >= 11)
7707 filename = NULL;
7708 else
7709 goto fail1;
7710 break;
7711 case BWN_PHYTYPE_LP:
7712 if (rev == 13)
7713 filename = "lp0bsinitvals13";
7714 else if (rev == 14)
7715 filename = "lp0bsinitvals14";
7716 else if (rev >= 15)
7717 filename = "lp0bsinitvals15";
7718 else
7719 goto fail1;
7720 break;
7721 case BWN_PHYTYPE_N:
7722 if (rev >= 11 && rev <= 12)
7723 filename = "n0bsinitvals11";
7724 else
7725 goto fail1;
7726 break;
7727 default:
7728 goto fail1;
7729 }
7730 error = bwn_fw_get(mac, type, filename, &fw->initvals_band);
7731 if (error) {
7732 bwn_release_firmware(mac);
7733 return (error);
7734 }
7735 return (0);
7736fail1:
7737 device_printf(sc->sc_dev, "no INITVALS for rev %d\n", rev);
7738 bwn_release_firmware(mac);
7739 return (EOPNOTSUPP);
7740}
7741
7742static int
7743bwn_fw_get(struct bwn_mac *mac, enum bwn_fwtype type,
7744 const char *name, struct bwn_fwfile *bfw)
7745{
7746 const struct bwn_fwhdr *hdr;
7747 struct bwn_softc *sc = mac->mac_sc;
7748 const struct firmware *fw;
7749 char namebuf[64];
7750
7751 if (name == NULL) {
7752 bwn_do_release_fw(bfw);
7753 return (0);
7754 }
7755 if (bfw->filename != NULL) {
7756 if (bfw->type == type && (strcmp(bfw->filename, name) == 0))
7757 return (0);
7758 bwn_do_release_fw(bfw);
7759 }
7760
7761 snprintf(namebuf, sizeof(namebuf), "bwn%s_v4_%s%s",
7762 (type == BWN_FWTYPE_OPENSOURCE) ? "-open" : "",
7763 (mac->mac_phy.type == BWN_PHYTYPE_LP) ? "lp_" : "", name);
7764 /* XXX Sleeping on "fwload" with the non-sleepable locks held */
7765 fw = firmware_get(namebuf);
7766 if (fw == NULL) {
7767 device_printf(sc->sc_dev, "the fw file(%s) not found\n",
7768 namebuf);
7769 return (ENOENT);
7770 }
7771 if (fw->datasize < sizeof(struct bwn_fwhdr))
7772 goto fail;
7773 hdr = (const struct bwn_fwhdr *)(fw->data);
7774 switch (hdr->type) {
7775 case BWN_FWTYPE_UCODE:
7776 case BWN_FWTYPE_PCM:
7777 if (be32toh(hdr->size) !=
7778 (fw->datasize - sizeof(struct bwn_fwhdr)))
7779 goto fail;
7780 /* FALLTHROUGH */
7781 case BWN_FWTYPE_IV:
7782 if (hdr->ver != 1)
7783 goto fail;
7784 break;
7785 default:
7786 goto fail;
7787 }
7788 bfw->filename = name;
7789 bfw->fw = fw;
7790 bfw->type = type;
7791 return (0);
7792fail:
7793 device_printf(sc->sc_dev, "the fw file(%s) format error\n", namebuf);
7794 if (fw != NULL)
7795 firmware_put(fw, FIRMWARE_UNLOAD);
7796 return (EPROTO);
7797}
7798
7799static void
7800bwn_release_firmware(struct bwn_mac *mac)
7801{
7802
7803 bwn_do_release_fw(&mac->mac_fw.ucode);
7804 bwn_do_release_fw(&mac->mac_fw.pcm);
7805 bwn_do_release_fw(&mac->mac_fw.initvals);
7806 bwn_do_release_fw(&mac->mac_fw.initvals_band);
7807}
7808
7809static void
7810bwn_do_release_fw(struct bwn_fwfile *bfw)
7811{
7812
7813 if (bfw->fw != NULL)
7814 firmware_put(bfw->fw, FIRMWARE_UNLOAD);
7815 bfw->fw = NULL;
7816 bfw->filename = NULL;
7817}
7818
7819static int
7820bwn_fw_loaducode(struct bwn_mac *mac)
7821{
7822#define GETFWOFFSET(fwp, offset) \
7823 ((const uint32_t *)((const char *)fwp.fw->data + offset))
7824#define GETFWSIZE(fwp, offset) \
7825 ((fwp.fw->datasize - offset) / sizeof(uint32_t))
7826 struct bwn_softc *sc = mac->mac_sc;
7827 const uint32_t *data;
7828 unsigned int i;
7829 uint32_t ctl;
7830 uint16_t date, fwcaps, time;
7831 int error = 0;
7832
7833 ctl = BWN_READ_4(mac, BWN_MACCTL);
7834 ctl |= BWN_MACCTL_MCODE_JMP0;
7835 KASSERT(!(ctl & BWN_MACCTL_MCODE_RUN), ("%s:%d: fail", __func__,
7836 __LINE__));
7837 BWN_WRITE_4(mac, BWN_MACCTL, ctl);
7838 for (i = 0; i < 64; i++)
7839 bwn_shm_write_2(mac, BWN_SCRATCH, i, 0);
7840 for (i = 0; i < 4096; i += 2)
7841 bwn_shm_write_2(mac, BWN_SHARED, i, 0);
7842
7843 data = GETFWOFFSET(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7844 bwn_shm_ctlword(mac, BWN_UCODE | BWN_SHARED_AUTOINC, 0x0000);
7845 for (i = 0; i < GETFWSIZE(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7846 i++) {
7847 BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7848 DELAY(10);
7849 }
7850
7851 if (mac->mac_fw.pcm.fw) {
7852 data = GETFWOFFSET(mac->mac_fw.pcm, sizeof(struct bwn_fwhdr));
7853 bwn_shm_ctlword(mac, BWN_HW, 0x01ea);
7854 BWN_WRITE_4(mac, BWN_SHM_DATA, 0x00004000);
7855 bwn_shm_ctlword(mac, BWN_HW, 0x01eb);
7856 for (i = 0; i < GETFWSIZE(mac->mac_fw.pcm,
7857 sizeof(struct bwn_fwhdr)); i++) {
7858 BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7859 DELAY(10);
7860 }
7861 }
7862
7863 BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_ALL);
7864 BWN_WRITE_4(mac, BWN_MACCTL,
7865 (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_JMP0) |
7866 BWN_MACCTL_MCODE_RUN);
7867
7868 for (i = 0; i < 21; i++) {
7869 if (BWN_READ_4(mac, BWN_INTR_REASON) == BWN_INTR_MAC_SUSPENDED)
7870 break;
7871 if (i >= 20) {
7872 device_printf(sc->sc_dev, "ucode timeout\n");
7873 error = ENXIO;
7874 goto error;
7875 }
7876 DELAY(50000);
7877 }
7878 BWN_READ_4(mac, BWN_INTR_REASON);
7879
7880 mac->mac_fw.rev = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_REV);
7881 if (mac->mac_fw.rev <= 0x128) {
7882 device_printf(sc->sc_dev, "the firmware is too old\n");
7883 error = EOPNOTSUPP;
7884 goto error;
7885 }
7886 mac->mac_fw.patch = bwn_shm_read_2(mac, BWN_SHARED,
7887 BWN_SHARED_UCODE_PATCH);
7888 date = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_DATE);
7889 mac->mac_fw.opensource = (date == 0xffff);
7890 if (bwn_wme != 0)
7891 mac->mac_flags |= BWN_MAC_FLAG_WME;
7892 mac->mac_flags |= BWN_MAC_FLAG_HWCRYPTO;
7893
7894 time = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_TIME);
7895 if (mac->mac_fw.opensource == 0) {
7896 device_printf(sc->sc_dev,
7897 "firmware version (rev %u patch %u date %#x time %#x)\n",
7898 mac->mac_fw.rev, mac->mac_fw.patch, date, time);
7899 if (mac->mac_fw.no_pcmfile)
7900 device_printf(sc->sc_dev,
7901 "no HW crypto acceleration due to pcm5\n");
7902 } else {
7903 mac->mac_fw.patch = time;
7904 fwcaps = bwn_fwcaps_read(mac);
7905 if (!(fwcaps & BWN_FWCAPS_HWCRYPTO) || mac->mac_fw.no_pcmfile) {
7906 device_printf(sc->sc_dev,
7907 "disabling HW crypto acceleration\n");
7908 mac->mac_flags &= ~BWN_MAC_FLAG_HWCRYPTO;
7909 }
7910 if (!(fwcaps & BWN_FWCAPS_WME)) {
7911 device_printf(sc->sc_dev, "disabling WME support\n");
7912 mac->mac_flags &= ~BWN_MAC_FLAG_WME;
7913 }
7914 }
7915
7916 if (BWN_ISOLDFMT(mac))
7917 device_printf(sc->sc_dev, "using old firmware image\n");
7918
7919 return (0);
7920
7921error:
7922 BWN_WRITE_4(mac, BWN_MACCTL,
7923 (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_RUN) |
7924 BWN_MACCTL_MCODE_JMP0);
7925
7926 return (error);
7927#undef GETFWSIZE
7928#undef GETFWOFFSET
7929}
7930
7931/* OpenFirmware only */
7932static uint16_t
7933bwn_fwcaps_read(struct bwn_mac *mac)
7934{
7935
7936 KASSERT(mac->mac_fw.opensource == 1,
7937 ("%s:%d: fail", __func__, __LINE__));
7938 return (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_FWCAPS));
7939}
7940
7941static int
7942bwn_fwinitvals_write(struct bwn_mac *mac, const struct bwn_fwinitvals *ivals,
7943 size_t count, size_t array_size)
7944{
7945#define GET_NEXTIV16(iv) \
7946 ((const struct bwn_fwinitvals *)((const uint8_t *)(iv) + \
7947 sizeof(uint16_t) + sizeof(uint16_t)))
7948#define GET_NEXTIV32(iv) \
7949 ((const struct bwn_fwinitvals *)((const uint8_t *)(iv) + \
7950 sizeof(uint16_t) + sizeof(uint32_t)))
7951 struct bwn_softc *sc = mac->mac_sc;
7952 const struct bwn_fwinitvals *iv;
7953 uint16_t offset;
7954 size_t i;
7955 uint8_t bit32;
7956
7957 KASSERT(sizeof(struct bwn_fwinitvals) == 6,
7958 ("%s:%d: fail", __func__, __LINE__));
7959 iv = ivals;
7960 for (i = 0; i < count; i++) {
7961 if (array_size < sizeof(iv->offset_size))
7962 goto fail;
7963 array_size -= sizeof(iv->offset_size);
7964 offset = be16toh(iv->offset_size);
7965 bit32 = (offset & BWN_FWINITVALS_32BIT) ? 1 : 0;
7966 offset &= BWN_FWINITVALS_OFFSET_MASK;
7967 if (offset >= 0x1000)
7968 goto fail;
7969 if (bit32) {
7970 if (array_size < sizeof(iv->data.d32))
7971 goto fail;
7972 array_size -= sizeof(iv->data.d32);
7973 BWN_WRITE_4(mac, offset, be32toh(iv->data.d32));
7974 iv = GET_NEXTIV32(iv);
7975 } else {
7976
7977 if (array_size < sizeof(iv->data.d16))
7978 goto fail;
7979 array_size -= sizeof(iv->data.d16);
7980 BWN_WRITE_2(mac, offset, be16toh(iv->data.d16));
7981
7982 iv = GET_NEXTIV16(iv);
7983 }
7984 }
7985 if (array_size != 0)
7986 goto fail;
7987 return (0);
7988fail:
7989 device_printf(sc->sc_dev, "initvals: invalid format\n");
7990 return (EPROTO);
7991#undef GET_NEXTIV16
7992#undef GET_NEXTIV32
7993}
7994
7995static int
7996bwn_switch_channel(struct bwn_mac *mac, int chan)
7997{
7998 struct bwn_phy *phy = &(mac->mac_phy);
7999 struct bwn_softc *sc = mac->mac_sc;
8000 struct ifnet *ifp = sc->sc_ifp;
8001 struct ieee80211com *ic = ifp->if_l2com;
8002 uint16_t channelcookie, savedcookie;
8003 int error;
8004
8005 if (chan == 0xffff)
8006 chan = phy->get_default_chan(mac);
8007
8008 channelcookie = chan;
8009 if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan))
8010 channelcookie |= 0x100;
8011 savedcookie = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_CHAN);
8012 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, channelcookie);
8013 error = phy->switch_channel(mac, chan);
8014 if (error)
8015 goto fail;
8016
8017 mac->mac_phy.chan = chan;
8018 DELAY(8000);
8019 return (0);
8020fail:
8021 device_printf(sc->sc_dev, "failed to switch channel\n");
8022 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, savedcookie);
8023 return (error);
8024}
8025
8026static uint16_t
8027bwn_ant2phy(int antenna)
8028{
8029
8030 switch (antenna) {
8031 case BWN_ANT0:
8032 return (BWN_TX_PHY_ANT0);
8033 case BWN_ANT1:
8034 return (BWN_TX_PHY_ANT1);
8035 case BWN_ANT2:
8036 return (BWN_TX_PHY_ANT2);
8037 case BWN_ANT3:
8038 return (BWN_TX_PHY_ANT3);
8039 case BWN_ANTAUTO:
8040 return (BWN_TX_PHY_ANT01AUTO);
8041 }
8042 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8043 return (0);
8044}
8045
8046static void
8047bwn_wme_load(struct bwn_mac *mac)
8048{
8049 struct bwn_softc *sc = mac->mac_sc;
8050 int i;
8051
8052 KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
8053 ("%s:%d: fail", __func__, __LINE__));
8054
8055 bwn_mac_suspend(mac);
8056 for (i = 0; i < N(sc->sc_wmeParams); i++)
8057 bwn_wme_loadparams(mac, &(sc->sc_wmeParams[i]),
8058 bwn_wme_shm_offsets[i]);
8059 bwn_mac_enable(mac);
8060}
8061
8062static void
8063bwn_wme_loadparams(struct bwn_mac *mac,
8064 const struct wmeParams *p, uint16_t shm_offset)
8065{
8066#define SM(_v, _f) (((_v) << _f##_S) & _f)
8067 struct bwn_softc *sc = mac->mac_sc;
8068 uint16_t params[BWN_NR_WMEPARAMS];
8069 int slot, tmp;
8070 unsigned int i;
8071
8072 slot = BWN_READ_2(mac, BWN_RNG) &
8073 SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8074
8075 memset(&params, 0, sizeof(params));
8076
8077 DPRINTF(sc, BWN_DEBUG_WME, "wmep_txopLimit %d wmep_logcwmin %d "
8078 "wmep_logcwmax %d wmep_aifsn %d\n", p->wmep_txopLimit,
8079 p->wmep_logcwmin, p->wmep_logcwmax, p->wmep_aifsn);
8080
8081 params[BWN_WMEPARAM_TXOP] = p->wmep_txopLimit * 32;
8082 params[BWN_WMEPARAM_CWMIN] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8083 params[BWN_WMEPARAM_CWMAX] = SM(p->wmep_logcwmax, WME_PARAM_LOGCWMAX);
8084 params[BWN_WMEPARAM_CWCUR] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8085 params[BWN_WMEPARAM_AIFS] = p->wmep_aifsn;
8086 params[BWN_WMEPARAM_BSLOTS] = slot;
8087 params[BWN_WMEPARAM_REGGAP] = slot + p->wmep_aifsn;
8088
8089 for (i = 0; i < N(params); i++) {
8090 if (i == BWN_WMEPARAM_STATUS) {
8091 tmp = bwn_shm_read_2(mac, BWN_SHARED,
8092 shm_offset + (i * 2));
8093 tmp |= 0x100;
8094 bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
8095 tmp);
8096 } else {
8097 bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
8098 params[i]);
8099 }
8100 }
8101}
8102
8103static void
8104bwn_mac_write_bssid(struct bwn_mac *mac)
8105{
8106 struct bwn_softc *sc = mac->mac_sc;
8107 uint32_t tmp;
8108 int i;
8109 uint8_t mac_bssid[IEEE80211_ADDR_LEN * 2];
8110
8111 bwn_mac_setfilter(mac, BWN_MACFILTER_BSSID, sc->sc_bssid);
8112 memcpy(mac_bssid, sc->sc_macaddr, IEEE80211_ADDR_LEN);
8113 memcpy(mac_bssid + IEEE80211_ADDR_LEN, sc->sc_bssid,
8114 IEEE80211_ADDR_LEN);
8115
8116 for (i = 0; i < N(mac_bssid); i += sizeof(uint32_t)) {
8117 tmp = (uint32_t) (mac_bssid[i + 0]);
8118 tmp |= (uint32_t) (mac_bssid[i + 1]) << 8;
8119 tmp |= (uint32_t) (mac_bssid[i + 2]) << 16;
8120 tmp |= (uint32_t) (mac_bssid[i + 3]) << 24;
8121 bwn_ram_write(mac, 0x20 + i, tmp);
8122 }
8123}
8124
8125static void
8126bwn_mac_setfilter(struct bwn_mac *mac, uint16_t offset,
8127 const uint8_t *macaddr)
8128{
8129 static const uint8_t zero[IEEE80211_ADDR_LEN] = { 0 };
8130 uint16_t data;
8131
8132 if (!mac)
8133 macaddr = zero;
8134
8135 offset |= 0x0020;
8136 BWN_WRITE_2(mac, BWN_MACFILTER_CONTROL, offset);
8137
8138 data = macaddr[0];
8139 data |= macaddr[1] << 8;
8140 BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8141 data = macaddr[2];
8142 data |= macaddr[3] << 8;
8143 BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8144 data = macaddr[4];
8145 data |= macaddr[5] << 8;
8146 BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8147}
8148
8149static void
8150bwn_key_dowrite(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8151 const uint8_t *key, size_t key_len, const uint8_t *mac_addr)
8152{
8153 uint8_t buf[BWN_SEC_KEYSIZE] = { 0, };
8154 uint8_t per_sta_keys_start = 8;
8155
8156 if (BWN_SEC_NEWAPI(mac))
8157 per_sta_keys_start = 4;
8158
8159 KASSERT(index < mac->mac_max_nr_keys,
8160 ("%s:%d: fail", __func__, __LINE__));
8161 KASSERT(key_len <= BWN_SEC_KEYSIZE,
8162 ("%s:%d: fail", __func__, __LINE__));
8163
8164 if (index >= per_sta_keys_start)
8165 bwn_key_macwrite(mac, index, NULL);
8166 if (key)
8167 memcpy(buf, key, key_len);
8168 bwn_key_write(mac, index, algorithm, buf);
8169 if (index >= per_sta_keys_start)
8170 bwn_key_macwrite(mac, index, mac_addr);
8171
8172 mac->mac_key[index].algorithm = algorithm;
8173}
8174
8175static void
8176bwn_key_macwrite(struct bwn_mac *mac, uint8_t index, const uint8_t *addr)
8177{
8178 struct bwn_softc *sc = mac->mac_sc;
8179 uint32_t addrtmp[2] = { 0, 0 };
8180 uint8_t start = 8;
8181
8182 if (BWN_SEC_NEWAPI(mac))
8183 start = 4;
8184
8185 KASSERT(index >= start,
8186 ("%s:%d: fail", __func__, __LINE__));
8187 index -= start;
8188
8189 if (addr) {
8190 addrtmp[0] = addr[0];
8191 addrtmp[0] |= ((uint32_t) (addr[1]) << 8);
8192 addrtmp[0] |= ((uint32_t) (addr[2]) << 16);
8193 addrtmp[0] |= ((uint32_t) (addr[3]) << 24);
8194 addrtmp[1] = addr[4];
8195 addrtmp[1] |= ((uint32_t) (addr[5]) << 8);
8196 }
8197
8198 if (siba_get_revid(sc->sc_dev) >= 5) {
8199 bwn_shm_write_4(mac, BWN_RCMTA, (index * 2) + 0, addrtmp[0]);
8200 bwn_shm_write_2(mac, BWN_RCMTA, (index * 2) + 1, addrtmp[1]);
8201 } else {
8202 if (index >= 8) {
8203 bwn_shm_write_4(mac, BWN_SHARED,
8204 BWN_SHARED_PSM + (index * 6) + 0, addrtmp[0]);
8205 bwn_shm_write_2(mac, BWN_SHARED,
8206 BWN_SHARED_PSM + (index * 6) + 4, addrtmp[1]);
8207 }
8208 }
8209}
8210
8211static void
8212bwn_key_write(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8213 const uint8_t *key)
8214{
8215 unsigned int i;
8216 uint32_t offset;
8217 uint16_t kidx, value;
8218
8219 kidx = BWN_SEC_KEY2FW(mac, index);
8220 bwn_shm_write_2(mac, BWN_SHARED,
8221 BWN_SHARED_KEYIDX_BLOCK + (kidx * 2), (kidx << 4) | algorithm);
8222
8223 offset = mac->mac_ktp + (index * BWN_SEC_KEYSIZE);
8224 for (i = 0; i < BWN_SEC_KEYSIZE; i += 2) {
8225 value = key[i];
8226 value |= (uint16_t)(key[i + 1]) << 8;
8227 bwn_shm_write_2(mac, BWN_SHARED, offset + i, value);
8228 }
8229}
8230
8231static void
8232bwn_phy_exit(struct bwn_mac *mac)
8233{
8234
8235 mac->mac_phy.rf_onoff(mac, 0);
8236 if (mac->mac_phy.exit != NULL)
8237 mac->mac_phy.exit(mac);
8238}
8239
8240static void
8241bwn_dma_free(struct bwn_mac *mac)
8242{
8243 struct bwn_dma *dma;
8244
8245 if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
8246 return;
8247 dma = &mac->mac_method.dma;
8248
8249 bwn_dma_ringfree(&dma->rx);
8250 bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
8251 bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
8252 bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
8253 bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
8254 bwn_dma_ringfree(&dma->mcast);
8255}
8256
8257static void
8258bwn_core_stop(struct bwn_mac *mac)
8259{
8260 struct bwn_softc *sc = mac->mac_sc;
8261
8262 BWN_ASSERT_LOCKED(sc);
8263
8264 if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8265 return;
8266
8267 callout_stop(&sc->sc_rfswitch_ch);
8268 callout_stop(&sc->sc_task_ch);
8269 callout_stop(&sc->sc_watchdog_ch);
8270 sc->sc_watchdog_timer = 0;
8271 BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8272 BWN_READ_4(mac, BWN_INTR_MASK);
8273 bwn_mac_suspend(mac);
8274
8275 mac->mac_status = BWN_MAC_STATUS_INITED;
8276}
8277
8278static int
8279bwn_switch_band(struct bwn_softc *sc, struct ieee80211_channel *chan)
8280{
8281 struct bwn_mac *up_dev = NULL;
8282 struct bwn_mac *down_dev;
8283 struct bwn_mac *mac;
8284 int err, status;
8285 uint8_t gmode;
8286
8287 BWN_ASSERT_LOCKED(sc);
8288
8289 TAILQ_FOREACH(mac, &sc->sc_maclist, mac_list) {
8290 if (IEEE80211_IS_CHAN_2GHZ(chan) &&
8291 mac->mac_phy.supports_2ghz) {
8292 up_dev = mac;
8293 gmode = 1;
8294 } else if (IEEE80211_IS_CHAN_5GHZ(chan) &&
8295 mac->mac_phy.supports_5ghz) {
8296 up_dev = mac;
8297 gmode = 0;
8298 } else {
8299 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8300 return (EINVAL);
8301 }
8302 if (up_dev != NULL)
8303 break;
8304 }
8305 if (up_dev == NULL) {
8306 device_printf(sc->sc_dev, "Could not find a device\n");
8307 return (ENODEV);
8308 }
8309 if (up_dev == sc->sc_curmac && sc->sc_curmac->mac_phy.gmode == gmode)
8310 return (0);
8311
8312 device_printf(sc->sc_dev, "switching to %s-GHz band\n",
8313 IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8314
8315 down_dev = sc->sc_curmac;;
8316 status = down_dev->mac_status;
8317 if (status >= BWN_MAC_STATUS_STARTED)
8318 bwn_core_stop(down_dev);
8319 if (status >= BWN_MAC_STATUS_INITED)
8320 bwn_core_exit(down_dev);
8321
8322 if (down_dev != up_dev)
8323 bwn_phy_reset(down_dev);
8324
8325 up_dev->mac_phy.gmode = gmode;
8326 if (status >= BWN_MAC_STATUS_INITED) {
8327 err = bwn_core_init(up_dev);
8328 if (err) {
8329 device_printf(sc->sc_dev,
8330 "fatal: failed to initialize for %s-GHz\n",
8331 IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8332 goto fail;
8333 }
8334 }
8335 if (status >= BWN_MAC_STATUS_STARTED)
8336 bwn_core_start(up_dev);
8337 KASSERT(up_dev->mac_status == status, ("%s: fail", __func__));
8338 sc->sc_curmac = up_dev;
8339
8340 return (0);
8341fail:
8342 sc->sc_curmac = NULL;
8343 return (err);
8344}
8345
8346static void
8347bwn_rf_turnon(struct bwn_mac *mac)
8348{
8349
8350 bwn_mac_suspend(mac);
8351 mac->mac_phy.rf_onoff(mac, 1);
8352 mac->mac_phy.rf_on = 1;
8353 bwn_mac_enable(mac);
8354}
8355
8356static void
8357bwn_rf_turnoff(struct bwn_mac *mac)
8358{
8359
8360 bwn_mac_suspend(mac);
8361 mac->mac_phy.rf_onoff(mac, 0);
8362 mac->mac_phy.rf_on = 0;
8363 bwn_mac_enable(mac);
8364}
8365
8366static void
8367bwn_phy_reset(struct bwn_mac *mac)
8368{
8369 struct bwn_softc *sc = mac->mac_sc;
8370
8371 siba_write_4(sc->sc_dev, SIBA_TGSLOW,
8372 ((siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~BWN_TGSLOW_SUPPORT_G) |
8373 BWN_TGSLOW_PHYRESET) | SIBA_TGSLOW_FGC);
8374 DELAY(1000);
8375 siba_write_4(sc->sc_dev, SIBA_TGSLOW,
8376 (siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~SIBA_TGSLOW_FGC) |
8377 BWN_TGSLOW_PHYRESET);
8378 DELAY(1000);
8379}
8380
8381static int
8382bwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
8383{
8384 struct bwn_vap *bvp = BWN_VAP(vap);
8385 struct ieee80211com *ic= vap->iv_ic;
8386 struct ifnet *ifp = ic->ic_ifp;
8387 enum ieee80211_state ostate = vap->iv_state;
8388 struct bwn_softc *sc = ifp->if_softc;
8389 struct bwn_mac *mac = sc->sc_curmac;
8390 int error;
8391
8392 DPRINTF(sc, BWN_DEBUG_STATE, "%s: %s -> %s\n", __func__,
8393 ieee80211_state_name[vap->iv_state],
8394 ieee80211_state_name[nstate]);
8395
8396 error = bvp->bv_newstate(vap, nstate, arg);
8397 if (error != 0)
8398 return (error);
8399
8400 BWN_LOCK(sc);
8401
8402 bwn_led_newstate(mac, nstate);
8403
8404 /*
8405 * Clear the BSSID when we stop a STA
8406 */
8407 if (vap->iv_opmode == IEEE80211_M_STA) {
8408 if (ostate == IEEE80211_S_RUN && nstate != IEEE80211_S_RUN) {
8409 /*
8410 * Clear out the BSSID. If we reassociate to
8411 * the same AP, this will reinialize things
8412 * correctly...
8413 */
8414 if (ic->ic_opmode == IEEE80211_M_STA &&
8415 (sc->sc_flags & BWN_FLAG_INVALID) == 0) {
8416 memset(sc->sc_bssid, 0, IEEE80211_ADDR_LEN);
8417 bwn_set_macaddr(mac);
8418 }
8419 }
8420 }
8421
8422 if (vap->iv_opmode == IEEE80211_M_MONITOR ||
8423 vap->iv_opmode == IEEE80211_M_AHDEMO) {
8424 /* XXX nothing to do? */
8425 } else if (nstate == IEEE80211_S_RUN) {
8426 memcpy(sc->sc_bssid, vap->iv_bss->ni_bssid, IEEE80211_ADDR_LEN);
8427 memcpy(sc->sc_macaddr, IF_LLADDR(ifp), IEEE80211_ADDR_LEN);
8428 bwn_set_opmode(mac);
8429 bwn_set_pretbtt(mac);
8430 bwn_spu_setdelay(mac, 0);
8431 bwn_set_macaddr(mac);
8432 }
8433
8434 BWN_UNLOCK(sc);
8435
8436 return (error);
8437}
8438
8439static void
8440bwn_set_pretbtt(struct bwn_mac *mac)
8441{
8442 struct bwn_softc *sc = mac->mac_sc;
8443 struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8444 uint16_t pretbtt;
8445
8446 if (ic->ic_opmode == IEEE80211_M_IBSS)
8447 pretbtt = 2;
8448 else
8449 pretbtt = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 120 : 250;
8450 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PRETBTT, pretbtt);
8451 BWN_WRITE_2(mac, BWN_TSF_CFP_PRETBTT, pretbtt);
8452}
8453
8454static int
8455bwn_intr(void *arg)
8456{
8457 struct bwn_mac *mac = arg;
8458 struct bwn_softc *sc = mac->mac_sc;
8459 uint32_t reason;
8460
8461 if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
8462 (sc->sc_flags & BWN_FLAG_INVALID))
8463 return (FILTER_STRAY);
8464
8465 reason = BWN_READ_4(mac, BWN_INTR_REASON);
8466 if (reason == 0xffffffff) /* shared IRQ */
8467 return (FILTER_STRAY);
8468 reason &= mac->mac_intr_mask;
8469 if (reason == 0)
8470 return (FILTER_HANDLED);
8471
8472 mac->mac_reason[0] = BWN_READ_4(mac, BWN_DMA0_REASON) & 0x0001dc00;
8473 mac->mac_reason[1] = BWN_READ_4(mac, BWN_DMA1_REASON) & 0x0000dc00;
8474 mac->mac_reason[2] = BWN_READ_4(mac, BWN_DMA2_REASON) & 0x0000dc00;
8475 mac->mac_reason[3] = BWN_READ_4(mac, BWN_DMA3_REASON) & 0x0001dc00;
8476 mac->mac_reason[4] = BWN_READ_4(mac, BWN_DMA4_REASON) & 0x0000dc00;
8477 BWN_WRITE_4(mac, BWN_INTR_REASON, reason);
8478 BWN_WRITE_4(mac, BWN_DMA0_REASON, mac->mac_reason[0]);
8479 BWN_WRITE_4(mac, BWN_DMA1_REASON, mac->mac_reason[1]);
8480 BWN_WRITE_4(mac, BWN_DMA2_REASON, mac->mac_reason[2]);
8481 BWN_WRITE_4(mac, BWN_DMA3_REASON, mac->mac_reason[3]);
8482 BWN_WRITE_4(mac, BWN_DMA4_REASON, mac->mac_reason[4]);
8483
8484 /* Disable interrupts. */
8485 BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8486
8487 mac->mac_reason_intr = reason;
8488
8489 BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8490 BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8491
8492 taskqueue_enqueue_fast(sc->sc_tq, &mac->mac_intrtask);
8493 return (FILTER_HANDLED);
8494}
8495
8496static void
8497bwn_intrtask(void *arg, int npending)
8498{
8499 struct bwn_mac *mac = arg;
8500 struct bwn_softc *sc = mac->mac_sc;
8501 struct ifnet *ifp = sc->sc_ifp;
8502 uint32_t merged = 0;
8503 int i, tx = 0, rx = 0;
8504
8505 BWN_LOCK(sc);
8506 if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
8507 (sc->sc_flags & BWN_FLAG_INVALID)) {
8508 BWN_UNLOCK(sc);
8509 return;
8510 }
8511
8512 for (i = 0; i < N(mac->mac_reason); i++)
8513 merged |= mac->mac_reason[i];
8514
8515 if (mac->mac_reason_intr & BWN_INTR_MAC_TXERR)
8516 device_printf(sc->sc_dev, "MAC trans error\n");
8517
8518 if (mac->mac_reason_intr & BWN_INTR_PHY_TXERR) {
8519 DPRINTF(sc, BWN_DEBUG_INTR, "%s: PHY trans error\n", __func__);
8520 mac->mac_phy.txerrors--;
8521 if (mac->mac_phy.txerrors == 0) {
8522 mac->mac_phy.txerrors = BWN_TXERROR_MAX;
8523 bwn_restart(mac, "PHY TX errors");
8524 }
8525 }
8526
8527 if (merged & (BWN_DMAINTR_FATALMASK | BWN_DMAINTR_NONFATALMASK)) {
8528 if (merged & BWN_DMAINTR_FATALMASK) {
8529 device_printf(sc->sc_dev,
8530 "Fatal DMA error: %#x %#x %#x %#x %#x %#x\n",
8531 mac->mac_reason[0], mac->mac_reason[1],
8532 mac->mac_reason[2], mac->mac_reason[3],
8533 mac->mac_reason[4], mac->mac_reason[5]);
8534 bwn_restart(mac, "DMA error");
8535 BWN_UNLOCK(sc);
8536 return;
8537 }
8538 if (merged & BWN_DMAINTR_NONFATALMASK) {
8539 device_printf(sc->sc_dev,
8540 "DMA error: %#x %#x %#x %#x %#x %#x\n",
8541 mac->mac_reason[0], mac->mac_reason[1],
8542 mac->mac_reason[2], mac->mac_reason[3],
8543 mac->mac_reason[4], mac->mac_reason[5]);
8544 }
8545 }
8546
8547 if (mac->mac_reason_intr & BWN_INTR_UCODE_DEBUG)
8548 bwn_intr_ucode_debug(mac);
8549 if (mac->mac_reason_intr & BWN_INTR_TBTT_INDI)
8550 bwn_intr_tbtt_indication(mac);
8551 if (mac->mac_reason_intr & BWN_INTR_ATIM_END)
8552 bwn_intr_atim_end(mac);
8553 if (mac->mac_reason_intr & BWN_INTR_BEACON)
8554 bwn_intr_beacon(mac);
8555 if (mac->mac_reason_intr & BWN_INTR_PMQ)
8556 bwn_intr_pmq(mac);
8557 if (mac->mac_reason_intr & BWN_INTR_NOISESAMPLE_OK)
8558 bwn_intr_noise(mac);
8559
8560 if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
8561 if (mac->mac_reason[0] & BWN_DMAINTR_RX_DONE) {
8562 bwn_dma_rx(mac->mac_method.dma.rx);
8563 rx = 1;
8564 }
8565 } else
8566 rx = bwn_pio_rx(&mac->mac_method.pio.rx);
8567
8568 KASSERT(!(mac->mac_reason[1] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8569 KASSERT(!(mac->mac_reason[2] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8570 KASSERT(!(mac->mac_reason[3] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8571 KASSERT(!(mac->mac_reason[4] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8572 KASSERT(!(mac->mac_reason[5] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8573
8574 if (mac->mac_reason_intr & BWN_INTR_TX_OK) {
8575 bwn_intr_txeof(mac);
8576 tx = 1;
8577 }
8578
8579 BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
8580
8581 if (sc->sc_blink_led != NULL && sc->sc_led_blink) {
8582 int evt = BWN_LED_EVENT_NONE;
8583
8584 if (tx && rx) {
8585 if (sc->sc_rx_rate > sc->sc_tx_rate)
8586 evt = BWN_LED_EVENT_RX;
8587 else
8588 evt = BWN_LED_EVENT_TX;
8589 } else if (tx) {
8590 evt = BWN_LED_EVENT_TX;
8591 } else if (rx) {
8592 evt = BWN_LED_EVENT_RX;
8593 } else if (rx == 0) {
8594 evt = BWN_LED_EVENT_POLL;
8595 }
8596
8597 if (evt != BWN_LED_EVENT_NONE)
8598 bwn_led_event(mac, evt);
8599 }
8600
8601 if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0) {
8602 if (!IFQ_IS_EMPTY(&ifp->if_snd))
8603 bwn_start_locked(ifp);
8604 }
8605
8606 BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8607 BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8608
8609 BWN_UNLOCK(sc);
8610}
8611
8612static void
8613bwn_restart(struct bwn_mac *mac, const char *msg)
8614{
8615 struct bwn_softc *sc = mac->mac_sc;
8616 struct ifnet *ifp = sc->sc_ifp;
8617 struct ieee80211com *ic = ifp->if_l2com;
8618
8619 if (mac->mac_status < BWN_MAC_STATUS_INITED)
8620 return;
8621
8622 device_printf(sc->sc_dev, "HW reset: %s\n", msg);
8623 ieee80211_runtask(ic, &mac->mac_hwreset);
8624}
8625
8626static void
8627bwn_intr_ucode_debug(struct bwn_mac *mac)
8628{
8629 struct bwn_softc *sc = mac->mac_sc;
8630 uint16_t reason;
8631
8632 if (mac->mac_fw.opensource == 0)
8633 return;
8634
8635 reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG);
8636 switch (reason) {
8637 case BWN_DEBUGINTR_PANIC:
8638 bwn_handle_fwpanic(mac);
8639 break;
8640 case BWN_DEBUGINTR_DUMP_SHM:
8641 device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_SHM\n");
8642 break;
8643 case BWN_DEBUGINTR_DUMP_REGS:
8644 device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_REGS\n");
8645 break;
8646 case BWN_DEBUGINTR_MARKER:
8647 device_printf(sc->sc_dev, "BWN_DEBUGINTR_MARKER\n");
8648 break;
8649 default:
8650 device_printf(sc->sc_dev,
8651 "ucode debug unknown reason: %#x\n", reason);
8652 }
8653
8654 bwn_shm_write_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG,
8655 BWN_DEBUGINTR_ACK);
8656}
8657
8658static void
8659bwn_intr_tbtt_indication(struct bwn_mac *mac)
8660{
8661 struct bwn_softc *sc = mac->mac_sc;
8662 struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8663
8664 if (ic->ic_opmode != IEEE80211_M_HOSTAP)
8665 bwn_psctl(mac, 0);
8666 if (ic->ic_opmode == IEEE80211_M_IBSS)
8667 mac->mac_flags |= BWN_MAC_FLAG_DFQVALID;
8668}
8669
8670static void
8671bwn_intr_atim_end(struct bwn_mac *mac)
8672{
8673
8674 if (mac->mac_flags & BWN_MAC_FLAG_DFQVALID) {
8675 BWN_WRITE_4(mac, BWN_MACCMD,
8676 BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_DFQ_VALID);
8677 mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
8678 }
8679}
8680
8681static void
8682bwn_intr_beacon(struct bwn_mac *mac)
8683{
8684 struct bwn_softc *sc = mac->mac_sc;
8685 struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8686 uint32_t cmd, beacon0, beacon1;
8687
8688 if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
8689 ic->ic_opmode == IEEE80211_M_MBSS)
8690 return;
8691
8692 mac->mac_intr_mask &= ~BWN_INTR_BEACON;
8693
8694 cmd = BWN_READ_4(mac, BWN_MACCMD);
8695 beacon0 = (cmd & BWN_MACCMD_BEACON0_VALID);
8696 beacon1 = (cmd & BWN_MACCMD_BEACON1_VALID);
8697
8698 if (beacon0 && beacon1) {
8699 BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_BEACON);
8700 mac->mac_intr_mask |= BWN_INTR_BEACON;
8701 return;
8702 }
8703
8704 if (sc->sc_flags & BWN_FLAG_NEED_BEACON_TP) {
8705 sc->sc_flags &= ~BWN_FLAG_NEED_BEACON_TP;
8706 bwn_load_beacon0(mac);
8707 bwn_load_beacon1(mac);
8708 cmd = BWN_READ_4(mac, BWN_MACCMD);
8709 cmd |= BWN_MACCMD_BEACON0_VALID;
8710 BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8711 } else {
8712 if (!beacon0) {
8713 bwn_load_beacon0(mac);
8714 cmd = BWN_READ_4(mac, BWN_MACCMD);
8715 cmd |= BWN_MACCMD_BEACON0_VALID;
8716 BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8717 } else if (!beacon1) {
8718 bwn_load_beacon1(mac);
8719 cmd = BWN_READ_4(mac, BWN_MACCMD);
8720 cmd |= BWN_MACCMD_BEACON1_VALID;
8721 BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8722 }
8723 }
8724}
8725
8726static void
8727bwn_intr_pmq(struct bwn_mac *mac)
8728{
8729 uint32_t tmp;
8730
8731 while (1) {
8732 tmp = BWN_READ_4(mac, BWN_PS_STATUS);
8733 if (!(tmp & 0x00000008))
8734 break;
8735 }
8736 BWN_WRITE_2(mac, BWN_PS_STATUS, 0x0002);
8737}
8738
8739static void
8740bwn_intr_noise(struct bwn_mac *mac)
8741{
8742 struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
8743 uint16_t tmp;
8744 uint8_t noise[4];
8745 uint8_t i, j;
8746 int32_t average;
8747
8748 if (mac->mac_phy.type != BWN_PHYTYPE_G)
8749 return;
8750
8751 KASSERT(mac->mac_noise.noi_running, ("%s: fail", __func__));
8752 *((uint32_t *)noise) = htole32(bwn_jssi_read(mac));
8753 if (noise[0] == 0x7f || noise[1] == 0x7f || noise[2] == 0x7f ||
8754 noise[3] == 0x7f)
8755 goto new;
8756
8757 KASSERT(mac->mac_noise.noi_nsamples < 8,
8758 ("%s:%d: fail", __func__, __LINE__));
8759 i = mac->mac_noise.noi_nsamples;
8760 noise[0] = MIN(MAX(noise[0], 0), N(pg->pg_nrssi_lt) - 1);
8761 noise[1] = MIN(MAX(noise[1], 0), N(pg->pg_nrssi_lt) - 1);
8762 noise[2] = MIN(MAX(noise[2], 0), N(pg->pg_nrssi_lt) - 1);
8763 noise[3] = MIN(MAX(noise[3], 0), N(pg->pg_nrssi_lt) - 1);
8764 mac->mac_noise.noi_samples[i][0] = pg->pg_nrssi_lt[noise[0]];
8765 mac->mac_noise.noi_samples[i][1] = pg->pg_nrssi_lt[noise[1]];
8766 mac->mac_noise.noi_samples[i][2] = pg->pg_nrssi_lt[noise[2]];
8767 mac->mac_noise.noi_samples[i][3] = pg->pg_nrssi_lt[noise[3]];
8768 mac->mac_noise.noi_nsamples++;
8769 if (mac->mac_noise.noi_nsamples == 8) {
8770 average = 0;
8771 for (i = 0; i < 8; i++) {
8772 for (j = 0; j < 4; j++)
8773 average += mac->mac_noise.noi_samples[i][j];
8774 }
8775 average = (((average / 32) * 125) + 64) / 128;
8776 tmp = (bwn_shm_read_2(mac, BWN_SHARED, 0x40c) / 128) & 0x1f;
8777 if (tmp >= 8)
8778 average += 2;
8779 else
8780 average -= 25;
8781 average -= (tmp == 8) ? 72 : 48;
8782
8783 mac->mac_stats.link_noise = average;
8784 mac->mac_noise.noi_running = 0;
8785 return;
8786 }
8787new:
8788 bwn_noise_gensample(mac);
8789}
8790
8791static int
8792bwn_pio_rx(struct bwn_pio_rxqueue *prq)
8793{
8794 struct bwn_mac *mac = prq->prq_mac;
8795 struct bwn_softc *sc = mac->mac_sc;
8796 unsigned int i;
8797
8798 BWN_ASSERT_LOCKED(sc);
8799
8800 if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8801 return (0);
8802
8803 for (i = 0; i < 5000; i++) {
8804 if (bwn_pio_rxeof(prq) == 0)
8805 break;
8806 }
8807 if (i >= 5000)
8808 device_printf(sc->sc_dev, "too many RX frames in PIO mode\n");
8809 return ((i > 0) ? 1 : 0);
8810}
8811
8812static void
8813bwn_dma_rx(struct bwn_dma_ring *dr)
8814{
8815 int slot, curslot;
8816
8817 KASSERT(!dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
8818 curslot = dr->get_curslot(dr);
8819 KASSERT(curslot >= 0 && curslot < dr->dr_numslots,
8820 ("%s:%d: fail", __func__, __LINE__));
8821
8822 slot = dr->dr_curslot;
8823 for (; slot != curslot; slot = bwn_dma_nextslot(dr, slot))
8824 bwn_dma_rxeof(dr, &slot);
8825
8826 bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
8827 BUS_DMASYNC_PREWRITE);
8828
8829 dr->set_curslot(dr, slot);
8830 dr->dr_curslot = slot;
8831}
8832
8833static void
8834bwn_intr_txeof(struct bwn_mac *mac)
8835{
8836 struct bwn_txstatus stat;
8837 uint32_t stat0, stat1;
8838 uint16_t tmp;
8839
8840 BWN_ASSERT_LOCKED(mac->mac_sc);
8841
8842 while (1) {
8843 stat0 = BWN_READ_4(mac, BWN_XMITSTAT_0);
8844 if (!(stat0 & 0x00000001))
8845 break;
8846 stat1 = BWN_READ_4(mac, BWN_XMITSTAT_1);
8847
8848 stat.cookie = (stat0 >> 16);
8849 stat.seq = (stat1 & 0x0000ffff);
8850 stat.phy_stat = ((stat1 & 0x00ff0000) >> 16);
8851 tmp = (stat0 & 0x0000ffff);
8852 stat.framecnt = ((tmp & 0xf000) >> 12);
8853 stat.rtscnt = ((tmp & 0x0f00) >> 8);
8854 stat.sreason = ((tmp & 0x001c) >> 2);
8855 stat.pm = (tmp & 0x0080) ? 1 : 0;
8856 stat.im = (tmp & 0x0040) ? 1 : 0;
8857 stat.ampdu = (tmp & 0x0020) ? 1 : 0;
8858 stat.ack = (tmp & 0x0002) ? 1 : 0;
8859
8860 bwn_handle_txeof(mac, &stat);
8861 }
8862}
8863
8864static void
8865bwn_hwreset(void *arg, int npending)
8866{
8867 struct bwn_mac *mac = arg;
8868 struct bwn_softc *sc = mac->mac_sc;
8869 int error = 0;
8870 int prev_status;
8871
8872 BWN_LOCK(sc);
8873
8874 prev_status = mac->mac_status;
8875 if (prev_status >= BWN_MAC_STATUS_STARTED)
8876 bwn_core_stop(mac);
8877 if (prev_status >= BWN_MAC_STATUS_INITED)
8878 bwn_core_exit(mac);
8879
8880 if (prev_status >= BWN_MAC_STATUS_INITED) {
8881 error = bwn_core_init(mac);
8882 if (error)
8883 goto out;
8884 }
8885 if (prev_status >= BWN_MAC_STATUS_STARTED)
8886 bwn_core_start(mac);
8887out:
8888 if (error) {
8889 device_printf(sc->sc_dev, "%s: failed (%d)\n", __func__, error);
8890 sc->sc_curmac = NULL;
8891 }
8892 BWN_UNLOCK(sc);
8893}
8894
8895static void
8896bwn_handle_fwpanic(struct bwn_mac *mac)
8897{
8898 struct bwn_softc *sc = mac->mac_sc;
8899 uint16_t reason;
8900
8901 reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_FWPANIC_REASON_REG);
8902 device_printf(sc->sc_dev,"fw panic (%u)\n", reason);
8903
8904 if (reason == BWN_FWPANIC_RESTART)
8905 bwn_restart(mac, "ucode panic");
8906}
8907
8908static void
8909bwn_load_beacon0(struct bwn_mac *mac)
8910{
8911
8912 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8913}
8914
8915static void
8916bwn_load_beacon1(struct bwn_mac *mac)
8917{
8918
8919 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8920}
8921
8922static uint32_t
8923bwn_jssi_read(struct bwn_mac *mac)
8924{
8925 uint32_t val = 0;
8926
8927 val = bwn_shm_read_2(mac, BWN_SHARED, 0x08a);
8928 val <<= 16;
8929 val |= bwn_shm_read_2(mac, BWN_SHARED, 0x088);
8930
8931 return (val);
8932}
8933
8934static void
8935bwn_noise_gensample(struct bwn_mac *mac)
8936{
8937 uint32_t jssi = 0x7f7f7f7f;
8938
8939 bwn_shm_write_2(mac, BWN_SHARED, 0x088, (jssi & 0x0000ffff));
8940 bwn_shm_write_2(mac, BWN_SHARED, 0x08a, (jssi & 0xffff0000) >> 16);
8941 BWN_WRITE_4(mac, BWN_MACCMD,
8942 BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_BGNOISE);
8943}
8944
8945static int
8946bwn_dma_freeslot(struct bwn_dma_ring *dr)
8947{
8948 BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8949
8950 return (dr->dr_numslots - dr->dr_usedslot);
8951}
8952
8953static int
8954bwn_dma_nextslot(struct bwn_dma_ring *dr, int slot)
8955{
8956 BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8957
8958 KASSERT(slot >= -1 && slot <= dr->dr_numslots - 1,
8959 ("%s:%d: fail", __func__, __LINE__));
8960 if (slot == dr->dr_numslots - 1)
8961 return (0);
8962 return (slot + 1);
8963}
8964
8965static void
8966bwn_dma_rxeof(struct bwn_dma_ring *dr, int *slot)
8967{
8968 struct bwn_mac *mac = dr->dr_mac;
8969 struct bwn_softc *sc = mac->mac_sc;
8970 struct bwn_dma *dma = &mac->mac_method.dma;
8971 struct bwn_dmadesc_generic *desc;
8972 struct bwn_dmadesc_meta *meta;
8973 struct bwn_rxhdr4 *rxhdr;
8974 struct ifnet *ifp = sc->sc_ifp;
8975 struct mbuf *m;
8976 uint32_t macstat;
8977 int32_t tmp;
8978 int cnt = 0;
8979 uint16_t len;
8980
8981 dr->getdesc(dr, *slot, &desc, &meta);
8982
8983 bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap, BUS_DMASYNC_POSTREAD);
8984 m = meta->mt_m;
8985
8986 if (bwn_dma_newbuf(dr, desc, meta, 0)) {
8987 ifp->if_ierrors++;
8988 return;
8989 }
8990
8991 rxhdr = mtod(m, struct bwn_rxhdr4 *);
8992 len = le16toh(rxhdr->frame_len);
8993 if (len <= 0) {
8994 ifp->if_ierrors++;
8995 return;
8996 }
8997 if (bwn_dma_check_redzone(dr, m)) {
8998 device_printf(sc->sc_dev, "redzone error.\n");
8999 bwn_dma_set_redzone(dr, m);
9000 bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
9001 BUS_DMASYNC_PREWRITE);
9002 return;
9003 }
9004 if (len > dr->dr_rx_bufsize) {
9005 tmp = len;
9006 while (1) {
9007 dr->getdesc(dr, *slot, &desc, &meta);
9008 bwn_dma_set_redzone(dr, meta->mt_m);
9009 bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
9010 BUS_DMASYNC_PREWRITE);
9011 *slot = bwn_dma_nextslot(dr, *slot);
9012 cnt++;
9013 tmp -= dr->dr_rx_bufsize;
9014 if (tmp <= 0)
9015 break;
9016 }
9017 device_printf(sc->sc_dev, "too small buffer "
9018 "(len %u buffer %u dropped %d)\n",
9019 len, dr->dr_rx_bufsize, cnt);
9020 return;
9021 }
9022 macstat = le32toh(rxhdr->mac_status);
9023 if (macstat & BWN_RX_MAC_FCSERR) {
9024 if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
9025 device_printf(sc->sc_dev, "RX drop\n");
9026 return;
9027 }
9028 }
9029
9030 m->m_pkthdr.rcvif = ifp;
9031 m->m_len = m->m_pkthdr.len = len + dr->dr_frameoffset;
9032 m_adj(m, dr->dr_frameoffset);
9033
9034 bwn_rxeof(dr->dr_mac, m, rxhdr);
9035}
9036
9037static void
9038bwn_handle_txeof(struct bwn_mac *mac, const struct bwn_txstatus *status)
9039{
9040 struct bwn_dma_ring *dr;
9041 struct bwn_dmadesc_generic *desc;
9042 struct bwn_dmadesc_meta *meta;
9043 struct bwn_node *bn;
9044 struct bwn_pio_txqueue *tq;
9045 struct bwn_pio_txpkt *tp = NULL;
9046 struct bwn_softc *sc = mac->mac_sc;
9047 struct bwn_stats *stats = &mac->mac_stats;
9048 struct ieee80211_node *ni;
9049 int slot;
9050
9051 BWN_ASSERT_LOCKED(mac->mac_sc);
9052
9053 if (status->im)
9054 device_printf(sc->sc_dev, "TODO: STATUS IM\n");
9055 if (status->ampdu)
9056 device_printf(sc->sc_dev, "TODO: STATUS AMPDU\n");
9057 if (status->rtscnt) {
9058 if (status->rtscnt == 0xf)
9059 stats->rtsfail++;
9060 else
9061 stats->rts++;
9062 }
9063
9064 if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
9065 if (status->ack) {
9066 dr = bwn_dma_parse_cookie(mac, status,
9067 status->cookie, &slot);
9068 if (dr == NULL) {
9069 device_printf(sc->sc_dev,
9070 "failed to parse cookie\n");
9071 return;
9072 }
9073 while (1) {
9074 dr->getdesc(dr, slot, &desc, &meta);
9075 if (meta->mt_islast) {
9076 ni = meta->mt_ni;
9077 bn = (struct bwn_node *)ni;
9078 ieee80211_amrr_tx_complete(&bn->bn_amn,
9079 status->ack, 0);
9080 break;
9081 }
9082 slot = bwn_dma_nextslot(dr, slot);
9083 }
9084 }
9085 bwn_dma_handle_txeof(mac, status);
9086 } else {
9087 if (status->ack) {
9088 tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9089 if (tq == NULL) {
9090 device_printf(sc->sc_dev,
9091 "failed to parse cookie\n");
9092 return;
9093 }
9094 ni = tp->tp_ni;
9095 bn = (struct bwn_node *)ni;
9096 ieee80211_amrr_tx_complete(&bn->bn_amn, status->ack, 0);
9097 }
9098 bwn_pio_handle_txeof(mac, status);
9099 }
9100
9101 bwn_phy_txpower_check(mac, 0);
9102}
9103
9104static uint8_t
9105bwn_pio_rxeof(struct bwn_pio_rxqueue *prq)
9106{
9107 struct bwn_mac *mac = prq->prq_mac;
9108 struct bwn_softc *sc = mac->mac_sc;
9109 struct bwn_rxhdr4 rxhdr;
9110 struct ifnet *ifp = sc->sc_ifp;
9111 struct mbuf *m;
9112 uint32_t ctl32, macstat, v32;
9113 unsigned int i, padding;
9114 uint16_t ctl16, len, v16;
9115 unsigned char *mp;
9116 char *data;
9117
9118 memset(&rxhdr, 0, sizeof(rxhdr));
9119
9120 if (prq->prq_rev >= 8) {
9121 ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
9122 if (!(ctl32 & BWN_PIO8_RXCTL_FRAMEREADY))
9123 return (0);
9124 bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9125 BWN_PIO8_RXCTL_FRAMEREADY);
9126 for (i = 0; i < 10; i++) {
9127 ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
9128 if (ctl32 & BWN_PIO8_RXCTL_DATAREADY)
9129 goto ready;
9130 DELAY(10);
9131 }
9132 } else {
9133 ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
9134 if (!(ctl16 & BWN_PIO_RXCTL_FRAMEREADY))
9135 return (0);
9136 bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL,
9137 BWN_PIO_RXCTL_FRAMEREADY);
9138 for (i = 0; i < 10; i++) {
9139 ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
9140 if (ctl16 & BWN_PIO_RXCTL_DATAREADY)
9141 goto ready;
9142 DELAY(10);
9143 }
9144 }
9145 device_printf(sc->sc_dev, "%s: timed out\n", __func__);
9146 return (1);
9147ready:
9148 if (prq->prq_rev >= 8)
9149 siba_read_multi_4(sc->sc_dev, &rxhdr, sizeof(rxhdr),
9150 prq->prq_base + BWN_PIO8_RXDATA);
9151 else
9152 siba_read_multi_2(sc->sc_dev, &rxhdr, sizeof(rxhdr),
9153 prq->prq_base + BWN_PIO_RXDATA);
9154 len = le16toh(rxhdr.frame_len);
9155 if (len > 0x700) {
9156 device_printf(sc->sc_dev, "%s: len is too big\n", __func__);
9157 goto error;
9158 }
9159 if (len == 0) {
9160 device_printf(sc->sc_dev, "%s: len is 0\n", __func__);
9161 goto error;
9162 }
9163
9164 macstat = le32toh(rxhdr.mac_status);
9165 if (macstat & BWN_RX_MAC_FCSERR) {
9166 if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
9167 device_printf(sc->sc_dev, "%s: FCS error", __func__);
9168 goto error;
9169 }
9170 }
9171
9172 padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9173 KASSERT(len + padding <= MCLBYTES, ("too big..\n"));
9174 m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
9175 if (m == NULL) {
9176 device_printf(sc->sc_dev, "%s: out of memory", __func__);
9177 goto error;
9178 }
9179 mp = mtod(m, unsigned char *);
9180 if (prq->prq_rev >= 8) {
9181 siba_read_multi_4(sc->sc_dev, mp + padding, (len & ~3),
9182 prq->prq_base + BWN_PIO8_RXDATA);
9183 if (len & 3) {
9184 v32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXDATA);
9185 data = &(mp[len + padding - 1]);
9186 switch (len & 3) {
9187 case 3:
9188 *data = (v32 >> 16);
9189 data--;
9190 case 2:
9191 *data = (v32 >> 8);
9192 data--;
9193 case 1:
9194 *data = v32;
9195 }
9196 }
9197 } else {
9198 siba_read_multi_2(sc->sc_dev, mp + padding, (len & ~1),
9199 prq->prq_base + BWN_PIO_RXDATA);
9200 if (len & 1) {
9201 v16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXDATA);
9202 mp[len + padding - 1] = v16;
9203 }
9204 }
9205
9206 m->m_pkthdr.rcvif = ifp;
9207 m->m_len = m->m_pkthdr.len = len + padding;
9208
9209 bwn_rxeof(prq->prq_mac, m, &rxhdr);
9210
9211 return (1);
9212error:
9213 if (prq->prq_rev >= 8)
9214 bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9215 BWN_PIO8_RXCTL_DATAREADY);
9216 else
9217 bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL, BWN_PIO_RXCTL_DATAREADY);
9218 return (1);
9219}
9220
9221static int
9222bwn_dma_newbuf(struct bwn_dma_ring *dr, struct bwn_dmadesc_generic *desc,
9223 struct bwn_dmadesc_meta *meta, int init)
9224{
9225 struct bwn_mac *mac = dr->dr_mac;
9226 struct bwn_dma *dma = &mac->mac_method.dma;
9227 struct bwn_rxhdr4 *hdr;
9228 bus_dmamap_t map;
9229 bus_addr_t paddr;
9230 struct mbuf *m;
9231 int error;
9232
9233 m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
9234 if (m == NULL) {
9235 error = ENOBUFS;
9236
9237 /*
9238 * If the NIC is up and running, we need to:
9239 * - Clear RX buffer's header.
9240 * - Restore RX descriptor settings.
9241 */
9242 if (init)
9243 return (error);
9244 else
9245 goto back;
9246 }
9247 m->m_len = m->m_pkthdr.len = MCLBYTES;
9248
9249 bwn_dma_set_redzone(dr, m);
9250
9251 /*
9252 * Try to load RX buf into temporary DMA map
9253 */
9254 error = bus_dmamap_load_mbuf(dma->rxbuf_dtag, dr->dr_spare_dmap, m,
9255 bwn_dma_buf_addr, &paddr, BUS_DMA_NOWAIT);
9256 if (error) {
9257 m_freem(m);
9258
9259 /*
9260 * See the comment above
9261 */
9262 if (init)
9263 return (error);
9264 else
9265 goto back;
9266 }
9267
9268 if (!init)
9269 bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
9270 meta->mt_m = m;
9271 meta->mt_paddr = paddr;
9272
9273 /*
9274 * Swap RX buf's DMA map with the loaded temporary one
9275 */
9276 map = meta->mt_dmap;
9277 meta->mt_dmap = dr->dr_spare_dmap;
9278 dr->dr_spare_dmap = map;
9279
9280back:
9281 /*
9282 * Clear RX buf header
9283 */
9284 hdr = mtod(meta->mt_m, struct bwn_rxhdr4 *);
9285 bzero(hdr, sizeof(*hdr));
9286 bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
9287 BUS_DMASYNC_PREWRITE);
9288
9289 /*
9290 * Setup RX buf descriptor
9291 */
9292 dr->setdesc(dr, desc, paddr, meta->mt_m->m_len -
9293 sizeof(*hdr), 0, 0, 0);
9294 return (error);
9295}
9296
9297static void
9298bwn_dma_buf_addr(void *arg, bus_dma_segment_t *seg, int nseg,
9299 bus_size_t mapsz __unused, int error)
9300{
9301
9302 if (!error) {
9303 KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
9304 *((bus_addr_t *)arg) = seg->ds_addr;
9305 }
9306}
9307
9308static int
9309bwn_hwrate2ieeerate(int rate)
9310{
9311
9312 switch (rate) {
9313 case BWN_CCK_RATE_1MB:
9314 return (2);
9315 case BWN_CCK_RATE_2MB:
9316 return (4);
9317 case BWN_CCK_RATE_5MB:
9318 return (11);
9319 case BWN_CCK_RATE_11MB:
9320 return (22);
9321 case BWN_OFDM_RATE_6MB:
9322 return (12);
9323 case BWN_OFDM_RATE_9MB:
9324 return (18);
9325 case BWN_OFDM_RATE_12MB:
9326 return (24);
9327 case BWN_OFDM_RATE_18MB:
9328 return (36);
9329 case BWN_OFDM_RATE_24MB:
9330 return (48);
9331 case BWN_OFDM_RATE_36MB:
9332 return (72);
9333 case BWN_OFDM_RATE_48MB:
9334 return (96);
9335 case BWN_OFDM_RATE_54MB:
9336 return (108);
9337 default:
9338 printf("Ooops\n");
9339 return (0);
9340 }
9341}
9342
9343static void
9344bwn_rxeof(struct bwn_mac *mac, struct mbuf *m, const void *_rxhdr)
9345{
9346 const struct bwn_rxhdr4 *rxhdr = _rxhdr;
9347 struct bwn_plcp6 *plcp;
9348 struct bwn_softc *sc = mac->mac_sc;
9349 struct ieee80211_frame_min *wh;
9350 struct ieee80211_node *ni;
9351 struct ifnet *ifp = sc->sc_ifp;
9352 struct ieee80211com *ic = ifp->if_l2com;
9353 uint32_t macstat;
9354 int padding, rate, rssi = 0, noise = 0, type;
9355 uint16_t phytype, phystat0, phystat3, chanstat;
9356 unsigned char *mp = mtod(m, unsigned char *);
9357 static int rx_mac_dec_rpt = 0;
9358
9359 BWN_ASSERT_LOCKED(sc);
9360
9361 phystat0 = le16toh(rxhdr->phy_status0);
9362 phystat3 = le16toh(rxhdr->phy_status3);
9363 macstat = le32toh(rxhdr->mac_status);
9364 chanstat = le16toh(rxhdr->channel);
9365 phytype = chanstat & BWN_RX_CHAN_PHYTYPE;
9366
9367 if (macstat & BWN_RX_MAC_FCSERR)
9368 device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_FCS_CRC\n");
9369 if (phystat0 & (BWN_RX_PHYST0_PLCPHCF | BWN_RX_PHYST0_PLCPFV))
9370 device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_PLCP_CRC\n");
9371 if (macstat & BWN_RX_MAC_DECERR)
9372 goto drop;
9373
9374 padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9375 if (m->m_pkthdr.len < (sizeof(struct bwn_plcp6) + padding)) {
9376 device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9377 m->m_pkthdr.len);
9378 goto drop;
9379 }
9380 plcp = (struct bwn_plcp6 *)(mp + padding);
9381 m_adj(m, sizeof(struct bwn_plcp6) + padding);
9382 if (m->m_pkthdr.len < IEEE80211_MIN_LEN) {
9383 device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9384 m->m_pkthdr.len);
9385 goto drop;
9386 }
9387 wh = mtod(m, struct ieee80211_frame_min *);
9388
9389 if (macstat & BWN_RX_MAC_DEC && rx_mac_dec_rpt++ < 50)
9390 device_printf(sc->sc_dev,
9391 "RX decryption attempted (old %d keyidx %#x)\n",
9392 BWN_ISOLDFMT(mac),
9393 (macstat & BWN_RX_MAC_KEYIDX) >> BWN_RX_MAC_KEYIDX_SHIFT);
9394
9395 /* XXX calculating RSSI & noise & antenna */
9396
9397 if (phystat0 & BWN_RX_PHYST0_OFDM)
9398 rate = bwn_plcp_get_ofdmrate(mac, plcp,
9399 phytype == BWN_PHYTYPE_A);
9400 else
9401 rate = bwn_plcp_get_cckrate(mac, plcp);
9402 if (rate == -1) {
9403 if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADPLCP))
9404 goto drop;
9405 }
9406 sc->sc_rx_rate = bwn_hwrate2ieeerate(rate);
9407
9408 /* RX radio tap */
9409 if (ieee80211_radiotap_active(ic))
9410 bwn_rx_radiotap(mac, m, rxhdr, plcp, rate, rssi, noise);
9411 m_adj(m, -IEEE80211_CRC_LEN);
9412
9413 rssi = rxhdr->phy.abg.rssi; /* XXX incorrect RSSI calculation? */
9414 noise = mac->mac_stats.link_noise;
9415
9416 BWN_UNLOCK(sc);
9417
9418 ni = ieee80211_find_rxnode(ic, wh);
9419 if (ni != NULL) {
9420 type = ieee80211_input(ni, m, rssi, noise);
9421 ieee80211_free_node(ni);
9422 } else
9423 type = ieee80211_input_all(ic, m, rssi, noise);
9424
9425 BWN_LOCK(sc);
9426 return;
9427drop:
9428 device_printf(sc->sc_dev, "%s: dropped\n", __func__);
9429}
9430
9431static void
9432bwn_dma_handle_txeof(struct bwn_mac *mac,
9433 const struct bwn_txstatus *status)
9434{
9435 struct bwn_dma *dma = &mac->mac_method.dma;
9436 struct bwn_dma_ring *dr;
9437 struct bwn_dmadesc_generic *desc;
9438 struct bwn_dmadesc_meta *meta;
9439 struct bwn_softc *sc = mac->mac_sc;
9440 struct ieee80211_node *ni;
9441 struct ifnet *ifp = sc->sc_ifp;
9442 struct mbuf *m;
9443 int slot;
9444
9445 BWN_ASSERT_LOCKED(sc);
9446
9447 dr = bwn_dma_parse_cookie(mac, status, status->cookie, &slot);
9448 if (dr == NULL) {
9449 device_printf(sc->sc_dev, "failed to parse cookie\n");
9450 return;
9451 }
9452 KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
9453
9454 while (1) {
9455 KASSERT(slot >= 0 && slot < dr->dr_numslots,
9456 ("%s:%d: fail", __func__, __LINE__));
9457 dr->getdesc(dr, slot, &desc, &meta);
9458
9459 if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
9460 bus_dmamap_unload(dr->dr_txring_dtag, meta->mt_dmap);
9461 else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
9462 bus_dmamap_unload(dma->txbuf_dtag, meta->mt_dmap);
9463
9464 if (meta->mt_islast) {
9465 KASSERT(meta->mt_m != NULL,
9466 ("%s:%d: fail", __func__, __LINE__));
9467
9468 ni = meta->mt_ni;
9469 m = meta->mt_m;
9470 if (ni != NULL) {
9471 /*
9472 * Do any tx complete callback. Note this must
9473 * be done before releasing the node reference.
9474 */
9475 if (m->m_flags & M_TXCB)
9476 ieee80211_process_callback(ni, m, 0);
9477 ieee80211_free_node(ni);
9478 meta->mt_ni = NULL;
9479 }
9480 m_freem(m);
9481 meta->mt_m = NULL;
9482 } else {
9483 KASSERT(meta->mt_m == NULL,
9484 ("%s:%d: fail", __func__, __LINE__));
9485 }
9486
9487 dr->dr_usedslot--;
9488 if (meta->mt_islast) {
9489 ifp->if_opackets++;
9490 break;
9491 }
9492 slot = bwn_dma_nextslot(dr, slot);
9493 }
9494 sc->sc_watchdog_timer = 0;
9495 if (dr->dr_stop) {
9496 KASSERT(bwn_dma_freeslot(dr) >= BWN_TX_SLOTS_PER_FRAME,
9497 ("%s:%d: fail", __func__, __LINE__));
9498 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
9499 dr->dr_stop = 0;
9500 }
9501}
9502
9503static void
9504bwn_pio_handle_txeof(struct bwn_mac *mac,
9505 const struct bwn_txstatus *status)
9506{
9507 struct bwn_pio_txqueue *tq;
9508 struct bwn_pio_txpkt *tp = NULL;
9509 struct bwn_softc *sc = mac->mac_sc;
9510 struct ifnet *ifp = sc->sc_ifp;
9511
9512 BWN_ASSERT_LOCKED(sc);
9513
9514 tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9515 if (tq == NULL)
9516 return;
9517
9518 tq->tq_used -= roundup(tp->tp_m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
9519 tq->tq_free++;
9520
9521 if (tp->tp_ni != NULL) {
9522 /*
9523 * Do any tx complete callback. Note this must
9524 * be done before releasing the node reference.
9525 */
9526 if (tp->tp_m->m_flags & M_TXCB)
9527 ieee80211_process_callback(tp->tp_ni, tp->tp_m, 0);
9528 ieee80211_free_node(tp->tp_ni);
9529 tp->tp_ni = NULL;
9530 }
9531 m_freem(tp->tp_m);
9532 tp->tp_m = NULL;
9533 TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
9534
9535 ifp->if_opackets++;
9536
9537 sc->sc_watchdog_timer = 0;
9538 if (tq->tq_stop) {
9539 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
9540 tq->tq_stop = 0;
9541 }
9542}
9543
9544static void
9545bwn_phy_txpower_check(struct bwn_mac *mac, uint32_t flags)
9546{
9547 struct bwn_softc *sc = mac->mac_sc;
9548 struct bwn_phy *phy = &mac->mac_phy;
9549 struct ifnet *ifp = sc->sc_ifp;
9550 struct ieee80211com *ic = ifp->if_l2com;
9551 unsigned long now;
9552 int result;
9553
9554 BWN_GETTIME(now);
9555
9556 if (!(flags & BWN_TXPWR_IGNORE_TIME) && time_before(now, phy->nexttime))
9557 return;
9558 phy->nexttime = now + 2 * 1000;
9559
9560 if (siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM &&
9561 siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306)
9562 return;
9563
9564 if (phy->recalc_txpwr != NULL) {
9565 result = phy->recalc_txpwr(mac,
9566 (flags & BWN_TXPWR_IGNORE_TSSI) ? 1 : 0);
9567 if (result == BWN_TXPWR_RES_DONE)
9568 return;
9569 KASSERT(result == BWN_TXPWR_RES_NEED_ADJUST,
9570 ("%s: fail", __func__));
9571 KASSERT(phy->set_txpwr != NULL, ("%s: fail", __func__));
9572
9573 ieee80211_runtask(ic, &mac->mac_txpower);
9574 }
9575}
9576
9577static uint16_t
9578bwn_pio_rx_read_2(struct bwn_pio_rxqueue *prq, uint16_t offset)
9579{
9580
9581 return (BWN_READ_2(prq->prq_mac, prq->prq_base + offset));
9582}
9583
9584static uint32_t
9585bwn_pio_rx_read_4(struct bwn_pio_rxqueue *prq, uint16_t offset)
9586{
9587
9588 return (BWN_READ_4(prq->prq_mac, prq->prq_base + offset));
9589}
9590
9591static void
9592bwn_pio_rx_write_2(struct bwn_pio_rxqueue *prq, uint16_t offset, uint16_t value)
9593{
9594
9595 BWN_WRITE_2(prq->prq_mac, prq->prq_base + offset, value);
9596}
9597
9598static void
9599bwn_pio_rx_write_4(struct bwn_pio_rxqueue *prq, uint16_t offset, uint32_t value)
9600{
9601
9602 BWN_WRITE_4(prq->prq_mac, prq->prq_base + offset, value);
9603}
9604
9605static int
9606bwn_ieeerate2hwrate(struct bwn_softc *sc, int rate)
9607{
9608
9609 switch (rate) {
9610 /* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
9611 case 12:
9612 return (BWN_OFDM_RATE_6MB);
9613 case 18:
9614 return (BWN_OFDM_RATE_9MB);
9615 case 24:
9616 return (BWN_OFDM_RATE_12MB);
9617 case 36:
9618 return (BWN_OFDM_RATE_18MB);
9619 case 48:
9620 return (BWN_OFDM_RATE_24MB);
9621 case 72:
9622 return (BWN_OFDM_RATE_36MB);
9623 case 96:
9624 return (BWN_OFDM_RATE_48MB);
9625 case 108:
9626 return (BWN_OFDM_RATE_54MB);
9627 /* CCK rates (NB: not IEEE std, device-specific) */
9628 case 2:
9629 return (BWN_CCK_RATE_1MB);
9630 case 4:
9631 return (BWN_CCK_RATE_2MB);
9632 case 11:
9633 return (BWN_CCK_RATE_5MB);
9634 case 22:
9635 return (BWN_CCK_RATE_11MB);
9636 }
9637
9638 device_printf(sc->sc_dev, "unsupported rate %d\n", rate);
9639 return (BWN_CCK_RATE_1MB);
9640}
9641
9642static int
9643bwn_set_txhdr(struct bwn_mac *mac, struct ieee80211_node *ni,
9644 struct mbuf *m, struct bwn_txhdr *txhdr, uint16_t cookie)
9645{
9646 const struct bwn_phy *phy = &mac->mac_phy;
9647 struct bwn_softc *sc = mac->mac_sc;
9648 struct ieee80211_frame *wh;
9649 struct ieee80211_frame *protwh;
9650 struct ieee80211_frame_cts *cts;
9651 struct ieee80211_frame_rts *rts;
9652 const struct ieee80211_txparam *tp;
9653 struct ieee80211vap *vap = ni->ni_vap;
9654 struct ifnet *ifp = sc->sc_ifp;
9655 struct ieee80211com *ic = ifp->if_l2com;
9656 struct mbuf *mprot;
9657 unsigned int len;
9658 uint32_t macctl = 0;
9659 int protdur, rts_rate, rts_rate_fb, ismcast, isshort, rix, type;
9660 uint16_t phyctl = 0;
9661 uint8_t rate, rate_fb;
9662
9663 wh = mtod(m, struct ieee80211_frame *);
9664 memset(txhdr, 0, sizeof(*txhdr));
9665
9666 type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
9667 ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
9668 isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0;
9669
9670 /*
9671 * Find TX rate
9672 */
9673 tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)];
9674 if (type != IEEE80211_FC0_TYPE_DATA || (m->m_flags & M_EAPOL))
9675 rate = rate_fb = tp->mgmtrate;
9676 else if (ismcast)
9677 rate = rate_fb = tp->mcastrate;
9678 else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
9679 rate = rate_fb = tp->ucastrate;
9680 else {
9681 rix = ieee80211_amrr_choose(ni, &BWN_NODE(ni)->bn_amn);
9682 rate = ni->ni_txrate;
9683
9684 if (rix > 0)
9685 rate_fb = ni->ni_rates.rs_rates[rix - 1] &
9686 IEEE80211_RATE_VAL;
9687 else
9688 rate_fb = rate;
9689 }
9690
9691 sc->sc_tx_rate = rate;
9692
9693 rate = bwn_ieeerate2hwrate(sc, rate);
9694 rate_fb = bwn_ieeerate2hwrate(sc, rate_fb);
9695
9696 txhdr->phyrate = (BWN_ISOFDMRATE(rate)) ? bwn_plcp_getofdm(rate) :
9697 bwn_plcp_getcck(rate);
9698 bcopy(wh->i_fc, txhdr->macfc, sizeof(txhdr->macfc));
9699 bcopy(wh->i_addr1, txhdr->addr1, IEEE80211_ADDR_LEN);
9700
9701 if ((rate_fb == rate) ||
9702 (*(u_int16_t *)wh->i_dur & htole16(0x8000)) ||
9703 (*(u_int16_t *)wh->i_dur == htole16(0)))
9704 txhdr->dur_fb = *(u_int16_t *)wh->i_dur;
9705 else
9706 txhdr->dur_fb = ieee80211_compute_duration(ic->ic_rt,
9707 m->m_pkthdr.len, rate, isshort);
9708
9709 /* XXX TX encryption */
9710 bwn_plcp_genhdr(BWN_ISOLDFMT(mac) ?
9711 (struct bwn_plcp4 *)(&txhdr->body.old.plcp) :
9712 (struct bwn_plcp4 *)(&txhdr->body.new.plcp),
9713 m->m_pkthdr.len + IEEE80211_CRC_LEN, rate);
9714 bwn_plcp_genhdr((struct bwn_plcp4 *)(&txhdr->plcp_fb),
9715 m->m_pkthdr.len + IEEE80211_CRC_LEN, rate_fb);
9716
9717 txhdr->eftypes |= (BWN_ISOFDMRATE(rate_fb)) ? BWN_TX_EFT_FB_OFDM :
9718 BWN_TX_EFT_FB_CCK;
9719 txhdr->chan = phy->chan;
9720 phyctl |= (BWN_ISOFDMRATE(rate)) ? BWN_TX_PHY_ENC_OFDM :
9721 BWN_TX_PHY_ENC_CCK;
9722 if (isshort && (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9723 rate == BWN_CCK_RATE_11MB))
9724 phyctl |= BWN_TX_PHY_SHORTPRMBL;
9725
9726 /* XXX TX antenna selection */
9727
9728 switch (bwn_antenna_sanitize(mac, 0)) {
9729 case 0:
9730 phyctl |= BWN_TX_PHY_ANT01AUTO;
9731 break;
9732 case 1:
9733 phyctl |= BWN_TX_PHY_ANT0;
9734 break;
9735 case 2:
9736 phyctl |= BWN_TX_PHY_ANT1;
9737 break;
9738 case 3:
9739 phyctl |= BWN_TX_PHY_ANT2;
9740 break;
9741 case 4:
9742 phyctl |= BWN_TX_PHY_ANT3;
9743 break;
9744 default:
9745 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9746 }
9747
9748 if (!ismcast)
9749 macctl |= BWN_TX_MAC_ACK;
9750
9751 macctl |= (BWN_TX_MAC_HWSEQ | BWN_TX_MAC_START_MSDU);
9752 if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
9753 m->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold)
9754 macctl |= BWN_TX_MAC_LONGFRAME;
9755
9756 if (ic->ic_flags & IEEE80211_F_USEPROT) {
9757 /* XXX RTS rate is always 1MB??? */
9758 rts_rate = BWN_CCK_RATE_1MB;
9759 rts_rate_fb = bwn_get_fbrate(rts_rate);
9760
9761 protdur = ieee80211_compute_duration(ic->ic_rt,
9762 m->m_pkthdr.len, rate, isshort) +
9763 + ieee80211_ack_duration(ic->ic_rt, rate, isshort);
9764
9765 if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) {
9766 cts = (struct ieee80211_frame_cts *)(BWN_ISOLDFMT(mac) ?
9767 (txhdr->body.old.rts_frame) :
9768 (txhdr->body.new.rts_frame));
9769 mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr,
9770 protdur);
9771 KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9772 bcopy(mtod(mprot, uint8_t *), (uint8_t *)cts,
9773 mprot->m_pkthdr.len);
9774 m_freem(mprot);
9775 macctl |= BWN_TX_MAC_SEND_CTSTOSELF;
9776 len = sizeof(struct ieee80211_frame_cts);
9777 } else {
9778 rts = (struct ieee80211_frame_rts *)(BWN_ISOLDFMT(mac) ?
9779 (txhdr->body.old.rts_frame) :
9780 (txhdr->body.new.rts_frame));
9781 protdur += ieee80211_ack_duration(ic->ic_rt, rate,
9782 isshort);
9783 mprot = ieee80211_alloc_rts(ic, wh->i_addr1,
9784 wh->i_addr2, protdur);
9785 KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9786 bcopy(mtod(mprot, uint8_t *), (uint8_t *)rts,
9787 mprot->m_pkthdr.len);
9788 m_freem(mprot);
9789 macctl |= BWN_TX_MAC_SEND_RTSCTS;
9790 len = sizeof(struct ieee80211_frame_rts);
9791 }
9792 len += IEEE80211_CRC_LEN;
9793 bwn_plcp_genhdr((struct bwn_plcp4 *)((BWN_ISOLDFMT(mac)) ?
9794 &txhdr->body.old.rts_plcp :
9795 &txhdr->body.new.rts_plcp), len, rts_rate);
9796 bwn_plcp_genhdr((struct bwn_plcp4 *)&txhdr->rts_plcp_fb, len,
9797 rts_rate_fb);
9798
9799 protwh = (struct ieee80211_frame *)(BWN_ISOLDFMT(mac) ?
9800 (&txhdr->body.old.rts_frame) :
9801 (&txhdr->body.new.rts_frame));
9802 txhdr->rts_dur_fb = *(u_int16_t *)protwh->i_dur;
9803
9804 if (BWN_ISOFDMRATE(rts_rate)) {
9805 txhdr->eftypes |= BWN_TX_EFT_RTS_OFDM;
9806 txhdr->phyrate_rts = bwn_plcp_getofdm(rts_rate);
9807 } else {
9808 txhdr->eftypes |= BWN_TX_EFT_RTS_CCK;
9809 txhdr->phyrate_rts = bwn_plcp_getcck(rts_rate);
9810 }
9811 txhdr->eftypes |= (BWN_ISOFDMRATE(rts_rate_fb)) ?
9812 BWN_TX_EFT_RTS_FBOFDM : BWN_TX_EFT_RTS_FBCCK;
9813 }
9814
9815 if (BWN_ISOLDFMT(mac))
9816 txhdr->body.old.cookie = htole16(cookie);
9817 else
9818 txhdr->body.new.cookie = htole16(cookie);
9819
9820 txhdr->macctl = htole32(macctl);
9821 txhdr->phyctl = htole16(phyctl);
9822
9823 /*
9824 * TX radio tap
9825 */
9826 if (ieee80211_radiotap_active_vap(vap)) {
9827 sc->sc_tx_th.wt_flags = 0;
9828 if (wh->i_fc[1] & IEEE80211_FC1_WEP)
9829 sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP;
9830 if (isshort &&
9831 (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9832 rate == BWN_CCK_RATE_11MB))
9833 sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
9834 sc->sc_tx_th.wt_rate = rate;
9835
9836 ieee80211_radiotap_tx(vap, m);
9837 }
9838
9839 return (0);
9840}
9841
9842static void
9843bwn_plcp_genhdr(struct bwn_plcp4 *plcp, const uint16_t octets,
9844 const uint8_t rate)
9845{
9846 uint32_t d, plen;
9847 uint8_t *raw = plcp->o.raw;
9848
9849 if (BWN_ISOFDMRATE(rate)) {
9850 d = bwn_plcp_getofdm(rate);
9851 KASSERT(!(octets & 0xf000),
9852 ("%s:%d: fail", __func__, __LINE__));
9853 d |= (octets << 5);
9854 plcp->o.data = htole32(d);
9855 } else {
9856 plen = octets * 16 / rate;
9857 if ((octets * 16 % rate) > 0) {
9858 plen++;
9859 if ((rate == BWN_CCK_RATE_11MB)
9860 && ((octets * 8 % 11) < 4)) {
9861 raw[1] = 0x84;
9862 } else
9863 raw[1] = 0x04;
9864 } else
9865 raw[1] = 0x04;
9866 plcp->o.data |= htole32(plen << 16);
9867 raw[0] = bwn_plcp_getcck(rate);
9868 }
9869}
9870
9871static uint8_t
9872bwn_antenna_sanitize(struct bwn_mac *mac, uint8_t n)
9873{
9874 struct bwn_softc *sc = mac->mac_sc;
9875 uint8_t mask;
9876
9877 if (n == 0)
9878 return (0);
9879 if (mac->mac_phy.gmode)
9880 mask = siba_sprom_get_ant_bg(sc->sc_dev);
9881 else
9882 mask = siba_sprom_get_ant_a(sc->sc_dev);
9883 if (!(mask & (1 << (n - 1))))
9884 return (0);
9885 return (n);
9886}
9887
9888static uint8_t
9889bwn_get_fbrate(uint8_t bitrate)
9890{
9891 switch (bitrate) {
9892 case BWN_CCK_RATE_1MB:
9893 return (BWN_CCK_RATE_1MB);
9894 case BWN_CCK_RATE_2MB:
9895 return (BWN_CCK_RATE_1MB);
9896 case BWN_CCK_RATE_5MB:
9897 return (BWN_CCK_RATE_2MB);
9898 case BWN_CCK_RATE_11MB:
9899 return (BWN_CCK_RATE_5MB);
9900 case BWN_OFDM_RATE_6MB:
9901 return (BWN_CCK_RATE_5MB);
9902 case BWN_OFDM_RATE_9MB:
9903 return (BWN_OFDM_RATE_6MB);
9904 case BWN_OFDM_RATE_12MB:
9905 return (BWN_OFDM_RATE_9MB);
9906 case BWN_OFDM_RATE_18MB:
9907 return (BWN_OFDM_RATE_12MB);
9908 case BWN_OFDM_RATE_24MB:
9909 return (BWN_OFDM_RATE_18MB);
9910 case BWN_OFDM_RATE_36MB:
9911 return (BWN_OFDM_RATE_24MB);
9912 case BWN_OFDM_RATE_48MB:
9913 return (BWN_OFDM_RATE_36MB);
9914 case BWN_OFDM_RATE_54MB:
9915 return (BWN_OFDM_RATE_48MB);
9916 }
9917 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9918 return (0);
9919}
9920
9921static uint32_t
9922bwn_pio_write_multi_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9923 uint32_t ctl, const void *_data, int len)
9924{
9925 struct bwn_softc *sc = mac->mac_sc;
9926 uint32_t value = 0;
9927 const uint8_t *data = _data;
9928
9929 ctl |= BWN_PIO8_TXCTL_0_7 | BWN_PIO8_TXCTL_8_15 |
9930 BWN_PIO8_TXCTL_16_23 | BWN_PIO8_TXCTL_24_31;
9931 bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9932
9933 siba_write_multi_4(sc->sc_dev, data, (len & ~3),
9934 tq->tq_base + BWN_PIO8_TXDATA);
9935 if (len & 3) {
9936 ctl &= ~(BWN_PIO8_TXCTL_8_15 | BWN_PIO8_TXCTL_16_23 |
9937 BWN_PIO8_TXCTL_24_31);
9938 data = &(data[len - 1]);
9939 switch (len & 3) {
9940 case 3:
9941 ctl |= BWN_PIO8_TXCTL_16_23;
9942 value |= (uint32_t)(*data) << 16;
9943 data--;
9944 case 2:
9945 ctl |= BWN_PIO8_TXCTL_8_15;
9946 value |= (uint32_t)(*data) << 8;
9947 data--;
9948 case 1:
9949 value |= (uint32_t)(*data);
9950 }
9951 bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9952 bwn_pio_write_4(mac, tq, BWN_PIO8_TXDATA, value);
9953 }
9954
9955 return (ctl);
9956}
9957
9958static void
9959bwn_pio_write_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9960 uint16_t offset, uint32_t value)
9961{
9962
9963 BWN_WRITE_4(mac, tq->tq_base + offset, value);
9964}
9965
9966static uint16_t
9967bwn_pio_write_multi_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9968 uint16_t ctl, const void *_data, int len)
9969{
9970 struct bwn_softc *sc = mac->mac_sc;
9971 const uint8_t *data = _data;
9972
9973 ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
9974 BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9975
9976 siba_write_multi_2(sc->sc_dev, data, (len & ~1),
9977 tq->tq_base + BWN_PIO_TXDATA);
9978 if (len & 1) {
9979 ctl &= ~BWN_PIO_TXCTL_WRITEHI;
9980 BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9981 BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data[len - 1]);
9982 }
9983
9984 return (ctl);
9985}
9986
9987static uint16_t
9988bwn_pio_write_mbuf_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9989 uint16_t ctl, struct mbuf *m0)
9990{
9991 int i, j = 0;
9992 uint16_t data = 0;
9993 const uint8_t *buf;
9994 struct mbuf *m = m0;
9995
9996 ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
9997 BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9998
9999 for (; m != NULL; m = m->m_next) {
10000 buf = mtod(m, const uint8_t *);
10001 for (i = 0; i < m->m_len; i++) {
10002 if (!((j++) % 2))
10003 data |= buf[i];
10004 else {
10005 data |= (buf[i] << 8);
10006 BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
10007 data = 0;
10008 }
10009 }
10010 }
10011 if (m0->m_pkthdr.len % 2) {
10012 ctl &= ~BWN_PIO_TXCTL_WRITEHI;
10013 BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
10014 BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
10015 }
10016
10017 return (ctl);
10018}
10019
10020static void
10021bwn_set_slot_time(struct bwn_mac *mac, uint16_t time)
10022{
10023
10024 if (mac->mac_phy.type != BWN_PHYTYPE_G)
10025 return;
10026 BWN_WRITE_2(mac, 0x684, 510 + time);
10027 bwn_shm_write_2(mac, BWN_SHARED, 0x0010, time);
10028}
10029
10030static struct bwn_dma_ring *
10031bwn_dma_select(struct bwn_mac *mac, uint8_t prio)
10032{
10033
10034 if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
10035 return (mac->mac_method.dma.wme[WME_AC_BE]);
10036
10037 switch (prio) {
10038 case 3:
10039 return (mac->mac_method.dma.wme[WME_AC_VO]);
10040 case 2:
10041 return (mac->mac_method.dma.wme[WME_AC_VI]);
10042 case 0:
10043 return (mac->mac_method.dma.wme[WME_AC_BE]);
10044 case 1:
10045 return (mac->mac_method.dma.wme[WME_AC_BK]);
10046 }
10047 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
10048 return (NULL);
10049}
10050
10051static int
10052bwn_dma_getslot(struct bwn_dma_ring *dr)
10053{
10054 int slot;
10055
10056 BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
10057
10058 KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
10059 KASSERT(!(dr->dr_stop), ("%s:%d: fail", __func__, __LINE__));
10060 KASSERT(bwn_dma_freeslot(dr) != 0, ("%s:%d: fail", __func__, __LINE__));
10061
10062 slot = bwn_dma_nextslot(dr, dr->dr_curslot);
10063 KASSERT(!(slot & ~0x0fff), ("%s:%d: fail", __func__, __LINE__));
10064 dr->dr_curslot = slot;
10065 dr->dr_usedslot++;
10066
10067 return (slot);
10068}
10069
10070static int
10071bwn_phy_shm_tssi_read(struct bwn_mac *mac, uint16_t shm_offset)
10072{
10073 const uint8_t ofdm = (shm_offset != BWN_SHARED_TSSI_CCK);
10074 unsigned int a, b, c, d;
10075 unsigned int avg;
10076 uint32_t tmp;
10077
10078 tmp = bwn_shm_read_4(mac, BWN_SHARED, shm_offset);
10079 a = tmp & 0xff;
10080 b = (tmp >> 8) & 0xff;
10081 c = (tmp >> 16) & 0xff;
10082 d = (tmp >> 24) & 0xff;
10083 if (a == 0 || a == BWN_TSSI_MAX || b == 0 || b == BWN_TSSI_MAX ||
10084 c == 0 || c == BWN_TSSI_MAX || d == 0 || d == BWN_TSSI_MAX)
10085 return (ENOENT);
10086 bwn_shm_write_4(mac, BWN_SHARED, shm_offset,
10087 BWN_TSSI_MAX | (BWN_TSSI_MAX << 8) |
10088 (BWN_TSSI_MAX << 16) | (BWN_TSSI_MAX << 24));
10089
10090 if (ofdm) {
10091 a = (a + 32) & 0x3f;
10092 b = (b + 32) & 0x3f;
10093 c = (c + 32) & 0x3f;
10094 d = (d + 32) & 0x3f;
10095 }
10096
10097 avg = (a + b + c + d + 2) / 4;
10098 if (ofdm) {
10099 if (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO)
10100 & BWN_HF_4DB_CCK_POWERBOOST)
10101 avg = (avg >= 13) ? (avg - 13) : 0;
10102 }
10103 return (avg);
10104}
10105
10106static void
10107bwn_phy_g_setatt(struct bwn_mac *mac, int *bbattp, int *rfattp)
10108{
10109 struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
10110 int rfatt = *rfattp;
10111 int bbatt = *bbattp;
10112
10113 while (1) {
10114 if (rfatt > lo->rfatt.max && bbatt > lo->bbatt.max - 4)
10115 break;
10116 if (rfatt < lo->rfatt.min && bbatt < lo->bbatt.min + 4)
10117 break;
10118 if (bbatt > lo->bbatt.max && rfatt > lo->rfatt.max - 1)
10119 break;
10120 if (bbatt < lo->bbatt.min && rfatt < lo->rfatt.min + 1)
10121 break;
10122 if (bbatt > lo->bbatt.max) {
10123 bbatt -= 4;
10124 rfatt += 1;
10125 continue;
10126 }
10127 if (bbatt < lo->bbatt.min) {
10128 bbatt += 4;
10129 rfatt -= 1;
10130 continue;
10131 }
10132 if (rfatt > lo->rfatt.max) {
10133 rfatt -= 1;
10134 bbatt += 4;
10135 continue;
10136 }
10137 if (rfatt < lo->rfatt.min) {
10138 rfatt += 1;
10139 bbatt -= 4;
10140 continue;
10141 }
10142 break;
10143 }
10144
10145 *rfattp = MIN(MAX(rfatt, lo->rfatt.min), lo->rfatt.max);
10146 *bbattp = MIN(MAX(bbatt, lo->bbatt.min), lo->bbatt.max);
10147}
10148
10149static void
10150bwn_phy_lock(struct bwn_mac *mac)
10151{
10152 struct bwn_softc *sc = mac->mac_sc;
10153 struct ieee80211com *ic = sc->sc_ifp->if_l2com;
10154
10155 KASSERT(siba_get_revid(sc->sc_dev) >= 3,
10156 ("%s: unsupported rev %d", __func__, siba_get_revid(sc->sc_dev)));
10157
10158 if (ic->ic_opmode != IEEE80211_M_HOSTAP)
10159 bwn_psctl(mac, BWN_PS_AWAKE);
10160}
10161
10162static void
10163bwn_phy_unlock(struct bwn_mac *mac)
10164{
10165 struct bwn_softc *sc = mac->mac_sc;
10166 struct ieee80211com *ic = sc->sc_ifp->if_l2com;
10167
10168 KASSERT(siba_get_revid(sc->sc_dev) >= 3,
10169 ("%s: unsupported rev %d", __func__, siba_get_revid(sc->sc_dev)));
10170
10171 if (ic->ic_opmode != IEEE80211_M_HOSTAP)
10172 bwn_psctl(mac, 0);
10173}
10174
10175static void
10176bwn_rf_lock(struct bwn_mac *mac)
10177{
10178
10179 BWN_WRITE_4(mac, BWN_MACCTL,
10180 BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_RADIO_LOCK);
10181 BWN_READ_4(mac, BWN_MACCTL);
10182 DELAY(10);
10183}
10184
10185static void
10186bwn_rf_unlock(struct bwn_mac *mac)
10187{
10188
10189 BWN_READ_2(mac, BWN_PHYVER);
10190 BWN_WRITE_4(mac, BWN_MACCTL,
10191 BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_RADIO_LOCK);
10192}
10193
10194static struct bwn_pio_txqueue *
10195bwn_pio_parse_cookie(struct bwn_mac *mac, uint16_t cookie,
10196 struct bwn_pio_txpkt **pack)
10197{
10198 struct bwn_pio *pio = &mac->mac_method.pio;
10199 struct bwn_pio_txqueue *tq = NULL;
10200 unsigned int index;
10201
10202 switch (cookie & 0xf000) {
10203 case 0x1000:
10204 tq = &pio->wme[WME_AC_BK];
10205 break;
10206 case 0x2000:
10207 tq = &pio->wme[WME_AC_BE];
10208 break;
10209 case 0x3000:
10210 tq = &pio->wme[WME_AC_VI];
10211 break;
10212 case 0x4000:
10213 tq = &pio->wme[WME_AC_VO];
10214 break;
10215 case 0x5000:
10216 tq = &pio->mcast;
10217 break;
10218 }
10219 KASSERT(tq != NULL, ("%s:%d: fail", __func__, __LINE__));
10220 if (tq == NULL)
10221 return (NULL);
10222 index = (cookie & 0x0fff);
10223 KASSERT(index < N(tq->tq_pkts), ("%s:%d: fail", __func__, __LINE__));
10224 if (index >= N(tq->tq_pkts))
10225 return (NULL);
10226 *pack = &tq->tq_pkts[index];
10227 KASSERT(*pack != NULL, ("%s:%d: fail", __func__, __LINE__));
10228 return (tq);
10229}
10230
10231static void
10232bwn_txpwr(void *arg, int npending)
10233{
10234 struct bwn_mac *mac = arg;
10235 struct bwn_softc *sc = mac->mac_sc;
10236
10237 BWN_LOCK(sc);
10238 if (mac && mac->mac_status >= BWN_MAC_STATUS_STARTED &&
10239 mac->mac_phy.set_txpwr != NULL)
10240 mac->mac_phy.set_txpwr(mac);
10241 BWN_UNLOCK(sc);
10242}
10243
10244static void
10245bwn_task_15s(struct bwn_mac *mac)
10246{
10247 uint16_t reg;
10248
10249 if (mac->mac_fw.opensource) {
10250 reg = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG);
10251 if (reg) {
10252 bwn_restart(mac, "fw watchdog");
10253 return;
10254 }
10255 bwn_shm_write_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG, 1);
10256 }
10257 if (mac->mac_phy.task_15s)
10258 mac->mac_phy.task_15s(mac);
10259
10260 mac->mac_phy.txerrors = BWN_TXERROR_MAX;
10261}
10262
10263static void
10264bwn_task_30s(struct bwn_mac *mac)
10265{
10266
10267 if (mac->mac_phy.type != BWN_PHYTYPE_G || mac->mac_noise.noi_running)
10268 return;
10269 mac->mac_noise.noi_running = 1;
10270 mac->mac_noise.noi_nsamples = 0;
10271
10272 bwn_noise_gensample(mac);
10273}
10274
10275static void
10276bwn_task_60s(struct bwn_mac *mac)
10277{
10278
10279 if (mac->mac_phy.task_60s)
10280 mac->mac_phy.task_60s(mac);
10281 bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME);
10282}
10283
10284static void
10285bwn_tasks(void *arg)
10286{
10287 struct bwn_mac *mac = arg;
10288 struct bwn_softc *sc = mac->mac_sc;
10289
10290 BWN_ASSERT_LOCKED(sc);
10291 if (mac->mac_status != BWN_MAC_STATUS_STARTED)
10292 return;
10293
10294 if (mac->mac_task_state % 4 == 0)
10295 bwn_task_60s(mac);
10296 if (mac->mac_task_state % 2 == 0)
10297 bwn_task_30s(mac);
10298 bwn_task_15s(mac);
10299
10300 mac->mac_task_state++;
10301 callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
10302}
10303
10304static int
10305bwn_plcp_get_ofdmrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp, uint8_t a)
10306{
10307 struct bwn_softc *sc = mac->mac_sc;
10308
10309 KASSERT(a == 0, ("not support APHY\n"));
10310
10311 switch (plcp->o.raw[0] & 0xf) {
10312 case 0xb:
10313 return (BWN_OFDM_RATE_6MB);
10314 case 0xf:
10315 return (BWN_OFDM_RATE_9MB);
10316 case 0xa:
10317 return (BWN_OFDM_RATE_12MB);
10318 case 0xe:
10319 return (BWN_OFDM_RATE_18MB);
10320 case 0x9:
10321 return (BWN_OFDM_RATE_24MB);
10322 case 0xd:
10323 return (BWN_OFDM_RATE_36MB);
10324 case 0x8:
10325 return (BWN_OFDM_RATE_48MB);
10326 case 0xc:
10327 return (BWN_OFDM_RATE_54MB);
10328 }
10329 device_printf(sc->sc_dev, "incorrect OFDM rate %d\n",
10330 plcp->o.raw[0] & 0xf);
10331 return (-1);
10332}
10333
10334static int
10335bwn_plcp_get_cckrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp)
10336{
10337 struct bwn_softc *sc = mac->mac_sc;
10338
10339 switch (plcp->o.raw[0]) {
10340 case 0x0a:
10341 return (BWN_CCK_RATE_1MB);
10342 case 0x14:
10343 return (BWN_CCK_RATE_2MB);
10344 case 0x37:
10345 return (BWN_CCK_RATE_5MB);
10346 case 0x6e:
10347 return (BWN_CCK_RATE_11MB);
10348 }
10349 device_printf(sc->sc_dev, "incorrect CCK rate %d\n", plcp->o.raw[0]);
10350 return (-1);
10351}
10352
10353static void
10354bwn_rx_radiotap(struct bwn_mac *mac, struct mbuf *m,
10355 const struct bwn_rxhdr4 *rxhdr, struct bwn_plcp6 *plcp, int rate,
10356 int rssi, int noise)
10357{
10358 struct bwn_softc *sc = mac->mac_sc;
10359 const struct ieee80211_frame_min *wh;
10360 uint64_t tsf;
10361 uint16_t low_mactime_now;
10362
10363 if (htole16(rxhdr->phy_status0) & BWN_RX_PHYST0_SHORTPRMBL)
10364 sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
10365
10366 wh = mtod(m, const struct ieee80211_frame_min *);
10367 if (wh->i_fc[1] & IEEE80211_FC1_WEP)
10368 sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_WEP;
10369
10370 bwn_tsf_read(mac, &tsf);
10371 low_mactime_now = tsf;
10372 tsf = tsf & ~0xffffULL;
10373 tsf += le16toh(rxhdr->mac_time);
10374 if (low_mactime_now < le16toh(rxhdr->mac_time))
10375 tsf -= 0x10000;
10376
10377 sc->sc_rx_th.wr_tsf = tsf;
10378 sc->sc_rx_th.wr_rate = rate;
10379 sc->sc_rx_th.wr_antsignal = rssi;
10380 sc->sc_rx_th.wr_antnoise = noise;
10381}
10382
10383static void
10384bwn_tsf_read(struct bwn_mac *mac, uint64_t *tsf)
10385{
10386 uint32_t low, high;
10387
10388 KASSERT(siba_get_revid(mac->mac_sc->sc_dev) >= 3,
10389 ("%s:%d: fail", __func__, __LINE__));
10390
10391 low = BWN_READ_4(mac, BWN_REV3PLUS_TSF_LOW);
10392 high = BWN_READ_4(mac, BWN_REV3PLUS_TSF_HIGH);
10393 *tsf = high;
10394 *tsf <<= 32;
10395 *tsf |= low;
10396}
10397
10398static int
10399bwn_dma_attach(struct bwn_mac *mac)
10400{
10401 struct bwn_dma *dma = &mac->mac_method.dma;
10402 struct bwn_softc *sc = mac->mac_sc;
10403 bus_addr_t lowaddr = 0;
10404 int error;
10405
10406 if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
10407 return (0);
10408
10409 KASSERT(siba_get_revid(sc->sc_dev) >= 5, ("%s: fail", __func__));
10410
10411 mac->mac_flags |= BWN_MAC_FLAG_DMA;
10412
10413 dma->dmatype = bwn_dma_gettype(mac);
10414 if (dma->dmatype == BWN_DMA_30BIT)
10415 lowaddr = BWN_BUS_SPACE_MAXADDR_30BIT;
10416 else if (dma->dmatype == BWN_DMA_32BIT)
10417 lowaddr = BUS_SPACE_MAXADDR_32BIT;
10418 else
10419 lowaddr = BUS_SPACE_MAXADDR;
10420
10421 /*
10422 * Create top level DMA tag
10423 */
10424 error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), /* parent */
10425 BWN_ALIGN, 0, /* alignment, bounds */
10426 lowaddr, /* lowaddr */
10427 BUS_SPACE_MAXADDR, /* highaddr */
10428 NULL, NULL, /* filter, filterarg */
10429 MAXBSIZE, /* maxsize */
10430 BUS_SPACE_UNRESTRICTED, /* nsegments */
10431 BUS_SPACE_MAXSIZE, /* maxsegsize */
10432 0, /* flags */
10433 NULL, NULL, /* lockfunc, lockarg */
10434 &dma->parent_dtag);
10435 if (error) {
10436 device_printf(sc->sc_dev, "can't create parent DMA tag\n");
10437 return (error);
10438 }
10439
10440 /*
10441 * Create TX/RX mbuf DMA tag
10442 */
10443 error = bus_dma_tag_create(dma->parent_dtag,
10444 1,
10445 0,
10446 BUS_SPACE_MAXADDR,
10447 BUS_SPACE_MAXADDR,
10448 NULL, NULL,
10449 MCLBYTES,
10450 1,
10451 BUS_SPACE_MAXSIZE_32BIT,
10452 0,
10453 NULL, NULL,
10454 &dma->rxbuf_dtag);
10455 if (error) {
10456 device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10457 goto fail0;
10458 }
10459 error = bus_dma_tag_create(dma->parent_dtag,
10460 1,
10461 0,
10462 BUS_SPACE_MAXADDR,
10463 BUS_SPACE_MAXADDR,
10464 NULL, NULL,
10465 MCLBYTES,
10466 1,
10467 BUS_SPACE_MAXSIZE_32BIT,
10468 0,
10469 NULL, NULL,
10470 &dma->txbuf_dtag);
10471 if (error) {
10472 device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10473 goto fail1;
10474 }
10475
10476 dma->wme[WME_AC_BK] = bwn_dma_ringsetup(mac, 0, 1, dma->dmatype);
10477 if (!dma->wme[WME_AC_BK])
10478 goto fail2;
10479
10480 dma->wme[WME_AC_BE] = bwn_dma_ringsetup(mac, 1, 1, dma->dmatype);
10481 if (!dma->wme[WME_AC_BE])
10482 goto fail3;
10483
10484 dma->wme[WME_AC_VI] = bwn_dma_ringsetup(mac, 2, 1, dma->dmatype);
10485 if (!dma->wme[WME_AC_VI])
10486 goto fail4;
10487
10488 dma->wme[WME_AC_VO] = bwn_dma_ringsetup(mac, 3, 1, dma->dmatype);
10489 if (!dma->wme[WME_AC_VO])
10490 goto fail5;
10491
10492 dma->mcast = bwn_dma_ringsetup(mac, 4, 1, dma->dmatype);
10493 if (!dma->mcast)
10494 goto fail6;
10495 dma->rx = bwn_dma_ringsetup(mac, 0, 0, dma->dmatype);
10496 if (!dma->rx)
10497 goto fail7;
10498
10499 return (error);
10500
10501fail7: bwn_dma_ringfree(&dma->mcast);
10502fail6: bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
10503fail5: bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
10504fail4: bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
10505fail3: bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
10506fail2: bus_dma_tag_destroy(dma->txbuf_dtag);
10507fail1: bus_dma_tag_destroy(dma->rxbuf_dtag);
10508fail0: bus_dma_tag_destroy(dma->parent_dtag);
10509 return (error);
10510}
10511
10512static struct bwn_dma_ring *
10513bwn_dma_parse_cookie(struct bwn_mac *mac, const struct bwn_txstatus *status,
10514 uint16_t cookie, int *slot)
10515{
10516 struct bwn_dma *dma = &mac->mac_method.dma;
10517 struct bwn_dma_ring *dr;
10518 struct bwn_softc *sc = mac->mac_sc;
10519
10520 BWN_ASSERT_LOCKED(mac->mac_sc);
10521
10522 switch (cookie & 0xf000) {
10523 case 0x1000:
10524 dr = dma->wme[WME_AC_BK];
10525 break;
10526 case 0x2000:
10527 dr = dma->wme[WME_AC_BE];
10528 break;
10529 case 0x3000:
10530 dr = dma->wme[WME_AC_VI];
10531 break;
10532 case 0x4000:
10533 dr = dma->wme[WME_AC_VO];
10534 break;
10535 case 0x5000:
10536 dr = dma->mcast;
10537 break;
10538 default:
10539 dr = NULL;
10540 KASSERT(0 == 1,
10541 ("invalid cookie value %d", cookie & 0xf000));
10542 }
10543 *slot = (cookie & 0x0fff);
10544 if (*slot < 0 || *slot >= dr->dr_numslots) {
10545 /*
10546 * XXX FIXME: sometimes H/W returns TX DONE events duplicately
10547 * that it occurs events which have same H/W sequence numbers.
10548 * When it's occurred just prints a WARNING msgs and ignores.
10549 */
10550 KASSERT(status->seq == dma->lastseq,
10551 ("%s:%d: fail", __func__, __LINE__));
10552 device_printf(sc->sc_dev,
10553 "out of slot ranges (0 < %d < %d)\n", *slot,
10554 dr->dr_numslots);
10555 return (NULL);
10556 }
10557 dma->lastseq = status->seq;
10558 return (dr);
10559}
10560
10561static void
10562bwn_dma_stop(struct bwn_mac *mac)
10563{
10564 struct bwn_dma *dma;
10565
10566 if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
10567 return;
10568 dma = &mac->mac_method.dma;
10569
10570 bwn_dma_ringstop(&dma->rx);
10571 bwn_dma_ringstop(&dma->wme[WME_AC_BK]);
10572 bwn_dma_ringstop(&dma->wme[WME_AC_BE]);
10573 bwn_dma_ringstop(&dma->wme[WME_AC_VI]);
10574 bwn_dma_ringstop(&dma->wme[WME_AC_VO]);
10575 bwn_dma_ringstop(&dma->mcast);
10576}
10577
10578static void
10579bwn_dma_ringstop(struct bwn_dma_ring **dr)
10580{
10581
10582 if (dr == NULL)
10583 return;
10584
10585 bwn_dma_cleanup(*dr);
10586}
10587
10588static void
10589bwn_pio_stop(struct bwn_mac *mac)
10590{
10591 struct bwn_pio *pio;
10592
10593 if (mac->mac_flags & BWN_MAC_FLAG_DMA)
10594 return;
10595 pio = &mac->mac_method.pio;
10596
10597 bwn_destroy_queue_tx(&pio->mcast);
10598 bwn_destroy_queue_tx(&pio->wme[WME_AC_VO]);
10599 bwn_destroy_queue_tx(&pio->wme[WME_AC_VI]);
10600 bwn_destroy_queue_tx(&pio->wme[WME_AC_BE]);
10601 bwn_destroy_queue_tx(&pio->wme[WME_AC_BK]);
10602}
10603
10604static void
10605bwn_led_attach(struct bwn_mac *mac)
10606{
10607 struct bwn_softc *sc = mac->mac_sc;
10608 const uint8_t *led_act = NULL;
10609 uint16_t val[BWN_LED_MAX];
10610 int i;
10611
10612 sc->sc_led_idle = (2350 * hz) / 1000;
10613 sc->sc_led_blink = 1;
10614
10615 for (i = 0; i < N(bwn_vendor_led_act); ++i) {
10616 if (siba_get_pci_subvendor(sc->sc_dev) ==
10617 bwn_vendor_led_act[i].vid) {
10618 led_act = bwn_vendor_led_act[i].led_act;
10619 break;
10620 }
10621 }
10622 if (led_act == NULL)
10623 led_act = bwn_default_led_act;
10624
10625 val[0] = siba_sprom_get_gpio0(sc->sc_dev);
10626 val[1] = siba_sprom_get_gpio1(sc->sc_dev);
10627 val[2] = siba_sprom_get_gpio2(sc->sc_dev);
10628 val[3] = siba_sprom_get_gpio3(sc->sc_dev);
10629
10630 for (i = 0; i < BWN_LED_MAX; ++i) {
10631 struct bwn_led *led = &sc->sc_leds[i];
10632
10633 if (val[i] == 0xff) {
10634 led->led_act = led_act[i];
10635 } else {
10636 if (val[i] & BWN_LED_ACT_LOW)
10637 led->led_flags |= BWN_LED_F_ACTLOW;
10638 led->led_act = val[i] & BWN_LED_ACT_MASK;
10639 }
10640 led->led_mask = (1 << i);
10641
10642 if (led->led_act == BWN_LED_ACT_BLINK_SLOW ||
10643 led->led_act == BWN_LED_ACT_BLINK_POLL ||
10644 led->led_act == BWN_LED_ACT_BLINK) {
10645 led->led_flags |= BWN_LED_F_BLINK;
10646 if (led->led_act == BWN_LED_ACT_BLINK_POLL)
10647 led->led_flags |= BWN_LED_F_POLLABLE;
10648 else if (led->led_act == BWN_LED_ACT_BLINK_SLOW)
10649 led->led_flags |= BWN_LED_F_SLOW;
10650
10651 if (sc->sc_blink_led == NULL) {
10652 sc->sc_blink_led = led;
10653 if (led->led_flags & BWN_LED_F_SLOW)
10654 BWN_LED_SLOWDOWN(sc->sc_led_idle);
10655 }
10656 }
10657
10658 DPRINTF(sc, BWN_DEBUG_LED,
10659 "%dth led, act %d, lowact %d\n", i,
10660 led->led_act, led->led_flags & BWN_LED_F_ACTLOW);
10661 }
10662 callout_init_mtx(&sc->sc_led_blink_ch, &sc->sc_mtx, 0);
10663}
10664
10665static __inline uint16_t
10666bwn_led_onoff(const struct bwn_led *led, uint16_t val, int on)
10667{
10668
10669 if (led->led_flags & BWN_LED_F_ACTLOW)
10670 on = !on;
10671 if (on)
10672 val |= led->led_mask;
10673 else
10674 val &= ~led->led_mask;
10675 return val;
10676}
10677
10678static void
10679bwn_led_newstate(struct bwn_mac *mac, enum ieee80211_state nstate)
10680{
10681 struct bwn_softc *sc = mac->mac_sc;
10682 struct ifnet *ifp = sc->sc_ifp;
10683 struct ieee80211com *ic = ifp->if_l2com;
10684 uint16_t val;
10685 int i;
10686
10687 if (nstate == IEEE80211_S_INIT) {
10688 callout_stop(&sc->sc_led_blink_ch);
10689 sc->sc_led_blinking = 0;
10690 }
10691
10692 if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
10693 return;
10694
10695 val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10696 for (i = 0; i < BWN_LED_MAX; ++i) {
10697 struct bwn_led *led = &sc->sc_leds[i];
10698 int on;
10699
10700 if (led->led_act == BWN_LED_ACT_UNKN ||
10701 led->led_act == BWN_LED_ACT_NULL)
10702 continue;
10703
10704 if ((led->led_flags & BWN_LED_F_BLINK) &&
10705 nstate != IEEE80211_S_INIT)
10706 continue;
10707
10708 switch (led->led_act) {
10709 case BWN_LED_ACT_ON: /* Always on */
10710 on = 1;
10711 break;
10712 case BWN_LED_ACT_OFF: /* Always off */
10713 case BWN_LED_ACT_5GHZ: /* TODO: 11A */
10714 on = 0;
10715 break;
10716 default:
10717 on = 1;
10718 switch (nstate) {
10719 case IEEE80211_S_INIT:
10720 on = 0;
10721 break;
10722 case IEEE80211_S_RUN:
10723 if (led->led_act == BWN_LED_ACT_11G &&
10724 ic->ic_curmode != IEEE80211_MODE_11G)
10725 on = 0;
10726 break;
10727 default:
10728 if (led->led_act == BWN_LED_ACT_ASSOC)
10729 on = 0;
10730 break;
10731 }
10732 break;
10733 }
10734
10735 val = bwn_led_onoff(led, val, on);
10736 }
10737 BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10738}
10739
10740static void
10741bwn_led_event(struct bwn_mac *mac, int event)
10742{
10743 struct bwn_softc *sc = mac->mac_sc;
10744 struct bwn_led *led = sc->sc_blink_led;
10745 int rate;
10746
10747 if (event == BWN_LED_EVENT_POLL) {
10748 if ((led->led_flags & BWN_LED_F_POLLABLE) == 0)
10749 return;
10750 if (ticks - sc->sc_led_ticks < sc->sc_led_idle)
10751 return;
10752 }
10753
10754 sc->sc_led_ticks = ticks;
10755 if (sc->sc_led_blinking)
10756 return;
10757
10758 switch (event) {
10759 case BWN_LED_EVENT_RX:
10760 rate = sc->sc_rx_rate;
10761 break;
10762 case BWN_LED_EVENT_TX:
10763 rate = sc->sc_tx_rate;
10764 break;
10765 case BWN_LED_EVENT_POLL:
10766 rate = 0;
10767 break;
10768 default:
10769 panic("unknown LED event %d\n", event);
10770 break;
10771 }
10772 bwn_led_blink_start(mac, bwn_led_duration[rate].on_dur,
10773 bwn_led_duration[rate].off_dur);
10774}
10775
10776static void
10777bwn_led_blink_start(struct bwn_mac *mac, int on_dur, int off_dur)
10778{
10779 struct bwn_softc *sc = mac->mac_sc;
10780 struct bwn_led *led = sc->sc_blink_led;
10781 uint16_t val;
10782
10783 val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10784 val = bwn_led_onoff(led, val, 1);
10785 BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10786
10787 if (led->led_flags & BWN_LED_F_SLOW) {
10788 BWN_LED_SLOWDOWN(on_dur);
10789 BWN_LED_SLOWDOWN(off_dur);
10790 }
10791
10792 sc->sc_led_blinking = 1;
10793 sc->sc_led_blink_offdur = off_dur;
10794
10795 callout_reset(&sc->sc_led_blink_ch, on_dur, bwn_led_blink_next, mac);
10796}
10797
10798static void
10799bwn_led_blink_next(void *arg)
10800{
10801 struct bwn_mac *mac = arg;
10802 struct bwn_softc *sc = mac->mac_sc;
10803 uint16_t val;
10804
10805 val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10806 val = bwn_led_onoff(sc->sc_blink_led, val, 0);
10807 BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10808
10809 callout_reset(&sc->sc_led_blink_ch, sc->sc_led_blink_offdur,
10810 bwn_led_blink_end, mac);
10811}
10812
10813static void
10814bwn_led_blink_end(void *arg)
10815{
10816 struct bwn_mac *mac = arg;
10817 struct bwn_softc *sc = mac->mac_sc;
10818
10819 sc->sc_led_blinking = 0;
10820}
10821
10822static int
10823bwn_suspend(device_t dev)
10824{
10825 struct bwn_softc *sc = device_get_softc(dev);
10826
10827 bwn_stop(sc, 1);
10828 return (0);
10829}
10830
10831static int
10832bwn_resume(device_t dev)
10833{
10834 struct bwn_softc *sc = device_get_softc(dev);
10835 struct ifnet *ifp = sc->sc_ifp;
10836
10837 if (ifp->if_flags & IFF_UP)
10838 bwn_init(sc);
10839 return (0);
10840}
10841
10842static void
10843bwn_rfswitch(void *arg)
10844{
10845 struct bwn_softc *sc = arg;
10846 struct bwn_mac *mac = sc->sc_curmac;
10847 int cur = 0, prev = 0;
10848
10849 KASSERT(mac->mac_status >= BWN_MAC_STATUS_STARTED,
10850 ("%s: invalid MAC status %d", __func__, mac->mac_status));
10851
10852 if (mac->mac_phy.rf_rev >= 3 || mac->mac_phy.type == BWN_PHYTYPE_LP) {
10853 if (!(BWN_READ_4(mac, BWN_RF_HWENABLED_HI)
10854 & BWN_RF_HWENABLED_HI_MASK))
10855 cur = 1;
10856 } else {
10857 if (BWN_READ_2(mac, BWN_RF_HWENABLED_LO)
10858 & BWN_RF_HWENABLED_LO_MASK)
10859 cur = 1;
10860 }
10861
10862 if (mac->mac_flags & BWN_MAC_FLAG_RADIO_ON)
10863 prev = 1;
10864
10865 if (cur != prev) {
10866 if (cur)
10867 mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
10868 else
10869 mac->mac_flags &= ~BWN_MAC_FLAG_RADIO_ON;
10870
10871 device_printf(sc->sc_dev,
10872 "status of RF switch is changed to %s\n",
10873 cur ? "ON" : "OFF");
10874 if (cur != mac->mac_phy.rf_on) {
10875 if (cur)
10876 bwn_rf_turnon(mac);
10877 else
10878 bwn_rf_turnoff(mac);
10879 }
10880 }
10881
10882 callout_schedule(&sc->sc_rfswitch_ch, hz);
10883}
10884
10885static void
10886bwn_phy_lp_init_pre(struct bwn_mac *mac)
10887{
10888 struct bwn_phy *phy = &mac->mac_phy;
10889 struct bwn_phy_lp *plp = &phy->phy_lp;
10890
10891 plp->plp_antenna = BWN_ANT_DEFAULT;
10892}
10893
10894static int
10895bwn_phy_lp_init(struct bwn_mac *mac)
10896{
10897 static const struct bwn_stxtable tables[] = {
10898 { 2, 6, 0x3d, 3, 0x01 }, { 1, 12, 0x4c, 1, 0x01 },
10899 { 1, 8, 0x50, 0, 0x7f }, { 0, 8, 0x44, 0, 0xff },
10900 { 1, 0, 0x4a, 0, 0xff }, { 0, 4, 0x4d, 0, 0xff },
10901 { 1, 4, 0x4e, 0, 0xff }, { 0, 12, 0x4f, 0, 0x0f },
10902 { 1, 0, 0x4f, 4, 0x0f }, { 3, 0, 0x49, 0, 0x0f },
10903 { 4, 3, 0x46, 4, 0x07 }, { 3, 15, 0x46, 0, 0x01 },
10904 { 4, 0, 0x46, 1, 0x07 }, { 3, 8, 0x48, 4, 0x07 },
10905 { 3, 11, 0x48, 0, 0x0f }, { 3, 4, 0x49, 4, 0x0f },
10906 { 2, 15, 0x45, 0, 0x01 }, { 5, 13, 0x52, 4, 0x07 },
10907 { 6, 0, 0x52, 7, 0x01 }, { 5, 3, 0x41, 5, 0x07 },
10908 { 5, 6, 0x41, 0, 0x0f }, { 5, 10, 0x42, 5, 0x07 },
10909 { 4, 15, 0x42, 0, 0x01 }, { 5, 0, 0x42, 1, 0x07 },
10910 { 4, 11, 0x43, 4, 0x0f }, { 4, 7, 0x43, 0, 0x0f },
10911 { 4, 6, 0x45, 1, 0x01 }, { 2, 7, 0x40, 4, 0x0f },
10912 { 2, 11, 0x40, 0, 0x0f }
10913 };
10914 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
10915 struct bwn_softc *sc = mac->mac_sc;
10916 const struct bwn_stxtable *st;
10917 struct ifnet *ifp = sc->sc_ifp;
10918 struct ieee80211com *ic = ifp->if_l2com;
10919 int i, error;
10920 uint16_t tmp;
10921
10922 bwn_phy_lp_readsprom(mac); /* XXX bad place */
10923 bwn_phy_lp_bbinit(mac);
10924
10925 /* initialize RF */
10926 BWN_PHY_SET(mac, BWN_PHY_4WIRECTL, 0x2);
10927 DELAY(1);
10928 BWN_PHY_MASK(mac, BWN_PHY_4WIRECTL, 0xfffd);
10929 DELAY(1);
10930
10931 if (mac->mac_phy.rf_ver == 0x2062)
10932 bwn_phy_lp_b2062_init(mac);
10933 else {
10934 bwn_phy_lp_b2063_init(mac);
10935
10936 /* synchronize stx table. */
10937 for (i = 0; i < N(tables); i++) {
10938 st = &tables[i];
10939 tmp = BWN_RF_READ(mac, st->st_rfaddr);
10940 tmp >>= st->st_rfshift;
10941 tmp <<= st->st_physhift;
10942 BWN_PHY_SETMASK(mac,
10943 BWN_PHY_OFDM(0xf2 + st->st_phyoffset),
10944 ~(st->st_mask << st->st_physhift), tmp);
10945 }
10946
10947 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf0), 0x5f80);
10948 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf1), 0);
10949 }
10950
10951 /* calibrate RC */
10952 if (mac->mac_phy.rev >= 2)
10953 bwn_phy_lp_rxcal_r2(mac);
10954 else if (!plp->plp_rccap) {
10955 if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
10956 bwn_phy_lp_rccal_r12(mac);
10957 } else
10958 bwn_phy_lp_set_rccap(mac);
10959
10960 error = bwn_phy_lp_switch_channel(mac, 7);
10961 if (error)
10962 device_printf(sc->sc_dev,
10963 "failed to change channel 7 (%d)\n", error);
10964 bwn_phy_lp_txpctl_init(mac);
10965 bwn_phy_lp_calib(mac);
10966 return (0);
10967}
10968
10969static uint16_t
10970bwn_phy_lp_read(struct bwn_mac *mac, uint16_t reg)
10971{
10972
10973 BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10974 return (BWN_READ_2(mac, BWN_PHYDATA));
10975}
10976
10977static void
10978bwn_phy_lp_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
10979{
10980
10981 BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10982 BWN_WRITE_2(mac, BWN_PHYDATA, value);
10983}
10984
10985static void
10986bwn_phy_lp_maskset(struct bwn_mac *mac, uint16_t reg, uint16_t mask,
10987 uint16_t set)
10988{
10989
10990 BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10991 BWN_WRITE_2(mac, BWN_PHYDATA,
10992 (BWN_READ_2(mac, BWN_PHYDATA) & mask) | set);
10993}
10994
10995static uint16_t
10996bwn_phy_lp_rf_read(struct bwn_mac *mac, uint16_t reg)
10997{
10998
10999 KASSERT(reg != 1, ("unaccessible register %d", reg));
11000 if (mac->mac_phy.rev < 2 && reg != 0x4001)
11001 reg |= 0x100;
11002 if (mac->mac_phy.rev >= 2)
11003 reg |= 0x200;
11004 BWN_WRITE_2(mac, BWN_RFCTL, reg);
11005 return BWN_READ_2(mac, BWN_RFDATALO);
11006}
11007
11008static void
11009bwn_phy_lp_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
11010{
11011
11012 KASSERT(reg != 1, ("unaccessible register %d", reg));
11013 BWN_WRITE_2(mac, BWN_RFCTL, reg);
11014 BWN_WRITE_2(mac, BWN_RFDATALO, value);
11015}
11016
11017static void
11018bwn_phy_lp_rf_onoff(struct bwn_mac *mac, int on)
11019{
11020
11021 if (on) {
11022 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xe0ff);
11023 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2,
11024 (mac->mac_phy.rev >= 2) ? 0xf7f7 : 0xffe7);
11025 return;
11026 }
11027
11028 if (mac->mac_phy.rev >= 2) {
11029 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x83ff);
11030 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
11031 BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0x80ff);
11032 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xdfff);
11033 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0808);
11034 return;
11035 }
11036
11037 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xe0ff);
11038 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
11039 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfcff);
11040 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0018);
11041}
11042
11043static int
11044bwn_phy_lp_switch_channel(struct bwn_mac *mac, uint32_t chan)
11045{
11046 struct bwn_phy *phy = &mac->mac_phy;
11047 struct bwn_phy_lp *plp = &phy->phy_lp;
11048 int error;
11049
11050 if (phy->rf_ver == 0x2063) {
11051 error = bwn_phy_lp_b2063_switch_channel(mac, chan);
11052 if (error)
11053 return (error);
11054 } else {
11055 error = bwn_phy_lp_b2062_switch_channel(mac, chan);
11056 if (error)
11057 return (error);
11058 bwn_phy_lp_set_anafilter(mac, chan);
11059 bwn_phy_lp_set_gaintbl(mac, ieee80211_ieee2mhz(chan, 0));
11060 }
11061
11062 plp->plp_chan = chan;
11063 BWN_WRITE_2(mac, BWN_CHANNEL, chan);
11064 return (0);
11065}
11066
11067static uint32_t
11068bwn_phy_lp_get_default_chan(struct bwn_mac *mac)
11069{
11070 struct bwn_softc *sc = mac->mac_sc;
11071 struct ifnet *ifp = sc->sc_ifp;
11072 struct ieee80211com *ic = ifp->if_l2com;
11073
11074 return (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? 1 : 36);
11075}
11076
11077static void
11078bwn_phy_lp_set_antenna(struct bwn_mac *mac, int antenna)
11079{
11080 struct bwn_phy *phy = &mac->mac_phy;
11081 struct bwn_phy_lp *plp = &phy->phy_lp;
11082
11083 if (phy->rev >= 2 || antenna > BWN_ANTAUTO1)
11084 return;
11085
11086 bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER);
11087 BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffd, antenna & 0x2);
11088 BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffe, antenna & 0x1);
11089 bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_UCODE_ANTDIV_HELPER);
11090 plp->plp_antenna = antenna;
11091}
11092
11093static void
11094bwn_phy_lp_task_60s(struct bwn_mac *mac)
11095{
11096
11097 bwn_phy_lp_calib(mac);
11098}
11099
11100static void
11101bwn_phy_lp_readsprom(struct bwn_mac *mac)
11102{
11103 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11104 struct bwn_softc *sc = mac->mac_sc;
11105 struct ifnet *ifp = sc->sc_ifp;
11106 struct ieee80211com *ic = ifp->if_l2com;
11107
11108 if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11109 plp->plp_txisoband_m = siba_sprom_get_tri2g(sc->sc_dev);
11110 plp->plp_bxarch = siba_sprom_get_bxa2g(sc->sc_dev);
11111 plp->plp_rxpwroffset = siba_sprom_get_rxpo2g(sc->sc_dev);
11112 plp->plp_rssivf = siba_sprom_get_rssismf2g(sc->sc_dev);
11113 plp->plp_rssivc = siba_sprom_get_rssismc2g(sc->sc_dev);
11114 plp->plp_rssigs = siba_sprom_get_rssisav2g(sc->sc_dev);
11115 return;
11116 }
11117
11118 plp->plp_txisoband_l = siba_sprom_get_tri5gl(sc->sc_dev);
11119 plp->plp_txisoband_m = siba_sprom_get_tri5g(sc->sc_dev);
11120 plp->plp_txisoband_h = siba_sprom_get_tri5gh(sc->sc_dev);
11121 plp->plp_bxarch = siba_sprom_get_bxa5g(sc->sc_dev);
11122 plp->plp_rxpwroffset = siba_sprom_get_rxpo5g(sc->sc_dev);
11123 plp->plp_rssivf = siba_sprom_get_rssismf5g(sc->sc_dev);
11124 plp->plp_rssivc = siba_sprom_get_rssismc5g(sc->sc_dev);
11125 plp->plp_rssigs = siba_sprom_get_rssisav5g(sc->sc_dev);
11126}
11127
11128static void
11129bwn_phy_lp_bbinit(struct bwn_mac *mac)
11130{
11131
11132 bwn_phy_lp_tblinit(mac);
11133 if (mac->mac_phy.rev >= 2)
11134 bwn_phy_lp_bbinit_r2(mac);
11135 else
11136 bwn_phy_lp_bbinit_r01(mac);
11137}
11138
11139static void
11140bwn_phy_lp_txpctl_init(struct bwn_mac *mac)
11141{
11142 struct bwn_txgain gain_2ghz = { 4, 12, 12, 0 };
11143 struct bwn_txgain gain_5ghz = { 7, 15, 14, 0 };
11144 struct bwn_softc *sc = mac->mac_sc;
11145 struct ifnet *ifp = sc->sc_ifp;
11146 struct ieee80211com *ic = ifp->if_l2com;
11147
11148 bwn_phy_lp_set_txgain(mac,
11149 IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? &gain_2ghz : &gain_5ghz);
11150 bwn_phy_lp_set_bbmult(mac, 150);
11151}
11152
11153static void
11154bwn_phy_lp_calib(struct bwn_mac *mac)
11155{
11156 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11157 struct bwn_softc *sc = mac->mac_sc;
11158 struct ifnet *ifp = sc->sc_ifp;
11159 struct ieee80211com *ic = ifp->if_l2com;
11160 const struct bwn_rxcompco *rc = NULL;
11161 struct bwn_txgain ogain;
11162 int i, omode, oafeovr, orf, obbmult;
11163 uint8_t mode, fc = 0;
11164
11165 if (plp->plp_chanfullcal != plp->plp_chan) {
11166 plp->plp_chanfullcal = plp->plp_chan;
11167 fc = 1;
11168 }
11169
11170 bwn_mac_suspend(mac);
11171
11172 /* BlueTooth Coexistance Override */
11173 BWN_WRITE_2(mac, BWN_BTCOEX_CTL, 0x3);
11174 BWN_WRITE_2(mac, BWN_BTCOEX_TXCTL, 0xff);
11175
11176 if (mac->mac_phy.rev >= 2)
11177 bwn_phy_lp_digflt_save(mac);
11178 bwn_phy_lp_get_txpctlmode(mac);
11179 mode = plp->plp_txpctlmode;
11180 bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11181 if (mac->mac_phy.rev == 0 && mode != BWN_PHYLP_TXPCTL_OFF)
11182 bwn_phy_lp_bugfix(mac);
11183 if (mac->mac_phy.rev >= 2 && fc == 1) {
11184 bwn_phy_lp_get_txpctlmode(mac);
11185 omode = plp->plp_txpctlmode;
11186 oafeovr = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40;
11187 if (oafeovr)
11188 ogain = bwn_phy_lp_get_txgain(mac);
11189 orf = BWN_PHY_READ(mac, BWN_PHY_RF_PWR_OVERRIDE) & 0xff;
11190 obbmult = bwn_phy_lp_get_bbmult(mac);
11191 bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11192 if (oafeovr)
11193 bwn_phy_lp_set_txgain(mac, &ogain);
11194 bwn_phy_lp_set_bbmult(mac, obbmult);
11195 bwn_phy_lp_set_txpctlmode(mac, omode);
11196 BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00, orf);
11197 }
11198 bwn_phy_lp_set_txpctlmode(mac, mode);
11199 if (mac->mac_phy.rev >= 2)
11200 bwn_phy_lp_digflt_restore(mac);
11201
11202 /* do RX IQ Calculation; assumes that noise is true. */
11203 if (siba_get_chipid(sc->sc_dev) == 0x5354) {
11204 for (i = 0; i < N(bwn_rxcompco_5354); i++) {
11205 if (bwn_rxcompco_5354[i].rc_chan == plp->plp_chan)
11206 rc = &bwn_rxcompco_5354[i];
11207 }
11208 } else if (mac->mac_phy.rev >= 2)
11209 rc = &bwn_rxcompco_r2;
11210 else {
11211 for (i = 0; i < N(bwn_rxcompco_r12); i++) {
11212 if (bwn_rxcompco_r12[i].rc_chan == plp->plp_chan)
11213 rc = &bwn_rxcompco_r12[i];
11214 }
11215 }
11216 if (rc == NULL)
11217 goto fail;
11218
11219 BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, rc->rc_c1);
11220 BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, rc->rc_c0 << 8);
11221
11222 bwn_phy_lp_set_trsw_over(mac, 1 /* TX */, 0 /* RX */);
11223
11224 if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11225 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
11226 BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7, 0);
11227 } else {
11228 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
11229 BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf, 0);
11230 }
11231
11232 bwn_phy_lp_set_rxgain(mac, 0x2d5d);
11233 BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11234 BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
11235 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
11236 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
11237 bwn_phy_lp_set_deaf(mac, 0);
11238 /* XXX no checking return value? */
11239 (void)bwn_phy_lp_calc_rx_iq_comp(mac, 0xfff0);
11240 bwn_phy_lp_clear_deaf(mac, 0);
11241 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffc);
11242 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfff7);
11243 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffdf);
11244
11245 /* disable RX GAIN override. */
11246 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffe);
11247 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffef);
11248 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffbf);
11249 if (mac->mac_phy.rev >= 2) {
11250 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11251 if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11252 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfbff);
11253 BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xe5), 0xfff7);
11254 }
11255 } else {
11256 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfdff);
11257 }
11258
11259 BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11260 BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xf7ff);
11261fail:
11262 bwn_mac_enable(mac);
11263}
11264
11265static void
11266bwn_phy_lp_switch_analog(struct bwn_mac *mac, int on)
11267{
11268
11269 if (on) {
11270 BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfff8);
11271 return;
11272 }
11273
11274 BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVRVAL, 0x0007);
11275 BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x0007);
11276}
11277
11278static int
11279bwn_phy_lp_b2063_switch_channel(struct bwn_mac *mac, uint8_t chan)
11280{
11281 static const struct bwn_b206x_chan *bc = NULL;
11282 struct bwn_softc *sc = mac->mac_sc;
11283 uint32_t count, freqref, freqvco, freqxtal, val[3], timeout, timeoutref,
11284 tmp[6];
11285 uint16_t old, scale, tmp16;
11286 int i, div;
11287
11288 for (i = 0; i < N(bwn_b2063_chantable); i++) {
11289 if (bwn_b2063_chantable[i].bc_chan == chan) {
11290 bc = &bwn_b2063_chantable[i];
11291 break;
11292 }
11293 }
11294 if (bc == NULL)
11295 return (EINVAL);
11296
11297 BWN_RF_WRITE(mac, BWN_B2063_LOGEN_VCOBUF1, bc->bc_data[0]);
11298 BWN_RF_WRITE(mac, BWN_B2063_LOGEN_MIXER2, bc->bc_data[1]);
11299 BWN_RF_WRITE(mac, BWN_B2063_LOGEN_BUF2, bc->bc_data[2]);
11300 BWN_RF_WRITE(mac, BWN_B2063_LOGEN_RCCR1, bc->bc_data[3]);
11301 BWN_RF_WRITE(mac, BWN_B2063_A_RX_1ST3, bc->bc_data[4]);
11302 BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND1, bc->bc_data[5]);
11303 BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND4, bc->bc_data[6]);
11304 BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND7, bc->bc_data[7]);
11305 BWN_RF_WRITE(mac, BWN_B2063_A_RX_PS6, bc->bc_data[8]);
11306 BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL2, bc->bc_data[9]);
11307 BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL5, bc->bc_data[10]);
11308 BWN_RF_WRITE(mac, BWN_B2063_PA_CTL11, bc->bc_data[11]);
11309
11310 old = BWN_RF_READ(mac, BWN_B2063_COM15);
11311 BWN_RF_SET(mac, BWN_B2063_COM15, 0x1e);
11312
11313 freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
11314 freqvco = bc->bc_freq << ((bc->bc_freq > 4000) ? 1 : 2);
11315 freqref = freqxtal * 3;
11316 div = (freqxtal <= 26000000 ? 1 : 2);
11317 timeout = ((((8 * freqxtal) / (div * 5000000)) + 1) >> 1) - 1;
11318 timeoutref = ((((8 * freqxtal) / (div * (timeout + 1))) +
11319 999999) / 1000000) + 1;
11320
11321 BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB3, 0x2);
11322 BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB6,
11323 0xfff8, timeout >> 2);
11324 BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11325 0xff9f,timeout << 5);
11326 BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB5, timeoutref);
11327
11328 val[0] = bwn_phy_lp_roundup(freqxtal, 1000000, 16);
11329 val[1] = bwn_phy_lp_roundup(freqxtal, 1000000 * div, 16);
11330 val[2] = bwn_phy_lp_roundup(freqvco, 3, 16);
11331
11332 count = (bwn_phy_lp_roundup(val[2], val[1] + 16, 16) * (timeout + 1) *
11333 (timeoutref + 1)) - 1;
11334 BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11335 0xf0, count >> 8);
11336 BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB8, count & 0xff);
11337
11338 tmp[0] = ((val[2] * 62500) / freqref) << 4;
11339 tmp[1] = ((val[2] * 62500) % freqref) << 4;
11340 while (tmp[1] >= freqref) {
11341 tmp[0]++;
11342 tmp[1] -= freqref;
11343 }
11344 BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG1, 0xffe0, tmp[0] >> 4);
11345 BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfe0f, tmp[0] << 4);
11346 BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfff0, tmp[0] >> 16);
11347 BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG3, (tmp[1] >> 8) & 0xff);
11348 BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG4, tmp[1] & 0xff);
11349
11350 BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF1, 0xb9);
11351 BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF2, 0x88);
11352 BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF3, 0x28);
11353 BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF4, 0x63);
11354
11355 tmp[2] = ((41 * (val[2] - 3000)) /1200) + 27;
11356 tmp[3] = bwn_phy_lp_roundup(132000 * tmp[0], 8451, 16);
11357
11358 if ((tmp[3] + tmp[2] - 1) / tmp[2] > 60) {
11359 scale = 1;
11360 tmp[4] = ((tmp[3] + tmp[2]) / (tmp[2] << 1)) - 8;
11361 } else {
11362 scale = 0;
11363 tmp[4] = ((tmp[3] + (tmp[2] >> 1)) / tmp[2]) - 8;
11364 }
11365 BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffc0, tmp[4]);
11366 BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffbf, scale << 6);
11367
11368 tmp[5] = bwn_phy_lp_roundup(100 * val[0], val[2], 16) * (tmp[4] * 8) *
11369 (scale + 1);
11370 if (tmp[5] > 150)
11371 tmp[5] = 0;
11372
11373 BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffe0, tmp[5]);
11374 BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffdf, scale << 5);
11375
11376 BWN_RF_SETMASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfffb, 0x4);
11377 if (freqxtal > 26000000)
11378 BWN_RF_SET(mac, BWN_B2063_JTAG_XTAL_12, 0x2);
11379 else
11380 BWN_RF_MASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfd);
11381
11382 if (val[0] == 45)
11383 BWN_RF_SET(mac, BWN_B2063_JTAG_VCO1, 0x2);
11384 else
11385 BWN_RF_MASK(mac, BWN_B2063_JTAG_VCO1, 0xfd);
11386
11387 BWN_RF_SET(mac, BWN_B2063_PLL_SP2, 0x3);
11388 DELAY(1);
11389 BWN_RF_MASK(mac, BWN_B2063_PLL_SP2, 0xfffc);
11390
11391 /* VCO Calibration */
11392 BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, ~0x40);
11393 tmp16 = BWN_RF_READ(mac, BWN_B2063_JTAG_CALNRST) & 0xf8;
11394 BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16);
11395 DELAY(1);
11396 BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x4);
11397 DELAY(1);
11398 BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x6);
11399 DELAY(1);
11400 BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x7);
11401 DELAY(300);
11402 BWN_RF_SET(mac, BWN_B2063_PLL_SP1, 0x40);
11403
11404 BWN_RF_WRITE(mac, BWN_B2063_COM15, old);
11405 return (0);
11406}
11407
11408static int
11409bwn_phy_lp_b2062_switch_channel(struct bwn_mac *mac, uint8_t chan)
11410{
11411 struct bwn_softc *sc = mac->mac_sc;
11412 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11413 const struct bwn_b206x_chan *bc = NULL;
11414 uint32_t freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
11415 uint32_t tmp[9];
11416 int i;
11417
11418 for (i = 0; i < N(bwn_b2062_chantable); i++) {
11419 if (bwn_b2062_chantable[i].bc_chan == chan) {
11420 bc = &bwn_b2062_chantable[i];
11421 break;
11422 }
11423 }
11424
11425 if (bc == NULL)
11426 return (EINVAL);
11427
11428 BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL14, 0x04);
11429 BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE0, bc->bc_data[0]);
11430 BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE2, bc->bc_data[1]);
11431 BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE3, bc->bc_data[2]);
11432 BWN_RF_WRITE(mac, BWN_B2062_N_TX_TUNE, bc->bc_data[3]);
11433 BWN_RF_WRITE(mac, BWN_B2062_S_LGENG_CTL1, bc->bc_data[4]);
11434 BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL5, bc->bc_data[5]);
11435 BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL6, bc->bc_data[6]);
11436 BWN_RF_WRITE(mac, BWN_B2062_N_TX_PGA, bc->bc_data[7]);
11437 BWN_RF_WRITE(mac, BWN_B2062_N_TX_PAD, bc->bc_data[8]);
11438
11439 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xcc);
11440 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0x07);
11441 bwn_phy_lp_b2062_reset_pllbias(mac);
11442 tmp[0] = freqxtal / 1000;
11443 tmp[1] = plp->plp_div * 1000;
11444 tmp[2] = tmp[1] * ieee80211_ieee2mhz(chan, 0);
11445 if (ieee80211_ieee2mhz(chan, 0) < 4000)
11446 tmp[2] *= 2;
11447 tmp[3] = 48 * tmp[0];
11448 tmp[5] = tmp[2] / tmp[3];
11449 tmp[6] = tmp[2] % tmp[3];
11450 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL26, tmp[5]);
11451 tmp[4] = tmp[6] * 0x100;
11452 tmp[5] = tmp[4] / tmp[3];
11453 tmp[6] = tmp[4] % tmp[3];
11454 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL27, tmp[5]);
11455 tmp[4] = tmp[6] * 0x100;
11456 tmp[5] = tmp[4] / tmp[3];
11457 tmp[6] = tmp[4] % tmp[3];
11458 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL28, tmp[5]);
11459 tmp[4] = tmp[6] * 0x100;
11460 tmp[5] = tmp[4] / tmp[3];
11461 tmp[6] = tmp[4] % tmp[3];
11462 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL29,
11463 tmp[5] + ((2 * tmp[6]) / tmp[3]));
11464 tmp[7] = BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL19);
11465 tmp[8] = ((2 * tmp[2] * (tmp[7] + 1)) + (3 * tmp[0])) / (6 * tmp[0]);
11466 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL23, (tmp[8] >> 8) + 16);
11467 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL24, tmp[8] & 0xff);
11468
11469 bwn_phy_lp_b2062_vco_calib(mac);
11470 if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11471 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xfc);
11472 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0);
11473 bwn_phy_lp_b2062_reset_pllbias(mac);
11474 bwn_phy_lp_b2062_vco_calib(mac);
11475 if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11476 BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11477 return (EIO);
11478 }
11479 }
11480 BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11481 return (0);
11482}
11483
11484static void
11485bwn_phy_lp_set_anafilter(struct bwn_mac *mac, uint8_t channel)
11486{
11487 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11488 uint16_t tmp = (channel == 14);
11489
11490 if (mac->mac_phy.rev < 2) {
11491 BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xfcff, tmp << 9);
11492 if ((mac->mac_phy.rev == 1) && (plp->plp_rccap))
11493 bwn_phy_lp_set_rccap(mac);
11494 return;
11495 }
11496
11497 BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, 0x3f);
11498}
11499
11500static void
11501bwn_phy_lp_set_gaintbl(struct bwn_mac *mac, uint32_t freq)
11502{
11503 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11504 struct bwn_softc *sc = mac->mac_sc;
11505 struct ifnet *ifp = sc->sc_ifp;
11506 struct ieee80211com *ic = ifp->if_l2com;
11507 uint16_t iso, tmp[3];
11508
11509 KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
11510
11511 if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
11512 iso = plp->plp_txisoband_m;
11513 else if (freq <= 5320)
11514 iso = plp->plp_txisoband_l;
11515 else if (freq <= 5700)
11516 iso = plp->plp_txisoband_m;
11517 else
11518 iso = plp->plp_txisoband_h;
11519
11520 tmp[0] = ((iso - 26) / 12) << 12;
11521 tmp[1] = tmp[0] + 0x1000;
11522 tmp[2] = tmp[0] + 0x2000;
11523
11524 bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), 3, tmp);
11525 bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), 3, tmp);
11526}
11527
11528static void
11529bwn_phy_lp_digflt_save(struct bwn_mac *mac)
11530{
11531 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11532 int i;
11533 static const uint16_t addr[] = {
11534 BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11535 BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11536 BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11537 BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11538 BWN_PHY_OFDM(0xcf),
11539 };
11540 static const uint16_t val[] = {
11541 0xde5e, 0xe832, 0xe331, 0x4d26,
11542 0x0026, 0x1420, 0x0020, 0xfe08,
11543 0x0008,
11544 };
11545
11546 for (i = 0; i < N(addr); i++) {
11547 plp->plp_digfilt[i] = BWN_PHY_READ(mac, addr[i]);
11548 BWN_PHY_WRITE(mac, addr[i], val[i]);
11549 }
11550}
11551
11552static void
11553bwn_phy_lp_get_txpctlmode(struct bwn_mac *mac)
11554{
11555 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11556 struct bwn_softc *sc = mac->mac_sc;
11557 uint16_t ctl;
11558
11559 ctl = BWN_PHY_READ(mac, BWN_PHY_TX_PWR_CTL_CMD);
11560 switch (ctl & BWN_PHY_TX_PWR_CTL_CMD_MODE) {
11561 case BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF:
11562 plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_OFF;
11563 break;
11564 case BWN_PHY_TX_PWR_CTL_CMD_MODE_SW:
11565 plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_SW;
11566 break;
11567 case BWN_PHY_TX_PWR_CTL_CMD_MODE_HW:
11568 plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_HW;
11569 break;
11570 default:
11571 plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_UNKNOWN;
11572 device_printf(sc->sc_dev, "unknown command mode\n");
11573 break;
11574 }
11575}
11576
11577static void
11578bwn_phy_lp_set_txpctlmode(struct bwn_mac *mac, uint8_t mode)
11579{
11580 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11581 uint16_t ctl;
11582 uint8_t old;
11583
11584 bwn_phy_lp_get_txpctlmode(mac);
11585 old = plp->plp_txpctlmode;
11586 if (old == mode)
11587 return;
11588 plp->plp_txpctlmode = mode;
11589
11590 if (old != BWN_PHYLP_TXPCTL_ON_HW && mode == BWN_PHYLP_TXPCTL_ON_HW) {
11591 BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD, 0xff80,
11592 plp->plp_tssiidx);
11593 BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_NNUM,
11594 0x8fff, ((uint16_t)plp->plp_tssinpt << 16));
11595
11596 /* disable TX GAIN override */
11597 if (mac->mac_phy.rev < 2)
11598 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11599 else {
11600 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xff7f);
11601 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xbfff);
11602 }
11603 BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xffbf);
11604
11605 plp->plp_txpwridx = -1;
11606 }
11607 if (mac->mac_phy.rev >= 2) {
11608 if (mode == BWN_PHYLP_TXPCTL_ON_HW)
11609 BWN_PHY_SET(mac, BWN_PHY_OFDM(0xd0), 0x2);
11610 else
11611 BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xd0), 0xfffd);
11612 }
11613
11614 /* writes TX Power Control mode */
11615 switch (plp->plp_txpctlmode) {
11616 case BWN_PHYLP_TXPCTL_OFF:
11617 ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF;
11618 break;
11619 case BWN_PHYLP_TXPCTL_ON_HW:
11620 ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_HW;
11621 break;
11622 case BWN_PHYLP_TXPCTL_ON_SW:
11623 ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_SW;
11624 break;
11625 default:
11626 ctl = 0;
11627 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
11628 }
11629 BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD,
11630 (uint16_t)~BWN_PHY_TX_PWR_CTL_CMD_MODE, ctl);
11631}
11632
11633static void
11634bwn_phy_lp_bugfix(struct bwn_mac *mac)
11635{
11636 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11637 struct bwn_softc *sc = mac->mac_sc;
11638 const unsigned int size = 256;
11639 struct bwn_txgain tg;
11640 uint32_t rxcomp, txgain, coeff, rfpwr, *tabs;
11641 uint16_t tssinpt, tssiidx, value[2];
11642 uint8_t mode;
11643 int8_t txpwridx;
11644
11645 tabs = (uint32_t *)malloc(sizeof(uint32_t) * size, M_DEVBUF,
11646 M_NOWAIT | M_ZERO);
11647 if (tabs == NULL) {
11648 device_printf(sc->sc_dev, "failed to allocate buffer.\n");
11649 return;
11650 }
11651
11652 bwn_phy_lp_get_txpctlmode(mac);
11653 mode = plp->plp_txpctlmode;
11654 txpwridx = plp->plp_txpwridx;
11655 tssinpt = plp->plp_tssinpt;
11656 tssiidx = plp->plp_tssiidx;
11657
11658 bwn_tab_read_multi(mac,
11659 (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11660 BWN_TAB_4(7, 0x140), size, tabs);
11661
11662 bwn_phy_lp_tblinit(mac);
11663 bwn_phy_lp_bbinit(mac);
11664 bwn_phy_lp_txpctl_init(mac);
11665 bwn_phy_lp_rf_onoff(mac, 1);
11666 bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11667
11668 bwn_tab_write_multi(mac,
11669 (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11670 BWN_TAB_4(7, 0x140), size, tabs);
11671
11672 BWN_WRITE_2(mac, BWN_CHANNEL, plp->plp_chan);
11673 plp->plp_tssinpt = tssinpt;
11674 plp->plp_tssiidx = tssiidx;
11675 bwn_phy_lp_set_anafilter(mac, plp->plp_chan);
11676 if (txpwridx != -1) {
11677 /* set TX power by index */
11678 plp->plp_txpwridx = txpwridx;
11679 bwn_phy_lp_get_txpctlmode(mac);
11680 if (plp->plp_txpctlmode != BWN_PHYLP_TXPCTL_OFF)
11681 bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_ON_SW);
11682 if (mac->mac_phy.rev >= 2) {
11683 rxcomp = bwn_tab_read(mac,
11684 BWN_TAB_4(7, txpwridx + 320));
11685 txgain = bwn_tab_read(mac,
11686 BWN_TAB_4(7, txpwridx + 192));
11687 tg.tg_pad = (txgain >> 16) & 0xff;
11688 tg.tg_gm = txgain & 0xff;
11689 tg.tg_pga = (txgain >> 8) & 0xff;
11690 tg.tg_dac = (rxcomp >> 28) & 0xff;
11691 bwn_phy_lp_set_txgain(mac, &tg);
11692 } else {
11693 rxcomp = bwn_tab_read(mac,
11694 BWN_TAB_4(10, txpwridx + 320));
11695 txgain = bwn_tab_read(mac,
11696 BWN_TAB_4(10, txpwridx + 192));
11697 BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
11698 0xf800, (txgain >> 4) & 0x7fff);
11699 bwn_phy_lp_set_txgain_dac(mac, txgain & 0x7);
11700 bwn_phy_lp_set_txgain_pa(mac, (txgain >> 24) & 0x7f);
11701 }
11702 bwn_phy_lp_set_bbmult(mac, (rxcomp >> 20) & 0xff);
11703
11704 /* set TX IQCC */
11705 value[0] = (rxcomp >> 10) & 0x3ff;
11706 value[1] = rxcomp & 0x3ff;
11707 bwn_tab_write_multi(mac, BWN_TAB_2(0, 80), 2, value);
11708
11709 coeff = bwn_tab_read(mac,
11710 (mac->mac_phy.rev >= 2) ? BWN_TAB_4(7, txpwridx + 448) :
11711 BWN_TAB_4(10, txpwridx + 448));
11712 bwn_tab_write(mac, BWN_TAB_2(0, 85), coeff & 0xffff);
11713 if (mac->mac_phy.rev >= 2) {
11714 rfpwr = bwn_tab_read(mac,
11715 BWN_TAB_4(7, txpwridx + 576));
11716 BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00,
11717 rfpwr & 0xffff);
11718 }
11719 bwn_phy_lp_set_txgain_override(mac);
11720 }
11721 if (plp->plp_rccap)
11722 bwn_phy_lp_set_rccap(mac);
11723 bwn_phy_lp_set_antenna(mac, plp->plp_antenna);
11724 bwn_phy_lp_set_txpctlmode(mac, mode);
11725 free(tabs, M_DEVBUF);
11726}
11727
11728static void
11729bwn_phy_lp_digflt_restore(struct bwn_mac *mac)
11730{
11731 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11732 int i;
11733 static const uint16_t addr[] = {
11734 BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11735 BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11736 BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11737 BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11738 BWN_PHY_OFDM(0xcf),
11739 };
11740
11741 for (i = 0; i < N(addr); i++)
11742 BWN_PHY_WRITE(mac, addr[i], plp->plp_digfilt[i]);
11743}
11744
11745static void
11746bwn_phy_lp_tblinit(struct bwn_mac *mac)
11747{
11748 uint32_t freq = ieee80211_ieee2mhz(bwn_phy_lp_get_default_chan(mac), 0);
11749
11750 if (mac->mac_phy.rev < 2) {
11751 bwn_phy_lp_tblinit_r01(mac);
11752 bwn_phy_lp_tblinit_txgain(mac);
11753 bwn_phy_lp_set_gaintbl(mac, freq);
11754 return;
11755 }
11756
11757 bwn_phy_lp_tblinit_r2(mac);
11758 bwn_phy_lp_tblinit_txgain(mac);
11759}
11760
11761struct bwn_wpair {
11762 uint16_t reg;
11763 uint16_t value;
11764};
11765
11766struct bwn_smpair {
11767 uint16_t offset;
11768 uint16_t mask;
11769 uint16_t set;
11770};
11771
11772static void
11773bwn_phy_lp_bbinit_r2(struct bwn_mac *mac)
11774{
11775 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11776 struct bwn_softc *sc = mac->mac_sc;
11777 struct ifnet *ifp = sc->sc_ifp;
11778 struct ieee80211com *ic = ifp->if_l2com;
11779 static const struct bwn_wpair v1[] = {
11780 { BWN_PHY_AFE_DAC_CTL, 0x50 },
11781 { BWN_PHY_AFE_CTL, 0x8800 },
11782 { BWN_PHY_AFE_CTL_OVR, 0 },
11783 { BWN_PHY_AFE_CTL_OVRVAL, 0 },
11784 { BWN_PHY_RF_OVERRIDE_0, 0 },
11785 { BWN_PHY_RF_OVERRIDE_2, 0 },
11786 { BWN_PHY_OFDM(0xf9), 0 },
11787 { BWN_PHY_TR_LOOKUP_1, 0 }
11788 };
11789 static const struct bwn_smpair v2[] = {
11790 { BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0xb4 },
11791 { BWN_PHY_DCOFFSETTRANSIENT, 0xf8ff, 0x200 },
11792 { BWN_PHY_DCOFFSETTRANSIENT, 0xff00, 0x7f },
11793 { BWN_PHY_GAINDIRECTMISMATCH, 0xff0f, 0x40 },
11794 { BWN_PHY_PREAMBLECONFIRMTO, 0xff00, 0x2 }
11795 };
11796 static const struct bwn_smpair v3[] = {
11797 { BWN_PHY_OFDM(0xfe), 0xffe0, 0x1f },
11798 { BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11799 { BWN_PHY_OFDM(0x100), 0xff00, 0x19 },
11800 { BWN_PHY_OFDM(0xff), 0x03ff, 0x3c00 },
11801 { BWN_PHY_OFDM(0xfe), 0xfc1f, 0x3e0 },
11802 { BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11803 { BWN_PHY_OFDM(0x100), 0x00ff, 0x1900 },
11804 { BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800 },
11805 { BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x12 },
11806 { BWN_PHY_GAINMISMATCH, 0x0fff, 0x9000 },
11807
11808 };
11809 int i;
11810
11811 for (i = 0; i < N(v1); i++)
11812 BWN_PHY_WRITE(mac, v1[i].reg, v1[i].value);
11813 BWN_PHY_SET(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x10);
11814 for (i = 0; i < N(v2); i++)
11815 BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask, v2[i].set);
11816
11817 BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x4000);
11818 BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x2000);
11819 BWN_PHY_SET(mac, BWN_PHY_OFDM(0x10a), 0x1);
11820 if (siba_get_pci_revid(sc->sc_dev) >= 0x18) {
11821 bwn_tab_write(mac, BWN_TAB_4(17, 65), 0xec);
11822 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x14);
11823 } else {
11824 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x10);
11825 }
11826 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0xff00, 0xf4);
11827 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0x00ff, 0xf100);
11828 BWN_PHY_WRITE(mac, BWN_PHY_CLIPTHRESH, 0x48);
11829 BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0xff00, 0x46);
11830 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe4), 0xff00, 0x10);
11831 BWN_PHY_SETMASK(mac, BWN_PHY_PWR_THRESH1, 0xfff0, 0x9);
11832 BWN_PHY_MASK(mac, BWN_PHY_GAINDIRECTMISMATCH, ~0xf);
11833 BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5500);
11834 BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0xa0);
11835 BWN_PHY_SETMASK(mac, BWN_PHY_GAINDIRECTMISMATCH, 0xe0ff, 0x300);
11836 BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2a00);
11837 if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11838 (siba_get_chiprev(sc->sc_dev) == 0)) {
11839 BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11840 BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xa);
11841 } else {
11842 BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x1e00);
11843 BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xd);
11844 }
11845 for (i = 0; i < N(v3); i++)
11846 BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask, v3[i].set);
11847 if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11848 (siba_get_chiprev(sc->sc_dev) == 0)) {
11849 bwn_tab_write(mac, BWN_TAB_2(0x08, 0x14), 0);
11850 bwn_tab_write(mac, BWN_TAB_2(0x08, 0x12), 0x40);
11851 }
11852
11853 if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11854 BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x40);
11855 BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0xb00);
11856 BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x6);
11857 BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0x9d00);
11858 BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0xff00, 0xa1);
11859 BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
11860 } else
11861 BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x40);
11862
11863 BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0xff00, 0xb3);
11864 BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00);
11865 BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB, 0xff00, plp->plp_rxpwroffset);
11866 BWN_PHY_SET(mac, BWN_PHY_RESET_CTL, 0x44);
11867 BWN_PHY_WRITE(mac, BWN_PHY_RESET_CTL, 0x80);
11868 BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, 0xa954);
11869 BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_1,
11870 0x2000 | ((uint16_t)plp->plp_rssigs << 10) |
11871 ((uint16_t)plp->plp_rssivc << 4) | plp->plp_rssivf);
11872
11873 if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11874 (siba_get_chiprev(sc->sc_dev) == 0)) {
11875 BWN_PHY_SET(mac, BWN_PHY_AFE_ADC_CTL_0, 0x1c);
11876 BWN_PHY_SETMASK(mac, BWN_PHY_AFE_CTL, 0x00ff, 0x8800);
11877 BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_1, 0xfc3c, 0x0400);
11878 }
11879
11880 bwn_phy_lp_digflt_save(mac);
11881}
11882
11883static void
11884bwn_phy_lp_bbinit_r01(struct bwn_mac *mac)
11885{
11886 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11887 struct bwn_softc *sc = mac->mac_sc;
11888 struct ifnet *ifp = sc->sc_ifp;
11889 struct ieee80211com *ic = ifp->if_l2com;
11890 static const struct bwn_smpair v1[] = {
11891 { BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x0005 },
11892 { BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0x0180 },
11893 { BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x3c00 },
11894 { BWN_PHY_GAINDIRECTMISMATCH, 0xfff0, 0x0005 },
11895 { BWN_PHY_GAIN_MISMATCH_LIMIT, 0xffc0, 0x001a },
11896 { BWN_PHY_CRS_ED_THRESH, 0xff00, 0x00b3 },
11897 { BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00 }
11898 };
11899 static const struct bwn_smpair v2[] = {
11900 { BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11901 { BWN_PHY_TR_LOOKUP_1, 0x3f00, 0x0900 },
11902 { BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11903 { BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11904 { BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x000a },
11905 { BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0400 },
11906 { BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x000a },
11907 { BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0b00 },
11908 { BWN_PHY_TR_LOOKUP_5, 0xffc0, 0x000a },
11909 { BWN_PHY_TR_LOOKUP_5, 0xc0ff, 0x0900 },
11910 { BWN_PHY_TR_LOOKUP_6, 0xffc0, 0x000a },
11911 { BWN_PHY_TR_LOOKUP_6, 0xc0ff, 0x0b00 },
11912 { BWN_PHY_TR_LOOKUP_7, 0xffc0, 0x000a },
11913 { BWN_PHY_TR_LOOKUP_7, 0xc0ff, 0x0900 },
11914 { BWN_PHY_TR_LOOKUP_8, 0xffc0, 0x000a },
11915 { BWN_PHY_TR_LOOKUP_8, 0xc0ff, 0x0b00 }
11916 };
11917 static const struct bwn_smpair v3[] = {
11918 { BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0001 },
11919 { BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0400 },
11920 { BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0001 },
11921 { BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0500 },
11922 { BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11923 { BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0800 },
11924 { BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11925 { BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0a00 }
11926 };
11927 static const struct bwn_smpair v4[] = {
11928 { BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0004 },
11929 { BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0800 },
11930 { BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0004 },
11931 { BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0c00 },
11932 { BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11933 { BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0100 },
11934 { BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11935 { BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0300 }
11936 };
11937 static const struct bwn_smpair v5[] = {
11938 { BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11939 { BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0900 },
11940 { BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11941 { BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11942 { BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0006 },
11943 { BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0500 },
11944 { BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0006 },
11945 { BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0700 }
11946 };
11947 int i;
11948 uint16_t tmp, tmp2;
11949
11950 BWN_PHY_MASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf7ff);
11951 BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL, 0);
11952 BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, 0);
11953 BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, 0);
11954 BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0);
11955 BWN_PHY_SET(mac, BWN_PHY_AFE_DAC_CTL, 0x0004);
11956 BWN_PHY_SETMASK(mac, BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0x0078);
11957 BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800);
11958 BWN_PHY_WRITE(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x0016);
11959 BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_0, 0xfff8, 0x0004);
11960 BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5400);
11961 BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2400);
11962 BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11963 BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0x0006);
11964 BWN_PHY_MASK(mac, BWN_PHY_RX_RADIO_CTL, 0xfffe);
11965 for (i = 0; i < N(v1); i++)
11966 BWN_PHY_SETMASK(mac, v1[i].offset, v1[i].mask, v1[i].set);
11967 BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB,
11968 0xff00, plp->plp_rxpwroffset);
11969 if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM) &&
11970 ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ||
11971 (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_LDO_PAREF))) {
11972 siba_cc_pmu_set_ldovolt(sc->sc_dev, SIBA_LDO_PAREF, 0x28);
11973 siba_cc_pmu_set_ldoparef(sc->sc_dev, 1);
11974 if (mac->mac_phy.rev == 0)
11975 BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT,
11976 0xffcf, 0x0010);
11977 bwn_tab_write(mac, BWN_TAB_2(11, 7), 60);
11978 } else {
11979 siba_cc_pmu_set_ldoparef(sc->sc_dev, 0);
11980 BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT, 0xffcf, 0x0020);
11981 bwn_tab_write(mac, BWN_TAB_2(11, 7), 100);
11982 }
11983 tmp = plp->plp_rssivf | plp->plp_rssivc << 4 | 0xa000;
11984 BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, tmp);
11985 if (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_RSSIINV)
11986 BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x0aaa);
11987 else
11988 BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x02aa);
11989 bwn_tab_write(mac, BWN_TAB_2(11, 1), 24);
11990 BWN_PHY_SETMASK(mac, BWN_PHY_RX_RADIO_CTL,
11991 0xfff9, (plp->plp_bxarch << 1));
11992 if (mac->mac_phy.rev == 1 &&
11993 (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_FEM_BT)) {
11994 for (i = 0; i < N(v2); i++)
11995 BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask,
11996 v2[i].set);
11997 } else if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ||
11998 (siba_get_pci_subdevice(sc->sc_dev) == 0x048a) ||
11999 ((mac->mac_phy.rev == 0) &&
12000 (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM))) {
12001 for (i = 0; i < N(v3); i++)
12002 BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask,
12003 v3[i].set);
12004 } else if (mac->mac_phy.rev == 1 ||
12005 (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM)) {
12006 for (i = 0; i < N(v4); i++)
12007 BWN_PHY_SETMASK(mac, v4[i].offset, v4[i].mask,
12008 v4[i].set);
12009 } else {
12010 for (i = 0; i < N(v5); i++)
12011 BWN_PHY_SETMASK(mac, v5[i].offset, v5[i].mask,
12012 v5[i].set);
12013 }
12014 if (mac->mac_phy.rev == 1 &&
12015 (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_LDO_PAREF)) {
12016 BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_5, BWN_PHY_TR_LOOKUP_1);
12017 BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_6, BWN_PHY_TR_LOOKUP_2);
12018 BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_7, BWN_PHY_TR_LOOKUP_3);
12019 BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_8, BWN_PHY_TR_LOOKUP_4);
12020 }
12021 if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_FEM_BT) &&
12022 (siba_get_chipid(sc->sc_dev) == 0x5354) &&
12023 (siba_get_chippkg(sc->sc_dev) == SIBA_CHIPPACK_BCM4712S)) {
12024 BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0006);
12025 BWN_PHY_WRITE(mac, BWN_PHY_GPIO_SELECT, 0x0005);
12026 BWN_PHY_WRITE(mac, BWN_PHY_GPIO_OUTEN, 0xffff);
12027 bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_PR45960W);
12028 }
12029 if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12030 BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x8000);
12031 BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0040);
12032 BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0xa400);
12033 BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0x0b00);
12034 BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x0007);
12035 BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xfff8, 0x0003);
12036 BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xffc7, 0x0020);
12037 BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
12038 } else {
12039 BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0x7fff);
12040 BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xffbf);
12041 }
12042 if (mac->mac_phy.rev == 1) {
12043 tmp = BWN_PHY_READ(mac, BWN_PHY_CLIPCTRTHRESH);
12044 tmp2 = (tmp & 0x03e0) >> 5;
12045 tmp2 |= tmp2 << 5;
12046 BWN_PHY_WRITE(mac, BWN_PHY_4C3, tmp2);
12047 tmp = BWN_PHY_READ(mac, BWN_PHY_GAINDIRECTMISMATCH);
12048 tmp2 = (tmp & 0x1f00) >> 8;
12049 tmp2 |= tmp2 << 5;
12050 BWN_PHY_WRITE(mac, BWN_PHY_4C4, tmp2);
12051 tmp = BWN_PHY_READ(mac, BWN_PHY_VERYLOWGAINDB);
12052 tmp2 = tmp & 0x00ff;
12053 tmp2 |= tmp << 8;
12054 BWN_PHY_WRITE(mac, BWN_PHY_4C5, tmp2);
12055 }
12056}
12057
12058struct bwn_b2062_freq {
12059 uint16_t freq;
12060 uint8_t value[6];
12061};
12062
12063static void
12064bwn_phy_lp_b2062_init(struct bwn_mac *mac)
12065{
12066#define CALC_CTL7(freq, div) \
12067 (((800000000 * (div) + (freq)) / (2 * (freq)) - 8) & 0xff)
12068#define CALC_CTL18(freq, div) \
12069 ((((100 * (freq) + 16000000 * (div)) / (32000000 * (div))) - 1) & 0xff)
12070#define CALC_CTL19(freq, div) \
12071 ((((2 * (freq) + 1000000 * (div)) / (2000000 * (div))) - 1) & 0xff)
12072 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12073 struct bwn_softc *sc = mac->mac_sc;
12074 struct ifnet *ifp = sc->sc_ifp;
12075 struct ieee80211com *ic = ifp->if_l2com;
12076 static const struct bwn_b2062_freq freqdata_tab[] = {
12077 { 12000, { 6, 6, 6, 6, 10, 6 } },
12078 { 13000, { 4, 4, 4, 4, 11, 7 } },
12079 { 14400, { 3, 3, 3, 3, 12, 7 } },
12080 { 16200, { 3, 3, 3, 3, 13, 8 } },
12081 { 18000, { 2, 2, 2, 2, 14, 8 } },
12082 { 19200, { 1, 1, 1, 1, 14, 9 } }
12083 };
12084 static const struct bwn_wpair v1[] = {
12085 { BWN_B2062_N_TXCTL3, 0 },
12086 { BWN_B2062_N_TXCTL4, 0 },
12087 { BWN_B2062_N_TXCTL5, 0 },
12088 { BWN_B2062_N_TXCTL6, 0 },
12089 { BWN_B2062_N_PDNCTL0, 0x40 },
12090 { BWN_B2062_N_PDNCTL0, 0 },
12091 { BWN_B2062_N_CALIB_TS, 0x10 },
12092 { BWN_B2062_N_CALIB_TS, 0 }
12093 };
12094 const struct bwn_b2062_freq *f = NULL;
12095 uint32_t xtalfreq, ref;
12096 unsigned int i;
12097
12098 bwn_phy_lp_b2062_tblinit(mac);
12099
12100 for (i = 0; i < N(v1); i++)
12101 BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12102 if (mac->mac_phy.rev > 0)
12103 BWN_RF_WRITE(mac, BWN_B2062_S_BG_CTL1,
12104 (BWN_RF_READ(mac, BWN_B2062_N_COM2) >> 1) | 0x80);
12105 if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12106 BWN_RF_SET(mac, BWN_B2062_N_TSSI_CTL0, 0x1);
12107 else
12108 BWN_RF_MASK(mac, BWN_B2062_N_TSSI_CTL0, ~0x1);
12109
12110 KASSERT(siba_get_cc_caps(sc->sc_dev) & SIBA_CC_CAPS_PMU,
12111 ("%s:%d: fail", __func__, __LINE__));
12112 xtalfreq = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
12113 KASSERT(xtalfreq != 0, ("%s:%d: fail", __func__, __LINE__));
12114
12115 if (xtalfreq <= 30000000) {
12116 plp->plp_div = 1;
12117 BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL1, 0xfffb);
12118 } else {
12119 plp->plp_div = 2;
12120 BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL1, 0x4);
12121 }
12122
12123 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL7,
12124 CALC_CTL7(xtalfreq, plp->plp_div));
12125 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL18,
12126 CALC_CTL18(xtalfreq, plp->plp_div));
12127 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL19,
12128 CALC_CTL19(xtalfreq, plp->plp_div));
12129
12130 ref = (1000 * plp->plp_div + 2 * xtalfreq) / (2000 * plp->plp_div);
12131 ref &= 0xffff;
12132 for (i = 0; i < N(freqdata_tab); i++) {
12133 if (ref < freqdata_tab[i].freq) {
12134 f = &freqdata_tab[i];
12135 break;
12136 }
12137 }
12138 if (f == NULL)
12139 f = &freqdata_tab[N(freqdata_tab) - 1];
12140 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL8,
12141 ((uint16_t)(f->value[1]) << 4) | f->value[0]);
12142 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL9,
12143 ((uint16_t)(f->value[3]) << 4) | f->value[2]);
12144 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL10, f->value[4]);
12145 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL11, f->value[5]);
12146#undef CALC_CTL7
12147#undef CALC_CTL18
12148#undef CALC_CTL19
12149}
12150
12151static void
12152bwn_phy_lp_b2063_init(struct bwn_mac *mac)
12153{
12154
12155 bwn_phy_lp_b2063_tblinit(mac);
12156 BWN_RF_WRITE(mac, BWN_B2063_LOGEN_SP5, 0);
12157 BWN_RF_SET(mac, BWN_B2063_COM8, 0x38);
12158 BWN_RF_WRITE(mac, BWN_B2063_REG_SP1, 0x56);
12159 BWN_RF_MASK(mac, BWN_B2063_RX_BB_CTL2, ~0x2);
12160 BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0);
12161 BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP6, 0x20);
12162 BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP9, 0x40);
12163 if (mac->mac_phy.rev == 2) {
12164 BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0xa0);
12165 BWN_RF_WRITE(mac, BWN_B2063_PA_SP4, 0xa0);
12166 BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x18);
12167 } else {
12168 BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0x20);
12169 BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x20);
12170 }
12171}
12172
12173static void
12174bwn_phy_lp_rxcal_r2(struct bwn_mac *mac)
12175{
12176 struct bwn_softc *sc = mac->mac_sc;
12177 static const struct bwn_wpair v1[] = {
12178 { BWN_B2063_RX_BB_SP8, 0x0 },
12179 { BWN_B2063_RC_CALIB_CTL1, 0x7e },
12180 { BWN_B2063_RC_CALIB_CTL1, 0x7c },
12181 { BWN_B2063_RC_CALIB_CTL2, 0x15 },
12182 { BWN_B2063_RC_CALIB_CTL3, 0x70 },
12183 { BWN_B2063_RC_CALIB_CTL4, 0x52 },
12184 { BWN_B2063_RC_CALIB_CTL5, 0x1 },
12185 { BWN_B2063_RC_CALIB_CTL1, 0x7d }
12186 };
12187 static const struct bwn_wpair v2[] = {
12188 { BWN_B2063_TX_BB_SP3, 0x0 },
12189 { BWN_B2063_RC_CALIB_CTL1, 0x7e },
12190 { BWN_B2063_RC_CALIB_CTL1, 0x7c },
12191 { BWN_B2063_RC_CALIB_CTL2, 0x55 },
12192 { BWN_B2063_RC_CALIB_CTL3, 0x76 }
12193 };
12194 uint32_t freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
12195 int i;
12196 uint8_t tmp;
12197
12198 tmp = BWN_RF_READ(mac, BWN_B2063_RX_BB_SP8) & 0xff;
12199
12200 for (i = 0; i < 2; i++)
12201 BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12202 BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, 0xf7);
12203 for (i = 2; i < N(v1); i++)
12204 BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12205 for (i = 0; i < 10000; i++) {
12206 if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12207 break;
12208 DELAY(1000);
12209 }
12210
12211 if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12212 BWN_RF_WRITE(mac, BWN_B2063_RX_BB_SP8, tmp);
12213
12214 tmp = BWN_RF_READ(mac, BWN_B2063_TX_BB_SP3) & 0xff;
12215
12216 for (i = 0; i < N(v2); i++)
12217 BWN_RF_WRITE(mac, v2[i].reg, v2[i].value);
12218 if (freqxtal == 24000000) {
12219 BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0xfc);
12220 BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x0);
12221 } else {
12222 BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0x13);
12223 BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x1);
12224 }
12225 BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0x7d);
12226 for (i = 0; i < 10000; i++) {
12227 if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12228 break;
12229 DELAY(1000);
12230 }
12231 if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12232 BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, tmp);
12233 BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL1, 0x7e);
12234}
12235
12236static void
12237bwn_phy_lp_rccal_r12(struct bwn_mac *mac)
12238{
12239 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12240 struct bwn_softc *sc = mac->mac_sc;
12241 struct bwn_phy_lp_iq_est ie;
12242 struct bwn_txgain tx_gains;
12243 static const uint32_t pwrtbl[21] = {
12244 0x10000, 0x10557, 0x10e2d, 0x113e0, 0x10f22, 0x0ff64,
12245 0x0eda2, 0x0e5d4, 0x0efd1, 0x0fbe8, 0x0b7b8, 0x04b35,
12246 0x01a5e, 0x00a0b, 0x00444, 0x001fd, 0x000ff, 0x00088,
12247 0x0004c, 0x0002c, 0x0001a,
12248 };
12249 uint32_t npwr, ipwr, sqpwr, tmp;
12250 int loopback, i, j, sum, error;
12251 uint16_t save[7];
12252 uint8_t txo, bbmult, txpctlmode;
12253
12254 error = bwn_phy_lp_switch_channel(mac, 7);
12255 if (error)
12256 device_printf(sc->sc_dev,
12257 "failed to change channel to 7 (%d)\n", error);
12258 txo = (BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40) ? 1 : 0;
12259 bbmult = bwn_phy_lp_get_bbmult(mac);
12260 if (txo)
12261 tx_gains = bwn_phy_lp_get_txgain(mac);
12262
12263 save[0] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_0);
12264 save[1] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_VAL_0);
12265 save[2] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR);
12266 save[3] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVRVAL);
12267 save[4] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2);
12268 save[5] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2_VAL);
12269 save[6] = BWN_PHY_READ(mac, BWN_PHY_LP_PHY_CTL);
12270
12271 bwn_phy_lp_get_txpctlmode(mac);
12272 txpctlmode = plp->plp_txpctlmode;
12273 bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
12274
12275 /* disable CRS */
12276 bwn_phy_lp_set_deaf(mac, 1);
12277 bwn_phy_lp_set_trsw_over(mac, 0, 1);
12278 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffb);
12279 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x4);
12280 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7);
12281 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
12282 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x10);
12283 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12284 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf);
12285 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
12286 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffbf);
12287 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12288 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x7);
12289 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x38);
12290 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f);
12291 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x100);
12292 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfdff);
12293 BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL0, 0);
12294 BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL1, 1);
12295 BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL2, 0x20);
12296 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfbff);
12297 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xf7ff);
12298 BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0);
12299 BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, 0x45af);
12300 BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0x3ff);
12301
12302 loopback = bwn_phy_lp_loopback(mac);
12303 if (loopback == -1)
12304 goto done;
12305 bwn_phy_lp_set_rxgain_idx(mac, loopback);
12306 BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xffbf, 0x40);
12307 BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfff8, 0x1);
12308 BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xffc7, 0x8);
12309 BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f, 0xc0);
12310
12311 tmp = 0;
12312 memset(&ie, 0, sizeof(ie));
12313 for (i = 128; i <= 159; i++) {
12314 BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2, i);
12315 sum = 0;
12316 for (j = 5; j <= 25; j++) {
12317 bwn_phy_lp_ddfs_turnon(mac, 1, 1, j, j, 0);
12318 if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
12319 goto done;
12320 sqpwr = ie.ie_ipwr + ie.ie_qpwr;
12321 ipwr = ((pwrtbl[j - 5] >> 3) + 1) >> 1;
12322 npwr = bwn_phy_lp_roundup(sqpwr, (j == 5) ? sqpwr : 0,
12323 12);
12324 sum += ((ipwr - npwr) * (ipwr - npwr));
12325 if ((i == 128) || (sum < tmp)) {
12326 plp->plp_rccap = i;
12327 tmp = sum;
12328 }
12329 }
12330 }
12331 bwn_phy_lp_ddfs_turnoff(mac);
12332done:
12333 /* restore CRS */
12334 bwn_phy_lp_clear_deaf(mac, 1);
12335 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xff80);
12336 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfc00);
12337
12338 BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_VAL_0, save[1]);
12339 BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, save[0]);
12340 BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVRVAL, save[3]);
12341 BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, save[2]);
12342 BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2_VAL, save[5]);
12343 BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, save[4]);
12344 BWN_PHY_WRITE(mac, BWN_PHY_LP_PHY_CTL, save[6]);
12345
12346 bwn_phy_lp_set_bbmult(mac, bbmult);
12347 if (txo)
12348 bwn_phy_lp_set_txgain(mac, &tx_gains);
12349 bwn_phy_lp_set_txpctlmode(mac, txpctlmode);
12350 if (plp->plp_rccap)
12351 bwn_phy_lp_set_rccap(mac);
12352}
12353
12354static void
12355bwn_phy_lp_set_rccap(struct bwn_mac *mac)
12356{
12357 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12358 uint8_t rc_cap = (plp->plp_rccap & 0x1f) >> 1;
12359
12360 if (mac->mac_phy.rev == 1)
12361 rc_cap = MIN(rc_cap + 5, 15);
12362
12363 BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2,
12364 MAX(plp->plp_rccap - 4, 0x80));
12365 BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, rc_cap | 0x80);
12366 BWN_RF_WRITE(mac, BWN_B2062_S_RXG_CNT16,
12367 ((plp->plp_rccap & 0x1f) >> 2) | 0x80);
12368}
12369
12370static uint32_t
12371bwn_phy_lp_roundup(uint32_t value, uint32_t div, uint8_t pre)
12372{
12373 uint32_t i, q, r;
12374
12375 if (div == 0)
12376 return (0);
12377
12378 for (i = 0, q = value / div, r = value % div; i < pre; i++) {
12379 q <<= 1;
12380 if (r << 1 >= div) {
12381 q++;
12382 r = (r << 1) - div;
12383 }
12384 }
12385 if (r << 1 >= div)
12386 q++;
12387 return (q);
12388}
12389
12390static void
12391bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *mac)
12392{
12393 struct bwn_softc *sc = mac->mac_sc;
12394
12395 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0xff);
12396 DELAY(20);
12397 if (siba_get_chipid(sc->sc_dev) == 0x5354) {
12398 BWN_RF_WRITE(mac, BWN_B2062_N_COM1, 4);
12399 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 4);
12400 } else {
12401 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0);
12402 }
12403 DELAY(5);
12404}
12405
12406static void
12407bwn_phy_lp_b2062_vco_calib(struct bwn_mac *mac)
12408{
12409
12410 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x42);
12411 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x62);
12412 DELAY(200);
12413}
12414
12415static void
12416bwn_phy_lp_b2062_tblinit(struct bwn_mac *mac)
12417{
12418#define FLAG_A 0x01
12419#define FLAG_G 0x02
12420 struct bwn_softc *sc = mac->mac_sc;
12421 struct ifnet *ifp = sc->sc_ifp;
12422 struct ieee80211com *ic = ifp->if_l2com;
12423 static const struct bwn_b206x_rfinit_entry bwn_b2062_init_tab[] = {
12424 { BWN_B2062_N_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12425 { BWN_B2062_N_PDNCTL1, 0x0, 0xca, FLAG_G, },
12426 { BWN_B2062_N_PDNCTL3, 0x0, 0x0, FLAG_A | FLAG_G, },
12427 { BWN_B2062_N_PDNCTL4, 0x15, 0x2a, FLAG_A | FLAG_G, },
12428 { BWN_B2062_N_LGENC, 0xDB, 0xff, FLAG_A, },
12429 { BWN_B2062_N_LGENATUNE0, 0xdd, 0x0, FLAG_A | FLAG_G, },
12430 { BWN_B2062_N_LGENATUNE2, 0xdd, 0x0, FLAG_A | FLAG_G, },
12431 { BWN_B2062_N_LGENATUNE3, 0x77, 0xB5, FLAG_A | FLAG_G, },
12432 { BWN_B2062_N_LGENACTL3, 0x0, 0xff, FLAG_A | FLAG_G, },
12433 { BWN_B2062_N_LGENACTL7, 0x33, 0x33, FLAG_A | FLAG_G, },
12434 { BWN_B2062_N_RXA_CTL1, 0x0, 0x0, FLAG_G, },
12435 { BWN_B2062_N_RXBB_CTL0, 0x82, 0x80, FLAG_A | FLAG_G, },
12436 { BWN_B2062_N_RXBB_GAIN1, 0x4, 0x4, FLAG_A | FLAG_G, },
12437 { BWN_B2062_N_RXBB_GAIN2, 0x0, 0x0, FLAG_A | FLAG_G, },
12438 { BWN_B2062_N_TXCTL4, 0x3, 0x3, FLAG_A | FLAG_G, },
12439 { BWN_B2062_N_TXCTL5, 0x2, 0x2, FLAG_A | FLAG_G, },
12440 { BWN_B2062_N_TX_TUNE, 0x88, 0x1b, FLAG_A | FLAG_G, },
12441 { BWN_B2062_S_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12442 { BWN_B2062_S_PDS_CTL0, 0xff, 0xff, FLAG_A | FLAG_G, },
12443 { BWN_B2062_S_LGENG_CTL0, 0xf8, 0xd8, FLAG_A | FLAG_G, },
12444 { BWN_B2062_S_LGENG_CTL1, 0x3c, 0x24, FLAG_A | FLAG_G, },
12445 { BWN_B2062_S_LGENG_CTL8, 0x88, 0x80, FLAG_A | FLAG_G, },
12446 { BWN_B2062_S_LGENG_CTL10, 0x88, 0x80, FLAG_A | FLAG_G, },
12447 { BWN_B2062_S_RFPLLCTL0, 0x98, 0x98, FLAG_A | FLAG_G, },
12448 { BWN_B2062_S_RFPLLCTL1, 0x10, 0x10, FLAG_A | FLAG_G, },
12449 { BWN_B2062_S_RFPLLCTL5, 0x43, 0x43, FLAG_A | FLAG_G, },
12450 { BWN_B2062_S_RFPLLCTL6, 0x47, 0x47, FLAG_A | FLAG_G, },
12451 { BWN_B2062_S_RFPLLCTL7, 0xc, 0xc, FLAG_A | FLAG_G, },
12452 { BWN_B2062_S_RFPLLCTL8, 0x11, 0x11, FLAG_A | FLAG_G, },
12453 { BWN_B2062_S_RFPLLCTL9, 0x11, 0x11, FLAG_A | FLAG_G, },
12454 { BWN_B2062_S_RFPLLCTL10, 0xe, 0xe, FLAG_A | FLAG_G, },
12455 { BWN_B2062_S_RFPLLCTL11, 0x8, 0x8, FLAG_A | FLAG_G, },
12456 { BWN_B2062_S_RFPLLCTL12, 0x33, 0x33, FLAG_A | FLAG_G, },
12457 { BWN_B2062_S_RFPLLCTL13, 0xa, 0xa, FLAG_A | FLAG_G, },
12458 { BWN_B2062_S_RFPLLCTL14, 0x6, 0x6, FLAG_A | FLAG_G, },
12459 { BWN_B2062_S_RFPLLCTL18, 0x3e, 0x3e, FLAG_A | FLAG_G, },
12460 { BWN_B2062_S_RFPLLCTL19, 0x13, 0x13, FLAG_A | FLAG_G, },
12461 { BWN_B2062_S_RFPLLCTL21, 0x62, 0x62, FLAG_A | FLAG_G, },
12462 { BWN_B2062_S_RFPLLCTL22, 0x7, 0x7, FLAG_A | FLAG_G, },
12463 { BWN_B2062_S_RFPLLCTL23, 0x16, 0x16, FLAG_A | FLAG_G, },
12464 { BWN_B2062_S_RFPLLCTL24, 0x5c, 0x5c, FLAG_A | FLAG_G, },
12465 { BWN_B2062_S_RFPLLCTL25, 0x95, 0x95, FLAG_A | FLAG_G, },
12466 { BWN_B2062_S_RFPLLCTL30, 0xa0, 0xa0, FLAG_A | FLAG_G, },
12467 { BWN_B2062_S_RFPLLCTL31, 0x4, 0x4, FLAG_A | FLAG_G, },
12468 { BWN_B2062_S_RFPLLCTL33, 0xcc, 0xcc, FLAG_A | FLAG_G, },
12469 { BWN_B2062_S_RFPLLCTL34, 0x7, 0x7, FLAG_A | FLAG_G, },
12470 { BWN_B2062_S_RXG_CNT8, 0xf, 0xf, FLAG_A, },
12471 };
12472 const struct bwn_b206x_rfinit_entry *br;
12473 unsigned int i;
12474
12475 for (i = 0; i < N(bwn_b2062_init_tab); i++) {
12476 br = &bwn_b2062_init_tab[i];
12477 if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12478 if (br->br_flags & FLAG_G)
12479 BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12480 } else {
12481 if (br->br_flags & FLAG_A)
12482 BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12483 }
12484 }
12485#undef FLAG_A
12486#undef FLAG_B
12487}
12488
12489static void
12490bwn_phy_lp_b2063_tblinit(struct bwn_mac *mac)
12491{
12492#define FLAG_A 0x01
12493#define FLAG_G 0x02
12494 struct bwn_softc *sc = mac->mac_sc;
12495 struct ifnet *ifp = sc->sc_ifp;
12496 struct ieee80211com *ic = ifp->if_l2com;
12497 static const struct bwn_b206x_rfinit_entry bwn_b2063_init_tab[] = {
12498 { BWN_B2063_COM1, 0x0, 0x0, FLAG_G, },
12499 { BWN_B2063_COM10, 0x1, 0x0, FLAG_A, },
12500 { BWN_B2063_COM16, 0x0, 0x0, FLAG_G, },
12501 { BWN_B2063_COM17, 0x0, 0x0, FLAG_G, },
12502 { BWN_B2063_COM18, 0x0, 0x0, FLAG_G, },
12503 { BWN_B2063_COM19, 0x0, 0x0, FLAG_G, },
12504 { BWN_B2063_COM20, 0x0, 0x0, FLAG_G, },
12505 { BWN_B2063_COM21, 0x0, 0x0, FLAG_G, },
12506 { BWN_B2063_COM22, 0x0, 0x0, FLAG_G, },
12507 { BWN_B2063_COM23, 0x0, 0x0, FLAG_G, },
12508 { BWN_B2063_COM24, 0x0, 0x0, FLAG_G, },
12509 { BWN_B2063_LOGEN_SP1, 0xe8, 0xd4, FLAG_A | FLAG_G, },
12510 { BWN_B2063_LOGEN_SP2, 0xa7, 0x53, FLAG_A | FLAG_G, },
12511 { BWN_B2063_LOGEN_SP4, 0xf0, 0xf, FLAG_A | FLAG_G, },
12512 { BWN_B2063_G_RX_SP1, 0x1f, 0x5e, FLAG_G, },
12513 { BWN_B2063_G_RX_SP2, 0x7f, 0x7e, FLAG_G, },
12514 { BWN_B2063_G_RX_SP3, 0x30, 0xf0, FLAG_G, },
12515 { BWN_B2063_G_RX_SP7, 0x7f, 0x7f, FLAG_A | FLAG_G, },
12516 { BWN_B2063_G_RX_SP10, 0xc, 0xc, FLAG_A | FLAG_G, },
12517 { BWN_B2063_A_RX_SP1, 0x3c, 0x3f, FLAG_A, },
12518 { BWN_B2063_A_RX_SP2, 0xfc, 0xfe, FLAG_A, },
12519 { BWN_B2063_A_RX_SP7, 0x8, 0x8, FLAG_A | FLAG_G, },
12520 { BWN_B2063_RX_BB_SP4, 0x60, 0x60, FLAG_A | FLAG_G, },
12521 { BWN_B2063_RX_BB_SP8, 0x30, 0x30, FLAG_A | FLAG_G, },
12522 { BWN_B2063_TX_RF_SP3, 0xc, 0xb, FLAG_A | FLAG_G, },
12523 { BWN_B2063_TX_RF_SP4, 0x10, 0xf, FLAG_A | FLAG_G, },
12524 { BWN_B2063_PA_SP1, 0x3d, 0xfd, FLAG_A | FLAG_G, },
12525 { BWN_B2063_TX_BB_SP1, 0x2, 0x2, FLAG_A | FLAG_G, },
12526 { BWN_B2063_BANDGAP_CTL1, 0x56, 0x56, FLAG_A | FLAG_G, },
12527 { BWN_B2063_JTAG_VCO2, 0xF7, 0xF7, FLAG_A | FLAG_G, },
12528 { BWN_B2063_G_RX_MIX3, 0x71, 0x71, FLAG_A | FLAG_G, },
12529 { BWN_B2063_G_RX_MIX4, 0x71, 0x71, FLAG_A | FLAG_G, },
12530 { BWN_B2063_A_RX_1ST2, 0xf0, 0x30, FLAG_A, },
12531 { BWN_B2063_A_RX_PS6, 0x77, 0x77, FLAG_A | FLAG_G, },
12532 { BWN_B2063_A_RX_MIX4, 0x3, 0x3, FLAG_A | FLAG_G, },
12533 { BWN_B2063_A_RX_MIX5, 0xf, 0xf, FLAG_A | FLAG_G, },
12534 { BWN_B2063_A_RX_MIX6, 0xf, 0xf, FLAG_A | FLAG_G, },
12535 { BWN_B2063_RX_TIA_CTL1, 0x77, 0x77, FLAG_A | FLAG_G, },
12536 { BWN_B2063_RX_TIA_CTL3, 0x77, 0x77, FLAG_A | FLAG_G, },
12537 { BWN_B2063_RX_BB_CTL2, 0x4, 0x4, FLAG_A | FLAG_G, },
12538 { BWN_B2063_PA_CTL1, 0x0, 0x4, FLAG_A, },
12539 { BWN_B2063_VREG_CTL1, 0x3, 0x3, FLAG_A | FLAG_G, },
12540 };
12541 const struct bwn_b206x_rfinit_entry *br;
12542 unsigned int i;
12543
12544 for (i = 0; i < N(bwn_b2063_init_tab); i++) {
12545 br = &bwn_b2063_init_tab[i];
12546 if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12547 if (br->br_flags & FLAG_G)
12548 BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12549 } else {
12550 if (br->br_flags & FLAG_A)
12551 BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12552 }
12553 }
12554#undef FLAG_A
12555#undef FLAG_B
12556}
12557
12558static void
12559bwn_tab_read_multi(struct bwn_mac *mac, uint32_t typenoffset,
12560 int count, void *_data)
12561{
12562 unsigned int i;
12563 uint32_t offset, type;
12564 uint8_t *data = _data;
12565
12566 type = BWN_TAB_GETTYPE(typenoffset);
12567 offset = BWN_TAB_GETOFFSET(typenoffset);
12568 KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12569
12570 BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12571
12572 for (i = 0; i < count; i++) {
12573 switch (type) {
12574 case BWN_TAB_8BIT:
12575 *data = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
12576 data++;
12577 break;
12578 case BWN_TAB_16BIT:
12579 *((uint16_t *)data) = BWN_PHY_READ(mac,
12580 BWN_PHY_TABLEDATALO);
12581 data += 2;
12582 break;
12583 case BWN_TAB_32BIT:
12584 *((uint32_t *)data) = BWN_PHY_READ(mac,
12585 BWN_PHY_TABLEDATAHI);
12586 *((uint32_t *)data) <<= 16;
12587 *((uint32_t *)data) |= BWN_PHY_READ(mac,
12588 BWN_PHY_TABLEDATALO);
12589 data += 4;
12590 break;
12591 default:
12592 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12593 }
12594 }
12595}
12596
12597static void
12598bwn_tab_write_multi(struct bwn_mac *mac, uint32_t typenoffset,
12599 int count, const void *_data)
12600{
12601 uint32_t offset, type, value;
12602 const uint8_t *data = _data;
12603 unsigned int i;
12604
12605 type = BWN_TAB_GETTYPE(typenoffset);
12606 offset = BWN_TAB_GETOFFSET(typenoffset);
12607 KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12608
12609 BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12610
12611 for (i = 0; i < count; i++) {
12612 switch (type) {
12613 case BWN_TAB_8BIT:
12614 value = *data;
12615 data++;
12616 KASSERT(!(value & ~0xff),
12617 ("%s:%d: fail", __func__, __LINE__));
12618 BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12619 break;
12620 case BWN_TAB_16BIT:
12621 value = *((const uint16_t *)data);
12622 data += 2;
12623 KASSERT(!(value & ~0xffff),
12624 ("%s:%d: fail", __func__, __LINE__));
12625 BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12626 break;
12627 case BWN_TAB_32BIT:
12628 value = *((const uint32_t *)data);
12629 data += 4;
12630 BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
12631 BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12632 break;
12633 default:
12634 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12635 }
12636 }
12637}
12638
12639static struct bwn_txgain
12640bwn_phy_lp_get_txgain(struct bwn_mac *mac)
12641{
12642 struct bwn_txgain tg;
12643 uint16_t tmp;
12644
12645 tg.tg_dac = (BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0x380) >> 7;
12646 if (mac->mac_phy.rev < 2) {
12647 tmp = BWN_PHY_READ(mac,
12648 BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL) & 0x7ff;
12649 tg.tg_gm = tmp & 0x0007;
12650 tg.tg_pga = (tmp & 0x0078) >> 3;
12651 tg.tg_pad = (tmp & 0x780) >> 7;
12652 return (tg);
12653 }
12654
12655 tmp = BWN_PHY_READ(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL);
12656 tg.tg_pad = BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0xff;
12657 tg.tg_gm = tmp & 0xff;
12658 tg.tg_pga = (tmp >> 8) & 0xff;
12659 return (tg);
12660}
12661
12662static uint8_t
12663bwn_phy_lp_get_bbmult(struct bwn_mac *mac)
12664{
12665
12666 return (bwn_tab_read(mac, BWN_TAB_2(0, 87)) & 0xff00) >> 8;
12667}
12668
12669static void
12670bwn_phy_lp_set_txgain(struct bwn_mac *mac, struct bwn_txgain *tg)
12671{
12672 uint16_t pa;
12673
12674 if (mac->mac_phy.rev < 2) {
12675 BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0xf800,
12676 (tg->tg_pad << 7) | (tg->tg_pga << 3) | tg->tg_gm);
12677 bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12678 bwn_phy_lp_set_txgain_override(mac);
12679 return;
12680 }
12681
12682 pa = bwn_phy_lp_get_pa_gain(mac);
12683 BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
12684 (tg->tg_pga << 8) | tg->tg_gm);
12685 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0x8000,
12686 tg->tg_pad | (pa << 6));
12687 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xfc), (tg->tg_pga << 8) | tg->tg_gm);
12688 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x8000,
12689 tg->tg_pad | (pa << 8));
12690 bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12691 bwn_phy_lp_set_txgain_override(mac);
12692}
12693
12694static void
12695bwn_phy_lp_set_bbmult(struct bwn_mac *mac, uint8_t bbmult)
12696{
12697
12698 bwn_tab_write(mac, BWN_TAB_2(0, 87), (uint16_t)bbmult << 8);
12699}
12700
12701static void
12702bwn_phy_lp_set_trsw_over(struct bwn_mac *mac, uint8_t tx, uint8_t rx)
12703{
12704 uint16_t trsw = (tx << 1) | rx;
12705
12706 BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffc, trsw);
12707 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x3);
12708}
12709
12710static void
12711bwn_phy_lp_set_rxgain(struct bwn_mac *mac, uint32_t gain)
12712{
12713 struct bwn_softc *sc = mac->mac_sc;
12714 struct ifnet *ifp = sc->sc_ifp;
12715 struct ieee80211com *ic = ifp->if_l2com;
12716 uint16_t ext_lna, high_gain, lna, low_gain, trsw, tmp;
12717
12718 if (mac->mac_phy.rev < 2) {
12719 trsw = gain & 0x1;
12720 lna = (gain & 0xfffc) | ((gain & 0xc) >> 2);
12721 ext_lna = (gain & 2) >> 1;
12722
12723 BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12724 BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12725 0xfbff, ext_lna << 10);
12726 BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12727 0xf7ff, ext_lna << 11);
12728 BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, lna);
12729 } else {
12730 low_gain = gain & 0xffff;
12731 high_gain = (gain >> 16) & 0xf;
12732 ext_lna = (gain >> 21) & 0x1;
12733 trsw = ~(gain >> 20) & 0x1;
12734
12735 BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12736 BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12737 0xfdff, ext_lna << 9);
12738 BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12739 0xfbff, ext_lna << 10);
12740 BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, low_gain);
12741 BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff0, high_gain);
12742 if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12743 tmp = (gain >> 2) & 0x3;
12744 BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12745 0xe7ff, tmp<<11);
12746 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe6), 0xffe7,
12747 tmp << 3);
12748 }
12749 }
12750
12751 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1);
12752 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12753 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12754 if (mac->mac_phy.rev >= 2) {
12755 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
12756 if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12757 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x400);
12758 BWN_PHY_SET(mac, BWN_PHY_OFDM(0xe5), 0x8);
12759 }
12760 return;
12761 }
12762 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x200);
12763}
12764
12765static void
12766bwn_phy_lp_set_deaf(struct bwn_mac *mac, uint8_t user)
12767{
12768 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12769
12770 if (user)
12771 plp->plp_crsusr_off = 1;
12772 else
12773 plp->plp_crssys_off = 1;
12774
12775 BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x80);
12776}
12777
12778static void
12779bwn_phy_lp_clear_deaf(struct bwn_mac *mac, uint8_t user)
12780{
12781 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12782 struct bwn_softc *sc = mac->mac_sc;
12783 struct ifnet *ifp = sc->sc_ifp;
12784 struct ieee80211com *ic = ifp->if_l2com;
12785
12786 if (user)
12787 plp->plp_crsusr_off = 0;
12788 else
12789 plp->plp_crssys_off = 0;
12790
12791 if (plp->plp_crsusr_off || plp->plp_crssys_off)
12792 return;
12793
12794 if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12795 BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x60);
12796 else
12797 BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x20);
12798}
12799
12800static unsigned int
12801bwn_sqrt(struct bwn_mac *mac, unsigned int x)
12802{
12803 /* Table holding (10 * sqrt(x)) for x between 1 and 256. */
12804 static uint8_t sqrt_table[256] = {
12805 10, 14, 17, 20, 22, 24, 26, 28,
12806 30, 31, 33, 34, 36, 37, 38, 40,
12807 41, 42, 43, 44, 45, 46, 47, 48,
12808 50, 50, 51, 52, 53, 54, 55, 56,
12809 57, 58, 59, 60, 60, 61, 62, 63,
12810 64, 64, 65, 66, 67, 67, 68, 69,
12811 70, 70, 71, 72, 72, 73, 74, 74,
12812 75, 76, 76, 77, 78, 78, 79, 80,
12813 80, 81, 81, 82, 83, 83, 84, 84,
12814 85, 86, 86, 87, 87, 88, 88, 89,
12815 90, 90, 91, 91, 92, 92, 93, 93,
12816 94, 94, 95, 95, 96, 96, 97, 97,
12817 98, 98, 99, 100, 100, 100, 101, 101,
12818 102, 102, 103, 103, 104, 104, 105, 105,
12819 106, 106, 107, 107, 108, 108, 109, 109,
12820 110, 110, 110, 111, 111, 112, 112, 113,
12821 113, 114, 114, 114, 115, 115, 116, 116,
12822 117, 117, 117, 118, 118, 119, 119, 120,
12823 120, 120, 121, 121, 122, 122, 122, 123,
12824 123, 124, 124, 124, 125, 125, 126, 126,
12825 126, 127, 127, 128, 128, 128, 129, 129,
12826 130, 130, 130, 131, 131, 131, 132, 132,
12827 133, 133, 133, 134, 134, 134, 135, 135,
12828 136, 136, 136, 137, 137, 137, 138, 138,
12829 138, 139, 139, 140, 140, 140, 141, 141,
12830 141, 142, 142, 142, 143, 143, 143, 144,
12831 144, 144, 145, 145, 145, 146, 146, 146,
12832 147, 147, 147, 148, 148, 148, 149, 149,
12833 150, 150, 150, 150, 151, 151, 151, 152,
12834 152, 152, 153, 153, 153, 154, 154, 154,
12835 155, 155, 155, 156, 156, 156, 157, 157,
12836 157, 158, 158, 158, 159, 159, 159, 160
12837 };
12838
12839 if (x == 0)
12840 return (0);
12841 if (x >= 256) {
12842 unsigned int tmp;
12843
12844 for (tmp = 0; x >= (2 * tmp) + 1; x -= (2 * tmp++) + 1)
12845 /* do nothing */ ;
12846 return (tmp);
12847 }
12848 return (sqrt_table[x - 1] / 10);
12849}
12850
12851static int
12852bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *mac, uint16_t sample)
12853{
12854#define CALC_COEFF(_v, _x, _y, _z) do { \
12855 int _t; \
12856 _t = _x - 20; \
12857 if (_t >= 0) { \
12858 _v = ((_y << (30 - _x)) + (_z >> (1 + _t))) / (_z >> _t); \
12859 } else { \
12860 _v = ((_y << (30 - _x)) + (_z << (-1 - _t))) / (_z << -_t); \
12861 } \
12862} while (0)
12863#define CALC_COEFF2(_v, _x, _y, _z) do { \
12864 int _t; \
12865 _t = _x - 11; \
12866 if (_t >= 0) \
12867 tmp[3] = (_y << (31 - _x)) / (_z >> _t); \
12868 else \
12869 tmp[3] = (_y << (31 - _x)) / (_z << -_t); \
12870} while (0)
12871 struct bwn_phy_lp_iq_est ie;
12872 uint16_t v0, v1;
12873 int tmp[2], ret;
12874
12875 v1 = BWN_PHY_READ(mac, BWN_PHY_RX_COMP_COEFF_S);
12876 v0 = v1 >> 8;
12877 v1 |= 0xff;
12878
12879 BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, 0x00c0);
12880 BWN_PHY_MASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff);
12881
12882 ret = bwn_phy_lp_rx_iq_est(mac, sample, 32, &ie);
12883 if (ret == 0)
12884 goto done;
12885
12886 if (ie.ie_ipwr + ie.ie_qpwr < 2) {
12887 ret = 0;
12888 goto done;
12889 }
12890
12891 CALC_COEFF(tmp[0], bwn_nbits(ie.ie_iqprod), ie.ie_iqprod, ie.ie_ipwr);
12892 CALC_COEFF2(tmp[1], bwn_nbits(ie.ie_qpwr), ie.ie_qpwr, ie.ie_ipwr);
12893
12894 tmp[1] = -bwn_sqrt(mac, tmp[1] - (tmp[0] * tmp[0]));
12895 v0 = tmp[0] >> 3;
12896 v1 = tmp[1] >> 4;
12897done:
12898 BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, v1);
12899 BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, v0 << 8);
12900 return ret;
12901#undef CALC_COEFF
12902#undef CALC_COEFF2
12903}
12904
12905static void
12906bwn_phy_lp_tblinit_r01(struct bwn_mac *mac)
12907{
12908 static const uint16_t noisescale[] = {
12909 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12910 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa400, 0xa4a4, 0xa4a4,
12911 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12912 0xa4a4, 0xa4a4, 0x00a4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12913 0x0000, 0x0000, 0x4c00, 0x2d36, 0x0000, 0x0000, 0x4c00, 0x2d36,
12914 };
12915 static const uint16_t crsgainnft[] = {
12916 0x0366, 0x036a, 0x036f, 0x0364, 0x0367, 0x036d, 0x0374, 0x037f,
12917 0x036f, 0x037b, 0x038a, 0x0378, 0x0367, 0x036d, 0x0375, 0x0381,
12918 0x0374, 0x0381, 0x0392, 0x03a9, 0x03c4, 0x03e1, 0x0001, 0x001f,
12919 0x0040, 0x005e, 0x007f, 0x009e, 0x00bd, 0x00dd, 0x00fd, 0x011d,
12920 0x013d,
12921 };
12922 static const uint16_t filterctl[] = {
12923 0xa0fc, 0x10fc, 0x10db, 0x20b7, 0xff93, 0x10bf, 0x109b, 0x2077,
12924 0xff53, 0x0127,
12925 };
12926 static const uint32_t psctl[] = {
12927 0x00010000, 0x000000a0, 0x00040000, 0x00000048, 0x08080101,
12928 0x00000080, 0x08080101, 0x00000040, 0x08080101, 0x000000c0,
12929 0x08a81501, 0x000000c0, 0x0fe8fd01, 0x000000c0, 0x08300105,
12930 0x000000c0, 0x08080201, 0x000000c0, 0x08280205, 0x000000c0,
12931 0xe80802fe, 0x000000c7, 0x28080206, 0x000000c0, 0x08080202,
12932 0x000000c0, 0x0ba87602, 0x000000c0, 0x1068013d, 0x000000c0,
12933 0x10280105, 0x000000c0, 0x08880102, 0x000000c0, 0x08280106,
12934 0x000000c0, 0xe80801fd, 0x000000c7, 0xa8080115, 0x000000c0,
12935 };
12936 static const uint16_t ofdmcckgain_r0[] = {
12937 0x0001, 0x0001, 0x0001, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12938 0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12939 0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12940 0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12941 0x755d,
12942 };
12943 static const uint16_t ofdmcckgain_r1[] = {
12944 0x5000, 0x6000, 0x7000, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12945 0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12946 0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12947 0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12948 0x755d,
12949 };
12950 static const uint16_t gaindelta[] = {
12951 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12952 0x0000,
12953 };
12954 static const uint32_t txpwrctl[] = {
12955 0x00000050, 0x0000004f, 0x0000004e, 0x0000004d, 0x0000004c,
12956 0x0000004b, 0x0000004a, 0x00000049, 0x00000048, 0x00000047,
12957 0x00000046, 0x00000045, 0x00000044, 0x00000043, 0x00000042,
12958 0x00000041, 0x00000040, 0x0000003f, 0x0000003e, 0x0000003d,
12959 0x0000003c, 0x0000003b, 0x0000003a, 0x00000039, 0x00000038,
12960 0x00000037, 0x00000036, 0x00000035, 0x00000034, 0x00000033,
12961 0x00000032, 0x00000031, 0x00000030, 0x0000002f, 0x0000002e,
12962 0x0000002d, 0x0000002c, 0x0000002b, 0x0000002a, 0x00000029,
12963 0x00000028, 0x00000027, 0x00000026, 0x00000025, 0x00000024,
12964 0x00000023, 0x00000022, 0x00000021, 0x00000020, 0x0000001f,
12965 0x0000001e, 0x0000001d, 0x0000001c, 0x0000001b, 0x0000001a,
12966 0x00000019, 0x00000018, 0x00000017, 0x00000016, 0x00000015,
12967 0x00000014, 0x00000013, 0x00000012, 0x00000011, 0x00000000,
12968 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12969 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12970 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12971 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12972 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12973 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12974 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12975 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12976 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12977 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12978 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12979 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12980 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12981 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12982 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12983 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12984 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12985 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12986 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12987 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12988 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12989 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12990 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12991 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12992 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12993 0x00000000, 0x00000000, 0x000075a0, 0x000075a0, 0x000075a1,
12994 0x000075a1, 0x000075a2, 0x000075a2, 0x000075a3, 0x000075a3,
12995 0x000074b0, 0x000074b0, 0x000074b1, 0x000074b1, 0x000074b2,
12996 0x000074b2, 0x000074b3, 0x000074b3, 0x00006d20, 0x00006d20,
12997 0x00006d21, 0x00006d21, 0x00006d22, 0x00006d22, 0x00006d23,
12998 0x00006d23, 0x00004660, 0x00004660, 0x00004661, 0x00004661,
12999 0x00004662, 0x00004662, 0x00004663, 0x00004663, 0x00003e60,
13000 0x00003e60, 0x00003e61, 0x00003e61, 0x00003e62, 0x00003e62,
13001 0x00003e63, 0x00003e63, 0x00003660, 0x00003660, 0x00003661,
13002 0x00003661, 0x00003662, 0x00003662, 0x00003663, 0x00003663,
13003 0x00002e60, 0x00002e60, 0x00002e61, 0x00002e61, 0x00002e62,
13004 0x00002e62, 0x00002e63, 0x00002e63, 0x00002660, 0x00002660,
13005 0x00002661, 0x00002661, 0x00002662, 0x00002662, 0x00002663,
13006 0x00002663, 0x000025e0, 0x000025e0, 0x000025e1, 0x000025e1,
13007 0x000025e2, 0x000025e2, 0x000025e3, 0x000025e3, 0x00001de0,
13008 0x00001de0, 0x00001de1, 0x00001de1, 0x00001de2, 0x00001de2,
13009 0x00001de3, 0x00001de3, 0x00001d60, 0x00001d60, 0x00001d61,
13010 0x00001d61, 0x00001d62, 0x00001d62, 0x00001d63, 0x00001d63,
13011 0x00001560, 0x00001560, 0x00001561, 0x00001561, 0x00001562,
13012 0x00001562, 0x00001563, 0x00001563, 0x00000d60, 0x00000d60,
13013 0x00000d61, 0x00000d61, 0x00000d62, 0x00000d62, 0x00000d63,
13014 0x00000d63, 0x00000ce0, 0x00000ce0, 0x00000ce1, 0x00000ce1,
13015 0x00000ce2, 0x00000ce2, 0x00000ce3, 0x00000ce3, 0x00000e10,
13016 0x00000e10, 0x00000e11, 0x00000e11, 0x00000e12, 0x00000e12,
13017 0x00000e13, 0x00000e13, 0x00000bf0, 0x00000bf0, 0x00000bf1,
13018 0x00000bf1, 0x00000bf2, 0x00000bf2, 0x00000bf3, 0x00000bf3,
13019 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13020 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13021 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13022 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13023 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13024 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13025 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13026 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13027 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13028 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13029 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13030 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13031 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13032 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13033 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13034 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13035 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13036 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13037 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13038 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13039 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13040 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13041 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13042 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13043 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13044 0x04000000, 0x04200000, 0x04000000, 0x000000ff, 0x000002fc,
13045 0x0000fa08, 0x00000305, 0x00000206, 0x00000304, 0x0000fb04,
13046 0x0000fcff, 0x000005fb, 0x0000fd01, 0x00000401, 0x00000006,
13047 0x0000ff03, 0x000007fc, 0x0000fc08, 0x00000203, 0x0000fffb,
13048 0x00000600, 0x0000fa01, 0x0000fc03, 0x0000fe06, 0x0000fe00,
13049 0x00000102, 0x000007fd, 0x000004fb, 0x000006ff, 0x000004fd,
13050 0x0000fdfa, 0x000007fb, 0x0000fdfa, 0x0000fa06, 0x00000500,
13051 0x0000f902, 0x000007fa, 0x0000fafa, 0x00000500, 0x000007fa,
13052 0x00000700, 0x00000305, 0x000004ff, 0x00000801, 0x00000503,
13053 0x000005f9, 0x00000404, 0x0000fb08, 0x000005fd, 0x00000501,
13054 0x00000405, 0x0000fb03, 0x000007fc, 0x00000403, 0x00000303,
13055 0x00000402, 0x0000faff, 0x0000fe05, 0x000005fd, 0x0000fe01,
13056 0x000007fa, 0x00000202, 0x00000504, 0x00000102, 0x000008fe,
13057 0x0000fa04, 0x0000fafc, 0x0000fe08, 0x000000f9, 0x000002fa,
13058 0x000003fe, 0x00000304, 0x000004f9, 0x00000100, 0x0000fd06,
13059 0x000008fc, 0x00000701, 0x00000504, 0x0000fdfe, 0x0000fdfc,
13060 0x000003fe, 0x00000704, 0x000002fc, 0x000004f9, 0x0000fdfd,
13061 0x0000fa07, 0x00000205, 0x000003fd, 0x000005fb, 0x000004f9,
13062 0x00000804, 0x0000fc06, 0x0000fcf9, 0x00000100, 0x0000fe05,
13063 0x00000408, 0x0000fb02, 0x00000304, 0x000006fe, 0x000004fa,
13064 0x00000305, 0x000008fc, 0x00000102, 0x000001fd, 0x000004fc,
13065 0x0000fe03, 0x00000701, 0x000001fb, 0x000001f9, 0x00000206,
13066 0x000006fd, 0x00000508, 0x00000700, 0x00000304, 0x000005fe,
13067 0x000005ff, 0x0000fa04, 0x00000303, 0x0000fefb, 0x000007f9,
13068 0x0000fefc, 0x000004fd, 0x000005fc, 0x0000fffd, 0x0000fc08,
13069 0x0000fbf9, 0x0000fd07, 0x000008fb, 0x0000fe02, 0x000006fb,
13070 0x00000702,
13071 };
13072
13073 KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13074
13075 bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13076 bwn_tab_sigsq_tbl);
13077 bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13078 bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(crsgainnft), crsgainnft);
13079 bwn_tab_write_multi(mac, BWN_TAB_2(8, 0), N(filterctl), filterctl);
13080 bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(psctl), psctl);
13081 bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13082 bwn_tab_pllfrac_tbl);
13083 bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13084 bwn_tabl_iqlocal_tbl);
13085 if (mac->mac_phy.rev == 0) {
13086 bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r0),
13087 ofdmcckgain_r0);
13088 bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r0),
13089 ofdmcckgain_r0);
13090 } else {
13091 bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r1),
13092 ofdmcckgain_r1);
13093 bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r1),
13094 ofdmcckgain_r1);
13095 }
13096 bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(gaindelta), gaindelta);
13097 bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(txpwrctl), txpwrctl);
13098}
13099
13100static void
13101bwn_phy_lp_tblinit_r2(struct bwn_mac *mac)
13102{
13103 struct bwn_softc *sc = mac->mac_sc;
13104 int i;
13105 static const uint16_t noisescale[] = {
13106 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13107 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13108 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13109 0x00a4, 0x00a4, 0x0000, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13110 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13111 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13112 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4
13113 };
13114 static const uint32_t filterctl[] = {
13115 0x000141fc, 0x000021fc, 0x000021b7, 0x0000416f, 0x0001ff27,
13116 0x0000217f, 0x00002137, 0x000040ef, 0x0001fea7, 0x0000024f
13117 };
13118 static const uint32_t psctl[] = {
13119 0x00e38e08, 0x00e08e38, 0x00000000, 0x00000000, 0x00000000,
13120 0x00002080, 0x00006180, 0x00003002, 0x00000040, 0x00002042,
13121 0x00180047, 0x00080043, 0x00000041, 0x000020c1, 0x00046006,
13122 0x00042002, 0x00040000, 0x00002003, 0x00180006, 0x00080002
13123 };
13124 static const uint32_t gainidx[] = {
13125 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13126 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13127 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13128 0x00000000, 0x00000000, 0x00000000, 0x10000001, 0x00000000,
13129 0x20000082, 0x00000000, 0x40000104, 0x00000000, 0x60004207,
13130 0x00000001, 0x7000838a, 0x00000001, 0xd021050d, 0x00000001,
13131 0xe041c683, 0x00000001, 0x50828805, 0x00000000, 0x80e34288,
13132 0x00000000, 0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000,
13133 0x12064711, 0x00000001, 0xb0a18612, 0x00000010, 0xe1024794,
13134 0x00000010, 0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011,
13135 0xc1848a9c, 0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21,
13136 0x00000019, 0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019,
13137 0xb36811a6, 0x00000019, 0xf3e89227, 0x00000019, 0x0408d329,
13138 0x0000001a, 0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a,
13139 0x54aa152c, 0x0000001a, 0x64ca55ad, 0x0000001a, 0x00000000,
13140 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13141 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13142 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13143 0x00000000, 0x00000000, 0x10000001, 0x00000000, 0x20000082,
13144 0x00000000, 0x40000104, 0x00000000, 0x60004207, 0x00000001,
13145 0x7000838a, 0x00000001, 0xd021050d, 0x00000001, 0xe041c683,
13146 0x00000001, 0x50828805, 0x00000000, 0x80e34288, 0x00000000,
13147 0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000, 0x12064711,
13148 0x00000001, 0xb0a18612, 0x00000010, 0xe1024794, 0x00000010,
13149 0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011, 0xc1848a9c,
13150 0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21, 0x00000019,
13151 0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019, 0xb36811a6,
13152 0x00000019, 0xf3e89227, 0x00000019, 0x0408d329, 0x0000001a,
13153 0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a, 0x54aa152c,
13154 0x0000001a, 0x64ca55ad, 0x0000001a
13155 };
13156 static const uint16_t auxgainidx[] = {
13157 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13158 0x0000, 0x0001, 0x0002, 0x0004, 0x0016, 0x0000, 0x0000, 0x0000,
13159 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002,
13160 0x0004, 0x0016
13161 };
13162 static const uint16_t swctl[] = {
13163 0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13164 0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13165 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
13166 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018,
13167 0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13168 0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13169 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
13170 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018
13171 };
13172 static const uint8_t hf[] = {
13173 0x4b, 0x36, 0x24, 0x18, 0x49, 0x34, 0x23, 0x17, 0x48,
13174 0x33, 0x23, 0x17, 0x48, 0x33, 0x23, 0x17
13175 };
13176 static const uint32_t gainval[] = {
13177 0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13178 0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13179 0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13180 0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13181 0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13182 0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13183 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13184 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13185 0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13186 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13187 0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13188 0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13189 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000009,
13190 0x000000f1, 0x00000000, 0x00000000
13191 };
13192 static const uint16_t gain[] = {
13193 0x0000, 0x0400, 0x0800, 0x0802, 0x0804, 0x0806, 0x0807, 0x0808,
13194 0x080a, 0x080b, 0x080c, 0x080e, 0x080f, 0x0810, 0x0812, 0x0813,
13195 0x0814, 0x0816, 0x0817, 0x081a, 0x081b, 0x081f, 0x0820, 0x0824,
13196 0x0830, 0x0834, 0x0837, 0x083b, 0x083f, 0x0840, 0x0844, 0x0857,
13197 0x085b, 0x085f, 0x08d7, 0x08db, 0x08df, 0x0957, 0x095b, 0x095f,
13198 0x0b57, 0x0b5b, 0x0b5f, 0x0f5f, 0x135f, 0x175f, 0x0000, 0x0000,
13199 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13200 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13201 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13202 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13203 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13204 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13205 };
13206 static const uint32_t papdeps[] = {
13207 0x00000000, 0x00013ffc, 0x0001dff3, 0x0001bff0, 0x00023fe9,
13208 0x00021fdf, 0x00028fdf, 0x00033fd2, 0x00039fcb, 0x00043fc7,
13209 0x0004efc2, 0x00055fb5, 0x0005cfb0, 0x00063fa8, 0x00068fa3,
13210 0x00071f98, 0x0007ef92, 0x00084f8b, 0x0008df82, 0x00097f77,
13211 0x0009df69, 0x000a3f62, 0x000adf57, 0x000b6f4c, 0x000bff41,
13212 0x000c9f39, 0x000cff30, 0x000dbf27, 0x000e4f1e, 0x000edf16,
13213 0x000f7f13, 0x00102f11, 0x00110f10, 0x0011df11, 0x0012ef15,
13214 0x00143f1c, 0x00158f27, 0x00172f35, 0x00193f47, 0x001baf5f,
13215 0x001e6f7e, 0x0021cfa4, 0x0025bfd2, 0x002a2008, 0x002fb047,
13216 0x00360090, 0x003d40e0, 0x0045c135, 0x004fb189, 0x005ae1d7,
13217 0x0067221d, 0x0075025a, 0x007ff291, 0x007ff2bf, 0x007ff2e3,
13218 0x007ff2ff, 0x007ff315, 0x007ff329, 0x007ff33f, 0x007ff356,
13219 0x007ff36e, 0x007ff39c, 0x007ff441, 0x007ff506
13220 };
13221 static const uint32_t papdmult[] = {
13222 0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13223 0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13224 0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13225 0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13226 0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13227 0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13228 0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13229 0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13230 0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13231 0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13232 0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13233 0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13234 0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13235 };
13236 static const uint32_t gainidx_a0[] = {
13237 0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13238 0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13239 0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13240 0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13241 0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13242 0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13243 0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13244 0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13245 0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13246 0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13247 0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13248 0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13249 0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13250 };
13251 static const uint16_t auxgainidx_a0[] = {
13252 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13253 0x0000, 0x0000, 0x0000, 0x0002, 0x0014, 0x0000, 0x0000, 0x0000,
13254 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13255 0x0002, 0x0014
13256 };
13257 static const uint32_t gainval_a0[] = {
13258 0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13259 0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13260 0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13261 0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13262 0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13263 0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13264 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13265 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13266 0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13267 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13268 0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13269 0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13270 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000f,
13271 0x000000f7, 0x00000000, 0x00000000
13272 };
13273 static const uint16_t gain_a0[] = {
13274 0x0000, 0x0002, 0x0004, 0x0006, 0x0007, 0x0008, 0x000a, 0x000b,
13275 0x000c, 0x000e, 0x000f, 0x0010, 0x0012, 0x0013, 0x0014, 0x0016,
13276 0x0017, 0x001a, 0x001b, 0x001f, 0x0020, 0x0024, 0x0030, 0x0034,
13277 0x0037, 0x003b, 0x003f, 0x0040, 0x0044, 0x0057, 0x005b, 0x005f,
13278 0x00d7, 0x00db, 0x00df, 0x0157, 0x015b, 0x015f, 0x0357, 0x035b,
13279 0x035f, 0x075f, 0x0b5f, 0x0f5f, 0x0000, 0x0000, 0x0000, 0x0000,
13280 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13281 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13282 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13283 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13284 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13285 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13286 };
13287
13288 KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13289
13290 for (i = 0; i < 704; i++)
13291 bwn_tab_write(mac, BWN_TAB_4(7, i), 0);
13292
13293 bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13294 bwn_tab_sigsq_tbl);
13295 bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13296 bwn_tab_write_multi(mac, BWN_TAB_4(11, 0), N(filterctl), filterctl);
13297 bwn_tab_write_multi(mac, BWN_TAB_4(12, 0), N(psctl), psctl);
13298 bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx), gainidx);
13299 bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx), auxgainidx);
13300 bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(swctl), swctl);
13301 bwn_tab_write_multi(mac, BWN_TAB_1(16, 0), N(hf), hf);
13302 bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval), gainval);
13303 bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain), gain);
13304 bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13305 bwn_tab_pllfrac_tbl);
13306 bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13307 bwn_tabl_iqlocal_tbl);
13308 bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(papdeps), papdeps);
13309 bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(papdmult), papdmult);
13310
13311 if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
13312 (siba_get_chiprev(sc->sc_dev) == 0)) {
13313 bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx_a0),
13314 gainidx_a0);
13315 bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx_a0),
13316 auxgainidx_a0);
13317 bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval_a0),
13318 gainval_a0);
13319 bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain_a0), gain_a0);
13320 }
13321}
13322
13323static void
13324bwn_phy_lp_tblinit_txgain(struct bwn_mac *mac)
13325{
13326 struct bwn_softc *sc = mac->mac_sc;
13327 struct ifnet *ifp = sc->sc_ifp;
13328 struct ieee80211com *ic = ifp->if_l2com;
13329 static struct bwn_txgain_entry txgain_r2[] = {
13330 { 255, 255, 203, 0, 152 }, { 255, 255, 203, 0, 147 },
13331 { 255, 255, 203, 0, 143 }, { 255, 255, 203, 0, 139 },
13332 { 255, 255, 203, 0, 135 }, { 255, 255, 203, 0, 131 },
13333 { 255, 255, 203, 0, 128 }, { 255, 255, 203, 0, 124 },
13334 { 255, 255, 203, 0, 121 }, { 255, 255, 203, 0, 117 },
13335 { 255, 255, 203, 0, 114 }, { 255, 255, 203, 0, 111 },
13336 { 255, 255, 203, 0, 107 }, { 255, 255, 203, 0, 104 },
13337 { 255, 255, 203, 0, 101 }, { 255, 255, 203, 0, 99 },
13338 { 255, 255, 203, 0, 96 }, { 255, 255, 203, 0, 93 },
13339 { 255, 255, 203, 0, 90 }, { 255, 255, 203, 0, 88 },
13340 { 255, 255, 203, 0, 85 }, { 255, 255, 203, 0, 83 },
13341 { 255, 255, 203, 0, 81 }, { 255, 255, 203, 0, 78 },
13342 { 255, 255, 203, 0, 76 }, { 255, 255, 203, 0, 74 },
13343 { 255, 255, 203, 0, 72 }, { 255, 255, 203, 0, 70 },
13344 { 255, 255, 203, 0, 68 }, { 255, 255, 203, 0, 66 },
13345 { 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13346 { 255, 255, 192, 0, 64 }, { 255, 255, 186, 0, 64 },
13347 { 255, 255, 181, 0, 64 }, { 255, 255, 176, 0, 64 },
13348 { 255, 255, 171, 0, 64 }, { 255, 255, 166, 0, 64 },
13349 { 255, 255, 161, 0, 64 }, { 255, 255, 157, 0, 64 },
13350 { 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13351 { 255, 255, 144, 0, 64 }, { 255, 255, 140, 0, 64 },
13352 { 255, 255, 136, 0, 64 }, { 255, 255, 132, 0, 64 },
13353 { 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13354 { 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13355 { 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13356 { 255, 255, 108, 0, 64 }, { 255, 255, 105, 0, 64 },
13357 { 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13358 { 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13359 { 255, 255, 91, 0, 64 }, { 255, 255, 88, 0, 64 },
13360 { 255, 255, 86, 0, 64 }, { 255, 255, 83, 0, 64 },
13361 { 255, 255, 81, 0, 64 }, { 255, 255, 79, 0, 64 },
13362 { 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13363 { 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13364 { 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13365 { 255, 255, 64, 0, 64 }, { 255, 248, 64, 0, 64 },
13366 { 255, 248, 62, 0, 64 }, { 255, 241, 62, 0, 64 },
13367 { 255, 241, 60, 0, 64 }, { 255, 234, 60, 0, 64 },
13368 { 255, 234, 59, 0, 64 }, { 255, 227, 59, 0, 64 },
13369 { 255, 227, 57, 0, 64 }, { 255, 221, 57, 0, 64 },
13370 { 255, 221, 55, 0, 64 }, { 255, 215, 55, 0, 64 },
13371 { 255, 215, 54, 0, 64 }, { 255, 208, 54, 0, 64 },
13372 { 255, 208, 52, 0, 64 }, { 255, 203, 52, 0, 64 },
13373 { 255, 203, 51, 0, 64 }, { 255, 197, 51, 0, 64 },
13374 { 255, 197, 49, 0, 64 }, { 255, 191, 49, 0, 64 },
13375 { 255, 191, 48, 0, 64 }, { 255, 186, 48, 0, 64 },
13376 { 255, 186, 47, 0, 64 }, { 255, 181, 47, 0, 64 },
13377 { 255, 181, 45, 0, 64 }, { 255, 175, 45, 0, 64 },
13378 { 255, 175, 44, 0, 64 }, { 255, 170, 44, 0, 64 },
13379 { 255, 170, 43, 0, 64 }, { 255, 166, 43, 0, 64 },
13380 { 255, 166, 42, 0, 64 }, { 255, 161, 42, 0, 64 },
13381 { 255, 161, 40, 0, 64 }, { 255, 156, 40, 0, 64 },
13382 { 255, 156, 39, 0, 64 }, { 255, 152, 39, 0, 64 },
13383 { 255, 152, 38, 0, 64 }, { 255, 148, 38, 0, 64 },
13384 { 255, 148, 37, 0, 64 }, { 255, 143, 37, 0, 64 },
13385 { 255, 143, 36, 0, 64 }, { 255, 139, 36, 0, 64 },
13386 { 255, 139, 35, 0, 64 }, { 255, 135, 35, 0, 64 },
13387 { 255, 135, 34, 0, 64 }, { 255, 132, 34, 0, 64 },
13388 { 255, 132, 33, 0, 64 }, { 255, 128, 33, 0, 64 },
13389 { 255, 128, 32, 0, 64 }, { 255, 124, 32, 0, 64 },
13390 { 255, 124, 31, 0, 64 }, { 255, 121, 31, 0, 64 },
13391 { 255, 121, 30, 0, 64 }, { 255, 117, 30, 0, 64 },
13392 { 255, 117, 29, 0, 64 }, { 255, 114, 29, 0, 64 },
13393 { 255, 114, 29, 0, 64 }, { 255, 111, 29, 0, 64 },
13394 };
13395 static struct bwn_txgain_entry txgain_2ghz_r2[] = {
13396 { 7, 99, 255, 0, 64 }, { 7, 96, 255, 0, 64 },
13397 { 7, 93, 255, 0, 64 }, { 7, 90, 255, 0, 64 },
13398 { 7, 88, 255, 0, 64 }, { 7, 85, 255, 0, 64 },
13399 { 7, 83, 255, 0, 64 }, { 7, 81, 255, 0, 64 },
13400 { 7, 78, 255, 0, 64 }, { 7, 76, 255, 0, 64 },
13401 { 7, 74, 255, 0, 64 }, { 7, 72, 255, 0, 64 },
13402 { 7, 70, 255, 0, 64 }, { 7, 68, 255, 0, 64 },
13403 { 7, 66, 255, 0, 64 }, { 7, 64, 255, 0, 64 },
13404 { 7, 64, 255, 0, 64 }, { 7, 62, 255, 0, 64 },
13405 { 7, 62, 248, 0, 64 }, { 7, 60, 248, 0, 64 },
13406 { 7, 60, 241, 0, 64 }, { 7, 59, 241, 0, 64 },
13407 { 7, 59, 234, 0, 64 }, { 7, 57, 234, 0, 64 },
13408 { 7, 57, 227, 0, 64 }, { 7, 55, 227, 0, 64 },
13409 { 7, 55, 221, 0, 64 }, { 7, 54, 221, 0, 64 },
13410 { 7, 54, 215, 0, 64 }, { 7, 52, 215, 0, 64 },
13411 { 7, 52, 208, 0, 64 }, { 7, 51, 208, 0, 64 },
13412 { 7, 51, 203, 0, 64 }, { 7, 49, 203, 0, 64 },
13413 { 7, 49, 197, 0, 64 }, { 7, 48, 197, 0, 64 },
13414 { 7, 48, 191, 0, 64 }, { 7, 47, 191, 0, 64 },
13415 { 7, 47, 186, 0, 64 }, { 7, 45, 186, 0, 64 },
13416 { 7, 45, 181, 0, 64 }, { 7, 44, 181, 0, 64 },
13417 { 7, 44, 175, 0, 64 }, { 7, 43, 175, 0, 64 },
13418 { 7, 43, 170, 0, 64 }, { 7, 42, 170, 0, 64 },
13419 { 7, 42, 166, 0, 64 }, { 7, 40, 166, 0, 64 },
13420 { 7, 40, 161, 0, 64 }, { 7, 39, 161, 0, 64 },
13421 { 7, 39, 156, 0, 64 }, { 7, 38, 156, 0, 64 },
13422 { 7, 38, 152, 0, 64 }, { 7, 37, 152, 0, 64 },
13423 { 7, 37, 148, 0, 64 }, { 7, 36, 148, 0, 64 },
13424 { 7, 36, 143, 0, 64 }, { 7, 35, 143, 0, 64 },
13425 { 7, 35, 139, 0, 64 }, { 7, 34, 139, 0, 64 },
13426 { 7, 34, 135, 0, 64 }, { 7, 33, 135, 0, 64 },
13427 { 7, 33, 132, 0, 64 }, { 7, 32, 132, 0, 64 },
13428 { 7, 32, 128, 0, 64 }, { 7, 31, 128, 0, 64 },
13429 { 7, 31, 124, 0, 64 }, { 7, 30, 124, 0, 64 },
13430 { 7, 30, 121, 0, 64 }, { 7, 29, 121, 0, 64 },
13431 { 7, 29, 117, 0, 64 }, { 7, 29, 117, 0, 64 },
13432 { 7, 29, 114, 0, 64 }, { 7, 28, 114, 0, 64 },
13433 { 7, 28, 111, 0, 64 }, { 7, 27, 111, 0, 64 },
13434 { 7, 27, 108, 0, 64 }, { 7, 26, 108, 0, 64 },
13435 { 7, 26, 104, 0, 64 }, { 7, 25, 104, 0, 64 },
13436 { 7, 25, 102, 0, 64 }, { 7, 25, 102, 0, 64 },
13437 { 7, 25, 99, 0, 64 }, { 7, 24, 99, 0, 64 },
13438 { 7, 24, 96, 0, 64 }, { 7, 23, 96, 0, 64 },
13439 { 7, 23, 93, 0, 64 }, { 7, 23, 93, 0, 64 },
13440 { 7, 23, 90, 0, 64 }, { 7, 22, 90, 0, 64 },
13441 { 7, 22, 88, 0, 64 }, { 7, 21, 88, 0, 64 },
13442 { 7, 21, 85, 0, 64 }, { 7, 21, 85, 0, 64 },
13443 { 7, 21, 83, 0, 64 }, { 7, 20, 83, 0, 64 },
13444 { 7, 20, 81, 0, 64 }, { 7, 20, 81, 0, 64 },
13445 { 7, 20, 78, 0, 64 }, { 7, 19, 78, 0, 64 },
13446 { 7, 19, 76, 0, 64 }, { 7, 19, 76, 0, 64 },
13447 { 7, 19, 74, 0, 64 }, { 7, 18, 74, 0, 64 },
13448 { 7, 18, 72, 0, 64 }, { 7, 18, 72, 0, 64 },
13449 { 7, 18, 70, 0, 64 }, { 7, 17, 70, 0, 64 },
13450 { 7, 17, 68, 0, 64 }, { 7, 17, 68, 0, 64 },
13451 { 7, 17, 66, 0, 64 }, { 7, 16, 66, 0, 64 },
13452 { 7, 16, 64, 0, 64 }, { 7, 16, 64, 0, 64 },
13453 { 7, 16, 62, 0, 64 }, { 7, 15, 62, 0, 64 },
13454 { 7, 15, 60, 0, 64 }, { 7, 15, 60, 0, 64 },
13455 { 7, 15, 59, 0, 64 }, { 7, 14, 59, 0, 64 },
13456 { 7, 14, 57, 0, 64 }, { 7, 14, 57, 0, 64 },
13457 { 7, 14, 55, 0, 64 }, { 7, 14, 55, 0, 64 },
13458 { 7, 14, 54, 0, 64 }, { 7, 13, 54, 0, 64 },
13459 { 7, 13, 52, 0, 64 }, { 7, 13, 52, 0, 64 },
13460 };
13461 static struct bwn_txgain_entry txgain_5ghz_r2[] = {
13462 { 255, 255, 255, 0, 152 }, { 255, 255, 255, 0, 147 },
13463 { 255, 255, 255, 0, 143 }, { 255, 255, 255, 0, 139 },
13464 { 255, 255, 255, 0, 135 }, { 255, 255, 255, 0, 131 },
13465 { 255, 255, 255, 0, 128 }, { 255, 255, 255, 0, 124 },
13466 { 255, 255, 255, 0, 121 }, { 255, 255, 255, 0, 117 },
13467 { 255, 255, 255, 0, 114 }, { 255, 255, 255, 0, 111 },
13468 { 255, 255, 255, 0, 107 }, { 255, 255, 255, 0, 104 },
13469 { 255, 255, 255, 0, 101 }, { 255, 255, 255, 0, 99 },
13470 { 255, 255, 255, 0, 96 }, { 255, 255, 255, 0, 93 },
13471 { 255, 255, 255, 0, 90 }, { 255, 255, 255, 0, 88 },
13472 { 255, 255, 255, 0, 85 }, { 255, 255, 255, 0, 83 },
13473 { 255, 255, 255, 0, 81 }, { 255, 255, 255, 0, 78 },
13474 { 255, 255, 255, 0, 76 }, { 255, 255, 255, 0, 74 },
13475 { 255, 255, 255, 0, 72 }, { 255, 255, 255, 0, 70 },
13476 { 255, 255, 255, 0, 68 }, { 255, 255, 255, 0, 66 },
13477 { 255, 255, 255, 0, 64 }, { 255, 255, 248, 0, 64 },
13478 { 255, 255, 241, 0, 64 }, { 255, 255, 234, 0, 64 },
13479 { 255, 255, 227, 0, 64 }, { 255, 255, 221, 0, 64 },
13480 { 255, 255, 215, 0, 64 }, { 255, 255, 208, 0, 64 },
13481 { 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13482 { 255, 255, 191, 0, 64 }, { 255, 255, 186, 0, 64 },
13483 { 255, 255, 181, 0, 64 }, { 255, 255, 175, 0, 64 },
13484 { 255, 255, 170, 0, 64 }, { 255, 255, 166, 0, 64 },
13485 { 255, 255, 161, 0, 64 }, { 255, 255, 156, 0, 64 },
13486 { 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13487 { 255, 255, 143, 0, 64 }, { 255, 255, 139, 0, 64 },
13488 { 255, 255, 135, 0, 64 }, { 255, 255, 132, 0, 64 },
13489 { 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13490 { 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13491 { 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13492 { 255, 255, 108, 0, 64 }, { 255, 255, 104, 0, 64 },
13493 { 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13494 { 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13495 { 255, 255, 90, 0, 64 }, { 255, 255, 88, 0, 64 },
13496 { 255, 255, 85, 0, 64 }, { 255, 255, 83, 0, 64 },
13497 { 255, 255, 81, 0, 64 }, { 255, 255, 78, 0, 64 },
13498 { 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13499 { 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13500 { 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13501 { 255, 255, 64, 0, 64 }, { 255, 255, 64, 0, 64 },
13502 { 255, 255, 62, 0, 64 }, { 255, 248, 62, 0, 64 },
13503 { 255, 248, 60, 0, 64 }, { 255, 241, 60, 0, 64 },
13504 { 255, 241, 59, 0, 64 }, { 255, 234, 59, 0, 64 },
13505 { 255, 234, 57, 0, 64 }, { 255, 227, 57, 0, 64 },
13506 { 255, 227, 55, 0, 64 }, { 255, 221, 55, 0, 64 },
13507 { 255, 221, 54, 0, 64 }, { 255, 215, 54, 0, 64 },
13508 { 255, 215, 52, 0, 64 }, { 255, 208, 52, 0, 64 },
13509 { 255, 208, 51, 0, 64 }, { 255, 203, 51, 0, 64 },
13510 { 255, 203, 49, 0, 64 }, { 255, 197, 49, 0, 64 },
13511 { 255, 197, 48, 0, 64 }, { 255, 191, 48, 0, 64 },
13512 { 255, 191, 47, 0, 64 }, { 255, 186, 47, 0, 64 },
13513 { 255, 186, 45, 0, 64 }, { 255, 181, 45, 0, 64 },
13514 { 255, 181, 44, 0, 64 }, { 255, 175, 44, 0, 64 },
13515 { 255, 175, 43, 0, 64 }, { 255, 170, 43, 0, 64 },
13516 { 255, 170, 42, 0, 64 }, { 255, 166, 42, 0, 64 },
13517 { 255, 166, 40, 0, 64 }, { 255, 161, 40, 0, 64 },
13518 { 255, 161, 39, 0, 64 }, { 255, 156, 39, 0, 64 },
13519 { 255, 156, 38, 0, 64 }, { 255, 152, 38, 0, 64 },
13520 { 255, 152, 37, 0, 64 }, { 255, 148, 37, 0, 64 },
13521 { 255, 148, 36, 0, 64 }, { 255, 143, 36, 0, 64 },
13522 { 255, 143, 35, 0, 64 }, { 255, 139, 35, 0, 64 },
13523 { 255, 139, 34, 0, 64 }, { 255, 135, 34, 0, 64 },
13524 { 255, 135, 33, 0, 64 }, { 255, 132, 33, 0, 64 },
13525 { 255, 132, 32, 0, 64 }, { 255, 128, 32, 0, 64 }
13526 };
13527 static struct bwn_txgain_entry txgain_r0[] = {
13528 { 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13529 { 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13530 { 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13531 { 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13532 { 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13533 { 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13534 { 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13535 { 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13536 { 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13537 { 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13538 { 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13539 { 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13540 { 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13541 { 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13542 { 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13543 { 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13544 { 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13545 { 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13546 { 7, 15, 13, 0, 70 }, { 7, 15, 13, 0, 68 },
13547 { 7, 15, 13, 0, 66 }, { 7, 15, 13, 0, 64 },
13548 { 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13549 { 7, 15, 13, 0, 59 }, { 7, 15, 13, 0, 57 },
13550 { 7, 15, 12, 0, 71 }, { 7, 15, 12, 0, 69 },
13551 { 7, 15, 12, 0, 67 }, { 7, 15, 12, 0, 65 },
13552 { 7, 15, 12, 0, 63 }, { 7, 15, 12, 0, 62 },
13553 { 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 58 },
13554 { 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 70 },
13555 { 7, 15, 11, 0, 68 }, { 7, 15, 11, 0, 66 },
13556 { 7, 15, 11, 0, 65 }, { 7, 15, 11, 0, 63 },
13557 { 7, 15, 11, 0, 61 }, { 7, 15, 11, 0, 59 },
13558 { 7, 15, 11, 0, 58 }, { 7, 15, 10, 0, 71 },
13559 { 7, 15, 10, 0, 69 }, { 7, 15, 10, 0, 67 },
13560 { 7, 15, 10, 0, 65 }, { 7, 15, 10, 0, 63 },
13561 { 7, 15, 10, 0, 61 }, { 7, 15, 10, 0, 60 },
13562 { 7, 15, 10, 0, 58 }, { 7, 15, 10, 0, 56 },
13563 { 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13564 { 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13565 { 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 60 },
13566 { 7, 15, 9, 0, 59 }, { 7, 14, 9, 0, 72 },
13567 { 7, 14, 9, 0, 70 }, { 7, 14, 9, 0, 68 },
13568 { 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 64 },
13569 { 7, 14, 9, 0, 62 }, { 7, 14, 9, 0, 60 },
13570 { 7, 14, 9, 0, 59 }, { 7, 13, 9, 0, 72 },
13571 { 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13572 { 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13573 { 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13574 { 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13575 { 7, 13, 8, 0, 72 }, { 7, 13, 8, 0, 70 },
13576 { 7, 13, 8, 0, 68 }, { 7, 13, 8, 0, 66 },
13577 { 7, 13, 8, 0, 64 }, { 7, 13, 8, 0, 62 },
13578 { 7, 13, 8, 0, 60 }, { 7, 13, 8, 0, 59 },
13579 { 7, 12, 8, 0, 72 }, { 7, 12, 8, 0, 70 },
13580 { 7, 12, 8, 0, 68 }, { 7, 12, 8, 0, 66 },
13581 { 7, 12, 8, 0, 64 }, { 7, 12, 8, 0, 62 },
13582 { 7, 12, 8, 0, 61 }, { 7, 12, 8, 0, 59 },
13583 { 7, 12, 7, 0, 73 }, { 7, 12, 7, 0, 71 },
13584 { 7, 12, 7, 0, 69 }, { 7, 12, 7, 0, 67 },
13585 { 7, 12, 7, 0, 65 }, { 7, 12, 7, 0, 63 },
13586 { 7, 12, 7, 0, 61 }, { 7, 12, 7, 0, 59 },
13587 { 7, 11, 7, 0, 72 }, { 7, 11, 7, 0, 70 },
13588 { 7, 11, 7, 0, 68 }, { 7, 11, 7, 0, 66 },
13589 { 7, 11, 7, 0, 65 }, { 7, 11, 7, 0, 63 },
13590 { 7, 11, 7, 0, 61 }, { 7, 11, 7, 0, 59 },
13591 { 7, 11, 6, 0, 73 }, { 7, 11, 6, 0, 71 }
13592 };
13593 static struct bwn_txgain_entry txgain_2ghz_r0[] = {
13594 { 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13595 { 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13596 { 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13597 { 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13598 { 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13599 { 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13600 { 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13601 { 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13602 { 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13603 { 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13604 { 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13605 { 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13606 { 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13607 { 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13608 { 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13609 { 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13610 { 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13611 { 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13612 { 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13613 { 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13614 { 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13615 { 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13616 { 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13617 { 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13618 { 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13619 { 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13620 { 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13621 { 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13622 { 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13623 { 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13624 { 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13625 { 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13626 { 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13627 { 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 },
13628 { 4, 10, 6, 0, 59 }, { 4, 10, 5, 0, 72 },
13629 { 4, 10, 5, 0, 70 }, { 4, 10, 5, 0, 68 },
13630 { 4, 10, 5, 0, 66 }, { 4, 10, 5, 0, 64 },
13631 { 4, 10, 5, 0, 62 }, { 4, 10, 5, 0, 60 },
13632 { 4, 10, 5, 0, 59 }, { 4, 9, 5, 0, 70 },
13633 { 4, 9, 5, 0, 68 }, { 4, 9, 5, 0, 66 },
13634 { 4, 9, 5, 0, 64 }, { 4, 9, 5, 0, 63 },
13635 { 4, 9, 5, 0, 61 }, { 4, 9, 5, 0, 59 },
13636 { 4, 9, 4, 0, 71 }, { 4, 9, 4, 0, 69 },
13637 { 4, 9, 4, 0, 67 }, { 4, 9, 4, 0, 65 },
13638 { 4, 9, 4, 0, 63 }, { 4, 9, 4, 0, 62 },
13639 { 4, 9, 4, 0, 60 }, { 4, 9, 4, 0, 58 },
13640 { 4, 8, 4, 0, 70 }, { 4, 8, 4, 0, 68 },
13641 { 4, 8, 4, 0, 66 }, { 4, 8, 4, 0, 65 },
13642 { 4, 8, 4, 0, 63 }, { 4, 8, 4, 0, 61 },
13643 { 4, 8, 4, 0, 59 }, { 4, 7, 4, 0, 68 },
13644 { 4, 7, 4, 0, 66 }, { 4, 7, 4, 0, 64 },
13645 { 4, 7, 4, 0, 62 }, { 4, 7, 4, 0, 61 },
13646 { 4, 7, 4, 0, 59 }, { 4, 7, 3, 0, 67 },
13647 { 4, 7, 3, 0, 65 }, { 4, 7, 3, 0, 63 },
13648 { 4, 7, 3, 0, 62 }, { 4, 7, 3, 0, 60 },
13649 { 4, 6, 3, 0, 65 }, { 4, 6, 3, 0, 63 },
13650 { 4, 6, 3, 0, 61 }, { 4, 6, 3, 0, 60 },
13651 { 4, 6, 3, 0, 58 }, { 4, 5, 3, 0, 68 },
13652 { 4, 5, 3, 0, 66 }, { 4, 5, 3, 0, 64 },
13653 { 4, 5, 3, 0, 62 }, { 4, 5, 3, 0, 60 },
13654 { 4, 5, 3, 0, 59 }, { 4, 5, 3, 0, 57 },
13655 { 4, 4, 2, 0, 83 }, { 4, 4, 2, 0, 81 },
13656 { 4, 4, 2, 0, 78 }, { 4, 4, 2, 0, 76 },
13657 { 4, 4, 2, 0, 74 }, { 4, 4, 2, 0, 72 }
13658 };
13659 static struct bwn_txgain_entry txgain_5ghz_r0[] = {
13660 { 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13661 { 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13662 { 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13663 { 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13664 { 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13665 { 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13666 { 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13667 { 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13668 { 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13669 { 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13670 { 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13671 { 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13672 { 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13673 { 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13674 { 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13675 { 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13676 { 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13677 { 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13678 { 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13679 { 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13680 { 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13681 { 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13682 { 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13683 { 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13684 { 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13685 { 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13686 { 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13687 { 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13688 { 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13689 { 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13690 { 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13691 { 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13692 { 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13693 { 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13694 { 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13695 { 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13696 { 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13697 { 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13698 { 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13699 { 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13700 { 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13701 { 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13702 { 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13703 { 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13704 { 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13705 { 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13706 { 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13707 { 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13708 { 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13709 { 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13710 { 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13711 { 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13712 { 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13713 { 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13714 { 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13715 { 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13716 { 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13717 { 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13718 { 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13719 { 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13720 { 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13721 { 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13722 { 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13723 { 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13724 };
13725 static struct bwn_txgain_entry txgain_r1[] = {
13726 { 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13727 { 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13728 { 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13729 { 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13730 { 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13731 { 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13732 { 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13733 { 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13734 { 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13735 { 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13736 { 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13737 { 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13738 { 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13739 { 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13740 { 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13741 { 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13742 { 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13743 { 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13744 { 7, 15, 13, 0, 70 }, { 7, 15, 14, 0, 68 },
13745 { 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13746 { 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13747 { 7, 15, 14, 0, 59 }, { 7, 15, 14, 0, 57 },
13748 { 7, 15, 13, 0, 72 }, { 7, 15, 13, 0, 70 },
13749 { 7, 15, 13, 0, 68 }, { 7, 15, 13, 0, 66 },
13750 { 7, 15, 13, 0, 64 }, { 7, 15, 13, 0, 62 },
13751 { 7, 15, 13, 0, 60 }, { 7, 15, 13, 0, 59 },
13752 { 7, 15, 13, 0, 57 }, { 7, 15, 12, 0, 71 },
13753 { 7, 15, 12, 0, 69 }, { 7, 15, 12, 0, 67 },
13754 { 7, 15, 12, 0, 65 }, { 7, 15, 12, 0, 63 },
13755 { 7, 15, 12, 0, 62 }, { 7, 15, 12, 0, 60 },
13756 { 7, 15, 12, 0, 58 }, { 7, 15, 12, 0, 57 },
13757 { 7, 15, 11, 0, 70 }, { 7, 15, 11, 0, 68 },
13758 { 7, 15, 11, 0, 66 }, { 7, 15, 11, 0, 65 },
13759 { 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13760 { 7, 15, 11, 0, 59 }, { 7, 15, 11, 0, 58 },
13761 { 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13762 { 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13763 { 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13764 { 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13765 { 7, 15, 10, 0, 56 }, { 7, 15, 9, 0, 70 },
13766 { 7, 15, 9, 0, 68 }, { 7, 15, 9, 0, 66 },
13767 { 7, 15, 9, 0, 64 }, { 7, 15, 9, 0, 62 },
13768 { 7, 15, 9, 0, 60 }, { 7, 15, 9, 0, 59 },
13769 { 7, 14, 9, 0, 72 }, { 7, 14, 9, 0, 70 },
13770 { 7, 14, 9, 0, 68 }, { 7, 14, 9, 0, 66 },
13771 { 7, 14, 9, 0, 64 }, { 7, 14, 9, 0, 62 },
13772 { 7, 14, 9, 0, 60 }, { 7, 14, 9, 0, 59 },
13773 { 7, 13, 9, 0, 72 }, { 7, 13, 9, 0, 70 },
13774 { 7, 13, 9, 0, 68 }, { 7, 13, 9, 0, 66 },
13775 { 7, 13, 9, 0, 64 }, { 7, 13, 9, 0, 63 },
13776 { 7, 13, 9, 0, 61 }, { 7, 13, 9, 0, 59 },
13777 { 7, 13, 9, 0, 57 }, { 7, 13, 8, 0, 72 },
13778 { 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13779 { 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13780 { 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13781 { 7, 13, 8, 0, 59 }, { 7, 12, 8, 0, 72 },
13782 { 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13783 { 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13784 { 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13785 { 7, 12, 8, 0, 59 }, { 7, 12, 7, 0, 73 },
13786 { 7, 12, 7, 0, 71 }, { 7, 12, 7, 0, 69 },
13787 { 7, 12, 7, 0, 67 }, { 7, 12, 7, 0, 65 },
13788 { 7, 12, 7, 0, 63 }, { 7, 12, 7, 0, 61 },
13789 { 7, 12, 7, 0, 59 }, { 7, 11, 7, 0, 72 },
13790 { 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13791 { 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 65 },
13792 { 7, 11, 7, 0, 63 }, { 7, 11, 7, 0, 61 },
13793 { 7, 11, 7, 0, 59 }, { 7, 11, 6, 0, 73 },
13794 { 7, 11, 6, 0, 71 }
13795 };
13796 static struct bwn_txgain_entry txgain_2ghz_r1[] = {
13797 { 4, 15, 15, 0, 90 }, { 4, 15, 15, 0, 88 },
13798 { 4, 15, 15, 0, 85 }, { 4, 15, 15, 0, 83 },
13799 { 4, 15, 15, 0, 81 }, { 4, 15, 15, 0, 78 },
13800 { 4, 15, 15, 0, 76 }, { 4, 15, 15, 0, 74 },
13801 { 4, 15, 15, 0, 72 }, { 4, 15, 15, 0, 70 },
13802 { 4, 15, 15, 0, 68 }, { 4, 15, 15, 0, 66 },
13803 { 4, 15, 15, 0, 64 }, { 4, 15, 15, 0, 62 },
13804 { 4, 15, 15, 0, 60 }, { 4, 15, 15, 0, 59 },
13805 { 4, 15, 14, 0, 72 }, { 4, 15, 14, 0, 70 },
13806 { 4, 15, 14, 0, 68 }, { 4, 15, 14, 0, 66 },
13807 { 4, 15, 14, 0, 64 }, { 4, 15, 14, 0, 62 },
13808 { 4, 15, 14, 0, 60 }, { 4, 15, 14, 0, 59 },
13809 { 4, 15, 13, 0, 72 }, { 4, 15, 13, 0, 70 },
13810 { 4, 15, 13, 0, 68 }, { 4, 15, 13, 0, 66 },
13811 { 4, 15, 13, 0, 64 }, { 4, 15, 13, 0, 62 },
13812 { 4, 15, 13, 0, 60 }, { 4, 15, 13, 0, 59 },
13813 { 4, 15, 12, 0, 72 }, { 4, 15, 12, 0, 70 },
13814 { 4, 15, 12, 0, 68 }, { 4, 15, 12, 0, 66 },
13815 { 4, 15, 12, 0, 64 }, { 4, 15, 12, 0, 62 },
13816 { 4, 15, 12, 0, 60 }, { 4, 15, 12, 0, 59 },
13817 { 4, 15, 11, 0, 72 }, { 4, 15, 11, 0, 70 },
13818 { 4, 15, 11, 0, 68 }, { 4, 15, 11, 0, 66 },
13819 { 4, 15, 11, 0, 64 }, { 4, 15, 11, 0, 62 },
13820 { 4, 15, 11, 0, 60 }, { 4, 15, 11, 0, 59 },
13821 { 4, 15, 10, 0, 72 }, { 4, 15, 10, 0, 70 },
13822 { 4, 15, 10, 0, 68 }, { 4, 15, 10, 0, 66 },
13823 { 4, 15, 10, 0, 64 }, { 4, 15, 10, 0, 62 },
13824 { 4, 15, 10, 0, 60 }, { 4, 15, 10, 0, 59 },
13825 { 4, 15, 9, 0, 72 }, { 4, 15, 9, 0, 70 },
13826 { 4, 15, 9, 0, 68 }, { 4, 15, 9, 0, 66 },
13827 { 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13828 { 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13829 { 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13830 { 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13831 { 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13832 { 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13833 { 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13834 { 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13835 { 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13836 { 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13837 { 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13838 { 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13839 { 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13840 { 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13841 { 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13842 { 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13843 { 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13844 { 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13845 { 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13846 { 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13847 { 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13848 { 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13849 { 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13850 { 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13851 { 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13852 { 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13853 { 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13854 { 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13855 { 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13856 { 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13857 { 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13858 { 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13859 { 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13860 { 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 }
13861 };
13862 static struct bwn_txgain_entry txgain_5ghz_r1[] = {
13863 { 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13864 { 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13865 { 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13866 { 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13867 { 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13868 { 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13869 { 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13870 { 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13871 { 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13872 { 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13873 { 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13874 { 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13875 { 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13876 { 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13877 { 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13878 { 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13879 { 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13880 { 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13881 { 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13882 { 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13883 { 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13884 { 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13885 { 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13886 { 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13887 { 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13888 { 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13889 { 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13890 { 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13891 { 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13892 { 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13893 { 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13894 { 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13895 { 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13896 { 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13897 { 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13898 { 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13899 { 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13900 { 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13901 { 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13902 { 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13903 { 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13904 { 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13905 { 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13906 { 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13907 { 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13908 { 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13909 { 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13910 { 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13911 { 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13912 { 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13913 { 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13914 { 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13915 { 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13916 { 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13917 { 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13918 { 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13919 { 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13920 { 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13921 { 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13922 { 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13923 { 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13924 { 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13925 { 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13926 { 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13927 };
13928
13929 if (mac->mac_phy.rev != 0 && mac->mac_phy.rev != 1) {
13930 if (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA)
13931 bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r2);
13932 else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13933 bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13934 txgain_2ghz_r2);
13935 else
13936 bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13937 txgain_5ghz_r2);
13938 return;
13939 }
13940
13941 if (mac->mac_phy.rev == 0) {
13942 if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA) ||
13943 (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_HGPA))
13944 bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r0);
13945 else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13946 bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13947 txgain_2ghz_r0);
13948 else
13949 bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13950 txgain_5ghz_r0);
13951 return;
13952 }
13953
13954 if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA) ||
13955 (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_HGPA))
13956 bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r1);
13957 else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13958 bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_2ghz_r1);
13959 else
13960 bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_5ghz_r1);
13961}
13962
13963static void
13964bwn_tab_write(struct bwn_mac *mac, uint32_t typeoffset, uint32_t value)
13965{
13966 uint32_t offset, type;
13967
13968 type = BWN_TAB_GETTYPE(typeoffset);
13969 offset = BWN_TAB_GETOFFSET(typeoffset);
13970 KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
13971
13972 switch (type) {
13973 case BWN_TAB_8BIT:
13974 KASSERT(!(value & ~0xff), ("%s:%d: fail", __func__, __LINE__));
13975 BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13976 BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13977 break;
13978 case BWN_TAB_16BIT:
13979 KASSERT(!(value & ~0xffff),
13980 ("%s:%d: fail", __func__, __LINE__));
13981 BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13982 BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13983 break;
13984 case BWN_TAB_32BIT:
13985 BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13986 BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
13987 BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13988 break;
13989 default:
13990 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
13991 }
13992}
13993
13994static int
13995bwn_phy_lp_loopback(struct bwn_mac *mac)
13996{
13997 struct bwn_phy_lp_iq_est ie;
13998 int i, index = -1;
13999 uint32_t tmp;
14000
14001 memset(&ie, 0, sizeof(ie));
14002
14003 bwn_phy_lp_set_trsw_over(mac, 1, 1);
14004 BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 1);
14005 BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
14006 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
14007 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
14008 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
14009 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x8);
14010 BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, 0x80);
14011 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x80);
14012 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x80);
14013 for (i = 0; i < 32; i++) {
14014 bwn_phy_lp_set_rxgain_idx(mac, i);
14015 bwn_phy_lp_ddfs_turnon(mac, 1, 1, 5, 5, 0);
14016 if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
14017 continue;
14018 tmp = (ie.ie_ipwr + ie.ie_qpwr) / 1000;
14019 if ((tmp > 4000) && (tmp < 10000)) {
14020 index = i;
14021 break;
14022 }
14023 }
14024 bwn_phy_lp_ddfs_turnoff(mac);
14025 return (index);
14026}
14027
14028static void
14029bwn_phy_lp_set_rxgain_idx(struct bwn_mac *mac, uint16_t idx)
14030{
14031
14032 bwn_phy_lp_set_rxgain(mac, bwn_tab_read(mac, BWN_TAB_2(12, idx)));
14033}
14034
14035static void
14036bwn_phy_lp_ddfs_turnon(struct bwn_mac *mac, int i_on, int q_on,
14037 int incr1, int incr2, int scale_idx)
14038{
14039
14040 bwn_phy_lp_ddfs_turnoff(mac);
14041 BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0xff80);
14042 BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0x80ff);
14043 BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0xff80, incr1);
14044 BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0x80ff, incr2 << 8);
14045 BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff7, i_on << 3);
14046 BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xffef, q_on << 4);
14047 BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xff9f, scale_idx << 5);
14048 BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffb);
14049 BWN_PHY_SET(mac, BWN_PHY_AFE_DDFS, 0x2);
14050 BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x20);
14051}
14052
14053static uint8_t
14054bwn_phy_lp_rx_iq_est(struct bwn_mac *mac, uint16_t sample, uint8_t time,
14055 struct bwn_phy_lp_iq_est *ie)
14056{
14057 int i;
14058
14059 BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfff7);
14060 BWN_PHY_WRITE(mac, BWN_PHY_IQ_NUM_SMPLS_ADDR, sample);
14061 BWN_PHY_SETMASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xff00, time);
14062 BWN_PHY_MASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xfeff);
14063 BWN_PHY_SET(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0x200);
14064
14065 for (i = 0; i < 500; i++) {
14066 if (!(BWN_PHY_READ(mac,
14067 BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200))
14068 break;
14069 DELAY(1000);
14070 }
14071 if ((BWN_PHY_READ(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200)) {
14072 BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
14073 return 0;
14074 }
14075
14076 ie->ie_iqprod = BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_HI_ADDR);
14077 ie->ie_iqprod <<= 16;
14078 ie->ie_iqprod |= BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_LO_ADDR);
14079 ie->ie_ipwr = BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_HI_ADDR);
14080 ie->ie_ipwr <<= 16;
14081 ie->ie_ipwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_LO_ADDR);
14082 ie->ie_qpwr = BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_HI_ADDR);
14083 ie->ie_qpwr <<= 16;
14084 ie->ie_qpwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_LO_ADDR);
14085
14086 BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
14087 return 1;
14088}
14089
14090static uint32_t
14091bwn_tab_read(struct bwn_mac *mac, uint32_t typeoffset)
14092{
14093 uint32_t offset, type, value;
14094
14095 type = BWN_TAB_GETTYPE(typeoffset);
14096 offset = BWN_TAB_GETOFFSET(typeoffset);
14097 KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
14098
14099 switch (type) {
14100 case BWN_TAB_8BIT:
14101 BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14102 value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
14103 break;
14104 case BWN_TAB_16BIT:
14105 BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14106 value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
14107 break;
14108 case BWN_TAB_32BIT:
14109 BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14110 value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATAHI);
14111 value <<= 16;
14112 value |= BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
14113 break;
14114 default:
14115 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
14116 value = 0;
14117 }
14118
14119 return (value);
14120}
14121
14122static void
14123bwn_phy_lp_ddfs_turnoff(struct bwn_mac *mac)
14124{
14125
14126 BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffd);
14127 BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0xffdf);
14128}
14129
14130static void
14131bwn_phy_lp_set_txgain_dac(struct bwn_mac *mac, uint16_t dac)
14132{
14133 uint16_t ctl;
14134
14135 ctl = BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0xc7f;
14136 ctl |= dac << 7;
14137 BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf000, ctl);
14138}
14139
14140static void
14141bwn_phy_lp_set_txgain_pa(struct bwn_mac *mac, uint16_t gain)
14142{
14143
14144 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0xe03f, gain << 6);
14145 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x80ff, gain << 8);
14146}
14147
14148static void
14149bwn_phy_lp_set_txgain_override(struct bwn_mac *mac)
14150{
14151
14152 if (mac->mac_phy.rev < 2)
14153 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
14154 else {
14155 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x80);
14156 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x4000);
14157 }
14158 BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x40);
14159}
14160
14161static uint16_t
14162bwn_phy_lp_get_pa_gain(struct bwn_mac *mac)
14163{
14164
14165 return BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0x7f;
14166}
14167
14168static uint8_t
14169bwn_nbits(int32_t val)
14170{
14171 uint32_t tmp;
14172 uint8_t nbits = 0;
14173
14174 for (tmp = abs(val); tmp != 0; tmp >>= 1)
14175 nbits++;
14176 return (nbits);
14177}
14178
14179static void
14180bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *mac, int offset, int count,
14181 struct bwn_txgain_entry *table)
14182{
14183 int i;
14184
14185 for (i = offset; i < count; i++)
14186 bwn_phy_lp_gaintbl_write(mac, i, table[i]);
14187}
14188
14189static void
14190bwn_phy_lp_gaintbl_write(struct bwn_mac *mac, int offset,
14191 struct bwn_txgain_entry data)
14192{
14193
14194 if (mac->mac_phy.rev >= 2)
14195 bwn_phy_lp_gaintbl_write_r2(mac, offset, data);
14196 else
14197 bwn_phy_lp_gaintbl_write_r01(mac, offset, data);
14198}
14199
14200static void
14201bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *mac, int offset,
14202 struct bwn_txgain_entry te)
14203{
14204 struct bwn_softc *sc = mac->mac_sc;
14205 struct ifnet *ifp = sc->sc_ifp;
14206 struct ieee80211com *ic = ifp->if_l2com;
14207 uint32_t tmp;
14208
14209 KASSERT(mac->mac_phy.rev >= 2, ("%s:%d: fail", __func__, __LINE__));
14210
14211 tmp = (te.te_pad << 16) | (te.te_pga << 8) | te.te_gm;
14212 if (mac->mac_phy.rev >= 3) {
14213 tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14214 (0x10 << 24) : (0x70 << 24));
14215 } else {
14216 tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14217 (0x14 << 24) : (0x7f << 24));
14218 }
14219 bwn_tab_write(mac, BWN_TAB_4(7, 0xc0 + offset), tmp);
14220 bwn_tab_write(mac, BWN_TAB_4(7, 0x140 + offset),
14221 te.te_bbmult << 20 | te.te_dac << 28);
14222}
14223
14224static void
14225bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *mac, int offset,
14226 struct bwn_txgain_entry te)
14227{
14228
14229 KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
14230
14231 bwn_tab_write(mac, BWN_TAB_4(10, 0xc0 + offset),
14232 (te.te_pad << 11) | (te.te_pga << 7) | (te.te_gm << 4) |
14233 te.te_dac);
14234 bwn_tab_write(mac, BWN_TAB_4(10, 0x140 + offset), te.te_bbmult << 20);
14235}
14236
14237static void
14238bwn_sysctl_node(struct bwn_softc *sc)
14239{
14240 device_t dev = sc->sc_dev;
14241 struct bwn_mac *mac;
14242 struct bwn_stats *stats;
14243
14244 /* XXX assume that count of MAC is only 1. */
14245
14246 if ((mac = sc->sc_curmac) == NULL)
14247 return;
14248 stats = &mac->mac_stats;
14249
14250 SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14251 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14252 "linknoise", CTLFLAG_RW, &stats->rts, 0, "Noise level");
14253 SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14254 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14255 "rts", CTLFLAG_RW, &stats->rts, 0, "RTS");
14256 SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14257 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14258 "rtsfail", CTLFLAG_RW, &stats->rtsfail, 0, "RTS failed to send");
14259
14260#ifdef BWN_DEBUG
14261 SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14262 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14263 "debug", CTLFLAG_RW, &sc->sc_debug, 0, "Debug flags");
14264#endif
14265}
14266
14267static device_method_t bwn_methods[] = {
14268 /* Device interface */
14269 DEVMETHOD(device_probe, bwn_probe),
14270 DEVMETHOD(device_attach, bwn_attach),
14271 DEVMETHOD(device_detach, bwn_detach),
14272 DEVMETHOD(device_suspend, bwn_suspend),
14273 DEVMETHOD(device_resume, bwn_resume),
14274 KOBJMETHOD_END
14275};
14276static driver_t bwn_driver = {
14277 "bwn",
14278 bwn_methods,
14279 sizeof(struct bwn_softc)
14280};
14281static devclass_t bwn_devclass;
14282DRIVER_MODULE(bwn, siba_bwn, bwn_driver, bwn_devclass, 0, 0);
14283MODULE_DEPEND(bwn, siba_bwn, 1, 1, 1);
14284MODULE_DEPEND(bwn, wlan, 1, 1, 1); /* 802.11 media layer */
14285MODULE_DEPEND(bwn, firmware, 1, 1, 1); /* firmware support */
14286MODULE_DEPEND(bwn, wlan_amrr, 1, 1, 1);