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 227309 2011-11-07 15:43:11Z ed $");
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_phy.h>
71#include <net80211/ieee80211_ratectl.h>
72
73#include <dev/bwn/if_bwnreg.h>
74#include <dev/bwn/if_bwnvar.h>
75
76static SYSCTL_NODE(_hw, OID_AUTO, bwn, CTLFLAG_RD, 0,
77 "Broadcom driver parameters");
78
79/*
80 * Tunable & sysctl variables.
81 */
82
83#ifdef BWN_DEBUG
84static int bwn_debug = 0;
85SYSCTL_INT(_hw_bwn, OID_AUTO, debug, CTLFLAG_RW, &bwn_debug, 0,
86 "Broadcom debugging printfs");
87TUNABLE_INT("hw.bwn.debug", &bwn_debug);
88enum {
89 BWN_DEBUG_XMIT = 0x00000001, /* basic xmit operation */
90 BWN_DEBUG_RECV = 0x00000002, /* basic recv operation */
91 BWN_DEBUG_STATE = 0x00000004, /* 802.11 state transitions */
92 BWN_DEBUG_TXPOW = 0x00000008, /* tx power processing */
93 BWN_DEBUG_RESET = 0x00000010, /* reset processing */
94 BWN_DEBUG_OPS = 0x00000020, /* bwn_ops processing */
95 BWN_DEBUG_BEACON = 0x00000040, /* beacon handling */
96 BWN_DEBUG_WATCHDOG = 0x00000080, /* watchdog timeout */
97 BWN_DEBUG_INTR = 0x00000100, /* ISR */
98 BWN_DEBUG_CALIBRATE = 0x00000200, /* periodic calibration */
99 BWN_DEBUG_NODE = 0x00000400, /* node management */
100 BWN_DEBUG_LED = 0x00000800, /* led management */
101 BWN_DEBUG_CMD = 0x00001000, /* cmd submission */
102 BWN_DEBUG_LO = 0x00002000, /* LO */
103 BWN_DEBUG_FW = 0x00004000, /* firmware */
104 BWN_DEBUG_WME = 0x00008000, /* WME */
105 BWN_DEBUG_RF = 0x00010000, /* RF */
106 BWN_DEBUG_FATAL = 0x80000000, /* fatal errors */
107 BWN_DEBUG_ANY = 0xffffffff
108};
109#define DPRINTF(sc, m, fmt, ...) do { \
110 if (sc->sc_debug & (m)) \
111 printf(fmt, __VA_ARGS__); \
112} while (0)
113#else
114#define DPRINTF(sc, m, fmt, ...) do { (void) sc; } while (0)
115#endif
116
117static int bwn_bfp = 0; /* use "Bad Frames Preemption" */
118SYSCTL_INT(_hw_bwn, OID_AUTO, bfp, CTLFLAG_RW, &bwn_bfp, 0,
119 "uses Bad Frames Preemption");
120static int bwn_bluetooth = 1;
121SYSCTL_INT(_hw_bwn, OID_AUTO, bluetooth, CTLFLAG_RW, &bwn_bluetooth, 0,
122 "turns on Bluetooth Coexistence");
123static int bwn_hwpctl = 0;
124SYSCTL_INT(_hw_bwn, OID_AUTO, hwpctl, CTLFLAG_RW, &bwn_hwpctl, 0,
125 "uses H/W power control");
126static int bwn_msi_disable = 0; /* MSI disabled */
127TUNABLE_INT("hw.bwn.msi_disable", &bwn_msi_disable);
128static int bwn_usedma = 1;
129SYSCTL_INT(_hw_bwn, OID_AUTO, usedma, CTLFLAG_RD, &bwn_usedma, 0,
130 "uses DMA");
131TUNABLE_INT("hw.bwn.usedma", &bwn_usedma);
132static int bwn_wme = 1;
133SYSCTL_INT(_hw_bwn, OID_AUTO, wme, CTLFLAG_RW, &bwn_wme, 0,
134 "uses WME support");
135
136static int bwn_attach_pre(struct bwn_softc *);
137static int bwn_attach_post(struct bwn_softc *);
138static void bwn_sprom_bugfixes(device_t);
139static void bwn_init(void *);
140static int bwn_init_locked(struct bwn_softc *);
141static int bwn_ioctl(struct ifnet *, u_long, caddr_t);
142static void bwn_start(struct ifnet *);
143static int bwn_attach_core(struct bwn_mac *);
144static void bwn_reset_core(struct bwn_mac *, uint32_t);
145static int bwn_phy_getinfo(struct bwn_mac *, int);
146static int bwn_chiptest(struct bwn_mac *);
147static int bwn_setup_channels(struct bwn_mac *, int, int);
148static int bwn_phy_g_attach(struct bwn_mac *);
149static void bwn_phy_g_detach(struct bwn_mac *);
150static void bwn_phy_g_init_pre(struct bwn_mac *);
151static int bwn_phy_g_prepare_hw(struct bwn_mac *);
152static int bwn_phy_g_init(struct bwn_mac *);
153static void bwn_phy_g_exit(struct bwn_mac *);
154static uint16_t bwn_phy_g_read(struct bwn_mac *, uint16_t);
155static void bwn_phy_g_write(struct bwn_mac *, uint16_t,
156 uint16_t);
157static uint16_t bwn_phy_g_rf_read(struct bwn_mac *, uint16_t);
158static void bwn_phy_g_rf_write(struct bwn_mac *, uint16_t,
159 uint16_t);
160static int bwn_phy_g_hwpctl(struct bwn_mac *);
161static void bwn_phy_g_rf_onoff(struct bwn_mac *, int);
162static int bwn_phy_g_switch_channel(struct bwn_mac *, uint32_t);
163static uint32_t bwn_phy_g_get_default_chan(struct bwn_mac *);
164static void bwn_phy_g_set_antenna(struct bwn_mac *, int);
165static int bwn_phy_g_im(struct bwn_mac *, int);
166static int bwn_phy_g_recalc_txpwr(struct bwn_mac *, int);
167static void bwn_phy_g_set_txpwr(struct bwn_mac *);
168static void bwn_phy_g_task_15s(struct bwn_mac *);
169static void bwn_phy_g_task_60s(struct bwn_mac *);
170static uint16_t bwn_phy_g_txctl(struct bwn_mac *);
171static void bwn_phy_switch_analog(struct bwn_mac *, int);
172static uint16_t bwn_shm_read_2(struct bwn_mac *, uint16_t, uint16_t);
173static void bwn_shm_write_2(struct bwn_mac *, uint16_t, uint16_t,
174 uint16_t);
175static uint32_t bwn_shm_read_4(struct bwn_mac *, uint16_t, uint16_t);
176static void bwn_shm_write_4(struct bwn_mac *, uint16_t, uint16_t,
177 uint32_t);
178static void bwn_shm_ctlword(struct bwn_mac *, uint16_t,
179 uint16_t);
180static void bwn_addchannels(struct ieee80211_channel [], int, int *,
181 const struct bwn_channelinfo *, int);
182static int bwn_raw_xmit(struct ieee80211_node *, struct mbuf *,
183 const struct ieee80211_bpf_params *);
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 void bwn_wme_clear(struct bwn_softc *);
189static void bwn_wme_load(struct bwn_mac *);
190static void bwn_wme_loadparams(struct bwn_mac *,
191 const struct wmeParams *, uint16_t);
192static void bwn_scan_start(struct ieee80211com *);
193static void bwn_scan_end(struct ieee80211com *);
194static void bwn_set_channel(struct ieee80211com *);
195static struct ieee80211vap *bwn_vap_create(struct ieee80211com *,
196 const char [IFNAMSIZ], int, int,
197 int, const uint8_t [IEEE80211_ADDR_LEN],
198 const uint8_t [IEEE80211_ADDR_LEN]);
199static void bwn_vap_delete(struct ieee80211vap *);
200static void bwn_stop(struct bwn_softc *, int);
201static void bwn_stop_locked(struct bwn_softc *, int);
202static int bwn_core_init(struct bwn_mac *);
203static void bwn_core_start(struct bwn_mac *);
204static void bwn_core_exit(struct bwn_mac *);
205static void bwn_bt_disable(struct bwn_mac *);
206static int bwn_chip_init(struct bwn_mac *);
207static uint64_t bwn_hf_read(struct bwn_mac *);
208static void bwn_hf_write(struct bwn_mac *, uint64_t);
209static void bwn_set_txretry(struct bwn_mac *, int, int);
210static void bwn_rate_init(struct bwn_mac *);
211static void bwn_set_phytxctl(struct bwn_mac *);
212static void bwn_spu_setdelay(struct bwn_mac *, int);
213static void bwn_bt_enable(struct bwn_mac *);
214static void bwn_set_macaddr(struct bwn_mac *);
215static void bwn_crypt_init(struct bwn_mac *);
216static void bwn_chip_exit(struct bwn_mac *);
217static int bwn_fw_fillinfo(struct bwn_mac *);
218static int bwn_fw_loaducode(struct bwn_mac *);
219static int bwn_gpio_init(struct bwn_mac *);
220static int bwn_fw_loadinitvals(struct bwn_mac *);
221static int bwn_phy_init(struct bwn_mac *);
222static void bwn_set_txantenna(struct bwn_mac *, int);
223static void bwn_set_opmode(struct bwn_mac *);
224static void bwn_rate_write(struct bwn_mac *, uint16_t, int);
225static uint8_t bwn_plcp_getcck(const uint8_t);
226static uint8_t bwn_plcp_getofdm(const uint8_t);
227static void bwn_pio_init(struct bwn_mac *);
228static uint16_t bwn_pio_idx2base(struct bwn_mac *, int);
229static void bwn_pio_set_txqueue(struct bwn_mac *, struct bwn_pio_txqueue *,
230 int);
231static void bwn_pio_setupqueue_rx(struct bwn_mac *,
232 struct bwn_pio_rxqueue *, int);
233static void bwn_destroy_queue_tx(struct bwn_pio_txqueue *);
234static uint16_t bwn_pio_read_2(struct bwn_mac *, struct bwn_pio_txqueue *,
235 uint16_t);
236static void bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *);
237static int bwn_pio_rx(struct bwn_pio_rxqueue *);
238static uint8_t bwn_pio_rxeof(struct bwn_pio_rxqueue *);
239static void bwn_pio_handle_txeof(struct bwn_mac *,
240 const struct bwn_txstatus *);
241static uint16_t bwn_pio_rx_read_2(struct bwn_pio_rxqueue *, uint16_t);
242static uint32_t bwn_pio_rx_read_4(struct bwn_pio_rxqueue *, uint16_t);
243static void bwn_pio_rx_write_2(struct bwn_pio_rxqueue *, uint16_t,
244 uint16_t);
245static void bwn_pio_rx_write_4(struct bwn_pio_rxqueue *, uint16_t,
246 uint32_t);
247static int bwn_pio_tx_start(struct bwn_mac *, struct ieee80211_node *,
248 struct mbuf *);
249static struct bwn_pio_txqueue *bwn_pio_select(struct bwn_mac *, uint8_t);
250static uint32_t bwn_pio_write_multi_4(struct bwn_mac *,
251 struct bwn_pio_txqueue *, uint32_t, const void *, int);
252static void bwn_pio_write_4(struct bwn_mac *, struct bwn_pio_txqueue *,
253 uint16_t, uint32_t);
254static uint16_t bwn_pio_write_multi_2(struct bwn_mac *,
255 struct bwn_pio_txqueue *, uint16_t, const void *, int);
256static uint16_t bwn_pio_write_mbuf_2(struct bwn_mac *,
257 struct bwn_pio_txqueue *, uint16_t, struct mbuf *);
258static struct bwn_pio_txqueue *bwn_pio_parse_cookie(struct bwn_mac *,
259 uint16_t, struct bwn_pio_txpkt **);
260static void bwn_dma_init(struct bwn_mac *);
261static void bwn_dma_rxdirectfifo(struct bwn_mac *, int, uint8_t);
262static int bwn_dma_mask2type(uint64_t);
263static uint64_t bwn_dma_mask(struct bwn_mac *);
264static uint16_t bwn_dma_base(int, int);
265static void bwn_dma_ringfree(struct bwn_dma_ring **);
266static void bwn_dma_32_getdesc(struct bwn_dma_ring *,
267 int, struct bwn_dmadesc_generic **,
268 struct bwn_dmadesc_meta **);
269static void bwn_dma_32_setdesc(struct bwn_dma_ring *,
270 struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int,
271 int, int);
272static void bwn_dma_32_start_transfer(struct bwn_dma_ring *, int);
273static void bwn_dma_32_suspend(struct bwn_dma_ring *);
274static void bwn_dma_32_resume(struct bwn_dma_ring *);
275static int bwn_dma_32_get_curslot(struct bwn_dma_ring *);
276static void bwn_dma_32_set_curslot(struct bwn_dma_ring *, int);
277static void bwn_dma_64_getdesc(struct bwn_dma_ring *,
278 int, struct bwn_dmadesc_generic **,
279 struct bwn_dmadesc_meta **);
280static void bwn_dma_64_setdesc(struct bwn_dma_ring *,
281 struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int,
282 int, int);
283static void bwn_dma_64_start_transfer(struct bwn_dma_ring *, int);
284static void bwn_dma_64_suspend(struct bwn_dma_ring *);
285static void bwn_dma_64_resume(struct bwn_dma_ring *);
286static int bwn_dma_64_get_curslot(struct bwn_dma_ring *);
287static void bwn_dma_64_set_curslot(struct bwn_dma_ring *, int);
288static int bwn_dma_allocringmemory(struct bwn_dma_ring *);
289static void bwn_dma_setup(struct bwn_dma_ring *);
290static void bwn_dma_free_ringmemory(struct bwn_dma_ring *);
291static void bwn_dma_cleanup(struct bwn_dma_ring *);
292static void bwn_dma_free_descbufs(struct bwn_dma_ring *);
293static int bwn_dma_tx_reset(struct bwn_mac *, uint16_t, int);
294static void bwn_dma_rx(struct bwn_dma_ring *);
295static int bwn_dma_rx_reset(struct bwn_mac *, uint16_t, int);
296static void bwn_dma_free_descbuf(struct bwn_dma_ring *,
297 struct bwn_dmadesc_meta *);
298static void bwn_dma_set_redzone(struct bwn_dma_ring *, struct mbuf *);
299static int bwn_dma_gettype(struct bwn_mac *);
300static void bwn_dma_ring_addr(void *, bus_dma_segment_t *, int, int);
301static int bwn_dma_freeslot(struct bwn_dma_ring *);
302static int bwn_dma_nextslot(struct bwn_dma_ring *, int);
303static void bwn_dma_rxeof(struct bwn_dma_ring *, int *);
304static int bwn_dma_newbuf(struct bwn_dma_ring *,
305 struct bwn_dmadesc_generic *, struct bwn_dmadesc_meta *,
306 int);
307static void bwn_dma_buf_addr(void *, bus_dma_segment_t *, int,
308 bus_size_t, int);
309static uint8_t bwn_dma_check_redzone(struct bwn_dma_ring *, struct mbuf *);
310static void bwn_dma_handle_txeof(struct bwn_mac *,
311 const struct bwn_txstatus *);
312static int bwn_dma_tx_start(struct bwn_mac *, struct ieee80211_node *,
313 struct mbuf *);
314static int bwn_dma_getslot(struct bwn_dma_ring *);
315static struct bwn_dma_ring *bwn_dma_select(struct bwn_mac *,
316 uint8_t);
317static int bwn_dma_attach(struct bwn_mac *);
318static struct bwn_dma_ring *bwn_dma_ringsetup(struct bwn_mac *,
319 int, int, int);
320static struct bwn_dma_ring *bwn_dma_parse_cookie(struct bwn_mac *,
321 const struct bwn_txstatus *, uint16_t, int *);
322static void bwn_dma_free(struct bwn_mac *);
323static void bwn_phy_g_init_sub(struct bwn_mac *);
324static uint8_t bwn_has_hwpctl(struct bwn_mac *);
325static void bwn_phy_init_b5(struct bwn_mac *);
326static void bwn_phy_init_b6(struct bwn_mac *);
327static void bwn_phy_init_a(struct bwn_mac *);
328static void bwn_loopback_calcgain(struct bwn_mac *);
329static uint16_t bwn_rf_init_bcm2050(struct bwn_mac *);
330static void bwn_lo_g_init(struct bwn_mac *);
331static void bwn_lo_g_adjust(struct bwn_mac *);
332static void bwn_lo_get_powervector(struct bwn_mac *);
333static struct bwn_lo_calib *bwn_lo_calibset(struct bwn_mac *,
334 const struct bwn_bbatt *, const struct bwn_rfatt *);
335static void bwn_lo_write(struct bwn_mac *, struct bwn_loctl *);
336static void bwn_phy_hwpctl_init(struct bwn_mac *);
337static void bwn_phy_g_switch_chan(struct bwn_mac *, int, uint8_t);
338static void bwn_phy_g_set_txpwr_sub(struct bwn_mac *,
339 const struct bwn_bbatt *, const struct bwn_rfatt *,
340 uint8_t);
341static void bwn_phy_g_set_bbatt(struct bwn_mac *, uint16_t);
342static uint16_t bwn_rf_2050_rfoverval(struct bwn_mac *, uint16_t, uint32_t);
343static void bwn_spu_workaround(struct bwn_mac *, uint8_t);
344static void bwn_wa_init(struct bwn_mac *);
345static void bwn_ofdmtab_write_2(struct bwn_mac *, uint16_t, uint16_t,
346 uint16_t);
347static void bwn_dummy_transmission(struct bwn_mac *, int, int);
348static void bwn_ofdmtab_write_4(struct bwn_mac *, uint16_t, uint16_t,
349 uint32_t);
350static void bwn_gtab_write(struct bwn_mac *, uint16_t, uint16_t,
351 uint16_t);
352static void bwn_ram_write(struct bwn_mac *, uint16_t, uint32_t);
353static void bwn_mac_suspend(struct bwn_mac *);
354static void bwn_mac_enable(struct bwn_mac *);
355static void bwn_psctl(struct bwn_mac *, uint32_t);
356static int16_t bwn_nrssi_read(struct bwn_mac *, uint16_t);
357static void bwn_nrssi_offset(struct bwn_mac *);
358static void bwn_nrssi_threshold(struct bwn_mac *);
359static void bwn_nrssi_slope_11g(struct bwn_mac *);
360static void bwn_set_all_gains(struct bwn_mac *, int16_t, int16_t,
361 int16_t);
362static void bwn_set_original_gains(struct bwn_mac *);
363static void bwn_hwpctl_early_init(struct bwn_mac *);
364static void bwn_hwpctl_init_gphy(struct bwn_mac *);
365static uint16_t bwn_phy_g_chan2freq(uint8_t);
366static int bwn_fw_gets(struct bwn_mac *, enum bwn_fwtype);
367static int bwn_fw_get(struct bwn_mac *, enum bwn_fwtype,
368 const char *, struct bwn_fwfile *);
369static void bwn_release_firmware(struct bwn_mac *);
370static void bwn_do_release_fw(struct bwn_fwfile *);
371static uint16_t bwn_fwcaps_read(struct bwn_mac *);
372static int bwn_fwinitvals_write(struct bwn_mac *,
373 const struct bwn_fwinitvals *, size_t, size_t);
374static int bwn_switch_channel(struct bwn_mac *, int);
375static uint16_t bwn_ant2phy(int);
376static void bwn_mac_write_bssid(struct bwn_mac *);
377static void bwn_mac_setfilter(struct bwn_mac *, uint16_t,
378 const uint8_t *);
379static void bwn_key_dowrite(struct bwn_mac *, uint8_t, uint8_t,
380 const uint8_t *, size_t, const uint8_t *);
381static void bwn_key_macwrite(struct bwn_mac *, uint8_t,
382 const uint8_t *);
383static void bwn_key_write(struct bwn_mac *, uint8_t, uint8_t,
384 const uint8_t *);
385static void bwn_phy_exit(struct bwn_mac *);
386static void bwn_core_stop(struct bwn_mac *);
387static int bwn_switch_band(struct bwn_softc *,
388 struct ieee80211_channel *);
389static void bwn_phy_reset(struct bwn_mac *);
390static int bwn_newstate(struct ieee80211vap *, enum ieee80211_state, int);
391static void bwn_set_pretbtt(struct bwn_mac *);
392static int bwn_intr(void *);
393static void bwn_intrtask(void *, int);
394static void bwn_restart(struct bwn_mac *, const char *);
395static void bwn_intr_ucode_debug(struct bwn_mac *);
396static void bwn_intr_tbtt_indication(struct bwn_mac *);
397static void bwn_intr_atim_end(struct bwn_mac *);
398static void bwn_intr_beacon(struct bwn_mac *);
399static void bwn_intr_pmq(struct bwn_mac *);
400static void bwn_intr_noise(struct bwn_mac *);
401static void bwn_intr_txeof(struct bwn_mac *);
402static void bwn_hwreset(void *, int);
403static void bwn_handle_fwpanic(struct bwn_mac *);
404static void bwn_load_beacon0(struct bwn_mac *);
405static void bwn_load_beacon1(struct bwn_mac *);
406static uint32_t bwn_jssi_read(struct bwn_mac *);
407static void bwn_noise_gensample(struct bwn_mac *);
408static void bwn_handle_txeof(struct bwn_mac *,
409 const struct bwn_txstatus *);
410static void bwn_rxeof(struct bwn_mac *, struct mbuf *, const void *);
411static void bwn_phy_txpower_check(struct bwn_mac *, uint32_t);
412static void bwn_start_locked(struct ifnet *);
413static int bwn_tx_start(struct bwn_softc *, struct ieee80211_node *,
414 struct mbuf *);
415static int bwn_tx_isfull(struct bwn_softc *, struct mbuf *);
416static int bwn_set_txhdr(struct bwn_mac *,
417 struct ieee80211_node *, struct mbuf *, struct bwn_txhdr *,
418 uint16_t);
419static void bwn_plcp_genhdr(struct bwn_plcp4 *, const uint16_t,
420 const uint8_t);
421static uint8_t bwn_antenna_sanitize(struct bwn_mac *, uint8_t);
422static uint8_t bwn_get_fbrate(uint8_t);
423static int bwn_phy_shm_tssi_read(struct bwn_mac *, uint16_t);
424static void bwn_phy_g_setatt(struct bwn_mac *, int *, int *);
425static void bwn_phy_lock(struct bwn_mac *);
426static void bwn_phy_unlock(struct bwn_mac *);
427static void bwn_rf_lock(struct bwn_mac *);
428static void bwn_rf_unlock(struct bwn_mac *);
429static void bwn_txpwr(void *, int);
430static void bwn_tasks(void *);
431static void bwn_task_15s(struct bwn_mac *);
432static void bwn_task_30s(struct bwn_mac *);
433static void bwn_task_60s(struct bwn_mac *);
434static int bwn_plcp_get_ofdmrate(struct bwn_mac *, struct bwn_plcp6 *,
435 uint8_t);
436static int bwn_plcp_get_cckrate(struct bwn_mac *, struct bwn_plcp6 *);
437static void bwn_rx_radiotap(struct bwn_mac *, struct mbuf *,
438 const struct bwn_rxhdr4 *, struct bwn_plcp6 *, int,
439 int, int);
440static void bwn_tsf_read(struct bwn_mac *, uint64_t *);
441static void bwn_phy_g_dc_lookup_init(struct bwn_mac *, uint8_t);
442static void bwn_set_slot_time(struct bwn_mac *, uint16_t);
443static void bwn_watchdog(void *);
444static void bwn_dma_stop(struct bwn_mac *);
445static void bwn_pio_stop(struct bwn_mac *);
446static void bwn_dma_ringstop(struct bwn_dma_ring **);
447static void bwn_led_attach(struct bwn_mac *);
448static void bwn_led_newstate(struct bwn_mac *, enum ieee80211_state);
449static void bwn_led_event(struct bwn_mac *, int);
450static void bwn_led_blink_start(struct bwn_mac *, int, int);
451static void bwn_led_blink_next(void *);
452static void bwn_led_blink_end(void *);
453static void bwn_rfswitch(void *);
454static void bwn_rf_turnon(struct bwn_mac *);
455static void bwn_rf_turnoff(struct bwn_mac *);
456static void bwn_phy_lp_init_pre(struct bwn_mac *);
457static int bwn_phy_lp_init(struct bwn_mac *);
458static uint16_t bwn_phy_lp_read(struct bwn_mac *, uint16_t);
459static void bwn_phy_lp_write(struct bwn_mac *, uint16_t, uint16_t);
460static void bwn_phy_lp_maskset(struct bwn_mac *, uint16_t, uint16_t,
461 uint16_t);
462static uint16_t bwn_phy_lp_rf_read(struct bwn_mac *, uint16_t);
463static void bwn_phy_lp_rf_write(struct bwn_mac *, uint16_t, uint16_t);
464static void bwn_phy_lp_rf_onoff(struct bwn_mac *, int);
465static int bwn_phy_lp_switch_channel(struct bwn_mac *, uint32_t);
466static uint32_t bwn_phy_lp_get_default_chan(struct bwn_mac *);
467static void bwn_phy_lp_set_antenna(struct bwn_mac *, int);
468static void bwn_phy_lp_task_60s(struct bwn_mac *);
469static void bwn_phy_lp_readsprom(struct bwn_mac *);
470static void bwn_phy_lp_bbinit(struct bwn_mac *);
471static void bwn_phy_lp_txpctl_init(struct bwn_mac *);
472static void bwn_phy_lp_calib(struct bwn_mac *);
473static void bwn_phy_lp_switch_analog(struct bwn_mac *, int);
474static int bwn_phy_lp_b2062_switch_channel(struct bwn_mac *, uint8_t);
475static int bwn_phy_lp_b2063_switch_channel(struct bwn_mac *, uint8_t);
476static void bwn_phy_lp_set_anafilter(struct bwn_mac *, uint8_t);
477static void bwn_phy_lp_set_gaintbl(struct bwn_mac *, uint32_t);
478static void bwn_phy_lp_digflt_save(struct bwn_mac *);
479static void bwn_phy_lp_get_txpctlmode(struct bwn_mac *);
480static void bwn_phy_lp_set_txpctlmode(struct bwn_mac *, uint8_t);
481static void bwn_phy_lp_bugfix(struct bwn_mac *);
482static void bwn_phy_lp_digflt_restore(struct bwn_mac *);
483static void bwn_phy_lp_tblinit(struct bwn_mac *);
484static void bwn_phy_lp_bbinit_r2(struct bwn_mac *);
485static void bwn_phy_lp_bbinit_r01(struct bwn_mac *);
486static void bwn_phy_lp_b2062_init(struct bwn_mac *);
487static void bwn_phy_lp_b2063_init(struct bwn_mac *);
488static void bwn_phy_lp_rxcal_r2(struct bwn_mac *);
489static void bwn_phy_lp_rccal_r12(struct bwn_mac *);
490static void bwn_phy_lp_set_rccap(struct bwn_mac *);
491static uint32_t bwn_phy_lp_roundup(uint32_t, uint32_t, uint8_t);
492static void bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *);
493static void bwn_phy_lp_b2062_vco_calib(struct bwn_mac *);
494static void bwn_tab_write_multi(struct bwn_mac *, uint32_t, int,
495 const void *);
496static void bwn_tab_read_multi(struct bwn_mac *, uint32_t, int, void *);
497static struct bwn_txgain
498 bwn_phy_lp_get_txgain(struct bwn_mac *);
499static uint8_t bwn_phy_lp_get_bbmult(struct bwn_mac *);
500static void bwn_phy_lp_set_txgain(struct bwn_mac *, struct bwn_txgain *);
501static void bwn_phy_lp_set_bbmult(struct bwn_mac *, uint8_t);
502static void bwn_phy_lp_set_trsw_over(struct bwn_mac *, uint8_t, uint8_t);
503static void bwn_phy_lp_set_rxgain(struct bwn_mac *, uint32_t);
504static void bwn_phy_lp_set_deaf(struct bwn_mac *, uint8_t);
505static int bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *, uint16_t);
506static void bwn_phy_lp_clear_deaf(struct bwn_mac *, uint8_t);
507static void bwn_phy_lp_tblinit_r01(struct bwn_mac *);
508static void bwn_phy_lp_tblinit_r2(struct bwn_mac *);
509static void bwn_phy_lp_tblinit_txgain(struct bwn_mac *);
510static void bwn_tab_write(struct bwn_mac *, uint32_t, uint32_t);
511static void bwn_phy_lp_b2062_tblinit(struct bwn_mac *);
512static void bwn_phy_lp_b2063_tblinit(struct bwn_mac *);
513static int bwn_phy_lp_loopback(struct bwn_mac *);
514static void bwn_phy_lp_set_rxgain_idx(struct bwn_mac *, uint16_t);
515static void bwn_phy_lp_ddfs_turnon(struct bwn_mac *, int, int, int, int,
516 int);
517static uint8_t bwn_phy_lp_rx_iq_est(struct bwn_mac *, uint16_t, uint8_t,
518 struct bwn_phy_lp_iq_est *);
519static void bwn_phy_lp_ddfs_turnoff(struct bwn_mac *);
520static uint32_t bwn_tab_read(struct bwn_mac *, uint32_t);
521static void bwn_phy_lp_set_txgain_dac(struct bwn_mac *, uint16_t);
522static void bwn_phy_lp_set_txgain_pa(struct bwn_mac *, uint16_t);
523static void bwn_phy_lp_set_txgain_override(struct bwn_mac *);
524static uint16_t bwn_phy_lp_get_pa_gain(struct bwn_mac *);
525static uint8_t bwn_nbits(int32_t);
526static void bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *, int, int,
527 struct bwn_txgain_entry *);
528static void bwn_phy_lp_gaintbl_write(struct bwn_mac *, int,
529 struct bwn_txgain_entry);
530static void bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *, int,
531 struct bwn_txgain_entry);
532static void bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *, int,
533 struct bwn_txgain_entry);
534static void bwn_sysctl_node(struct bwn_softc *);
535
536static struct resource_spec bwn_res_spec_legacy[] = {
537 { SYS_RES_IRQ, 0, RF_ACTIVE | RF_SHAREABLE },
538 { -1, 0, 0 }
539};
540
541static struct resource_spec bwn_res_spec_msi[] = {
542 { SYS_RES_IRQ, 1, RF_ACTIVE },
543 { -1, 0, 0 }
544};
545
546static const struct bwn_channelinfo bwn_chantable_bg = {
547 .channels = {
548 { 2412, 1, 30 }, { 2417, 2, 30 }, { 2422, 3, 30 },
549 { 2427, 4, 30 }, { 2432, 5, 30 }, { 2437, 6, 30 },
550 { 2442, 7, 30 }, { 2447, 8, 30 }, { 2452, 9, 30 },
551 { 2457, 10, 30 }, { 2462, 11, 30 }, { 2467, 12, 30 },
552 { 2472, 13, 30 }, { 2484, 14, 30 } },
553 .nchannels = 14
554};
555
556static const struct bwn_channelinfo bwn_chantable_a = {
557 .channels = {
558 { 5170, 34, 30 }, { 5180, 36, 30 }, { 5190, 38, 30 },
559 { 5200, 40, 30 }, { 5210, 42, 30 }, { 5220, 44, 30 },
560 { 5230, 46, 30 }, { 5240, 48, 30 }, { 5260, 52, 30 },
561 { 5280, 56, 30 }, { 5300, 60, 30 }, { 5320, 64, 30 },
562 { 5500, 100, 30 }, { 5520, 104, 30 }, { 5540, 108, 30 },
563 { 5560, 112, 30 }, { 5580, 116, 30 }, { 5600, 120, 30 },
564 { 5620, 124, 30 }, { 5640, 128, 30 }, { 5660, 132, 30 },
565 { 5680, 136, 30 }, { 5700, 140, 30 }, { 5745, 149, 30 },
566 { 5765, 153, 30 }, { 5785, 157, 30 }, { 5805, 161, 30 },
567 { 5825, 165, 30 }, { 5920, 184, 30 }, { 5940, 188, 30 },
568 { 5960, 192, 30 }, { 5980, 196, 30 }, { 6000, 200, 30 },
569 { 6020, 204, 30 }, { 6040, 208, 30 }, { 6060, 212, 30 },
570 { 6080, 216, 30 } },
571 .nchannels = 37
572};
573
574static const struct bwn_channelinfo bwn_chantable_n = {
575 .channels = {
576 { 5160, 32, 30 }, { 5170, 34, 30 }, { 5180, 36, 30 },
577 { 5190, 38, 30 }, { 5200, 40, 30 }, { 5210, 42, 30 },
578 { 5220, 44, 30 }, { 5230, 46, 30 }, { 5240, 48, 30 },
579 { 5250, 50, 30 }, { 5260, 52, 30 }, { 5270, 54, 30 },
580 { 5280, 56, 30 }, { 5290, 58, 30 }, { 5300, 60, 30 },
581 { 5310, 62, 30 }, { 5320, 64, 30 }, { 5330, 66, 30 },
582 { 5340, 68, 30 }, { 5350, 70, 30 }, { 5360, 72, 30 },
583 { 5370, 74, 30 }, { 5380, 76, 30 }, { 5390, 78, 30 },
584 { 5400, 80, 30 }, { 5410, 82, 30 }, { 5420, 84, 30 },
585 { 5430, 86, 30 }, { 5440, 88, 30 }, { 5450, 90, 30 },
586 { 5460, 92, 30 }, { 5470, 94, 30 }, { 5480, 96, 30 },
587 { 5490, 98, 30 }, { 5500, 100, 30 }, { 5510, 102, 30 },
588 { 5520, 104, 30 }, { 5530, 106, 30 }, { 5540, 108, 30 },
589 { 5550, 110, 30 }, { 5560, 112, 30 }, { 5570, 114, 30 },
590 { 5580, 116, 30 }, { 5590, 118, 30 }, { 5600, 120, 30 },
591 { 5610, 122, 30 }, { 5620, 124, 30 }, { 5630, 126, 30 },
592 { 5640, 128, 30 }, { 5650, 130, 30 }, { 5660, 132, 30 },
593 { 5670, 134, 30 }, { 5680, 136, 30 }, { 5690, 138, 30 },
594 { 5700, 140, 30 }, { 5710, 142, 30 }, { 5720, 144, 30 },
595 { 5725, 145, 30 }, { 5730, 146, 30 }, { 5735, 147, 30 },
596 { 5740, 148, 30 }, { 5745, 149, 30 }, { 5750, 150, 30 },
597 { 5755, 151, 30 }, { 5760, 152, 30 }, { 5765, 153, 30 },
598 { 5770, 154, 30 }, { 5775, 155, 30 }, { 5780, 156, 30 },
599 { 5785, 157, 30 }, { 5790, 158, 30 }, { 5795, 159, 30 },
600 { 5800, 160, 30 }, { 5805, 161, 30 }, { 5810, 162, 30 },
601 { 5815, 163, 30 }, { 5820, 164, 30 }, { 5825, 165, 30 },
602 { 5830, 166, 30 }, { 5840, 168, 30 }, { 5850, 170, 30 },
603 { 5860, 172, 30 }, { 5870, 174, 30 }, { 5880, 176, 30 },
604 { 5890, 178, 30 }, { 5900, 180, 30 }, { 5910, 182, 30 },
605 { 5920, 184, 30 }, { 5930, 186, 30 }, { 5940, 188, 30 },
606 { 5950, 190, 30 }, { 5960, 192, 30 }, { 5970, 194, 30 },
607 { 5980, 196, 30 }, { 5990, 198, 30 }, { 6000, 200, 30 },
608 { 6010, 202, 30 }, { 6020, 204, 30 }, { 6030, 206, 30 },
609 { 6040, 208, 30 }, { 6050, 210, 30 }, { 6060, 212, 30 },
610 { 6070, 214, 30 }, { 6080, 216, 30 }, { 6090, 218, 30 },
611 { 6100, 220, 30 }, { 6110, 222, 30 }, { 6120, 224, 30 },
612 { 6130, 226, 30 }, { 6140, 228, 30 } },
613 .nchannels = 110
614};
615
616static const uint8_t bwn_b2063_chantable_data[33][12] = {
617 { 0x6f, 0x3c, 0x3c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
618 { 0x6f, 0x2c, 0x2c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
619 { 0x6f, 0x1c, 0x1c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
620 { 0x6e, 0x1c, 0x1c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
621 { 0x6e, 0xc, 0xc, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
622 { 0x6a, 0xc, 0xc, 0, 0x2, 0x5, 0xd, 0xd, 0x77, 0x80, 0x20, 0 },
623 { 0x6a, 0xc, 0xc, 0, 0x1, 0x5, 0xd, 0xc, 0x77, 0x80, 0x20, 0 },
624 { 0x6a, 0xc, 0xc, 0, 0x1, 0x4, 0xc, 0xc, 0x77, 0x80, 0x20, 0 },
625 { 0x69, 0xc, 0xc, 0, 0x1, 0x4, 0xc, 0xc, 0x77, 0x70, 0x20, 0 },
626 { 0x69, 0xc, 0xc, 0, 0x1, 0x4, 0xb, 0xc, 0x77, 0x70, 0x20, 0 },
627 { 0x69, 0xc, 0xc, 0, 0, 0x4, 0xb, 0xb, 0x77, 0x60, 0x20, 0 },
628 { 0x69, 0xc, 0xc, 0, 0, 0x3, 0xa, 0xb, 0x77, 0x60, 0x20, 0 },
629 { 0x69, 0xc, 0xc, 0, 0, 0x3, 0xa, 0xa, 0x77, 0x60, 0x20, 0 },
630 { 0x68, 0xc, 0xc, 0, 0, 0x2, 0x9, 0x9, 0x77, 0x60, 0x20, 0 },
631 { 0x68, 0xc, 0xc, 0, 0, 0x1, 0x8, 0x8, 0x77, 0x50, 0x10, 0 },
632 { 0x67, 0xc, 0xc, 0, 0, 0, 0x8, 0x8, 0x77, 0x50, 0x10, 0 },
633 { 0x64, 0xc, 0xc, 0, 0, 0, 0x2, 0x1, 0x77, 0x20, 0, 0 },
634 { 0x64, 0xc, 0xc, 0, 0, 0, 0x1, 0x1, 0x77, 0x20, 0, 0 },
635 { 0x63, 0xc, 0xc, 0, 0, 0, 0x1, 0, 0x77, 0x10, 0, 0 },
636 { 0x63, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0x10, 0, 0 },
637 { 0x62, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0x10, 0, 0 },
638 { 0x62, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
639 { 0x61, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
640 { 0x60, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
641 { 0x6e, 0xc, 0xc, 0, 0x9, 0xe, 0xf, 0xf, 0x77, 0xc0, 0x50, 0 },
642 { 0x6e, 0xc, 0xc, 0, 0x9, 0xd, 0xf, 0xf, 0x77, 0xb0, 0x50, 0 },
643 { 0x6e, 0xc, 0xc, 0, 0x8, 0xc, 0xf, 0xf, 0x77, 0xb0, 0x50, 0 },
644 { 0x6d, 0xc, 0xc, 0, 0x8, 0xc, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
645 { 0x6d, 0xc, 0xc, 0, 0x8, 0xb, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
646 { 0x6d, 0xc, 0xc, 0, 0x8, 0xa, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
647 { 0x6c, 0xc, 0xc, 0, 0x7, 0x9, 0xf, 0xf, 0x77, 0x90, 0x40, 0 },
648 { 0x6c, 0xc, 0xc, 0, 0x6, 0x8, 0xf, 0xf, 0x77, 0x90, 0x40, 0 },
649 { 0x6c, 0xc, 0xc, 0, 0x5, 0x8, 0xf, 0xf, 0x77, 0x90, 0x40, 0 }
650};
651
652static const struct bwn_b206x_chan bwn_b2063_chantable[] = {
653 { 1, 2412, bwn_b2063_chantable_data[0] },
654 { 2, 2417, bwn_b2063_chantable_data[0] },
655 { 3, 2422, bwn_b2063_chantable_data[0] },
656 { 4, 2427, bwn_b2063_chantable_data[1] },
657 { 5, 2432, bwn_b2063_chantable_data[1] },
658 { 6, 2437, bwn_b2063_chantable_data[1] },
659 { 7, 2442, bwn_b2063_chantable_data[1] },
660 { 8, 2447, bwn_b2063_chantable_data[1] },
661 { 9, 2452, bwn_b2063_chantable_data[2] },
662 { 10, 2457, bwn_b2063_chantable_data[2] },
663 { 11, 2462, bwn_b2063_chantable_data[3] },
664 { 12, 2467, bwn_b2063_chantable_data[3] },
665 { 13, 2472, bwn_b2063_chantable_data[3] },
666 { 14, 2484, bwn_b2063_chantable_data[4] },
667 { 34, 5170, bwn_b2063_chantable_data[5] },
668 { 36, 5180, bwn_b2063_chantable_data[6] },
669 { 38, 5190, bwn_b2063_chantable_data[7] },
670 { 40, 5200, bwn_b2063_chantable_data[8] },
671 { 42, 5210, bwn_b2063_chantable_data[9] },
672 { 44, 5220, bwn_b2063_chantable_data[10] },
673 { 46, 5230, bwn_b2063_chantable_data[11] },
674 { 48, 5240, bwn_b2063_chantable_data[12] },
675 { 52, 5260, bwn_b2063_chantable_data[13] },
676 { 56, 5280, bwn_b2063_chantable_data[14] },
677 { 60, 5300, bwn_b2063_chantable_data[14] },
678 { 64, 5320, bwn_b2063_chantable_data[15] },
679 { 100, 5500, bwn_b2063_chantable_data[16] },
680 { 104, 5520, bwn_b2063_chantable_data[17] },
681 { 108, 5540, bwn_b2063_chantable_data[18] },
682 { 112, 5560, bwn_b2063_chantable_data[19] },
683 { 116, 5580, bwn_b2063_chantable_data[20] },
684 { 120, 5600, bwn_b2063_chantable_data[21] },
685 { 124, 5620, bwn_b2063_chantable_data[21] },
686 { 128, 5640, bwn_b2063_chantable_data[22] },
687 { 132, 5660, bwn_b2063_chantable_data[22] },
688 { 136, 5680, bwn_b2063_chantable_data[22] },
689 { 140, 5700, bwn_b2063_chantable_data[23] },
690 { 149, 5745, bwn_b2063_chantable_data[23] },
691 { 153, 5765, bwn_b2063_chantable_data[23] },
692 { 157, 5785, bwn_b2063_chantable_data[23] },
693 { 161, 5805, bwn_b2063_chantable_data[23] },
694 { 165, 5825, bwn_b2063_chantable_data[23] },
695 { 184, 4920, bwn_b2063_chantable_data[24] },
696 { 188, 4940, bwn_b2063_chantable_data[25] },
697 { 192, 4960, bwn_b2063_chantable_data[26] },
698 { 196, 4980, bwn_b2063_chantable_data[27] },
699 { 200, 5000, bwn_b2063_chantable_data[28] },
700 { 204, 5020, bwn_b2063_chantable_data[29] },
701 { 208, 5040, bwn_b2063_chantable_data[30] },
702 { 212, 5060, bwn_b2063_chantable_data[31] },
703 { 216, 5080, bwn_b2063_chantable_data[32] }
704};
705
706static const uint8_t bwn_b2062_chantable_data[22][12] = {
707 { 0xff, 0xff, 0xb5, 0x1b, 0x24, 0x32, 0x32, 0x88, 0x88, 0, 0, 0 },
708 { 0, 0x22, 0x20, 0x84, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
709 { 0, 0x11, 0x10, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
710 { 0, 0, 0, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
711 { 0, 0x11, 0x20, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
712 { 0, 0x11, 0x10, 0x84, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
713 { 0, 0x11, 0, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
714 { 0, 0, 0, 0x63, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
715 { 0, 0, 0, 0x62, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
716 { 0, 0, 0, 0x30, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
717 { 0, 0, 0, 0x20, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
718 { 0, 0, 0, 0x10, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
719 { 0, 0, 0, 0, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
720 { 0x55, 0x77, 0x90, 0xf7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
721 { 0x44, 0x77, 0x80, 0xe7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
722 { 0x44, 0x66, 0x80, 0xe7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
723 { 0x33, 0x66, 0x70, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
724 { 0x22, 0x55, 0x60, 0xd7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
725 { 0x22, 0x55, 0x60, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
726 { 0x22, 0x44, 0x50, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
727 { 0x11, 0x44, 0x50, 0xa5, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
728 { 0, 0x44, 0x40, 0xb6, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 }
729};
730
731static const struct bwn_b206x_chan bwn_b2062_chantable[] = {
732 { 1, 2412, bwn_b2062_chantable_data[0] },
733 { 2, 2417, bwn_b2062_chantable_data[0] },
734 { 3, 2422, bwn_b2062_chantable_data[0] },
735 { 4, 2427, bwn_b2062_chantable_data[0] },
736 { 5, 2432, bwn_b2062_chantable_data[0] },
737 { 6, 2437, bwn_b2062_chantable_data[0] },
738 { 7, 2442, bwn_b2062_chantable_data[0] },
739 { 8, 2447, bwn_b2062_chantable_data[0] },
740 { 9, 2452, bwn_b2062_chantable_data[0] },
741 { 10, 2457, bwn_b2062_chantable_data[0] },
742 { 11, 2462, bwn_b2062_chantable_data[0] },
743 { 12, 2467, bwn_b2062_chantable_data[0] },
744 { 13, 2472, bwn_b2062_chantable_data[0] },
745 { 14, 2484, bwn_b2062_chantable_data[0] },
746 { 34, 5170, bwn_b2062_chantable_data[1] },
747 { 38, 5190, bwn_b2062_chantable_data[2] },
748 { 42, 5210, bwn_b2062_chantable_data[2] },
749 { 46, 5230, bwn_b2062_chantable_data[3] },
750 { 36, 5180, bwn_b2062_chantable_data[4] },
751 { 40, 5200, bwn_b2062_chantable_data[5] },
752 { 44, 5220, bwn_b2062_chantable_data[6] },
753 { 48, 5240, bwn_b2062_chantable_data[3] },
754 { 52, 5260, bwn_b2062_chantable_data[3] },
755 { 56, 5280, bwn_b2062_chantable_data[3] },
756 { 60, 5300, bwn_b2062_chantable_data[7] },
757 { 64, 5320, bwn_b2062_chantable_data[8] },
758 { 100, 5500, bwn_b2062_chantable_data[9] },
759 { 104, 5520, bwn_b2062_chantable_data[10] },
760 { 108, 5540, bwn_b2062_chantable_data[10] },
761 { 112, 5560, bwn_b2062_chantable_data[10] },
762 { 116, 5580, bwn_b2062_chantable_data[11] },
763 { 120, 5600, bwn_b2062_chantable_data[12] },
764 { 124, 5620, bwn_b2062_chantable_data[12] },
765 { 128, 5640, bwn_b2062_chantable_data[12] },
766 { 132, 5660, bwn_b2062_chantable_data[12] },
767 { 136, 5680, bwn_b2062_chantable_data[12] },
768 { 140, 5700, bwn_b2062_chantable_data[12] },
769 { 149, 5745, bwn_b2062_chantable_data[12] },
770 { 153, 5765, bwn_b2062_chantable_data[12] },
771 { 157, 5785, bwn_b2062_chantable_data[12] },
772 { 161, 5805, bwn_b2062_chantable_data[12] },
773 { 165, 5825, bwn_b2062_chantable_data[12] },
774 { 184, 4920, bwn_b2062_chantable_data[13] },
775 { 188, 4940, bwn_b2062_chantable_data[14] },
776 { 192, 4960, bwn_b2062_chantable_data[15] },
777 { 196, 4980, bwn_b2062_chantable_data[16] },
778 { 200, 5000, bwn_b2062_chantable_data[17] },
779 { 204, 5020, bwn_b2062_chantable_data[18] },
780 { 208, 5040, bwn_b2062_chantable_data[19] },
781 { 212, 5060, bwn_b2062_chantable_data[20] },
782 { 216, 5080, bwn_b2062_chantable_data[21] }
783};
784
785/* for LP PHY */
786static const struct bwn_rxcompco bwn_rxcompco_5354[] = {
787 { 1, -66, 15 }, { 2, -66, 15 }, { 3, -66, 15 }, { 4, -66, 15 },
788 { 5, -66, 15 }, { 6, -66, 15 }, { 7, -66, 14 }, { 8, -66, 14 },
789 { 9, -66, 14 }, { 10, -66, 14 }, { 11, -66, 14 }, { 12, -66, 13 },
790 { 13, -66, 13 }, { 14, -66, 13 },
791};
792
793/* for LP PHY */
794static const struct bwn_rxcompco bwn_rxcompco_r12[] = {
795 { 1, -64, 13 }, { 2, -64, 13 }, { 3, -64, 13 }, { 4, -64, 13 },
796 { 5, -64, 12 }, { 6, -64, 12 }, { 7, -64, 12 }, { 8, -64, 12 },
797 { 9, -64, 12 }, { 10, -64, 11 }, { 11, -64, 11 }, { 12, -64, 11 },
798 { 13, -64, 11 }, { 14, -64, 10 }, { 34, -62, 24 }, { 38, -62, 24 },
799 { 42, -62, 24 }, { 46, -62, 23 }, { 36, -62, 24 }, { 40, -62, 24 },
800 { 44, -62, 23 }, { 48, -62, 23 }, { 52, -62, 23 }, { 56, -62, 22 },
801 { 60, -62, 22 }, { 64, -62, 22 }, { 100, -62, 16 }, { 104, -62, 16 },
802 { 108, -62, 15 }, { 112, -62, 14 }, { 116, -62, 14 }, { 120, -62, 13 },
803 { 124, -62, 12 }, { 128, -62, 12 }, { 132, -62, 12 }, { 136, -62, 11 },
804 { 140, -62, 10 }, { 149, -61, 9 }, { 153, -61, 9 }, { 157, -61, 9 },
805 { 161, -61, 8 }, { 165, -61, 8 }, { 184, -62, 25 }, { 188, -62, 25 },
806 { 192, -62, 25 }, { 196, -62, 25 }, { 200, -62, 25 }, { 204, -62, 25 },
807 { 208, -62, 25 }, { 212, -62, 25 }, { 216, -62, 26 },
808};
809
810static const struct bwn_rxcompco bwn_rxcompco_r2 = { 0, -64, 0 };
811
812static const uint8_t bwn_tab_sigsq_tbl[] = {
813 0xde, 0xdc, 0xda, 0xd8, 0xd6, 0xd4, 0xd2, 0xcf, 0xcd,
814 0xca, 0xc7, 0xc4, 0xc1, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
815 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0x00,
816 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
817 0xbe, 0xbe, 0xbe, 0xbe, 0xc1, 0xc4, 0xc7, 0xca, 0xcd,
818 0xcf, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
819};
820
821static const uint8_t bwn_tab_pllfrac_tbl[] = {
822 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x80,
823 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
824};
825
826static const uint16_t bwn_tabl_iqlocal_tbl[] = {
827 0x0200, 0x0300, 0x0400, 0x0600, 0x0800, 0x0b00, 0x1000, 0x1001, 0x1002,
828 0x1003, 0x1004, 0x1005, 0x1006, 0x1007, 0x1707, 0x2007, 0x2d07, 0x4007,
829 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
830 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0200, 0x0300, 0x0400, 0x0600,
831 0x0800, 0x0b00, 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006,
832 0x1007, 0x1707, 0x2007, 0x2d07, 0x4007, 0x0000, 0x0000, 0x0000, 0x0000,
833 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
834 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
835 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
836 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4000, 0x0000, 0x0000,
837 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
838 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
839};
840
841static const uint16_t bwn_tab_noise_g1[] = BWN_TAB_NOISE_G1;
842static const uint16_t bwn_tab_noise_g2[] = BWN_TAB_NOISE_G2;
843static const uint16_t bwn_tab_noisescale_g1[] = BWN_TAB_NOISESCALE_G1;
844static const uint16_t bwn_tab_noisescale_g2[] = BWN_TAB_NOISESCALE_G2;
845static const uint16_t bwn_tab_noisescale_g3[] = BWN_TAB_NOISESCALE_G3;
846const uint8_t bwn_bitrev_table[256] = BWN_BITREV_TABLE;
847
848#define VENDOR_LED_ACT(vendor) \
849{ \
850 .vid = PCI_VENDOR_##vendor, \
851 .led_act = { BWN_VENDOR_LED_ACT_##vendor } \
852}
853
854static const struct {
855 uint16_t vid;
856 uint8_t led_act[BWN_LED_MAX];
857} bwn_vendor_led_act[] = {
858 VENDOR_LED_ACT(COMPAQ),
859 VENDOR_LED_ACT(ASUSTEK)
860};
861
862static const uint8_t bwn_default_led_act[BWN_LED_MAX] =
863 { BWN_VENDOR_LED_ACT_DEFAULT };
864
865#undef VENDOR_LED_ACT
866
867static const struct {
868 int on_dur;
869 int off_dur;
870} bwn_led_duration[109] = {
871 [0] = { 400, 100 },
872 [2] = { 150, 75 },
873 [4] = { 90, 45 },
874 [11] = { 66, 34 },
875 [12] = { 53, 26 },
876 [18] = { 42, 21 },
877 [22] = { 35, 17 },
878 [24] = { 32, 16 },
879 [36] = { 21, 10 },
880 [48] = { 16, 8 },
881 [72] = { 11, 5 },
882 [96] = { 9, 4 },
883 [108] = { 7, 3 }
884};
885
886static const uint16_t bwn_wme_shm_offsets[] = {
887 [0] = BWN_WME_BESTEFFORT,
888 [1] = BWN_WME_BACKGROUND,
889 [2] = BWN_WME_VOICE,
890 [3] = BWN_WME_VIDEO,
891};
892
893static const struct siba_devid bwn_devs[] = {
894 SIBA_DEV(BROADCOM, 80211, 5, "Revision 5"),
895 SIBA_DEV(BROADCOM, 80211, 6, "Revision 6"),
896 SIBA_DEV(BROADCOM, 80211, 7, "Revision 7"),
897 SIBA_DEV(BROADCOM, 80211, 9, "Revision 9"),
898 SIBA_DEV(BROADCOM, 80211, 10, "Revision 10"),
899 SIBA_DEV(BROADCOM, 80211, 11, "Revision 11"),
900 SIBA_DEV(BROADCOM, 80211, 13, "Revision 13"),
901 SIBA_DEV(BROADCOM, 80211, 15, "Revision 15"),
902 SIBA_DEV(BROADCOM, 80211, 16, "Revision 16")
903};
904
905static int
906bwn_probe(device_t dev)
907{
908 int i;
909
910 for (i = 0; i < sizeof(bwn_devs) / sizeof(bwn_devs[0]); i++) {
911 if (siba_get_vendor(dev) == bwn_devs[i].sd_vendor &&
912 siba_get_device(dev) == bwn_devs[i].sd_device &&
913 siba_get_revid(dev) == bwn_devs[i].sd_rev)
914 return (BUS_PROBE_DEFAULT);
915 }
916
917 return (ENXIO);
918}
919
920static int
921bwn_attach(device_t dev)
922{
923 struct bwn_mac *mac;
924 struct bwn_softc *sc = device_get_softc(dev);
925 int error, i, msic, reg;
926
927 sc->sc_dev = dev;
928#ifdef BWN_DEBUG
929 sc->sc_debug = bwn_debug;
930#endif
931
932 if ((sc->sc_flags & BWN_FLAG_ATTACHED) == 0) {
933 error = bwn_attach_pre(sc);
934 if (error != 0)
935 return (error);
936 bwn_sprom_bugfixes(dev);
937 sc->sc_flags |= BWN_FLAG_ATTACHED;
938 }
939
940 if (!TAILQ_EMPTY(&sc->sc_maclist)) {
941 if (siba_get_pci_device(dev) != 0x4313 &&
942 siba_get_pci_device(dev) != 0x431a &&
943 siba_get_pci_device(dev) != 0x4321) {
944 device_printf(sc->sc_dev,
945 "skip 802.11 cores\n");
946 return (ENODEV);
947 }
948 }
949
950 mac = (struct bwn_mac *)malloc(sizeof(*mac), M_DEVBUF,
951 M_NOWAIT | M_ZERO);
952 if (mac == NULL)
953 return (ENOMEM);
954 mac->mac_sc = sc;
955 mac->mac_status = BWN_MAC_STATUS_UNINIT;
956 if (bwn_bfp != 0)
957 mac->mac_flags |= BWN_MAC_FLAG_BADFRAME_PREEMP;
958
959 TASK_INIT(&mac->mac_hwreset, 0, bwn_hwreset, mac);
960 TASK_INIT(&mac->mac_intrtask, 0, bwn_intrtask, mac);
961 TASK_INIT(&mac->mac_txpower, 0, bwn_txpwr, mac);
962
963 error = bwn_attach_core(mac);
964 if (error)
965 goto fail0;
966 bwn_led_attach(mac);
967
968 device_printf(sc->sc_dev, "WLAN (chipid %#x rev %u) "
969 "PHY (analog %d type %d rev %d) RADIO (manuf %#x ver %#x rev %d)\n",
970 siba_get_chipid(sc->sc_dev), siba_get_revid(sc->sc_dev),
971 mac->mac_phy.analog, mac->mac_phy.type, mac->mac_phy.rev,
972 mac->mac_phy.rf_manuf, mac->mac_phy.rf_ver,
973 mac->mac_phy.rf_rev);
974 if (mac->mac_flags & BWN_MAC_FLAG_DMA)
975 device_printf(sc->sc_dev, "DMA (%d bits)\n",
976 mac->mac_method.dma.dmatype);
977 else
978 device_printf(sc->sc_dev, "PIO\n");
979
980 /*
981 * setup PCI resources and interrupt.
982 */
983 if (pci_find_cap(dev, PCIY_EXPRESS, ®) == 0) {
984 msic = pci_msi_count(dev);
985 if (bootverbose)
986 device_printf(sc->sc_dev, "MSI count : %d\n", msic);
987 } else
988 msic = 0;
989
990 mac->mac_intr_spec = bwn_res_spec_legacy;
991 if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0) {
992 if (pci_alloc_msi(dev, &msic) == 0) {
993 device_printf(sc->sc_dev,
994 "Using %d MSI messages\n", msic);
995 mac->mac_intr_spec = bwn_res_spec_msi;
996 mac->mac_msi = 1;
997 }
998 }
999
1000 error = bus_alloc_resources(dev, mac->mac_intr_spec,
1001 mac->mac_res_irq);
1002 if (error) {
1003 device_printf(sc->sc_dev,
1004 "couldn't allocate IRQ resources (%d)\n", error);
1005 goto fail1;
1006 }
1007
1008 if (mac->mac_msi == 0)
1009 error = bus_setup_intr(dev, mac->mac_res_irq[0],
1010 INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac,
1011 &mac->mac_intrhand[0]);
1012 else {
1013 for (i = 0; i < BWN_MSI_MESSAGES; i++) {
1014 error = bus_setup_intr(dev, mac->mac_res_irq[i],
1015 INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac,
1016 &mac->mac_intrhand[i]);
1017 if (error != 0) {
1018 device_printf(sc->sc_dev,
1019 "couldn't setup interrupt (%d)\n", error);
1020 break;
1021 }
1022 }
1023 }
1024
1025 TAILQ_INSERT_TAIL(&sc->sc_maclist, mac, mac_list);
1026
1027 /*
1028 * calls attach-post routine
1029 */
1030 if ((sc->sc_flags & BWN_FLAG_ATTACHED) != 0)
1031 bwn_attach_post(sc);
1032
1033 return (0);
1034fail1:
1035 if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0)
1036 pci_release_msi(dev);
1037fail0:
1038 free(mac, M_DEVBUF);
1039 return (error);
1040}
1041
1042static int
1043bwn_is_valid_ether_addr(uint8_t *addr)
1044{
1045 char zero_addr[6] = { 0, 0, 0, 0, 0, 0 };
1046
1047 if ((addr[0] & 1) || (!bcmp(addr, zero_addr, ETHER_ADDR_LEN)))
1048 return (FALSE);
1049
1050 return (TRUE);
1051}
1052
1053static int
1054bwn_attach_post(struct bwn_softc *sc)
1055{
1056 struct ieee80211com *ic;
1057 struct ifnet *ifp = sc->sc_ifp;
1058
1059 ic = ifp->if_l2com;
1060 ic->ic_ifp = ifp;
1061 /* XXX not right but it's not used anywhere important */
1062 ic->ic_phytype = IEEE80211_T_OFDM;
1063 ic->ic_opmode = IEEE80211_M_STA;
1064 ic->ic_caps =
1065 IEEE80211_C_STA /* station mode supported */
1066 | IEEE80211_C_MONITOR /* monitor mode */
1067 | IEEE80211_C_AHDEMO /* adhoc demo mode */
1068 | IEEE80211_C_SHPREAMBLE /* short preamble supported */
1069 | IEEE80211_C_SHSLOT /* short slot time supported */
1070 | IEEE80211_C_WME /* WME/WMM supported */
1071 | IEEE80211_C_WPA /* capable of WPA1+WPA2 */
1072 | IEEE80211_C_BGSCAN /* capable of bg scanning */
1073 | IEEE80211_C_TXPMGT /* capable of txpow mgt */
1074 ;
1075
1076 ic->ic_flags_ext |= IEEE80211_FEXT_SWBMISS; /* s/w bmiss */
1077
1078 /* call MI attach routine. */
1079 ieee80211_ifattach(ic,
1080 bwn_is_valid_ether_addr(siba_sprom_get_mac_80211a(sc->sc_dev)) ?
1081 siba_sprom_get_mac_80211a(sc->sc_dev) :
1082 siba_sprom_get_mac_80211bg(sc->sc_dev));
1083
1084 ic->ic_headroom = sizeof(struct bwn_txhdr);
1085
1086 /* override default methods */
1087 ic->ic_raw_xmit = bwn_raw_xmit;
1088 ic->ic_updateslot = bwn_updateslot;
1089 ic->ic_update_promisc = bwn_update_promisc;
1090 ic->ic_wme.wme_update = bwn_wme_update;
1091
1092 ic->ic_scan_start = bwn_scan_start;
1093 ic->ic_scan_end = bwn_scan_end;
1094 ic->ic_set_channel = bwn_set_channel;
1095
1096 ic->ic_vap_create = bwn_vap_create;
1097 ic->ic_vap_delete = bwn_vap_delete;
1098
1099 ieee80211_radiotap_attach(ic,
1100 &sc->sc_tx_th.wt_ihdr, sizeof(sc->sc_tx_th),
1101 BWN_TX_RADIOTAP_PRESENT,
1102 &sc->sc_rx_th.wr_ihdr, sizeof(sc->sc_rx_th),
1103 BWN_RX_RADIOTAP_PRESENT);
1104
1105 bwn_sysctl_node(sc);
1106
1107 if (bootverbose)
1108 ieee80211_announce(ic);
1109 return (0);
1110}
1111
1112static void
1113bwn_phy_detach(struct bwn_mac *mac)
1114{
1115
1116 if (mac->mac_phy.detach != NULL)
1117 mac->mac_phy.detach(mac);
1118}
1119
1120static int
1121bwn_detach(device_t dev)
1122{
1123 struct bwn_softc *sc = device_get_softc(dev);
1124 struct bwn_mac *mac = sc->sc_curmac;
1125 struct ifnet *ifp = sc->sc_ifp;
1126 struct ieee80211com *ic = ifp->if_l2com;
1127 int i;
1128
1129 sc->sc_flags |= BWN_FLAG_INVALID;
1130
1131 if (device_is_attached(sc->sc_dev)) {
1132 bwn_stop(sc, 1);
1133 bwn_dma_free(mac);
1134 callout_drain(&sc->sc_led_blink_ch);
1135 callout_drain(&sc->sc_rfswitch_ch);
1136 callout_drain(&sc->sc_task_ch);
1137 callout_drain(&sc->sc_watchdog_ch);
1138 bwn_phy_detach(mac);
1139 if (ifp != NULL) {
1140 ieee80211_draintask(ic, &mac->mac_hwreset);
1141 ieee80211_draintask(ic, &mac->mac_txpower);
1142 ieee80211_ifdetach(ic);
1143 if_free(ifp);
1144 }
1145 }
1146 taskqueue_drain(sc->sc_tq, &mac->mac_intrtask);
1147 taskqueue_free(sc->sc_tq);
1148
1149 for (i = 0; i < BWN_MSI_MESSAGES; i++) {
1150 if (mac->mac_intrhand[i] != NULL) {
1151 bus_teardown_intr(dev, mac->mac_res_irq[i],
1152 mac->mac_intrhand[i]);
1153 mac->mac_intrhand[i] = NULL;
1154 }
1155 }
1156 bus_release_resources(dev, mac->mac_intr_spec, mac->mac_res_irq);
1157 if (mac->mac_msi != 0)
1158 pci_release_msi(dev);
1159
1160 BWN_LOCK_DESTROY(sc);
1161 return (0);
1162}
1163
1164static int
1165bwn_attach_pre(struct bwn_softc *sc)
1166{
1167 struct ifnet *ifp;
1168 int error = 0;
1169
1170 BWN_LOCK_INIT(sc);
1171 TAILQ_INIT(&sc->sc_maclist);
1172 callout_init_mtx(&sc->sc_rfswitch_ch, &sc->sc_mtx, 0);
1173 callout_init_mtx(&sc->sc_task_ch, &sc->sc_mtx, 0);
1174 callout_init_mtx(&sc->sc_watchdog_ch, &sc->sc_mtx, 0);
1175
1176 sc->sc_tq = taskqueue_create_fast("bwn_taskq", M_NOWAIT,
1177 taskqueue_thread_enqueue, &sc->sc_tq);
1178 taskqueue_start_threads(&sc->sc_tq, 1, PI_NET,
1179 "%s taskq", device_get_nameunit(sc->sc_dev));
1180
1181 ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
1182 if (ifp == NULL) {
1183 device_printf(sc->sc_dev, "can not if_alloc()\n");
1184 error = ENOSPC;
1185 goto fail;
1186 }
1187
1188 /* set these up early for if_printf use */
1189 if_initname(ifp, device_get_name(sc->sc_dev),
1190 device_get_unit(sc->sc_dev));
1191
1192 ifp->if_softc = sc;
1193 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
1194 ifp->if_init = bwn_init;
1195 ifp->if_ioctl = bwn_ioctl;
1196 ifp->if_start = bwn_start;
1197 IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
1198 ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
1199 IFQ_SET_READY(&ifp->if_snd);
1200
1201 return (0);
1202
1203fail: BWN_LOCK_DESTROY(sc);
1204 return (error);
1205}
1206
1207static void
1208bwn_sprom_bugfixes(device_t dev)
1209{
1210#define BWN_ISDEV(_vendor, _device, _subvendor, _subdevice) \
1211 ((siba_get_pci_vendor(dev) == PCI_VENDOR_##_vendor) && \
1212 (siba_get_pci_device(dev) == _device) && \
1213 (siba_get_pci_subvendor(dev) == PCI_VENDOR_##_subvendor) && \
1214 (siba_get_pci_subdevice(dev) == _subdevice))
1215
1216 if (siba_get_pci_subvendor(dev) == PCI_VENDOR_APPLE &&
1217 siba_get_pci_subdevice(dev) == 0x4e &&
1218 siba_get_pci_revid(dev) > 0x40)
1219 siba_sprom_set_bf_lo(dev,
1220 siba_sprom_get_bf_lo(dev) | BWN_BFL_PACTRL);
1221 if (siba_get_pci_subvendor(dev) == SIBA_BOARDVENDOR_DELL &&
1222 siba_get_chipid(dev) == 0x4301 && siba_get_pci_revid(dev) == 0x74)
1223 siba_sprom_set_bf_lo(dev,
1224 siba_sprom_get_bf_lo(dev) | BWN_BFL_BTCOEXIST);
1225 if (siba_get_type(dev) == SIBA_TYPE_PCI) {
1226 if (BWN_ISDEV(BROADCOM, 0x4318, ASUSTEK, 0x100f) ||
1227 BWN_ISDEV(BROADCOM, 0x4320, DELL, 0x0003) ||
1228 BWN_ISDEV(BROADCOM, 0x4320, HP, 0x12f8) ||
1229 BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0013) ||
1230 BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0014) ||
1231 BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0015) ||
1232 BWN_ISDEV(BROADCOM, 0x4320, MOTOROLA, 0x7010))
1233 siba_sprom_set_bf_lo(dev,
1234 siba_sprom_get_bf_lo(dev) & ~BWN_BFL_BTCOEXIST);
1235 }
1236#undef BWN_ISDEV
1237}
1238
1239static int
1240bwn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1241{
1242#define IS_RUNNING(ifp) \
1243 ((ifp->if_flags & IFF_UP) && (ifp->if_drv_flags & IFF_DRV_RUNNING))
1244 struct bwn_softc *sc = ifp->if_softc;
1245 struct ieee80211com *ic = ifp->if_l2com;
1246 struct ifreq *ifr = (struct ifreq *)data;
1247 int error = 0, startall;
1248
1249 switch (cmd) {
1250 case SIOCSIFFLAGS:
1251 startall = 0;
1252 if (IS_RUNNING(ifp)) {
1253 bwn_update_promisc(ifp);
1254 } else if (ifp->if_flags & IFF_UP) {
1255 if ((sc->sc_flags & BWN_FLAG_INVALID) == 0) {
1256 bwn_init(sc);
1257 startall = 1;
1258 }
1259 } else
1260 bwn_stop(sc, 1);
1261 if (startall)
1262 ieee80211_start_all(ic);
1263 break;
1264 case SIOCGIFMEDIA:
1265 error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
1266 break;
1267 case SIOCGIFADDR:
1268 error = ether_ioctl(ifp, cmd, data);
1269 break;
1270 default:
1271 error = EINVAL;
1272 break;
1273 }
1274 return (error);
1275}
1276
1277static void
1278bwn_start(struct ifnet *ifp)
1279{
1280 struct bwn_softc *sc = ifp->if_softc;
1281
1282 BWN_LOCK(sc);
1283 bwn_start_locked(ifp);
1284 BWN_UNLOCK(sc);
1285}
1286
1287static void
1288bwn_start_locked(struct ifnet *ifp)
1289{
1290 struct bwn_softc *sc = ifp->if_softc;
1291 struct bwn_mac *mac = sc->sc_curmac;
1292 struct ieee80211_frame *wh;
1293 struct ieee80211_node *ni;
1294 struct ieee80211_key *k;
1295 struct mbuf *m;
1296
1297 BWN_ASSERT_LOCKED(sc);
1298
1299 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || mac == NULL ||
1300 mac->mac_status < BWN_MAC_STATUS_STARTED)
1301 return;
1302
1303 for (;;) {
1304 IFQ_DRV_DEQUEUE(&ifp->if_snd, m); /* XXX: LOCK */
1305 if (m == NULL)
1306 break;
1307
1308 if (bwn_tx_isfull(sc, m))
1309 break;
1310 ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
1311 if (ni == NULL) {
1312 device_printf(sc->sc_dev, "unexpected NULL ni\n");
1313 m_freem(m);
1314 ifp->if_oerrors++;
1315 continue;
1316 }
1317 KASSERT(ni != NULL, ("%s:%d: fail", __func__, __LINE__));
1318 wh = mtod(m, struct ieee80211_frame *);
1319 if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
1320 k = ieee80211_crypto_encap(ni, m);
1321 if (k == NULL) {
1322 ieee80211_free_node(ni);
1323 m_freem(m);
1324 ifp->if_oerrors++;
1325 continue;
1326 }
1327 }
1328 wh = NULL; /* Catch any invalid use */
1329
1330 if (bwn_tx_start(sc, ni, m) != 0) {
1331 if (ni != NULL)
1332 ieee80211_free_node(ni);
1333 ifp->if_oerrors++;
1334 continue;
1335 }
1336
1337 sc->sc_watchdog_timer = 5;
1338 }
1339}
1340
1341static int
1342bwn_tx_isfull(struct bwn_softc *sc, struct mbuf *m)
1343{
1344 struct bwn_dma_ring *dr;
1345 struct bwn_mac *mac = sc->sc_curmac;
1346 struct bwn_pio_txqueue *tq;
1347 struct ifnet *ifp = sc->sc_ifp;
1348 int pktlen = roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1349
1350 BWN_ASSERT_LOCKED(sc);
1351
1352 if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
1353 dr = bwn_dma_select(mac, M_WME_GETAC(m));
1354 if (dr->dr_stop == 1 ||
1355 bwn_dma_freeslot(dr) < BWN_TX_SLOTS_PER_FRAME) {
1356 dr->dr_stop = 1;
1357 goto full;
1358 }
1359 } else {
1360 tq = bwn_pio_select(mac, M_WME_GETAC(m));
1361 if (tq->tq_free == 0 || pktlen > tq->tq_size ||
1362 pktlen > (tq->tq_size - tq->tq_used)) {
1363 tq->tq_stop = 1;
1364 goto full;
1365 }
1366 }
1367 return (0);
1368full:
1369 IFQ_DRV_PREPEND(&ifp->if_snd, m);
1370 ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1371 return (1);
1372}
1373
1374static int
1375bwn_tx_start(struct bwn_softc *sc, struct ieee80211_node *ni, struct mbuf *m)
1376{
1377 struct bwn_mac *mac = sc->sc_curmac;
1378 int error;
1379
1380 BWN_ASSERT_LOCKED(sc);
1381
1382 if (m->m_pkthdr.len < IEEE80211_MIN_LEN || mac == NULL) {
1383 m_freem(m);
1384 return (ENXIO);
1385 }
1386
1387 error = (mac->mac_flags & BWN_MAC_FLAG_DMA) ?
1388 bwn_dma_tx_start(mac, ni, m) : bwn_pio_tx_start(mac, ni, m);
1389 if (error) {
1390 m_freem(m);
1391 return (error);
1392 }
1393 return (0);
1394}
1395
1396static int
1397bwn_pio_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1398{
1399 struct bwn_pio_txpkt *tp;
1400 struct bwn_pio_txqueue *tq = bwn_pio_select(mac, M_WME_GETAC(m));
1401 struct bwn_softc *sc = mac->mac_sc;
1402 struct bwn_txhdr txhdr;
1403 struct mbuf *m_new;
1404 uint32_t ctl32;
1405 int error;
1406 uint16_t ctl16;
1407
1408 BWN_ASSERT_LOCKED(sc);
1409
1410 /* XXX TODO send packets after DTIM */
1411
1412 KASSERT(!TAILQ_EMPTY(&tq->tq_pktlist), ("%s: fail", __func__));
1413 tp = TAILQ_FIRST(&tq->tq_pktlist);
1414 tp->tp_ni = ni;
1415 tp->tp_m = m;
1416
1417 error = bwn_set_txhdr(mac, ni, m, &txhdr, BWN_PIO_COOKIE(tq, tp));
1418 if (error) {
1419 device_printf(sc->sc_dev, "tx fail\n");
1420 return (error);
1421 }
1422
1423 TAILQ_REMOVE(&tq->tq_pktlist, tp, tp_list);
1424 tq->tq_used += roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1425 tq->tq_free--;
1426
1427 if (siba_get_revid(sc->sc_dev) >= 8) {
1428 /*
1429 * XXX please removes m_defrag(9)
1430 */
1431 m_new = m_defrag(m, M_DONTWAIT);
1432 if (m_new == NULL) {
1433 device_printf(sc->sc_dev,
1434 "%s: can't defrag TX buffer\n",
1435 __func__);
1436 return (ENOBUFS);
1437 }
1438 if (m_new->m_next != NULL)
1439 device_printf(sc->sc_dev,
1440 "TODO: fragmented packets for PIO\n");
1441 tp->tp_m = m_new;
1442
1443 /* send HEADER */
1444 ctl32 = bwn_pio_write_multi_4(mac, tq,
1445 (BWN_PIO_READ_4(mac, tq, BWN_PIO8_TXCTL) |
1446 BWN_PIO8_TXCTL_FRAMEREADY) & ~BWN_PIO8_TXCTL_EOF,
1447 (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1448 /* send BODY */
1449 ctl32 = bwn_pio_write_multi_4(mac, tq, ctl32,
1450 mtod(m_new, const void *), m_new->m_pkthdr.len);
1451 bwn_pio_write_4(mac, tq, BWN_PIO_TXCTL,
1452 ctl32 | BWN_PIO8_TXCTL_EOF);
1453 } else {
1454 ctl16 = bwn_pio_write_multi_2(mac, tq,
1455 (bwn_pio_read_2(mac, tq, BWN_PIO_TXCTL) |
1456 BWN_PIO_TXCTL_FRAMEREADY) & ~BWN_PIO_TXCTL_EOF,
1457 (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1458 ctl16 = bwn_pio_write_mbuf_2(mac, tq, ctl16, m);
1459 BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL,
1460 ctl16 | BWN_PIO_TXCTL_EOF);
1461 }
1462
1463 return (0);
1464}
1465
1466static struct bwn_pio_txqueue *
1467bwn_pio_select(struct bwn_mac *mac, uint8_t prio)
1468{
1469
1470 if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
1471 return (&mac->mac_method.pio.wme[WME_AC_BE]);
1472
1473 switch (prio) {
1474 case 0:
1475 return (&mac->mac_method.pio.wme[WME_AC_BE]);
1476 case 1:
1477 return (&mac->mac_method.pio.wme[WME_AC_BK]);
1478 case 2:
1479 return (&mac->mac_method.pio.wme[WME_AC_VI]);
1480 case 3:
1481 return (&mac->mac_method.pio.wme[WME_AC_VO]);
1482 }
1483 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
1484 return (NULL);
1485}
1486
1487static int
1488bwn_dma_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1489{
1490#define BWN_GET_TXHDRCACHE(slot) \
1491 &(txhdr_cache[(slot / BWN_TX_SLOTS_PER_FRAME) * BWN_HDRSIZE(mac)])
1492 struct bwn_dma *dma = &mac->mac_method.dma;
1493 struct bwn_dma_ring *dr = bwn_dma_select(mac, M_WME_GETAC(m));
1494 struct bwn_dmadesc_generic *desc;
1495 struct bwn_dmadesc_meta *mt;
1496 struct bwn_softc *sc = mac->mac_sc;
1497 struct ifnet *ifp = sc->sc_ifp;
1498 uint8_t *txhdr_cache = (uint8_t *)dr->dr_txhdr_cache;
1499 int error, slot, backup[2] = { dr->dr_curslot, dr->dr_usedslot };
1500
1501 BWN_ASSERT_LOCKED(sc);
1502 KASSERT(!dr->dr_stop, ("%s:%d: fail", __func__, __LINE__));
1503
1504 /* XXX send after DTIM */
1505
1506 slot = bwn_dma_getslot(dr);
1507 dr->getdesc(dr, slot, &desc, &mt);
1508 KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_HEADER,
1509 ("%s:%d: fail", __func__, __LINE__));
1510
1511 error = bwn_set_txhdr(dr->dr_mac, ni, m,
1512 (struct bwn_txhdr *)BWN_GET_TXHDRCACHE(slot),
1513 BWN_DMA_COOKIE(dr, slot));
1514 if (error)
1515 goto fail;
1516 error = bus_dmamap_load(dr->dr_txring_dtag, mt->mt_dmap,
1517 BWN_GET_TXHDRCACHE(slot), BWN_HDRSIZE(mac), bwn_dma_ring_addr,
1518 &mt->mt_paddr, BUS_DMA_NOWAIT);
1519 if (error) {
1520 if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
1521 __func__, error);
1522 goto fail;
1523 }
1524 bus_dmamap_sync(dr->dr_txring_dtag, mt->mt_dmap,
1525 BUS_DMASYNC_PREWRITE);
1526 dr->setdesc(dr, desc, mt->mt_paddr, BWN_HDRSIZE(mac), 1, 0, 0);
1527 bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1528 BUS_DMASYNC_PREWRITE);
1529
1530 slot = bwn_dma_getslot(dr);
1531 dr->getdesc(dr, slot, &desc, &mt);
1532 KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_BODY &&
1533 mt->mt_islast == 1, ("%s:%d: fail", __func__, __LINE__));
1534 mt->mt_m = m;
1535 mt->mt_ni = ni;
1536
1537 error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap, m,
1538 bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1539 if (error && error != EFBIG) {
1540 if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
1541 __func__, error);
1542 goto fail;
1543 }
1544 if (error) { /* error == EFBIG */
1545 struct mbuf *m_new;
1546
1547 m_new = m_defrag(m, M_DONTWAIT);
1548 if (m_new == NULL) {
1549 if_printf(ifp, "%s: can't defrag TX buffer\n",
1550 __func__);
1551 error = ENOBUFS;
1552 goto fail;
1553 } else {
1554 m = m_new;
1555 }
1556
1557 mt->mt_m = m;
1558 error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap,
1559 m, bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1560 if (error) {
1561 if_printf(ifp, "%s: can't load TX buffer (2) %d\n",
1562 __func__, error);
1563 goto fail;
1564 }
1565 }
1566 bus_dmamap_sync(dma->txbuf_dtag, mt->mt_dmap, BUS_DMASYNC_PREWRITE);
1567 dr->setdesc(dr, desc, mt->mt_paddr, m->m_pkthdr.len, 0, 1, 1);
1568 bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1569 BUS_DMASYNC_PREWRITE);
1570
1571 /* XXX send after DTIM */
1572
1573 dr->start_transfer(dr, bwn_dma_nextslot(dr, slot));
1574 return (0);
1575fail:
1576 dr->dr_curslot = backup[0];
1577 dr->dr_usedslot = backup[1];
1578 return (error);
1579#undef BWN_GET_TXHDRCACHE
1580}
1581
1582static void
1583bwn_watchdog(void *arg)
1584{
1585 struct bwn_softc *sc = arg;
1586 struct ifnet *ifp = sc->sc_ifp;
1587
1588 if (sc->sc_watchdog_timer != 0 && --sc->sc_watchdog_timer == 0) {
1589 if_printf(ifp, "device timeout\n");
1590 ifp->if_oerrors++;
1591 }
1592 callout_schedule(&sc->sc_watchdog_ch, hz);
1593}
1594
1595static int
1596bwn_attach_core(struct bwn_mac *mac)
1597{
1598 struct bwn_softc *sc = mac->mac_sc;
1599 int error, have_bg = 0, have_a = 0;
1600 uint32_t high;
1601
1602 KASSERT(siba_get_revid(sc->sc_dev) >= 5,
1603 ("unsupported revision %d", siba_get_revid(sc->sc_dev)));
1604
1605 siba_powerup(sc->sc_dev, 0);
1606
1607 high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH);
1608 bwn_reset_core(mac,
1609 (high & BWN_TGSHIGH_HAVE_2GHZ) ? BWN_TGSLOW_SUPPORT_G : 0);
1610 error = bwn_phy_getinfo(mac, high);
1611 if (error)
1612 goto fail;
1613
1614 have_a = (high & BWN_TGSHIGH_HAVE_5GHZ) ? 1 : 0;
1615 have_bg = (high & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1616 if (siba_get_pci_device(sc->sc_dev) != 0x4312 &&
1617 siba_get_pci_device(sc->sc_dev) != 0x4319 &&
1618 siba_get_pci_device(sc->sc_dev) != 0x4324) {
1619 have_a = have_bg = 0;
1620 if (mac->mac_phy.type == BWN_PHYTYPE_A)
1621 have_a = 1;
1622 else if (mac->mac_phy.type == BWN_PHYTYPE_G ||
1623 mac->mac_phy.type == BWN_PHYTYPE_N ||
1624 mac->mac_phy.type == BWN_PHYTYPE_LP)
1625 have_bg = 1;
1626 else
1627 KASSERT(0 == 1, ("%s: unknown phy type (%d)", __func__,
1628 mac->mac_phy.type));
1629 }
1630 /* XXX turns off PHY A because it's not supported */
1631 if (mac->mac_phy.type != BWN_PHYTYPE_LP &&
1632 mac->mac_phy.type != BWN_PHYTYPE_N) {
1633 have_a = 0;
1634 have_bg = 1;
1635 }
1636
1637 if (mac->mac_phy.type == BWN_PHYTYPE_G) {
1638 mac->mac_phy.attach = bwn_phy_g_attach;
1639 mac->mac_phy.detach = bwn_phy_g_detach;
1640 mac->mac_phy.prepare_hw = bwn_phy_g_prepare_hw;
1641 mac->mac_phy.init_pre = bwn_phy_g_init_pre;
1642 mac->mac_phy.init = bwn_phy_g_init;
1643 mac->mac_phy.exit = bwn_phy_g_exit;
1644 mac->mac_phy.phy_read = bwn_phy_g_read;
1645 mac->mac_phy.phy_write = bwn_phy_g_write;
1646 mac->mac_phy.rf_read = bwn_phy_g_rf_read;
1647 mac->mac_phy.rf_write = bwn_phy_g_rf_write;
1648 mac->mac_phy.use_hwpctl = bwn_phy_g_hwpctl;
1649 mac->mac_phy.rf_onoff = bwn_phy_g_rf_onoff;
1650 mac->mac_phy.switch_analog = bwn_phy_switch_analog;
1651 mac->mac_phy.switch_channel = bwn_phy_g_switch_channel;
1652 mac->mac_phy.get_default_chan = bwn_phy_g_get_default_chan;
1653 mac->mac_phy.set_antenna = bwn_phy_g_set_antenna;
1654 mac->mac_phy.set_im = bwn_phy_g_im;
1655 mac->mac_phy.recalc_txpwr = bwn_phy_g_recalc_txpwr;
1656 mac->mac_phy.set_txpwr = bwn_phy_g_set_txpwr;
1657 mac->mac_phy.task_15s = bwn_phy_g_task_15s;
1658 mac->mac_phy.task_60s = bwn_phy_g_task_60s;
1659 } else if (mac->mac_phy.type == BWN_PHYTYPE_LP) {
1660 mac->mac_phy.init_pre = bwn_phy_lp_init_pre;
1661 mac->mac_phy.init = bwn_phy_lp_init;
1662 mac->mac_phy.phy_read = bwn_phy_lp_read;
1663 mac->mac_phy.phy_write = bwn_phy_lp_write;
1664 mac->mac_phy.phy_maskset = bwn_phy_lp_maskset;
1665 mac->mac_phy.rf_read = bwn_phy_lp_rf_read;
1666 mac->mac_phy.rf_write = bwn_phy_lp_rf_write;
1667 mac->mac_phy.rf_onoff = bwn_phy_lp_rf_onoff;
1668 mac->mac_phy.switch_analog = bwn_phy_lp_switch_analog;
1669 mac->mac_phy.switch_channel = bwn_phy_lp_switch_channel;
1670 mac->mac_phy.get_default_chan = bwn_phy_lp_get_default_chan;
1671 mac->mac_phy.set_antenna = bwn_phy_lp_set_antenna;
1672 mac->mac_phy.task_60s = bwn_phy_lp_task_60s;
1673 } else {
1674 device_printf(sc->sc_dev, "unsupported PHY type (%d)\n",
1675 mac->mac_phy.type);
1676 error = ENXIO;
1677 goto fail;
1678 }
1679
1680 mac->mac_phy.gmode = have_bg;
1681 if (mac->mac_phy.attach != NULL) {
1682 error = mac->mac_phy.attach(mac);
1683 if (error) {
1684 device_printf(sc->sc_dev, "failed\n");
1685 goto fail;
1686 }
1687 }
1688
1689 bwn_reset_core(mac, have_bg ? BWN_TGSLOW_SUPPORT_G : 0);
1690
1691 error = bwn_chiptest(mac);
1692 if (error)
1693 goto fail;
1694 error = bwn_setup_channels(mac, have_bg, have_a);
1695 if (error) {
1696 device_printf(sc->sc_dev, "failed to setup channels\n");
1697 goto fail;
1698 }
1699
1700 if (sc->sc_curmac == NULL)
1701 sc->sc_curmac = mac;
1702
1703 error = bwn_dma_attach(mac);
1704 if (error != 0) {
1705 device_printf(sc->sc_dev, "failed to initialize DMA\n");
1706 goto fail;
1707 }
1708
1709 mac->mac_phy.switch_analog(mac, 0);
1710
1711 siba_dev_down(sc->sc_dev, 0);
1712fail:
1713 siba_powerdown(sc->sc_dev);
1714 return (error);
1715}
1716
1717static void
1718bwn_reset_core(struct bwn_mac *mac, uint32_t flags)
1719{
1720 struct bwn_softc *sc = mac->mac_sc;
1721 uint32_t low, ctl;
1722
1723 flags |= (BWN_TGSLOW_PHYCLOCK_ENABLE | BWN_TGSLOW_PHYRESET);
1724
1725 siba_dev_up(sc->sc_dev, flags);
1726 DELAY(2000);
1727
1728 low = (siba_read_4(sc->sc_dev, SIBA_TGSLOW) | SIBA_TGSLOW_FGC) &
1729 ~BWN_TGSLOW_PHYRESET;
1730 siba_write_4(sc->sc_dev, SIBA_TGSLOW, low);
1731 siba_read_4(sc->sc_dev, SIBA_TGSLOW);
1732 DELAY(1000);
1733 siba_write_4(sc->sc_dev, SIBA_TGSLOW, low & ~SIBA_TGSLOW_FGC);
1734 siba_read_4(sc->sc_dev, SIBA_TGSLOW);
1735 DELAY(1000);
1736
1737 if (mac->mac_phy.switch_analog != NULL)
1738 mac->mac_phy.switch_analog(mac, 1);
1739
1740 ctl = BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GMODE;
1741 if (flags & BWN_TGSLOW_SUPPORT_G)
1742 ctl |= BWN_MACCTL_GMODE;
1743 BWN_WRITE_4(mac, BWN_MACCTL, ctl | BWN_MACCTL_IHR_ON);
1744}
1745
1746static int
1747bwn_phy_getinfo(struct bwn_mac *mac, int tgshigh)
1748{
1749 struct bwn_phy *phy = &mac->mac_phy;
1750 struct bwn_softc *sc = mac->mac_sc;
1751 uint32_t tmp;
1752
1753 /* PHY */
1754 tmp = BWN_READ_2(mac, BWN_PHYVER);
1755 phy->gmode = (tgshigh & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1756 phy->rf_on = 1;
1757 phy->analog = (tmp & BWN_PHYVER_ANALOG) >> 12;
1758 phy->type = (tmp & BWN_PHYVER_TYPE) >> 8;
1759 phy->rev = (tmp & BWN_PHYVER_VERSION);
1760 if ((phy->type == BWN_PHYTYPE_A && phy->rev >= 4) ||
1761 (phy->type == BWN_PHYTYPE_B && phy->rev != 2 &&
1762 phy->rev != 4 && phy->rev != 6 && phy->rev != 7) ||
1763 (phy->type == BWN_PHYTYPE_G && phy->rev > 9) ||
1764 (phy->type == BWN_PHYTYPE_N && phy->rev > 4) ||
1765 (phy->type == BWN_PHYTYPE_LP && phy->rev > 2))
1766 goto unsupphy;
1767
1768 /* RADIO */
1769 if (siba_get_chipid(sc->sc_dev) == 0x4317) {
1770 if (siba_get_chiprev(sc->sc_dev) == 0)
1771 tmp = 0x3205017f;
1772 else if (siba_get_chiprev(sc->sc_dev) == 1)
1773 tmp = 0x4205017f;
1774 else
1775 tmp = 0x5205017f;
1776 } else {
1777 BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1778 tmp = BWN_READ_2(mac, BWN_RFDATALO);
1779 BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1780 tmp |= (uint32_t)BWN_READ_2(mac, BWN_RFDATAHI) << 16;
1781 }
1782 phy->rf_rev = (tmp & 0xf0000000) >> 28;
1783 phy->rf_ver = (tmp & 0x0ffff000) >> 12;
1784 phy->rf_manuf = (tmp & 0x00000fff);
1785 if (phy->rf_manuf != 0x17f) /* 0x17f is broadcom */
1786 goto unsupradio;
1787 if ((phy->type == BWN_PHYTYPE_A && (phy->rf_ver != 0x2060 ||
1788 phy->rf_rev != 1 || phy->rf_manuf != 0x17f)) ||
1789 (phy->type == BWN_PHYTYPE_B && (phy->rf_ver & 0xfff0) != 0x2050) ||
1790 (phy->type == BWN_PHYTYPE_G && phy->rf_ver != 0x2050) ||
1791 (phy->type == BWN_PHYTYPE_N &&
1792 phy->rf_ver != 0x2055 && phy->rf_ver != 0x2056) ||
1793 (phy->type == BWN_PHYTYPE_LP &&
1794 phy->rf_ver != 0x2062 && phy->rf_ver != 0x2063))
1795 goto unsupradio;
1796
1797 return (0);
1798unsupphy:
1799 device_printf(sc->sc_dev, "unsupported PHY (type %#x, rev %#x, "
1800 "analog %#x)\n",
1801 phy->type, phy->rev, phy->analog);
1802 return (ENXIO);
1803unsupradio:
1804 device_printf(sc->sc_dev, "unsupported radio (manuf %#x, ver %#x, "
1805 "rev %#x)\n",
1806 phy->rf_manuf, phy->rf_ver, phy->rf_rev);
1807 return (ENXIO);
1808}
1809
1810static int
1811bwn_chiptest(struct bwn_mac *mac)
1812{
1813#define TESTVAL0 0x55aaaa55
1814#define TESTVAL1 0xaa5555aa
1815 struct bwn_softc *sc = mac->mac_sc;
1816 uint32_t v, backup;
1817
1818 BWN_LOCK(sc);
1819
1820 backup = bwn_shm_read_4(mac, BWN_SHARED, 0);
1821
1822 bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL0);
1823 if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL0)
1824 goto error;
1825 bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL1);
1826 if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL1)
1827 goto error;
1828
1829 bwn_shm_write_4(mac, BWN_SHARED, 0, backup);
1830
1831 if ((siba_get_revid(sc->sc_dev) >= 3) &&
1832 (siba_get_revid(sc->sc_dev) <= 10)) {
1833 BWN_WRITE_2(mac, BWN_TSF_CFP_START, 0xaaaa);
1834 BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0xccccbbbb);
1835 if (BWN_READ_2(mac, BWN_TSF_CFP_START_LOW) != 0xbbbb)
1836 goto error;
1837 if (BWN_READ_2(mac, BWN_TSF_CFP_START_HIGH) != 0xcccc)
1838 goto error;
1839 }
1840 BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0);
1841
1842 v = BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_GMODE;
1843 if (v != (BWN_MACCTL_GMODE | BWN_MACCTL_IHR_ON))
1844 goto error;
1845
1846 BWN_UNLOCK(sc);
1847 return (0);
1848error:
1849 BWN_UNLOCK(sc);
1850 device_printf(sc->sc_dev, "failed to validate the chipaccess\n");
1851 return (ENODEV);
1852}
1853
1854#define IEEE80211_CHAN_HTG (IEEE80211_CHAN_HT | IEEE80211_CHAN_G)
1855#define IEEE80211_CHAN_HTA (IEEE80211_CHAN_HT | IEEE80211_CHAN_A)
1856
1857static int
1858bwn_setup_channels(struct bwn_mac *mac, int have_bg, int have_a)
1859{
1860 struct bwn_softc *sc = mac->mac_sc;
1861 struct ifnet *ifp = sc->sc_ifp;
1862 struct ieee80211com *ic = ifp->if_l2com;
1863
1864 memset(ic->ic_channels, 0, sizeof(ic->ic_channels));
1865 ic->ic_nchans = 0;
1866
1867 if (have_bg)
1868 bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1869 &ic->ic_nchans, &bwn_chantable_bg, IEEE80211_CHAN_G);
1870 if (mac->mac_phy.type == BWN_PHYTYPE_N) {
1871 if (have_a)
1872 bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1873 &ic->ic_nchans, &bwn_chantable_n,
1874 IEEE80211_CHAN_HTA);
1875 } else {
1876 if (have_a)
1877 bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1878 &ic->ic_nchans, &bwn_chantable_a,
1879 IEEE80211_CHAN_A);
1880 }
1881
1882 mac->mac_phy.supports_2ghz = have_bg;
1883 mac->mac_phy.supports_5ghz = have_a;
1884
1885 return (ic->ic_nchans == 0 ? ENXIO : 0);
1886}
1887
1888static uint32_t
1889bwn_shm_read_4(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1890{
1891 uint32_t ret;
1892
1893 BWN_ASSERT_LOCKED(mac->mac_sc);
1894
1895 if (way == BWN_SHARED) {
1896 KASSERT((offset & 0x0001) == 0,
1897 ("%s:%d warn", __func__, __LINE__));
1898 if (offset & 0x0003) {
1899 bwn_shm_ctlword(mac, way, offset >> 2);
1900 ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1901 ret <<= 16;
1902 bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1903 ret |= BWN_READ_2(mac, BWN_SHM_DATA);
1904 goto out;
1905 }
1906 offset >>= 2;
1907 }
1908 bwn_shm_ctlword(mac, way, offset);
1909 ret = BWN_READ_4(mac, BWN_SHM_DATA);
1910out:
1911 return (ret);
1912}
1913
1914static uint16_t
1915bwn_shm_read_2(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1916{
1917 uint16_t ret;
1918
1919 BWN_ASSERT_LOCKED(mac->mac_sc);
1920
1921 if (way == BWN_SHARED) {
1922 KASSERT((offset & 0x0001) == 0,
1923 ("%s:%d warn", __func__, __LINE__));
1924 if (offset & 0x0003) {
1925 bwn_shm_ctlword(mac, way, offset >> 2);
1926 ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1927 goto out;
1928 }
1929 offset >>= 2;
1930 }
1931 bwn_shm_ctlword(mac, way, offset);
1932 ret = BWN_READ_2(mac, BWN_SHM_DATA);
1933out:
1934
1935 return (ret);
1936}
1937
1938static void
1939bwn_shm_ctlword(struct bwn_mac *mac, uint16_t way,
1940 uint16_t offset)
1941{
1942 uint32_t control;
1943
1944 control = way;
1945 control <<= 16;
1946 control |= offset;
1947 BWN_WRITE_4(mac, BWN_SHM_CONTROL, control);
1948}
1949
1950static void
1951bwn_shm_write_4(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1952 uint32_t value)
1953{
1954 BWN_ASSERT_LOCKED(mac->mac_sc);
1955
1956 if (way == BWN_SHARED) {
1957 KASSERT((offset & 0x0001) == 0,
1958 ("%s:%d warn", __func__, __LINE__));
1959 if (offset & 0x0003) {
1960 bwn_shm_ctlword(mac, way, offset >> 2);
1961 BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED,
1962 (value >> 16) & 0xffff);
1963 bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1964 BWN_WRITE_2(mac, BWN_SHM_DATA, value & 0xffff);
1965 return;
1966 }
1967 offset >>= 2;
1968 }
1969 bwn_shm_ctlword(mac, way, offset);
1970 BWN_WRITE_4(mac, BWN_SHM_DATA, value);
1971}
1972
1973static void
1974bwn_shm_write_2(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1975 uint16_t value)
1976{
1977 BWN_ASSERT_LOCKED(mac->mac_sc);
1978
1979 if (way == BWN_SHARED) {
1980 KASSERT((offset & 0x0001) == 0,
1981 ("%s:%d warn", __func__, __LINE__));
1982 if (offset & 0x0003) {
1983 bwn_shm_ctlword(mac, way, offset >> 2);
1984 BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED, value);
1985 return;
1986 }
1987 offset >>= 2;
1988 }
1989 bwn_shm_ctlword(mac, way, offset);
1990 BWN_WRITE_2(mac, BWN_SHM_DATA, value);
1991}
1992
1993static void
1994bwn_addchan(struct ieee80211_channel *c, int freq, int flags, int ieee,
1995 int txpow)
1996{
1997
1998 c->ic_freq = freq;
1999 c->ic_flags = flags;
2000 c->ic_ieee = ieee;
2001 c->ic_minpower = 0;
2002 c->ic_maxpower = 2 * txpow;
2003 c->ic_maxregpower = txpow;
2004}
2005
2006static void
2007bwn_addchannels(struct ieee80211_channel chans[], int maxchans, int *nchans,
2008 const struct bwn_channelinfo *ci, int flags)
2009{
2010 struct ieee80211_channel *c;
2011 int i;
2012
2013 c = &chans[*nchans];
2014
2015 for (i = 0; i < ci->nchannels; i++) {
2016 const struct bwn_channel *hc;
2017
2018 hc = &ci->channels[i];
2019 if (*nchans >= maxchans)
2020 break;
2021 bwn_addchan(c, hc->freq, flags, hc->ieee, hc->maxTxPow);
2022 c++, (*nchans)++;
2023 if (flags == IEEE80211_CHAN_G || flags == IEEE80211_CHAN_HTG) {
2024 /* g channel have a separate b-only entry */
2025 if (*nchans >= maxchans)
2026 break;
2027 c[0] = c[-1];
2028 c[-1].ic_flags = IEEE80211_CHAN_B;
2029 c++, (*nchans)++;
2030 }
2031 if (flags == IEEE80211_CHAN_HTG) {
2032 /* HT g channel have a separate g-only entry */
2033 if (*nchans >= maxchans)
2034 break;
2035 c[-1].ic_flags = IEEE80211_CHAN_G;
2036 c[0] = c[-1];
2037 c[0].ic_flags &= ~IEEE80211_CHAN_HT;
2038 c[0].ic_flags |= IEEE80211_CHAN_HT20; /* HT20 */
2039 c++, (*nchans)++;
2040 }
2041 if (flags == IEEE80211_CHAN_HTA) {
2042 /* HT a channel have a separate a-only entry */
2043 if (*nchans >= maxchans)
2044 break;
2045 c[-1].ic_flags = IEEE80211_CHAN_A;
2046 c[0] = c[-1];
2047 c[0].ic_flags &= ~IEEE80211_CHAN_HT;
2048 c[0].ic_flags |= IEEE80211_CHAN_HT20; /* HT20 */
2049 c++, (*nchans)++;
2050 }
2051 }
2052}
2053
2054static int
2055bwn_phy_g_attach(struct bwn_mac *mac)
2056{
2057 struct bwn_softc *sc = mac->mac_sc;
2058 struct bwn_phy *phy = &mac->mac_phy;
2059 struct bwn_phy_g *pg = &phy->phy_g;
2060 unsigned int i;
2061 int16_t pab0, pab1, pab2;
2062 static int8_t bwn_phy_g_tssi2dbm_table[] = BWN_PHY_G_TSSI2DBM_TABLE;
2063 int8_t bg;
2064
2065 bg = (int8_t)siba_sprom_get_tssi_bg(sc->sc_dev);
2066 pab0 = (int16_t)siba_sprom_get_pa0b0(sc->sc_dev);
2067 pab1 = (int16_t)siba_sprom_get_pa0b1(sc->sc_dev);
2068 pab2 = (int16_t)siba_sprom_get_pa0b2(sc->sc_dev);
2069
2070 if ((siba_get_chipid(sc->sc_dev) == 0x4301) && (phy->rf_ver != 0x2050))
2071 device_printf(sc->sc_dev, "not supported anymore\n");
2072
2073 pg->pg_flags = 0;
2074 if (pab0 == 0 || pab1 == 0 || pab2 == 0 || pab0 == -1 || pab1 == -1 ||
2075 pab2 == -1) {
2076 pg->pg_idletssi = 52;
2077 pg->pg_tssi2dbm = bwn_phy_g_tssi2dbm_table;
2078 return (0);
2079 }
2080
2081 pg->pg_idletssi = (bg == 0 || bg == -1) ? 62 : bg;
2082 pg->pg_tssi2dbm = (uint8_t *)malloc(64, M_DEVBUF, M_NOWAIT | M_ZERO);
2083 if (pg->pg_tssi2dbm == NULL) {
2084 device_printf(sc->sc_dev, "failed to allocate buffer\n");
2085 return (ENOMEM);
2086 }
2087 for (i = 0; i < 64; i++) {
2088 int32_t m1, m2, f, q, delta;
2089 int8_t j = 0;
2090
2091 m1 = BWN_TSSI2DBM(16 * pab0 + i * pab1, 32);
2092 m2 = MAX(BWN_TSSI2DBM(32768 + i * pab2, 256), 1);
2093 f = 256;
2094
2095 do {
2096 if (j > 15) {
2097 device_printf(sc->sc_dev,
2098 "failed to generate tssi2dBm\n");
2099 free(pg->pg_tssi2dbm, M_DEVBUF);
2100 return (ENOMEM);
2101 }
2102 q = BWN_TSSI2DBM(f * 4096 - BWN_TSSI2DBM(m2 * f, 16) *
2103 f, 2048);
2104 delta = abs(q - f);
2105 f = q;
2106 j++;
2107 } while (delta >= 2);
2108
2109 pg->pg_tssi2dbm[i] = MIN(MAX(BWN_TSSI2DBM(m1 * f, 8192), -127),
2110 128);
2111 }
2112
2113 pg->pg_flags |= BWN_PHY_G_FLAG_TSSITABLE_ALLOC;
2114 return (0);
2115}
2116
2117static void
2118bwn_phy_g_detach(struct bwn_mac *mac)
2119{
2120 struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
2121
2122 if (pg->pg_flags & BWN_PHY_G_FLAG_TSSITABLE_ALLOC) {
2123 free(pg->pg_tssi2dbm, M_DEVBUF);
2124 pg->pg_tssi2dbm = NULL;
2125 }
2126 pg->pg_flags = 0;
2127}
2128
2129static void
2130bwn_phy_g_init_pre(struct bwn_mac *mac)
2131{
2132 struct bwn_phy *phy = &mac->mac_phy;
2133 struct bwn_phy_g *pg = &phy->phy_g;
2134 void *tssi2dbm;
2135 int idletssi;
2136 unsigned int i;
2137
2138 tssi2dbm = pg->pg_tssi2dbm;
2139 idletssi = pg->pg_idletssi;
2140
2141 memset(pg, 0, sizeof(*pg));
2142
2143 pg->pg_tssi2dbm = tssi2dbm;
2144 pg->pg_idletssi = idletssi;
2145
2146 memset(pg->pg_minlowsig, 0xff, sizeof(pg->pg_minlowsig));
2147
2148 for (i = 0; i < N(pg->pg_nrssi); i++)
2149 pg->pg_nrssi[i] = -1000;
2150 for (i = 0; i < N(pg->pg_nrssi_lt); i++)
2151 pg->pg_nrssi_lt[i] = i;
2152 pg->pg_lofcal = 0xffff;
2153 pg->pg_initval = 0xffff;
2154 pg->pg_immode = BWN_IMMODE_NONE;
2155 pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_UNKNOWN;
2156 pg->pg_avgtssi = 0xff;
2157
2158 pg->pg_loctl.tx_bias = 0xff;
2159 TAILQ_INIT(&pg->pg_loctl.calib_list);
2160}
2161
2162static int
2163bwn_phy_g_prepare_hw(struct bwn_mac *mac)
2164{
2165 struct bwn_phy *phy = &mac->mac_phy;
2166 struct bwn_phy_g *pg = &phy->phy_g;
2167 struct bwn_softc *sc = mac->mac_sc;
2168 struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2169 static const struct bwn_rfatt rfatt0[] = {
2170 { 3, 0 }, { 1, 0 }, { 5, 0 }, { 7, 0 }, { 9, 0 }, { 2, 0 },
2171 { 0, 0 }, { 4, 0 }, { 6, 0 }, { 8, 0 }, { 1, 1 }, { 2, 1 },
2172 { 3, 1 }, { 4, 1 }
2173 };
2174 static const struct bwn_rfatt rfatt1[] = {
2175 { 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 10, 1 }, { 12, 1 },
2176 { 14, 1 }
2177 };
2178 static const struct bwn_rfatt rfatt2[] = {
2179 { 0, 1 }, { 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 9, 1 },
2180 { 9, 1 }
2181 };
2182 static const struct bwn_bbatt bbatt_0[] = {
2183 { 0 }, { 1 }, { 2 }, { 3 }, { 4 }, { 5 }, { 6 }, { 7 }, { 8 }
2184 };
2185
2186 KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
2187
2188 if (phy->rf_ver == 0x2050 && phy->rf_rev < 6)
2189 pg->pg_bbatt.att = 0;
2190 else
2191 pg->pg_bbatt.att = 2;
2192
2193 /* prepare Radio Attenuation */
2194 pg->pg_rfatt.padmix = 0;
2195
2196 if (siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM &&
2197 siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BCM4309G) {
2198 if (siba_get_pci_revid(sc->sc_dev) < 0x43) {
2199 pg->pg_rfatt.att = 2;
2200 goto done;
2201 } else if (siba_get_pci_revid(sc->sc_dev) < 0x51) {
2202 pg->pg_rfatt.att = 3;
2203 goto done;
2204 }
2205 }
2206
2207 if (phy->type == BWN_PHYTYPE_A) {
2208 pg->pg_rfatt.att = 0x60;
2209 goto done;
2210 }
2211
2212 switch (phy->rf_ver) {
2213 case 0x2050:
2214 switch (phy->rf_rev) {
2215 case 0:
2216 pg->pg_rfatt.att = 5;
2217 goto done;
2218 case 1:
2219 if (phy->type == BWN_PHYTYPE_G) {
2220 if (siba_get_pci_subvendor(sc->sc_dev) ==
2221 SIBA_BOARDVENDOR_BCM &&
2222 siba_get_pci_subdevice(sc->sc_dev) ==
2223 SIBA_BOARD_BCM4309G &&
2224 siba_get_pci_revid(sc->sc_dev) >= 30)
2225 pg->pg_rfatt.att = 3;
2226 else if (siba_get_pci_subvendor(sc->sc_dev) ==
2227 SIBA_BOARDVENDOR_BCM &&
2228 siba_get_pci_subdevice(sc->sc_dev) ==
2229 SIBA_BOARD_BU4306)
2230 pg->pg_rfatt.att = 3;
2231 else
2232 pg->pg_rfatt.att = 1;
2233 } else {
2234 if (siba_get_pci_subvendor(sc->sc_dev) ==
2235 SIBA_BOARDVENDOR_BCM &&
2236 siba_get_pci_subdevice(sc->sc_dev) ==
2237 SIBA_BOARD_BCM4309G &&
2238 siba_get_pci_revid(sc->sc_dev) >= 30)
2239 pg->pg_rfatt.att = 7;
2240 else
2241 pg->pg_rfatt.att = 6;
2242 }
2243 goto done;
2244 case 2:
2245 if (phy->type == BWN_PHYTYPE_G) {
2246 if (siba_get_pci_subvendor(sc->sc_dev) ==
2247 SIBA_BOARDVENDOR_BCM &&
2248 siba_get_pci_subdevice(sc->sc_dev) ==
2249 SIBA_BOARD_BCM4309G &&
2250 siba_get_pci_revid(sc->sc_dev) >= 30)
2251 pg->pg_rfatt.att = 3;
2252 else if (siba_get_pci_subvendor(sc->sc_dev) ==
2253 SIBA_BOARDVENDOR_BCM &&
2254 siba_get_pci_subdevice(sc->sc_dev) ==
2255 SIBA_BOARD_BU4306)
2256 pg->pg_rfatt.att = 5;
2257 else if (siba_get_chipid(sc->sc_dev) == 0x4320)
2258 pg->pg_rfatt.att = 4;
2259 else
2260 pg->pg_rfatt.att = 3;
2261 } else
2262 pg->pg_rfatt.att = 6;
2263 goto done;
2264 case 3:
2265 pg->pg_rfatt.att = 5;
2266 goto done;
2267 case 4:
2268 case 5:
2269 pg->pg_rfatt.att = 1;
2270 goto done;
2271 case 6:
2272 case 7:
2273 pg->pg_rfatt.att = 5;
2274 goto done;
2275 case 8:
2276 pg->pg_rfatt.att = 0xa;
2277 pg->pg_rfatt.padmix = 1;
2278 goto done;
2279 case 9:
2280 default:
2281 pg->pg_rfatt.att = 5;
2282 goto done;
2283 }
2284 break;
2285 case 0x2053:
2286 switch (phy->rf_rev) {
2287 case 1:
2288 pg->pg_rfatt.att = 6;
2289 goto done;
2290 }
2291 break;
2292 }
2293 pg->pg_rfatt.att = 5;
2294done:
2295 pg->pg_txctl = (bwn_phy_g_txctl(mac) << 4);
2296
2297 if (!bwn_has_hwpctl(mac)) {
2298 lo->rfatt.array = rfatt0;
2299 lo->rfatt.len = N(rfatt0);
2300 lo->rfatt.min = 0;
2301 lo->rfatt.max = 9;
2302 goto genbbatt;
2303 }
2304 if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
2305 lo->rfatt.array = rfatt1;
2306 lo->rfatt.len = N(rfatt1);
2307 lo->rfatt.min = 0;
2308 lo->rfatt.max = 14;
2309 goto genbbatt;
2310 }
2311 lo->rfatt.array = rfatt2;
2312 lo->rfatt.len = N(rfatt2);
2313 lo->rfatt.min = 0;
2314 lo->rfatt.max = 9;
2315genbbatt:
2316 lo->bbatt.array = bbatt_0;
2317 lo->bbatt.len = N(bbatt_0);
2318 lo->bbatt.min = 0;
2319 lo->bbatt.max = 8;
2320
2321 BWN_READ_4(mac, BWN_MACCTL);
2322 if (phy->rev == 1) {
2323 phy->gmode = 0;
2324 bwn_reset_core(mac, 0);
2325 bwn_phy_g_init_sub(mac);
2326 phy->gmode = 1;
2327 bwn_reset_core(mac, BWN_TGSLOW_SUPPORT_G);
2328 }
2329 return (0);
2330}
2331
2332static uint16_t
2333bwn_phy_g_txctl(struct bwn_mac *mac)
2334{
2335 struct bwn_phy *phy = &mac->mac_phy;
2336
2337 if (phy->rf_ver != 0x2050)
2338 return (0);
2339 if (phy->rf_rev == 1)
2340 return (BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX);
2341 if (phy->rf_rev < 6)
2342 return (BWN_TXCTL_PA2DB);
2343 if (phy->rf_rev == 8)
2344 return (BWN_TXCTL_TXMIX);
2345 return (0);
2346}
2347
2348static int
2349bwn_phy_g_init(struct bwn_mac *mac)
2350{
2351
2352 bwn_phy_g_init_sub(mac);
2353 return (0);
2354}
2355
2356static void
2357bwn_phy_g_exit(struct bwn_mac *mac)
2358{
2359 struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
2360 struct bwn_lo_calib *cal, *tmp;
2361
2362 if (lo == NULL)
2363 return;
2364 TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
2365 TAILQ_REMOVE(&lo->calib_list, cal, list);
2366 free(cal, M_DEVBUF);
2367 }
2368}
2369
2370static uint16_t
2371bwn_phy_g_read(struct bwn_mac *mac, uint16_t reg)
2372{
2373
2374 BWN_WRITE_2(mac, BWN_PHYCTL, reg);
2375 return (BWN_READ_2(mac, BWN_PHYDATA));
2376}
2377
2378static void
2379bwn_phy_g_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
2380{
2381
2382 BWN_WRITE_2(mac, BWN_PHYCTL, reg);
2383 BWN_WRITE_2(mac, BWN_PHYDATA, value);
2384}
2385
2386static uint16_t
2387bwn_phy_g_rf_read(struct bwn_mac *mac, uint16_t reg)
2388{
2389
2390 KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
2391 BWN_WRITE_2(mac, BWN_RFCTL, reg | 0x80);
2392 return (BWN_READ_2(mac, BWN_RFDATALO));
2393}
2394
2395static void
2396bwn_phy_g_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
2397{
2398
2399 KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
2400 BWN_WRITE_2(mac, BWN_RFCTL, reg);
2401 BWN_WRITE_2(mac, BWN_RFDATALO, value);
2402}
2403
2404static int
2405bwn_phy_g_hwpctl(struct bwn_mac *mac)
2406{
2407
2408 return (mac->mac_phy.rev >= 6);
2409}
2410
2411static void
2412bwn_phy_g_rf_onoff(struct bwn_mac *mac, int on)
2413{
2414 struct bwn_phy *phy = &mac->mac_phy;
2415 struct bwn_phy_g *pg = &phy->phy_g;
2416 unsigned int channel;
2417 uint16_t rfover, rfoverval;
2418
2419 if (on) {
2420 if (phy->rf_on)
2421 return;
2422
2423 BWN_PHY_WRITE(mac, 0x15, 0x8000);
2424 BWN_PHY_WRITE(mac, 0x15, 0xcc00);
2425 BWN_PHY_WRITE(mac, 0x15, (phy->gmode ? 0xc0 : 0x0));
2426 if (pg->pg_flags & BWN_PHY_G_FLAG_RADIOCTX_VALID) {
2427 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
2428 pg->pg_radioctx_over);
2429 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
2430 pg->pg_radioctx_overval);
2431 pg->pg_flags &= ~BWN_PHY_G_FLAG_RADIOCTX_VALID;
2432 }
2433 channel = phy->chan;
2434 bwn_phy_g_switch_chan(mac, 6, 1);
2435 bwn_phy_g_switch_chan(mac, channel, 0);
2436 return;
2437 }
2438
2439 rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
2440 rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
2441 pg->pg_radioctx_over = rfover;
2442 pg->pg_radioctx_overval = rfoverval;
2443 pg->pg_flags |= BWN_PHY_G_FLAG_RADIOCTX_VALID;
2444 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover | 0x008c);
2445 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval & 0xff73);
2446}
2447
2448static int
2449bwn_phy_g_switch_channel(struct bwn_mac *mac, uint32_t newchan)
2450{
2451
2452 if ((newchan < 1) || (newchan > 14))
2453 return (EINVAL);
2454 bwn_phy_g_switch_chan(mac, newchan, 0);
2455
2456 return (0);
2457}
2458
2459static uint32_t
2460bwn_phy_g_get_default_chan(struct bwn_mac *mac)
2461{
2462
2463 return (1);
2464}
2465
2466static void
2467bwn_phy_g_set_antenna(struct bwn_mac *mac, int antenna)
2468{
2469 struct bwn_phy *phy = &mac->mac_phy;
2470 uint64_t hf;
2471 int autodiv = 0;
2472 uint16_t tmp;
2473
2474 if (antenna == BWN_ANTAUTO0 || antenna == BWN_ANTAUTO1)
2475 autodiv = 1;
2476
2477 hf = bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER;
2478 bwn_hf_write(mac, hf);
2479
2480 BWN_PHY_WRITE(mac, BWN_PHY_BBANDCFG,
2481 (BWN_PHY_READ(mac, BWN_PHY_BBANDCFG) & ~BWN_PHY_BBANDCFG_RXANT) |
2482 ((autodiv ? BWN_ANTAUTO1 : antenna)
2483 << BWN_PHY_BBANDCFG_RXANT_SHIFT));
2484
2485 if (autodiv) {
2486 tmp = BWN_PHY_READ(mac, BWN_PHY_ANTDWELL);
2487 if (antenna == BWN_ANTAUTO1)
2488 tmp &= ~BWN_PHY_ANTDWELL_AUTODIV1;
2489 else
2490 tmp |= BWN_PHY_ANTDWELL_AUTODIV1;
2491 BWN_PHY_WRITE(mac, BWN_PHY_ANTDWELL, tmp);
2492 }
2493 tmp = BWN_PHY_READ(mac, BWN_PHY_ANTWRSETT);
2494 if (autodiv)
2495 tmp |= BWN_PHY_ANTWRSETT_ARXDIV;
2496 else
2497 tmp &= ~BWN_PHY_ANTWRSETT_ARXDIV;
2498 BWN_PHY_WRITE(mac, BWN_PHY_ANTWRSETT, tmp);
2499 if (phy->rev >= 2) {
2500 BWN_PHY_WRITE(mac, BWN_PHY_OFDM61,
2501 BWN_PHY_READ(mac, BWN_PHY_OFDM61) | BWN_PHY_OFDM61_10);
2502 BWN_PHY_WRITE(mac, BWN_PHY_DIVSRCHGAINBACK,
2503 (BWN_PHY_READ(mac, BWN_PHY_DIVSRCHGAINBACK) & 0xff00) |
2504 0x15);
2505 if (phy->rev == 2)
2506 BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED, 8);
2507 else
2508 BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED,
2509 (BWN_PHY_READ(mac, BWN_PHY_ADIVRELATED) & 0xff00) |
2510 8);
2511 }
2512 if (phy->rev >= 6)
2513 BWN_PHY_WRITE(mac, BWN_PHY_OFDM9B, 0xdc);
2514
2515 hf |= BWN_HF_UCODE_ANTDIV_HELPER;
2516 bwn_hf_write(mac, hf);
2517}
2518
2519static int
2520bwn_phy_g_im(struct bwn_mac *mac, int mode)
2521{
2522 struct bwn_phy *phy = &mac->mac_phy;
2523 struct bwn_phy_g *pg = &phy->phy_g;
2524
2525 KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2526 KASSERT(mode == BWN_IMMODE_NONE, ("%s: fail", __func__));
2527
2528 if (phy->rev == 0 || !phy->gmode)
2529 return (ENODEV);
2530
2531 pg->pg_aci_wlan_automatic = 0;
2532 return (0);
2533}
2534
2535static int
2536bwn_phy_g_recalc_txpwr(struct bwn_mac *mac, int ignore_tssi)
2537{
2538 struct bwn_phy *phy = &mac->mac_phy;
2539 struct bwn_phy_g *pg = &phy->phy_g;
2540 struct bwn_softc *sc = mac->mac_sc;
2541 unsigned int tssi;
2542 int cck, ofdm;
2543 int power;
2544 int rfatt, bbatt;
2545 unsigned int max;
2546
2547 KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2548
2549 cck = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_CCK);
2550 ofdm = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_OFDM_G);
2551 if (cck < 0 && ofdm < 0) {
2552 if (ignore_tssi == 0)
2553 return (BWN_TXPWR_RES_DONE);
2554 cck = 0;
2555 ofdm = 0;
2556 }
2557 tssi = (cck < 0) ? ofdm : ((ofdm < 0) ? cck : (cck + ofdm) / 2);
2558 if (pg->pg_avgtssi != 0xff)
2559 tssi = (tssi + pg->pg_avgtssi) / 2;
2560 pg->pg_avgtssi = tssi;
2561 KASSERT(tssi < BWN_TSSI_MAX, ("%s:%d: fail", __func__, __LINE__));
2562
2563 max = siba_sprom_get_maxpwr_bg(sc->sc_dev);
2564 if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
2565 max -= 3;
2566 if (max >= 120) {
2567 device_printf(sc->sc_dev, "invalid max TX-power value\n");
2568 max = 80;
2569 siba_sprom_set_maxpwr_bg(sc->sc_dev, max);
2570 }
2571
2572 power = MIN(MAX((phy->txpower < 0) ? 0 : (phy->txpower << 2), 0), max) -
2573 (pg->pg_tssi2dbm[MIN(MAX(pg->pg_idletssi - pg->pg_curtssi +
2574 tssi, 0x00), 0x3f)]);
2575 if (power == 0)
2576 return (BWN_TXPWR_RES_DONE);
2577
2578 rfatt = -((power + 7) / 8);
2579 bbatt = (-(power / 2)) - (4 * rfatt);
2580 if ((rfatt == 0) && (bbatt == 0))
2581 return (BWN_TXPWR_RES_DONE);
2582 pg->pg_bbatt_delta = bbatt;
2583 pg->pg_rfatt_delta = rfatt;
2584 return (BWN_TXPWR_RES_NEED_ADJUST);
2585}
2586
2587static void
2588bwn_phy_g_set_txpwr(struct bwn_mac *mac)
2589{
2590 struct bwn_phy *phy = &mac->mac_phy;
2591 struct bwn_phy_g *pg = &phy->phy_g;
2592 struct bwn_softc *sc = mac->mac_sc;
2593 int rfatt, bbatt;
2594 uint8_t txctl;
2595
2596 bwn_mac_suspend(mac);
2597
2598 BWN_ASSERT_LOCKED(sc);
2599
2600 bbatt = pg->pg_bbatt.att;
2601 bbatt += pg->pg_bbatt_delta;
2602 rfatt = pg->pg_rfatt.att;
2603 rfatt += pg->pg_rfatt_delta;
2604
2605 bwn_phy_g_setatt(mac, &bbatt, &rfatt);
2606 txctl = pg->pg_txctl;
2607 if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 2)) {
2608 if (rfatt <= 1) {
2609 if (txctl == 0) {
2610 txctl = BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX;
2611 rfatt += 2;
2612 bbatt += 2;
2613 } else if (siba_sprom_get_bf_lo(sc->sc_dev) &
2614 BWN_BFL_PACTRL) {
2615 bbatt += 4 * (rfatt - 2);
2616 rfatt = 2;
2617 }
2618 } else if (rfatt > 4 && txctl) {
2619 txctl = 0;
2620 if (bbatt < 3) {
2621 rfatt -= 3;
2622 bbatt += 2;
2623 } else {
2624 rfatt -= 2;
2625 bbatt -= 2;
2626 }
2627 }
2628 }
2629 pg->pg_txctl = txctl;
2630 bwn_phy_g_setatt(mac, &bbatt, &rfatt);
2631 pg->pg_rfatt.att = rfatt;
2632 pg->pg_bbatt.att = bbatt;
2633
2634 DPRINTF(sc, BWN_DEBUG_TXPOW, "%s: adjust TX power\n", __func__);
2635
2636 bwn_phy_lock(mac);
2637 bwn_rf_lock(mac);
2638 bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
2639 pg->pg_txctl);
2640 bwn_rf_unlock(mac);
2641 bwn_phy_unlock(mac);
2642
2643 bwn_mac_enable(mac);
2644}
2645
2646static void
2647bwn_phy_g_task_15s(struct bwn_mac *mac)
2648{
2649 struct bwn_phy *phy = &mac->mac_phy;
2650 struct bwn_phy_g *pg = &phy->phy_g;
2651 struct bwn_softc *sc = mac->mac_sc;
2652 struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2653 unsigned long expire, now;
2654 struct bwn_lo_calib *cal, *tmp;
2655 uint8_t expired = 0;
2656
2657 bwn_mac_suspend(mac);
2658
2659 if (lo == NULL)
2660 goto fail;
2661
2662 BWN_GETTIME(now);
2663 if (bwn_has_hwpctl(mac)) {
2664 expire = now - BWN_LO_PWRVEC_EXPIRE;
2665 if (time_before(lo->pwr_vec_read_time, expire)) {
2666 bwn_lo_get_powervector(mac);
2667 bwn_phy_g_dc_lookup_init(mac, 0);
2668 }
2669 goto fail;
2670 }
2671
2672 expire = now - BWN_LO_CALIB_EXPIRE;
2673 TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
2674 if (!time_before(cal->calib_time, expire))
2675 continue;
2676 if (BWN_BBATTCMP(&cal->bbatt, &pg->pg_bbatt) &&
2677 BWN_RFATTCMP(&cal->rfatt, &pg->pg_rfatt)) {
2678 KASSERT(!expired, ("%s:%d: fail", __func__, __LINE__));
2679 expired = 1;
2680 }
2681
2682 DPRINTF(sc, BWN_DEBUG_LO, "expired BB %u RF %u %u I %d Q %d\n",
2683 cal->bbatt.att, cal->rfatt.att, cal->rfatt.padmix,
2684 cal->ctl.i, cal->ctl.q);
2685
2686 TAILQ_REMOVE(&lo->calib_list, cal, list);
2687 free(cal, M_DEVBUF);
2688 }
2689 if (expired || TAILQ_EMPTY(&lo->calib_list)) {
2690 cal = bwn_lo_calibset(mac, &pg->pg_bbatt,
2691 &pg->pg_rfatt);
2692 if (cal == NULL) {
2693 device_printf(sc->sc_dev,
2694 "failed to recalibrate LO\n");
2695 goto fail;
2696 }
2697 TAILQ_INSERT_TAIL(&lo->calib_list, cal, list);
2698 bwn_lo_write(mac, &cal->ctl);
2699 }
2700
2701fail:
2702 bwn_mac_enable(mac);
2703}
2704
2705static void
2706bwn_phy_g_task_60s(struct bwn_mac *mac)
2707{
2708 struct bwn_phy *phy = &mac->mac_phy;
2709 struct bwn_softc *sc = mac->mac_sc;
2710 uint8_t old = phy->chan;
2711
2712 if (!(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI))
2713 return;
2714
2715 bwn_mac_suspend(mac);
2716 bwn_nrssi_slope_11g(mac);
2717 if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 8)) {
2718 bwn_switch_channel(mac, (old >= 8) ? 1 : 13);
2719 bwn_switch_channel(mac, old);
2720 }
2721 bwn_mac_enable(mac);
2722}
2723
2724static void
2725bwn_phy_switch_analog(struct bwn_mac *mac, int on)
2726{
2727
2728 BWN_WRITE_2(mac, BWN_PHY0, on ? 0 : 0xf4);
2729}
2730
2731static int
2732bwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
2733 const struct ieee80211_bpf_params *params)
2734{
2735 struct ieee80211com *ic = ni->ni_ic;
2736 struct ifnet *ifp = ic->ic_ifp;
2737 struct bwn_softc *sc = ifp->if_softc;
2738 struct bwn_mac *mac = sc->sc_curmac;
2739
2740 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
2741 mac->mac_status < BWN_MAC_STATUS_STARTED) {
2742 ieee80211_free_node(ni);
2743 m_freem(m);
2744 return (ENETDOWN);
2745 }
2746
2747 BWN_LOCK(sc);
2748 if (bwn_tx_isfull(sc, m)) {
2749 ieee80211_free_node(ni);
2750 m_freem(m);
2751 ifp->if_oerrors++;
2752 BWN_UNLOCK(sc);
2753 return (ENOBUFS);
2754 }
2755
2756 if (bwn_tx_start(sc, ni, m) != 0) {
2757 if (ni != NULL)
2758 ieee80211_free_node(ni);
2759 ifp->if_oerrors++;
2760 }
2761 sc->sc_watchdog_timer = 5;
2762 BWN_UNLOCK(sc);
2763 return (0);
2764}
2765
2766/*
2767 * Callback from the 802.11 layer to update the slot time
2768 * based on the current setting. We use it to notify the
2769 * firmware of ERP changes and the f/w takes care of things
2770 * like slot time and preamble.
2771 */
2772static void
2773bwn_updateslot(struct ifnet *ifp)
2774{
2775 struct bwn_softc *sc = ifp->if_softc;
2776 struct ieee80211com *ic = ifp->if_l2com;
2777 struct bwn_mac *mac;
2778
2779 BWN_LOCK(sc);
2780 if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
2781 mac = (struct bwn_mac *)sc->sc_curmac;
2782 bwn_set_slot_time(mac,
2783 (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20);
2784 }
2785 BWN_UNLOCK(sc);
2786}
2787
2788/*
2789 * Callback from the 802.11 layer after a promiscuous mode change.
2790 * Note this interface does not check the operating mode as this
2791 * is an internal callback and we are expected to honor the current
2792 * state (e.g. this is used for setting the interface in promiscuous
2793 * mode when operating in hostap mode to do ACS).
2794 */
2795static void
2796bwn_update_promisc(struct ifnet *ifp)
2797{
2798 struct bwn_softc *sc = ifp->if_softc;
2799 struct bwn_mac *mac = sc->sc_curmac;
2800
2801 BWN_LOCK(sc);
2802 mac = sc->sc_curmac;
2803 if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2804 if (ifp->if_flags & IFF_PROMISC)
2805 sc->sc_filters |= BWN_MACCTL_PROMISC;
2806 else
2807 sc->sc_filters &= ~BWN_MACCTL_PROMISC;
2808 bwn_set_opmode(mac);
2809 }
2810 BWN_UNLOCK(sc);
2811}
2812
2813/*
2814 * Callback from the 802.11 layer to update WME parameters.
2815 */
2816static int
2817bwn_wme_update(struct ieee80211com *ic)
2818{
2819 struct bwn_softc *sc = ic->ic_ifp->if_softc;
2820 struct bwn_mac *mac = sc->sc_curmac;
2821 struct wmeParams *wmep;
2822 int i;
2823
2824 BWN_LOCK(sc);
2825 mac = sc->sc_curmac;
2826 if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2827 bwn_mac_suspend(mac);
2828 for (i = 0; i < N(sc->sc_wmeParams); i++) {
2829 wmep = &ic->ic_wme.wme_chanParams.cap_wmeParams[i];
2830 bwn_wme_loadparams(mac, wmep, bwn_wme_shm_offsets[i]);
2831 }
2832 bwn_mac_enable(mac);
2833 }
2834 BWN_UNLOCK(sc);
2835 return (0);
2836}
2837
2838static void
2839bwn_scan_start(struct ieee80211com *ic)
2840{
2841 struct ifnet *ifp = ic->ic_ifp;
2842 struct bwn_softc *sc = ifp->if_softc;
2843 struct bwn_mac *mac;
2844
2845 BWN_LOCK(sc);
2846 mac = sc->sc_curmac;
2847 if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2848 sc->sc_filters |= BWN_MACCTL_BEACON_PROMISC;
2849 bwn_set_opmode(mac);
2850 /* disable CFP update during scan */
2851 bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_SKIP_CFP_UPDATE);
2852 }
2853 BWN_UNLOCK(sc);
2854}
2855
2856static void
2857bwn_scan_end(struct ieee80211com *ic)
2858{
2859 struct ifnet *ifp = ic->ic_ifp;
2860 struct bwn_softc *sc = ifp->if_softc;
2861 struct bwn_mac *mac;
2862
2863 BWN_LOCK(sc);
2864 mac = sc->sc_curmac;
2865 if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2866 sc->sc_filters &= ~BWN_MACCTL_BEACON_PROMISC;
2867 bwn_set_opmode(mac);
2868 bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_SKIP_CFP_UPDATE);
2869 }
2870 BWN_UNLOCK(sc);
2871}
2872
2873static void
2874bwn_set_channel(struct ieee80211com *ic)
2875{
2876 struct ifnet *ifp = ic->ic_ifp;
2877 struct bwn_softc *sc = ifp->if_softc;
2878 struct bwn_mac *mac = sc->sc_curmac;
2879 struct bwn_phy *phy = &mac->mac_phy;
2880 int chan, error;
2881
2882 BWN_LOCK(sc);
2883
2884 error = bwn_switch_band(sc, ic->ic_curchan);
2885 if (error)
2886 goto fail;
2887 bwn_mac_suspend(mac);
2888 bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
2889 chan = ieee80211_chan2ieee(ic, ic->ic_curchan);
2890 if (chan != phy->chan)
2891 bwn_switch_channel(mac, chan);
2892
2893 /* TX power level */
2894 if (ic->ic_curchan->ic_maxpower != 0 &&
2895 ic->ic_curchan->ic_maxpower != phy->txpower) {
2896 phy->txpower = ic->ic_curchan->ic_maxpower / 2;
2897 bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME |
2898 BWN_TXPWR_IGNORE_TSSI);
2899 }
2900
2901 bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
2902 if (phy->set_antenna)
2903 phy->set_antenna(mac, BWN_ANT_DEFAULT);
2904
2905 if (sc->sc_rf_enabled != phy->rf_on) {
2906 if (sc->sc_rf_enabled) {
2907 bwn_rf_turnon(mac);
2908 if (!(mac->mac_flags & BWN_MAC_FLAG_RADIO_ON))
2909 device_printf(sc->sc_dev,
2910 "please turn on the RF switch\n");
2911 } else
2912 bwn_rf_turnoff(mac);
2913 }
2914
2915 bwn_mac_enable(mac);
2916
2917fail:
2918 /*
2919 * Setup radio tap channel freq and flags
2920 */
2921 sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq =
2922 htole16(ic->ic_curchan->ic_freq);
2923 sc->sc_tx_th.wt_chan_flags = sc->sc_rx_th.wr_chan_flags =
2924 htole16(ic->ic_curchan->ic_flags & 0xffff);
2925
2926 BWN_UNLOCK(sc);
2927}
2928
2929static struct ieee80211vap *
2930bwn_vap_create(struct ieee80211com *ic,
2931 const char name[IFNAMSIZ], int unit, int opmode, int flags,
2932 const uint8_t bssid[IEEE80211_ADDR_LEN],
2933 const uint8_t mac0[IEEE80211_ADDR_LEN])
2934{
2935 struct ifnet *ifp = ic->ic_ifp;
2936 struct bwn_softc *sc = ifp->if_softc;
2937 struct ieee80211vap *vap;
2938 struct bwn_vap *bvp;
2939 uint8_t mac[IEEE80211_ADDR_LEN];
2940
2941 IEEE80211_ADDR_COPY(mac, mac0);
2942 switch (opmode) {
2943 case IEEE80211_M_HOSTAP:
2944 case IEEE80211_M_MBSS:
2945 case IEEE80211_M_STA:
2946 case IEEE80211_M_WDS:
2947 case IEEE80211_M_MONITOR:
2948 case IEEE80211_M_IBSS:
2949 case IEEE80211_M_AHDEMO:
2950 break;
2951 default:
2952 return (NULL);
2953 }
2954
2955 IEEE80211_ADDR_COPY(sc->sc_macaddr, mac0);
2956
2957 bvp = (struct bwn_vap *) malloc(sizeof(struct bwn_vap),
2958 M_80211_VAP, M_NOWAIT | M_ZERO);
2959 if (bvp == NULL) {
2960 device_printf(sc->sc_dev, "failed to allocate a buffer\n");
2961 return (NULL);
2962 }
2963 vap = &bvp->bv_vap;
2964 ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
2965 IEEE80211_ADDR_COPY(vap->iv_myaddr, mac);
2966 /* override with driver methods */
2967 bvp->bv_newstate = vap->iv_newstate;
2968 vap->iv_newstate = bwn_newstate;
2969
2970 /* override max aid so sta's cannot assoc when we're out of sta id's */
2971 vap->iv_max_aid = BWN_STAID_MAX;
2972
2973 ieee80211_ratectl_init(vap);
2974
2975 /* complete setup */
2976 ieee80211_vap_attach(vap, ieee80211_media_change,
2977 ieee80211_media_status);
2978 return (vap);
2979}
2980
2981static void
2982bwn_vap_delete(struct ieee80211vap *vap)
2983{
2984 struct bwn_vap *bvp = BWN_VAP(vap);
2985
2986 ieee80211_ratectl_deinit(vap);
2987 ieee80211_vap_detach(vap);
2988 free(bvp, M_80211_VAP);
2989}
2990
2991static void
2992bwn_init(void *arg)
2993{
2994 struct bwn_softc *sc = arg;
2995 struct ifnet *ifp = sc->sc_ifp;
2996 struct ieee80211com *ic = ifp->if_l2com;
2997 int error = 0;
2998
2999 DPRINTF(sc, BWN_DEBUG_ANY, "%s: if_flags 0x%x\n",
3000 __func__, ifp->if_flags);
3001
3002 BWN_LOCK(sc);
3003 error = bwn_init_locked(sc);
3004 BWN_UNLOCK(sc);
3005
3006 if (error == 0)
3007 ieee80211_start_all(ic); /* start all vap's */
3008}
3009
3010static int
3011bwn_init_locked(struct bwn_softc *sc)
3012{
3013 struct bwn_mac *mac;
3014 struct ifnet *ifp = sc->sc_ifp;
3015 int error;
3016
3017 BWN_ASSERT_LOCKED(sc);
3018
3019 bzero(sc->sc_bssid, IEEE80211_ADDR_LEN);
3020 sc->sc_flags |= BWN_FLAG_NEED_BEACON_TP;
3021 sc->sc_filters = 0;
3022 bwn_wme_clear(sc);
3023 sc->sc_beacons[0] = sc->sc_beacons[1] = 0;
3024 sc->sc_rf_enabled = 1;
3025
3026 mac = sc->sc_curmac;
3027 if (mac->mac_status == BWN_MAC_STATUS_UNINIT) {
3028 error = bwn_core_init(mac);
3029 if (error != 0)
3030 return (error);
3031 }
3032 if (mac->mac_status == BWN_MAC_STATUS_INITED)
3033 bwn_core_start(mac);
3034
3035 bwn_set_opmode(mac);
3036 bwn_set_pretbtt(mac);
3037 bwn_spu_setdelay(mac, 0);
3038 bwn_set_macaddr(mac);
3039
3040 ifp->if_drv_flags |= IFF_DRV_RUNNING;
3041 callout_reset(&sc->sc_rfswitch_ch, hz, bwn_rfswitch, sc);
3042 callout_reset(&sc->sc_watchdog_ch, hz, bwn_watchdog, sc);
3043
3044 return (0);
3045}
3046
3047static void
3048bwn_stop(struct bwn_softc *sc, int statechg)
3049{
3050
3051 BWN_LOCK(sc);
3052 bwn_stop_locked(sc, statechg);
3053 BWN_UNLOCK(sc);
3054}
3055
3056static void
3057bwn_stop_locked(struct bwn_softc *sc, int statechg)
3058{
3059 struct bwn_mac *mac = sc->sc_curmac;
3060 struct ifnet *ifp = sc->sc_ifp;
3061
3062 BWN_ASSERT_LOCKED(sc);
3063
3064 if (mac->mac_status >= BWN_MAC_STATUS_INITED) {
3065 /* XXX FIXME opmode not based on VAP */
3066 bwn_set_opmode(mac);
3067 bwn_set_macaddr(mac);
3068 }
3069
3070 if (mac->mac_status >= BWN_MAC_STATUS_STARTED)
3071 bwn_core_stop(mac);
3072
3073 callout_stop(&sc->sc_led_blink_ch);
3074 sc->sc_led_blinking = 0;
3075
3076 bwn_core_exit(mac);
3077 sc->sc_rf_enabled = 0;
3078
3079 ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
3080}
3081
3082static void
3083bwn_wme_clear(struct bwn_softc *sc)
3084{
3085#define MS(_v, _f) (((_v) & _f) >> _f##_S)
3086 struct wmeParams *p;
3087 unsigned int i;
3088
3089 KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
3090 ("%s:%d: fail", __func__, __LINE__));
3091
3092 for (i = 0; i < N(sc->sc_wmeParams); i++) {
3093 p = &(sc->sc_wmeParams[i]);
3094
3095 switch (bwn_wme_shm_offsets[i]) {
3096 case BWN_WME_VOICE:
3097 p->wmep_txopLimit = 0;
3098 p->wmep_aifsn = 2;
3099 /* XXX FIXME: log2(cwmin) */
3100 p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3101 p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3102 break;
3103 case BWN_WME_VIDEO:
3104 p->wmep_txopLimit = 0;
3105 p->wmep_aifsn = 2;
3106 /* XXX FIXME: log2(cwmin) */
3107 p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3108 p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3109 break;
3110 case BWN_WME_BESTEFFORT:
3111 p->wmep_txopLimit = 0;
3112 p->wmep_aifsn = 3;
3113 /* XXX FIXME: log2(cwmin) */
3114 p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3115 p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3116 break;
3117 case BWN_WME_BACKGROUND:
3118 p->wmep_txopLimit = 0;
3119 p->wmep_aifsn = 7;
3120 /* XXX FIXME: log2(cwmin) */
3121 p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3122 p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3123 break;
3124 default:
3125 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3126 }
3127 }
3128}
3129
3130static int
3131bwn_core_init(struct bwn_mac *mac)
3132{
3133 struct bwn_softc *sc = mac->mac_sc;
3134 uint64_t hf;
3135 int error;
3136
3137 KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3138 ("%s:%d: fail", __func__, __LINE__));
3139
3140 siba_powerup(sc->sc_dev, 0);
3141 if (!siba_dev_isup(sc->sc_dev))
3142 bwn_reset_core(mac,
3143 mac->mac_phy.gmode ? BWN_TGSLOW_SUPPORT_G : 0);
3144
3145 mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
3146 mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
3147 mac->mac_phy.hwpctl = (bwn_hwpctl) ? 1 : 0;
3148 BWN_GETTIME(mac->mac_phy.nexttime);
3149 mac->mac_phy.txerrors = BWN_TXERROR_MAX;
3150 bzero(&mac->mac_stats, sizeof(mac->mac_stats));
3151 mac->mac_stats.link_noise = -95;
3152 mac->mac_reason_intr = 0;
3153 bzero(mac->mac_reason, sizeof(mac->mac_reason));
3154 mac->mac_intr_mask = BWN_INTR_MASKTEMPLATE;
3155#ifdef BWN_DEBUG
3156 if (sc->sc_debug & BWN_DEBUG_XMIT)
3157 mac->mac_intr_mask &= ~BWN_INTR_PHY_TXERR;
3158#endif
3159 mac->mac_suspended = 1;
3160 mac->mac_task_state = 0;
3161 memset(&mac->mac_noise, 0, sizeof(mac->mac_noise));
3162
3163 mac->mac_phy.init_pre(mac);
3164
3165 siba_pcicore_intr(sc->sc_dev);
3166
3167 siba_fix_imcfglobug(sc->sc_dev);
3168 bwn_bt_disable(mac);
3169 if (mac->mac_phy.prepare_hw) {
3170 error = mac->mac_phy.prepare_hw(mac);
3171 if (error)
3172 goto fail0;
3173 }
3174 error = bwn_chip_init(mac);
3175 if (error)
3176 goto fail0;
3177 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_COREREV,
3178 siba_get_revid(sc->sc_dev));
3179 hf = bwn_hf_read(mac);
3180 if (mac->mac_phy.type == BWN_PHYTYPE_G) {
3181 hf |= BWN_HF_GPHY_SYM_WORKAROUND;
3182 if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
3183 hf |= BWN_HF_PAGAINBOOST_OFDM_ON;
3184 if (mac->mac_phy.rev == 1)
3185 hf |= BWN_HF_GPHY_DC_CANCELFILTER;
3186 }
3187 if (mac->mac_phy.rf_ver == 0x2050) {
3188 if (mac->mac_phy.rf_rev < 6)
3189 hf |= BWN_HF_FORCE_VCO_RECALC;
3190 if (mac->mac_phy.rf_rev == 6)
3191 hf |= BWN_HF_4318_TSSI;
3192 }
3193 if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW)
3194 hf |= BWN_HF_SLOWCLOCK_REQ_OFF;
3195 if ((siba_get_type(sc->sc_dev) == SIBA_TYPE_PCI) &&
3196 (siba_get_pcicore_revid(sc->sc_dev) <= 10))
3197 hf |= BWN_HF_PCI_SLOWCLOCK_WORKAROUND;
3198 hf &= ~BWN_HF_SKIP_CFP_UPDATE;
3199 bwn_hf_write(mac, hf);
3200
3201 bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
3202 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SHORT_RETRY_FALLBACK, 3);
3203 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_LONG_RETRY_FALLBACK, 2);
3204 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_MAXTIME, 1);
3205
3206 bwn_rate_init(mac);
3207 bwn_set_phytxctl(mac);
3208
3209 bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MIN,
3210 (mac->mac_phy.type == BWN_PHYTYPE_B) ? 0x1f : 0xf);
3211 bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MAX, 0x3ff);
3212
3213 if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
3214 bwn_pio_init(mac);
3215 else
3216 bwn_dma_init(mac);
3217 bwn_wme_init(mac);
3218 bwn_spu_setdelay(mac, 1);
3219 bwn_bt_enable(mac);
3220
3221 siba_powerup(sc->sc_dev,
3222 !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW));
3223 bwn_set_macaddr(mac);
3224 bwn_crypt_init(mac);
3225
3226 /* XXX LED initializatin */
3227
3228 mac->mac_status = BWN_MAC_STATUS_INITED;
3229
3230 return (error);
3231
3232fail0:
3233 siba_powerdown(sc->sc_dev);
3234 KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3235 ("%s:%d: fail", __func__, __LINE__));
3236 return (error);
3237}
3238
3239static void
3240bwn_core_start(struct bwn_mac *mac)
3241{
3242 struct bwn_softc *sc = mac->mac_sc;
3243 uint32_t tmp;
3244
3245 KASSERT(mac->mac_status == BWN_MAC_STATUS_INITED,
3246 ("%s:%d: fail", __func__, __LINE__));
3247
3248 if (siba_get_revid(sc->sc_dev) < 5)
3249 return;
3250
3251 while (1) {
3252 tmp = BWN_READ_4(mac, BWN_XMITSTAT_0);
3253 if (!(tmp & 0x00000001))
3254 break;
3255 tmp = BWN_READ_4(mac, BWN_XMITSTAT_1);
3256 }
3257
3258 bwn_mac_enable(mac);
3259 BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
3260 callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
3261
3262 mac->mac_status = BWN_MAC_STATUS_STARTED;
3263}
3264
3265static void
3266bwn_core_exit(struct bwn_mac *mac)
3267{
3268 struct bwn_softc *sc = mac->mac_sc;
3269 uint32_t macctl;
3270
3271 BWN_ASSERT_LOCKED(mac->mac_sc);
3272
3273 KASSERT(mac->mac_status <= BWN_MAC_STATUS_INITED,
3274 ("%s:%d: fail", __func__, __LINE__));
3275
3276 if (mac->mac_status != BWN_MAC_STATUS_INITED)
3277 return;
3278 mac->mac_status = BWN_MAC_STATUS_UNINIT;
3279
3280 macctl = BWN_READ_4(mac, BWN_MACCTL);
3281 macctl &= ~BWN_MACCTL_MCODE_RUN;
3282 macctl |= BWN_MACCTL_MCODE_JMP0;
3283 BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3284
3285 bwn_dma_stop(mac);
3286 bwn_pio_stop(mac);
3287 bwn_chip_exit(mac);
3288 mac->mac_phy.switch_analog(mac, 0);
3289 siba_dev_down(sc->sc_dev, 0);
3290 siba_powerdown(sc->sc_dev);
3291}
3292
3293static void
3294bwn_bt_disable(struct bwn_mac *mac)
3295{
3296 struct bwn_softc *sc = mac->mac_sc;
3297
3298 (void)sc;
3299 /* XXX do nothing yet */
3300}
3301
3302static int
3303bwn_chip_init(struct bwn_mac *mac)
3304{
3305 struct bwn_softc *sc = mac->mac_sc;
3306 struct bwn_phy *phy = &mac->mac_phy;
3307 uint32_t macctl;
3308 int error;
3309
3310 macctl = BWN_MACCTL_IHR_ON | BWN_MACCTL_SHM_ON | BWN_MACCTL_STA;
3311 if (phy->gmode)
3312 macctl |= BWN_MACCTL_GMODE;
3313 BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3314
3315 error = bwn_fw_fillinfo(mac);
3316 if (error)
3317 return (error);
3318 error = bwn_fw_loaducode(mac);
3319 if (error)
3320 return (error);
3321
3322 error = bwn_gpio_init(mac);
3323 if (error)
3324 return (error);
3325
3326 error = bwn_fw_loadinitvals(mac);
3327 if (error) {
3328 siba_gpio_set(sc->sc_dev, 0);
3329 return (error);
3330 }
3331 phy->switch_analog(mac, 1);
3332 error = bwn_phy_init(mac);
3333 if (error) {
3334 siba_gpio_set(sc->sc_dev, 0);
3335 return (error);
3336 }
3337 if (phy->set_im)
3338 phy->set_im(mac, BWN_IMMODE_NONE);
3339 if (phy->set_antenna)
3340 phy->set_antenna(mac, BWN_ANT_DEFAULT);
3341 bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
3342
3343 if (phy->type == BWN_PHYTYPE_B)
3344 BWN_WRITE_2(mac, 0x005e, BWN_READ_2(mac, 0x005e) | 0x0004);
3345 BWN_WRITE_4(mac, 0x0100, 0x01000000);
3346 if (siba_get_revid(sc->sc_dev) < 5)
3347 BWN_WRITE_4(mac, 0x010c, 0x01000000);
3348
3349 BWN_WRITE_4(mac, BWN_MACCTL,
3350 BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_STA);
3351 BWN_WRITE_4(mac, BWN_MACCTL,
3352 BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_STA);
3353 bwn_shm_write_2(mac, BWN_SHARED, 0x0074, 0x0000);
3354
3355 bwn_set_opmode(mac);
3356 if (siba_get_revid(sc->sc_dev) < 3) {
3357 BWN_WRITE_2(mac, 0x060e, 0x0000);
3358 BWN_WRITE_2(mac, 0x0610, 0x8000);
3359 BWN_WRITE_2(mac, 0x0604, 0x0000);
3360 BWN_WRITE_2(mac, 0x0606, 0x0200);
3361 } else {
3362 BWN_WRITE_4(mac, 0x0188, 0x80000000);
3363 BWN_WRITE_4(mac, 0x018c, 0x02000000);
3364 }
3365 BWN_WRITE_4(mac, BWN_INTR_REASON, 0x00004000);
3366 BWN_WRITE_4(mac, BWN_DMA0_INTR_MASK, 0x0001dc00);
3367 BWN_WRITE_4(mac, BWN_DMA1_INTR_MASK, 0x0000dc00);
3368 BWN_WRITE_4(mac, BWN_DMA2_INTR_MASK, 0x0000dc00);
3369 BWN_WRITE_4(mac, BWN_DMA3_INTR_MASK, 0x0001dc00);
3370 BWN_WRITE_4(mac, BWN_DMA4_INTR_MASK, 0x0000dc00);
3371 BWN_WRITE_4(mac, BWN_DMA5_INTR_MASK, 0x0000dc00);
3372 siba_write_4(sc->sc_dev, SIBA_TGSLOW,
3373 siba_read_4(sc->sc_dev, SIBA_TGSLOW) | 0x00100000);
3374 BWN_WRITE_2(mac, BWN_POWERUP_DELAY, siba_get_cc_powerdelay(sc->sc_dev));
3375 return (error);
3376}
3377
3378/* read hostflags */
3379static uint64_t
3380bwn_hf_read(struct bwn_mac *mac)
3381{
3382 uint64_t ret;
3383
3384 ret = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFHI);
3385 ret <<= 16;
3386 ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFMI);
3387 ret <<= 16;
3388 ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO);
3389 return (ret);
3390}
3391
3392static void
3393bwn_hf_write(struct bwn_mac *mac, uint64_t value)
3394{
3395
3396 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFLO,
3397 (value & 0x00000000ffffull));
3398 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFMI,
3399 (value & 0x0000ffff0000ull) >> 16);
3400 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFHI,
3401 (value & 0xffff00000000ULL) >> 32);
3402}
3403
3404static void
3405bwn_set_txretry(struct bwn_mac *mac, int s, int l)
3406{
3407
3408 bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_SHORT_RETRY, MIN(s, 0xf));
3409 bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_LONG_RETRY, MIN(l, 0xf));
3410}
3411
3412static void
3413bwn_rate_init(struct bwn_mac *mac)
3414{
3415
3416 switch (mac->mac_phy.type) {
3417 case BWN_PHYTYPE_A:
3418 case BWN_PHYTYPE_G:
3419 case BWN_PHYTYPE_LP:
3420 case BWN_PHYTYPE_N:
3421 bwn_rate_write(mac, BWN_OFDM_RATE_6MB, 1);
3422 bwn_rate_write(mac, BWN_OFDM_RATE_12MB, 1);
3423 bwn_rate_write(mac, BWN_OFDM_RATE_18MB, 1);
3424 bwn_rate_write(mac, BWN_OFDM_RATE_24MB, 1);
3425 bwn_rate_write(mac, BWN_OFDM_RATE_36MB, 1);
3426 bwn_rate_write(mac, BWN_OFDM_RATE_48MB, 1);
3427 bwn_rate_write(mac, BWN_OFDM_RATE_54MB, 1);
3428 if (mac->mac_phy.type == BWN_PHYTYPE_A)
3429 break;
3430 /* FALLTHROUGH */
3431 case BWN_PHYTYPE_B:
3432 bwn_rate_write(mac, BWN_CCK_RATE_1MB, 0);
3433 bwn_rate_write(mac, BWN_CCK_RATE_2MB, 0);
3434 bwn_rate_write(mac, BWN_CCK_RATE_5MB, 0);
3435 bwn_rate_write(mac, BWN_CCK_RATE_11MB, 0);
3436 break;
3437 default:
3438 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3439 }
3440}
3441
3442static void
3443bwn_rate_write(struct bwn_mac *mac, uint16_t rate, int ofdm)
3444{
3445 uint16_t offset;
3446
3447 if (ofdm) {
3448 offset = 0x480;
3449 offset += (bwn_plcp_getofdm(rate) & 0x000f) * 2;
3450 } else {
3451 offset = 0x4c0;
3452 offset += (bwn_plcp_getcck(rate) & 0x000f) * 2;
3453 }
3454 bwn_shm_write_2(mac, BWN_SHARED, offset + 0x20,
3455 bwn_shm_read_2(mac, BWN_SHARED, offset));
3456}
3457
3458static uint8_t
3459bwn_plcp_getcck(const uint8_t bitrate)
3460{
3461
3462 switch (bitrate) {
3463 case BWN_CCK_RATE_1MB:
3464 return (0x0a);
3465 case BWN_CCK_RATE_2MB:
3466 return (0x14);
3467 case BWN_CCK_RATE_5MB:
3468 return (0x37);
3469 case BWN_CCK_RATE_11MB:
3470 return (0x6e);
3471 }
3472 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3473 return (0);
3474}
3475
3476static uint8_t
3477bwn_plcp_getofdm(const uint8_t bitrate)
3478{
3479
3480 switch (bitrate) {
3481 case BWN_OFDM_RATE_6MB:
3482 return (0xb);
3483 case BWN_OFDM_RATE_9MB:
3484 return (0xf);
3485 case BWN_OFDM_RATE_12MB:
3486 return (0xa);
3487 case BWN_OFDM_RATE_18MB:
3488 return (0xe);
3489 case BWN_OFDM_RATE_24MB:
3490 return (0x9);
3491 case BWN_OFDM_RATE_36MB:
3492 return (0xd);
3493 case BWN_OFDM_RATE_48MB:
3494 return (0x8);
3495 case BWN_OFDM_RATE_54MB:
3496 return (0xc);
3497 }
3498 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3499 return (0);
3500}
3501
3502static void
3503bwn_set_phytxctl(struct bwn_mac *mac)
3504{
3505 uint16_t ctl;
3506
3507 ctl = (BWN_TX_PHY_ENC_CCK | BWN_TX_PHY_ANT01AUTO |
3508 BWN_TX_PHY_TXPWR);
3509 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_BEACON_PHYCTL, ctl);
3510 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, ctl);
3511 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, ctl);
3512}
3513
3514static void
3515bwn_pio_init(struct bwn_mac *mac)
3516{
3517 struct bwn_pio *pio = &mac->mac_method.pio;
3518
3519 BWN_WRITE_4(mac, BWN_MACCTL, BWN_READ_4(mac, BWN_MACCTL)
3520 & ~BWN_MACCTL_BIGENDIAN);
3521 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RX_PADOFFSET, 0);
3522
3523 bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BK], 0);
3524 bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BE], 1);
3525 bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VI], 2);
3526 bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VO], 3);
3527 bwn_pio_set_txqueue(mac, &pio->mcast, 4);
3528 bwn_pio_setupqueue_rx(mac, &pio->rx, 0);
3529}
3530
3531static void
3532bwn_pio_set_txqueue(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3533 int index)
3534{
3535 struct bwn_pio_txpkt *tp;
3536 struct bwn_softc *sc = mac->mac_sc;
3537 unsigned int i;
3538
3539 tq->tq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_TXQOFFSET(mac);
3540 tq->tq_index = index;
3541
3542 tq->tq_free = BWN_PIO_MAX_TXPACKETS;
3543 if (siba_get_revid(sc->sc_dev) >= 8)
3544 tq->tq_size = 1920;
3545 else {
3546 tq->tq_size = bwn_pio_read_2(mac, tq, BWN_PIO_TXQBUFSIZE);
3547 tq->tq_size -= 80;
3548 }
3549
3550 TAILQ_INIT(&tq->tq_pktlist);
3551 for (i = 0; i < N(tq->tq_pkts); i++) {
3552 tp = &(tq->tq_pkts[i]);
3553 tp->tp_index = i;
3554 tp->tp_queue = tq;
3555 TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
3556 }
3557}
3558
3559static uint16_t
3560bwn_pio_idx2base(struct bwn_mac *mac, int index)
3561{
3562 struct bwn_softc *sc = mac->mac_sc;
3563 static const uint16_t bases[] = {
3564 BWN_PIO_BASE0,
3565 BWN_PIO_BASE1,
3566 BWN_PIO_BASE2,
3567 BWN_PIO_BASE3,
3568 BWN_PIO_BASE4,
3569 BWN_PIO_BASE5,
3570 BWN_PIO_BASE6,
3571 BWN_PIO_BASE7,
3572 };
3573 static const uint16_t bases_rev11[] = {
3574 BWN_PIO11_BASE0,
3575 BWN_PIO11_BASE1,
3576 BWN_PIO11_BASE2,
3577 BWN_PIO11_BASE3,
3578 BWN_PIO11_BASE4,
3579 BWN_PIO11_BASE5,
3580 };
3581
3582 if (siba_get_revid(sc->sc_dev) >= 11) {
3583 if (index >= N(bases_rev11))
3584 device_printf(sc->sc_dev, "%s: warning\n", __func__);
3585 return (bases_rev11[index]);
3586 }
3587 if (index >= N(bases))
3588 device_printf(sc->sc_dev, "%s: warning\n", __func__);
3589 return (bases[index]);
3590}
3591
3592static void
3593bwn_pio_setupqueue_rx(struct bwn_mac *mac, struct bwn_pio_rxqueue *prq,
3594 int index)
3595{
3596 struct bwn_softc *sc = mac->mac_sc;
3597
3598 prq->prq_mac = mac;
3599 prq->prq_rev = siba_get_revid(sc->sc_dev);
3600 prq->prq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_RXQOFFSET(mac);
3601 bwn_dma_rxdirectfifo(mac, index, 1);
3602}
3603
3604static void
3605bwn_destroy_pioqueue_tx(struct bwn_pio_txqueue *tq)
3606{
3607 if (tq == NULL)
3608 return;
3609 bwn_pio_cancel_tx_packets(tq);
3610}
3611
3612static void
3613bwn_destroy_queue_tx(struct bwn_pio_txqueue *pio)
3614{
3615
3616 bwn_destroy_pioqueue_tx(pio);
3617}
3618
3619static uint16_t
3620bwn_pio_read_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3621 uint16_t offset)
3622{
3623
3624 return (BWN_READ_2(mac, tq->tq_base + offset));
3625}
3626
3627static void
3628bwn_dma_rxdirectfifo(struct bwn_mac *mac, int idx, uint8_t enable)
3629{
3630 uint32_t ctl;
3631 int type;
3632 uint16_t base;
3633
3634 type = bwn_dma_mask2type(bwn_dma_mask(mac));
3635 base = bwn_dma_base(type, idx);
3636 if (type == BWN_DMA_64BIT) {
3637 ctl = BWN_READ_4(mac, base + BWN_DMA64_RXCTL);
3638 ctl &= ~BWN_DMA64_RXDIRECTFIFO;
3639 if (enable)
3640 ctl |= BWN_DMA64_RXDIRECTFIFO;
3641 BWN_WRITE_4(mac, base + BWN_DMA64_RXCTL, ctl);
3642 } else {
3643 ctl = BWN_READ_4(mac, base + BWN_DMA32_RXCTL);
3644 ctl &= ~BWN_DMA32_RXDIRECTFIFO;
3645 if (enable)
3646 ctl |= BWN_DMA32_RXDIRECTFIFO;
3647 BWN_WRITE_4(mac, base + BWN_DMA32_RXCTL, ctl);
3648 }
3649}
3650
3651static uint64_t
3652bwn_dma_mask(struct bwn_mac *mac)
3653{
3654 uint32_t tmp;
3655 uint16_t base;
3656
3657 tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
3658 if (tmp & SIBA_TGSHIGH_DMA64)
3659 return (BWN_DMA_BIT_MASK(64));
3660 base = bwn_dma_base(0, 0);
3661 BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
3662 tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
3663 if (tmp & BWN_DMA32_TXADDREXT_MASK)
3664 return (BWN_DMA_BIT_MASK(32));
3665
3666 return (BWN_DMA_BIT_MASK(30));
3667}
3668
3669static int
3670bwn_dma_mask2type(uint64_t dmamask)
3671{
3672
3673 if (dmamask == BWN_DMA_BIT_MASK(30))
3674 return (BWN_DMA_30BIT);
3675 if (dmamask == BWN_DMA_BIT_MASK(32))
3676 return (BWN_DMA_32BIT);
3677 if (dmamask == BWN_DMA_BIT_MASK(64))
3678 return (BWN_DMA_64BIT);
3679 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3680 return (BWN_DMA_30BIT);
3681}
3682
3683static void
3684bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *tq)
3685{
3686 struct bwn_pio_txpkt *tp;
3687 unsigned int i;
3688
3689 for (i = 0; i < N(tq->tq_pkts); i++) {
3690 tp = &(tq->tq_pkts[i]);
3691 if (tp->tp_m) {
3692 m_freem(tp->tp_m);
3693 tp->tp_m = NULL;
3694 }
3695 }
3696}
3697
3698static uint16_t
3699bwn_dma_base(int type, int controller_idx)
3700{
3701 static const uint16_t map64[] = {
3702 BWN_DMA64_BASE0,
3703 BWN_DMA64_BASE1,
3704 BWN_DMA64_BASE2,
3705 BWN_DMA64_BASE3,
3706 BWN_DMA64_BASE4,
3707 BWN_DMA64_BASE5,
3708 };
3709 static const uint16_t map32[] = {
3710 BWN_DMA32_BASE0,
3711 BWN_DMA32_BASE1,
3712 BWN_DMA32_BASE2,
3713 BWN_DMA32_BASE3,
3714 BWN_DMA32_BASE4,
3715 BWN_DMA32_BASE5,
3716 };
3717
3718 if (type == BWN_DMA_64BIT) {
3719 KASSERT(controller_idx >= 0 && controller_idx < N(map64),
3720 ("%s:%d: fail", __func__, __LINE__));
3721 return (map64[controller_idx]);
3722 }
3723 KASSERT(controller_idx >= 0 && controller_idx < N(map32),
3724 ("%s:%d: fail", __func__, __LINE__));
3725 return (map32[controller_idx]);
3726}
3727
3728static void
3729bwn_dma_init(struct bwn_mac *mac)
3730{
3731 struct bwn_dma *dma = &mac->mac_method.dma;
3732
3733 /* setup TX DMA channels. */
3734 bwn_dma_setup(dma->wme[WME_AC_BK]);
3735 bwn_dma_setup(dma->wme[WME_AC_BE]);
3736 bwn_dma_setup(dma->wme[WME_AC_VI]);
3737 bwn_dma_setup(dma->wme[WME_AC_VO]);
3738 bwn_dma_setup(dma->mcast);
3739 /* setup RX DMA channel. */
3740 bwn_dma_setup(dma->rx);
3741}
3742
3743static struct bwn_dma_ring *
3744bwn_dma_ringsetup(struct bwn_mac *mac, int controller_index,
3745 int for_tx, int type)
3746{
3747 struct bwn_dma *dma = &mac->mac_method.dma;
3748 struct bwn_dma_ring *dr;
3749 struct bwn_dmadesc_generic *desc;
3750 struct bwn_dmadesc_meta *mt;
3751 struct bwn_softc *sc = mac->mac_sc;
3752 int error, i;
3753
3754 dr = malloc(sizeof(*dr), M_DEVBUF, M_NOWAIT | M_ZERO);
3755 if (dr == NULL)
3756 goto out;
3757 dr->dr_numslots = BWN_RXRING_SLOTS;
3758 if (for_tx)
3759 dr->dr_numslots = BWN_TXRING_SLOTS;
3760
3761 dr->dr_meta = malloc(dr->dr_numslots * sizeof(struct bwn_dmadesc_meta),
3762 M_DEVBUF, M_NOWAIT | M_ZERO);
3763 if (dr->dr_meta == NULL)
3764 goto fail0;
3765
3766 dr->dr_type = type;
3767 dr->dr_mac = mac;
3768 dr->dr_base = bwn_dma_base(type, controller_index);
3769 dr->dr_index = controller_index;
3770 if (type == BWN_DMA_64BIT) {
3771 dr->getdesc = bwn_dma_64_getdesc;
3772 dr->setdesc = bwn_dma_64_setdesc;
3773 dr->start_transfer = bwn_dma_64_start_transfer;
3774 dr->suspend = bwn_dma_64_suspend;
3775 dr->resume = bwn_dma_64_resume;
3776 dr->get_curslot = bwn_dma_64_get_curslot;
3777 dr->set_curslot = bwn_dma_64_set_curslot;
3778 } else {
3779 dr->getdesc = bwn_dma_32_getdesc;
3780 dr->setdesc = bwn_dma_32_setdesc;
3781 dr->start_transfer = bwn_dma_32_start_transfer;
3782 dr->suspend = bwn_dma_32_suspend;
3783 dr->resume = bwn_dma_32_resume;
3784 dr->get_curslot = bwn_dma_32_get_curslot;
3785 dr->set_curslot = bwn_dma_32_set_curslot;
3786 }
3787 if (for_tx) {
3788 dr->dr_tx = 1;
3789 dr->dr_curslot = -1;
3790 } else {
3791 if (dr->dr_index == 0) {
3792 dr->dr_rx_bufsize = BWN_DMA0_RX_BUFFERSIZE;
3793 dr->dr_frameoffset = BWN_DMA0_RX_FRAMEOFFSET;
3794 } else
3795 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3796 }
3797
3798 error = bwn_dma_allocringmemory(dr);
3799 if (error)
3800 goto fail2;
3801
3802 if (for_tx) {
3803 /*
3804 * Assumption: BWN_TXRING_SLOTS can be divided by
3805 * BWN_TX_SLOTS_PER_FRAME
3806 */
3807 KASSERT(BWN_TXRING_SLOTS % BWN_TX_SLOTS_PER_FRAME == 0,
3808 ("%s:%d: fail", __func__, __LINE__));
3809
3810 dr->dr_txhdr_cache =
3811 malloc((dr->dr_numslots / BWN_TX_SLOTS_PER_FRAME) *
3812 BWN_HDRSIZE(mac), M_DEVBUF, M_NOWAIT | M_ZERO);
3813 KASSERT(dr->dr_txhdr_cache != NULL,
3814 ("%s:%d: fail", __func__, __LINE__));
3815
3816 /*
3817 * Create TX ring DMA stuffs
3818 */
3819 error = bus_dma_tag_create(dma->parent_dtag,
3820 BWN_ALIGN, 0,
3821 BUS_SPACE_MAXADDR,
3822 BUS_SPACE_MAXADDR,
3823 NULL, NULL,
3824 BWN_HDRSIZE(mac),
3825 1,
3826 BUS_SPACE_MAXSIZE_32BIT,
3827 0,
3828 NULL, NULL,
3829 &dr->dr_txring_dtag);
3830 if (error) {
3831 device_printf(sc->sc_dev,
3832 "can't create TX ring DMA tag: TODO frees\n");
3833 goto fail1;
3834 }
3835
3836 for (i = 0; i < dr->dr_numslots; i += 2) {
3837 dr->getdesc(dr, i, &desc, &mt);
3838
3839 mt->mt_txtype = BWN_DMADESC_METATYPE_HEADER;
3840 mt->mt_m = NULL;
3841 mt->mt_ni = NULL;
3842 mt->mt_islast = 0;
3843 error = bus_dmamap_create(dr->dr_txring_dtag, 0,
3844 &mt->mt_dmap);
3845 if (error) {
3846 device_printf(sc->sc_dev,
3847 "can't create RX buf DMA map\n");
3848 goto fail1;
3849 }
3850
3851 dr->getdesc(dr, i + 1, &desc, &mt);
3852
3853 mt->mt_txtype = BWN_DMADESC_METATYPE_BODY;
3854 mt->mt_m = NULL;
3855 mt->mt_ni = NULL;
3856 mt->mt_islast = 1;
3857 error = bus_dmamap_create(dma->txbuf_dtag, 0,
3858 &mt->mt_dmap);
3859 if (error) {
3860 device_printf(sc->sc_dev,
3861 "can't create RX buf DMA map\n");
3862 goto fail1;
3863 }
3864 }
3865 } else {
3866 error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3867 &dr->dr_spare_dmap);
3868 if (error) {
3869 device_printf(sc->sc_dev,
3870 "can't create RX buf DMA map\n");
3871 goto out; /* XXX wrong! */
3872 }
3873
3874 for (i = 0; i < dr->dr_numslots; i++) {
3875 dr->getdesc(dr, i, &desc, &mt);
3876
3877 error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3878 &mt->mt_dmap);
3879 if (error) {
3880 device_printf(sc->sc_dev,
3881 "can't create RX buf DMA map\n");
3882 goto out; /* XXX wrong! */
3883 }
3884 error = bwn_dma_newbuf(dr, desc, mt, 1);
3885 if (error) {
3886 device_printf(sc->sc_dev,
3887 "failed to allocate RX buf\n");
3888 goto out; /* XXX wrong! */
3889 }
3890 }
3891
3892 bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
3893 BUS_DMASYNC_PREWRITE);
3894
3895 dr->dr_usedslot = dr->dr_numslots;
3896 }
3897
3898 out:
3899 return (dr);
3900
3901fail2:
3902 free(dr->dr_txhdr_cache, M_DEVBUF);
3903fail1:
3904 free(dr->dr_meta, M_DEVBUF);
3905fail0:
3906 free(dr, M_DEVBUF);
3907 return (NULL);
3908}
3909
3910static void
3911bwn_dma_ringfree(struct bwn_dma_ring **dr)
3912{
3913
3914 if (dr == NULL)
3915 return;
3916
3917 bwn_dma_free_descbufs(*dr);
3918 bwn_dma_free_ringmemory(*dr);
3919
3920 free((*dr)->dr_txhdr_cache, M_DEVBUF);
3921 free((*dr)->dr_meta, M_DEVBUF);
3922 free(*dr, M_DEVBUF);
3923
3924 *dr = NULL;
3925}
3926
3927static void
3928bwn_dma_32_getdesc(struct bwn_dma_ring *dr, int slot,
3929 struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
3930{
3931 struct bwn_dmadesc32 *desc;
3932
3933 *meta = &(dr->dr_meta[slot]);
3934 desc = dr->dr_ring_descbase;
3935 desc = &(desc[slot]);
3936
3937 *gdesc = (struct bwn_dmadesc_generic *)desc;
3938}
3939
3940static void
3941bwn_dma_32_setdesc(struct bwn_dma_ring *dr,
3942 struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
3943 int start, int end, int irq)
3944{
3945 struct bwn_dmadesc32 *descbase = dr->dr_ring_descbase;
3946 struct bwn_softc *sc = dr->dr_mac->mac_sc;
3947 uint32_t addr, addrext, ctl;
3948 int slot;
3949
3950 slot = (int)(&(desc->dma.dma32) - descbase);
3951 KASSERT(slot >= 0 && slot < dr->dr_numslots,
3952 ("%s:%d: fail", __func__, __LINE__));
3953
3954 addr = (uint32_t) (dmaaddr & ~SIBA_DMA_TRANSLATION_MASK);
3955 addrext = (uint32_t) (dmaaddr & SIBA_DMA_TRANSLATION_MASK) >> 30;
3956 addr |= siba_dma_translation(sc->sc_dev);
3957 ctl = bufsize & BWN_DMA32_DCTL_BYTECNT;
3958 if (slot == dr->dr_numslots - 1)
3959 ctl |= BWN_DMA32_DCTL_DTABLEEND;
3960 if (start)
3961 ctl |= BWN_DMA32_DCTL_FRAMESTART;
3962 if (end)
3963 ctl |= BWN_DMA32_DCTL_FRAMEEND;
3964 if (irq)
3965 ctl |= BWN_DMA32_DCTL_IRQ;
3966 ctl |= (addrext << BWN_DMA32_DCTL_ADDREXT_SHIFT)
3967 & BWN_DMA32_DCTL_ADDREXT_MASK;
3968
3969 desc->dma.dma32.control = htole32(ctl);
3970 desc->dma.dma32.address = htole32(addr);
3971}
3972
3973static void
3974bwn_dma_32_start_transfer(struct bwn_dma_ring *dr, int slot)
3975{
3976
3977 BWN_DMA_WRITE(dr, BWN_DMA32_TXINDEX,
3978 (uint32_t)(slot * sizeof(struct bwn_dmadesc32)));
3979}
3980
3981static void
3982bwn_dma_32_suspend(struct bwn_dma_ring *dr)
3983{
3984
3985 BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
3986 BWN_DMA_READ(dr, BWN_DMA32_TXCTL) | BWN_DMA32_TXSUSPEND);
3987}
3988
3989static void
3990bwn_dma_32_resume(struct bwn_dma_ring *dr)
3991{
3992
3993 BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
3994 BWN_DMA_READ(dr, BWN_DMA32_TXCTL) & ~BWN_DMA32_TXSUSPEND);
3995}
3996
3997static int
3998bwn_dma_32_get_curslot(struct bwn_dma_ring *dr)
3999{
4000 uint32_t val;
4001
4002 val = BWN_DMA_READ(dr, BWN_DMA32_RXSTATUS);
4003 val &= BWN_DMA32_RXDPTR;
4004
4005 return (val / sizeof(struct bwn_dmadesc32));
4006}
4007
4008static void
4009bwn_dma_32_set_curslot(struct bwn_dma_ring *dr, int slot)
4010{
4011
4012 BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX,
4013 (uint32_t) (slot * sizeof(struct bwn_dmadesc32)));
4014}
4015
4016static void
4017bwn_dma_64_getdesc(struct bwn_dma_ring *dr, int slot,
4018 struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
4019{
4020 struct bwn_dmadesc64 *desc;
4021
4022 *meta = &(dr->dr_meta[slot]);
4023 desc = dr->dr_ring_descbase;
4024 desc = &(desc[slot]);
4025
4026 *gdesc = (struct bwn_dmadesc_generic *)desc;
4027}
4028
4029static void
4030bwn_dma_64_setdesc(struct bwn_dma_ring *dr,
4031 struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
4032 int start, int end, int irq)
4033{
4034 struct bwn_dmadesc64 *descbase = dr->dr_ring_descbase;
4035 struct bwn_softc *sc = dr->dr_mac->mac_sc;
4036 int slot;
4037 uint32_t ctl0 = 0, ctl1 = 0;
4038 uint32_t addrlo, addrhi;
4039 uint32_t addrext;
4040
4041 slot = (int)(&(desc->dma.dma64) - descbase);
4042 KASSERT(slot >= 0 && slot < dr->dr_numslots,
4043 ("%s:%d: fail", __func__, __LINE__));
4044
4045 addrlo = (uint32_t) (dmaaddr & 0xffffffff);
4046 addrhi = (((uint64_t) dmaaddr >> 32) & ~SIBA_DMA_TRANSLATION_MASK);
4047 addrext = (((uint64_t) dmaaddr >> 32) & SIBA_DMA_TRANSLATION_MASK) >>
4048 30;
4049 addrhi |= (siba_dma_translation(sc->sc_dev) << 1);
4050 if (slot == dr->dr_numslots - 1)
4051 ctl0 |= BWN_DMA64_DCTL0_DTABLEEND;
4052 if (start)
4053 ctl0 |= BWN_DMA64_DCTL0_FRAMESTART;
4054 if (end)
4055 ctl0 |= BWN_DMA64_DCTL0_FRAMEEND;
4056 if (irq)
4057 ctl0 |= BWN_DMA64_DCTL0_IRQ;
4058 ctl1 |= bufsize & BWN_DMA64_DCTL1_BYTECNT;
4059 ctl1 |= (addrext << BWN_DMA64_DCTL1_ADDREXT_SHIFT)
4060 & BWN_DMA64_DCTL1_ADDREXT_MASK;
4061
4062 desc->dma.dma64.control0 = htole32(ctl0);
4063 desc->dma.dma64.control1 = htole32(ctl1);
4064 desc->dma.dma64.address_low = htole32(addrlo);
4065 desc->dma.dma64.address_high = htole32(addrhi);
4066}
4067
4068static void
4069bwn_dma_64_start_transfer(struct bwn_dma_ring *dr, int slot)
4070{
4071
4072 BWN_DMA_WRITE(dr, BWN_DMA64_TXINDEX,
4073 (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4074}
4075
4076static void
4077bwn_dma_64_suspend(struct bwn_dma_ring *dr)
4078{
4079
4080 BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
4081 BWN_DMA_READ(dr, BWN_DMA64_TXCTL) | BWN_DMA64_TXSUSPEND);
4082}
4083
4084static void
4085bwn_dma_64_resume(struct bwn_dma_ring *dr)
4086{
4087
4088 BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
4089 BWN_DMA_READ(dr, BWN_DMA64_TXCTL) & ~BWN_DMA64_TXSUSPEND);
4090}
4091
4092static int
4093bwn_dma_64_get_curslot(struct bwn_dma_ring *dr)
4094{
4095 uint32_t val;
4096
4097 val = BWN_DMA_READ(dr, BWN_DMA64_RXSTATUS);
4098 val &= BWN_DMA64_RXSTATDPTR;
4099
4100 return (val / sizeof(struct bwn_dmadesc64));
4101}
4102
4103static void
4104bwn_dma_64_set_curslot(struct bwn_dma_ring *dr, int slot)
4105{
4106
4107 BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX,
4108 (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4109}
4110
4111static int
4112bwn_dma_allocringmemory(struct bwn_dma_ring *dr)
4113{
4114 struct bwn_mac *mac = dr->dr_mac;
4115 struct bwn_dma *dma = &mac->mac_method.dma;
4116 struct bwn_softc *sc = mac->mac_sc;
4117 int error;
4118
4119 error = bus_dma_tag_create(dma->parent_dtag,
4120 BWN_ALIGN, 0,
4121 BUS_SPACE_MAXADDR,
4122 BUS_SPACE_MAXADDR,
4123 NULL, NULL,
4124 BWN_DMA_RINGMEMSIZE,
4125 1,
4126 BUS_SPACE_MAXSIZE_32BIT,
4127 0,
4128 NULL, NULL,
4129 &dr->dr_ring_dtag);
4130 if (error) {
4131 device_printf(sc->sc_dev,
4132 "can't create TX ring DMA tag: TODO frees\n");
4133 return (-1);
4134 }
4135
4136 error = bus_dmamem_alloc(dr->dr_ring_dtag,
4137 &dr->dr_ring_descbase, BUS_DMA_WAITOK | BUS_DMA_ZERO,
4138 &dr->dr_ring_dmap);
4139 if (error) {
4140 device_printf(sc->sc_dev,
4141 "can't allocate DMA mem: TODO frees\n");
4142 return (-1);
4143 }
4144 error = bus_dmamap_load(dr->dr_ring_dtag, dr->dr_ring_dmap,
4145 dr->dr_ring_descbase, BWN_DMA_RINGMEMSIZE,
4146 bwn_dma_ring_addr, &dr->dr_ring_dmabase, BUS_DMA_NOWAIT);
4147 if (error) {
4148 device_printf(sc->sc_dev,
4149 "can't load DMA mem: TODO free\n");
4150 return (-1);
4151 }
4152
4153 return (0);
4154}
4155
4156static void
4157bwn_dma_setup(struct bwn_dma_ring *dr)
4158{
4159 struct bwn_softc *sc = dr->dr_mac->mac_sc;
4160 uint64_t ring64;
4161 uint32_t addrext, ring32, value;
4162 uint32_t trans = siba_dma_translation(sc->sc_dev);
4163
4164 if (dr->dr_tx) {
4165 dr->dr_curslot = -1;
4166
4167 if (dr->dr_type == BWN_DMA_64BIT) {
4168 ring64 = (uint64_t)(dr->dr_ring_dmabase);
4169 addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK)
4170 >> 30;
4171 value = BWN_DMA64_TXENABLE;
4172 value |= (addrext << BWN_DMA64_TXADDREXT_SHIFT)
4173 & BWN_DMA64_TXADDREXT_MASK;
4174 BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL, value);
4175 BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO,
4176 (ring64 & 0xffffffff));
4177 BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI,
4178 ((ring64 >> 32) &
4179 ~SIBA_DMA_TRANSLATION_MASK) | (trans << 1));
4180 } else {
4181 ring32 = (uint32_t)(dr->dr_ring_dmabase);
4182 addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4183 value = BWN_DMA32_TXENABLE;
4184 value |= (addrext << BWN_DMA32_TXADDREXT_SHIFT)
4185 & BWN_DMA32_TXADDREXT_MASK;
4186 BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL, value);
4187 BWN_DMA_WRITE(dr, BWN_DMA32_TXRING,
4188 (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4189 }
4190 return;
4191 }
4192
4193 /*
4194 * set for RX
4195 */
4196 dr->dr_usedslot = dr->dr_numslots;
4197
4198 if (dr->dr_type == BWN_DMA_64BIT) {
4199 ring64 = (uint64_t)(dr->dr_ring_dmabase);
4200 addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK) >> 30;
4201 value = (dr->dr_frameoffset << BWN_DMA64_RXFROFF_SHIFT);
4202 value |= BWN_DMA64_RXENABLE;
4203 value |= (addrext << BWN_DMA64_RXADDREXT_SHIFT)
4204 & BWN_DMA64_RXADDREXT_MASK;
4205 BWN_DMA_WRITE(dr, BWN_DMA64_RXCTL, value);
4206 BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, (ring64 & 0xffffffff));
4207 BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI,
4208 ((ring64 >> 32) & ~SIBA_DMA_TRANSLATION_MASK)
4209 | (trans << 1));
4210 BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX, dr->dr_numslots *
4211 sizeof(struct bwn_dmadesc64));
4212 } else {
4213 ring32 = (uint32_t)(dr->dr_ring_dmabase);
4214 addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4215 value = (dr->dr_frameoffset << BWN_DMA32_RXFROFF_SHIFT);
4216 value |= BWN_DMA32_RXENABLE;
4217 value |= (addrext << BWN_DMA32_RXADDREXT_SHIFT)
4218 & BWN_DMA32_RXADDREXT_MASK;
4219 BWN_DMA_WRITE(dr, BWN_DMA32_RXCTL, value);
4220 BWN_DMA_WRITE(dr, BWN_DMA32_RXRING,
4221 (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4222 BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX, dr->dr_numslots *
4223 sizeof(struct bwn_dmadesc32));
4224 }
4225}
4226
4227static void
4228bwn_dma_free_ringmemory(struct bwn_dma_ring *dr)
4229{
4230
4231 bus_dmamap_unload(dr->dr_ring_dtag, dr->dr_ring_dmap);
4232 bus_dmamem_free(dr->dr_ring_dtag, dr->dr_ring_descbase,
4233 dr->dr_ring_dmap);
4234}
4235
4236static void
4237bwn_dma_cleanup(struct bwn_dma_ring *dr)
4238{
4239
4240 if (dr->dr_tx) {
4241 bwn_dma_tx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4242 if (dr->dr_type == BWN_DMA_64BIT) {
4243 BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO, 0);
4244 BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI, 0);
4245 } else
4246 BWN_DMA_WRITE(dr, BWN_DMA32_TXRING, 0);
4247 } else {
4248 bwn_dma_rx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4249 if (dr->dr_type == BWN_DMA_64BIT) {
4250 BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, 0);
4251 BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI, 0);
4252 } else
4253 BWN_DMA_WRITE(dr, BWN_DMA32_RXRING, 0);
4254 }
4255}
4256
4257static void
4258bwn_dma_free_descbufs(struct bwn_dma_ring *dr)
4259{
4260 struct bwn_dmadesc_generic *desc;
4261 struct bwn_dmadesc_meta *meta;
4262 struct bwn_mac *mac = dr->dr_mac;
4263 struct bwn_dma *dma = &mac->mac_method.dma;
4264 struct bwn_softc *sc = mac->mac_sc;
4265 int i;
4266
4267 if (!dr->dr_usedslot)
4268 return;
4269 for (i = 0; i < dr->dr_numslots; i++) {
4270 dr->getdesc(dr, i, &desc, &meta);
4271
4272 if (meta->mt_m == NULL) {
4273 if (!dr->dr_tx)
4274 device_printf(sc->sc_dev, "%s: not TX?\n",
4275 __func__);
4276 continue;
4277 }
4278 if (dr->dr_tx) {
4279 if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
4280 bus_dmamap_unload(dr->dr_txring_dtag,
4281 meta->mt_dmap);
4282 else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
4283 bus_dmamap_unload(dma->txbuf_dtag,
4284 meta->mt_dmap);
4285 } else
4286 bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
4287 bwn_dma_free_descbuf(dr, meta);
4288 }
4289}
4290
4291static int
4292bwn_dma_tx_reset(struct bwn_mac *mac, uint16_t base,
4293 int type)
4294{
4295 struct bwn_softc *sc = mac->mac_sc;
4296 uint32_t value;
4297 int i;
4298 uint16_t offset;
4299
4300 for (i = 0; i < 10; i++) {
4301 offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4302 BWN_DMA32_TXSTATUS;
4303 value = BWN_READ_4(mac, base + offset);
4304 if (type == BWN_DMA_64BIT) {
4305 value &= BWN_DMA64_TXSTAT;
4306 if (value == BWN_DMA64_TXSTAT_DISABLED ||
4307 value == BWN_DMA64_TXSTAT_IDLEWAIT ||
4308 value == BWN_DMA64_TXSTAT_STOPPED)
4309 break;
4310 } else {
4311 value &= BWN_DMA32_TXSTATE;
4312 if (value == BWN_DMA32_TXSTAT_DISABLED ||
4313 value == BWN_DMA32_TXSTAT_IDLEWAIT ||
4314 value == BWN_DMA32_TXSTAT_STOPPED)
4315 break;
4316 }
4317 DELAY(1000);
4318 }
4319 offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXCTL : BWN_DMA32_TXCTL;
4320 BWN_WRITE_4(mac, base + offset, 0);
4321 for (i = 0; i < 10; i++) {
4322 offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4323 BWN_DMA32_TXSTATUS;
4324 value = BWN_READ_4(mac, base + offset);
4325 if (type == BWN_DMA_64BIT) {
4326 value &= BWN_DMA64_TXSTAT;
4327 if (value == BWN_DMA64_TXSTAT_DISABLED) {
4328 i = -1;
4329 break;
4330 }
4331 } else {
4332 value &= BWN_DMA32_TXSTATE;
4333 if (value == BWN_DMA32_TXSTAT_DISABLED) {
4334 i = -1;
4335 break;
4336 }
4337 }
4338 DELAY(1000);
4339 }
4340 if (i != -1) {
4341 device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4342 return (ENODEV);
4343 }
4344 DELAY(1000);
4345
4346 return (0);
4347}
4348
4349static int
4350bwn_dma_rx_reset(struct bwn_mac *mac, uint16_t base,
4351 int type)
4352{
4353 struct bwn_softc *sc = mac->mac_sc;
4354 uint32_t value;
4355 int i;
4356 uint16_t offset;
4357
4358 offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXCTL : BWN_DMA32_RXCTL;
4359 BWN_WRITE_4(mac, base + offset, 0);
4360 for (i = 0; i < 10; i++) {
4361 offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXSTATUS :
4362 BWN_DMA32_RXSTATUS;
4363 value = BWN_READ_4(mac, base + offset);
4364 if (type == BWN_DMA_64BIT) {
4365 value &= BWN_DMA64_RXSTAT;
4366 if (value == BWN_DMA64_RXSTAT_DISABLED) {
4367 i = -1;
4368 break;
4369 }
4370 } else {
4371 value &= BWN_DMA32_RXSTATE;
4372 if (value == BWN_DMA32_RXSTAT_DISABLED) {
4373 i = -1;
4374 break;
4375 }
4376 }
4377 DELAY(1000);
4378 }
4379 if (i != -1) {
4380 device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4381 return (ENODEV);
4382 }
4383
4384 return (0);
4385}
4386
4387static void
4388bwn_dma_free_descbuf(struct bwn_dma_ring *dr,
4389 struct bwn_dmadesc_meta *meta)
4390{
4391
4392 if (meta->mt_m != NULL) {
4393 m_freem(meta->mt_m);
4394 meta->mt_m = NULL;
4395 }
4396 if (meta->mt_ni != NULL) {
4397 ieee80211_free_node(meta->mt_ni);
4398 meta->mt_ni = NULL;
4399 }
4400}
4401
4402static void
4403bwn_dma_set_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4404{
4405 struct bwn_rxhdr4 *rxhdr;
4406 unsigned char *frame;
4407
4408 rxhdr = mtod(m, struct bwn_rxhdr4 *);
4409 rxhdr->frame_len = 0;
4410
4411 KASSERT(dr->dr_rx_bufsize >= dr->dr_frameoffset +
4412 sizeof(struct bwn_plcp6) + 2,
4413 ("%s:%d: fail", __func__, __LINE__));
4414 frame = mtod(m, char *) + dr->dr_frameoffset;
4415 memset(frame, 0xff, sizeof(struct bwn_plcp6) + 2 /* padding */);
4416}
4417
4418static uint8_t
4419bwn_dma_check_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4420{
4421 unsigned char *f = mtod(m, char *) + dr->dr_frameoffset;
4422
4423 return ((f[0] & f[1] & f[2] & f[3] & f[4] & f[5] & f[6] & f[7])
4424 == 0xff);
4425}
4426
4427static void
4428bwn_wme_init(struct bwn_mac *mac)
4429{
4430
4431 bwn_wme_load(mac);
4432
4433 /* enable WME support. */
4434 bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_EDCF);
4435 BWN_WRITE_2(mac, BWN_IFSCTL, BWN_READ_2(mac, BWN_IFSCTL) |
4436 BWN_IFSCTL_USE_EDCF);
4437}
4438
4439static void
4440bwn_spu_setdelay(struct bwn_mac *mac, int idle)
4441{
4442 struct bwn_softc *sc = mac->mac_sc;
4443 struct ieee80211com *ic = sc->sc_ifp->if_l2com;
4444 uint16_t delay; /* microsec */
4445
4446 delay = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 3700 : 1050;
4447 if (ic->ic_opmode == IEEE80211_M_IBSS || idle)
4448 delay = 500;
4449 if ((mac->mac_phy.rf_ver == 0x2050) && (mac->mac_phy.rf_rev == 8))
4450 delay = max(delay, (uint16_t)2400);
4451
4452 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SPU_WAKEUP, delay);
4453}
4454
4455static void
4456bwn_bt_enable(struct bwn_mac *mac)
4457{
4458 struct bwn_softc *sc = mac->mac_sc;
4459 uint64_t hf;
4460
4461 if (bwn_bluetooth == 0)
4462 return;
4463 if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCOEXIST) == 0)
4464 return;
4465 if (mac->mac_phy.type != BWN_PHYTYPE_B && !mac->mac_phy.gmode)
4466 return;
4467
4468 hf = bwn_hf_read(mac);
4469 if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCMOD)
4470 hf |= BWN_HF_BT_COEXISTALT;
4471 else
4472 hf |= BWN_HF_BT_COEXIST;
4473 bwn_hf_write(mac, hf);
4474}
4475
4476static void
4477bwn_set_macaddr(struct bwn_mac *mac)
4478{
4479
4480 bwn_mac_write_bssid(mac);
4481 bwn_mac_setfilter(mac, BWN_MACFILTER_SELF, mac->mac_sc->sc_macaddr);
4482}
4483
4484static void
4485bwn_clear_keys(struct bwn_mac *mac)
4486{
4487 int i;
4488
4489 for (i = 0; i < mac->mac_max_nr_keys; i++) {
4490 KASSERT(i >= 0 && i < mac->mac_max_nr_keys,
4491 ("%s:%d: fail", __func__, __LINE__));
4492
4493 bwn_key_dowrite(mac, i, BWN_SEC_ALGO_NONE,
4494 NULL, BWN_SEC_KEYSIZE, NULL);
4495 if ((i <= 3) && !BWN_SEC_NEWAPI(mac)) {
4496 bwn_key_dowrite(mac, i + 4, BWN_SEC_ALGO_NONE,
4497 NULL, BWN_SEC_KEYSIZE, NULL);
4498 }
4499 mac->mac_key[i].keyconf = NULL;
4500 }
4501}
4502
4503static void
4504bwn_crypt_init(struct bwn_mac *mac)
4505{
4506 struct bwn_softc *sc = mac->mac_sc;
4507
4508 mac->mac_max_nr_keys = (siba_get_revid(sc->sc_dev) >= 5) ? 58 : 20;
4509 KASSERT(mac->mac_max_nr_keys <= N(mac->mac_key),
4510 ("%s:%d: fail", __func__, __LINE__));
4511 mac->mac_ktp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_KEY_TABLEP);
4512 mac->mac_ktp *= 2;
4513 if (siba_get_revid(sc->sc_dev) >= 5)
4514 BWN_WRITE_2(mac, BWN_RCMTA_COUNT, mac->mac_max_nr_keys - 8);
4515 bwn_clear_keys(mac);
4516}
4517
4518static void
4519bwn_chip_exit(struct bwn_mac *mac)
4520{
4521 struct bwn_softc *sc = mac->mac_sc;
4522
4523 bwn_phy_exit(mac);
4524 siba_gpio_set(sc->sc_dev, 0);
4525}
4526
4527static int
4528bwn_fw_fillinfo(struct bwn_mac *mac)
4529{
4530 int error;
4531
4532 error = bwn_fw_gets(mac, BWN_FWTYPE_DEFAULT);
4533 if (error == 0)
4534 return (0);
4535 error = bwn_fw_gets(mac, BWN_FWTYPE_OPENSOURCE);
4536 if (error == 0)
4537 return (0);
4538 return (error);
4539}
4540
4541static int
4542bwn_gpio_init(struct bwn_mac *mac)
4543{
4544 struct bwn_softc *sc = mac->mac_sc;
4545 uint32_t mask = 0x1f, set = 0xf, value;
4546
4547 BWN_WRITE_4(mac, BWN_MACCTL,
4548 BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GPOUT_MASK);
4549 BWN_WRITE_2(mac, BWN_GPIO_MASK,
4550 BWN_READ_2(mac, BWN_GPIO_MASK) | 0x000f);
4551
4552 if (siba_get_chipid(sc->sc_dev) == 0x4301) {
4553 mask |= 0x0060;
4554 set |= 0x0060;
4555 }
4556 if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL) {
4557 BWN_WRITE_2(mac, BWN_GPIO_MASK,
4558 BWN_READ_2(mac, BWN_GPIO_MASK) | 0x0200);
4559 mask |= 0x0200;
4560 set |= 0x0200;
4561 }
4562 if (siba_get_revid(sc->sc_dev) >= 2)
4563 mask |= 0x0010;
4564
4565 value = siba_gpio_get(sc->sc_dev);
4566 if (value == -1)
4567 return (0);
4568 siba_gpio_set(sc->sc_dev, (value & mask) | set);
4569
4570 return (0);
4571}
4572
4573static int
4574bwn_fw_loadinitvals(struct bwn_mac *mac)
4575{
4576#define GETFWOFFSET(fwp, offset) \
4577 ((const struct bwn_fwinitvals *)((const char *)fwp.fw->data + offset))
4578 const size_t hdr_len = sizeof(struct bwn_fwhdr);
4579 const struct bwn_fwhdr *hdr;
4580 struct bwn_fw *fw = &mac->mac_fw;
4581 int error;
4582
4583 hdr = (const struct bwn_fwhdr *)(fw->initvals.fw->data);
4584 error = bwn_fwinitvals_write(mac, GETFWOFFSET(fw->initvals, hdr_len),
4585 be32toh(hdr->size), fw->initvals.fw->datasize - hdr_len);
4586 if (error)
4587 return (error);
4588 if (fw->initvals_band.fw) {
4589 hdr = (const struct bwn_fwhdr *)(fw->initvals_band.fw->data);
4590 error = bwn_fwinitvals_write(mac,
4591 GETFWOFFSET(fw->initvals_band, hdr_len),
4592 be32toh(hdr->size),
4593 fw->initvals_band.fw->datasize - hdr_len);
4594 }
4595 return (error);
4596#undef GETFWOFFSET
4597}
4598
4599static int
4600bwn_phy_init(struct bwn_mac *mac)
4601{
4602 struct bwn_softc *sc = mac->mac_sc;
4603 int error;
4604
4605 mac->mac_phy.chan = mac->mac_phy.get_default_chan(mac);
4606 mac->mac_phy.rf_onoff(mac, 1);
4607 error = mac->mac_phy.init(mac);
4608 if (error) {
4609 device_printf(sc->sc_dev, "PHY init failed\n");
4610 goto fail0;
4611 }
4612 error = bwn_switch_channel(mac,
4613 mac->mac_phy.get_default_chan(mac));
4614 if (error) {
4615 device_printf(sc->sc_dev,
4616 "failed to switch default channel\n");
4617 goto fail1;
4618 }
4619 return (0);
4620fail1:
4621 if (mac->mac_phy.exit)
4622 mac->mac_phy.exit(mac);
4623fail0:
4624 mac->mac_phy.rf_onoff(mac, 0);
4625
4626 return (error);
4627}
4628
4629static void
4630bwn_set_txantenna(struct bwn_mac *mac, int antenna)
4631{
4632 uint16_t ant;
4633 uint16_t tmp;
4634
4635 ant = bwn_ant2phy(antenna);
4636
4637 /* For ACK/CTS */
4638 tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL);
4639 tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4640 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, tmp);
4641 /* For Probe Resposes */
4642 tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL);
4643 tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4644 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, tmp);
4645}
4646
4647static void
4648bwn_set_opmode(struct bwn_mac *mac)
4649{
4650 struct bwn_softc *sc = mac->mac_sc;
4651 struct ifnet *ifp = sc->sc_ifp;
4652 struct ieee80211com *ic = ifp->if_l2com;
4653 uint32_t ctl;
4654 uint16_t cfp_pretbtt;
4655
4656 ctl = BWN_READ_4(mac, BWN_MACCTL);
4657 ctl &= ~(BWN_MACCTL_HOSTAP | BWN_MACCTL_PASS_CTL |
4658 BWN_MACCTL_PASS_BADPLCP | BWN_MACCTL_PASS_BADFCS |
4659 BWN_MACCTL_PROMISC | BWN_MACCTL_BEACON_PROMISC);
4660 ctl |= BWN_MACCTL_STA;
4661
4662 if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
4663 ic->ic_opmode == IEEE80211_M_MBSS)
4664 ctl |= BWN_MACCTL_HOSTAP;
4665 else if (ic->ic_opmode == IEEE80211_M_IBSS)
4666 ctl &= ~BWN_MACCTL_STA;
4667 ctl |= sc->sc_filters;
4668
4669 if (siba_get_revid(sc->sc_dev) <= 4)
4670 ctl |= BWN_MACCTL_PROMISC;
4671
4672 BWN_WRITE_4(mac, BWN_MACCTL, ctl);
4673
4674 cfp_pretbtt = 2;
4675 if ((ctl & BWN_MACCTL_STA) && !(ctl & BWN_MACCTL_HOSTAP)) {
4676 if (siba_get_chipid(sc->sc_dev) == 0x4306 &&
4677 siba_get_chiprev(sc->sc_dev) == 3)
4678 cfp_pretbtt = 100;
4679 else
4680 cfp_pretbtt = 50;
4681 }
4682 BWN_WRITE_2(mac, 0x612, cfp_pretbtt);
4683}
4684
4685static int
4686bwn_dma_gettype(struct bwn_mac *mac)
4687{
4688 uint32_t tmp;
4689 uint16_t base;
4690
4691 tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
4692 if (tmp & SIBA_TGSHIGH_DMA64)
4693 return (BWN_DMA_64BIT);
4694 base = bwn_dma_base(0, 0);
4695 BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
4696 tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
4697 if (tmp & BWN_DMA32_TXADDREXT_MASK)
4698 return (BWN_DMA_32BIT);
4699
4700 return (BWN_DMA_30BIT);
4701}
4702
4703static void
4704bwn_dma_ring_addr(void *arg, bus_dma_segment_t *seg, int nseg, int error)
4705{
4706 if (!error) {
4707 KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
4708 *((bus_addr_t *)arg) = seg->ds_addr;
4709 }
4710}
4711
4712static void
4713bwn_phy_g_init_sub(struct bwn_mac *mac)
4714{
4715 struct bwn_phy *phy = &mac->mac_phy;
4716 struct bwn_phy_g *pg = &phy->phy_g;
4717 struct bwn_softc *sc = mac->mac_sc;
4718 uint16_t i, tmp;
4719
4720 if (phy->rev == 1)
4721 bwn_phy_init_b5(mac);
4722 else
4723 bwn_phy_init_b6(mac);
4724
4725 if (phy->rev >= 2 || phy->gmode)
4726 bwn_phy_init_a(mac);
4727
4728 if (phy->rev >= 2) {
4729 BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, 0);
4730 BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, 0);
4731 }
4732 if (phy->rev == 2) {
4733 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
4734 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4735 }
4736 if (phy->rev > 5) {
4737 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x400);
4738 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4739 }
4740 if (phy->gmode || phy->rev >= 2) {
4741 tmp = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
4742 tmp &= BWN_PHYVER_VERSION;
4743 if (tmp == 3 || tmp == 5) {
4744 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc2), 0x1816);
4745 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc3), 0x8006);
4746 }
4747 if (tmp == 5) {
4748 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xcc), 0x00ff,
4749 0x1f00);
4750 }
4751 }
4752 if ((phy->rev <= 2 && phy->gmode) || phy->rev >= 2)
4753 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x7e), 0x78);
4754 if (phy->rf_rev == 8) {
4755 BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x80);
4756 BWN_PHY_SET(mac, BWN_PHY_OFDM(0x3e), 0x4);
4757 }
4758 if (BWN_HAS_LOOPBACK(phy))
4759 bwn_loopback_calcgain(mac);
4760
4761 if (phy->rf_rev != 8) {
4762 if (pg->pg_initval == 0xffff)
4763 pg->pg_initval = bwn_rf_init_bcm2050(mac);
4764 else
4765 BWN_RF_WRITE(mac, 0x0078, pg->pg_initval);
4766 }
4767 bwn_lo_g_init(mac);
4768 if (BWN_HAS_TXMAG(phy)) {
4769 BWN_RF_WRITE(mac, 0x52,
4770 (BWN_RF_READ(mac, 0x52) & 0xff00)
4771 | pg->pg_loctl.tx_bias |
4772 pg->pg_loctl.tx_magn);
4773 } else {
4774 BWN_RF_SETMASK(mac, 0x52, 0xfff0, pg->pg_loctl.tx_bias);
4775 }
4776 if (phy->rev >= 6) {
4777 BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x36), 0x0fff,
4778 (pg->pg_loctl.tx_bias << 12));
4779 }
4780 if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
4781 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8075);
4782 else
4783 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x807f);
4784 if (phy->rev < 2)
4785 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x101);
4786 else
4787 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x202);
4788 if (phy->gmode || phy->rev >= 2) {
4789 bwn_lo_g_adjust(mac);
4790 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
4791 }
4792
4793 if (!(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI)) {
4794 for (i = 0; i < 64; i++) {
4795 BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, i);
4796 BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_DATA,
4797 (uint16_t)MIN(MAX(bwn_nrssi_read(mac, i) - 0xffff,
4798 -32), 31));
4799 }
4800 bwn_nrssi_threshold(mac);
4801 } else if (phy->gmode || phy->rev >= 2) {
4802 if (pg->pg_nrssi[0] == -1000) {
4803 KASSERT(pg->pg_nrssi[1] == -1000,
4804 ("%s:%d: fail", __func__, __LINE__));
4805 bwn_nrssi_slope_11g(mac);
4806 } else
4807 bwn_nrssi_threshold(mac);
4808 }
4809 if (phy->rf_rev == 8)
4810 BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x05), 0x3230);
4811 bwn_phy_hwpctl_init(mac);
4812 if ((siba_get_chipid(sc->sc_dev) == 0x4306
4813 && siba_get_chippkg(sc->sc_dev) == 2) || 0) {
4814 BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0xbfff);
4815 BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xc3), 0x7fff);
4816 }
4817}
4818
4819static uint8_t
4820bwn_has_hwpctl(struct bwn_mac *mac)
4821{
4822
4823 if (mac->mac_phy.hwpctl == 0 || mac->mac_phy.use_hwpctl == NULL)
4824 return (0);
4825 return (mac->mac_phy.use_hwpctl(mac));
4826}
4827
4828static void
4829bwn_phy_init_b5(struct bwn_mac *mac)
4830{
4831 struct bwn_phy *phy = &mac->mac_phy;
4832 struct bwn_phy_g *pg = &phy->phy_g;
4833 struct bwn_softc *sc = mac->mac_sc;
4834 uint16_t offset, value;
4835 uint8_t old_channel;
4836
4837 if (phy->analog == 1)
4838 BWN_RF_SET(mac, 0x007a, 0x0050);
4839 if ((siba_get_pci_subvendor(sc->sc_dev) != SIBA_BOARDVENDOR_BCM) &&
4840 (siba_get_pci_subdevice(sc->sc_dev) != SIBA_BOARD_BU4306)) {
4841 value = 0x2120;
4842 for (offset = 0x00a8; offset < 0x00c7; offset++) {
4843 BWN_PHY_WRITE(mac, offset, value);
4844 value += 0x202;
4845 }
4846 }
4847 BWN_PHY_SETMASK(mac, 0x0035, 0xf0ff, 0x0700);
4848 if (phy->rf_ver == 0x2050)
4849 BWN_PHY_WRITE(mac, 0x0038, 0x0667);
4850
4851 if (phy->gmode || phy->rev >= 2) {
4852 if (phy->rf_ver == 0x2050) {
4853 BWN_RF_SET(mac, 0x007a, 0x0020);
4854 BWN_RF_SET(mac, 0x0051, 0x0004);
4855 }
4856 BWN_WRITE_2(mac, BWN_PHY_RADIO, 0x0000);
4857
4858 BWN_PHY_SET(mac, 0x0802, 0x0100);
4859 BWN_PHY_SET(mac, 0x042b, 0x2000);
4860
4861 BWN_PHY_WRITE(mac, 0x001c, 0x186a);
4862
4863 BWN_PHY_SETMASK(mac, 0x0013, 0x00ff, 0x1900);
4864 BWN_PHY_SETMASK(mac, 0x0035, 0xffc0, 0x0064);
4865 BWN_PHY_SETMASK(mac, 0x005d, 0xff80, 0x000a);
4866 }
4867
4868 if (mac->mac_flags & BWN_MAC_FLAG_BADFRAME_PREEMP)
4869 BWN_PHY_SET(mac, BWN_PHY_RADIO_BITFIELD, (1 << 11));
4870
4871 if (phy->analog == 1) {
4872 BWN_PHY_WRITE(mac, 0x0026, 0xce00);
4873 BWN_PHY_WRITE(mac, 0x0021, 0x3763);
4874 BWN_PHY_WRITE(mac, 0x0022, 0x1bc3);
4875 BWN_PHY_WRITE(mac, 0x0023, 0x06f9);
4876 BWN_PHY_WRITE(mac, 0x0024, 0x037e);
4877 } else
4878 BWN_PHY_WRITE(mac, 0x0026, 0xcc00);
4879 BWN_PHY_WRITE(mac, 0x0030, 0x00c6);
4880 BWN_WRITE_2(mac, 0x03ec, 0x3f22);
4881
4882 if (phy->analog == 1)
4883 BWN_PHY_WRITE(mac, 0x0020, 0x3e1c);
4884 else
4885 BWN_PHY_WRITE(mac, 0x0020, 0x301c);
4886
4887 if (phy->analog == 0)
4888 BWN_WRITE_2(mac, 0x03e4, 0x3000);
4889
4890 old_channel = phy->chan;
4891 bwn_phy_g_switch_chan(mac, 7, 0);
4892
4893 if (phy->rf_ver != 0x2050) {
4894 BWN_RF_WRITE(mac, 0x0075, 0x0080);
4895 BWN_RF_WRITE(mac, 0x0079, 0x0081);
4896 }
4897
4898 BWN_RF_WRITE(mac, 0x0050, 0x0020);
4899 BWN_RF_WRITE(mac, 0x0050, 0x0023);
4900
4901 if (phy->rf_ver == 0x2050) {
4902 BWN_RF_WRITE(mac, 0x0050, 0x0020);
4903 BWN_RF_WRITE(mac, 0x005a, 0x0070);
4904 }
4905
4906 BWN_RF_WRITE(mac, 0x005b, 0x007b);
4907 BWN_RF_WRITE(mac, 0x005c, 0x00b0);
4908 BWN_RF_SET(mac, 0x007a, 0x0007);
4909
4910 bwn_phy_g_switch_chan(mac, old_channel, 0);
4911 BWN_PHY_WRITE(mac, 0x0014, 0x0080);
4912 BWN_PHY_WRITE(mac, 0x0032, 0x00ca);
4913 BWN_PHY_WRITE(mac, 0x002a, 0x88a3);
4914
4915 bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
4916 pg->pg_txctl);
4917
4918 if (phy->rf_ver == 0x2050)
4919 BWN_RF_WRITE(mac, 0x005d, 0x000d);
4920
4921 BWN_WRITE_2(mac, 0x03e4, (BWN_READ_2(mac, 0x03e4) & 0xffc0) | 0x0004);
4922}
4923
4924static void
4925bwn_loopback_calcgain(struct bwn_mac *mac)
4926{
4927 struct bwn_phy *phy = &mac->mac_phy;
4928 struct bwn_phy_g *pg = &phy->phy_g;
4929 struct bwn_softc *sc = mac->mac_sc;
4930 uint16_t backup_phy[16] = { 0 };
4931 uint16_t backup_radio[3];
4932 uint16_t backup_bband;
4933 uint16_t i, j, loop_i_max;
4934 uint16_t trsw_rx;
4935 uint16_t loop1_outer_done, loop1_inner_done;
4936
4937 backup_phy[0] = BWN_PHY_READ(mac, BWN_PHY_CRS0);
4938 backup_phy[1] = BWN_PHY_READ(mac, BWN_PHY_CCKBBANDCFG);
4939 backup_phy[2] = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
4940 backup_phy[3] = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
4941 if (phy->rev != 1) {
4942 backup_phy[4] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
4943 backup_phy[5] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
4944 }
4945 backup_phy[6] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
4946 backup_phy[7] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
4947 backup_phy[8] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
4948 backup_phy[9] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x0a));
4949 backup_phy[10] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x03));
4950 backup_phy[11] = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
4951 backup_phy[12] = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
4952 backup_phy[13] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2b));
4953 backup_phy[14] = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
4954 backup_phy[15] = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
4955 backup_bband = pg->pg_bbatt.att;
4956 backup_radio[0] = BWN_RF_READ(mac, 0x52);
4957 backup_radio[1] = BWN_RF_READ(mac, 0x43);
4958 backup_radio[2] = BWN_RF_READ(mac, 0x7a);
4959
4960 BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x3fff);
4961 BWN_PHY_SET(mac, BWN_PHY_CCKBBANDCFG, 0x8000);
4962 BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0002);
4963 BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffd);
4964 BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0001);
4965 BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffe);
4966 if (phy->rev != 1) {
4967 BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0001);
4968 BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffe);
4969 BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0002);
4970 BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffd);
4971 }
4972 BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x000c);
4973 BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x000c);
4974 BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0030);
4975 BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xffcf, 0x10);
4976
4977 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0780);
4978 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
4979 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
4980
4981 BWN_PHY_SET(mac, BWN_PHY_CCK(0x0a), 0x2000);
4982 if (phy->rev != 1) {
4983 BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0004);
4984 BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffb);
4985 }
4986 BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xff9f, 0x40);
4987
4988 if (phy->rf_rev == 8)
4989 BWN_RF_WRITE(mac, 0x43, 0x000f);
4990 else {
4991 BWN_RF_WRITE(mac, 0x52, 0);
4992 BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x9);
4993 }
4994 bwn_phy_g_set_bbatt(mac, 11);
4995
4996 if (phy->rev >= 3)
4997 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
4998 else
4999 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
5000 BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
5001
5002 BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xffc0, 0x01);
5003 BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xc0ff, 0x800);
5004
5005 BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0100);
5006 BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xcfff);
5007
5008 if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA) {
5009 if (phy->rev >= 7) {
5010 BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0800);
5011 BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x8000);
5012 }
5013 }
5014 BWN_RF_MASK(mac, 0x7a, 0x00f7);
5015
5016 j = 0;
5017 loop_i_max = (phy->rf_rev == 8) ? 15 : 9;
5018 for (i = 0; i < loop_i_max; i++) {
5019 for (j = 0; j < 16; j++) {
5020 BWN_RF_WRITE(mac, 0x43, i);
5021 BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff,
5022 (j << 8));
5023 BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
5024 BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
5025 DELAY(20);
5026 if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
5027 goto done0;
5028 }
5029 }
5030done0:
5031 loop1_outer_done = i;
5032 loop1_inner_done = j;
5033 if (j >= 8) {
5034 BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x30);
5035 trsw_rx = 0x1b;
5036 for (j = j - 8; j < 16; j++) {
5037 BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff, j << 8);
5038 BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
5039 BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
5040 DELAY(20);
5041 trsw_rx -= 3;
5042 if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
5043 goto done1;
5044 }
5045 } else
5046 trsw_rx = 0x18;
5047done1:
5048
5049 if (phy->rev != 1) {
5050 BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, backup_phy[4]);
5051 BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, backup_phy[5]);
5052 }
5053 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), backup_phy[6]);
5054 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), backup_phy[7]);
5055 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), backup_phy[8]);
5056 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x0a), backup_phy[9]);
5057 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x03), backup_phy[10]);
5058 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, backup_phy[11]);
5059 BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, backup_phy[12]);
5060 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), backup_phy[13]);
5061 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, backup_phy[14]);
5062
5063 bwn_phy_g_set_bbatt(mac, backup_bband);
5064
5065 BWN_RF_WRITE(mac, 0x52, backup_radio[0]);
5066 BWN_RF_WRITE(mac, 0x43, backup_radio[1]);
5067 BWN_RF_WRITE(mac, 0x7a, backup_radio[2]);
5068
5069 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2] | 0x0003);
5070 DELAY(10);
5071 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2]);
5072 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, backup_phy[3]);
5073 BWN_PHY_WRITE(mac, BWN_PHY_CRS0, backup_phy[0]);
5074 BWN_PHY_WRITE(mac, BWN_PHY_CCKBBANDCFG, backup_phy[1]);
5075
5076 pg->pg_max_lb_gain =
5077 ((loop1_inner_done * 6) - (loop1_outer_done * 4)) - 11;
5078 pg->pg_trsw_rx_gain = trsw_rx * 2;
5079}
5080
5081static uint16_t
5082bwn_rf_init_bcm2050(struct bwn_mac *mac)
5083{
5084 struct bwn_phy *phy = &mac->mac_phy;
5085 uint32_t tmp1 = 0, tmp2 = 0;
5086 uint16_t rcc, i, j, pgactl, cck0, cck1, cck2, cck3, rfover, rfoverval,
5087 analogover, analogoverval, crs0, classctl, lomask, loctl, syncctl,
5088 radio0, radio1, radio2, reg0, reg1, reg2, radio78, reg, index;
5089 static const uint8_t rcc_table[] = {
5090 0x02, 0x03, 0x01, 0x0f,
5091 0x06, 0x07, 0x05, 0x0f,
5092 0x0a, 0x0b, 0x09, 0x0f,
5093 0x0e, 0x0f, 0x0d, 0x0f,
5094 };
5095
5096 loctl = lomask = reg0 = classctl = crs0 = analogoverval = analogover =
5097 rfoverval = rfover = cck3 = 0;
5098 radio0 = BWN_RF_READ(mac, 0x43);
5099 radio1 = BWN_RF_READ(mac, 0x51);
5100 radio2 = BWN_RF_READ(mac, 0x52);
5101 pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
5102 cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
5103 cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
5104 cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
5105
5106 if (phy->type == BWN_PHYTYPE_B) {
5107 cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
5108 reg0 = BWN_READ_2(mac, 0x3ec);
5109
5110 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0xff);
5111 BWN_WRITE_2(mac, 0x3ec, 0x3f3f);
5112 } else if (phy->gmode || phy->rev >= 2) {
5113 rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
5114 rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
5115 analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
5116 analogoverval = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
5117 crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
5118 classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
5119
5120 BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
5121 BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
5122 BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
5123 BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
5124 if (BWN_HAS_LOOPBACK(phy)) {
5125 lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
5126 loctl = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
5127 if (phy->rev >= 3)
5128 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
5129 else
5130 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
5131 BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
5132 }
5133
5134 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5135 bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5136 BWN_LPD(0, 1, 1)));
5137 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
5138 bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVER, 0));
5139 }
5140 BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2) | 0x8000);
5141
5142 syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
5143 BWN_PHY_MASK(mac, BWN_PHY_SYNCCTL, 0xff7f);
5144 reg1 = BWN_READ_2(mac, 0x3e6);
5145 reg2 = BWN_READ_2(mac, 0x3f4);
5146
5147 if (phy->analog == 0)
5148 BWN_WRITE_2(mac, 0x03e6, 0x0122);
5149 else {
5150 if (phy->analog >= 2)
5151 BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xffbf, 0x40);
5152 BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
5153 (BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000));
5154 }
5155
5156 reg = BWN_RF_READ(mac, 0x60);
5157 index = (reg & 0x001e) >> 1;
5158 rcc = (((rcc_table[index] << 1) | (reg & 0x0001)) | 0x0020);
5159
5160 if (phy->type == BWN_PHYTYPE_B)
5161 BWN_RF_WRITE(mac, 0x78, 0x26);
5162 if (phy->gmode || phy->rev >= 2) {
5163 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5164 bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5165 BWN_LPD(0, 1, 1)));
5166 }
5167 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfaf);
5168 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1403);
5169 if (phy->gmode || phy->rev >= 2) {
5170 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5171 bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5172 BWN_LPD(0, 0, 1)));
5173 }
5174 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfa0);
5175 BWN_RF_SET(mac, 0x51, 0x0004);
5176 if (phy->rf_rev == 8)
5177 BWN_RF_WRITE(mac, 0x43, 0x1f);
5178 else {
5179 BWN_RF_WRITE(mac, 0x52, 0);
5180 BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x0009);
5181 }
5182 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5183
5184 for (i = 0; i < 16; i++) {
5185 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0480);
5186 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5187 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5188 if (phy->gmode || phy->rev >= 2) {
5189 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5190 bwn_rf_2050_rfoverval(mac,
5191 BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5192 }
5193 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5194 DELAY(10);
5195 if (phy->gmode || phy->rev >= 2) {
5196 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5197 bwn_rf_2050_rfoverval(mac,
5198 BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5199 }
5200 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5201 DELAY(10);
5202 if (phy->gmode || phy->rev >= 2) {
5203 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5204 bwn_rf_2050_rfoverval(mac,
5205 BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5206 }
5207 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5208 DELAY(20);
5209 tmp1 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5210 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5211 if (phy->gmode || phy->rev >= 2) {
5212 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5213 bwn_rf_2050_rfoverval(mac,
5214 BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5215 }
5216 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5217 }
5218 DELAY(10);
5219
5220 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5221 tmp1++;
5222 tmp1 >>= 9;
5223
5224 for (i = 0; i < 16; i++) {
5225 radio78 = (BWN_BITREV4(i) << 1) | 0x0020;
5226 BWN_RF_WRITE(mac, 0x78, radio78);
5227 DELAY(10);
5228 for (j = 0; j < 16; j++) {
5229 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0d80);
5230 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5231 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5232 if (phy->gmode || phy->rev >= 2) {
5233 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5234 bwn_rf_2050_rfoverval(mac,
5235 BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5236 }
5237 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5238 DELAY(10);
5239 if (phy->gmode || phy->rev >= 2) {
5240 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5241 bwn_rf_2050_rfoverval(mac,
5242 BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5243 }
5244 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5245 DELAY(10);
5246 if (phy->gmode || phy->rev >= 2) {
5247 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5248 bwn_rf_2050_rfoverval(mac,
5249 BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5250 }
5251 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5252 DELAY(10);
5253 tmp2 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5254 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
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, 1)));
5259 }
5260 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5261 }
5262 tmp2++;
5263 tmp2 >>= 8;
5264 if (tmp1 < tmp2)
5265 break;
5266 }
5267
5268 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pgactl);
5269 BWN_RF_WRITE(mac, 0x51, radio1);
5270 BWN_RF_WRITE(mac, 0x52, radio2);
5271 BWN_RF_WRITE(mac, 0x43, radio0);
5272 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), cck0);
5273 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), cck1);
5274 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), cck2);
5275 BWN_WRITE_2(mac, 0x3e6, reg1);
5276 if (phy->analog != 0)
5277 BWN_WRITE_2(mac, 0x3f4, reg2);
5278 BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, syncctl);
5279 bwn_spu_workaround(mac, phy->chan);
5280 if (phy->type == BWN_PHYTYPE_B) {
5281 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), cck3);
5282 BWN_WRITE_2(mac, 0x3ec, reg0);
5283 } else if (phy->gmode) {
5284 BWN_WRITE_2(mac, BWN_PHY_RADIO,
5285 BWN_READ_2(mac, BWN_PHY_RADIO)
5286 & 0x7fff);
5287 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover);
5288 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval);
5289 BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, analogover);
5290 BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
5291 analogoverval);
5292 BWN_PHY_WRITE(mac, BWN_PHY_CRS0, crs0);
5293 BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, classctl);
5294 if (BWN_HAS_LOOPBACK(phy)) {
5295 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, lomask);
5296 BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, loctl);
5297 }
5298 }
5299
5300 return ((i > 15) ? radio78 : rcc);
5301}
5302
5303static void
5304bwn_phy_init_b6(struct bwn_mac *mac)
5305{
5306 struct bwn_phy *phy = &mac->mac_phy;
5307 struct bwn_phy_g *pg = &phy->phy_g;
5308 struct bwn_softc *sc = mac->mac_sc;
5309 uint16_t offset, val;
5310 uint8_t old_channel;
5311
5312 KASSERT(!(phy->rf_rev == 6 || phy->rf_rev == 7),
5313 ("%s:%d: fail", __func__, __LINE__));
5314
5315 BWN_PHY_WRITE(mac, 0x003e, 0x817a);
5316 BWN_RF_WRITE(mac, 0x007a, BWN_RF_READ(mac, 0x007a) | 0x0058);
5317 if (phy->rf_rev == 4 || phy->rf_rev == 5) {
5318 BWN_RF_WRITE(mac, 0x51, 0x37);
5319 BWN_RF_WRITE(mac, 0x52, 0x70);
5320 BWN_RF_WRITE(mac, 0x53, 0xb3);
5321 BWN_RF_WRITE(mac, 0x54, 0x9b);
5322 BWN_RF_WRITE(mac, 0x5a, 0x88);
5323 BWN_RF_WRITE(mac, 0x5b, 0x88);
5324 BWN_RF_WRITE(mac, 0x5d, 0x88);
5325 BWN_RF_WRITE(mac, 0x5e, 0x88);
5326 BWN_RF_WRITE(mac, 0x7d, 0x88);
5327 bwn_hf_write(mac,
5328 bwn_hf_read(mac) | BWN_HF_TSSI_RESET_PSM_WORKAROUN);
5329 }
5330 if (phy->rf_rev == 8) {
5331 BWN_RF_WRITE(mac, 0x51, 0);
5332 BWN_RF_WRITE(mac, 0x52, 0x40);
5333 BWN_RF_WRITE(mac, 0x53, 0xb7);
5334 BWN_RF_WRITE(mac, 0x54, 0x98);
5335 BWN_RF_WRITE(mac, 0x5a, 0x88);
5336 BWN_RF_WRITE(mac, 0x5b, 0x6b);
5337 BWN_RF_WRITE(mac, 0x5c, 0x0f);
5338 if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_ALTIQ) {
5339 BWN_RF_WRITE(mac, 0x5d, 0xfa);
5340 BWN_RF_WRITE(mac, 0x5e, 0xd8);
5341 } else {
5342 BWN_RF_WRITE(mac, 0x5d, 0xf5);
5343 BWN_RF_WRITE(mac, 0x5e, 0xb8);
5344 }
5345 BWN_RF_WRITE(mac, 0x0073, 0x0003);
5346 BWN_RF_WRITE(mac, 0x007d, 0x00a8);
5347 BWN_RF_WRITE(mac, 0x007c, 0x0001);
5348 BWN_RF_WRITE(mac, 0x007e, 0x0008);
5349 }
5350 for (val = 0x1e1f, offset = 0x0088; offset < 0x0098; offset++) {
5351 BWN_PHY_WRITE(mac, offset, val);
5352 val -= 0x0202;
5353 }
5354 for (val = 0x3e3f, offset = 0x0098; offset < 0x00a8; offset++) {
5355 BWN_PHY_WRITE(mac, offset, val);
5356 val -= 0x0202;
5357 }
5358 for (val = 0x2120, offset = 0x00a8; offset < 0x00c8; offset++) {
5359 BWN_PHY_WRITE(mac, offset, (val & 0x3f3f));
5360 val += 0x0202;
5361 }
5362 if (phy->type == BWN_PHYTYPE_G) {
5363 BWN_RF_SET(mac, 0x007a, 0x0020);
5364 BWN_RF_SET(mac, 0x0051, 0x0004);
5365 BWN_PHY_SET(mac, 0x0802, 0x0100);
5366 BWN_PHY_SET(mac, 0x042b, 0x2000);
5367 BWN_PHY_WRITE(mac, 0x5b, 0);
5368 BWN_PHY_WRITE(mac, 0x5c, 0);
5369 }
5370
5371 old_channel = phy->chan;
5372 bwn_phy_g_switch_chan(mac, (old_channel >= 8) ? 1 : 13, 0);
5373
5374 BWN_RF_WRITE(mac, 0x0050, 0x0020);
5375 BWN_RF_WRITE(mac, 0x0050, 0x0023);
5376 DELAY(40);
5377 if (phy->rf_rev < 6 || phy->rf_rev == 8) {
5378 BWN_RF_WRITE(mac, 0x7c, BWN_RF_READ(mac, 0x7c) | 0x0002);
5379 BWN_RF_WRITE(mac, 0x50, 0x20);
5380 }
5381 if (phy->rf_rev <= 2) {
5382 BWN_RF_WRITE(mac, 0x7c, 0x20);
5383 BWN_RF_WRITE(mac, 0x5a, 0x70);
5384 BWN_RF_WRITE(mac, 0x5b, 0x7b);
5385 BWN_RF_WRITE(mac, 0x5c, 0xb0);
5386 }
5387 BWN_RF_SETMASK(mac, 0x007a, 0x00f8, 0x0007);
5388
5389 bwn_phy_g_switch_chan(mac, old_channel, 0);
5390
5391 BWN_PHY_WRITE(mac, 0x0014, 0x0200);
5392 if (phy->rf_rev >= 6)
5393 BWN_PHY_WRITE(mac, 0x2a, 0x88c2);
5394 else
5395 BWN_PHY_WRITE(mac, 0x2a, 0x8ac0);
5396 BWN_PHY_WRITE(mac, 0x0038, 0x0668);
5397 bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
5398 pg->pg_txctl);
5399 if (phy->rf_rev <= 5)
5400 BWN_PHY_SETMASK(mac, 0x5d, 0xff80, 0x0003);
5401 if (phy->rf_rev <= 2)
5402 BWN_RF_WRITE(mac, 0x005d, 0x000d);
5403
5404 if (phy->analog == 4) {
5405 BWN_WRITE_2(mac, 0x3e4, 9);
5406 BWN_PHY_MASK(mac, 0x61, 0x0fff);
5407 } else
5408 BWN_PHY_SETMASK(mac, 0x0002, 0xffc0, 0x0004);
5409 if (phy->type == BWN_PHYTYPE_B)
5410 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5411 else if (phy->type == BWN_PHYTYPE_G)
5412 BWN_WRITE_2(mac, 0x03e6, 0x0);
5413}
5414
5415static void
5416bwn_phy_init_a(struct bwn_mac *mac)
5417{
5418 struct bwn_phy *phy = &mac->mac_phy;
5419 struct bwn_softc *sc = mac->mac_sc;
5420
5421 KASSERT(phy->type == BWN_PHYTYPE_A || phy->type == BWN_PHYTYPE_G,
5422 ("%s:%d: fail", __func__, __LINE__));
5423
5424 if (phy->rev >= 6) {
5425 if (phy->type == BWN_PHYTYPE_A)
5426 BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x1000);
5427 if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) & BWN_PHY_ENCORE_EN)
5428 BWN_PHY_SET(mac, BWN_PHY_ENCORE, 0x0010);
5429 else
5430 BWN_PHY_MASK(mac, BWN_PHY_ENCORE, ~0x1010);
5431 }
5432
5433 bwn_wa_init(mac);
5434
5435 if (phy->type == BWN_PHYTYPE_G &&
5436 (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL))
5437 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x6e), 0xe000, 0x3cf);
5438}
5439
5440static void
5441bwn_wa_write_noisescale(struct bwn_mac *mac, const uint16_t *nst)
5442{
5443 int i;
5444
5445 for (i = 0; i < BWN_TAB_NOISESCALE_SIZE; i++)
5446 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_NOISESCALE, i, nst[i]);
5447}
5448
5449static void
5450bwn_wa_agc(struct bwn_mac *mac)
5451{
5452 struct bwn_phy *phy = &mac->mac_phy;
5453
5454 if (phy->rev == 1) {
5455 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 0, 254);
5456 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 1, 13);
5457 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 2, 19);
5458 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 3, 25);
5459 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 0, 0x2710);
5460 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 1, 0x9b83);
5461 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 2, 0x9b83);
5462 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 3, 0x0f8d);
5463 BWN_PHY_WRITE(mac, BWN_PHY_LMS, 4);
5464 } else {
5465 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 0, 254);
5466 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 1, 13);
5467 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 2, 19);
5468 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 3, 25);
5469 }
5470
5471 BWN_PHY_SETMASK(mac, BWN_PHY_CCKSHIFTBITS_WA, (uint16_t)~0xff00,
5472 0x5700);
5473 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x007f, 0x000f);
5474 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x3f80, 0x2b80);
5475 BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, 0xf0ff, 0x0300);
5476 BWN_RF_SET(mac, 0x7a, 0x0008);
5477 BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x000f, 0x0008);
5478 BWN_PHY_SETMASK(mac, BWN_PHY_P1P2GAIN, ~0x0f00, 0x0600);
5479 BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x0f00, 0x0700);
5480 BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x0f00, 0x0100);
5481 if (phy->rev == 1)
5482 BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x000f, 0x0007);
5483 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x00ff, 0x001c);
5484 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x3f00, 0x0200);
5485 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), ~0x00ff, 0x001c);
5486 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x00ff, 0x0020);
5487 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x3f00, 0x0200);
5488 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x82), ~0x00ff, 0x002e);
5489 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), (uint16_t)~0xff00, 0x1a00);
5490 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), ~0x00ff, 0x0028);
5491 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), (uint16_t)~0xff00, 0x2c00);
5492 if (phy->rev == 1) {
5493 BWN_PHY_WRITE(mac, BWN_PHY_PEAK_COUNT, 0x092b);
5494 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e, 0x0002);
5495 } else {
5496 BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e);
5497 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x1f), 0x287a);
5498 BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL, ~0x000f, 0x0004);
5499 if (phy->rev >= 6) {
5500 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x22), 0x287a);
5501 BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL,
5502 (uint16_t)~0xf000, 0x3000);
5503 }
5504 }
5505 BWN_PHY_SETMASK(mac, BWN_PHY_DIVSRCHIDX, 0x8080, 0x7874);
5506 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8e), 0x1c00);
5507 if (phy->rev == 1) {
5508 BWN_PHY_SETMASK(mac, BWN_PHY_DIVP1P2GAIN, ~0x0f00, 0x0600);
5509 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8b), 0x005e);
5510 BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, ~0x00ff, 0x001e);
5511 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8d), 0x0002);
5512 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 0, 0);
5513 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 1, 7);
5514 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 2, 16);
5515 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 3, 28);
5516 } else {
5517 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 0, 0);
5518 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 1, 7);
5519 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 2, 16);
5520 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 3, 28);
5521 }
5522 if (phy->rev >= 6) {
5523 BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x0003);
5524 BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x1000);
5525 }
5526 BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
5527}
5528
5529static void
5530bwn_wa_grev1(struct bwn_mac *mac)
5531{
5532 struct bwn_phy *phy = &mac->mac_phy;
5533 int i;
5534 static const uint16_t bwn_tab_finefreqg[] = BWN_TAB_FINEFREQ_G;
5535 static const uint32_t bwn_tab_retard[] = BWN_TAB_RETARD;
5536 static const uint32_t bwn_tab_rotor[] = BWN_TAB_ROTOR;
5537
5538 KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5539
5540 /* init CRSTHRES and ANTDWELL */
5541 if (phy->rev == 1) {
5542 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5543 } else if (phy->rev == 2) {
5544 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5545 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5546 BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5547 } else {
5548 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5549 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5550 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5551 BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5552 }
5553 BWN_PHY_SETMASK(mac, BWN_PHY_CRS0, ~0x03c0, 0xd000);
5554 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x2c), 0x005a);
5555 BWN_PHY_WRITE(mac, BWN_PHY_CCKSHIFTBITS, 0x0026);
5556
5557 /* XXX support PHY-A??? */
5558 for (i = 0; i < N(bwn_tab_finefreqg); i++)
5559 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DACRFPABB, i,
5560 bwn_tab_finefreqg[i]);
5561
5562 /* XXX support PHY-A??? */
5563 if (phy->rev == 1)
5564 for (i = 0; i < N(bwn_tab_noise_g1); i++)
5565 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5566 bwn_tab_noise_g1[i]);
5567 else
5568 for (i = 0; i < N(bwn_tab_noise_g2); i++)
5569 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5570 bwn_tab_noise_g2[i]);
5571
5572
5573 for (i = 0; i < N(bwn_tab_rotor); i++)
5574 bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ROTOR, i,
5575 bwn_tab_rotor[i]);
5576
5577 /* XXX support PHY-A??? */
5578 if (phy->rev >= 6) {
5579 if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5580 BWN_PHY_ENCORE_EN)
5581 bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5582 else
5583 bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5584 } else
5585 bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5586
5587 for (i = 0; i < N(bwn_tab_retard); i++)
5588 bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ADVRETARD, i,
5589 bwn_tab_retard[i]);
5590
5591 if (phy->rev == 1) {
5592 for (i = 0; i < 16; i++)
5593 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1,
5594 i, 0x0020);
5595 } else {
5596 for (i = 0; i < 32; i++)
5597 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5598 }
5599
5600 bwn_wa_agc(mac);
5601}
5602
5603static void
5604bwn_wa_grev26789(struct bwn_mac *mac)
5605{
5606 struct bwn_phy *phy = &mac->mac_phy;
5607 int i;
5608 static const uint16_t bwn_tab_sigmasqr2[] = BWN_TAB_SIGMASQR2;
5609 uint16_t ofdmrev;
5610
5611 KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5612
5613 bwn_gtab_write(mac, BWN_GTAB_ORIGTR, 0, 0xc480);
5614
5615 /* init CRSTHRES and ANTDWELL */
5616 if (phy->rev == 1)
5617 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5618 else if (phy->rev == 2) {
5619 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5620 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5621 BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5622 } else {
5623 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5624 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5625 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5626 BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5627 }
5628
5629 for (i = 0; i < 64; i++)
5630 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_RSSI, i, i);
5631
5632 /* XXX support PHY-A??? */
5633 if (phy->rev == 1)
5634 for (i = 0; i < N(bwn_tab_noise_g1); i++)
5635 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5636 bwn_tab_noise_g1[i]);
5637 else
5638 for (i = 0; i < N(bwn_tab_noise_g2); i++)
5639 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5640 bwn_tab_noise_g2[i]);
5641
5642 /* XXX support PHY-A??? */
5643 if (phy->rev >= 6) {
5644 if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5645 BWN_PHY_ENCORE_EN)
5646 bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5647 else
5648 bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5649 } else
5650 bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5651
5652 for (i = 0; i < N(bwn_tab_sigmasqr2); i++)
5653 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_MINSIGSQ, i,
5654 bwn_tab_sigmasqr2[i]);
5655
5656 if (phy->rev == 1) {
5657 for (i = 0; i < 16; i++)
5658 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1, i,
5659 0x0020);
5660 } else {
5661 for (i = 0; i < 32; i++)
5662 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5663 }
5664
5665 bwn_wa_agc(mac);
5666
5667 ofdmrev = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM) & BWN_PHYVER_VERSION;
5668 if (ofdmrev > 2) {
5669 if (phy->type == BWN_PHYTYPE_A)
5670 BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1808);
5671 else
5672 BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1000);
5673 } else {
5674 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 3, 0x1044);
5675 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 4, 0x7201);
5676 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 6, 0x0040);
5677 }
5678
5679 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 2, 15);
5680 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 3, 20);
5681}
5682
5683static void
5684bwn_wa_init(struct bwn_mac *mac)
5685{
5686 struct bwn_phy *phy = &mac->mac_phy;
5687 struct bwn_softc *sc = mac->mac_sc;
5688
5689 KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5690
5691 switch (phy->rev) {
5692 case 1:
5693 bwn_wa_grev1(mac);
5694 break;
5695 case 2:
5696 case 6:
5697 case 7:
5698 case 8:
5699 case 9:
5700 bwn_wa_grev26789(mac);
5701 break;
5702 default:
5703 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5704 }
5705
5706 if (siba_get_pci_subvendor(sc->sc_dev) != SIBA_BOARDVENDOR_BCM ||
5707 siba_get_pci_subdevice(sc->sc_dev) != SIBA_BOARD_BU4306 ||
5708 siba_get_pci_revid(sc->sc_dev) != 0x17) {
5709 if (phy->rev < 2) {
5710 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 1,
5711 0x0002);
5712 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 2,
5713 0x0001);
5714 } else {
5715 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 1, 0x0002);
5716 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 2, 0x0001);
5717 if ((siba_sprom_get_bf_lo(sc->sc_dev) &
5718 BWN_BFL_EXTLNA) &&
5719 (phy->rev >= 7)) {
5720 BWN_PHY_MASK(mac, BWN_PHY_EXTG(0x11), 0xf7ff);
5721 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5722 0x0020, 0x0001);
5723 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5724 0x0021, 0x0001);
5725 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5726 0x0022, 0x0001);
5727 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5728 0x0023, 0x0000);
5729 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5730 0x0000, 0x0000);
5731 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5732 0x0003, 0x0002);
5733 }
5734 }
5735 }
5736 if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM) {
5737 BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, 0x3120);
5738 BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, 0xc480);
5739 }
5740
5741 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 0, 0);
5742 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 1, 0);
5743}
5744
5745static void
5746bwn_ofdmtab_write_2(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5747 uint16_t value)
5748{
5749 struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5750 uint16_t addr;
5751
5752 addr = table + offset;
5753 if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5754 (addr - 1 != pg->pg_ofdmtab_addr)) {
5755 BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5756 pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5757 }
5758 pg->pg_ofdmtab_addr = addr;
5759 BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5760}
5761
5762static void
5763bwn_ofdmtab_write_4(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5764 uint32_t value)
5765{
5766 struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5767 uint16_t addr;
5768
5769 addr = table + offset;
5770 if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5771 (addr - 1 != pg->pg_ofdmtab_addr)) {
5772 BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5773 pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5774 }
5775 pg->pg_ofdmtab_addr = addr;
5776
5777 BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5778 BWN_PHY_WRITE(mac, BWN_PHY_OTABLEQ, (value >> 16));
5779}
5780
5781static void
5782bwn_gtab_write(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5783 uint16_t value)
5784{
5785
5786 BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, table + offset);
5787 BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, value);
5788}
5789
5790static void
5791bwn_dummy_transmission(struct bwn_mac *mac, int ofdm, int paon)
5792{
5793 struct bwn_phy *phy = &mac->mac_phy;
5794 struct bwn_softc *sc = mac->mac_sc;
5795 unsigned int i, max_loop;
5796 uint16_t value;
5797 uint32_t buffer[5] = {
5798 0x00000000, 0x00d40000, 0x00000000, 0x01000000, 0x00000000
5799 };
5800
5801 if (ofdm) {
5802 max_loop = 0x1e;
5803 buffer[0] = 0x000201cc;
5804 } else {
5805 max_loop = 0xfa;
5806 buffer[0] = 0x000b846e;
5807 }
5808
5809 BWN_ASSERT_LOCKED(mac->mac_sc);
5810
5811 for (i = 0; i < 5; i++)
5812 bwn_ram_write(mac, i * 4, buffer[i]);
5813
5814 BWN_WRITE_2(mac, 0x0568, 0x0000);
5815 BWN_WRITE_2(mac, 0x07c0,
5816 (siba_get_revid(sc->sc_dev) < 11) ? 0x0000 : 0x0100);
5817 value = ((phy->type == BWN_PHYTYPE_A) ? 0x41 : 0x40);
5818 BWN_WRITE_2(mac, 0x050c, value);
5819 if (phy->type == BWN_PHYTYPE_LP)
5820 BWN_WRITE_2(mac, 0x0514, 0x1a02);
5821 BWN_WRITE_2(mac, 0x0508, 0x0000);
5822 BWN_WRITE_2(mac, 0x050a, 0x0000);
5823 BWN_WRITE_2(mac, 0x054c, 0x0000);
5824 BWN_WRITE_2(mac, 0x056a, 0x0014);
5825 BWN_WRITE_2(mac, 0x0568, 0x0826);
5826 BWN_WRITE_2(mac, 0x0500, 0x0000);
5827 if (phy->type == BWN_PHYTYPE_LP)
5828 BWN_WRITE_2(mac, 0x0502, 0x0050);
5829 else
5830 BWN_WRITE_2(mac, 0x0502, 0x0030);
5831
5832 if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5833 BWN_RF_WRITE(mac, 0x0051, 0x0017);
5834 for (i = 0x00; i < max_loop; i++) {
5835 value = BWN_READ_2(mac, 0x050e);
5836 if (value & 0x0080)
5837 break;
5838 DELAY(10);
5839 }
5840 for (i = 0x00; i < 0x0a; i++) {
5841 value = BWN_READ_2(mac, 0x050e);
5842 if (value & 0x0400)
5843 break;
5844 DELAY(10);
5845 }
5846 for (i = 0x00; i < 0x19; i++) {
5847 value = BWN_READ_2(mac, 0x0690);
5848 if (!(value & 0x0100))
5849 break;
5850 DELAY(10);
5851 }
5852 if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5853 BWN_RF_WRITE(mac, 0x0051, 0x0037);
5854}
5855
5856static void
5857bwn_ram_write(struct bwn_mac *mac, uint16_t offset, uint32_t val)
5858{
5859 uint32_t macctl;
5860
5861 KASSERT(offset % 4 == 0, ("%s:%d: fail", __func__, __LINE__));
5862
5863 macctl = BWN_READ_4(mac, BWN_MACCTL);
5864 if (macctl & BWN_MACCTL_BIGENDIAN)
5865 printf("TODO: need swap\n");
5866
5867 BWN_WRITE_4(mac, BWN_RAM_CONTROL, offset);
5868 BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
5869 BWN_WRITE_4(mac, BWN_RAM_DATA, val);
5870}
5871
5872static void
5873bwn_lo_write(struct bwn_mac *mac, struct bwn_loctl *ctl)
5874{
5875 uint16_t value;
5876
5877 KASSERT(mac->mac_phy.type == BWN_PHYTYPE_G,
5878 ("%s:%d: fail", __func__, __LINE__));
5879
5880 value = (uint8_t) (ctl->q);
5881 value |= ((uint8_t) (ctl->i)) << 8;
5882 BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, value);
5883}
5884
5885static uint16_t
5886bwn_lo_calcfeed(struct bwn_mac *mac,
5887 uint16_t lna, uint16_t pga, uint16_t trsw_rx)
5888{
5889 struct bwn_phy *phy = &mac->mac_phy;
5890 struct bwn_softc *sc = mac->mac_sc;
5891 uint16_t rfover;
5892 uint16_t feedthrough;
5893
5894 if (phy->gmode) {
5895 lna <<= BWN_PHY_RFOVERVAL_LNA_SHIFT;
5896 pga <<= BWN_PHY_RFOVERVAL_PGA_SHIFT;
5897
5898 KASSERT((lna & ~BWN_PHY_RFOVERVAL_LNA) == 0,
5899 ("%s:%d: fail", __func__, __LINE__));
5900 KASSERT((pga & ~BWN_PHY_RFOVERVAL_PGA) == 0,
5901 ("%s:%d: fail", __func__, __LINE__));
5902
5903 trsw_rx &= (BWN_PHY_RFOVERVAL_TRSWRX | BWN_PHY_RFOVERVAL_BW);
5904
5905 rfover = BWN_PHY_RFOVERVAL_UNK | pga | lna | trsw_rx;
5906 if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA) &&
5907 phy->rev > 6)
5908 rfover |= BWN_PHY_RFOVERVAL_EXTLNA;
5909
5910 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
5911 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5912 DELAY(10);
5913 rfover |= BWN_PHY_RFOVERVAL_BW_LBW;
5914 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5915 DELAY(10);
5916 rfover |= BWN_PHY_RFOVERVAL_BW_LPF;
5917 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5918 DELAY(10);
5919 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xf300);
5920 } else {
5921 pga |= BWN_PHY_PGACTL_UNKNOWN;
5922 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5923 DELAY(10);
5924 pga |= BWN_PHY_PGACTL_LOWBANDW;
5925 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5926 DELAY(10);
5927 pga |= BWN_PHY_PGACTL_LPF;
5928 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5929 }
5930 DELAY(21);
5931 feedthrough = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5932
5933 return (feedthrough);
5934}
5935
5936static uint16_t
5937bwn_lo_txctl_regtable(struct bwn_mac *mac,
5938 uint16_t *value, uint16_t *pad_mix_gain)
5939{
5940 struct bwn_phy *phy = &mac->mac_phy;
5941 uint16_t reg, v, padmix;
5942
5943 if (phy->type == BWN_PHYTYPE_B) {
5944 v = 0x30;
5945 if (phy->rf_rev <= 5) {
5946 reg = 0x43;
5947 padmix = 0;
5948 } else {
5949 reg = 0x52;
5950 padmix = 5;
5951 }
5952 } else {
5953 if (phy->rev >= 2 && phy->rf_rev == 8) {
5954 reg = 0x43;
5955 v = 0x10;
5956 padmix = 2;
5957 } else {
5958 reg = 0x52;
5959 v = 0x30;
5960 padmix = 5;
5961 }
5962 }
5963 if (value)
5964 *value = v;
5965 if (pad_mix_gain)
5966 *pad_mix_gain = padmix;
5967
5968 return (reg);
5969}
5970
5971static void
5972bwn_lo_measure_txctl_values(struct bwn_mac *mac)
5973{
5974 struct bwn_phy *phy = &mac->mac_phy;
5975 struct bwn_phy_g *pg = &phy->phy_g;
5976 struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
5977 uint16_t reg, mask;
5978 uint16_t trsw_rx, pga;
5979 uint16_t rf_pctl_reg;
5980
5981 static const uint8_t tx_bias_values[] = {
5982 0x09, 0x08, 0x0a, 0x01, 0x00,
5983 0x02, 0x05, 0x04, 0x06,
5984 };
5985 static const uint8_t tx_magn_values[] = {
5986 0x70, 0x40,
5987 };
5988
5989 if (!BWN_HAS_LOOPBACK(phy)) {
5990 rf_pctl_reg = 6;
5991 trsw_rx = 2;
5992 pga = 0;
5993 } else {
5994 int lb_gain;
5995
5996 trsw_rx = 0;
5997 lb_gain = pg->pg_max_lb_gain / 2;
5998 if (lb_gain > 10) {
5999 rf_pctl_reg = 0;
6000 pga = abs(10 - lb_gain) / 6;
6001 pga = MIN(MAX(pga, 0), 15);
6002 } else {
6003 int cmp_val;
6004 int tmp;
6005
6006 pga = 0;
6007 cmp_val = 0x24;
6008 if ((phy->rev >= 2) &&
6009 (phy->rf_ver == 0x2050) && (phy->rf_rev == 8))
6010 cmp_val = 0x3c;
6011 tmp = lb_gain;
6012 if ((10 - lb_gain) < cmp_val)
6013 tmp = (10 - lb_gain);
6014 if (tmp < 0)
6015 tmp += 6;
6016 else
6017 tmp += 3;
6018 cmp_val /= 4;
6019 tmp /= 4;
6020 if (tmp >= cmp_val)
6021 rf_pctl_reg = cmp_val;
6022 else
6023 rf_pctl_reg = tmp;
6024 }
6025 }
6026 BWN_RF_SETMASK(mac, 0x43, 0xfff0, rf_pctl_reg);
6027 bwn_phy_g_set_bbatt(mac, 2);
6028
6029 reg = bwn_lo_txctl_regtable(mac, &mask, NULL);
6030 mask = ~mask;
6031 BWN_RF_MASK(mac, reg, mask);
6032
6033 if (BWN_HAS_TXMAG(phy)) {
6034 int i, j;
6035 int feedthrough;
6036 int min_feedth = 0xffff;
6037 uint8_t tx_magn, tx_bias;
6038
6039 for (i = 0; i < N(tx_magn_values); i++) {
6040 tx_magn = tx_magn_values[i];
6041 BWN_RF_SETMASK(mac, 0x52, 0xff0f, tx_magn);
6042 for (j = 0; j < N(tx_bias_values); j++) {
6043 tx_bias = tx_bias_values[j];
6044 BWN_RF_SETMASK(mac, 0x52, 0xfff0, tx_bias);
6045 feedthrough = bwn_lo_calcfeed(mac, 0, pga,
6046 trsw_rx);
6047 if (feedthrough < min_feedth) {
6048 lo->tx_bias = tx_bias;
6049 lo->tx_magn = tx_magn;
6050 min_feedth = feedthrough;
6051 }
6052 if (lo->tx_bias == 0)
6053 break;
6054 }
6055 BWN_RF_WRITE(mac, 0x52,
6056 (BWN_RF_READ(mac, 0x52)
6057 & 0xff00) | lo->tx_bias | lo->
6058 tx_magn);
6059 }
6060 } else {
6061 lo->tx_magn = 0;
6062 lo->tx_bias = 0;
6063 BWN_RF_MASK(mac, 0x52, 0xfff0);
6064 }
6065
6066 BWN_GETTIME(lo->txctl_measured_time);
6067}
6068
6069static void
6070bwn_lo_get_powervector(struct bwn_mac *mac)
6071{
6072 struct bwn_phy *phy = &mac->mac_phy;
6073 struct bwn_phy_g *pg = &phy->phy_g;
6074 struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6075 int i;
6076 uint64_t tmp;
6077 uint64_t power_vector = 0;
6078
6079 for (i = 0; i < 8; i += 2) {
6080 tmp = bwn_shm_read_2(mac, BWN_SHARED, 0x310 + i);
6081 power_vector |= (tmp << (i * 8));
6082 bwn_shm_write_2(mac, BWN_SHARED, 0x310 + i, 0);
6083 }
6084 if (power_vector)
6085 lo->power_vector = power_vector;
6086
6087 BWN_GETTIME(lo->pwr_vec_read_time);
6088}
6089
6090static void
6091bwn_lo_measure_gain_values(struct bwn_mac *mac, int16_t max_rx_gain,
6092 int use_trsw_rx)
6093{
6094 struct bwn_phy *phy = &mac->mac_phy;
6095 struct bwn_phy_g *pg = &phy->phy_g;
6096 uint16_t tmp;
6097
6098 if (max_rx_gain < 0)
6099 max_rx_gain = 0;
6100
6101 if (BWN_HAS_LOOPBACK(phy)) {
6102 int trsw_rx = 0;
6103 int trsw_rx_gain;
6104
6105 if (use_trsw_rx) {
6106 trsw_rx_gain = pg->pg_trsw_rx_gain / 2;
6107 if (max_rx_gain >= trsw_rx_gain) {
6108 trsw_rx_gain = max_rx_gain - trsw_rx_gain;
6109 trsw_rx = 0x20;
6110 }
6111 } else
6112 trsw_rx_gain = max_rx_gain;
6113 if (trsw_rx_gain < 9) {
6114 pg->pg_lna_lod_gain = 0;
6115 } else {
6116 pg->pg_lna_lod_gain = 1;
6117 trsw_rx_gain -= 8;
6118 }
6119 trsw_rx_gain = MIN(MAX(trsw_rx_gain, 0), 0x2d);
6120 pg->pg_pga_gain = trsw_rx_gain / 3;
6121 if (pg->pg_pga_gain >= 5) {
6122 pg->pg_pga_gain -= 5;
6123 pg->pg_lna_gain = 2;
6124 } else
6125 pg->pg_lna_gain = 0;
6126 } else {
6127 pg->pg_lna_gain = 0;
6128 pg->pg_trsw_rx_gain = 0x20;
6129 if (max_rx_gain >= 0x14) {
6130 pg->pg_lna_lod_gain = 1;
6131 pg->pg_pga_gain = 2;
6132 } else if (max_rx_gain >= 0x12) {
6133 pg->pg_lna_lod_gain = 1;
6134 pg->pg_pga_gain = 1;
6135 } else if (max_rx_gain >= 0xf) {
6136 pg->pg_lna_lod_gain = 1;
6137 pg->pg_pga_gain = 0;
6138 } else {
6139 pg->pg_lna_lod_gain = 0;
6140 pg->pg_pga_gain = 0;
6141 }
6142 }
6143
6144 tmp = BWN_RF_READ(mac, 0x7a);
6145 if (pg->pg_lna_lod_gain == 0)
6146 tmp &= ~0x0008;
6147 else
6148 tmp |= 0x0008;
6149 BWN_RF_WRITE(mac, 0x7a, tmp);
6150}
6151
6152static void
6153bwn_lo_save(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6154{
6155 struct bwn_phy *phy = &mac->mac_phy;
6156 struct bwn_phy_g *pg = &phy->phy_g;
6157 struct bwn_softc *sc = mac->mac_sc;
6158 struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6159 struct timespec ts;
6160 uint16_t tmp;
6161
6162 if (bwn_has_hwpctl(mac)) {
6163 sav->phy_lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
6164 sav->phy_extg = BWN_PHY_READ(mac, BWN_PHY_EXTG(0x01));
6165 sav->phy_dacctl_hwpctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6166 sav->phy_cck4 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x14));
6167 sav->phy_hpwr_tssictl = BWN_PHY_READ(mac, BWN_PHY_HPWR_TSSICTL);
6168
6169 BWN_PHY_SET(mac, BWN_PHY_HPWR_TSSICTL, 0x100);
6170 BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x40);
6171 BWN_PHY_SET(mac, BWN_PHY_DACCTL, 0x40);
6172 BWN_PHY_SET(mac, BWN_PHY_CCK(0x14), 0x200);
6173 }
6174 if (phy->type == BWN_PHYTYPE_B &&
6175 phy->rf_ver == 0x2050 && phy->rf_rev < 6) {
6176 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x16), 0x410);
6177 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x17), 0x820);
6178 }
6179 if (phy->rev >= 2) {
6180 sav->phy_analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
6181 sav->phy_analogoverval =
6182 BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
6183 sav->phy_rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
6184 sav->phy_rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
6185 sav->phy_classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
6186 sav->phy_cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x3e));
6187 sav->phy_crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
6188
6189 BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
6190 BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
6191 BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
6192 BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
6193 if (phy->type == BWN_PHYTYPE_G) {
6194 if ((phy->rev >= 7) &&
6195 (siba_sprom_get_bf_lo(sc->sc_dev) &
6196 BWN_BFL_EXTLNA)) {
6197 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x933);
6198 } else {
6199 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x133);
6200 }
6201 } else {
6202 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
6203 }
6204 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), 0);
6205 }
6206 sav->reg0 = BWN_READ_2(mac, 0x3f4);
6207 sav->reg1 = BWN_READ_2(mac, 0x3e2);
6208 sav->rf0 = BWN_RF_READ(mac, 0x43);
6209 sav->rf1 = BWN_RF_READ(mac, 0x7a);
6210 sav->phy_pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
6211 sav->phy_cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2a));
6212 sav->phy_syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
6213 sav->phy_dacctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6214
6215 if (!BWN_HAS_TXMAG(phy)) {
6216 sav->rf2 = BWN_RF_READ(mac, 0x52);
6217 sav->rf2 &= 0x00f0;
6218 }
6219 if (phy->type == BWN_PHYTYPE_B) {
6220 sav->phy_cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
6221 sav->phy_cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x06));
6222 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0x00ff);
6223 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), 0x3f3f);
6224 } else {
6225 BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2)
6226 | 0x8000);
6227 }
6228 BWN_WRITE_2(mac, 0x3f4, BWN_READ_2(mac, 0x3f4)
6229 & 0xf000);
6230
6231 tmp =
6232 (phy->type == BWN_PHYTYPE_G) ? BWN_PHY_LO_MASK : BWN_PHY_CCK(0x2e);
6233 BWN_PHY_WRITE(mac, tmp, 0x007f);
6234
6235 tmp = sav->phy_syncctl;
6236 BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, tmp & 0xff7f);
6237 tmp = sav->rf1;
6238 BWN_RF_WRITE(mac, 0x007a, tmp & 0xfff0);
6239
6240 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), 0x8a3);
6241 if (phy->type == BWN_PHYTYPE_G ||
6242 (phy->type == BWN_PHYTYPE_B &&
6243 phy->rf_ver == 0x2050 && phy->rf_rev >= 6)) {
6244 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1003);
6245 } else
6246 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x0802);
6247 if (phy->rev >= 2)
6248 bwn_dummy_transmission(mac, 0, 1);
6249 bwn_phy_g_switch_chan(mac, 6, 0);
6250 BWN_RF_READ(mac, 0x51);
6251 if (phy->type == BWN_PHYTYPE_G)
6252 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0);
6253
6254 nanouptime(&ts);
6255 if (time_before(lo->txctl_measured_time,
6256 (ts.tv_nsec / 1000000 + ts.tv_sec * 1000) - BWN_LO_TXCTL_EXPIRE))
6257 bwn_lo_measure_txctl_values(mac);
6258
6259 if (phy->type == BWN_PHYTYPE_G && phy->rev >= 3)
6260 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc078);
6261 else {
6262 if (phy->type == BWN_PHYTYPE_B)
6263 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6264 else
6265 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
6266 }
6267}
6268
6269static void
6270bwn_lo_restore(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6271{
6272 struct bwn_phy *phy = &mac->mac_phy;
6273 struct bwn_phy_g *pg = &phy->phy_g;
6274 uint16_t tmp;
6275
6276 if (phy->rev >= 2) {
6277 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
6278 tmp = (pg->pg_pga_gain << 8);
6279 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa0);
6280 DELAY(5);
6281 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa2);
6282 DELAY(2);
6283 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa3);
6284 } else {
6285 tmp = (pg->pg_pga_gain | 0xefa0);
6286 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, tmp);
6287 }
6288 if (phy->type == BWN_PHYTYPE_G) {
6289 if (phy->rev >= 3)
6290 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0xc078);
6291 else
6292 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6293 if (phy->rev >= 2)
6294 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0202);
6295 else
6296 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0101);
6297 }
6298 BWN_WRITE_2(mac, 0x3f4, sav->reg0);
6299 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, sav->phy_pgactl);
6300 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), sav->phy_cck2);
6301 BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, sav->phy_syncctl);
6302 BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl);
6303 BWN_RF_WRITE(mac, 0x43, sav->rf0);
6304 BWN_RF_WRITE(mac, 0x7a, sav->rf1);
6305 if (!BWN_HAS_TXMAG(phy)) {
6306 tmp = sav->rf2;
6307 BWN_RF_SETMASK(mac, 0x52, 0xff0f, tmp);
6308 }
6309 BWN_WRITE_2(mac, 0x3e2, sav->reg1);
6310 if (phy->type == BWN_PHYTYPE_B &&
6311 phy->rf_ver == 0x2050 && phy->rf_rev <= 5) {
6312 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), sav->phy_cck0);
6313 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), sav->phy_cck1);
6314 }
6315 if (phy->rev >= 2) {
6316 BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, sav->phy_analogover);
6317 BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
6318 sav->phy_analogoverval);
6319 BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, sav->phy_classctl);
6320 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, sav->phy_rfover);
6321 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, sav->phy_rfoverval);
6322 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), sav->phy_cck3);
6323 BWN_PHY_WRITE(mac, BWN_PHY_CRS0, sav->phy_crs0);
6324 }
6325 if (bwn_has_hwpctl(mac)) {
6326 tmp = (sav->phy_lomask & 0xbfff);
6327 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, tmp);
6328 BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x01), sav->phy_extg);
6329 BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl_hwpctl);
6330 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x14), sav->phy_cck4);
6331 BWN_PHY_WRITE(mac, BWN_PHY_HPWR_TSSICTL, sav->phy_hpwr_tssictl);
6332 }
6333 bwn_phy_g_switch_chan(mac, sav->old_channel, 1);
6334}
6335
6336static int
6337bwn_lo_probe_loctl(struct bwn_mac *mac,
6338 struct bwn_loctl *probe, struct bwn_lo_g_sm *d)
6339{
6340 struct bwn_phy *phy = &mac->mac_phy;
6341 struct bwn_phy_g *pg = &phy->phy_g;
6342 struct bwn_loctl orig, test;
6343 struct bwn_loctl prev = { -100, -100 };
6344 static const struct bwn_loctl modifiers[] = {
6345 { 1, 1,}, { 1, 0,}, { 1, -1,}, { 0, -1,},
6346 { -1, -1,}, { -1, 0,}, { -1, 1,}, { 0, 1,}
6347 };
6348 int begin, end, lower = 0, i;
6349 uint16_t feedth;
6350
6351 if (d->curstate == 0) {
6352 begin = 1;
6353 end = 8;
6354 } else if (d->curstate % 2 == 0) {
6355 begin = d->curstate - 1;
6356 end = d->curstate + 1;
6357 } else {
6358 begin = d->curstate - 2;
6359 end = d->curstate + 2;
6360 }
6361 if (begin < 1)
6362 begin += 8;
6363 if (end > 8)
6364 end -= 8;
6365
6366 memcpy(&orig, probe, sizeof(struct bwn_loctl));
6367 i = begin;
6368 d->curstate = i;
6369 while (1) {
6370 KASSERT(i >= 1 && i <= 8, ("%s:%d: fail", __func__, __LINE__));
6371 memcpy(&test, &orig, sizeof(struct bwn_loctl));
6372 test.i += modifiers[i - 1].i * d->multipler;
6373 test.q += modifiers[i - 1].q * d->multipler;
6374 if ((test.i != prev.i || test.q != prev.q) &&
6375 (abs(test.i) <= 16 && abs(test.q) <= 16)) {
6376 bwn_lo_write(mac, &test);
6377 feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6378 pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6379 if (feedth < d->feedth) {
6380 memcpy(probe, &test,
6381 sizeof(struct bwn_loctl));
6382 lower = 1;
6383 d->feedth = feedth;
6384 if (d->nmeasure < 2 && !BWN_HAS_LOOPBACK(phy))
6385 break;
6386 }
6387 }
6388 memcpy(&prev, &test, sizeof(prev));
6389 if (i == end)
6390 break;
6391 if (i == 8)
6392 i = 1;
6393 else
6394 i++;
6395 d->curstate = i;
6396 }
6397
6398 return (lower);
6399}
6400
6401static void
6402bwn_lo_probe_sm(struct bwn_mac *mac, struct bwn_loctl *loctl, int *rxgain)
6403{
6404 struct bwn_phy *phy = &mac->mac_phy;
6405 struct bwn_phy_g *pg = &phy->phy_g;
6406 struct bwn_lo_g_sm d;
6407 struct bwn_loctl probe;
6408 int lower, repeat, cnt = 0;
6409 uint16_t feedth;
6410
6411 d.nmeasure = 0;
6412 d.multipler = 1;
6413 if (BWN_HAS_LOOPBACK(phy))
6414 d.multipler = 3;
6415
6416 memcpy(&d.loctl, loctl, sizeof(struct bwn_loctl));
6417 repeat = (BWN_HAS_LOOPBACK(phy)) ? 4 : 1;
6418
6419 do {
6420 bwn_lo_write(mac, &d.loctl);
6421 feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6422 pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6423 if (feedth < 0x258) {
6424 if (feedth >= 0x12c)
6425 *rxgain += 6;
6426 else
6427 *rxgain += 3;
6428 feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6429 pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6430 }
6431 d.feedth = feedth;
6432 d.curstate = 0;
6433 do {
6434 KASSERT(d.curstate >= 0 && d.curstate <= 8,
6435 ("%s:%d: fail", __func__, __LINE__));
6436 memcpy(&probe, &d.loctl,
6437 sizeof(struct bwn_loctl));
6438 lower = bwn_lo_probe_loctl(mac, &probe, &d);
6439 if (!lower)
6440 break;
6441 if ((probe.i == d.loctl.i) && (probe.q == d.loctl.q))
6442 break;
6443 memcpy(&d.loctl, &probe, sizeof(struct bwn_loctl));
6444 d.nmeasure++;
6445 } while (d.nmeasure < 24);
6446 memcpy(loctl, &d.loctl, sizeof(struct bwn_loctl));
6447
6448 if (BWN_HAS_LOOPBACK(phy)) {
6449 if (d.feedth > 0x1194)
6450 *rxgain -= 6;
6451 else if (d.feedth < 0x5dc)
6452 *rxgain += 3;
6453 if (cnt == 0) {
6454 if (d.feedth <= 0x5dc) {
6455 d.multipler = 1;
6456 cnt++;
6457 } else
6458 d.multipler = 2;
6459 } else if (cnt == 2)
6460 d.multipler = 1;
6461 }
6462 bwn_lo_measure_gain_values(mac, *rxgain, BWN_HAS_LOOPBACK(phy));
6463 } while (++cnt < repeat);
6464}
6465
6466static struct bwn_lo_calib *
6467bwn_lo_calibset(struct bwn_mac *mac,
6468 const struct bwn_bbatt *bbatt, const struct bwn_rfatt *rfatt)
6469{
6470 struct bwn_phy *phy = &mac->mac_phy;
6471 struct bwn_phy_g *pg = &phy->phy_g;
6472 struct bwn_loctl loctl = { 0, 0 };
6473 struct bwn_lo_calib *cal;
6474 struct bwn_lo_g_value sval = { 0 };
6475 int rxgain;
6476 uint16_t pad, reg, value;
6477
6478 sval.old_channel = phy->chan;
6479 bwn_mac_suspend(mac);
6480 bwn_lo_save(mac, &sval);
6481
6482 reg = bwn_lo_txctl_regtable(mac, &value, &pad);
6483 BWN_RF_SETMASK(mac, 0x43, 0xfff0, rfatt->att);
6484 BWN_RF_SETMASK(mac, reg, ~value, (rfatt->padmix ? value :0));
6485
6486 rxgain = (rfatt->att * 2) + (bbatt->att / 2);
6487 if (rfatt->padmix)
6488 rxgain -= pad;
6489 if (BWN_HAS_LOOPBACK(phy))
6490 rxgain += pg->pg_max_lb_gain;
6491 bwn_lo_measure_gain_values(mac, rxgain, BWN_HAS_LOOPBACK(phy));
6492 bwn_phy_g_set_bbatt(mac, bbatt->att);
6493 bwn_lo_probe_sm(mac, &loctl, &rxgain);
6494
6495 bwn_lo_restore(mac, &sval);
6496 bwn_mac_enable(mac);
6497
6498 cal = malloc(sizeof(*cal), M_DEVBUF, M_NOWAIT | M_ZERO);
6499 if (!cal) {
6500 device_printf(mac->mac_sc->sc_dev, "out of memory\n");
6501 return (NULL);
6502 }
6503 memcpy(&cal->bbatt, bbatt, sizeof(*bbatt));
6504 memcpy(&cal->rfatt, rfatt, sizeof(*rfatt));
6505 memcpy(&cal->ctl, &loctl, sizeof(loctl));
6506
6507 BWN_GETTIME(cal->calib_time);
6508
6509 return (cal);
6510}
6511
6512static struct bwn_lo_calib *
6513bwn_lo_get_calib(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
6514 const struct bwn_rfatt *rfatt)
6515{
6516 struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
6517 struct bwn_lo_calib *c;
6518
6519 TAILQ_FOREACH(c, &lo->calib_list, list) {
6520 if (!BWN_BBATTCMP(&c->bbatt, bbatt))
6521 continue;
6522 if (!BWN_RFATTCMP(&c->rfatt, rfatt))
6523 continue;
6524 return (c);
6525 }
6526
6527 c = bwn_lo_calibset(mac, bbatt, rfatt);
6528 if (!c)
6529 return (NULL);
6530 TAILQ_INSERT_TAIL(&lo->calib_list, c, list);
6531
6532 return (c);
6533}
6534
6535static void
6536bwn_phy_g_dc_lookup_init(struct bwn_mac *mac, uint8_t update)
6537{
6538 struct bwn_phy *phy = &mac->mac_phy;
6539 struct bwn_phy_g *pg = &phy->phy_g;
6540 struct bwn_softc *sc = mac->mac_sc;
6541 struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6542 const struct bwn_rfatt *rfatt;
6543 const struct bwn_bbatt *bbatt;
6544 uint64_t pvector;
6545 int i;
6546 int rf_offset, bb_offset;
6547 uint8_t changed = 0;
6548
6549 KASSERT(BWN_DC_LT_SIZE == 32, ("%s:%d: fail", __func__, __LINE__));
6550 KASSERT(lo->rfatt.len * lo->bbatt.len <= 64,
6551 ("%s:%d: fail", __func__, __LINE__));
6552
6553 pvector = lo->power_vector;
6554 if (!update && !pvector)
6555 return;
6556
6557 bwn_mac_suspend(mac);
6558
6559 for (i = 0; i < BWN_DC_LT_SIZE * 2; i++) {
6560 struct bwn_lo_calib *cal;
6561 int idx;
6562 uint16_t val;
6563
6564 if (!update && !(pvector & (((uint64_t)1ULL) << i)))
6565 continue;
6566 bb_offset = i / lo->rfatt.len;
6567 rf_offset = i % lo->rfatt.len;
6568 bbatt = &(lo->bbatt.array[bb_offset]);
6569 rfatt = &(lo->rfatt.array[rf_offset]);
6570
6571 cal = bwn_lo_calibset(mac, bbatt, rfatt);
6572 if (!cal) {
6573 device_printf(sc->sc_dev, "LO: Could not "
6574 "calibrate DC table entry\n");
6575 continue;
6576 }
6577 val = (uint8_t)(cal->ctl.q);
6578 val |= ((uint8_t)(cal->ctl.i)) << 4;
6579 free(cal, M_DEVBUF);
6580
6581 idx = i / 2;
6582 if (i % 2)
6583 lo->dc_lt[idx] = (lo->dc_lt[idx] & 0x00ff)
6584 | ((val & 0x00ff) << 8);
6585 else
6586 lo->dc_lt[idx] = (lo->dc_lt[idx] & 0xff00)
6587 | (val & 0x00ff);
6588 changed = 1;
6589 }
6590 if (changed) {
6591 for (i = 0; i < BWN_DC_LT_SIZE; i++)
6592 BWN_PHY_WRITE(mac, 0x3a0 + i, lo->dc_lt[i]);
6593 }
6594 bwn_mac_enable(mac);
6595}
6596
6597static void
6598bwn_lo_fixup_rfatt(struct bwn_rfatt *rf)
6599{
6600
6601 if (!rf->padmix)
6602 return;
6603 if ((rf->att != 1) && (rf->att != 2) && (rf->att != 3))
6604 rf->att = 4;
6605}
6606
6607static void
6608bwn_lo_g_adjust(struct bwn_mac *mac)
6609{
6610 struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
6611 struct bwn_lo_calib *cal;
6612 struct bwn_rfatt rf;
6613
6614 memcpy(&rf, &pg->pg_rfatt, sizeof(rf));
6615 bwn_lo_fixup_rfatt(&rf);
6616
6617 cal = bwn_lo_get_calib(mac, &pg->pg_bbatt, &rf);
6618 if (!cal)
6619 return;
6620 bwn_lo_write(mac, &cal->ctl);
6621}
6622
6623static void
6624bwn_lo_g_init(struct bwn_mac *mac)
6625{
6626
6627 if (!bwn_has_hwpctl(mac))
6628 return;
6629
6630 bwn_lo_get_powervector(mac);
6631 bwn_phy_g_dc_lookup_init(mac, 1);
6632}
6633
6634static void
6635bwn_mac_suspend(struct bwn_mac *mac)
6636{
6637 struct bwn_softc *sc = mac->mac_sc;
6638 int i;
6639 uint32_t tmp;
6640
6641 KASSERT(mac->mac_suspended >= 0,
6642 ("%s:%d: fail", __func__, __LINE__));
6643
6644 if (mac->mac_suspended == 0) {
6645 bwn_psctl(mac, BWN_PS_AWAKE);
6646 BWN_WRITE_4(mac, BWN_MACCTL,
6647 BWN_READ_4(mac, BWN_MACCTL)
6648 & ~BWN_MACCTL_ON);
6649 BWN_READ_4(mac, BWN_MACCTL);
6650 for (i = 35; i; i--) {
6651 tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6652 if (tmp & BWN_INTR_MAC_SUSPENDED)
6653 goto out;
6654 DELAY(10);
6655 }
6656 for (i = 40; i; i--) {
6657 tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6658 if (tmp & BWN_INTR_MAC_SUSPENDED)
6659 goto out;
6660 DELAY(1000);
6661 }
6662 device_printf(sc->sc_dev, "MAC suspend failed\n");
6663 }
6664out:
6665 mac->mac_suspended++;
6666}
6667
6668static void
6669bwn_mac_enable(struct bwn_mac *mac)
6670{
6671 struct bwn_softc *sc = mac->mac_sc;
6672 uint16_t state;
6673
6674 state = bwn_shm_read_2(mac, BWN_SHARED,
6675 BWN_SHARED_UCODESTAT);
6676 if (state != BWN_SHARED_UCODESTAT_SUSPEND &&
6677 state != BWN_SHARED_UCODESTAT_SLEEP)
6678 device_printf(sc->sc_dev, "warn: firmware state (%d)\n", state);
6679
6680 mac->mac_suspended--;
6681 KASSERT(mac->mac_suspended >= 0,
6682 ("%s:%d: fail", __func__, __LINE__));
6683 if (mac->mac_suspended == 0) {
6684 BWN_WRITE_4(mac, BWN_MACCTL,
6685 BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_ON);
6686 BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_MAC_SUSPENDED);
6687 BWN_READ_4(mac, BWN_MACCTL);
6688 BWN_READ_4(mac, BWN_INTR_REASON);
6689 bwn_psctl(mac, 0);
6690 }
6691}
6692
6693static void
6694bwn_psctl(struct bwn_mac *mac, uint32_t flags)
6695{
6696 struct bwn_softc *sc = mac->mac_sc;
6697 int i;
6698 uint16_t ucstat;
6699
6700 KASSERT(!((flags & BWN_PS_ON) && (flags & BWN_PS_OFF)),
6701 ("%s:%d: fail", __func__, __LINE__));
6702 KASSERT(!((flags & BWN_PS_AWAKE) && (flags & BWN_PS_ASLEEP)),
6703 ("%s:%d: fail", __func__, __LINE__));
6704
6705 /* XXX forcibly awake and hwps-off */
6706
6707 BWN_WRITE_4(mac, BWN_MACCTL,
6708 (BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_AWAKE) &
6709 ~BWN_MACCTL_HWPS);
6710 BWN_READ_4(mac, BWN_MACCTL);
6711 if (siba_get_revid(sc->sc_dev) >= 5) {
6712 for (i = 0; i < 100; i++) {
6713 ucstat = bwn_shm_read_2(mac, BWN_SHARED,
6714 BWN_SHARED_UCODESTAT);
6715 if (ucstat != BWN_SHARED_UCODESTAT_SLEEP)
6716 break;
6717 DELAY(10);
6718 }
6719 }
6720}
6721
6722static int16_t
6723bwn_nrssi_read(struct bwn_mac *mac, uint16_t offset)
6724{
6725
6726 BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, offset);
6727 return ((int16_t)BWN_PHY_READ(mac, BWN_PHY_NRSSI_DATA));
6728}
6729
6730static void
6731bwn_nrssi_threshold(struct bwn_mac *mac)
6732{
6733 struct bwn_phy *phy = &mac->mac_phy;
6734 struct bwn_phy_g *pg = &phy->phy_g;
6735 struct bwn_softc *sc = mac->mac_sc;
6736 int32_t a, b;
6737 int16_t tmp16;
6738 uint16_t tmpu16;
6739
6740 KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
6741
6742 if (phy->gmode && (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI)) {
6743 if (!pg->pg_aci_wlan_automatic && pg->pg_aci_enable) {
6744 a = 0x13;
6745 b = 0x12;
6746 } else {
6747 a = 0xe;
6748 b = 0x11;
6749 }
6750
6751 a = a * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6752 a += (pg->pg_nrssi[0] << 6);
6753 a += (a < 32) ? 31 : 32;
6754 a = a >> 6;
6755 a = MIN(MAX(a, -31), 31);
6756
6757 b = b * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6758 b += (pg->pg_nrssi[0] << 6);
6759 if (b < 32)
6760 b += 31;
6761 else
6762 b += 32;
6763 b = b >> 6;
6764 b = MIN(MAX(b, -31), 31);
6765
6766 tmpu16 = BWN_PHY_READ(mac, 0x048a) & 0xf000;
6767 tmpu16 |= ((uint32_t)b & 0x0000003f);
6768 tmpu16 |= (((uint32_t)a & 0x0000003f) << 6);
6769 BWN_PHY_WRITE(mac, 0x048a, tmpu16);
6770 return;
6771 }
6772
6773 tmp16 = bwn_nrssi_read(mac, 0x20);
6774 if (tmp16 >= 0x20)
6775 tmp16 -= 0x40;
6776 BWN_PHY_SETMASK(mac, 0x048a, 0xf000, (tmp16 < 3) ? 0x09eb : 0x0aed);
6777}
6778
6779static void
6780bwn_nrssi_slope_11g(struct bwn_mac *mac)
6781{
6782#define SAVE_RF_MAX 3
6783#define SAVE_PHY_COMM_MAX 4
6784#define SAVE_PHY3_MAX 8
6785 static const uint16_t save_rf_regs[SAVE_RF_MAX] =
6786 { 0x7a, 0x52, 0x43 };
6787 static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] =
6788 { 0x15, 0x5a, 0x59, 0x58 };
6789 static const uint16_t save_phy3_regs[SAVE_PHY3_MAX] = {
6790 0x002e, 0x002f, 0x080f, BWN_PHY_G_LOCTL,
6791 0x0801, 0x0060, 0x0014, 0x0478
6792 };
6793 struct bwn_phy *phy = &mac->mac_phy;
6794 struct bwn_phy_g *pg = &phy->phy_g;
6795 int32_t i, tmp32, phy3_idx = 0;
6796 uint16_t delta, tmp;
6797 uint16_t save_rf[SAVE_RF_MAX];
6798 uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
6799 uint16_t save_phy3[SAVE_PHY3_MAX];
6800 uint16_t ant_div, phy0, chan_ex;
6801 int16_t nrssi0, nrssi1;
6802
6803 KASSERT(phy->type == BWN_PHYTYPE_G,
6804 ("%s:%d: fail", __func__, __LINE__));
6805
6806 if (phy->rf_rev >= 9)
6807 return;
6808 if (phy->rf_rev == 8)
6809 bwn_nrssi_offset(mac);
6810
6811 BWN_PHY_MASK(mac, BWN_PHY_G_CRS, 0x7fff);
6812 BWN_PHY_MASK(mac, 0x0802, 0xfffc);
6813
6814 /*
6815 * Save RF/PHY registers for later restoration
6816 */
6817 ant_div = BWN_READ_2(mac, 0x03e2);
6818 BWN_WRITE_2(mac, 0x03e2, BWN_READ_2(mac, 0x03e2) | 0x8000);
6819 for (i = 0; i < SAVE_RF_MAX; ++i)
6820 save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
6821 for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6822 save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
6823
6824 phy0 = BWN_READ_2(mac, BWN_PHY0);
6825 chan_ex = BWN_READ_2(mac, BWN_CHANNEL_EXT);
6826 if (phy->rev >= 3) {
6827 for (i = 0; i < SAVE_PHY3_MAX; ++i)
6828 save_phy3[i] = BWN_PHY_READ(mac, save_phy3_regs[i]);
6829 BWN_PHY_WRITE(mac, 0x002e, 0);
6830 BWN_PHY_WRITE(mac, BWN_PHY_G_LOCTL, 0);
6831 switch (phy->rev) {
6832 case 4:
6833 case 6:
6834 case 7:
6835 BWN_PHY_SET(mac, 0x0478, 0x0100);
6836 BWN_PHY_SET(mac, 0x0801, 0x0040);
6837 break;
6838 case 3:
6839 case 5:
6840 BWN_PHY_MASK(mac, 0x0801, 0xffbf);
6841 break;
6842 }
6843 BWN_PHY_SET(mac, 0x0060, 0x0040);
6844 BWN_PHY_SET(mac, 0x0014, 0x0200);
6845 }
6846 /*
6847 * Calculate nrssi0
6848 */
6849 BWN_RF_SET(mac, 0x007a, 0x0070);
6850 bwn_set_all_gains(mac, 0, 8, 0);
6851 BWN_RF_MASK(mac, 0x007a, 0x00f7);
6852 if (phy->rev >= 2) {
6853 BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0030);
6854 BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0010);
6855 }
6856 BWN_RF_SET(mac, 0x007a, 0x0080);
6857 DELAY(20);
6858
6859 nrssi0 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6860 if (nrssi0 >= 0x0020)
6861 nrssi0 -= 0x0040;
6862
6863 /*
6864 * Calculate nrssi1
6865 */
6866 BWN_RF_MASK(mac, 0x007a, 0x007f);
6867 if (phy->rev >= 2)
6868 BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
6869
6870 BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
6871 BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000);
6872 BWN_RF_SET(mac, 0x007a, 0x000f);
6873 BWN_PHY_WRITE(mac, 0x0015, 0xf330);
6874 if (phy->rev >= 2) {
6875 BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0020);
6876 BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0020);
6877 }
6878
6879 bwn_set_all_gains(mac, 3, 0, 1);
6880 if (phy->rf_rev == 8) {
6881 BWN_RF_WRITE(mac, 0x0043, 0x001f);
6882 } else {
6883 tmp = BWN_RF_READ(mac, 0x0052) & 0xff0f;
6884 BWN_RF_WRITE(mac, 0x0052, tmp | 0x0060);
6885 tmp = BWN_RF_READ(mac, 0x0043) & 0xfff0;
6886 BWN_RF_WRITE(mac, 0x0043, tmp | 0x0009);
6887 }
6888 BWN_PHY_WRITE(mac, 0x005a, 0x0480);
6889 BWN_PHY_WRITE(mac, 0x0059, 0x0810);
6890 BWN_PHY_WRITE(mac, 0x0058, 0x000d);
6891 DELAY(20);
6892 nrssi1 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6893
6894 /*
6895 * Install calculated narrow RSSI values
6896 */
6897 if (nrssi1 >= 0x0020)
6898 nrssi1 -= 0x0040;
6899 if (nrssi0 == nrssi1)
6900 pg->pg_nrssi_slope = 0x00010000;
6901 else
6902 pg->pg_nrssi_slope = 0x00400000 / (nrssi0 - nrssi1);
6903 if (nrssi0 >= -4) {
6904 pg->pg_nrssi[0] = nrssi1;
6905 pg->pg_nrssi[1] = nrssi0;
6906 }
6907
6908 /*
6909 * Restore saved RF/PHY registers
6910 */
6911 if (phy->rev >= 3) {
6912 for (phy3_idx = 0; phy3_idx < 4; ++phy3_idx) {
6913 BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
6914 save_phy3[phy3_idx]);
6915 }
6916 }
6917 if (phy->rev >= 2) {
6918 BWN_PHY_MASK(mac, 0x0812, 0xffcf);
6919 BWN_PHY_MASK(mac, 0x0811, 0xffcf);
6920 }
6921
6922 for (i = 0; i < SAVE_RF_MAX; ++i)
6923 BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
6924
6925 BWN_WRITE_2(mac, 0x03e2, ant_div);
6926 BWN_WRITE_2(mac, 0x03e6, phy0);
6927 BWN_WRITE_2(mac, BWN_CHANNEL_EXT, chan_ex);
6928
6929 for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6930 BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
6931
6932 bwn_spu_workaround(mac, phy->chan);
6933 BWN_PHY_SET(mac, 0x0802, (0x0001 | 0x0002));
6934 bwn_set_original_gains(mac);
6935 BWN_PHY_SET(mac, BWN_PHY_G_CRS, 0x8000);
6936 if (phy->rev >= 3) {
6937 for (; phy3_idx < SAVE_PHY3_MAX; ++phy3_idx) {
6938 BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
6939 save_phy3[phy3_idx]);
6940 }
6941 }
6942
6943 delta = 0x1f - pg->pg_nrssi[0];
6944 for (i = 0; i < 64; i++) {
6945 tmp32 = (((i - delta) * pg->pg_nrssi_slope) / 0x10000) + 0x3a;
6946 tmp32 = MIN(MAX(tmp32, 0), 0x3f);
6947 pg->pg_nrssi_lt[i] = tmp32;
6948 }
6949
6950 bwn_nrssi_threshold(mac);
6951#undef SAVE_RF_MAX
6952#undef SAVE_PHY_COMM_MAX
6953#undef SAVE_PHY3_MAX
6954}
6955
6956static void
6957bwn_nrssi_offset(struct bwn_mac *mac)
6958{
6959#define SAVE_RF_MAX 2
6960#define SAVE_PHY_COMM_MAX 10
6961#define SAVE_PHY6_MAX 8
6962 static const uint16_t save_rf_regs[SAVE_RF_MAX] =
6963 { 0x7a, 0x43 };
6964 static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] = {
6965 0x0001, 0x0811, 0x0812, 0x0814,
6966 0x0815, 0x005a, 0x0059, 0x0058,
6967 0x000a, 0x0003
6968 };
6969 static const uint16_t save_phy6_regs[SAVE_PHY6_MAX] = {
6970 0x002e, 0x002f, 0x080f, 0x0810,
6971 0x0801, 0x0060, 0x0014, 0x0478
6972 };
6973 struct bwn_phy *phy = &mac->mac_phy;
6974 int i, phy6_idx = 0;
6975 uint16_t save_rf[SAVE_RF_MAX];
6976 uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
6977 uint16_t save_phy6[SAVE_PHY6_MAX];
6978 int16_t nrssi;
6979 uint16_t saved = 0xffff;
6980
6981 for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6982 save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
6983 for (i = 0; i < SAVE_RF_MAX; ++i)
6984 save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
6985
6986 BWN_PHY_MASK(mac, 0x0429, 0x7fff);
6987 BWN_PHY_SETMASK(mac, 0x0001, 0x3fff, 0x4000);
6988 BWN_PHY_SET(mac, 0x0811, 0x000c);
6989 BWN_PHY_SETMASK(mac, 0x0812, 0xfff3, 0x0004);
6990 BWN_PHY_MASK(mac, 0x0802, ~(0x1 | 0x2));
6991 if (phy->rev >= 6) {
6992 for (i = 0; i < SAVE_PHY6_MAX; ++i)
6993 save_phy6[i] = BWN_PHY_READ(mac, save_phy6_regs[i]);
6994
6995 BWN_PHY_WRITE(mac, 0x002e, 0);
6996 BWN_PHY_WRITE(mac, 0x002f, 0);
6997 BWN_PHY_WRITE(mac, 0x080f, 0);
6998 BWN_PHY_WRITE(mac, 0x0810, 0);
6999 BWN_PHY_SET(mac, 0x0478, 0x0100);
7000 BWN_PHY_SET(mac, 0x0801, 0x0040);
7001 BWN_PHY_SET(mac, 0x0060, 0x0040);
7002 BWN_PHY_SET(mac, 0x0014, 0x0200);
7003 }
7004 BWN_RF_SET(mac, 0x007a, 0x0070);
7005 BWN_RF_SET(mac, 0x007a, 0x0080);
7006 DELAY(30);
7007
7008 nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
7009 if (nrssi >= 0x20)
7010 nrssi -= 0x40;
7011 if (nrssi == 31) {
7012 for (i = 7; i >= 4; i--) {
7013 BWN_RF_WRITE(mac, 0x007b, i);
7014 DELAY(20);
7015 nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) &
7016 0x003f);
7017 if (nrssi >= 0x20)
7018 nrssi -= 0x40;
7019 if (nrssi < 31 && saved == 0xffff)
7020 saved = i;
7021 }
7022 if (saved == 0xffff)
7023 saved = 4;
7024 } else {
7025 BWN_RF_MASK(mac, 0x007a, 0x007f);
7026 if (phy->rev != 1) {
7027 BWN_PHY_SET(mac, 0x0814, 0x0001);
7028 BWN_PHY_MASK(mac, 0x0815, 0xfffe);
7029 }
7030 BWN_PHY_SET(mac, 0x0811, 0x000c);
7031 BWN_PHY_SET(mac, 0x0812, 0x000c);
7032 BWN_PHY_SET(mac, 0x0811, 0x0030);
7033 BWN_PHY_SET(mac, 0x0812, 0x0030);
7034 BWN_PHY_WRITE(mac, 0x005a, 0x0480);
7035 BWN_PHY_WRITE(mac, 0x0059, 0x0810);
7036 BWN_PHY_WRITE(mac, 0x0058, 0x000d);
7037 if (phy->rev == 0)
7038 BWN_PHY_WRITE(mac, 0x0003, 0x0122);
7039 else
7040 BWN_PHY_SET(mac, 0x000a, 0x2000);
7041 if (phy->rev != 1) {
7042 BWN_PHY_SET(mac, 0x0814, 0x0004);
7043 BWN_PHY_MASK(mac, 0x0815, 0xfffb);
7044 }
7045 BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
7046 BWN_RF_SET(mac, 0x007a, 0x000f);
7047 bwn_set_all_gains(mac, 3, 0, 1);
7048 BWN_RF_SETMASK(mac, 0x0043, 0x00f0, 0x000f);
7049 DELAY(30);
7050 nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
7051 if (nrssi >= 0x20)
7052 nrssi -= 0x40;
7053 if (nrssi == -32) {
7054 for (i = 0; i < 4; i++) {
7055 BWN_RF_WRITE(mac, 0x007b, i);
7056 DELAY(20);
7057 nrssi = (int16_t)((BWN_PHY_READ(mac,
7058 0x047f) >> 8) & 0x003f);
7059 if (nrssi >= 0x20)
7060 nrssi -= 0x40;
7061 if (nrssi > -31 && saved == 0xffff)
7062 saved = i;
7063 }
7064 if (saved == 0xffff)
7065 saved = 3;
7066 } else
7067 saved = 0;
7068 }
7069 BWN_RF_WRITE(mac, 0x007b, saved);
7070
7071 /*
7072 * Restore saved RF/PHY registers
7073 */
7074 if (phy->rev >= 6) {
7075 for (phy6_idx = 0; phy6_idx < 4; ++phy6_idx) {
7076 BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
7077 save_phy6[phy6_idx]);
7078 }
7079 }
7080 if (phy->rev != 1) {
7081 for (i = 3; i < 5; i++)
7082 BWN_PHY_WRITE(mac, save_phy_comm_regs[i],
7083 save_phy_comm[i]);
7084 }
7085 for (i = 5; i < SAVE_PHY_COMM_MAX; i++)
7086 BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
7087
7088 for (i = SAVE_RF_MAX - 1; i >= 0; --i)
7089 BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
7090
7091 BWN_PHY_WRITE(mac, 0x0802, BWN_PHY_READ(mac, 0x0802) | 0x1 | 0x2);
7092 BWN_PHY_SET(mac, 0x0429, 0x8000);
7093 bwn_set_original_gains(mac);
7094 if (phy->rev >= 6) {
7095 for (; phy6_idx < SAVE_PHY6_MAX; ++phy6_idx) {
7096 BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
7097 save_phy6[phy6_idx]);
7098 }
7099 }
7100
7101 BWN_PHY_WRITE(mac, save_phy_comm_regs[0], save_phy_comm[0]);
7102 BWN_PHY_WRITE(mac, save_phy_comm_regs[2], save_phy_comm[2]);
7103 BWN_PHY_WRITE(mac, save_phy_comm_regs[1], save_phy_comm[1]);
7104}
7105
7106static void
7107bwn_set_all_gains(struct bwn_mac *mac, int16_t first, int16_t second,
7108 int16_t third)
7109{
7110 struct bwn_phy *phy = &mac->mac_phy;
7111 uint16_t i;
7112 uint16_t start = 0x08, end = 0x18;
7113 uint16_t tmp;
7114 uint16_t table;
7115
7116 if (phy->rev <= 1) {
7117 start = 0x10;
7118 end = 0x20;
7119 }
7120
7121 table = BWN_OFDMTAB_GAINX;
7122 if (phy->rev <= 1)
7123 table = BWN_OFDMTAB_GAINX_R1;
7124 for (i = 0; i < 4; i++)
7125 bwn_ofdmtab_write_2(mac, table, i, first);
7126
7127 for (i = start; i < end; i++)
7128 bwn_ofdmtab_write_2(mac, table, i, second);
7129
7130 if (third != -1) {
7131 tmp = ((uint16_t) third << 14) | ((uint16_t) third << 6);
7132 BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, tmp);
7133 BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, tmp);
7134 BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, tmp);
7135 }
7136 bwn_dummy_transmission(mac, 0, 1);
7137}
7138
7139static void
7140bwn_set_original_gains(struct bwn_mac *mac)
7141{
7142 struct bwn_phy *phy = &mac->mac_phy;
7143 uint16_t i, tmp;
7144 uint16_t table;
7145 uint16_t start = 0x0008, end = 0x0018;
7146
7147 if (phy->rev <= 1) {
7148 start = 0x0010;
7149 end = 0x0020;
7150 }
7151
7152 table = BWN_OFDMTAB_GAINX;
7153 if (phy->rev <= 1)
7154 table = BWN_OFDMTAB_GAINX_R1;
7155 for (i = 0; i < 4; i++) {
7156 tmp = (i & 0xfffc);
7157 tmp |= (i & 0x0001) << 1;
7158 tmp |= (i & 0x0002) >> 1;
7159
7160 bwn_ofdmtab_write_2(mac, table, i, tmp);
7161 }
7162
7163 for (i = start; i < end; i++)
7164 bwn_ofdmtab_write_2(mac, table, i, i - start);
7165
7166 BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, 0x4040);
7167 BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, 0x4040);
7168 BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, 0x4000);
7169 bwn_dummy_transmission(mac, 0, 1);
7170}
7171
7172static void
7173bwn_phy_hwpctl_init(struct bwn_mac *mac)
7174{
7175 struct bwn_phy *phy = &mac->mac_phy;
7176 struct bwn_phy_g *pg = &phy->phy_g;
7177 struct bwn_rfatt old_rfatt, rfatt;
7178 struct bwn_bbatt old_bbatt, bbatt;
7179 struct bwn_softc *sc = mac->mac_sc;
7180 uint8_t old_txctl = 0;
7181
7182 KASSERT(phy->type == BWN_PHYTYPE_G,
7183 ("%s:%d: fail", __func__, __LINE__));
7184
7185 if ((siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM) &&
7186 (siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306))
7187 return;
7188
7189 BWN_PHY_WRITE(mac, 0x0028, 0x8018);
7190
7191 BWN_WRITE_2(mac, BWN_PHY0, BWN_READ_2(mac, BWN_PHY0) & 0xffdf);
7192
7193 if (!phy->gmode)
7194 return;
7195 bwn_hwpctl_early_init(mac);
7196 if (pg->pg_curtssi == 0) {
7197 if (phy->rf_ver == 0x2050 && phy->analog == 0) {
7198 BWN_RF_SETMASK(mac, 0x0076, 0x00f7, 0x0084);
7199 } else {
7200 memcpy(&old_rfatt, &pg->pg_rfatt, sizeof(old_rfatt));
7201 memcpy(&old_bbatt, &pg->pg_bbatt, sizeof(old_bbatt));
7202 old_txctl = pg->pg_txctl;
7203
7204 bbatt.att = 11;
7205 if (phy->rf_rev == 8) {
7206 rfatt.att = 15;
7207 rfatt.padmix = 1;
7208 } else {
7209 rfatt.att = 9;
7210 rfatt.padmix = 0;
7211 }
7212 bwn_phy_g_set_txpwr_sub(mac, &bbatt, &rfatt, 0);
7213 }
7214 bwn_dummy_transmission(mac, 0, 1);
7215 pg->pg_curtssi = BWN_PHY_READ(mac, BWN_PHY_TSSI);
7216 if (phy->rf_ver == 0x2050 && phy->analog == 0)
7217 BWN_RF_MASK(mac, 0x0076, 0xff7b);
7218 else
7219 bwn_phy_g_set_txpwr_sub(mac, &old_bbatt,
7220 &old_rfatt, old_txctl);
7221 }
7222 bwn_hwpctl_init_gphy(mac);
7223
7224 /* clear TSSI */
7225 bwn_shm_write_2(mac, BWN_SHARED, 0x0058, 0x7f7f);
7226 bwn_shm_write_2(mac, BWN_SHARED, 0x005a, 0x7f7f);
7227 bwn_shm_write_2(mac, BWN_SHARED, 0x0070, 0x7f7f);
7228 bwn_shm_write_2(mac, BWN_SHARED, 0x0072, 0x7f7f);
7229}
7230
7231static void
7232bwn_hwpctl_early_init(struct bwn_mac *mac)
7233{
7234 struct bwn_phy *phy = &mac->mac_phy;
7235
7236 if (!bwn_has_hwpctl(mac)) {
7237 BWN_PHY_WRITE(mac, 0x047a, 0xc111);
7238 return;
7239 }
7240
7241 BWN_PHY_MASK(mac, 0x0036, 0xfeff);
7242 BWN_PHY_WRITE(mac, 0x002f, 0x0202);
7243 BWN_PHY_SET(mac, 0x047c, 0x0002);
7244 BWN_PHY_SET(mac, 0x047a, 0xf000);
7245 if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
7246 BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7247 BWN_PHY_SET(mac, 0x005d, 0x8000);
7248 BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7249 BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7250 BWN_PHY_SET(mac, 0x0036, 0x0400);
7251 } else {
7252 BWN_PHY_SET(mac, 0x0036, 0x0200);
7253 BWN_PHY_SET(mac, 0x0036, 0x0400);
7254 BWN_PHY_MASK(mac, 0x005d, 0x7fff);
7255 BWN_PHY_MASK(mac, 0x004f, 0xfffe);
7256 BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7257 BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7258 BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7259 }
7260}
7261
7262static void
7263bwn_hwpctl_init_gphy(struct bwn_mac *mac)
7264{
7265 struct bwn_phy *phy = &mac->mac_phy;
7266 struct bwn_phy_g *pg = &phy->phy_g;
7267 struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7268 int i;
7269 uint16_t nr_written = 0, tmp, value;
7270 uint8_t rf, bb;
7271
7272 if (!bwn_has_hwpctl(mac)) {
7273 bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_HW_POWERCTL);
7274 return;
7275 }
7276
7277 BWN_PHY_SETMASK(mac, 0x0036, 0xffc0,
7278 (pg->pg_idletssi - pg->pg_curtssi));
7279 BWN_PHY_SETMASK(mac, 0x0478, 0xff00,
7280 (pg->pg_idletssi - pg->pg_curtssi));
7281
7282 for (i = 0; i < 32; i++)
7283 bwn_ofdmtab_write_2(mac, 0x3c20, i, pg->pg_tssi2dbm[i]);
7284 for (i = 32; i < 64; i++)
7285 bwn_ofdmtab_write_2(mac, 0x3c00, i - 32, pg->pg_tssi2dbm[i]);
7286 for (i = 0; i < 64; i += 2) {
7287 value = (uint16_t) pg->pg_tssi2dbm[i];
7288 value |= ((uint16_t) pg->pg_tssi2dbm[i + 1]) << 8;
7289 BWN_PHY_WRITE(mac, 0x380 + (i / 2), value);
7290 }
7291
7292 for (rf = 0; rf < lo->rfatt.len; rf++) {
7293 for (bb = 0; bb < lo->bbatt.len; bb++) {
7294 if (nr_written >= 0x40)
7295 return;
7296 tmp = lo->bbatt.array[bb].att;
7297 tmp <<= 8;
7298 if (phy->rf_rev == 8)
7299 tmp |= 0x50;
7300 else
7301 tmp |= 0x40;
7302 tmp |= lo->rfatt.array[rf].att;
7303 BWN_PHY_WRITE(mac, 0x3c0 + nr_written, tmp);
7304 nr_written++;
7305 }
7306 }
7307
7308 BWN_PHY_MASK(mac, 0x0060, 0xffbf);
7309 BWN_PHY_WRITE(mac, 0x0014, 0x0000);
7310
7311 KASSERT(phy->rev >= 6, ("%s:%d: fail", __func__, __LINE__));
7312 BWN_PHY_SET(mac, 0x0478, 0x0800);
7313 BWN_PHY_MASK(mac, 0x0478, 0xfeff);
7314 BWN_PHY_MASK(mac, 0x0801, 0xffbf);
7315
7316 bwn_phy_g_dc_lookup_init(mac, 1);
7317 bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_HW_POWERCTL);
7318}
7319
7320static void
7321bwn_phy_g_switch_chan(struct bwn_mac *mac, int channel, uint8_t spu)
7322{
7323 struct bwn_softc *sc = mac->mac_sc;
7324
7325 if (spu != 0)
7326 bwn_spu_workaround(mac, channel);
7327
7328 BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7329
7330 if (channel == 14) {
7331 if (siba_sprom_get_ccode(sc->sc_dev) == SIBA_CCODE_JAPAN)
7332 bwn_hf_write(mac,
7333 bwn_hf_read(mac) & ~BWN_HF_JAPAN_CHAN14_OFF);
7334 else
7335 bwn_hf_write(mac,
7336 bwn_hf_read(mac) | BWN_HF_JAPAN_CHAN14_OFF);
7337 BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7338 BWN_READ_2(mac, BWN_CHANNEL_EXT) | (1 << 11));
7339 return;
7340 }
7341
7342 BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7343 BWN_READ_2(mac, BWN_CHANNEL_EXT) & 0xf7bf);
7344}
7345
7346static uint16_t
7347bwn_phy_g_chan2freq(uint8_t channel)
7348{
7349 static const uint8_t bwn_phy_g_rf_channels[] = BWN_PHY_G_RF_CHANNELS;
7350
7351 KASSERT(channel >= 1 && channel <= 14,
7352 ("%s:%d: fail", __func__, __LINE__));
7353
7354 return (bwn_phy_g_rf_channels[channel - 1]);
7355}
7356
7357static void
7358bwn_phy_g_set_txpwr_sub(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
7359 const struct bwn_rfatt *rfatt, uint8_t txctl)
7360{
7361 struct bwn_phy *phy = &mac->mac_phy;
7362 struct bwn_phy_g *pg = &phy->phy_g;
7363 struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7364 uint16_t bb, rf;
7365 uint16_t tx_bias, tx_magn;
7366
7367 bb = bbatt->att;
7368 rf = rfatt->att;
7369 tx_bias = lo->tx_bias;
7370 tx_magn = lo->tx_magn;
7371 if (tx_bias == 0xff)
7372 tx_bias = 0;
7373
7374 pg->pg_txctl = txctl;
7375 memmove(&pg->pg_rfatt, rfatt, sizeof(*rfatt));
7376 pg->pg_rfatt.padmix = (txctl & BWN_TXCTL_TXMIX) ? 1 : 0;
7377 memmove(&pg->pg_bbatt, bbatt, sizeof(*bbatt));
7378 bwn_phy_g_set_bbatt(mac, bb);
7379 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RADIO_ATT, rf);
7380 if (phy->rf_ver == 0x2050 && phy->rf_rev == 8)
7381 BWN_RF_WRITE(mac, 0x43, (rf & 0x000f) | (txctl & 0x0070));
7382 else {
7383 BWN_RF_SETMASK(mac, 0x43, 0xfff0, (rf & 0x000f));
7384 BWN_RF_SETMASK(mac, 0x52, ~0x0070, (txctl & 0x0070));
7385 }
7386 if (BWN_HAS_TXMAG(phy))
7387 BWN_RF_WRITE(mac, 0x52, tx_magn | tx_bias);
7388 else
7389 BWN_RF_SETMASK(mac, 0x52, 0xfff0, (tx_bias & 0x000f));
7390 bwn_lo_g_adjust(mac);
7391}
7392
7393static void
7394bwn_phy_g_set_bbatt(struct bwn_mac *mac,
7395 uint16_t bbatt)
7396{
7397 struct bwn_phy *phy = &mac->mac_phy;
7398
7399 if (phy->analog == 0) {
7400 BWN_WRITE_2(mac, BWN_PHY0,
7401 (BWN_READ_2(mac, BWN_PHY0) & 0xfff0) | bbatt);
7402 return;
7403 }
7404 if (phy->analog > 1) {
7405 BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xffc3, bbatt << 2);
7406 return;
7407 }
7408 BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xff87, bbatt << 3);
7409}
7410
7411static uint16_t
7412bwn_rf_2050_rfoverval(struct bwn_mac *mac, uint16_t reg, uint32_t lpd)
7413{
7414 struct bwn_phy *phy = &mac->mac_phy;
7415 struct bwn_phy_g *pg = &phy->phy_g;
7416 struct bwn_softc *sc = mac->mac_sc;
7417 int max_lb_gain;
7418 uint16_t extlna;
7419 uint16_t i;
7420
7421 if (phy->gmode == 0)
7422 return (0);
7423
7424 if (BWN_HAS_LOOPBACK(phy)) {
7425 max_lb_gain = pg->pg_max_lb_gain;
7426 max_lb_gain += (phy->rf_rev == 8) ? 0x3e : 0x26;
7427 if (max_lb_gain >= 0x46) {
7428 extlna = 0x3000;
7429 max_lb_gain -= 0x46;
7430 } else if (max_lb_gain >= 0x3a) {
7431 extlna = 0x1000;
7432 max_lb_gain -= 0x3a;
7433 } else if (max_lb_gain >= 0x2e) {
7434 extlna = 0x2000;
7435 max_lb_gain -= 0x2e;
7436 } else {
7437 extlna = 0;
7438 max_lb_gain -= 0x10;
7439 }
7440
7441 for (i = 0; i < 16; i++) {
7442 max_lb_gain -= (i * 6);
7443 if (max_lb_gain < 6)
7444 break;
7445 }
7446
7447 if ((phy->rev < 7) ||
7448 !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA)) {
7449 if (reg == BWN_PHY_RFOVER) {
7450 return (0x1b3);
7451 } else if (reg == BWN_PHY_RFOVERVAL) {
7452 extlna |= (i << 8);
7453 switch (lpd) {
7454 case BWN_LPD(0, 1, 1):
7455 return (0x0f92);
7456 case BWN_LPD(0, 0, 1):
7457 case BWN_LPD(1, 0, 1):
7458 return (0x0092 | extlna);
7459 case BWN_LPD(1, 0, 0):
7460 return (0x0093 | extlna);
7461 }
7462 KASSERT(0 == 1,
7463 ("%s:%d: fail", __func__, __LINE__));
7464 }
7465 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7466 } else {
7467 if (reg == BWN_PHY_RFOVER)
7468 return (0x9b3);
7469 if (reg == BWN_PHY_RFOVERVAL) {
7470 if (extlna)
7471 extlna |= 0x8000;
7472 extlna |= (i << 8);
7473 switch (lpd) {
7474 case BWN_LPD(0, 1, 1):
7475 return (0x8f92);
7476 case BWN_LPD(0, 0, 1):
7477 return (0x8092 | extlna);
7478 case BWN_LPD(1, 0, 1):
7479 return (0x2092 | extlna);
7480 case BWN_LPD(1, 0, 0):
7481 return (0x2093 | extlna);
7482 }
7483 KASSERT(0 == 1,
7484 ("%s:%d: fail", __func__, __LINE__));
7485 }
7486 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7487 }
7488 return (0);
7489 }
7490
7491 if ((phy->rev < 7) ||
7492 !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA)) {
7493 if (reg == BWN_PHY_RFOVER) {
7494 return (0x1b3);
7495 } else if (reg == BWN_PHY_RFOVERVAL) {
7496 switch (lpd) {
7497 case BWN_LPD(0, 1, 1):
7498 return (0x0fb2);
7499 case BWN_LPD(0, 0, 1):
7500 return (0x00b2);
7501 case BWN_LPD(1, 0, 1):
7502 return (0x30b2);
7503 case BWN_LPD(1, 0, 0):
7504 return (0x30b3);
7505 }
7506 KASSERT(0 == 1,
7507 ("%s:%d: fail", __func__, __LINE__));
7508 }
7509 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7510 } else {
7511 if (reg == BWN_PHY_RFOVER) {
7512 return (0x9b3);
7513 } else if (reg == BWN_PHY_RFOVERVAL) {
7514 switch (lpd) {
7515 case BWN_LPD(0, 1, 1):
7516 return (0x8fb2);
7517 case BWN_LPD(0, 0, 1):
7518 return (0x80b2);
7519 case BWN_LPD(1, 0, 1):
7520 return (0x20b2);
7521 case BWN_LPD(1, 0, 0):
7522 return (0x20b3);
7523 }
7524 KASSERT(0 == 1,
7525 ("%s:%d: fail", __func__, __LINE__));
7526 }
7527 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7528 }
7529 return (0);
7530}
7531
7532static void
7533bwn_spu_workaround(struct bwn_mac *mac, uint8_t channel)
7534{
7535
7536 if (mac->mac_phy.rf_ver != 0x2050 || mac->mac_phy.rf_rev >= 6)
7537 return;
7538 BWN_WRITE_2(mac, BWN_CHANNEL, (channel <= 10) ?
7539 bwn_phy_g_chan2freq(channel + 4) : bwn_phy_g_chan2freq(1));
7540 DELAY(1000);
7541 BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7542}
7543
7544static int
7545bwn_fw_gets(struct bwn_mac *mac, enum bwn_fwtype type)
7546{
7547 struct bwn_softc *sc = mac->mac_sc;
7548 struct bwn_fw *fw = &mac->mac_fw;
7549 const uint8_t rev = siba_get_revid(sc->sc_dev);
7550 const char *filename;
7551 uint32_t high;
7552 int error;
7553
7554 /* microcode */
7555 if (rev >= 5 && rev <= 10)
7556 filename = "ucode5";
7557 else if (rev >= 11 && rev <= 12)
7558 filename = "ucode11";
7559 else if (rev == 13)
7560 filename = "ucode13";
7561 else if (rev == 14)
7562 filename = "ucode14";
7563 else if (rev >= 15)
7564 filename = "ucode15";
7565 else {
7566 device_printf(sc->sc_dev, "no ucode for rev %d\n", rev);
7567 bwn_release_firmware(mac);
7568 return (EOPNOTSUPP);
7569 }
7570 error = bwn_fw_get(mac, type, filename, &fw->ucode);
7571 if (error) {
7572 bwn_release_firmware(mac);
7573 return (error);
7574 }
7575
7576 /* PCM */
7577 KASSERT(fw->no_pcmfile == 0, ("%s:%d fail", __func__, __LINE__));
7578 if (rev >= 5 && rev <= 10) {
7579 error = bwn_fw_get(mac, type, "pcm5", &fw->pcm);
7580 if (error == ENOENT)
7581 fw->no_pcmfile = 1;
7582 else if (error) {
7583 bwn_release_firmware(mac);
7584 return (error);
7585 }
7586 } else if (rev < 11) {
7587 device_printf(sc->sc_dev, "no PCM for rev %d\n", rev);
7588 return (EOPNOTSUPP);
7589 }
7590
7591 /* initvals */
7592 high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH);
7593 switch (mac->mac_phy.type) {
7594 case BWN_PHYTYPE_A:
7595 if (rev < 5 || rev > 10)
7596 goto fail1;
7597 if (high & BWN_TGSHIGH_HAVE_2GHZ)
7598 filename = "a0g1initvals5";
7599 else
7600 filename = "a0g0initvals5";
7601 break;
7602 case BWN_PHYTYPE_G:
7603 if (rev >= 5 && rev <= 10)
7604 filename = "b0g0initvals5";
7605 else if (rev >= 13)
7606 filename = "b0g0initvals13";
7607 else
7608 goto fail1;
7609 break;
7610 case BWN_PHYTYPE_LP:
7611 if (rev == 13)
7612 filename = "lp0initvals13";
7613 else if (rev == 14)
7614 filename = "lp0initvals14";
7615 else if (rev >= 15)
7616 filename = "lp0initvals15";
7617 else
7618 goto fail1;
7619 break;
7620 case BWN_PHYTYPE_N:
7621 if (rev >= 11 && rev <= 12)
7622 filename = "n0initvals11";
7623 else
7624 goto fail1;
7625 break;
7626 default:
7627 goto fail1;
7628 }
7629 error = bwn_fw_get(mac, type, filename, &fw->initvals);
7630 if (error) {
7631 bwn_release_firmware(mac);
7632 return (error);
7633 }
7634
7635 /* bandswitch initvals */
7636 switch (mac->mac_phy.type) {
7637 case BWN_PHYTYPE_A:
7638 if (rev >= 5 && rev <= 10) {
7639 if (high & BWN_TGSHIGH_HAVE_2GHZ)
7640 filename = "a0g1bsinitvals5";
7641 else
7642 filename = "a0g0bsinitvals5";
7643 } else if (rev >= 11)
7644 filename = NULL;
7645 else
7646 goto fail1;
7647 break;
7648 case BWN_PHYTYPE_G:
7649 if (rev >= 5 && rev <= 10)
7650 filename = "b0g0bsinitvals5";
7651 else if (rev >= 11)
7652 filename = NULL;
7653 else
7654 goto fail1;
7655 break;
7656 case BWN_PHYTYPE_LP:
7657 if (rev == 13)
7658 filename = "lp0bsinitvals13";
7659 else if (rev == 14)
7660 filename = "lp0bsinitvals14";
7661 else if (rev >= 15)
7662 filename = "lp0bsinitvals15";
7663 else
7664 goto fail1;
7665 break;
7666 case BWN_PHYTYPE_N:
7667 if (rev >= 11 && rev <= 12)
7668 filename = "n0bsinitvals11";
7669 else
7670 goto fail1;
7671 break;
7672 default:
7673 goto fail1;
7674 }
7675 error = bwn_fw_get(mac, type, filename, &fw->initvals_band);
7676 if (error) {
7677 bwn_release_firmware(mac);
7678 return (error);
7679 }
7680 return (0);
7681fail1:
7682 device_printf(sc->sc_dev, "no INITVALS for rev %d\n", rev);
7683 bwn_release_firmware(mac);
7684 return (EOPNOTSUPP);
7685}
7686
7687static int
7688bwn_fw_get(struct bwn_mac *mac, enum bwn_fwtype type,
7689 const char *name, struct bwn_fwfile *bfw)
7690{
7691 const struct bwn_fwhdr *hdr;
7692 struct bwn_softc *sc = mac->mac_sc;
7693 const struct firmware *fw;
7694 char namebuf[64];
7695
7696 if (name == NULL) {
7697 bwn_do_release_fw(bfw);
7698 return (0);
7699 }
7700 if (bfw->filename != NULL) {
7701 if (bfw->type == type && (strcmp(bfw->filename, name) == 0))
7702 return (0);
7703 bwn_do_release_fw(bfw);
7704 }
7705
7706 snprintf(namebuf, sizeof(namebuf), "bwn%s_v4_%s%s",
7707 (type == BWN_FWTYPE_OPENSOURCE) ? "-open" : "",
7708 (mac->mac_phy.type == BWN_PHYTYPE_LP) ? "lp_" : "", name);
7709 /* XXX Sleeping on "fwload" with the non-sleepable locks held */
7710 fw = firmware_get(namebuf);
7711 if (fw == NULL) {
7712 device_printf(sc->sc_dev, "the fw file(%s) not found\n",
7713 namebuf);
7714 return (ENOENT);
7715 }
7716 if (fw->datasize < sizeof(struct bwn_fwhdr))
7717 goto fail;
7718 hdr = (const struct bwn_fwhdr *)(fw->data);
7719 switch (hdr->type) {
7720 case BWN_FWTYPE_UCODE:
7721 case BWN_FWTYPE_PCM:
7722 if (be32toh(hdr->size) !=
7723 (fw->datasize - sizeof(struct bwn_fwhdr)))
7724 goto fail;
7725 /* FALLTHROUGH */
7726 case BWN_FWTYPE_IV:
7727 if (hdr->ver != 1)
7728 goto fail;
7729 break;
7730 default:
7731 goto fail;
7732 }
7733 bfw->filename = name;
7734 bfw->fw = fw;
7735 bfw->type = type;
7736 return (0);
7737fail:
7738 device_printf(sc->sc_dev, "the fw file(%s) format error\n", namebuf);
7739 if (fw != NULL)
7740 firmware_put(fw, FIRMWARE_UNLOAD);
7741 return (EPROTO);
7742}
7743
7744static void
7745bwn_release_firmware(struct bwn_mac *mac)
7746{
7747
7748 bwn_do_release_fw(&mac->mac_fw.ucode);
7749 bwn_do_release_fw(&mac->mac_fw.pcm);
7750 bwn_do_release_fw(&mac->mac_fw.initvals);
7751 bwn_do_release_fw(&mac->mac_fw.initvals_band);
7752}
7753
7754static void
7755bwn_do_release_fw(struct bwn_fwfile *bfw)
7756{
7757
7758 if (bfw->fw != NULL)
7759 firmware_put(bfw->fw, FIRMWARE_UNLOAD);
7760 bfw->fw = NULL;
7761 bfw->filename = NULL;
7762}
7763
7764static int
7765bwn_fw_loaducode(struct bwn_mac *mac)
7766{
7767#define GETFWOFFSET(fwp, offset) \
7768 ((const uint32_t *)((const char *)fwp.fw->data + offset))
7769#define GETFWSIZE(fwp, offset) \
7770 ((fwp.fw->datasize - offset) / sizeof(uint32_t))
7771 struct bwn_softc *sc = mac->mac_sc;
7772 const uint32_t *data;
7773 unsigned int i;
7774 uint32_t ctl;
7775 uint16_t date, fwcaps, time;
7776 int error = 0;
7777
7778 ctl = BWN_READ_4(mac, BWN_MACCTL);
7779 ctl |= BWN_MACCTL_MCODE_JMP0;
7780 KASSERT(!(ctl & BWN_MACCTL_MCODE_RUN), ("%s:%d: fail", __func__,
7781 __LINE__));
7782 BWN_WRITE_4(mac, BWN_MACCTL, ctl);
7783 for (i = 0; i < 64; i++)
7784 bwn_shm_write_2(mac, BWN_SCRATCH, i, 0);
7785 for (i = 0; i < 4096; i += 2)
7786 bwn_shm_write_2(mac, BWN_SHARED, i, 0);
7787
7788 data = GETFWOFFSET(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7789 bwn_shm_ctlword(mac, BWN_UCODE | BWN_SHARED_AUTOINC, 0x0000);
7790 for (i = 0; i < GETFWSIZE(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7791 i++) {
7792 BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7793 DELAY(10);
7794 }
7795
7796 if (mac->mac_fw.pcm.fw) {
7797 data = GETFWOFFSET(mac->mac_fw.pcm, sizeof(struct bwn_fwhdr));
7798 bwn_shm_ctlword(mac, BWN_HW, 0x01ea);
7799 BWN_WRITE_4(mac, BWN_SHM_DATA, 0x00004000);
7800 bwn_shm_ctlword(mac, BWN_HW, 0x01eb);
7801 for (i = 0; i < GETFWSIZE(mac->mac_fw.pcm,
7802 sizeof(struct bwn_fwhdr)); i++) {
7803 BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7804 DELAY(10);
7805 }
7806 }
7807
7808 BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_ALL);
7809 BWN_WRITE_4(mac, BWN_MACCTL,
7810 (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_JMP0) |
7811 BWN_MACCTL_MCODE_RUN);
7812
7813 for (i = 0; i < 21; i++) {
7814 if (BWN_READ_4(mac, BWN_INTR_REASON) == BWN_INTR_MAC_SUSPENDED)
7815 break;
7816 if (i >= 20) {
7817 device_printf(sc->sc_dev, "ucode timeout\n");
7818 error = ENXIO;
7819 goto error;
7820 }
7821 DELAY(50000);
7822 }
7823 BWN_READ_4(mac, BWN_INTR_REASON);
7824
7825 mac->mac_fw.rev = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_REV);
7826 if (mac->mac_fw.rev <= 0x128) {
7827 device_printf(sc->sc_dev, "the firmware is too old\n");
7828 error = EOPNOTSUPP;
7829 goto error;
7830 }
7831 mac->mac_fw.patch = bwn_shm_read_2(mac, BWN_SHARED,
7832 BWN_SHARED_UCODE_PATCH);
7833 date = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_DATE);
7834 mac->mac_fw.opensource = (date == 0xffff);
7835 if (bwn_wme != 0)
7836 mac->mac_flags |= BWN_MAC_FLAG_WME;
7837 mac->mac_flags |= BWN_MAC_FLAG_HWCRYPTO;
7838
7839 time = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_TIME);
7840 if (mac->mac_fw.opensource == 0) {
7841 device_printf(sc->sc_dev,
7842 "firmware version (rev %u patch %u date %#x time %#x)\n",
7843 mac->mac_fw.rev, mac->mac_fw.patch, date, time);
7844 if (mac->mac_fw.no_pcmfile)
7845 device_printf(sc->sc_dev,
7846 "no HW crypto acceleration due to pcm5\n");
7847 } else {
7848 mac->mac_fw.patch = time;
7849 fwcaps = bwn_fwcaps_read(mac);
7850 if (!(fwcaps & BWN_FWCAPS_HWCRYPTO) || mac->mac_fw.no_pcmfile) {
7851 device_printf(sc->sc_dev,
7852 "disabling HW crypto acceleration\n");
7853 mac->mac_flags &= ~BWN_MAC_FLAG_HWCRYPTO;
7854 }
7855 if (!(fwcaps & BWN_FWCAPS_WME)) {
7856 device_printf(sc->sc_dev, "disabling WME support\n");
7857 mac->mac_flags &= ~BWN_MAC_FLAG_WME;
7858 }
7859 }
7860
7861 if (BWN_ISOLDFMT(mac))
7862 device_printf(sc->sc_dev, "using old firmware image\n");
7863
7864 return (0);
7865
7866error:
7867 BWN_WRITE_4(mac, BWN_MACCTL,
7868 (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_RUN) |
7869 BWN_MACCTL_MCODE_JMP0);
7870
7871 return (error);
7872#undef GETFWSIZE
7873#undef GETFWOFFSET
7874}
7875
7876/* OpenFirmware only */
7877static uint16_t
7878bwn_fwcaps_read(struct bwn_mac *mac)
7879{
7880
7881 KASSERT(mac->mac_fw.opensource == 1,
7882 ("%s:%d: fail", __func__, __LINE__));
7883 return (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_FWCAPS));
7884}
7885
7886static int
7887bwn_fwinitvals_write(struct bwn_mac *mac, const struct bwn_fwinitvals *ivals,
7888 size_t count, size_t array_size)
7889{
7890#define GET_NEXTIV16(iv) \
7891 ((const struct bwn_fwinitvals *)((const uint8_t *)(iv) + \
7892 sizeof(uint16_t) + sizeof(uint16_t)))
7893#define GET_NEXTIV32(iv) \
7894 ((const struct bwn_fwinitvals *)((const uint8_t *)(iv) + \
7895 sizeof(uint16_t) + sizeof(uint32_t)))
7896 struct bwn_softc *sc = mac->mac_sc;
7897 const struct bwn_fwinitvals *iv;
7898 uint16_t offset;
7899 size_t i;
7900 uint8_t bit32;
7901
7902 KASSERT(sizeof(struct bwn_fwinitvals) == 6,
7903 ("%s:%d: fail", __func__, __LINE__));
7904 iv = ivals;
7905 for (i = 0; i < count; i++) {
7906 if (array_size < sizeof(iv->offset_size))
7907 goto fail;
7908 array_size -= sizeof(iv->offset_size);
7909 offset = be16toh(iv->offset_size);
7910 bit32 = (offset & BWN_FWINITVALS_32BIT) ? 1 : 0;
7911 offset &= BWN_FWINITVALS_OFFSET_MASK;
7912 if (offset >= 0x1000)
7913 goto fail;
7914 if (bit32) {
7915 if (array_size < sizeof(iv->data.d32))
7916 goto fail;
7917 array_size -= sizeof(iv->data.d32);
7918 BWN_WRITE_4(mac, offset, be32toh(iv->data.d32));
7919 iv = GET_NEXTIV32(iv);
7920 } else {
7921
7922 if (array_size < sizeof(iv->data.d16))
7923 goto fail;
7924 array_size -= sizeof(iv->data.d16);
7925 BWN_WRITE_2(mac, offset, be16toh(iv->data.d16));
7926
7927 iv = GET_NEXTIV16(iv);
7928 }
7929 }
7930 if (array_size != 0)
7931 goto fail;
7932 return (0);
7933fail:
7934 device_printf(sc->sc_dev, "initvals: invalid format\n");
7935 return (EPROTO);
7936#undef GET_NEXTIV16
7937#undef GET_NEXTIV32
7938}
7939
7940static int
7941bwn_switch_channel(struct bwn_mac *mac, int chan)
7942{
7943 struct bwn_phy *phy = &(mac->mac_phy);
7944 struct bwn_softc *sc = mac->mac_sc;
7945 struct ifnet *ifp = sc->sc_ifp;
7946 struct ieee80211com *ic = ifp->if_l2com;
7947 uint16_t channelcookie, savedcookie;
7948 int error;
7949
7950 if (chan == 0xffff)
7951 chan = phy->get_default_chan(mac);
7952
7953 channelcookie = chan;
7954 if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan))
7955 channelcookie |= 0x100;
7956 savedcookie = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_CHAN);
7957 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, channelcookie);
7958 error = phy->switch_channel(mac, chan);
7959 if (error)
7960 goto fail;
7961
7962 mac->mac_phy.chan = chan;
7963 DELAY(8000);
7964 return (0);
7965fail:
7966 device_printf(sc->sc_dev, "failed to switch channel\n");
7967 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, savedcookie);
7968 return (error);
7969}
7970
7971static uint16_t
7972bwn_ant2phy(int antenna)
7973{
7974
7975 switch (antenna) {
7976 case BWN_ANT0:
7977 return (BWN_TX_PHY_ANT0);
7978 case BWN_ANT1:
7979 return (BWN_TX_PHY_ANT1);
7980 case BWN_ANT2:
7981 return (BWN_TX_PHY_ANT2);
7982 case BWN_ANT3:
7983 return (BWN_TX_PHY_ANT3);
7984 case BWN_ANTAUTO:
7985 return (BWN_TX_PHY_ANT01AUTO);
7986 }
7987 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7988 return (0);
7989}
7990
7991static void
7992bwn_wme_load(struct bwn_mac *mac)
7993{
7994 struct bwn_softc *sc = mac->mac_sc;
7995 int i;
7996
7997 KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
7998 ("%s:%d: fail", __func__, __LINE__));
7999
8000 bwn_mac_suspend(mac);
8001 for (i = 0; i < N(sc->sc_wmeParams); i++)
8002 bwn_wme_loadparams(mac, &(sc->sc_wmeParams[i]),
8003 bwn_wme_shm_offsets[i]);
8004 bwn_mac_enable(mac);
8005}
8006
8007static void
8008bwn_wme_loadparams(struct bwn_mac *mac,
8009 const struct wmeParams *p, uint16_t shm_offset)
8010{
8011#define SM(_v, _f) (((_v) << _f##_S) & _f)
8012 struct bwn_softc *sc = mac->mac_sc;
8013 uint16_t params[BWN_NR_WMEPARAMS];
8014 int slot, tmp;
8015 unsigned int i;
8016
8017 slot = BWN_READ_2(mac, BWN_RNG) &
8018 SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8019
8020 memset(¶ms, 0, sizeof(params));
8021
8022 DPRINTF(sc, BWN_DEBUG_WME, "wmep_txopLimit %d wmep_logcwmin %d "
8023 "wmep_logcwmax %d wmep_aifsn %d\n", p->wmep_txopLimit,
8024 p->wmep_logcwmin, p->wmep_logcwmax, p->wmep_aifsn);
8025
8026 params[BWN_WMEPARAM_TXOP] = p->wmep_txopLimit * 32;
8027 params[BWN_WMEPARAM_CWMIN] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8028 params[BWN_WMEPARAM_CWMAX] = SM(p->wmep_logcwmax, WME_PARAM_LOGCWMAX);
8029 params[BWN_WMEPARAM_CWCUR] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8030 params[BWN_WMEPARAM_AIFS] = p->wmep_aifsn;
8031 params[BWN_WMEPARAM_BSLOTS] = slot;
8032 params[BWN_WMEPARAM_REGGAP] = slot + p->wmep_aifsn;
8033
8034 for (i = 0; i < N(params); i++) {
8035 if (i == BWN_WMEPARAM_STATUS) {
8036 tmp = bwn_shm_read_2(mac, BWN_SHARED,
8037 shm_offset + (i * 2));
8038 tmp |= 0x100;
8039 bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
8040 tmp);
8041 } else {
8042 bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
8043 params[i]);
8044 }
8045 }
8046}
8047
8048static void
8049bwn_mac_write_bssid(struct bwn_mac *mac)
8050{
8051 struct bwn_softc *sc = mac->mac_sc;
8052 uint32_t tmp;
8053 int i;
8054 uint8_t mac_bssid[IEEE80211_ADDR_LEN * 2];
8055
8056 bwn_mac_setfilter(mac, BWN_MACFILTER_BSSID, sc->sc_bssid);
8057 memcpy(mac_bssid, sc->sc_macaddr, IEEE80211_ADDR_LEN);
8058 memcpy(mac_bssid + IEEE80211_ADDR_LEN, sc->sc_bssid,
8059 IEEE80211_ADDR_LEN);
8060
8061 for (i = 0; i < N(mac_bssid); i += sizeof(uint32_t)) {
8062 tmp = (uint32_t) (mac_bssid[i + 0]);
8063 tmp |= (uint32_t) (mac_bssid[i + 1]) << 8;
8064 tmp |= (uint32_t) (mac_bssid[i + 2]) << 16;
8065 tmp |= (uint32_t) (mac_bssid[i + 3]) << 24;
8066 bwn_ram_write(mac, 0x20 + i, tmp);
8067 }
8068}
8069
8070static void
8071bwn_mac_setfilter(struct bwn_mac *mac, uint16_t offset,
8072 const uint8_t *macaddr)
8073{
8074 static const uint8_t zero[IEEE80211_ADDR_LEN] = { 0 };
8075 uint16_t data;
8076
8077 if (!mac)
8078 macaddr = zero;
8079
8080 offset |= 0x0020;
8081 BWN_WRITE_2(mac, BWN_MACFILTER_CONTROL, offset);
8082
8083 data = macaddr[0];
8084 data |= macaddr[1] << 8;
8085 BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8086 data = macaddr[2];
8087 data |= macaddr[3] << 8;
8088 BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8089 data = macaddr[4];
8090 data |= macaddr[5] << 8;
8091 BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8092}
8093
8094static void
8095bwn_key_dowrite(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8096 const uint8_t *key, size_t key_len, const uint8_t *mac_addr)
8097{
8098 uint8_t buf[BWN_SEC_KEYSIZE] = { 0, };
8099 uint8_t per_sta_keys_start = 8;
8100
8101 if (BWN_SEC_NEWAPI(mac))
8102 per_sta_keys_start = 4;
8103
8104 KASSERT(index < mac->mac_max_nr_keys,
8105 ("%s:%d: fail", __func__, __LINE__));
8106 KASSERT(key_len <= BWN_SEC_KEYSIZE,
8107 ("%s:%d: fail", __func__, __LINE__));
8108
8109 if (index >= per_sta_keys_start)
8110 bwn_key_macwrite(mac, index, NULL);
8111 if (key)
8112 memcpy(buf, key, key_len);
8113 bwn_key_write(mac, index, algorithm, buf);
8114 if (index >= per_sta_keys_start)
8115 bwn_key_macwrite(mac, index, mac_addr);
8116
8117 mac->mac_key[index].algorithm = algorithm;
8118}
8119
8120static void
8121bwn_key_macwrite(struct bwn_mac *mac, uint8_t index, const uint8_t *addr)
8122{
8123 struct bwn_softc *sc = mac->mac_sc;
8124 uint32_t addrtmp[2] = { 0, 0 };
8125 uint8_t start = 8;
8126
8127 if (BWN_SEC_NEWAPI(mac))
8128 start = 4;
8129
8130 KASSERT(index >= start,
8131 ("%s:%d: fail", __func__, __LINE__));
8132 index -= start;
8133
8134 if (addr) {
8135 addrtmp[0] = addr[0];
8136 addrtmp[0] |= ((uint32_t) (addr[1]) << 8);
8137 addrtmp[0] |= ((uint32_t) (addr[2]) << 16);
8138 addrtmp[0] |= ((uint32_t) (addr[3]) << 24);
8139 addrtmp[1] = addr[4];
8140 addrtmp[1] |= ((uint32_t) (addr[5]) << 8);
8141 }
8142
8143 if (siba_get_revid(sc->sc_dev) >= 5) {
8144 bwn_shm_write_4(mac, BWN_RCMTA, (index * 2) + 0, addrtmp[0]);
8145 bwn_shm_write_2(mac, BWN_RCMTA, (index * 2) + 1, addrtmp[1]);
8146 } else {
8147 if (index >= 8) {
8148 bwn_shm_write_4(mac, BWN_SHARED,
8149 BWN_SHARED_PSM + (index * 6) + 0, addrtmp[0]);
8150 bwn_shm_write_2(mac, BWN_SHARED,
8151 BWN_SHARED_PSM + (index * 6) + 4, addrtmp[1]);
8152 }
8153 }
8154}
8155
8156static void
8157bwn_key_write(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8158 const uint8_t *key)
8159{
8160 unsigned int i;
8161 uint32_t offset;
8162 uint16_t kidx, value;
8163
8164 kidx = BWN_SEC_KEY2FW(mac, index);
8165 bwn_shm_write_2(mac, BWN_SHARED,
8166 BWN_SHARED_KEYIDX_BLOCK + (kidx * 2), (kidx << 4) | algorithm);
8167
8168 offset = mac->mac_ktp + (index * BWN_SEC_KEYSIZE);
8169 for (i = 0; i < BWN_SEC_KEYSIZE; i += 2) {
8170 value = key[i];
8171 value |= (uint16_t)(key[i + 1]) << 8;
8172 bwn_shm_write_2(mac, BWN_SHARED, offset + i, value);
8173 }
8174}
8175
8176static void
8177bwn_phy_exit(struct bwn_mac *mac)
8178{
8179
8180 mac->mac_phy.rf_onoff(mac, 0);
8181 if (mac->mac_phy.exit != NULL)
8182 mac->mac_phy.exit(mac);
8183}
8184
8185static void
8186bwn_dma_free(struct bwn_mac *mac)
8187{
8188 struct bwn_dma *dma;
8189
8190 if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
8191 return;
8192 dma = &mac->mac_method.dma;
8193
8194 bwn_dma_ringfree(&dma->rx);
8195 bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
8196 bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
8197 bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
8198 bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
8199 bwn_dma_ringfree(&dma->mcast);
8200}
8201
8202static void
8203bwn_core_stop(struct bwn_mac *mac)
8204{
8205 struct bwn_softc *sc = mac->mac_sc;
8206
8207 BWN_ASSERT_LOCKED(sc);
8208
8209 if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8210 return;
8211
8212 callout_stop(&sc->sc_rfswitch_ch);
8213 callout_stop(&sc->sc_task_ch);
8214 callout_stop(&sc->sc_watchdog_ch);
8215 sc->sc_watchdog_timer = 0;
8216 BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8217 BWN_READ_4(mac, BWN_INTR_MASK);
8218 bwn_mac_suspend(mac);
8219
8220 mac->mac_status = BWN_MAC_STATUS_INITED;
8221}
8222
8223static int
8224bwn_switch_band(struct bwn_softc *sc, struct ieee80211_channel *chan)
8225{
8226 struct bwn_mac *up_dev = NULL;
8227 struct bwn_mac *down_dev;
8228 struct bwn_mac *mac;
8229 int err, status;
8230 uint8_t gmode;
8231
8232 BWN_ASSERT_LOCKED(sc);
8233
8234 TAILQ_FOREACH(mac, &sc->sc_maclist, mac_list) {
8235 if (IEEE80211_IS_CHAN_2GHZ(chan) &&
8236 mac->mac_phy.supports_2ghz) {
8237 up_dev = mac;
8238 gmode = 1;
8239 } else if (IEEE80211_IS_CHAN_5GHZ(chan) &&
8240 mac->mac_phy.supports_5ghz) {
8241 up_dev = mac;
8242 gmode = 0;
8243 } else {
8244 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8245 return (EINVAL);
8246 }
8247 if (up_dev != NULL)
8248 break;
8249 }
8250 if (up_dev == NULL) {
8251 device_printf(sc->sc_dev, "Could not find a device\n");
8252 return (ENODEV);
8253 }
8254 if (up_dev == sc->sc_curmac && sc->sc_curmac->mac_phy.gmode == gmode)
8255 return (0);
8256
8257 device_printf(sc->sc_dev, "switching to %s-GHz band\n",
8258 IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8259
8260 down_dev = sc->sc_curmac;
8261 status = down_dev->mac_status;
8262 if (status >= BWN_MAC_STATUS_STARTED)
8263 bwn_core_stop(down_dev);
8264 if (status >= BWN_MAC_STATUS_INITED)
8265 bwn_core_exit(down_dev);
8266
8267 if (down_dev != up_dev)
8268 bwn_phy_reset(down_dev);
8269
8270 up_dev->mac_phy.gmode = gmode;
8271 if (status >= BWN_MAC_STATUS_INITED) {
8272 err = bwn_core_init(up_dev);
8273 if (err) {
8274 device_printf(sc->sc_dev,
8275 "fatal: failed to initialize for %s-GHz\n",
8276 IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8277 goto fail;
8278 }
8279 }
8280 if (status >= BWN_MAC_STATUS_STARTED)
8281 bwn_core_start(up_dev);
8282 KASSERT(up_dev->mac_status == status, ("%s: fail", __func__));
8283 sc->sc_curmac = up_dev;
8284
8285 return (0);
8286fail:
8287 sc->sc_curmac = NULL;
8288 return (err);
8289}
8290
8291static void
8292bwn_rf_turnon(struct bwn_mac *mac)
8293{
8294
8295 bwn_mac_suspend(mac);
8296 mac->mac_phy.rf_onoff(mac, 1);
8297 mac->mac_phy.rf_on = 1;
8298 bwn_mac_enable(mac);
8299}
8300
8301static void
8302bwn_rf_turnoff(struct bwn_mac *mac)
8303{
8304
8305 bwn_mac_suspend(mac);
8306 mac->mac_phy.rf_onoff(mac, 0);
8307 mac->mac_phy.rf_on = 0;
8308 bwn_mac_enable(mac);
8309}
8310
8311static void
8312bwn_phy_reset(struct bwn_mac *mac)
8313{
8314 struct bwn_softc *sc = mac->mac_sc;
8315
8316 siba_write_4(sc->sc_dev, SIBA_TGSLOW,
8317 ((siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~BWN_TGSLOW_SUPPORT_G) |
8318 BWN_TGSLOW_PHYRESET) | SIBA_TGSLOW_FGC);
8319 DELAY(1000);
8320 siba_write_4(sc->sc_dev, SIBA_TGSLOW,
8321 (siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~SIBA_TGSLOW_FGC) |
8322 BWN_TGSLOW_PHYRESET);
8323 DELAY(1000);
8324}
8325
8326static int
8327bwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
8328{
8329 struct bwn_vap *bvp = BWN_VAP(vap);
8330 struct ieee80211com *ic= vap->iv_ic;
8331 struct ifnet *ifp = ic->ic_ifp;
8332 enum ieee80211_state ostate = vap->iv_state;
8333 struct bwn_softc *sc = ifp->if_softc;
8334 struct bwn_mac *mac = sc->sc_curmac;
8335 int error;
8336
8337 DPRINTF(sc, BWN_DEBUG_STATE, "%s: %s -> %s\n", __func__,
8338 ieee80211_state_name[vap->iv_state],
8339 ieee80211_state_name[nstate]);
8340
8341 error = bvp->bv_newstate(vap, nstate, arg);
8342 if (error != 0)
8343 return (error);
8344
8345 BWN_LOCK(sc);
8346
8347 bwn_led_newstate(mac, nstate);
8348
8349 /*
8350 * Clear the BSSID when we stop a STA
8351 */
8352 if (vap->iv_opmode == IEEE80211_M_STA) {
8353 if (ostate == IEEE80211_S_RUN && nstate != IEEE80211_S_RUN) {
8354 /*
8355 * Clear out the BSSID. If we reassociate to
8356 * the same AP, this will reinialize things
8357 * correctly...
8358 */
8359 if (ic->ic_opmode == IEEE80211_M_STA &&
8360 (sc->sc_flags & BWN_FLAG_INVALID) == 0) {
8361 memset(sc->sc_bssid, 0, IEEE80211_ADDR_LEN);
8362 bwn_set_macaddr(mac);
8363 }
8364 }
8365 }
8366
8367 if (vap->iv_opmode == IEEE80211_M_MONITOR ||
8368 vap->iv_opmode == IEEE80211_M_AHDEMO) {
8369 /* XXX nothing to do? */
8370 } else if (nstate == IEEE80211_S_RUN) {
8371 memcpy(sc->sc_bssid, vap->iv_bss->ni_bssid, IEEE80211_ADDR_LEN);
8372 memcpy(sc->sc_macaddr, IF_LLADDR(ifp), IEEE80211_ADDR_LEN);
8373 bwn_set_opmode(mac);
8374 bwn_set_pretbtt(mac);
8375 bwn_spu_setdelay(mac, 0);
8376 bwn_set_macaddr(mac);
8377 }
8378
8379 BWN_UNLOCK(sc);
8380
8381 return (error);
8382}
8383
8384static void
8385bwn_set_pretbtt(struct bwn_mac *mac)
8386{
8387 struct bwn_softc *sc = mac->mac_sc;
8388 struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8389 uint16_t pretbtt;
8390
8391 if (ic->ic_opmode == IEEE80211_M_IBSS)
8392 pretbtt = 2;
8393 else
8394 pretbtt = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 120 : 250;
8395 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PRETBTT, pretbtt);
8396 BWN_WRITE_2(mac, BWN_TSF_CFP_PRETBTT, pretbtt);
8397}
8398
8399static int
8400bwn_intr(void *arg)
8401{
8402 struct bwn_mac *mac = arg;
8403 struct bwn_softc *sc = mac->mac_sc;
8404 uint32_t reason;
8405
8406 if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
8407 (sc->sc_flags & BWN_FLAG_INVALID))
8408 return (FILTER_STRAY);
8409
8410 reason = BWN_READ_4(mac, BWN_INTR_REASON);
8411 if (reason == 0xffffffff) /* shared IRQ */
8412 return (FILTER_STRAY);
8413 reason &= mac->mac_intr_mask;
8414 if (reason == 0)
8415 return (FILTER_HANDLED);
8416
8417 mac->mac_reason[0] = BWN_READ_4(mac, BWN_DMA0_REASON) & 0x0001dc00;
8418 mac->mac_reason[1] = BWN_READ_4(mac, BWN_DMA1_REASON) & 0x0000dc00;
8419 mac->mac_reason[2] = BWN_READ_4(mac, BWN_DMA2_REASON) & 0x0000dc00;
8420 mac->mac_reason[3] = BWN_READ_4(mac, BWN_DMA3_REASON) & 0x0001dc00;
8421 mac->mac_reason[4] = BWN_READ_4(mac, BWN_DMA4_REASON) & 0x0000dc00;
8422 BWN_WRITE_4(mac, BWN_INTR_REASON, reason);
8423 BWN_WRITE_4(mac, BWN_DMA0_REASON, mac->mac_reason[0]);
8424 BWN_WRITE_4(mac, BWN_DMA1_REASON, mac->mac_reason[1]);
8425 BWN_WRITE_4(mac, BWN_DMA2_REASON, mac->mac_reason[2]);
8426 BWN_WRITE_4(mac, BWN_DMA3_REASON, mac->mac_reason[3]);
8427 BWN_WRITE_4(mac, BWN_DMA4_REASON, mac->mac_reason[4]);
8428
8429 /* Disable interrupts. */
8430 BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8431
8432 mac->mac_reason_intr = reason;
8433
8434 BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8435 BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8436
8437 taskqueue_enqueue_fast(sc->sc_tq, &mac->mac_intrtask);
8438 return (FILTER_HANDLED);
8439}
8440
8441static void
8442bwn_intrtask(void *arg, int npending)
8443{
8444 struct bwn_mac *mac = arg;
8445 struct bwn_softc *sc = mac->mac_sc;
8446 struct ifnet *ifp = sc->sc_ifp;
8447 uint32_t merged = 0;
8448 int i, tx = 0, rx = 0;
8449
8450 BWN_LOCK(sc);
8451 if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
8452 (sc->sc_flags & BWN_FLAG_INVALID)) {
8453 BWN_UNLOCK(sc);
8454 return;
8455 }
8456
8457 for (i = 0; i < N(mac->mac_reason); i++)
8458 merged |= mac->mac_reason[i];
8459
8460 if (mac->mac_reason_intr & BWN_INTR_MAC_TXERR)
8461 device_printf(sc->sc_dev, "MAC trans error\n");
8462
8463 if (mac->mac_reason_intr & BWN_INTR_PHY_TXERR) {
8464 DPRINTF(sc, BWN_DEBUG_INTR, "%s: PHY trans error\n", __func__);
8465 mac->mac_phy.txerrors--;
8466 if (mac->mac_phy.txerrors == 0) {
8467 mac->mac_phy.txerrors = BWN_TXERROR_MAX;
8468 bwn_restart(mac, "PHY TX errors");
8469 }
8470 }
8471
8472 if (merged & (BWN_DMAINTR_FATALMASK | BWN_DMAINTR_NONFATALMASK)) {
8473 if (merged & BWN_DMAINTR_FATALMASK) {
8474 device_printf(sc->sc_dev,
8475 "Fatal DMA error: %#x %#x %#x %#x %#x %#x\n",
8476 mac->mac_reason[0], mac->mac_reason[1],
8477 mac->mac_reason[2], mac->mac_reason[3],
8478 mac->mac_reason[4], mac->mac_reason[5]);
8479 bwn_restart(mac, "DMA error");
8480 BWN_UNLOCK(sc);
8481 return;
8482 }
8483 if (merged & BWN_DMAINTR_NONFATALMASK) {
8484 device_printf(sc->sc_dev,
8485 "DMA error: %#x %#x %#x %#x %#x %#x\n",
8486 mac->mac_reason[0], mac->mac_reason[1],
8487 mac->mac_reason[2], mac->mac_reason[3],
8488 mac->mac_reason[4], mac->mac_reason[5]);
8489 }
8490 }
8491
8492 if (mac->mac_reason_intr & BWN_INTR_UCODE_DEBUG)
8493 bwn_intr_ucode_debug(mac);
8494 if (mac->mac_reason_intr & BWN_INTR_TBTT_INDI)
8495 bwn_intr_tbtt_indication(mac);
8496 if (mac->mac_reason_intr & BWN_INTR_ATIM_END)
8497 bwn_intr_atim_end(mac);
8498 if (mac->mac_reason_intr & BWN_INTR_BEACON)
8499 bwn_intr_beacon(mac);
8500 if (mac->mac_reason_intr & BWN_INTR_PMQ)
8501 bwn_intr_pmq(mac);
8502 if (mac->mac_reason_intr & BWN_INTR_NOISESAMPLE_OK)
8503 bwn_intr_noise(mac);
8504
8505 if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
8506 if (mac->mac_reason[0] & BWN_DMAINTR_RX_DONE) {
8507 bwn_dma_rx(mac->mac_method.dma.rx);
8508 rx = 1;
8509 }
8510 } else
8511 rx = bwn_pio_rx(&mac->mac_method.pio.rx);
8512
8513 KASSERT(!(mac->mac_reason[1] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8514 KASSERT(!(mac->mac_reason[2] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8515 KASSERT(!(mac->mac_reason[3] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8516 KASSERT(!(mac->mac_reason[4] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8517 KASSERT(!(mac->mac_reason[5] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8518
8519 if (mac->mac_reason_intr & BWN_INTR_TX_OK) {
8520 bwn_intr_txeof(mac);
8521 tx = 1;
8522 }
8523
8524 BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
8525
8526 if (sc->sc_blink_led != NULL && sc->sc_led_blink) {
8527 int evt = BWN_LED_EVENT_NONE;
8528
8529 if (tx && rx) {
8530 if (sc->sc_rx_rate > sc->sc_tx_rate)
8531 evt = BWN_LED_EVENT_RX;
8532 else
8533 evt = BWN_LED_EVENT_TX;
8534 } else if (tx) {
8535 evt = BWN_LED_EVENT_TX;
8536 } else if (rx) {
8537 evt = BWN_LED_EVENT_RX;
8538 } else if (rx == 0) {
8539 evt = BWN_LED_EVENT_POLL;
8540 }
8541
8542 if (evt != BWN_LED_EVENT_NONE)
8543 bwn_led_event(mac, evt);
8544 }
8545
8546 if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0) {
8547 if (!IFQ_IS_EMPTY(&ifp->if_snd))
8548 bwn_start_locked(ifp);
8549 }
8550
8551 BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8552 BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8553
8554 BWN_UNLOCK(sc);
8555}
8556
8557static void
8558bwn_restart(struct bwn_mac *mac, const char *msg)
8559{
8560 struct bwn_softc *sc = mac->mac_sc;
8561 struct ifnet *ifp = sc->sc_ifp;
8562 struct ieee80211com *ic = ifp->if_l2com;
8563
8564 if (mac->mac_status < BWN_MAC_STATUS_INITED)
8565 return;
8566
8567 device_printf(sc->sc_dev, "HW reset: %s\n", msg);
8568 ieee80211_runtask(ic, &mac->mac_hwreset);
8569}
8570
8571static void
8572bwn_intr_ucode_debug(struct bwn_mac *mac)
8573{
8574 struct bwn_softc *sc = mac->mac_sc;
8575 uint16_t reason;
8576
8577 if (mac->mac_fw.opensource == 0)
8578 return;
8579
8580 reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG);
8581 switch (reason) {
8582 case BWN_DEBUGINTR_PANIC:
8583 bwn_handle_fwpanic(mac);
8584 break;
8585 case BWN_DEBUGINTR_DUMP_SHM:
8586 device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_SHM\n");
8587 break;
8588 case BWN_DEBUGINTR_DUMP_REGS:
8589 device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_REGS\n");
8590 break;
8591 case BWN_DEBUGINTR_MARKER:
8592 device_printf(sc->sc_dev, "BWN_DEBUGINTR_MARKER\n");
8593 break;
8594 default:
8595 device_printf(sc->sc_dev,
8596 "ucode debug unknown reason: %#x\n", reason);
8597 }
8598
8599 bwn_shm_write_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG,
8600 BWN_DEBUGINTR_ACK);
8601}
8602
8603static void
8604bwn_intr_tbtt_indication(struct bwn_mac *mac)
8605{
8606 struct bwn_softc *sc = mac->mac_sc;
8607 struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8608
8609 if (ic->ic_opmode != IEEE80211_M_HOSTAP)
8610 bwn_psctl(mac, 0);
8611 if (ic->ic_opmode == IEEE80211_M_IBSS)
8612 mac->mac_flags |= BWN_MAC_FLAG_DFQVALID;
8613}
8614
8615static void
8616bwn_intr_atim_end(struct bwn_mac *mac)
8617{
8618
8619 if (mac->mac_flags & BWN_MAC_FLAG_DFQVALID) {
8620 BWN_WRITE_4(mac, BWN_MACCMD,
8621 BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_DFQ_VALID);
8622 mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
8623 }
8624}
8625
8626static void
8627bwn_intr_beacon(struct bwn_mac *mac)
8628{
8629 struct bwn_softc *sc = mac->mac_sc;
8630 struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8631 uint32_t cmd, beacon0, beacon1;
8632
8633 if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
8634 ic->ic_opmode == IEEE80211_M_MBSS)
8635 return;
8636
8637 mac->mac_intr_mask &= ~BWN_INTR_BEACON;
8638
8639 cmd = BWN_READ_4(mac, BWN_MACCMD);
8640 beacon0 = (cmd & BWN_MACCMD_BEACON0_VALID);
8641 beacon1 = (cmd & BWN_MACCMD_BEACON1_VALID);
8642
8643 if (beacon0 && beacon1) {
8644 BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_BEACON);
8645 mac->mac_intr_mask |= BWN_INTR_BEACON;
8646 return;
8647 }
8648
8649 if (sc->sc_flags & BWN_FLAG_NEED_BEACON_TP) {
8650 sc->sc_flags &= ~BWN_FLAG_NEED_BEACON_TP;
8651 bwn_load_beacon0(mac);
8652 bwn_load_beacon1(mac);
8653 cmd = BWN_READ_4(mac, BWN_MACCMD);
8654 cmd |= BWN_MACCMD_BEACON0_VALID;
8655 BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8656 } else {
8657 if (!beacon0) {
8658 bwn_load_beacon0(mac);
8659 cmd = BWN_READ_4(mac, BWN_MACCMD);
8660 cmd |= BWN_MACCMD_BEACON0_VALID;
8661 BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8662 } else if (!beacon1) {
8663 bwn_load_beacon1(mac);
8664 cmd = BWN_READ_4(mac, BWN_MACCMD);
8665 cmd |= BWN_MACCMD_BEACON1_VALID;
8666 BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8667 }
8668 }
8669}
8670
8671static void
8672bwn_intr_pmq(struct bwn_mac *mac)
8673{
8674 uint32_t tmp;
8675
8676 while (1) {
8677 tmp = BWN_READ_4(mac, BWN_PS_STATUS);
8678 if (!(tmp & 0x00000008))
8679 break;
8680 }
8681 BWN_WRITE_2(mac, BWN_PS_STATUS, 0x0002);
8682}
8683
8684static void
8685bwn_intr_noise(struct bwn_mac *mac)
8686{
8687 struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
8688 uint16_t tmp;
8689 uint8_t noise[4];
8690 uint8_t i, j;
8691 int32_t average;
8692
8693 if (mac->mac_phy.type != BWN_PHYTYPE_G)
8694 return;
8695
8696 KASSERT(mac->mac_noise.noi_running, ("%s: fail", __func__));
8697 *((uint32_t *)noise) = htole32(bwn_jssi_read(mac));
8698 if (noise[0] == 0x7f || noise[1] == 0x7f || noise[2] == 0x7f ||
8699 noise[3] == 0x7f)
8700 goto new;
8701
8702 KASSERT(mac->mac_noise.noi_nsamples < 8,
8703 ("%s:%d: fail", __func__, __LINE__));
8704 i = mac->mac_noise.noi_nsamples;
8705 noise[0] = MIN(MAX(noise[0], 0), N(pg->pg_nrssi_lt) - 1);
8706 noise[1] = MIN(MAX(noise[1], 0), N(pg->pg_nrssi_lt) - 1);
8707 noise[2] = MIN(MAX(noise[2], 0), N(pg->pg_nrssi_lt) - 1);
8708 noise[3] = MIN(MAX(noise[3], 0), N(pg->pg_nrssi_lt) - 1);
8709 mac->mac_noise.noi_samples[i][0] = pg->pg_nrssi_lt[noise[0]];
8710 mac->mac_noise.noi_samples[i][1] = pg->pg_nrssi_lt[noise[1]];
8711 mac->mac_noise.noi_samples[i][2] = pg->pg_nrssi_lt[noise[2]];
8712 mac->mac_noise.noi_samples[i][3] = pg->pg_nrssi_lt[noise[3]];
8713 mac->mac_noise.noi_nsamples++;
8714 if (mac->mac_noise.noi_nsamples == 8) {
8715 average = 0;
8716 for (i = 0; i < 8; i++) {
8717 for (j = 0; j < 4; j++)
8718 average += mac->mac_noise.noi_samples[i][j];
8719 }
8720 average = (((average / 32) * 125) + 64) / 128;
8721 tmp = (bwn_shm_read_2(mac, BWN_SHARED, 0x40c) / 128) & 0x1f;
8722 if (tmp >= 8)
8723 average += 2;
8724 else
8725 average -= 25;
8726 average -= (tmp == 8) ? 72 : 48;
8727
8728 mac->mac_stats.link_noise = average;
8729 mac->mac_noise.noi_running = 0;
8730 return;
8731 }
8732new:
8733 bwn_noise_gensample(mac);
8734}
8735
8736static int
8737bwn_pio_rx(struct bwn_pio_rxqueue *prq)
8738{
8739 struct bwn_mac *mac = prq->prq_mac;
8740 struct bwn_softc *sc = mac->mac_sc;
8741 unsigned int i;
8742
8743 BWN_ASSERT_LOCKED(sc);
8744
8745 if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8746 return (0);
8747
8748 for (i = 0; i < 5000; i++) {
8749 if (bwn_pio_rxeof(prq) == 0)
8750 break;
8751 }
8752 if (i >= 5000)
8753 device_printf(sc->sc_dev, "too many RX frames in PIO mode\n");
8754 return ((i > 0) ? 1 : 0);
8755}
8756
8757static void
8758bwn_dma_rx(struct bwn_dma_ring *dr)
8759{
8760 int slot, curslot;
8761
8762 KASSERT(!dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
8763 curslot = dr->get_curslot(dr);
8764 KASSERT(curslot >= 0 && curslot < dr->dr_numslots,
8765 ("%s:%d: fail", __func__, __LINE__));
8766
8767 slot = dr->dr_curslot;
8768 for (; slot != curslot; slot = bwn_dma_nextslot(dr, slot))
8769 bwn_dma_rxeof(dr, &slot);
8770
8771 bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
8772 BUS_DMASYNC_PREWRITE);
8773
8774 dr->set_curslot(dr, slot);
8775 dr->dr_curslot = slot;
8776}
8777
8778static void
8779bwn_intr_txeof(struct bwn_mac *mac)
8780{
8781 struct bwn_txstatus stat;
8782 uint32_t stat0, stat1;
8783 uint16_t tmp;
8784
8785 BWN_ASSERT_LOCKED(mac->mac_sc);
8786
8787 while (1) {
8788 stat0 = BWN_READ_4(mac, BWN_XMITSTAT_0);
8789 if (!(stat0 & 0x00000001))
8790 break;
8791 stat1 = BWN_READ_4(mac, BWN_XMITSTAT_1);
8792
8793 stat.cookie = (stat0 >> 16);
8794 stat.seq = (stat1 & 0x0000ffff);
8795 stat.phy_stat = ((stat1 & 0x00ff0000) >> 16);
8796 tmp = (stat0 & 0x0000ffff);
8797 stat.framecnt = ((tmp & 0xf000) >> 12);
8798 stat.rtscnt = ((tmp & 0x0f00) >> 8);
8799 stat.sreason = ((tmp & 0x001c) >> 2);
8800 stat.pm = (tmp & 0x0080) ? 1 : 0;
8801 stat.im = (tmp & 0x0040) ? 1 : 0;
8802 stat.ampdu = (tmp & 0x0020) ? 1 : 0;
8803 stat.ack = (tmp & 0x0002) ? 1 : 0;
8804
8805 bwn_handle_txeof(mac, &stat);
8806 }
8807}
8808
8809static void
8810bwn_hwreset(void *arg, int npending)
8811{
8812 struct bwn_mac *mac = arg;
8813 struct bwn_softc *sc = mac->mac_sc;
8814 int error = 0;
8815 int prev_status;
8816
8817 BWN_LOCK(sc);
8818
8819 prev_status = mac->mac_status;
8820 if (prev_status >= BWN_MAC_STATUS_STARTED)
8821 bwn_core_stop(mac);
8822 if (prev_status >= BWN_MAC_STATUS_INITED)
8823 bwn_core_exit(mac);
8824
8825 if (prev_status >= BWN_MAC_STATUS_INITED) {
8826 error = bwn_core_init(mac);
8827 if (error)
8828 goto out;
8829 }
8830 if (prev_status >= BWN_MAC_STATUS_STARTED)
8831 bwn_core_start(mac);
8832out:
8833 if (error) {
8834 device_printf(sc->sc_dev, "%s: failed (%d)\n", __func__, error);
8835 sc->sc_curmac = NULL;
8836 }
8837 BWN_UNLOCK(sc);
8838}
8839
8840static void
8841bwn_handle_fwpanic(struct bwn_mac *mac)
8842{
8843 struct bwn_softc *sc = mac->mac_sc;
8844 uint16_t reason;
8845
8846 reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_FWPANIC_REASON_REG);
8847 device_printf(sc->sc_dev,"fw panic (%u)\n", reason);
8848
8849 if (reason == BWN_FWPANIC_RESTART)
8850 bwn_restart(mac, "ucode panic");
8851}
8852
8853static void
8854bwn_load_beacon0(struct bwn_mac *mac)
8855{
8856
8857 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8858}
8859
8860static void
8861bwn_load_beacon1(struct bwn_mac *mac)
8862{
8863
8864 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8865}
8866
8867static uint32_t
8868bwn_jssi_read(struct bwn_mac *mac)
8869{
8870 uint32_t val = 0;
8871
8872 val = bwn_shm_read_2(mac, BWN_SHARED, 0x08a);
8873 val <<= 16;
8874 val |= bwn_shm_read_2(mac, BWN_SHARED, 0x088);
8875
8876 return (val);
8877}
8878
8879static void
8880bwn_noise_gensample(struct bwn_mac *mac)
8881{
8882 uint32_t jssi = 0x7f7f7f7f;
8883
8884 bwn_shm_write_2(mac, BWN_SHARED, 0x088, (jssi & 0x0000ffff));
8885 bwn_shm_write_2(mac, BWN_SHARED, 0x08a, (jssi & 0xffff0000) >> 16);
8886 BWN_WRITE_4(mac, BWN_MACCMD,
8887 BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_BGNOISE);
8888}
8889
8890static int
8891bwn_dma_freeslot(struct bwn_dma_ring *dr)
8892{
8893 BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8894
8895 return (dr->dr_numslots - dr->dr_usedslot);
8896}
8897
8898static int
8899bwn_dma_nextslot(struct bwn_dma_ring *dr, int slot)
8900{
8901 BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8902
8903 KASSERT(slot >= -1 && slot <= dr->dr_numslots - 1,
8904 ("%s:%d: fail", __func__, __LINE__));
8905 if (slot == dr->dr_numslots - 1)
8906 return (0);
8907 return (slot + 1);
8908}
8909
8910static void
8911bwn_dma_rxeof(struct bwn_dma_ring *dr, int *slot)
8912{
8913 struct bwn_mac *mac = dr->dr_mac;
8914 struct bwn_softc *sc = mac->mac_sc;
8915 struct bwn_dma *dma = &mac->mac_method.dma;
8916 struct bwn_dmadesc_generic *desc;
8917 struct bwn_dmadesc_meta *meta;
8918 struct bwn_rxhdr4 *rxhdr;
8919 struct ifnet *ifp = sc->sc_ifp;
8920 struct mbuf *m;
8921 uint32_t macstat;
8922 int32_t tmp;
8923 int cnt = 0;
8924 uint16_t len;
8925
8926 dr->getdesc(dr, *slot, &desc, &meta);
8927
8928 bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap, BUS_DMASYNC_POSTREAD);
8929 m = meta->mt_m;
8930
8931 if (bwn_dma_newbuf(dr, desc, meta, 0)) {
8932 ifp->if_ierrors++;
8933 return;
8934 }
8935
8936 rxhdr = mtod(m, struct bwn_rxhdr4 *);
8937 len = le16toh(rxhdr->frame_len);
8938 if (len <= 0) {
8939 ifp->if_ierrors++;
8940 return;
8941 }
8942 if (bwn_dma_check_redzone(dr, m)) {
8943 device_printf(sc->sc_dev, "redzone error.\n");
8944 bwn_dma_set_redzone(dr, m);
8945 bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
8946 BUS_DMASYNC_PREWRITE);
8947 return;
8948 }
8949 if (len > dr->dr_rx_bufsize) {
8950 tmp = len;
8951 while (1) {
8952 dr->getdesc(dr, *slot, &desc, &meta);
8953 bwn_dma_set_redzone(dr, meta->mt_m);
8954 bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
8955 BUS_DMASYNC_PREWRITE);
8956 *slot = bwn_dma_nextslot(dr, *slot);
8957 cnt++;
8958 tmp -= dr->dr_rx_bufsize;
8959 if (tmp <= 0)
8960 break;
8961 }
8962 device_printf(sc->sc_dev, "too small buffer "
8963 "(len %u buffer %u dropped %d)\n",
8964 len, dr->dr_rx_bufsize, cnt);
8965 return;
8966 }
8967 macstat = le32toh(rxhdr->mac_status);
8968 if (macstat & BWN_RX_MAC_FCSERR) {
8969 if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
8970 device_printf(sc->sc_dev, "RX drop\n");
8971 return;
8972 }
8973 }
8974
8975 m->m_pkthdr.rcvif = ifp;
8976 m->m_len = m->m_pkthdr.len = len + dr->dr_frameoffset;
8977 m_adj(m, dr->dr_frameoffset);
8978
8979 bwn_rxeof(dr->dr_mac, m, rxhdr);
8980}
8981
8982static void
8983bwn_handle_txeof(struct bwn_mac *mac, const struct bwn_txstatus *status)
8984{
8985 struct bwn_dma_ring *dr;
8986 struct bwn_dmadesc_generic *desc;
8987 struct bwn_dmadesc_meta *meta;
8988 struct bwn_pio_txqueue *tq;
8989 struct bwn_pio_txpkt *tp = NULL;
8990 struct bwn_softc *sc = mac->mac_sc;
8991 struct bwn_stats *stats = &mac->mac_stats;
8992 struct ieee80211_node *ni;
8993 struct ieee80211vap *vap;
8994 int retrycnt = 0, slot;
8995
8996 BWN_ASSERT_LOCKED(mac->mac_sc);
8997
8998 if (status->im)
8999 device_printf(sc->sc_dev, "TODO: STATUS IM\n");
9000 if (status->ampdu)
9001 device_printf(sc->sc_dev, "TODO: STATUS AMPDU\n");
9002 if (status->rtscnt) {
9003 if (status->rtscnt == 0xf)
9004 stats->rtsfail++;
9005 else
9006 stats->rts++;
9007 }
9008
9009 if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
9010 if (status->ack) {
9011 dr = bwn_dma_parse_cookie(mac, status,
9012 status->cookie, &slot);
9013 if (dr == NULL) {
9014 device_printf(sc->sc_dev,
9015 "failed to parse cookie\n");
9016 return;
9017 }
9018 while (1) {
9019 dr->getdesc(dr, slot, &desc, &meta);
9020 if (meta->mt_islast) {
9021 ni = meta->mt_ni;
9022 vap = ni->ni_vap;
9023 ieee80211_ratectl_tx_complete(vap, ni,
9024 status->ack ?
9025 IEEE80211_RATECTL_TX_SUCCESS :
9026 IEEE80211_RATECTL_TX_FAILURE,
9027 &retrycnt, 0);
9028 break;
9029 }
9030 slot = bwn_dma_nextslot(dr, slot);
9031 }
9032 }
9033 bwn_dma_handle_txeof(mac, status);
9034 } else {
9035 if (status->ack) {
9036 tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9037 if (tq == NULL) {
9038 device_printf(sc->sc_dev,
9039 "failed to parse cookie\n");
9040 return;
9041 }
9042 ni = tp->tp_ni;
9043 vap = ni->ni_vap;
9044 ieee80211_ratectl_tx_complete(vap, ni,
9045 status->ack ?
9046 IEEE80211_RATECTL_TX_SUCCESS :
9047 IEEE80211_RATECTL_TX_FAILURE,
9048 &retrycnt, 0);
9049 }
9050 bwn_pio_handle_txeof(mac, status);
9051 }
9052
9053 bwn_phy_txpower_check(mac, 0);
9054}
9055
9056static uint8_t
9057bwn_pio_rxeof(struct bwn_pio_rxqueue *prq)
9058{
9059 struct bwn_mac *mac = prq->prq_mac;
9060 struct bwn_softc *sc = mac->mac_sc;
9061 struct bwn_rxhdr4 rxhdr;
9062 struct ifnet *ifp = sc->sc_ifp;
9063 struct mbuf *m;
9064 uint32_t ctl32, macstat, v32;
9065 unsigned int i, padding;
9066 uint16_t ctl16, len, totlen, v16;
9067 unsigned char *mp;
9068 char *data;
9069
9070 memset(&rxhdr, 0, sizeof(rxhdr));
9071
9072 if (prq->prq_rev >= 8) {
9073 ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
9074 if (!(ctl32 & BWN_PIO8_RXCTL_FRAMEREADY))
9075 return (0);
9076 bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9077 BWN_PIO8_RXCTL_FRAMEREADY);
9078 for (i = 0; i < 10; i++) {
9079 ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
9080 if (ctl32 & BWN_PIO8_RXCTL_DATAREADY)
9081 goto ready;
9082 DELAY(10);
9083 }
9084 } else {
9085 ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
9086 if (!(ctl16 & BWN_PIO_RXCTL_FRAMEREADY))
9087 return (0);
9088 bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL,
9089 BWN_PIO_RXCTL_FRAMEREADY);
9090 for (i = 0; i < 10; i++) {
9091 ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
9092 if (ctl16 & BWN_PIO_RXCTL_DATAREADY)
9093 goto ready;
9094 DELAY(10);
9095 }
9096 }
9097 device_printf(sc->sc_dev, "%s: timed out\n", __func__);
9098 return (1);
9099ready:
9100 if (prq->prq_rev >= 8)
9101 siba_read_multi_4(sc->sc_dev, &rxhdr, sizeof(rxhdr),
9102 prq->prq_base + BWN_PIO8_RXDATA);
9103 else
9104 siba_read_multi_2(sc->sc_dev, &rxhdr, sizeof(rxhdr),
9105 prq->prq_base + BWN_PIO_RXDATA);
9106 len = le16toh(rxhdr.frame_len);
9107 if (len > 0x700) {
9108 device_printf(sc->sc_dev, "%s: len is too big\n", __func__);
9109 goto error;
9110 }
9111 if (len == 0) {
9112 device_printf(sc->sc_dev, "%s: len is 0\n", __func__);
9113 goto error;
9114 }
9115
9116 macstat = le32toh(rxhdr.mac_status);
9117 if (macstat & BWN_RX_MAC_FCSERR) {
9118 if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
9119 device_printf(sc->sc_dev, "%s: FCS error", __func__);
9120 goto error;
9121 }
9122 }
9123
9124 padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9125 totlen = len + padding;
9126 KASSERT(totlen <= MCLBYTES, ("too big..\n"));
9127 m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
9128 if (m == NULL) {
9129 device_printf(sc->sc_dev, "%s: out of memory", __func__);
9130 goto error;
9131 }
9132 mp = mtod(m, unsigned char *);
9133 if (prq->prq_rev >= 8) {
9134 siba_read_multi_4(sc->sc_dev, mp, (totlen & ~3),
9135 prq->prq_base + BWN_PIO8_RXDATA);
9136 if (totlen & 3) {
9137 v32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXDATA);
9138 data = &(mp[totlen - 1]);
9139 switch (totlen & 3) {
9140 case 3:
9141 *data = (v32 >> 16);
9142 data--;
9143 case 2:
9144 *data = (v32 >> 8);
9145 data--;
9146 case 1:
9147 *data = v32;
9148 }
9149 }
9150 } else {
9151 siba_read_multi_2(sc->sc_dev, mp, (totlen & ~1),
9152 prq->prq_base + BWN_PIO_RXDATA);
9153 if (totlen & 1) {
9154 v16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXDATA);
9155 mp[totlen - 1] = v16;
9156 }
9157 }
9158
9159 m->m_pkthdr.rcvif = ifp;
9160 m->m_len = m->m_pkthdr.len = totlen;
9161
9162 bwn_rxeof(prq->prq_mac, m, &rxhdr);
9163
9164 return (1);
9165error:
9166 if (prq->prq_rev >= 8)
9167 bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9168 BWN_PIO8_RXCTL_DATAREADY);
9169 else
9170 bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL, BWN_PIO_RXCTL_DATAREADY);
9171 return (1);
9172}
9173
9174static int
9175bwn_dma_newbuf(struct bwn_dma_ring *dr, struct bwn_dmadesc_generic *desc,
9176 struct bwn_dmadesc_meta *meta, int init)
9177{
9178 struct bwn_mac *mac = dr->dr_mac;
9179 struct bwn_dma *dma = &mac->mac_method.dma;
9180 struct bwn_rxhdr4 *hdr;
9181 bus_dmamap_t map;
9182 bus_addr_t paddr;
9183 struct mbuf *m;
9184 int error;
9185
9186 m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
9187 if (m == NULL) {
9188 error = ENOBUFS;
9189
9190 /*
9191 * If the NIC is up and running, we need to:
9192 * - Clear RX buffer's header.
9193 * - Restore RX descriptor settings.
9194 */
9195 if (init)
9196 return (error);
9197 else
9198 goto back;
9199 }
9200 m->m_len = m->m_pkthdr.len = MCLBYTES;
9201
9202 bwn_dma_set_redzone(dr, m);
9203
9204 /*
9205 * Try to load RX buf into temporary DMA map
9206 */
9207 error = bus_dmamap_load_mbuf(dma->rxbuf_dtag, dr->dr_spare_dmap, m,
9208 bwn_dma_buf_addr, &paddr, BUS_DMA_NOWAIT);
9209 if (error) {
9210 m_freem(m);
9211
9212 /*
9213 * See the comment above
9214 */
9215 if (init)
9216 return (error);
9217 else
9218 goto back;
9219 }
9220
9221 if (!init)
9222 bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
9223 meta->mt_m = m;
9224 meta->mt_paddr = paddr;
9225
9226 /*
9227 * Swap RX buf's DMA map with the loaded temporary one
9228 */
9229 map = meta->mt_dmap;
9230 meta->mt_dmap = dr->dr_spare_dmap;
9231 dr->dr_spare_dmap = map;
9232
9233back:
9234 /*
9235 * Clear RX buf header
9236 */
9237 hdr = mtod(meta->mt_m, struct bwn_rxhdr4 *);
9238 bzero(hdr, sizeof(*hdr));
9239 bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
9240 BUS_DMASYNC_PREWRITE);
9241
9242 /*
9243 * Setup RX buf descriptor
9244 */
9245 dr->setdesc(dr, desc, paddr, meta->mt_m->m_len -
9246 sizeof(*hdr), 0, 0, 0);
9247 return (error);
9248}
9249
9250static void
9251bwn_dma_buf_addr(void *arg, bus_dma_segment_t *seg, int nseg,
9252 bus_size_t mapsz __unused, int error)
9253{
9254
9255 if (!error) {
9256 KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
9257 *((bus_addr_t *)arg) = seg->ds_addr;
9258 }
9259}
9260
9261static int
9262bwn_hwrate2ieeerate(int rate)
9263{
9264
9265 switch (rate) {
9266 case BWN_CCK_RATE_1MB:
9267 return (2);
9268 case BWN_CCK_RATE_2MB:
9269 return (4);
9270 case BWN_CCK_RATE_5MB:
9271 return (11);
9272 case BWN_CCK_RATE_11MB:
9273 return (22);
9274 case BWN_OFDM_RATE_6MB:
9275 return (12);
9276 case BWN_OFDM_RATE_9MB:
9277 return (18);
9278 case BWN_OFDM_RATE_12MB:
9279 return (24);
9280 case BWN_OFDM_RATE_18MB:
9281 return (36);
9282 case BWN_OFDM_RATE_24MB:
9283 return (48);
9284 case BWN_OFDM_RATE_36MB:
9285 return (72);
9286 case BWN_OFDM_RATE_48MB:
9287 return (96);
9288 case BWN_OFDM_RATE_54MB:
9289 return (108);
9290 default:
9291 printf("Ooops\n");
9292 return (0);
9293 }
9294}
9295
9296static void
9297bwn_rxeof(struct bwn_mac *mac, struct mbuf *m, const void *_rxhdr)
9298{
9299 const struct bwn_rxhdr4 *rxhdr = _rxhdr;
9300 struct bwn_plcp6 *plcp;
9301 struct bwn_softc *sc = mac->mac_sc;
9302 struct ieee80211_frame_min *wh;
9303 struct ieee80211_node *ni;
9304 struct ifnet *ifp = sc->sc_ifp;
9305 struct ieee80211com *ic = ifp->if_l2com;
9306 uint32_t macstat;
9307 int padding, rate, rssi = 0, noise = 0, type;
9308 uint16_t phytype, phystat0, phystat3, chanstat;
9309 unsigned char *mp = mtod(m, unsigned char *);
9310 static int rx_mac_dec_rpt = 0;
9311
9312 BWN_ASSERT_LOCKED(sc);
9313
9314 phystat0 = le16toh(rxhdr->phy_status0);
9315 phystat3 = le16toh(rxhdr->phy_status3);
9316 macstat = le32toh(rxhdr->mac_status);
9317 chanstat = le16toh(rxhdr->channel);
9318 phytype = chanstat & BWN_RX_CHAN_PHYTYPE;
9319
9320 if (macstat & BWN_RX_MAC_FCSERR)
9321 device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_FCS_CRC\n");
9322 if (phystat0 & (BWN_RX_PHYST0_PLCPHCF | BWN_RX_PHYST0_PLCPFV))
9323 device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_PLCP_CRC\n");
9324 if (macstat & BWN_RX_MAC_DECERR)
9325 goto drop;
9326
9327 padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9328 if (m->m_pkthdr.len < (sizeof(struct bwn_plcp6) + padding)) {
9329 device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9330 m->m_pkthdr.len);
9331 goto drop;
9332 }
9333 plcp = (struct bwn_plcp6 *)(mp + padding);
9334 m_adj(m, sizeof(struct bwn_plcp6) + padding);
9335 if (m->m_pkthdr.len < IEEE80211_MIN_LEN) {
9336 device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9337 m->m_pkthdr.len);
9338 goto drop;
9339 }
9340 wh = mtod(m, struct ieee80211_frame_min *);
9341
9342 if (macstat & BWN_RX_MAC_DEC && rx_mac_dec_rpt++ < 50)
9343 device_printf(sc->sc_dev,
9344 "RX decryption attempted (old %d keyidx %#x)\n",
9345 BWN_ISOLDFMT(mac),
9346 (macstat & BWN_RX_MAC_KEYIDX) >> BWN_RX_MAC_KEYIDX_SHIFT);
9347
9348 /* XXX calculating RSSI & noise & antenna */
9349
9350 if (phystat0 & BWN_RX_PHYST0_OFDM)
9351 rate = bwn_plcp_get_ofdmrate(mac, plcp,
9352 phytype == BWN_PHYTYPE_A);
9353 else
9354 rate = bwn_plcp_get_cckrate(mac, plcp);
9355 if (rate == -1) {
9356 if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADPLCP))
9357 goto drop;
9358 }
9359 sc->sc_rx_rate = bwn_hwrate2ieeerate(rate);
9360
9361 /* RX radio tap */
9362 if (ieee80211_radiotap_active(ic))
9363 bwn_rx_radiotap(mac, m, rxhdr, plcp, rate, rssi, noise);
9364 m_adj(m, -IEEE80211_CRC_LEN);
9365
9366 rssi = rxhdr->phy.abg.rssi; /* XXX incorrect RSSI calculation? */
9367 noise = mac->mac_stats.link_noise;
9368
9369 ifp->if_ipackets++;
9370
9371 BWN_UNLOCK(sc);
9372
9373 ni = ieee80211_find_rxnode(ic, wh);
9374 if (ni != NULL) {
9375 type = ieee80211_input(ni, m, rssi, noise);
9376 ieee80211_free_node(ni);
9377 } else
9378 type = ieee80211_input_all(ic, m, rssi, noise);
9379
9380 BWN_LOCK(sc);
9381 return;
9382drop:
9383 device_printf(sc->sc_dev, "%s: dropped\n", __func__);
9384}
9385
9386static void
9387bwn_dma_handle_txeof(struct bwn_mac *mac,
9388 const struct bwn_txstatus *status)
9389{
9390 struct bwn_dma *dma = &mac->mac_method.dma;
9391 struct bwn_dma_ring *dr;
9392 struct bwn_dmadesc_generic *desc;
9393 struct bwn_dmadesc_meta *meta;
9394 struct bwn_softc *sc = mac->mac_sc;
9395 struct ieee80211_node *ni;
9396 struct ifnet *ifp = sc->sc_ifp;
9397 struct mbuf *m;
9398 int slot;
9399
9400 BWN_ASSERT_LOCKED(sc);
9401
9402 dr = bwn_dma_parse_cookie(mac, status, status->cookie, &slot);
9403 if (dr == NULL) {
9404 device_printf(sc->sc_dev, "failed to parse cookie\n");
9405 return;
9406 }
9407 KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
9408
9409 while (1) {
9410 KASSERT(slot >= 0 && slot < dr->dr_numslots,
9411 ("%s:%d: fail", __func__, __LINE__));
9412 dr->getdesc(dr, slot, &desc, &meta);
9413
9414 if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
9415 bus_dmamap_unload(dr->dr_txring_dtag, meta->mt_dmap);
9416 else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
9417 bus_dmamap_unload(dma->txbuf_dtag, meta->mt_dmap);
9418
9419 if (meta->mt_islast) {
9420 KASSERT(meta->mt_m != NULL,
9421 ("%s:%d: fail", __func__, __LINE__));
9422
9423 ni = meta->mt_ni;
9424 m = meta->mt_m;
9425 if (ni != NULL) {
9426 /*
9427 * Do any tx complete callback. Note this must
9428 * be done before releasing the node reference.
9429 */
9430 if (m->m_flags & M_TXCB)
9431 ieee80211_process_callback(ni, m, 0);
9432 ieee80211_free_node(ni);
9433 meta->mt_ni = NULL;
9434 }
9435 m_freem(m);
9436 meta->mt_m = NULL;
9437 } else {
9438 KASSERT(meta->mt_m == NULL,
9439 ("%s:%d: fail", __func__, __LINE__));
9440 }
9441
9442 dr->dr_usedslot--;
9443 if (meta->mt_islast) {
9444 ifp->if_opackets++;
9445 break;
9446 }
9447 slot = bwn_dma_nextslot(dr, slot);
9448 }
9449 sc->sc_watchdog_timer = 0;
9450 if (dr->dr_stop) {
9451 KASSERT(bwn_dma_freeslot(dr) >= BWN_TX_SLOTS_PER_FRAME,
9452 ("%s:%d: fail", __func__, __LINE__));
9453 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
9454 dr->dr_stop = 0;
9455 }
9456}
9457
9458static void
9459bwn_pio_handle_txeof(struct bwn_mac *mac,
9460 const struct bwn_txstatus *status)
9461{
9462 struct bwn_pio_txqueue *tq;
9463 struct bwn_pio_txpkt *tp = NULL;
9464 struct bwn_softc *sc = mac->mac_sc;
9465 struct ifnet *ifp = sc->sc_ifp;
9466
9467 BWN_ASSERT_LOCKED(sc);
9468
9469 tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9470 if (tq == NULL)
9471 return;
9472
9473 tq->tq_used -= roundup(tp->tp_m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
9474 tq->tq_free++;
9475
9476 if (tp->tp_ni != NULL) {
9477 /*
9478 * Do any tx complete callback. Note this must
9479 * be done before releasing the node reference.
9480 */
9481 if (tp->tp_m->m_flags & M_TXCB)
9482 ieee80211_process_callback(tp->tp_ni, tp->tp_m, 0);
9483 ieee80211_free_node(tp->tp_ni);
9484 tp->tp_ni = NULL;
9485 }
9486 m_freem(tp->tp_m);
9487 tp->tp_m = NULL;
9488 TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
9489
9490 ifp->if_opackets++;
9491
9492 sc->sc_watchdog_timer = 0;
9493 if (tq->tq_stop) {
9494 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
9495 tq->tq_stop = 0;
9496 }
9497}
9498
9499static void
9500bwn_phy_txpower_check(struct bwn_mac *mac, uint32_t flags)
9501{
9502 struct bwn_softc *sc = mac->mac_sc;
9503 struct bwn_phy *phy = &mac->mac_phy;
9504 struct ifnet *ifp = sc->sc_ifp;
9505 struct ieee80211com *ic = ifp->if_l2com;
9506 unsigned long now;
9507 int result;
9508
9509 BWN_GETTIME(now);
9510
9511 if (!(flags & BWN_TXPWR_IGNORE_TIME) && time_before(now, phy->nexttime))
9512 return;
9513 phy->nexttime = now + 2 * 1000;
9514
9515 if (siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM &&
9516 siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306)
9517 return;
9518
9519 if (phy->recalc_txpwr != NULL) {
9520 result = phy->recalc_txpwr(mac,
9521 (flags & BWN_TXPWR_IGNORE_TSSI) ? 1 : 0);
9522 if (result == BWN_TXPWR_RES_DONE)
9523 return;
9524 KASSERT(result == BWN_TXPWR_RES_NEED_ADJUST,
9525 ("%s: fail", __func__));
9526 KASSERT(phy->set_txpwr != NULL, ("%s: fail", __func__));
9527
9528 ieee80211_runtask(ic, &mac->mac_txpower);
9529 }
9530}
9531
9532static uint16_t
9533bwn_pio_rx_read_2(struct bwn_pio_rxqueue *prq, uint16_t offset)
9534{
9535
9536 return (BWN_READ_2(prq->prq_mac, prq->prq_base + offset));
9537}
9538
9539static uint32_t
9540bwn_pio_rx_read_4(struct bwn_pio_rxqueue *prq, uint16_t offset)
9541{
9542
9543 return (BWN_READ_4(prq->prq_mac, prq->prq_base + offset));
9544}
9545
9546static void
9547bwn_pio_rx_write_2(struct bwn_pio_rxqueue *prq, uint16_t offset, uint16_t value)
9548{
9549
9550 BWN_WRITE_2(prq->prq_mac, prq->prq_base + offset, value);
9551}
9552
9553static void
9554bwn_pio_rx_write_4(struct bwn_pio_rxqueue *prq, uint16_t offset, uint32_t value)
9555{
9556
9557 BWN_WRITE_4(prq->prq_mac, prq->prq_base + offset, value);
9558}
9559
9560static int
9561bwn_ieeerate2hwrate(struct bwn_softc *sc, int rate)
9562{
9563
9564 switch (rate) {
9565 /* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
9566 case 12:
9567 return (BWN_OFDM_RATE_6MB);
9568 case 18:
9569 return (BWN_OFDM_RATE_9MB);
9570 case 24:
9571 return (BWN_OFDM_RATE_12MB);
9572 case 36:
9573 return (BWN_OFDM_RATE_18MB);
9574 case 48:
9575 return (BWN_OFDM_RATE_24MB);
9576 case 72:
9577 return (BWN_OFDM_RATE_36MB);
9578 case 96:
9579 return (BWN_OFDM_RATE_48MB);
9580 case 108:
9581 return (BWN_OFDM_RATE_54MB);
9582 /* CCK rates (NB: not IEEE std, device-specific) */
9583 case 2:
9584 return (BWN_CCK_RATE_1MB);
9585 case 4:
9586 return (BWN_CCK_RATE_2MB);
9587 case 11:
9588 return (BWN_CCK_RATE_5MB);
9589 case 22:
9590 return (BWN_CCK_RATE_11MB);
9591 }
9592
9593 device_printf(sc->sc_dev, "unsupported rate %d\n", rate);
9594 return (BWN_CCK_RATE_1MB);
9595}
9596
9597static int
9598bwn_set_txhdr(struct bwn_mac *mac, struct ieee80211_node *ni,
9599 struct mbuf *m, struct bwn_txhdr *txhdr, uint16_t cookie)
9600{
9601 const struct bwn_phy *phy = &mac->mac_phy;
9602 struct bwn_softc *sc = mac->mac_sc;
9603 struct ieee80211_frame *wh;
9604 struct ieee80211_frame *protwh;
9605 struct ieee80211_frame_cts *cts;
9606 struct ieee80211_frame_rts *rts;
9607 const struct ieee80211_txparam *tp;
9608 struct ieee80211vap *vap = ni->ni_vap;
9609 struct ifnet *ifp = sc->sc_ifp;
9610 struct ieee80211com *ic = ifp->if_l2com;
9611 struct mbuf *mprot;
9612 unsigned int len;
9613 uint32_t macctl = 0;
9614 int protdur, rts_rate, rts_rate_fb, ismcast, isshort, rix, type;
9615 uint16_t phyctl = 0;
9616 uint8_t rate, rate_fb;
9617
9618 wh = mtod(m, struct ieee80211_frame *);
9619 memset(txhdr, 0, sizeof(*txhdr));
9620
9621 type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
9622 ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
9623 isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0;
9624
9625 /*
9626 * Find TX rate
9627 */
9628 tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)];
9629 if (type != IEEE80211_FC0_TYPE_DATA || (m->m_flags & M_EAPOL))
9630 rate = rate_fb = tp->mgmtrate;
9631 else if (ismcast)
9632 rate = rate_fb = tp->mcastrate;
9633 else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
9634 rate = rate_fb = tp->ucastrate;
9635 else {
9636 rix = ieee80211_ratectl_rate(ni, NULL, 0);
9637 rate = ni->ni_txrate;
9638
9639 if (rix > 0)
9640 rate_fb = ni->ni_rates.rs_rates[rix - 1] &
9641 IEEE80211_RATE_VAL;
9642 else
9643 rate_fb = rate;
9644 }
9645
9646 sc->sc_tx_rate = rate;
9647
9648 rate = bwn_ieeerate2hwrate(sc, rate);
9649 rate_fb = bwn_ieeerate2hwrate(sc, rate_fb);
9650
9651 txhdr->phyrate = (BWN_ISOFDMRATE(rate)) ? bwn_plcp_getofdm(rate) :
9652 bwn_plcp_getcck(rate);
9653 bcopy(wh->i_fc, txhdr->macfc, sizeof(txhdr->macfc));
9654 bcopy(wh->i_addr1, txhdr->addr1, IEEE80211_ADDR_LEN);
9655
9656 if ((rate_fb == rate) ||
9657 (*(u_int16_t *)wh->i_dur & htole16(0x8000)) ||
9658 (*(u_int16_t *)wh->i_dur == htole16(0)))
9659 txhdr->dur_fb = *(u_int16_t *)wh->i_dur;
9660 else
9661 txhdr->dur_fb = ieee80211_compute_duration(ic->ic_rt,
9662 m->m_pkthdr.len, rate, isshort);
9663
9664 /* XXX TX encryption */
9665 bwn_plcp_genhdr(BWN_ISOLDFMT(mac) ?
9666 (struct bwn_plcp4 *)(&txhdr->body.old.plcp) :
9667 (struct bwn_plcp4 *)(&txhdr->body.new.plcp),
9668 m->m_pkthdr.len + IEEE80211_CRC_LEN, rate);
9669 bwn_plcp_genhdr((struct bwn_plcp4 *)(&txhdr->plcp_fb),
9670 m->m_pkthdr.len + IEEE80211_CRC_LEN, rate_fb);
9671
9672 txhdr->eftypes |= (BWN_ISOFDMRATE(rate_fb)) ? BWN_TX_EFT_FB_OFDM :
9673 BWN_TX_EFT_FB_CCK;
9674 txhdr->chan = phy->chan;
9675 phyctl |= (BWN_ISOFDMRATE(rate)) ? BWN_TX_PHY_ENC_OFDM :
9676 BWN_TX_PHY_ENC_CCK;
9677 if (isshort && (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9678 rate == BWN_CCK_RATE_11MB))
9679 phyctl |= BWN_TX_PHY_SHORTPRMBL;
9680
9681 /* XXX TX antenna selection */
9682
9683 switch (bwn_antenna_sanitize(mac, 0)) {
9684 case 0:
9685 phyctl |= BWN_TX_PHY_ANT01AUTO;
9686 break;
9687 case 1:
9688 phyctl |= BWN_TX_PHY_ANT0;
9689 break;
9690 case 2:
9691 phyctl |= BWN_TX_PHY_ANT1;
9692 break;
9693 case 3:
9694 phyctl |= BWN_TX_PHY_ANT2;
9695 break;
9696 case 4:
9697 phyctl |= BWN_TX_PHY_ANT3;
9698 break;
9699 default:
9700 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9701 }
9702
9703 if (!ismcast)
9704 macctl |= BWN_TX_MAC_ACK;
9705
9706 macctl |= (BWN_TX_MAC_HWSEQ | BWN_TX_MAC_START_MSDU);
9707 if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
9708 m->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold)
9709 macctl |= BWN_TX_MAC_LONGFRAME;
9710
9711 if (ic->ic_flags & IEEE80211_F_USEPROT) {
9712 /* XXX RTS rate is always 1MB??? */
9713 rts_rate = BWN_CCK_RATE_1MB;
9714 rts_rate_fb = bwn_get_fbrate(rts_rate);
9715
9716 protdur = ieee80211_compute_duration(ic->ic_rt,
9717 m->m_pkthdr.len, rate, isshort) +
9718 + ieee80211_ack_duration(ic->ic_rt, rate, isshort);
9719
9720 if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) {
9721 cts = (struct ieee80211_frame_cts *)(BWN_ISOLDFMT(mac) ?
9722 (txhdr->body.old.rts_frame) :
9723 (txhdr->body.new.rts_frame));
9724 mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr,
9725 protdur);
9726 KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9727 bcopy(mtod(mprot, uint8_t *), (uint8_t *)cts,
9728 mprot->m_pkthdr.len);
9729 m_freem(mprot);
9730 macctl |= BWN_TX_MAC_SEND_CTSTOSELF;
9731 len = sizeof(struct ieee80211_frame_cts);
9732 } else {
9733 rts = (struct ieee80211_frame_rts *)(BWN_ISOLDFMT(mac) ?
9734 (txhdr->body.old.rts_frame) :
9735 (txhdr->body.new.rts_frame));
9736 protdur += ieee80211_ack_duration(ic->ic_rt, rate,
9737 isshort);
9738 mprot = ieee80211_alloc_rts(ic, wh->i_addr1,
9739 wh->i_addr2, protdur);
9740 KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9741 bcopy(mtod(mprot, uint8_t *), (uint8_t *)rts,
9742 mprot->m_pkthdr.len);
9743 m_freem(mprot);
9744 macctl |= BWN_TX_MAC_SEND_RTSCTS;
9745 len = sizeof(struct ieee80211_frame_rts);
9746 }
9747 len += IEEE80211_CRC_LEN;
9748 bwn_plcp_genhdr((struct bwn_plcp4 *)((BWN_ISOLDFMT(mac)) ?
9749 &txhdr->body.old.rts_plcp :
9750 &txhdr->body.new.rts_plcp), len, rts_rate);
9751 bwn_plcp_genhdr((struct bwn_plcp4 *)&txhdr->rts_plcp_fb, len,
9752 rts_rate_fb);
9753
9754 protwh = (struct ieee80211_frame *)(BWN_ISOLDFMT(mac) ?
9755 (&txhdr->body.old.rts_frame) :
9756 (&txhdr->body.new.rts_frame));
9757 txhdr->rts_dur_fb = *(u_int16_t *)protwh->i_dur;
9758
9759 if (BWN_ISOFDMRATE(rts_rate)) {
9760 txhdr->eftypes |= BWN_TX_EFT_RTS_OFDM;
9761 txhdr->phyrate_rts = bwn_plcp_getofdm(rts_rate);
9762 } else {
9763 txhdr->eftypes |= BWN_TX_EFT_RTS_CCK;
9764 txhdr->phyrate_rts = bwn_plcp_getcck(rts_rate);
9765 }
9766 txhdr->eftypes |= (BWN_ISOFDMRATE(rts_rate_fb)) ?
9767 BWN_TX_EFT_RTS_FBOFDM : BWN_TX_EFT_RTS_FBCCK;
9768 }
9769
9770 if (BWN_ISOLDFMT(mac))
9771 txhdr->body.old.cookie = htole16(cookie);
9772 else
9773 txhdr->body.new.cookie = htole16(cookie);
9774
9775 txhdr->macctl = htole32(macctl);
9776 txhdr->phyctl = htole16(phyctl);
9777
9778 /*
9779 * TX radio tap
9780 */
9781 if (ieee80211_radiotap_active_vap(vap)) {
9782 sc->sc_tx_th.wt_flags = 0;
9783 if (wh->i_fc[1] & IEEE80211_FC1_WEP)
9784 sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP;
9785 if (isshort &&
9786 (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9787 rate == BWN_CCK_RATE_11MB))
9788 sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
9789 sc->sc_tx_th.wt_rate = rate;
9790
9791 ieee80211_radiotap_tx(vap, m);
9792 }
9793
9794 return (0);
9795}
9796
9797static void
9798bwn_plcp_genhdr(struct bwn_plcp4 *plcp, const uint16_t octets,
9799 const uint8_t rate)
9800{
9801 uint32_t d, plen;
9802 uint8_t *raw = plcp->o.raw;
9803
9804 if (BWN_ISOFDMRATE(rate)) {
9805 d = bwn_plcp_getofdm(rate);
9806 KASSERT(!(octets & 0xf000),
9807 ("%s:%d: fail", __func__, __LINE__));
9808 d |= (octets << 5);
9809 plcp->o.data = htole32(d);
9810 } else {
9811 plen = octets * 16 / rate;
9812 if ((octets * 16 % rate) > 0) {
9813 plen++;
9814 if ((rate == BWN_CCK_RATE_11MB)
9815 && ((octets * 8 % 11) < 4)) {
9816 raw[1] = 0x84;
9817 } else
9818 raw[1] = 0x04;
9819 } else
9820 raw[1] = 0x04;
9821 plcp->o.data |= htole32(plen << 16);
9822 raw[0] = bwn_plcp_getcck(rate);
9823 }
9824}
9825
9826static uint8_t
9827bwn_antenna_sanitize(struct bwn_mac *mac, uint8_t n)
9828{
9829 struct bwn_softc *sc = mac->mac_sc;
9830 uint8_t mask;
9831
9832 if (n == 0)
9833 return (0);
9834 if (mac->mac_phy.gmode)
9835 mask = siba_sprom_get_ant_bg(sc->sc_dev);
9836 else
9837 mask = siba_sprom_get_ant_a(sc->sc_dev);
9838 if (!(mask & (1 << (n - 1))))
9839 return (0);
9840 return (n);
9841}
9842
9843static uint8_t
9844bwn_get_fbrate(uint8_t bitrate)
9845{
9846 switch (bitrate) {
9847 case BWN_CCK_RATE_1MB:
9848 return (BWN_CCK_RATE_1MB);
9849 case BWN_CCK_RATE_2MB:
9850 return (BWN_CCK_RATE_1MB);
9851 case BWN_CCK_RATE_5MB:
9852 return (BWN_CCK_RATE_2MB);
9853 case BWN_CCK_RATE_11MB:
9854 return (BWN_CCK_RATE_5MB);
9855 case BWN_OFDM_RATE_6MB:
9856 return (BWN_CCK_RATE_5MB);
9857 case BWN_OFDM_RATE_9MB:
9858 return (BWN_OFDM_RATE_6MB);
9859 case BWN_OFDM_RATE_12MB:
9860 return (BWN_OFDM_RATE_9MB);
9861 case BWN_OFDM_RATE_18MB:
9862 return (BWN_OFDM_RATE_12MB);
9863 case BWN_OFDM_RATE_24MB:
9864 return (BWN_OFDM_RATE_18MB);
9865 case BWN_OFDM_RATE_36MB:
9866 return (BWN_OFDM_RATE_24MB);
9867 case BWN_OFDM_RATE_48MB:
9868 return (BWN_OFDM_RATE_36MB);
9869 case BWN_OFDM_RATE_54MB:
9870 return (BWN_OFDM_RATE_48MB);
9871 }
9872 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9873 return (0);
9874}
9875
9876static uint32_t
9877bwn_pio_write_multi_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9878 uint32_t ctl, const void *_data, int len)
9879{
9880 struct bwn_softc *sc = mac->mac_sc;
9881 uint32_t value = 0;
9882 const uint8_t *data = _data;
9883
9884 ctl |= BWN_PIO8_TXCTL_0_7 | BWN_PIO8_TXCTL_8_15 |
9885 BWN_PIO8_TXCTL_16_23 | BWN_PIO8_TXCTL_24_31;
9886 bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9887
9888 siba_write_multi_4(sc->sc_dev, data, (len & ~3),
9889 tq->tq_base + BWN_PIO8_TXDATA);
9890 if (len & 3) {
9891 ctl &= ~(BWN_PIO8_TXCTL_8_15 | BWN_PIO8_TXCTL_16_23 |
9892 BWN_PIO8_TXCTL_24_31);
9893 data = &(data[len - 1]);
9894 switch (len & 3) {
9895 case 3:
9896 ctl |= BWN_PIO8_TXCTL_16_23;
9897 value |= (uint32_t)(*data) << 16;
9898 data--;
9899 case 2:
9900 ctl |= BWN_PIO8_TXCTL_8_15;
9901 value |= (uint32_t)(*data) << 8;
9902 data--;
9903 case 1:
9904 value |= (uint32_t)(*data);
9905 }
9906 bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9907 bwn_pio_write_4(mac, tq, BWN_PIO8_TXDATA, value);
9908 }
9909
9910 return (ctl);
9911}
9912
9913static void
9914bwn_pio_write_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9915 uint16_t offset, uint32_t value)
9916{
9917
9918 BWN_WRITE_4(mac, tq->tq_base + offset, value);
9919}
9920
9921static uint16_t
9922bwn_pio_write_multi_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9923 uint16_t ctl, const void *_data, int len)
9924{
9925 struct bwn_softc *sc = mac->mac_sc;
9926 const uint8_t *data = _data;
9927
9928 ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
9929 BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9930
9931 siba_write_multi_2(sc->sc_dev, data, (len & ~1),
9932 tq->tq_base + BWN_PIO_TXDATA);
9933 if (len & 1) {
9934 ctl &= ~BWN_PIO_TXCTL_WRITEHI;
9935 BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9936 BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data[len - 1]);
9937 }
9938
9939 return (ctl);
9940}
9941
9942static uint16_t
9943bwn_pio_write_mbuf_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9944 uint16_t ctl, struct mbuf *m0)
9945{
9946 int i, j = 0;
9947 uint16_t data = 0;
9948 const uint8_t *buf;
9949 struct mbuf *m = m0;
9950
9951 ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
9952 BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9953
9954 for (; m != NULL; m = m->m_next) {
9955 buf = mtod(m, const uint8_t *);
9956 for (i = 0; i < m->m_len; i++) {
9957 if (!((j++) % 2))
9958 data |= buf[i];
9959 else {
9960 data |= (buf[i] << 8);
9961 BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
9962 data = 0;
9963 }
9964 }
9965 }
9966 if (m0->m_pkthdr.len % 2) {
9967 ctl &= ~BWN_PIO_TXCTL_WRITEHI;
9968 BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9969 BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
9970 }
9971
9972 return (ctl);
9973}
9974
9975static void
9976bwn_set_slot_time(struct bwn_mac *mac, uint16_t time)
9977{
9978
9979 if (mac->mac_phy.type != BWN_PHYTYPE_G)
9980 return;
9981 BWN_WRITE_2(mac, 0x684, 510 + time);
9982 bwn_shm_write_2(mac, BWN_SHARED, 0x0010, time);
9983}
9984
9985static struct bwn_dma_ring *
9986bwn_dma_select(struct bwn_mac *mac, uint8_t prio)
9987{
9988
9989 if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
9990 return (mac->mac_method.dma.wme[WME_AC_BE]);
9991
9992 switch (prio) {
9993 case 3:
9994 return (mac->mac_method.dma.wme[WME_AC_VO]);
9995 case 2:
9996 return (mac->mac_method.dma.wme[WME_AC_VI]);
9997 case 0:
9998 return (mac->mac_method.dma.wme[WME_AC_BE]);
9999 case 1:
10000 return (mac->mac_method.dma.wme[WME_AC_BK]);
10001 }
10002 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
10003 return (NULL);
10004}
10005
10006static int
10007bwn_dma_getslot(struct bwn_dma_ring *dr)
10008{
10009 int slot;
10010
10011 BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
10012
10013 KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
10014 KASSERT(!(dr->dr_stop), ("%s:%d: fail", __func__, __LINE__));
10015 KASSERT(bwn_dma_freeslot(dr) != 0, ("%s:%d: fail", __func__, __LINE__));
10016
10017 slot = bwn_dma_nextslot(dr, dr->dr_curslot);
10018 KASSERT(!(slot & ~0x0fff), ("%s:%d: fail", __func__, __LINE__));
10019 dr->dr_curslot = slot;
10020 dr->dr_usedslot++;
10021
10022 return (slot);
10023}
10024
10025static int
10026bwn_phy_shm_tssi_read(struct bwn_mac *mac, uint16_t shm_offset)
10027{
10028 const uint8_t ofdm = (shm_offset != BWN_SHARED_TSSI_CCK);
10029 unsigned int a, b, c, d;
10030 unsigned int avg;
10031 uint32_t tmp;
10032
10033 tmp = bwn_shm_read_4(mac, BWN_SHARED, shm_offset);
10034 a = tmp & 0xff;
10035 b = (tmp >> 8) & 0xff;
10036 c = (tmp >> 16) & 0xff;
10037 d = (tmp >> 24) & 0xff;
10038 if (a == 0 || a == BWN_TSSI_MAX || b == 0 || b == BWN_TSSI_MAX ||
10039 c == 0 || c == BWN_TSSI_MAX || d == 0 || d == BWN_TSSI_MAX)
10040 return (ENOENT);
10041 bwn_shm_write_4(mac, BWN_SHARED, shm_offset,
10042 BWN_TSSI_MAX | (BWN_TSSI_MAX << 8) |
10043 (BWN_TSSI_MAX << 16) | (BWN_TSSI_MAX << 24));
10044
10045 if (ofdm) {
10046 a = (a + 32) & 0x3f;
10047 b = (b + 32) & 0x3f;
10048 c = (c + 32) & 0x3f;
10049 d = (d + 32) & 0x3f;
10050 }
10051
10052 avg = (a + b + c + d + 2) / 4;
10053 if (ofdm) {
10054 if (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO)
10055 & BWN_HF_4DB_CCK_POWERBOOST)
10056 avg = (avg >= 13) ? (avg - 13) : 0;
10057 }
10058 return (avg);
10059}
10060
10061static void
10062bwn_phy_g_setatt(struct bwn_mac *mac, int *bbattp, int *rfattp)
10063{
10064 struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
10065 int rfatt = *rfattp;
10066 int bbatt = *bbattp;
10067
10068 while (1) {
10069 if (rfatt > lo->rfatt.max && bbatt > lo->bbatt.max - 4)
10070 break;
10071 if (rfatt < lo->rfatt.min && bbatt < lo->bbatt.min + 4)
10072 break;
10073 if (bbatt > lo->bbatt.max && rfatt > lo->rfatt.max - 1)
10074 break;
10075 if (bbatt < lo->bbatt.min && rfatt < lo->rfatt.min + 1)
10076 break;
10077 if (bbatt > lo->bbatt.max) {
10078 bbatt -= 4;
10079 rfatt += 1;
10080 continue;
10081 }
10082 if (bbatt < lo->bbatt.min) {
10083 bbatt += 4;
10084 rfatt -= 1;
10085 continue;
10086 }
10087 if (rfatt > lo->rfatt.max) {
10088 rfatt -= 1;
10089 bbatt += 4;
10090 continue;
10091 }
10092 if (rfatt < lo->rfatt.min) {
10093 rfatt += 1;
10094 bbatt -= 4;
10095 continue;
10096 }
10097 break;
10098 }
10099
10100 *rfattp = MIN(MAX(rfatt, lo->rfatt.min), lo->rfatt.max);
10101 *bbattp = MIN(MAX(bbatt, lo->bbatt.min), lo->bbatt.max);
10102}
10103
10104static void
10105bwn_phy_lock(struct bwn_mac *mac)
10106{
10107 struct bwn_softc *sc = mac->mac_sc;
10108 struct ieee80211com *ic = sc->sc_ifp->if_l2com;
10109
10110 KASSERT(siba_get_revid(sc->sc_dev) >= 3,
10111 ("%s: unsupported rev %d", __func__, siba_get_revid(sc->sc_dev)));
10112
10113 if (ic->ic_opmode != IEEE80211_M_HOSTAP)
10114 bwn_psctl(mac, BWN_PS_AWAKE);
10115}
10116
10117static void
10118bwn_phy_unlock(struct bwn_mac *mac)
10119{
10120 struct bwn_softc *sc = mac->mac_sc;
10121 struct ieee80211com *ic = sc->sc_ifp->if_l2com;
10122
10123 KASSERT(siba_get_revid(sc->sc_dev) >= 3,
10124 ("%s: unsupported rev %d", __func__, siba_get_revid(sc->sc_dev)));
10125
10126 if (ic->ic_opmode != IEEE80211_M_HOSTAP)
10127 bwn_psctl(mac, 0);
10128}
10129
10130static void
10131bwn_rf_lock(struct bwn_mac *mac)
10132{
10133
10134 BWN_WRITE_4(mac, BWN_MACCTL,
10135 BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_RADIO_LOCK);
10136 BWN_READ_4(mac, BWN_MACCTL);
10137 DELAY(10);
10138}
10139
10140static void
10141bwn_rf_unlock(struct bwn_mac *mac)
10142{
10143
10144 BWN_READ_2(mac, BWN_PHYVER);
10145 BWN_WRITE_4(mac, BWN_MACCTL,
10146 BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_RADIO_LOCK);
10147}
10148
10149static struct bwn_pio_txqueue *
10150bwn_pio_parse_cookie(struct bwn_mac *mac, uint16_t cookie,
10151 struct bwn_pio_txpkt **pack)
10152{
10153 struct bwn_pio *pio = &mac->mac_method.pio;
10154 struct bwn_pio_txqueue *tq = NULL;
10155 unsigned int index;
10156
10157 switch (cookie & 0xf000) {
10158 case 0x1000:
10159 tq = &pio->wme[WME_AC_BK];
10160 break;
10161 case 0x2000:
10162 tq = &pio->wme[WME_AC_BE];
10163 break;
10164 case 0x3000:
10165 tq = &pio->wme[WME_AC_VI];
10166 break;
10167 case 0x4000:
10168 tq = &pio->wme[WME_AC_VO];
10169 break;
10170 case 0x5000:
10171 tq = &pio->mcast;
10172 break;
10173 }
10174 KASSERT(tq != NULL, ("%s:%d: fail", __func__, __LINE__));
10175 if (tq == NULL)
10176 return (NULL);
10177 index = (cookie & 0x0fff);
10178 KASSERT(index < N(tq->tq_pkts), ("%s:%d: fail", __func__, __LINE__));
10179 if (index >= N(tq->tq_pkts))
10180 return (NULL);
10181 *pack = &tq->tq_pkts[index];
10182 KASSERT(*pack != NULL, ("%s:%d: fail", __func__, __LINE__));
10183 return (tq);
10184}
10185
10186static void
10187bwn_txpwr(void *arg, int npending)
10188{
10189 struct bwn_mac *mac = arg;
10190 struct bwn_softc *sc = mac->mac_sc;
10191
10192 BWN_LOCK(sc);
10193 if (mac && mac->mac_status >= BWN_MAC_STATUS_STARTED &&
10194 mac->mac_phy.set_txpwr != NULL)
10195 mac->mac_phy.set_txpwr(mac);
10196 BWN_UNLOCK(sc);
10197}
10198
10199static void
10200bwn_task_15s(struct bwn_mac *mac)
10201{
10202 uint16_t reg;
10203
10204 if (mac->mac_fw.opensource) {
10205 reg = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG);
10206 if (reg) {
10207 bwn_restart(mac, "fw watchdog");
10208 return;
10209 }
10210 bwn_shm_write_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG, 1);
10211 }
10212 if (mac->mac_phy.task_15s)
10213 mac->mac_phy.task_15s(mac);
10214
10215 mac->mac_phy.txerrors = BWN_TXERROR_MAX;
10216}
10217
10218static void
10219bwn_task_30s(struct bwn_mac *mac)
10220{
10221
10222 if (mac->mac_phy.type != BWN_PHYTYPE_G || mac->mac_noise.noi_running)
10223 return;
10224 mac->mac_noise.noi_running = 1;
10225 mac->mac_noise.noi_nsamples = 0;
10226
10227 bwn_noise_gensample(mac);
10228}
10229
10230static void
10231bwn_task_60s(struct bwn_mac *mac)
10232{
10233
10234 if (mac->mac_phy.task_60s)
10235 mac->mac_phy.task_60s(mac);
10236 bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME);
10237}
10238
10239static void
10240bwn_tasks(void *arg)
10241{
10242 struct bwn_mac *mac = arg;
10243 struct bwn_softc *sc = mac->mac_sc;
10244
10245 BWN_ASSERT_LOCKED(sc);
10246 if (mac->mac_status != BWN_MAC_STATUS_STARTED)
10247 return;
10248
10249 if (mac->mac_task_state % 4 == 0)
10250 bwn_task_60s(mac);
10251 if (mac->mac_task_state % 2 == 0)
10252 bwn_task_30s(mac);
10253 bwn_task_15s(mac);
10254
10255 mac->mac_task_state++;
10256 callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
10257}
10258
10259static int
10260bwn_plcp_get_ofdmrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp, uint8_t a)
10261{
10262 struct bwn_softc *sc = mac->mac_sc;
10263
10264 KASSERT(a == 0, ("not support APHY\n"));
10265
10266 switch (plcp->o.raw[0] & 0xf) {
10267 case 0xb:
10268 return (BWN_OFDM_RATE_6MB);
10269 case 0xf:
10270 return (BWN_OFDM_RATE_9MB);
10271 case 0xa:
10272 return (BWN_OFDM_RATE_12MB);
10273 case 0xe:
10274 return (BWN_OFDM_RATE_18MB);
10275 case 0x9:
10276 return (BWN_OFDM_RATE_24MB);
10277 case 0xd:
10278 return (BWN_OFDM_RATE_36MB);
10279 case 0x8:
10280 return (BWN_OFDM_RATE_48MB);
10281 case 0xc:
10282 return (BWN_OFDM_RATE_54MB);
10283 }
10284 device_printf(sc->sc_dev, "incorrect OFDM rate %d\n",
10285 plcp->o.raw[0] & 0xf);
10286 return (-1);
10287}
10288
10289static int
10290bwn_plcp_get_cckrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp)
10291{
10292 struct bwn_softc *sc = mac->mac_sc;
10293
10294 switch (plcp->o.raw[0]) {
10295 case 0x0a:
10296 return (BWN_CCK_RATE_1MB);
10297 case 0x14:
10298 return (BWN_CCK_RATE_2MB);
10299 case 0x37:
10300 return (BWN_CCK_RATE_5MB);
10301 case 0x6e:
10302 return (BWN_CCK_RATE_11MB);
10303 }
10304 device_printf(sc->sc_dev, "incorrect CCK rate %d\n", plcp->o.raw[0]);
10305 return (-1);
10306}
10307
10308static void
10309bwn_rx_radiotap(struct bwn_mac *mac, struct mbuf *m,
10310 const struct bwn_rxhdr4 *rxhdr, struct bwn_plcp6 *plcp, int rate,
10311 int rssi, int noise)
10312{
10313 struct bwn_softc *sc = mac->mac_sc;
10314 const struct ieee80211_frame_min *wh;
10315 uint64_t tsf;
10316 uint16_t low_mactime_now;
10317
10318 if (htole16(rxhdr->phy_status0) & BWN_RX_PHYST0_SHORTPRMBL)
10319 sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
10320
10321 wh = mtod(m, const struct ieee80211_frame_min *);
10322 if (wh->i_fc[1] & IEEE80211_FC1_WEP)
10323 sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_WEP;
10324
10325 bwn_tsf_read(mac, &tsf);
10326 low_mactime_now = tsf;
10327 tsf = tsf & ~0xffffULL;
10328 tsf += le16toh(rxhdr->mac_time);
10329 if (low_mactime_now < le16toh(rxhdr->mac_time))
10330 tsf -= 0x10000;
10331
10332 sc->sc_rx_th.wr_tsf = tsf;
10333 sc->sc_rx_th.wr_rate = rate;
10334 sc->sc_rx_th.wr_antsignal = rssi;
10335 sc->sc_rx_th.wr_antnoise = noise;
10336}
10337
10338static void
10339bwn_tsf_read(struct bwn_mac *mac, uint64_t *tsf)
10340{
10341 uint32_t low, high;
10342
10343 KASSERT(siba_get_revid(mac->mac_sc->sc_dev) >= 3,
10344 ("%s:%d: fail", __func__, __LINE__));
10345
10346 low = BWN_READ_4(mac, BWN_REV3PLUS_TSF_LOW);
10347 high = BWN_READ_4(mac, BWN_REV3PLUS_TSF_HIGH);
10348 *tsf = high;
10349 *tsf <<= 32;
10350 *tsf |= low;
10351}
10352
10353static int
10354bwn_dma_attach(struct bwn_mac *mac)
10355{
10356 struct bwn_dma *dma = &mac->mac_method.dma;
10357 struct bwn_softc *sc = mac->mac_sc;
10358 bus_addr_t lowaddr = 0;
10359 int error;
10360
10361 if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
10362 return (0);
10363
10364 KASSERT(siba_get_revid(sc->sc_dev) >= 5, ("%s: fail", __func__));
10365
10366 mac->mac_flags |= BWN_MAC_FLAG_DMA;
10367
10368 dma->dmatype = bwn_dma_gettype(mac);
10369 if (dma->dmatype == BWN_DMA_30BIT)
10370 lowaddr = BWN_BUS_SPACE_MAXADDR_30BIT;
10371 else if (dma->dmatype == BWN_DMA_32BIT)
10372 lowaddr = BUS_SPACE_MAXADDR_32BIT;
10373 else
10374 lowaddr = BUS_SPACE_MAXADDR;
10375
10376 /*
10377 * Create top level DMA tag
10378 */
10379 error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), /* parent */
10380 BWN_ALIGN, 0, /* alignment, bounds */
10381 lowaddr, /* lowaddr */
10382 BUS_SPACE_MAXADDR, /* highaddr */
10383 NULL, NULL, /* filter, filterarg */
10384 MAXBSIZE, /* maxsize */
10385 BUS_SPACE_UNRESTRICTED, /* nsegments */
10386 BUS_SPACE_MAXSIZE, /* maxsegsize */
10387 0, /* flags */
10388 NULL, NULL, /* lockfunc, lockarg */
10389 &dma->parent_dtag);
10390 if (error) {
10391 device_printf(sc->sc_dev, "can't create parent DMA tag\n");
10392 return (error);
10393 }
10394
10395 /*
10396 * Create TX/RX mbuf DMA tag
10397 */
10398 error = bus_dma_tag_create(dma->parent_dtag,
10399 1,
10400 0,
10401 BUS_SPACE_MAXADDR,
10402 BUS_SPACE_MAXADDR,
10403 NULL, NULL,
10404 MCLBYTES,
10405 1,
10406 BUS_SPACE_MAXSIZE_32BIT,
10407 0,
10408 NULL, NULL,
10409 &dma->rxbuf_dtag);
10410 if (error) {
10411 device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10412 goto fail0;
10413 }
10414 error = bus_dma_tag_create(dma->parent_dtag,
10415 1,
10416 0,
10417 BUS_SPACE_MAXADDR,
10418 BUS_SPACE_MAXADDR,
10419 NULL, NULL,
10420 MCLBYTES,
10421 1,
10422 BUS_SPACE_MAXSIZE_32BIT,
10423 0,
10424 NULL, NULL,
10425 &dma->txbuf_dtag);
10426 if (error) {
10427 device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10428 goto fail1;
10429 }
10430
10431 dma->wme[WME_AC_BK] = bwn_dma_ringsetup(mac, 0, 1, dma->dmatype);
10432 if (!dma->wme[WME_AC_BK])
10433 goto fail2;
10434
10435 dma->wme[WME_AC_BE] = bwn_dma_ringsetup(mac, 1, 1, dma->dmatype);
10436 if (!dma->wme[WME_AC_BE])
10437 goto fail3;
10438
10439 dma->wme[WME_AC_VI] = bwn_dma_ringsetup(mac, 2, 1, dma->dmatype);
10440 if (!dma->wme[WME_AC_VI])
10441 goto fail4;
10442
10443 dma->wme[WME_AC_VO] = bwn_dma_ringsetup(mac, 3, 1, dma->dmatype);
10444 if (!dma->wme[WME_AC_VO])
10445 goto fail5;
10446
10447 dma->mcast = bwn_dma_ringsetup(mac, 4, 1, dma->dmatype);
10448 if (!dma->mcast)
10449 goto fail6;
10450 dma->rx = bwn_dma_ringsetup(mac, 0, 0, dma->dmatype);
10451 if (!dma->rx)
10452 goto fail7;
10453
10454 return (error);
10455
10456fail7: bwn_dma_ringfree(&dma->mcast);
10457fail6: bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
10458fail5: bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
10459fail4: bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
10460fail3: bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
10461fail2: bus_dma_tag_destroy(dma->txbuf_dtag);
10462fail1: bus_dma_tag_destroy(dma->rxbuf_dtag);
10463fail0: bus_dma_tag_destroy(dma->parent_dtag);
10464 return (error);
10465}
10466
10467static struct bwn_dma_ring *
10468bwn_dma_parse_cookie(struct bwn_mac *mac, const struct bwn_txstatus *status,
10469 uint16_t cookie, int *slot)
10470{
10471 struct bwn_dma *dma = &mac->mac_method.dma;
10472 struct bwn_dma_ring *dr;
10473 struct bwn_softc *sc = mac->mac_sc;
10474
10475 BWN_ASSERT_LOCKED(mac->mac_sc);
10476
10477 switch (cookie & 0xf000) {
10478 case 0x1000:
10479 dr = dma->wme[WME_AC_BK];
10480 break;
10481 case 0x2000:
10482 dr = dma->wme[WME_AC_BE];
10483 break;
10484 case 0x3000:
10485 dr = dma->wme[WME_AC_VI];
10486 break;
10487 case 0x4000:
10488 dr = dma->wme[WME_AC_VO];
10489 break;
10490 case 0x5000:
10491 dr = dma->mcast;
10492 break;
10493 default:
10494 dr = NULL;
10495 KASSERT(0 == 1,
10496 ("invalid cookie value %d", cookie & 0xf000));
10497 }
10498 *slot = (cookie & 0x0fff);
10499 if (*slot < 0 || *slot >= dr->dr_numslots) {
10500 /*
10501 * XXX FIXME: sometimes H/W returns TX DONE events duplicately
10502 * that it occurs events which have same H/W sequence numbers.
10503 * When it's occurred just prints a WARNING msgs and ignores.
10504 */
10505 KASSERT(status->seq == dma->lastseq,
10506 ("%s:%d: fail", __func__, __LINE__));
10507 device_printf(sc->sc_dev,
10508 "out of slot ranges (0 < %d < %d)\n", *slot,
10509 dr->dr_numslots);
10510 return (NULL);
10511 }
10512 dma->lastseq = status->seq;
10513 return (dr);
10514}
10515
10516static void
10517bwn_dma_stop(struct bwn_mac *mac)
10518{
10519 struct bwn_dma *dma;
10520
10521 if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
10522 return;
10523 dma = &mac->mac_method.dma;
10524
10525 bwn_dma_ringstop(&dma->rx);
10526 bwn_dma_ringstop(&dma->wme[WME_AC_BK]);
10527 bwn_dma_ringstop(&dma->wme[WME_AC_BE]);
10528 bwn_dma_ringstop(&dma->wme[WME_AC_VI]);
10529 bwn_dma_ringstop(&dma->wme[WME_AC_VO]);
10530 bwn_dma_ringstop(&dma->mcast);
10531}
10532
10533static void
10534bwn_dma_ringstop(struct bwn_dma_ring **dr)
10535{
10536
10537 if (dr == NULL)
10538 return;
10539
10540 bwn_dma_cleanup(*dr);
10541}
10542
10543static void
10544bwn_pio_stop(struct bwn_mac *mac)
10545{
10546 struct bwn_pio *pio;
10547
10548 if (mac->mac_flags & BWN_MAC_FLAG_DMA)
10549 return;
10550 pio = &mac->mac_method.pio;
10551
10552 bwn_destroy_queue_tx(&pio->mcast);
10553 bwn_destroy_queue_tx(&pio->wme[WME_AC_VO]);
10554 bwn_destroy_queue_tx(&pio->wme[WME_AC_VI]);
10555 bwn_destroy_queue_tx(&pio->wme[WME_AC_BE]);
10556 bwn_destroy_queue_tx(&pio->wme[WME_AC_BK]);
10557}
10558
10559static void
10560bwn_led_attach(struct bwn_mac *mac)
10561{
10562 struct bwn_softc *sc = mac->mac_sc;
10563 const uint8_t *led_act = NULL;
10564 uint16_t val[BWN_LED_MAX];
10565 int i;
10566
10567 sc->sc_led_idle = (2350 * hz) / 1000;
10568 sc->sc_led_blink = 1;
10569
10570 for (i = 0; i < N(bwn_vendor_led_act); ++i) {
10571 if (siba_get_pci_subvendor(sc->sc_dev) ==
10572 bwn_vendor_led_act[i].vid) {
10573 led_act = bwn_vendor_led_act[i].led_act;
10574 break;
10575 }
10576 }
10577 if (led_act == NULL)
10578 led_act = bwn_default_led_act;
10579
10580 val[0] = siba_sprom_get_gpio0(sc->sc_dev);
10581 val[1] = siba_sprom_get_gpio1(sc->sc_dev);
10582 val[2] = siba_sprom_get_gpio2(sc->sc_dev);
10583 val[3] = siba_sprom_get_gpio3(sc->sc_dev);
10584
10585 for (i = 0; i < BWN_LED_MAX; ++i) {
10586 struct bwn_led *led = &sc->sc_leds[i];
10587
10588 if (val[i] == 0xff) {
10589 led->led_act = led_act[i];
10590 } else {
10591 if (val[i] & BWN_LED_ACT_LOW)
10592 led->led_flags |= BWN_LED_F_ACTLOW;
10593 led->led_act = val[i] & BWN_LED_ACT_MASK;
10594 }
10595 led->led_mask = (1 << i);
10596
10597 if (led->led_act == BWN_LED_ACT_BLINK_SLOW ||
10598 led->led_act == BWN_LED_ACT_BLINK_POLL ||
10599 led->led_act == BWN_LED_ACT_BLINK) {
10600 led->led_flags |= BWN_LED_F_BLINK;
10601 if (led->led_act == BWN_LED_ACT_BLINK_POLL)
10602 led->led_flags |= BWN_LED_F_POLLABLE;
10603 else if (led->led_act == BWN_LED_ACT_BLINK_SLOW)
10604 led->led_flags |= BWN_LED_F_SLOW;
10605
10606 if (sc->sc_blink_led == NULL) {
10607 sc->sc_blink_led = led;
10608 if (led->led_flags & BWN_LED_F_SLOW)
10609 BWN_LED_SLOWDOWN(sc->sc_led_idle);
10610 }
10611 }
10612
10613 DPRINTF(sc, BWN_DEBUG_LED,
10614 "%dth led, act %d, lowact %d\n", i,
10615 led->led_act, led->led_flags & BWN_LED_F_ACTLOW);
10616 }
10617 callout_init_mtx(&sc->sc_led_blink_ch, &sc->sc_mtx, 0);
10618}
10619
10620static __inline uint16_t
10621bwn_led_onoff(const struct bwn_led *led, uint16_t val, int on)
10622{
10623
10624 if (led->led_flags & BWN_LED_F_ACTLOW)
10625 on = !on;
10626 if (on)
10627 val |= led->led_mask;
10628 else
10629 val &= ~led->led_mask;
10630 return val;
10631}
10632
10633static void
10634bwn_led_newstate(struct bwn_mac *mac, enum ieee80211_state nstate)
10635{
10636 struct bwn_softc *sc = mac->mac_sc;
10637 struct ifnet *ifp = sc->sc_ifp;
10638 struct ieee80211com *ic = ifp->if_l2com;
10639 uint16_t val;
10640 int i;
10641
10642 if (nstate == IEEE80211_S_INIT) {
10643 callout_stop(&sc->sc_led_blink_ch);
10644 sc->sc_led_blinking = 0;
10645 }
10646
10647 if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
10648 return;
10649
10650 val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10651 for (i = 0; i < BWN_LED_MAX; ++i) {
10652 struct bwn_led *led = &sc->sc_leds[i];
10653 int on;
10654
10655 if (led->led_act == BWN_LED_ACT_UNKN ||
10656 led->led_act == BWN_LED_ACT_NULL)
10657 continue;
10658
10659 if ((led->led_flags & BWN_LED_F_BLINK) &&
10660 nstate != IEEE80211_S_INIT)
10661 continue;
10662
10663 switch (led->led_act) {
10664 case BWN_LED_ACT_ON: /* Always on */
10665 on = 1;
10666 break;
10667 case BWN_LED_ACT_OFF: /* Always off */
10668 case BWN_LED_ACT_5GHZ: /* TODO: 11A */
10669 on = 0;
10670 break;
10671 default:
10672 on = 1;
10673 switch (nstate) {
10674 case IEEE80211_S_INIT:
10675 on = 0;
10676 break;
10677 case IEEE80211_S_RUN:
10678 if (led->led_act == BWN_LED_ACT_11G &&
10679 ic->ic_curmode != IEEE80211_MODE_11G)
10680 on = 0;
10681 break;
10682 default:
10683 if (led->led_act == BWN_LED_ACT_ASSOC)
10684 on = 0;
10685 break;
10686 }
10687 break;
10688 }
10689
10690 val = bwn_led_onoff(led, val, on);
10691 }
10692 BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10693}
10694
10695static void
10696bwn_led_event(struct bwn_mac *mac, int event)
10697{
10698 struct bwn_softc *sc = mac->mac_sc;
10699 struct bwn_led *led = sc->sc_blink_led;
10700 int rate;
10701
10702 if (event == BWN_LED_EVENT_POLL) {
10703 if ((led->led_flags & BWN_LED_F_POLLABLE) == 0)
10704 return;
10705 if (ticks - sc->sc_led_ticks < sc->sc_led_idle)
10706 return;
10707 }
10708
10709 sc->sc_led_ticks = ticks;
10710 if (sc->sc_led_blinking)
10711 return;
10712
10713 switch (event) {
10714 case BWN_LED_EVENT_RX:
10715 rate = sc->sc_rx_rate;
10716 break;
10717 case BWN_LED_EVENT_TX:
10718 rate = sc->sc_tx_rate;
10719 break;
10720 case BWN_LED_EVENT_POLL:
10721 rate = 0;
10722 break;
10723 default:
10724 panic("unknown LED event %d\n", event);
10725 break;
10726 }
10727 bwn_led_blink_start(mac, bwn_led_duration[rate].on_dur,
10728 bwn_led_duration[rate].off_dur);
10729}
10730
10731static void
10732bwn_led_blink_start(struct bwn_mac *mac, int on_dur, int off_dur)
10733{
10734 struct bwn_softc *sc = mac->mac_sc;
10735 struct bwn_led *led = sc->sc_blink_led;
10736 uint16_t val;
10737
10738 val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10739 val = bwn_led_onoff(led, val, 1);
10740 BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10741
10742 if (led->led_flags & BWN_LED_F_SLOW) {
10743 BWN_LED_SLOWDOWN(on_dur);
10744 BWN_LED_SLOWDOWN(off_dur);
10745 }
10746
10747 sc->sc_led_blinking = 1;
10748 sc->sc_led_blink_offdur = off_dur;
10749
10750 callout_reset(&sc->sc_led_blink_ch, on_dur, bwn_led_blink_next, mac);
10751}
10752
10753static void
10754bwn_led_blink_next(void *arg)
10755{
10756 struct bwn_mac *mac = arg;
10757 struct bwn_softc *sc = mac->mac_sc;
10758 uint16_t val;
10759
10760 val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10761 val = bwn_led_onoff(sc->sc_blink_led, val, 0);
10762 BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10763
10764 callout_reset(&sc->sc_led_blink_ch, sc->sc_led_blink_offdur,
10765 bwn_led_blink_end, mac);
10766}
10767
10768static void
10769bwn_led_blink_end(void *arg)
10770{
10771 struct bwn_mac *mac = arg;
10772 struct bwn_softc *sc = mac->mac_sc;
10773
10774 sc->sc_led_blinking = 0;
10775}
10776
10777static int
10778bwn_suspend(device_t dev)
10779{
10780 struct bwn_softc *sc = device_get_softc(dev);
10781
10782 bwn_stop(sc, 1);
10783 return (0);
10784}
10785
10786static int
10787bwn_resume(device_t dev)
10788{
10789 struct bwn_softc *sc = device_get_softc(dev);
10790 struct ifnet *ifp = sc->sc_ifp;
10791
10792 if (ifp->if_flags & IFF_UP)
10793 bwn_init(sc);
10794 return (0);
10795}
10796
10797static void
10798bwn_rfswitch(void *arg)
10799{
10800 struct bwn_softc *sc = arg;
10801 struct bwn_mac *mac = sc->sc_curmac;
10802 int cur = 0, prev = 0;
10803
10804 KASSERT(mac->mac_status >= BWN_MAC_STATUS_STARTED,
10805 ("%s: invalid MAC status %d", __func__, mac->mac_status));
10806
10807 if (mac->mac_phy.rf_rev >= 3 || mac->mac_phy.type == BWN_PHYTYPE_LP) {
10808 if (!(BWN_READ_4(mac, BWN_RF_HWENABLED_HI)
10809 & BWN_RF_HWENABLED_HI_MASK))
10810 cur = 1;
10811 } else {
10812 if (BWN_READ_2(mac, BWN_RF_HWENABLED_LO)
10813 & BWN_RF_HWENABLED_LO_MASK)
10814 cur = 1;
10815 }
10816
10817 if (mac->mac_flags & BWN_MAC_FLAG_RADIO_ON)
10818 prev = 1;
10819
10820 if (cur != prev) {
10821 if (cur)
10822 mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
10823 else
10824 mac->mac_flags &= ~BWN_MAC_FLAG_RADIO_ON;
10825
10826 device_printf(sc->sc_dev,
10827 "status of RF switch is changed to %s\n",
10828 cur ? "ON" : "OFF");
10829 if (cur != mac->mac_phy.rf_on) {
10830 if (cur)
10831 bwn_rf_turnon(mac);
10832 else
10833 bwn_rf_turnoff(mac);
10834 }
10835 }
10836
10837 callout_schedule(&sc->sc_rfswitch_ch, hz);
10838}
10839
10840static void
10841bwn_phy_lp_init_pre(struct bwn_mac *mac)
10842{
10843 struct bwn_phy *phy = &mac->mac_phy;
10844 struct bwn_phy_lp *plp = &phy->phy_lp;
10845
10846 plp->plp_antenna = BWN_ANT_DEFAULT;
10847}
10848
10849static int
10850bwn_phy_lp_init(struct bwn_mac *mac)
10851{
10852 static const struct bwn_stxtable tables[] = {
10853 { 2, 6, 0x3d, 3, 0x01 }, { 1, 12, 0x4c, 1, 0x01 },
10854 { 1, 8, 0x50, 0, 0x7f }, { 0, 8, 0x44, 0, 0xff },
10855 { 1, 0, 0x4a, 0, 0xff }, { 0, 4, 0x4d, 0, 0xff },
10856 { 1, 4, 0x4e, 0, 0xff }, { 0, 12, 0x4f, 0, 0x0f },
10857 { 1, 0, 0x4f, 4, 0x0f }, { 3, 0, 0x49, 0, 0x0f },
10858 { 4, 3, 0x46, 4, 0x07 }, { 3, 15, 0x46, 0, 0x01 },
10859 { 4, 0, 0x46, 1, 0x07 }, { 3, 8, 0x48, 4, 0x07 },
10860 { 3, 11, 0x48, 0, 0x0f }, { 3, 4, 0x49, 4, 0x0f },
10861 { 2, 15, 0x45, 0, 0x01 }, { 5, 13, 0x52, 4, 0x07 },
10862 { 6, 0, 0x52, 7, 0x01 }, { 5, 3, 0x41, 5, 0x07 },
10863 { 5, 6, 0x41, 0, 0x0f }, { 5, 10, 0x42, 5, 0x07 },
10864 { 4, 15, 0x42, 0, 0x01 }, { 5, 0, 0x42, 1, 0x07 },
10865 { 4, 11, 0x43, 4, 0x0f }, { 4, 7, 0x43, 0, 0x0f },
10866 { 4, 6, 0x45, 1, 0x01 }, { 2, 7, 0x40, 4, 0x0f },
10867 { 2, 11, 0x40, 0, 0x0f }
10868 };
10869 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
10870 struct bwn_softc *sc = mac->mac_sc;
10871 const struct bwn_stxtable *st;
10872 struct ifnet *ifp = sc->sc_ifp;
10873 struct ieee80211com *ic = ifp->if_l2com;
10874 int i, error;
10875 uint16_t tmp;
10876
10877 bwn_phy_lp_readsprom(mac); /* XXX bad place */
10878 bwn_phy_lp_bbinit(mac);
10879
10880 /* initialize RF */
10881 BWN_PHY_SET(mac, BWN_PHY_4WIRECTL, 0x2);
10882 DELAY(1);
10883 BWN_PHY_MASK(mac, BWN_PHY_4WIRECTL, 0xfffd);
10884 DELAY(1);
10885
10886 if (mac->mac_phy.rf_ver == 0x2062)
10887 bwn_phy_lp_b2062_init(mac);
10888 else {
10889 bwn_phy_lp_b2063_init(mac);
10890
10891 /* synchronize stx table. */
10892 for (i = 0; i < N(tables); i++) {
10893 st = &tables[i];
10894 tmp = BWN_RF_READ(mac, st->st_rfaddr);
10895 tmp >>= st->st_rfshift;
10896 tmp <<= st->st_physhift;
10897 BWN_PHY_SETMASK(mac,
10898 BWN_PHY_OFDM(0xf2 + st->st_phyoffset),
10899 ~(st->st_mask << st->st_physhift), tmp);
10900 }
10901
10902 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf0), 0x5f80);
10903 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf1), 0);
10904 }
10905
10906 /* calibrate RC */
10907 if (mac->mac_phy.rev >= 2)
10908 bwn_phy_lp_rxcal_r2(mac);
10909 else if (!plp->plp_rccap) {
10910 if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
10911 bwn_phy_lp_rccal_r12(mac);
10912 } else
10913 bwn_phy_lp_set_rccap(mac);
10914
10915 error = bwn_phy_lp_switch_channel(mac, 7);
10916 if (error)
10917 device_printf(sc->sc_dev,
10918 "failed to change channel 7 (%d)\n", error);
10919 bwn_phy_lp_txpctl_init(mac);
10920 bwn_phy_lp_calib(mac);
10921 return (0);
10922}
10923
10924static uint16_t
10925bwn_phy_lp_read(struct bwn_mac *mac, uint16_t reg)
10926{
10927
10928 BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10929 return (BWN_READ_2(mac, BWN_PHYDATA));
10930}
10931
10932static void
10933bwn_phy_lp_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
10934{
10935
10936 BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10937 BWN_WRITE_2(mac, BWN_PHYDATA, value);
10938}
10939
10940static void
10941bwn_phy_lp_maskset(struct bwn_mac *mac, uint16_t reg, uint16_t mask,
10942 uint16_t set)
10943{
10944
10945 BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10946 BWN_WRITE_2(mac, BWN_PHYDATA,
10947 (BWN_READ_2(mac, BWN_PHYDATA) & mask) | set);
10948}
10949
10950static uint16_t
10951bwn_phy_lp_rf_read(struct bwn_mac *mac, uint16_t reg)
10952{
10953
10954 KASSERT(reg != 1, ("unaccessible register %d", reg));
10955 if (mac->mac_phy.rev < 2 && reg != 0x4001)
10956 reg |= 0x100;
10957 if (mac->mac_phy.rev >= 2)
10958 reg |= 0x200;
10959 BWN_WRITE_2(mac, BWN_RFCTL, reg);
10960 return BWN_READ_2(mac, BWN_RFDATALO);
10961}
10962
10963static void
10964bwn_phy_lp_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
10965{
10966
10967 KASSERT(reg != 1, ("unaccessible register %d", reg));
10968 BWN_WRITE_2(mac, BWN_RFCTL, reg);
10969 BWN_WRITE_2(mac, BWN_RFDATALO, value);
10970}
10971
10972static void
10973bwn_phy_lp_rf_onoff(struct bwn_mac *mac, int on)
10974{
10975
10976 if (on) {
10977 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xe0ff);
10978 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2,
10979 (mac->mac_phy.rev >= 2) ? 0xf7f7 : 0xffe7);
10980 return;
10981 }
10982
10983 if (mac->mac_phy.rev >= 2) {
10984 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x83ff);
10985 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
10986 BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0x80ff);
10987 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xdfff);
10988 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0808);
10989 return;
10990 }
10991
10992 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xe0ff);
10993 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
10994 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfcff);
10995 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0018);
10996}
10997
10998static int
10999bwn_phy_lp_switch_channel(struct bwn_mac *mac, uint32_t chan)
11000{
11001 struct bwn_phy *phy = &mac->mac_phy;
11002 struct bwn_phy_lp *plp = &phy->phy_lp;
11003 int error;
11004
11005 if (phy->rf_ver == 0x2063) {
11006 error = bwn_phy_lp_b2063_switch_channel(mac, chan);
11007 if (error)
11008 return (error);
11009 } else {
11010 error = bwn_phy_lp_b2062_switch_channel(mac, chan);
11011 if (error)
11012 return (error);
11013 bwn_phy_lp_set_anafilter(mac, chan);
11014 bwn_phy_lp_set_gaintbl(mac, ieee80211_ieee2mhz(chan, 0));
11015 }
11016
11017 plp->plp_chan = chan;
11018 BWN_WRITE_2(mac, BWN_CHANNEL, chan);
11019 return (0);
11020}
11021
11022static uint32_t
11023bwn_phy_lp_get_default_chan(struct bwn_mac *mac)
11024{
11025 struct bwn_softc *sc = mac->mac_sc;
11026 struct ifnet *ifp = sc->sc_ifp;
11027 struct ieee80211com *ic = ifp->if_l2com;
11028
11029 return (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? 1 : 36);
11030}
11031
11032static void
11033bwn_phy_lp_set_antenna(struct bwn_mac *mac, int antenna)
11034{
11035 struct bwn_phy *phy = &mac->mac_phy;
11036 struct bwn_phy_lp *plp = &phy->phy_lp;
11037
11038 if (phy->rev >= 2 || antenna > BWN_ANTAUTO1)
11039 return;
11040
11041 bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER);
11042 BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffd, antenna & 0x2);
11043 BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffe, antenna & 0x1);
11044 bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_UCODE_ANTDIV_HELPER);
11045 plp->plp_antenna = antenna;
11046}
11047
11048static void
11049bwn_phy_lp_task_60s(struct bwn_mac *mac)
11050{
11051
11052 bwn_phy_lp_calib(mac);
11053}
11054
11055static void
11056bwn_phy_lp_readsprom(struct bwn_mac *mac)
11057{
11058 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11059 struct bwn_softc *sc = mac->mac_sc;
11060 struct ifnet *ifp = sc->sc_ifp;
11061 struct ieee80211com *ic = ifp->if_l2com;
11062
11063 if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11064 plp->plp_txisoband_m = siba_sprom_get_tri2g(sc->sc_dev);
11065 plp->plp_bxarch = siba_sprom_get_bxa2g(sc->sc_dev);
11066 plp->plp_rxpwroffset = siba_sprom_get_rxpo2g(sc->sc_dev);
11067 plp->plp_rssivf = siba_sprom_get_rssismf2g(sc->sc_dev);
11068 plp->plp_rssivc = siba_sprom_get_rssismc2g(sc->sc_dev);
11069 plp->plp_rssigs = siba_sprom_get_rssisav2g(sc->sc_dev);
11070 return;
11071 }
11072
11073 plp->plp_txisoband_l = siba_sprom_get_tri5gl(sc->sc_dev);
11074 plp->plp_txisoband_m = siba_sprom_get_tri5g(sc->sc_dev);
11075 plp->plp_txisoband_h = siba_sprom_get_tri5gh(sc->sc_dev);
11076 plp->plp_bxarch = siba_sprom_get_bxa5g(sc->sc_dev);
11077 plp->plp_rxpwroffset = siba_sprom_get_rxpo5g(sc->sc_dev);
11078 plp->plp_rssivf = siba_sprom_get_rssismf5g(sc->sc_dev);
11079 plp->plp_rssivc = siba_sprom_get_rssismc5g(sc->sc_dev);
11080 plp->plp_rssigs = siba_sprom_get_rssisav5g(sc->sc_dev);
11081}
11082
11083static void
11084bwn_phy_lp_bbinit(struct bwn_mac *mac)
11085{
11086
11087 bwn_phy_lp_tblinit(mac);
11088 if (mac->mac_phy.rev >= 2)
11089 bwn_phy_lp_bbinit_r2(mac);
11090 else
11091 bwn_phy_lp_bbinit_r01(mac);
11092}
11093
11094static void
11095bwn_phy_lp_txpctl_init(struct bwn_mac *mac)
11096{
11097 struct bwn_txgain gain_2ghz = { 4, 12, 12, 0 };
11098 struct bwn_txgain gain_5ghz = { 7, 15, 14, 0 };
11099 struct bwn_softc *sc = mac->mac_sc;
11100 struct ifnet *ifp = sc->sc_ifp;
11101 struct ieee80211com *ic = ifp->if_l2com;
11102
11103 bwn_phy_lp_set_txgain(mac,
11104 IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? &gain_2ghz : &gain_5ghz);
11105 bwn_phy_lp_set_bbmult(mac, 150);
11106}
11107
11108static void
11109bwn_phy_lp_calib(struct bwn_mac *mac)
11110{
11111 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11112 struct bwn_softc *sc = mac->mac_sc;
11113 struct ifnet *ifp = sc->sc_ifp;
11114 struct ieee80211com *ic = ifp->if_l2com;
11115 const struct bwn_rxcompco *rc = NULL;
11116 struct bwn_txgain ogain;
11117 int i, omode, oafeovr, orf, obbmult;
11118 uint8_t mode, fc = 0;
11119
11120 if (plp->plp_chanfullcal != plp->plp_chan) {
11121 plp->plp_chanfullcal = plp->plp_chan;
11122 fc = 1;
11123 }
11124
11125 bwn_mac_suspend(mac);
11126
11127 /* BlueTooth Coexistance Override */
11128 BWN_WRITE_2(mac, BWN_BTCOEX_CTL, 0x3);
11129 BWN_WRITE_2(mac, BWN_BTCOEX_TXCTL, 0xff);
11130
11131 if (mac->mac_phy.rev >= 2)
11132 bwn_phy_lp_digflt_save(mac);
11133 bwn_phy_lp_get_txpctlmode(mac);
11134 mode = plp->plp_txpctlmode;
11135 bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11136 if (mac->mac_phy.rev == 0 && mode != BWN_PHYLP_TXPCTL_OFF)
11137 bwn_phy_lp_bugfix(mac);
11138 if (mac->mac_phy.rev >= 2 && fc == 1) {
11139 bwn_phy_lp_get_txpctlmode(mac);
11140 omode = plp->plp_txpctlmode;
11141 oafeovr = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40;
11142 if (oafeovr)
11143 ogain = bwn_phy_lp_get_txgain(mac);
11144 orf = BWN_PHY_READ(mac, BWN_PHY_RF_PWR_OVERRIDE) & 0xff;
11145 obbmult = bwn_phy_lp_get_bbmult(mac);
11146 bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11147 if (oafeovr)
11148 bwn_phy_lp_set_txgain(mac, &ogain);
11149 bwn_phy_lp_set_bbmult(mac, obbmult);
11150 bwn_phy_lp_set_txpctlmode(mac, omode);
11151 BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00, orf);
11152 }
11153 bwn_phy_lp_set_txpctlmode(mac, mode);
11154 if (mac->mac_phy.rev >= 2)
11155 bwn_phy_lp_digflt_restore(mac);
11156
11157 /* do RX IQ Calculation; assumes that noise is true. */
11158 if (siba_get_chipid(sc->sc_dev) == 0x5354) {
11159 for (i = 0; i < N(bwn_rxcompco_5354); i++) {
11160 if (bwn_rxcompco_5354[i].rc_chan == plp->plp_chan)
11161 rc = &bwn_rxcompco_5354[i];
11162 }
11163 } else if (mac->mac_phy.rev >= 2)
11164 rc = &bwn_rxcompco_r2;
11165 else {
11166 for (i = 0; i < N(bwn_rxcompco_r12); i++) {
11167 if (bwn_rxcompco_r12[i].rc_chan == plp->plp_chan)
11168 rc = &bwn_rxcompco_r12[i];
11169 }
11170 }
11171 if (rc == NULL)
11172 goto fail;
11173
11174 BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, rc->rc_c1);
11175 BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, rc->rc_c0 << 8);
11176
11177 bwn_phy_lp_set_trsw_over(mac, 1 /* TX */, 0 /* RX */);
11178
11179 if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11180 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
11181 BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7, 0);
11182 } else {
11183 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
11184 BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf, 0);
11185 }
11186
11187 bwn_phy_lp_set_rxgain(mac, 0x2d5d);
11188 BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11189 BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
11190 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
11191 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
11192 bwn_phy_lp_set_deaf(mac, 0);
11193 /* XXX no checking return value? */
11194 (void)bwn_phy_lp_calc_rx_iq_comp(mac, 0xfff0);
11195 bwn_phy_lp_clear_deaf(mac, 0);
11196 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffc);
11197 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfff7);
11198 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffdf);
11199
11200 /* disable RX GAIN override. */
11201 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffe);
11202 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffef);
11203 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffbf);
11204 if (mac->mac_phy.rev >= 2) {
11205 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11206 if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11207 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfbff);
11208 BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xe5), 0xfff7);
11209 }
11210 } else {
11211 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfdff);
11212 }
11213
11214 BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11215 BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xf7ff);
11216fail:
11217 bwn_mac_enable(mac);
11218}
11219
11220static void
11221bwn_phy_lp_switch_analog(struct bwn_mac *mac, int on)
11222{
11223
11224 if (on) {
11225 BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfff8);
11226 return;
11227 }
11228
11229 BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVRVAL, 0x0007);
11230 BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x0007);
11231}
11232
11233static int
11234bwn_phy_lp_b2063_switch_channel(struct bwn_mac *mac, uint8_t chan)
11235{
11236 static const struct bwn_b206x_chan *bc = NULL;
11237 struct bwn_softc *sc = mac->mac_sc;
11238 uint32_t count, freqref, freqvco, freqxtal, val[3], timeout, timeoutref,
11239 tmp[6];
11240 uint16_t old, scale, tmp16;
11241 int i, div;
11242
11243 for (i = 0; i < N(bwn_b2063_chantable); i++) {
11244 if (bwn_b2063_chantable[i].bc_chan == chan) {
11245 bc = &bwn_b2063_chantable[i];
11246 break;
11247 }
11248 }
11249 if (bc == NULL)
11250 return (EINVAL);
11251
11252 BWN_RF_WRITE(mac, BWN_B2063_LOGEN_VCOBUF1, bc->bc_data[0]);
11253 BWN_RF_WRITE(mac, BWN_B2063_LOGEN_MIXER2, bc->bc_data[1]);
11254 BWN_RF_WRITE(mac, BWN_B2063_LOGEN_BUF2, bc->bc_data[2]);
11255 BWN_RF_WRITE(mac, BWN_B2063_LOGEN_RCCR1, bc->bc_data[3]);
11256 BWN_RF_WRITE(mac, BWN_B2063_A_RX_1ST3, bc->bc_data[4]);
11257 BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND1, bc->bc_data[5]);
11258 BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND4, bc->bc_data[6]);
11259 BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND7, bc->bc_data[7]);
11260 BWN_RF_WRITE(mac, BWN_B2063_A_RX_PS6, bc->bc_data[8]);
11261 BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL2, bc->bc_data[9]);
11262 BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL5, bc->bc_data[10]);
11263 BWN_RF_WRITE(mac, BWN_B2063_PA_CTL11, bc->bc_data[11]);
11264
11265 old = BWN_RF_READ(mac, BWN_B2063_COM15);
11266 BWN_RF_SET(mac, BWN_B2063_COM15, 0x1e);
11267
11268 freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
11269 freqvco = bc->bc_freq << ((bc->bc_freq > 4000) ? 1 : 2);
11270 freqref = freqxtal * 3;
11271 div = (freqxtal <= 26000000 ? 1 : 2);
11272 timeout = ((((8 * freqxtal) / (div * 5000000)) + 1) >> 1) - 1;
11273 timeoutref = ((((8 * freqxtal) / (div * (timeout + 1))) +
11274 999999) / 1000000) + 1;
11275
11276 BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB3, 0x2);
11277 BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB6,
11278 0xfff8, timeout >> 2);
11279 BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11280 0xff9f,timeout << 5);
11281 BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB5, timeoutref);
11282
11283 val[0] = bwn_phy_lp_roundup(freqxtal, 1000000, 16);
11284 val[1] = bwn_phy_lp_roundup(freqxtal, 1000000 * div, 16);
11285 val[2] = bwn_phy_lp_roundup(freqvco, 3, 16);
11286
11287 count = (bwn_phy_lp_roundup(val[2], val[1] + 16, 16) * (timeout + 1) *
11288 (timeoutref + 1)) - 1;
11289 BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11290 0xf0, count >> 8);
11291 BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB8, count & 0xff);
11292
11293 tmp[0] = ((val[2] * 62500) / freqref) << 4;
11294 tmp[1] = ((val[2] * 62500) % freqref) << 4;
11295 while (tmp[1] >= freqref) {
11296 tmp[0]++;
11297 tmp[1] -= freqref;
11298 }
11299 BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG1, 0xffe0, tmp[0] >> 4);
11300 BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfe0f, tmp[0] << 4);
11301 BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfff0, tmp[0] >> 16);
11302 BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG3, (tmp[1] >> 8) & 0xff);
11303 BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG4, tmp[1] & 0xff);
11304
11305 BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF1, 0xb9);
11306 BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF2, 0x88);
11307 BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF3, 0x28);
11308 BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF4, 0x63);
11309
11310 tmp[2] = ((41 * (val[2] - 3000)) /1200) + 27;
11311 tmp[3] = bwn_phy_lp_roundup(132000 * tmp[0], 8451, 16);
11312
11313 if ((tmp[3] + tmp[2] - 1) / tmp[2] > 60) {
11314 scale = 1;
11315 tmp[4] = ((tmp[3] + tmp[2]) / (tmp[2] << 1)) - 8;
11316 } else {
11317 scale = 0;
11318 tmp[4] = ((tmp[3] + (tmp[2] >> 1)) / tmp[2]) - 8;
11319 }
11320 BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffc0, tmp[4]);
11321 BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffbf, scale << 6);
11322
11323 tmp[5] = bwn_phy_lp_roundup(100 * val[0], val[2], 16) * (tmp[4] * 8) *
11324 (scale + 1);
11325 if (tmp[5] > 150)
11326 tmp[5] = 0;
11327
11328 BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffe0, tmp[5]);
11329 BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffdf, scale << 5);
11330
11331 BWN_RF_SETMASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfffb, 0x4);
11332 if (freqxtal > 26000000)
11333 BWN_RF_SET(mac, BWN_B2063_JTAG_XTAL_12, 0x2);
11334 else
11335 BWN_RF_MASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfd);
11336
11337 if (val[0] == 45)
11338 BWN_RF_SET(mac, BWN_B2063_JTAG_VCO1, 0x2);
11339 else
11340 BWN_RF_MASK(mac, BWN_B2063_JTAG_VCO1, 0xfd);
11341
11342 BWN_RF_SET(mac, BWN_B2063_PLL_SP2, 0x3);
11343 DELAY(1);
11344 BWN_RF_MASK(mac, BWN_B2063_PLL_SP2, 0xfffc);
11345
11346 /* VCO Calibration */
11347 BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, ~0x40);
11348 tmp16 = BWN_RF_READ(mac, BWN_B2063_JTAG_CALNRST) & 0xf8;
11349 BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16);
11350 DELAY(1);
11351 BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x4);
11352 DELAY(1);
11353 BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x6);
11354 DELAY(1);
11355 BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x7);
11356 DELAY(300);
11357 BWN_RF_SET(mac, BWN_B2063_PLL_SP1, 0x40);
11358
11359 BWN_RF_WRITE(mac, BWN_B2063_COM15, old);
11360 return (0);
11361}
11362
11363static int
11364bwn_phy_lp_b2062_switch_channel(struct bwn_mac *mac, uint8_t chan)
11365{
11366 struct bwn_softc *sc = mac->mac_sc;
11367 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11368 const struct bwn_b206x_chan *bc = NULL;
11369 uint32_t freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
11370 uint32_t tmp[9];
11371 int i;
11372
11373 for (i = 0; i < N(bwn_b2062_chantable); i++) {
11374 if (bwn_b2062_chantable[i].bc_chan == chan) {
11375 bc = &bwn_b2062_chantable[i];
11376 break;
11377 }
11378 }
11379
11380 if (bc == NULL)
11381 return (EINVAL);
11382
11383 BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL14, 0x04);
11384 BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE0, bc->bc_data[0]);
11385 BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE2, bc->bc_data[1]);
11386 BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE3, bc->bc_data[2]);
11387 BWN_RF_WRITE(mac, BWN_B2062_N_TX_TUNE, bc->bc_data[3]);
11388 BWN_RF_WRITE(mac, BWN_B2062_S_LGENG_CTL1, bc->bc_data[4]);
11389 BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL5, bc->bc_data[5]);
11390 BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL6, bc->bc_data[6]);
11391 BWN_RF_WRITE(mac, BWN_B2062_N_TX_PGA, bc->bc_data[7]);
11392 BWN_RF_WRITE(mac, BWN_B2062_N_TX_PAD, bc->bc_data[8]);
11393
11394 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xcc);
11395 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0x07);
11396 bwn_phy_lp_b2062_reset_pllbias(mac);
11397 tmp[0] = freqxtal / 1000;
11398 tmp[1] = plp->plp_div * 1000;
11399 tmp[2] = tmp[1] * ieee80211_ieee2mhz(chan, 0);
11400 if (ieee80211_ieee2mhz(chan, 0) < 4000)
11401 tmp[2] *= 2;
11402 tmp[3] = 48 * tmp[0];
11403 tmp[5] = tmp[2] / tmp[3];
11404 tmp[6] = tmp[2] % tmp[3];
11405 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL26, tmp[5]);
11406 tmp[4] = tmp[6] * 0x100;
11407 tmp[5] = tmp[4] / tmp[3];
11408 tmp[6] = tmp[4] % tmp[3];
11409 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL27, tmp[5]);
11410 tmp[4] = tmp[6] * 0x100;
11411 tmp[5] = tmp[4] / tmp[3];
11412 tmp[6] = tmp[4] % tmp[3];
11413 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL28, tmp[5]);
11414 tmp[4] = tmp[6] * 0x100;
11415 tmp[5] = tmp[4] / tmp[3];
11416 tmp[6] = tmp[4] % tmp[3];
11417 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL29,
11418 tmp[5] + ((2 * tmp[6]) / tmp[3]));
11419 tmp[7] = BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL19);
11420 tmp[8] = ((2 * tmp[2] * (tmp[7] + 1)) + (3 * tmp[0])) / (6 * tmp[0]);
11421 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL23, (tmp[8] >> 8) + 16);
11422 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL24, tmp[8] & 0xff);
11423
11424 bwn_phy_lp_b2062_vco_calib(mac);
11425 if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11426 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xfc);
11427 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0);
11428 bwn_phy_lp_b2062_reset_pllbias(mac);
11429 bwn_phy_lp_b2062_vco_calib(mac);
11430 if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11431 BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11432 return (EIO);
11433 }
11434 }
11435 BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11436 return (0);
11437}
11438
11439static void
11440bwn_phy_lp_set_anafilter(struct bwn_mac *mac, uint8_t channel)
11441{
11442 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11443 uint16_t tmp = (channel == 14);
11444
11445 if (mac->mac_phy.rev < 2) {
11446 BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xfcff, tmp << 9);
11447 if ((mac->mac_phy.rev == 1) && (plp->plp_rccap))
11448 bwn_phy_lp_set_rccap(mac);
11449 return;
11450 }
11451
11452 BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, 0x3f);
11453}
11454
11455static void
11456bwn_phy_lp_set_gaintbl(struct bwn_mac *mac, uint32_t freq)
11457{
11458 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11459 struct bwn_softc *sc = mac->mac_sc;
11460 struct ifnet *ifp = sc->sc_ifp;
11461 struct ieee80211com *ic = ifp->if_l2com;
11462 uint16_t iso, tmp[3];
11463
11464 KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
11465
11466 if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
11467 iso = plp->plp_txisoband_m;
11468 else if (freq <= 5320)
11469 iso = plp->plp_txisoband_l;
11470 else if (freq <= 5700)
11471 iso = plp->plp_txisoband_m;
11472 else
11473 iso = plp->plp_txisoband_h;
11474
11475 tmp[0] = ((iso - 26) / 12) << 12;
11476 tmp[1] = tmp[0] + 0x1000;
11477 tmp[2] = tmp[0] + 0x2000;
11478
11479 bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), 3, tmp);
11480 bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), 3, tmp);
11481}
11482
11483static void
11484bwn_phy_lp_digflt_save(struct bwn_mac *mac)
11485{
11486 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11487 int i;
11488 static const uint16_t addr[] = {
11489 BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11490 BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11491 BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11492 BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11493 BWN_PHY_OFDM(0xcf),
11494 };
11495 static const uint16_t val[] = {
11496 0xde5e, 0xe832, 0xe331, 0x4d26,
11497 0x0026, 0x1420, 0x0020, 0xfe08,
11498 0x0008,
11499 };
11500
11501 for (i = 0; i < N(addr); i++) {
11502 plp->plp_digfilt[i] = BWN_PHY_READ(mac, addr[i]);
11503 BWN_PHY_WRITE(mac, addr[i], val[i]);
11504 }
11505}
11506
11507static void
11508bwn_phy_lp_get_txpctlmode(struct bwn_mac *mac)
11509{
11510 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11511 struct bwn_softc *sc = mac->mac_sc;
11512 uint16_t ctl;
11513
11514 ctl = BWN_PHY_READ(mac, BWN_PHY_TX_PWR_CTL_CMD);
11515 switch (ctl & BWN_PHY_TX_PWR_CTL_CMD_MODE) {
11516 case BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF:
11517 plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_OFF;
11518 break;
11519 case BWN_PHY_TX_PWR_CTL_CMD_MODE_SW:
11520 plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_SW;
11521 break;
11522 case BWN_PHY_TX_PWR_CTL_CMD_MODE_HW:
11523 plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_HW;
11524 break;
11525 default:
11526 plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_UNKNOWN;
11527 device_printf(sc->sc_dev, "unknown command mode\n");
11528 break;
11529 }
11530}
11531
11532static void
11533bwn_phy_lp_set_txpctlmode(struct bwn_mac *mac, uint8_t mode)
11534{
11535 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11536 uint16_t ctl;
11537 uint8_t old;
11538
11539 bwn_phy_lp_get_txpctlmode(mac);
11540 old = plp->plp_txpctlmode;
11541 if (old == mode)
11542 return;
11543 plp->plp_txpctlmode = mode;
11544
11545 if (old != BWN_PHYLP_TXPCTL_ON_HW && mode == BWN_PHYLP_TXPCTL_ON_HW) {
11546 BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD, 0xff80,
11547 plp->plp_tssiidx);
11548 BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_NNUM,
11549 0x8fff, ((uint16_t)plp->plp_tssinpt << 16));
11550
11551 /* disable TX GAIN override */
11552 if (mac->mac_phy.rev < 2)
11553 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11554 else {
11555 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xff7f);
11556 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xbfff);
11557 }
11558 BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xffbf);
11559
11560 plp->plp_txpwridx = -1;
11561 }
11562 if (mac->mac_phy.rev >= 2) {
11563 if (mode == BWN_PHYLP_TXPCTL_ON_HW)
11564 BWN_PHY_SET(mac, BWN_PHY_OFDM(0xd0), 0x2);
11565 else
11566 BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xd0), 0xfffd);
11567 }
11568
11569 /* writes TX Power Control mode */
11570 switch (plp->plp_txpctlmode) {
11571 case BWN_PHYLP_TXPCTL_OFF:
11572 ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF;
11573 break;
11574 case BWN_PHYLP_TXPCTL_ON_HW:
11575 ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_HW;
11576 break;
11577 case BWN_PHYLP_TXPCTL_ON_SW:
11578 ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_SW;
11579 break;
11580 default:
11581 ctl = 0;
11582 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
11583 }
11584 BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD,
11585 (uint16_t)~BWN_PHY_TX_PWR_CTL_CMD_MODE, ctl);
11586}
11587
11588static void
11589bwn_phy_lp_bugfix(struct bwn_mac *mac)
11590{
11591 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11592 struct bwn_softc *sc = mac->mac_sc;
11593 const unsigned int size = 256;
11594 struct bwn_txgain tg;
11595 uint32_t rxcomp, txgain, coeff, rfpwr, *tabs;
11596 uint16_t tssinpt, tssiidx, value[2];
11597 uint8_t mode;
11598 int8_t txpwridx;
11599
11600 tabs = (uint32_t *)malloc(sizeof(uint32_t) * size, M_DEVBUF,
11601 M_NOWAIT | M_ZERO);
11602 if (tabs == NULL) {
11603 device_printf(sc->sc_dev, "failed to allocate buffer.\n");
11604 return;
11605 }
11606
11607 bwn_phy_lp_get_txpctlmode(mac);
11608 mode = plp->plp_txpctlmode;
11609 txpwridx = plp->plp_txpwridx;
11610 tssinpt = plp->plp_tssinpt;
11611 tssiidx = plp->plp_tssiidx;
11612
11613 bwn_tab_read_multi(mac,
11614 (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11615 BWN_TAB_4(7, 0x140), size, tabs);
11616
11617 bwn_phy_lp_tblinit(mac);
11618 bwn_phy_lp_bbinit(mac);
11619 bwn_phy_lp_txpctl_init(mac);
11620 bwn_phy_lp_rf_onoff(mac, 1);
11621 bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11622
11623 bwn_tab_write_multi(mac,
11624 (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11625 BWN_TAB_4(7, 0x140), size, tabs);
11626
11627 BWN_WRITE_2(mac, BWN_CHANNEL, plp->plp_chan);
11628 plp->plp_tssinpt = tssinpt;
11629 plp->plp_tssiidx = tssiidx;
11630 bwn_phy_lp_set_anafilter(mac, plp->plp_chan);
11631 if (txpwridx != -1) {
11632 /* set TX power by index */
11633 plp->plp_txpwridx = txpwridx;
11634 bwn_phy_lp_get_txpctlmode(mac);
11635 if (plp->plp_txpctlmode != BWN_PHYLP_TXPCTL_OFF)
11636 bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_ON_SW);
11637 if (mac->mac_phy.rev >= 2) {
11638 rxcomp = bwn_tab_read(mac,
11639 BWN_TAB_4(7, txpwridx + 320));
11640 txgain = bwn_tab_read(mac,
11641 BWN_TAB_4(7, txpwridx + 192));
11642 tg.tg_pad = (txgain >> 16) & 0xff;
11643 tg.tg_gm = txgain & 0xff;
11644 tg.tg_pga = (txgain >> 8) & 0xff;
11645 tg.tg_dac = (rxcomp >> 28) & 0xff;
11646 bwn_phy_lp_set_txgain(mac, &tg);
11647 } else {
11648 rxcomp = bwn_tab_read(mac,
11649 BWN_TAB_4(10, txpwridx + 320));
11650 txgain = bwn_tab_read(mac,
11651 BWN_TAB_4(10, txpwridx + 192));
11652 BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
11653 0xf800, (txgain >> 4) & 0x7fff);
11654 bwn_phy_lp_set_txgain_dac(mac, txgain & 0x7);
11655 bwn_phy_lp_set_txgain_pa(mac, (txgain >> 24) & 0x7f);
11656 }
11657 bwn_phy_lp_set_bbmult(mac, (rxcomp >> 20) & 0xff);
11658
11659 /* set TX IQCC */
11660 value[0] = (rxcomp >> 10) & 0x3ff;
11661 value[1] = rxcomp & 0x3ff;
11662 bwn_tab_write_multi(mac, BWN_TAB_2(0, 80), 2, value);
11663
11664 coeff = bwn_tab_read(mac,
11665 (mac->mac_phy.rev >= 2) ? BWN_TAB_4(7, txpwridx + 448) :
11666 BWN_TAB_4(10, txpwridx + 448));
11667 bwn_tab_write(mac, BWN_TAB_2(0, 85), coeff & 0xffff);
11668 if (mac->mac_phy.rev >= 2) {
11669 rfpwr = bwn_tab_read(mac,
11670 BWN_TAB_4(7, txpwridx + 576));
11671 BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00,
11672 rfpwr & 0xffff);
11673 }
11674 bwn_phy_lp_set_txgain_override(mac);
11675 }
11676 if (plp->plp_rccap)
11677 bwn_phy_lp_set_rccap(mac);
11678 bwn_phy_lp_set_antenna(mac, plp->plp_antenna);
11679 bwn_phy_lp_set_txpctlmode(mac, mode);
11680 free(tabs, M_DEVBUF);
11681}
11682
11683static void
11684bwn_phy_lp_digflt_restore(struct bwn_mac *mac)
11685{
11686 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11687 int i;
11688 static const uint16_t addr[] = {
11689 BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11690 BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11691 BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11692 BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11693 BWN_PHY_OFDM(0xcf),
11694 };
11695
11696 for (i = 0; i < N(addr); i++)
11697 BWN_PHY_WRITE(mac, addr[i], plp->plp_digfilt[i]);
11698}
11699
11700static void
11701bwn_phy_lp_tblinit(struct bwn_mac *mac)
11702{
11703 uint32_t freq = ieee80211_ieee2mhz(bwn_phy_lp_get_default_chan(mac), 0);
11704
11705 if (mac->mac_phy.rev < 2) {
11706 bwn_phy_lp_tblinit_r01(mac);
11707 bwn_phy_lp_tblinit_txgain(mac);
11708 bwn_phy_lp_set_gaintbl(mac, freq);
11709 return;
11710 }
11711
11712 bwn_phy_lp_tblinit_r2(mac);
11713 bwn_phy_lp_tblinit_txgain(mac);
11714}
11715
11716struct bwn_wpair {
11717 uint16_t reg;
11718 uint16_t value;
11719};
11720
11721struct bwn_smpair {
11722 uint16_t offset;
11723 uint16_t mask;
11724 uint16_t set;
11725};
11726
11727static void
11728bwn_phy_lp_bbinit_r2(struct bwn_mac *mac)
11729{
11730 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11731 struct bwn_softc *sc = mac->mac_sc;
11732 struct ifnet *ifp = sc->sc_ifp;
11733 struct ieee80211com *ic = ifp->if_l2com;
11734 static const struct bwn_wpair v1[] = {
11735 { BWN_PHY_AFE_DAC_CTL, 0x50 },
11736 { BWN_PHY_AFE_CTL, 0x8800 },
11737 { BWN_PHY_AFE_CTL_OVR, 0 },
11738 { BWN_PHY_AFE_CTL_OVRVAL, 0 },
11739 { BWN_PHY_RF_OVERRIDE_0, 0 },
11740 { BWN_PHY_RF_OVERRIDE_2, 0 },
11741 { BWN_PHY_OFDM(0xf9), 0 },
11742 { BWN_PHY_TR_LOOKUP_1, 0 }
11743 };
11744 static const struct bwn_smpair v2[] = {
11745 { BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0xb4 },
11746 { BWN_PHY_DCOFFSETTRANSIENT, 0xf8ff, 0x200 },
11747 { BWN_PHY_DCOFFSETTRANSIENT, 0xff00, 0x7f },
11748 { BWN_PHY_GAINDIRECTMISMATCH, 0xff0f, 0x40 },
11749 { BWN_PHY_PREAMBLECONFIRMTO, 0xff00, 0x2 }
11750 };
11751 static const struct bwn_smpair v3[] = {
11752 { BWN_PHY_OFDM(0xfe), 0xffe0, 0x1f },
11753 { BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11754 { BWN_PHY_OFDM(0x100), 0xff00, 0x19 },
11755 { BWN_PHY_OFDM(0xff), 0x03ff, 0x3c00 },
11756 { BWN_PHY_OFDM(0xfe), 0xfc1f, 0x3e0 },
11757 { BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11758 { BWN_PHY_OFDM(0x100), 0x00ff, 0x1900 },
11759 { BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800 },
11760 { BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x12 },
11761 { BWN_PHY_GAINMISMATCH, 0x0fff, 0x9000 },
11762
11763 };
11764 int i;
11765
11766 for (i = 0; i < N(v1); i++)
11767 BWN_PHY_WRITE(mac, v1[i].reg, v1[i].value);
11768 BWN_PHY_SET(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x10);
11769 for (i = 0; i < N(v2); i++)
11770 BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask, v2[i].set);
11771
11772 BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x4000);
11773 BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x2000);
11774 BWN_PHY_SET(mac, BWN_PHY_OFDM(0x10a), 0x1);
11775 if (siba_get_pci_revid(sc->sc_dev) >= 0x18) {
11776 bwn_tab_write(mac, BWN_TAB_4(17, 65), 0xec);
11777 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x14);
11778 } else {
11779 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x10);
11780 }
11781 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0xff00, 0xf4);
11782 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0x00ff, 0xf100);
11783 BWN_PHY_WRITE(mac, BWN_PHY_CLIPTHRESH, 0x48);
11784 BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0xff00, 0x46);
11785 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe4), 0xff00, 0x10);
11786 BWN_PHY_SETMASK(mac, BWN_PHY_PWR_THRESH1, 0xfff0, 0x9);
11787 BWN_PHY_MASK(mac, BWN_PHY_GAINDIRECTMISMATCH, ~0xf);
11788 BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5500);
11789 BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0xa0);
11790 BWN_PHY_SETMASK(mac, BWN_PHY_GAINDIRECTMISMATCH, 0xe0ff, 0x300);
11791 BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2a00);
11792 if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11793 (siba_get_chiprev(sc->sc_dev) == 0)) {
11794 BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11795 BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xa);
11796 } else {
11797 BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x1e00);
11798 BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xd);
11799 }
11800 for (i = 0; i < N(v3); i++)
11801 BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask, v3[i].set);
11802 if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11803 (siba_get_chiprev(sc->sc_dev) == 0)) {
11804 bwn_tab_write(mac, BWN_TAB_2(0x08, 0x14), 0);
11805 bwn_tab_write(mac, BWN_TAB_2(0x08, 0x12), 0x40);
11806 }
11807
11808 if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11809 BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x40);
11810 BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0xb00);
11811 BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x6);
11812 BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0x9d00);
11813 BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0xff00, 0xa1);
11814 BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
11815 } else
11816 BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x40);
11817
11818 BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0xff00, 0xb3);
11819 BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00);
11820 BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB, 0xff00, plp->plp_rxpwroffset);
11821 BWN_PHY_SET(mac, BWN_PHY_RESET_CTL, 0x44);
11822 BWN_PHY_WRITE(mac, BWN_PHY_RESET_CTL, 0x80);
11823 BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, 0xa954);
11824 BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_1,
11825 0x2000 | ((uint16_t)plp->plp_rssigs << 10) |
11826 ((uint16_t)plp->plp_rssivc << 4) | plp->plp_rssivf);
11827
11828 if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11829 (siba_get_chiprev(sc->sc_dev) == 0)) {
11830 BWN_PHY_SET(mac, BWN_PHY_AFE_ADC_CTL_0, 0x1c);
11831 BWN_PHY_SETMASK(mac, BWN_PHY_AFE_CTL, 0x00ff, 0x8800);
11832 BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_1, 0xfc3c, 0x0400);
11833 }
11834
11835 bwn_phy_lp_digflt_save(mac);
11836}
11837
11838static void
11839bwn_phy_lp_bbinit_r01(struct bwn_mac *mac)
11840{
11841 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11842 struct bwn_softc *sc = mac->mac_sc;
11843 struct ifnet *ifp = sc->sc_ifp;
11844 struct ieee80211com *ic = ifp->if_l2com;
11845 static const struct bwn_smpair v1[] = {
11846 { BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x0005 },
11847 { BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0x0180 },
11848 { BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x3c00 },
11849 { BWN_PHY_GAINDIRECTMISMATCH, 0xfff0, 0x0005 },
11850 { BWN_PHY_GAIN_MISMATCH_LIMIT, 0xffc0, 0x001a },
11851 { BWN_PHY_CRS_ED_THRESH, 0xff00, 0x00b3 },
11852 { BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00 }
11853 };
11854 static const struct bwn_smpair v2[] = {
11855 { BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11856 { BWN_PHY_TR_LOOKUP_1, 0x3f00, 0x0900 },
11857 { BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11858 { BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11859 { BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x000a },
11860 { BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0400 },
11861 { BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x000a },
11862 { BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0b00 },
11863 { BWN_PHY_TR_LOOKUP_5, 0xffc0, 0x000a },
11864 { BWN_PHY_TR_LOOKUP_5, 0xc0ff, 0x0900 },
11865 { BWN_PHY_TR_LOOKUP_6, 0xffc0, 0x000a },
11866 { BWN_PHY_TR_LOOKUP_6, 0xc0ff, 0x0b00 },
11867 { BWN_PHY_TR_LOOKUP_7, 0xffc0, 0x000a },
11868 { BWN_PHY_TR_LOOKUP_7, 0xc0ff, 0x0900 },
11869 { BWN_PHY_TR_LOOKUP_8, 0xffc0, 0x000a },
11870 { BWN_PHY_TR_LOOKUP_8, 0xc0ff, 0x0b00 }
11871 };
11872 static const struct bwn_smpair v3[] = {
11873 { BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0001 },
11874 { BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0400 },
11875 { BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0001 },
11876 { BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0500 },
11877 { BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11878 { BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0800 },
11879 { BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11880 { BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0a00 }
11881 };
11882 static const struct bwn_smpair v4[] = {
11883 { BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0004 },
11884 { BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0800 },
11885 { BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0004 },
11886 { BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0c00 },
11887 { BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11888 { BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0100 },
11889 { BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11890 { BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0300 }
11891 };
11892 static const struct bwn_smpair v5[] = {
11893 { BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11894 { BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0900 },
11895 { BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11896 { BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11897 { BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0006 },
11898 { BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0500 },
11899 { BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0006 },
11900 { BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0700 }
11901 };
11902 int i;
11903 uint16_t tmp, tmp2;
11904
11905 BWN_PHY_MASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf7ff);
11906 BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL, 0);
11907 BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, 0);
11908 BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, 0);
11909 BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0);
11910 BWN_PHY_SET(mac, BWN_PHY_AFE_DAC_CTL, 0x0004);
11911 BWN_PHY_SETMASK(mac, BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0x0078);
11912 BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800);
11913 BWN_PHY_WRITE(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x0016);
11914 BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_0, 0xfff8, 0x0004);
11915 BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5400);
11916 BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2400);
11917 BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11918 BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0x0006);
11919 BWN_PHY_MASK(mac, BWN_PHY_RX_RADIO_CTL, 0xfffe);
11920 for (i = 0; i < N(v1); i++)
11921 BWN_PHY_SETMASK(mac, v1[i].offset, v1[i].mask, v1[i].set);
11922 BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB,
11923 0xff00, plp->plp_rxpwroffset);
11924 if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM) &&
11925 ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ||
11926 (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_LDO_PAREF))) {
11927 siba_cc_pmu_set_ldovolt(sc->sc_dev, SIBA_LDO_PAREF, 0x28);
11928 siba_cc_pmu_set_ldoparef(sc->sc_dev, 1);
11929 if (mac->mac_phy.rev == 0)
11930 BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT,
11931 0xffcf, 0x0010);
11932 bwn_tab_write(mac, BWN_TAB_2(11, 7), 60);
11933 } else {
11934 siba_cc_pmu_set_ldoparef(sc->sc_dev, 0);
11935 BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT, 0xffcf, 0x0020);
11936 bwn_tab_write(mac, BWN_TAB_2(11, 7), 100);
11937 }
11938 tmp = plp->plp_rssivf | plp->plp_rssivc << 4 | 0xa000;
11939 BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, tmp);
11940 if (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_RSSIINV)
11941 BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x0aaa);
11942 else
11943 BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x02aa);
11944 bwn_tab_write(mac, BWN_TAB_2(11, 1), 24);
11945 BWN_PHY_SETMASK(mac, BWN_PHY_RX_RADIO_CTL,
11946 0xfff9, (plp->plp_bxarch << 1));
11947 if (mac->mac_phy.rev == 1 &&
11948 (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_FEM_BT)) {
11949 for (i = 0; i < N(v2); i++)
11950 BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask,
11951 v2[i].set);
11952 } else if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ||
11953 (siba_get_pci_subdevice(sc->sc_dev) == 0x048a) ||
11954 ((mac->mac_phy.rev == 0) &&
11955 (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM))) {
11956 for (i = 0; i < N(v3); i++)
11957 BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask,
11958 v3[i].set);
11959 } else if (mac->mac_phy.rev == 1 ||
11960 (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM)) {
11961 for (i = 0; i < N(v4); i++)
11962 BWN_PHY_SETMASK(mac, v4[i].offset, v4[i].mask,
11963 v4[i].set);
11964 } else {
11965 for (i = 0; i < N(v5); i++)
11966 BWN_PHY_SETMASK(mac, v5[i].offset, v5[i].mask,
11967 v5[i].set);
11968 }
11969 if (mac->mac_phy.rev == 1 &&
11970 (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_LDO_PAREF)) {
11971 BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_5, BWN_PHY_TR_LOOKUP_1);
11972 BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_6, BWN_PHY_TR_LOOKUP_2);
11973 BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_7, BWN_PHY_TR_LOOKUP_3);
11974 BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_8, BWN_PHY_TR_LOOKUP_4);
11975 }
11976 if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_FEM_BT) &&
11977 (siba_get_chipid(sc->sc_dev) == 0x5354) &&
11978 (siba_get_chippkg(sc->sc_dev) == SIBA_CHIPPACK_BCM4712S)) {
11979 BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0006);
11980 BWN_PHY_WRITE(mac, BWN_PHY_GPIO_SELECT, 0x0005);
11981 BWN_PHY_WRITE(mac, BWN_PHY_GPIO_OUTEN, 0xffff);
11982 bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_PR45960W);
11983 }
11984 if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11985 BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x8000);
11986 BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0040);
11987 BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0xa400);
11988 BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0x0b00);
11989 BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x0007);
11990 BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xfff8, 0x0003);
11991 BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xffc7, 0x0020);
11992 BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
11993 } else {
11994 BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0x7fff);
11995 BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xffbf);
11996 }
11997 if (mac->mac_phy.rev == 1) {
11998 tmp = BWN_PHY_READ(mac, BWN_PHY_CLIPCTRTHRESH);
11999 tmp2 = (tmp & 0x03e0) >> 5;
12000 tmp2 |= tmp2 << 5;
12001 BWN_PHY_WRITE(mac, BWN_PHY_4C3, tmp2);
12002 tmp = BWN_PHY_READ(mac, BWN_PHY_GAINDIRECTMISMATCH);
12003 tmp2 = (tmp & 0x1f00) >> 8;
12004 tmp2 |= tmp2 << 5;
12005 BWN_PHY_WRITE(mac, BWN_PHY_4C4, tmp2);
12006 tmp = BWN_PHY_READ(mac, BWN_PHY_VERYLOWGAINDB);
12007 tmp2 = tmp & 0x00ff;
12008 tmp2 |= tmp << 8;
12009 BWN_PHY_WRITE(mac, BWN_PHY_4C5, tmp2);
12010 }
12011}
12012
12013struct bwn_b2062_freq {
12014 uint16_t freq;
12015 uint8_t value[6];
12016};
12017
12018static void
12019bwn_phy_lp_b2062_init(struct bwn_mac *mac)
12020{
12021#define CALC_CTL7(freq, div) \
12022 (((800000000 * (div) + (freq)) / (2 * (freq)) - 8) & 0xff)
12023#define CALC_CTL18(freq, div) \
12024 ((((100 * (freq) + 16000000 * (div)) / (32000000 * (div))) - 1) & 0xff)
12025#define CALC_CTL19(freq, div) \
12026 ((((2 * (freq) + 1000000 * (div)) / (2000000 * (div))) - 1) & 0xff)
12027 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12028 struct bwn_softc *sc = mac->mac_sc;
12029 struct ifnet *ifp = sc->sc_ifp;
12030 struct ieee80211com *ic = ifp->if_l2com;
12031 static const struct bwn_b2062_freq freqdata_tab[] = {
12032 { 12000, { 6, 6, 6, 6, 10, 6 } },
12033 { 13000, { 4, 4, 4, 4, 11, 7 } },
12034 { 14400, { 3, 3, 3, 3, 12, 7 } },
12035 { 16200, { 3, 3, 3, 3, 13, 8 } },
12036 { 18000, { 2, 2, 2, 2, 14, 8 } },
12037 { 19200, { 1, 1, 1, 1, 14, 9 } }
12038 };
12039 static const struct bwn_wpair v1[] = {
12040 { BWN_B2062_N_TXCTL3, 0 },
12041 { BWN_B2062_N_TXCTL4, 0 },
12042 { BWN_B2062_N_TXCTL5, 0 },
12043 { BWN_B2062_N_TXCTL6, 0 },
12044 { BWN_B2062_N_PDNCTL0, 0x40 },
12045 { BWN_B2062_N_PDNCTL0, 0 },
12046 { BWN_B2062_N_CALIB_TS, 0x10 },
12047 { BWN_B2062_N_CALIB_TS, 0 }
12048 };
12049 const struct bwn_b2062_freq *f = NULL;
12050 uint32_t xtalfreq, ref;
12051 unsigned int i;
12052
12053 bwn_phy_lp_b2062_tblinit(mac);
12054
12055 for (i = 0; i < N(v1); i++)
12056 BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12057 if (mac->mac_phy.rev > 0)
12058 BWN_RF_WRITE(mac, BWN_B2062_S_BG_CTL1,
12059 (BWN_RF_READ(mac, BWN_B2062_N_COM2) >> 1) | 0x80);
12060 if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12061 BWN_RF_SET(mac, BWN_B2062_N_TSSI_CTL0, 0x1);
12062 else
12063 BWN_RF_MASK(mac, BWN_B2062_N_TSSI_CTL0, ~0x1);
12064
12065 KASSERT(siba_get_cc_caps(sc->sc_dev) & SIBA_CC_CAPS_PMU,
12066 ("%s:%d: fail", __func__, __LINE__));
12067 xtalfreq = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
12068 KASSERT(xtalfreq != 0, ("%s:%d: fail", __func__, __LINE__));
12069
12070 if (xtalfreq <= 30000000) {
12071 plp->plp_div = 1;
12072 BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL1, 0xfffb);
12073 } else {
12074 plp->plp_div = 2;
12075 BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL1, 0x4);
12076 }
12077
12078 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL7,
12079 CALC_CTL7(xtalfreq, plp->plp_div));
12080 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL18,
12081 CALC_CTL18(xtalfreq, plp->plp_div));
12082 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL19,
12083 CALC_CTL19(xtalfreq, plp->plp_div));
12084
12085 ref = (1000 * plp->plp_div + 2 * xtalfreq) / (2000 * plp->plp_div);
12086 ref &= 0xffff;
12087 for (i = 0; i < N(freqdata_tab); i++) {
12088 if (ref < freqdata_tab[i].freq) {
12089 f = &freqdata_tab[i];
12090 break;
12091 }
12092 }
12093 if (f == NULL)
12094 f = &freqdata_tab[N(freqdata_tab) - 1];
12095 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL8,
12096 ((uint16_t)(f->value[1]) << 4) | f->value[0]);
12097 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL9,
12098 ((uint16_t)(f->value[3]) << 4) | f->value[2]);
12099 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL10, f->value[4]);
12100 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL11, f->value[5]);
12101#undef CALC_CTL7
12102#undef CALC_CTL18
12103#undef CALC_CTL19
12104}
12105
12106static void
12107bwn_phy_lp_b2063_init(struct bwn_mac *mac)
12108{
12109
12110 bwn_phy_lp_b2063_tblinit(mac);
12111 BWN_RF_WRITE(mac, BWN_B2063_LOGEN_SP5, 0);
12112 BWN_RF_SET(mac, BWN_B2063_COM8, 0x38);
12113 BWN_RF_WRITE(mac, BWN_B2063_REG_SP1, 0x56);
12114 BWN_RF_MASK(mac, BWN_B2063_RX_BB_CTL2, ~0x2);
12115 BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0);
12116 BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP6, 0x20);
12117 BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP9, 0x40);
12118 if (mac->mac_phy.rev == 2) {
12119 BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0xa0);
12120 BWN_RF_WRITE(mac, BWN_B2063_PA_SP4, 0xa0);
12121 BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x18);
12122 } else {
12123 BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0x20);
12124 BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x20);
12125 }
12126}
12127
12128static void
12129bwn_phy_lp_rxcal_r2(struct bwn_mac *mac)
12130{
12131 struct bwn_softc *sc = mac->mac_sc;
12132 static const struct bwn_wpair v1[] = {
12133 { BWN_B2063_RX_BB_SP8, 0x0 },
12134 { BWN_B2063_RC_CALIB_CTL1, 0x7e },
12135 { BWN_B2063_RC_CALIB_CTL1, 0x7c },
12136 { BWN_B2063_RC_CALIB_CTL2, 0x15 },
12137 { BWN_B2063_RC_CALIB_CTL3, 0x70 },
12138 { BWN_B2063_RC_CALIB_CTL4, 0x52 },
12139 { BWN_B2063_RC_CALIB_CTL5, 0x1 },
12140 { BWN_B2063_RC_CALIB_CTL1, 0x7d }
12141 };
12142 static const struct bwn_wpair v2[] = {
12143 { BWN_B2063_TX_BB_SP3, 0x0 },
12144 { BWN_B2063_RC_CALIB_CTL1, 0x7e },
12145 { BWN_B2063_RC_CALIB_CTL1, 0x7c },
12146 { BWN_B2063_RC_CALIB_CTL2, 0x55 },
12147 { BWN_B2063_RC_CALIB_CTL3, 0x76 }
12148 };
12149 uint32_t freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
12150 int i;
12151 uint8_t tmp;
12152
12153 tmp = BWN_RF_READ(mac, BWN_B2063_RX_BB_SP8) & 0xff;
12154
12155 for (i = 0; i < 2; i++)
12156 BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12157 BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, 0xf7);
12158 for (i = 2; i < N(v1); i++)
12159 BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12160 for (i = 0; i < 10000; i++) {
12161 if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12162 break;
12163 DELAY(1000);
12164 }
12165
12166 if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12167 BWN_RF_WRITE(mac, BWN_B2063_RX_BB_SP8, tmp);
12168
12169 tmp = BWN_RF_READ(mac, BWN_B2063_TX_BB_SP3) & 0xff;
12170
12171 for (i = 0; i < N(v2); i++)
12172 BWN_RF_WRITE(mac, v2[i].reg, v2[i].value);
12173 if (freqxtal == 24000000) {
12174 BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0xfc);
12175 BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x0);
12176 } else {
12177 BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0x13);
12178 BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x1);
12179 }
12180 BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0x7d);
12181 for (i = 0; i < 10000; i++) {
12182 if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12183 break;
12184 DELAY(1000);
12185 }
12186 if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12187 BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, tmp);
12188 BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL1, 0x7e);
12189}
12190
12191static void
12192bwn_phy_lp_rccal_r12(struct bwn_mac *mac)
12193{
12194 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12195 struct bwn_softc *sc = mac->mac_sc;
12196 struct bwn_phy_lp_iq_est ie;
12197 struct bwn_txgain tx_gains;
12198 static const uint32_t pwrtbl[21] = {
12199 0x10000, 0x10557, 0x10e2d, 0x113e0, 0x10f22, 0x0ff64,
12200 0x0eda2, 0x0e5d4, 0x0efd1, 0x0fbe8, 0x0b7b8, 0x04b35,
12201 0x01a5e, 0x00a0b, 0x00444, 0x001fd, 0x000ff, 0x00088,
12202 0x0004c, 0x0002c, 0x0001a,
12203 };
12204 uint32_t npwr, ipwr, sqpwr, tmp;
12205 int loopback, i, j, sum, error;
12206 uint16_t save[7];
12207 uint8_t txo, bbmult, txpctlmode;
12208
12209 error = bwn_phy_lp_switch_channel(mac, 7);
12210 if (error)
12211 device_printf(sc->sc_dev,
12212 "failed to change channel to 7 (%d)\n", error);
12213 txo = (BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40) ? 1 : 0;
12214 bbmult = bwn_phy_lp_get_bbmult(mac);
12215 if (txo)
12216 tx_gains = bwn_phy_lp_get_txgain(mac);
12217
12218 save[0] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_0);
12219 save[1] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_VAL_0);
12220 save[2] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR);
12221 save[3] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVRVAL);
12222 save[4] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2);
12223 save[5] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2_VAL);
12224 save[6] = BWN_PHY_READ(mac, BWN_PHY_LP_PHY_CTL);
12225
12226 bwn_phy_lp_get_txpctlmode(mac);
12227 txpctlmode = plp->plp_txpctlmode;
12228 bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
12229
12230 /* disable CRS */
12231 bwn_phy_lp_set_deaf(mac, 1);
12232 bwn_phy_lp_set_trsw_over(mac, 0, 1);
12233 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffb);
12234 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x4);
12235 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7);
12236 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
12237 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x10);
12238 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12239 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf);
12240 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
12241 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffbf);
12242 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12243 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x7);
12244 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x38);
12245 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f);
12246 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x100);
12247 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfdff);
12248 BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL0, 0);
12249 BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL1, 1);
12250 BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL2, 0x20);
12251 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfbff);
12252 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xf7ff);
12253 BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0);
12254 BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, 0x45af);
12255 BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0x3ff);
12256
12257 loopback = bwn_phy_lp_loopback(mac);
12258 if (loopback == -1)
12259 goto done;
12260 bwn_phy_lp_set_rxgain_idx(mac, loopback);
12261 BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xffbf, 0x40);
12262 BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfff8, 0x1);
12263 BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xffc7, 0x8);
12264 BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f, 0xc0);
12265
12266 tmp = 0;
12267 memset(&ie, 0, sizeof(ie));
12268 for (i = 128; i <= 159; i++) {
12269 BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2, i);
12270 sum = 0;
12271 for (j = 5; j <= 25; j++) {
12272 bwn_phy_lp_ddfs_turnon(mac, 1, 1, j, j, 0);
12273 if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
12274 goto done;
12275 sqpwr = ie.ie_ipwr + ie.ie_qpwr;
12276 ipwr = ((pwrtbl[j - 5] >> 3) + 1) >> 1;
12277 npwr = bwn_phy_lp_roundup(sqpwr, (j == 5) ? sqpwr : 0,
12278 12);
12279 sum += ((ipwr - npwr) * (ipwr - npwr));
12280 if ((i == 128) || (sum < tmp)) {
12281 plp->plp_rccap = i;
12282 tmp = sum;
12283 }
12284 }
12285 }
12286 bwn_phy_lp_ddfs_turnoff(mac);
12287done:
12288 /* restore CRS */
12289 bwn_phy_lp_clear_deaf(mac, 1);
12290 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xff80);
12291 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfc00);
12292
12293 BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_VAL_0, save[1]);
12294 BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, save[0]);
12295 BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVRVAL, save[3]);
12296 BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, save[2]);
12297 BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2_VAL, save[5]);
12298 BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, save[4]);
12299 BWN_PHY_WRITE(mac, BWN_PHY_LP_PHY_CTL, save[6]);
12300
12301 bwn_phy_lp_set_bbmult(mac, bbmult);
12302 if (txo)
12303 bwn_phy_lp_set_txgain(mac, &tx_gains);
12304 bwn_phy_lp_set_txpctlmode(mac, txpctlmode);
12305 if (plp->plp_rccap)
12306 bwn_phy_lp_set_rccap(mac);
12307}
12308
12309static void
12310bwn_phy_lp_set_rccap(struct bwn_mac *mac)
12311{
12312 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12313 uint8_t rc_cap = (plp->plp_rccap & 0x1f) >> 1;
12314
12315 if (mac->mac_phy.rev == 1)
12316 rc_cap = MIN(rc_cap + 5, 15);
12317
12318 BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2,
12319 MAX(plp->plp_rccap - 4, 0x80));
12320 BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, rc_cap | 0x80);
12321 BWN_RF_WRITE(mac, BWN_B2062_S_RXG_CNT16,
12322 ((plp->plp_rccap & 0x1f) >> 2) | 0x80);
12323}
12324
12325static uint32_t
12326bwn_phy_lp_roundup(uint32_t value, uint32_t div, uint8_t pre)
12327{
12328 uint32_t i, q, r;
12329
12330 if (div == 0)
12331 return (0);
12332
12333 for (i = 0, q = value / div, r = value % div; i < pre; i++) {
12334 q <<= 1;
12335 if (r << 1 >= div) {
12336 q++;
12337 r = (r << 1) - div;
12338 }
12339 }
12340 if (r << 1 >= div)
12341 q++;
12342 return (q);
12343}
12344
12345static void
12346bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *mac)
12347{
12348 struct bwn_softc *sc = mac->mac_sc;
12349
12350 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0xff);
12351 DELAY(20);
12352 if (siba_get_chipid(sc->sc_dev) == 0x5354) {
12353 BWN_RF_WRITE(mac, BWN_B2062_N_COM1, 4);
12354 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 4);
12355 } else {
12356 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0);
12357 }
12358 DELAY(5);
12359}
12360
12361static void
12362bwn_phy_lp_b2062_vco_calib(struct bwn_mac *mac)
12363{
12364
12365 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x42);
12366 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x62);
12367 DELAY(200);
12368}
12369
12370static void
12371bwn_phy_lp_b2062_tblinit(struct bwn_mac *mac)
12372{
12373#define FLAG_A 0x01
12374#define FLAG_G 0x02
12375 struct bwn_softc *sc = mac->mac_sc;
12376 struct ifnet *ifp = sc->sc_ifp;
12377 struct ieee80211com *ic = ifp->if_l2com;
12378 static const struct bwn_b206x_rfinit_entry bwn_b2062_init_tab[] = {
12379 { BWN_B2062_N_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12380 { BWN_B2062_N_PDNCTL1, 0x0, 0xca, FLAG_G, },
12381 { BWN_B2062_N_PDNCTL3, 0x0, 0x0, FLAG_A | FLAG_G, },
12382 { BWN_B2062_N_PDNCTL4, 0x15, 0x2a, FLAG_A | FLAG_G, },
12383 { BWN_B2062_N_LGENC, 0xDB, 0xff, FLAG_A, },
12384 { BWN_B2062_N_LGENATUNE0, 0xdd, 0x0, FLAG_A | FLAG_G, },
12385 { BWN_B2062_N_LGENATUNE2, 0xdd, 0x0, FLAG_A | FLAG_G, },
12386 { BWN_B2062_N_LGENATUNE3, 0x77, 0xB5, FLAG_A | FLAG_G, },
12387 { BWN_B2062_N_LGENACTL3, 0x0, 0xff, FLAG_A | FLAG_G, },
12388 { BWN_B2062_N_LGENACTL7, 0x33, 0x33, FLAG_A | FLAG_G, },
12389 { BWN_B2062_N_RXA_CTL1, 0x0, 0x0, FLAG_G, },
12390 { BWN_B2062_N_RXBB_CTL0, 0x82, 0x80, FLAG_A | FLAG_G, },
12391 { BWN_B2062_N_RXBB_GAIN1, 0x4, 0x4, FLAG_A | FLAG_G, },
12392 { BWN_B2062_N_RXBB_GAIN2, 0x0, 0x0, FLAG_A | FLAG_G, },
12393 { BWN_B2062_N_TXCTL4, 0x3, 0x3, FLAG_A | FLAG_G, },
12394 { BWN_B2062_N_TXCTL5, 0x2, 0x2, FLAG_A | FLAG_G, },
12395 { BWN_B2062_N_TX_TUNE, 0x88, 0x1b, FLAG_A | FLAG_G, },
12396 { BWN_B2062_S_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12397 { BWN_B2062_S_PDS_CTL0, 0xff, 0xff, FLAG_A | FLAG_G, },
12398 { BWN_B2062_S_LGENG_CTL0, 0xf8, 0xd8, FLAG_A | FLAG_G, },
12399 { BWN_B2062_S_LGENG_CTL1, 0x3c, 0x24, FLAG_A | FLAG_G, },
12400 { BWN_B2062_S_LGENG_CTL8, 0x88, 0x80, FLAG_A | FLAG_G, },
12401 { BWN_B2062_S_LGENG_CTL10, 0x88, 0x80, FLAG_A | FLAG_G, },
12402 { BWN_B2062_S_RFPLLCTL0, 0x98, 0x98, FLAG_A | FLAG_G, },
12403 { BWN_B2062_S_RFPLLCTL1, 0x10, 0x10, FLAG_A | FLAG_G, },
12404 { BWN_B2062_S_RFPLLCTL5, 0x43, 0x43, FLAG_A | FLAG_G, },
12405 { BWN_B2062_S_RFPLLCTL6, 0x47, 0x47, FLAG_A | FLAG_G, },
12406 { BWN_B2062_S_RFPLLCTL7, 0xc, 0xc, FLAG_A | FLAG_G, },
12407 { BWN_B2062_S_RFPLLCTL8, 0x11, 0x11, FLAG_A | FLAG_G, },
12408 { BWN_B2062_S_RFPLLCTL9, 0x11, 0x11, FLAG_A | FLAG_G, },
12409 { BWN_B2062_S_RFPLLCTL10, 0xe, 0xe, FLAG_A | FLAG_G, },
12410 { BWN_B2062_S_RFPLLCTL11, 0x8, 0x8, FLAG_A | FLAG_G, },
12411 { BWN_B2062_S_RFPLLCTL12, 0x33, 0x33, FLAG_A | FLAG_G, },
12412 { BWN_B2062_S_RFPLLCTL13, 0xa, 0xa, FLAG_A | FLAG_G, },
12413 { BWN_B2062_S_RFPLLCTL14, 0x6, 0x6, FLAG_A | FLAG_G, },
12414 { BWN_B2062_S_RFPLLCTL18, 0x3e, 0x3e, FLAG_A | FLAG_G, },
12415 { BWN_B2062_S_RFPLLCTL19, 0x13, 0x13, FLAG_A | FLAG_G, },
12416 { BWN_B2062_S_RFPLLCTL21, 0x62, 0x62, FLAG_A | FLAG_G, },
12417 { BWN_B2062_S_RFPLLCTL22, 0x7, 0x7, FLAG_A | FLAG_G, },
12418 { BWN_B2062_S_RFPLLCTL23, 0x16, 0x16, FLAG_A | FLAG_G, },
12419 { BWN_B2062_S_RFPLLCTL24, 0x5c, 0x5c, FLAG_A | FLAG_G, },
12420 { BWN_B2062_S_RFPLLCTL25, 0x95, 0x95, FLAG_A | FLAG_G, },
12421 { BWN_B2062_S_RFPLLCTL30, 0xa0, 0xa0, FLAG_A | FLAG_G, },
12422 { BWN_B2062_S_RFPLLCTL31, 0x4, 0x4, FLAG_A | FLAG_G, },
12423 { BWN_B2062_S_RFPLLCTL33, 0xcc, 0xcc, FLAG_A | FLAG_G, },
12424 { BWN_B2062_S_RFPLLCTL34, 0x7, 0x7, FLAG_A | FLAG_G, },
12425 { BWN_B2062_S_RXG_CNT8, 0xf, 0xf, FLAG_A, },
12426 };
12427 const struct bwn_b206x_rfinit_entry *br;
12428 unsigned int i;
12429
12430 for (i = 0; i < N(bwn_b2062_init_tab); i++) {
12431 br = &bwn_b2062_init_tab[i];
12432 if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12433 if (br->br_flags & FLAG_G)
12434 BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12435 } else {
12436 if (br->br_flags & FLAG_A)
12437 BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12438 }
12439 }
12440#undef FLAG_A
12441#undef FLAG_B
12442}
12443
12444static void
12445bwn_phy_lp_b2063_tblinit(struct bwn_mac *mac)
12446{
12447#define FLAG_A 0x01
12448#define FLAG_G 0x02
12449 struct bwn_softc *sc = mac->mac_sc;
12450 struct ifnet *ifp = sc->sc_ifp;
12451 struct ieee80211com *ic = ifp->if_l2com;
12452 static const struct bwn_b206x_rfinit_entry bwn_b2063_init_tab[] = {
12453 { BWN_B2063_COM1, 0x0, 0x0, FLAG_G, },
12454 { BWN_B2063_COM10, 0x1, 0x0, FLAG_A, },
12455 { BWN_B2063_COM16, 0x0, 0x0, FLAG_G, },
12456 { BWN_B2063_COM17, 0x0, 0x0, FLAG_G, },
12457 { BWN_B2063_COM18, 0x0, 0x0, FLAG_G, },
12458 { BWN_B2063_COM19, 0x0, 0x0, FLAG_G, },
12459 { BWN_B2063_COM20, 0x0, 0x0, FLAG_G, },
12460 { BWN_B2063_COM21, 0x0, 0x0, FLAG_G, },
12461 { BWN_B2063_COM22, 0x0, 0x0, FLAG_G, },
12462 { BWN_B2063_COM23, 0x0, 0x0, FLAG_G, },
12463 { BWN_B2063_COM24, 0x0, 0x0, FLAG_G, },
12464 { BWN_B2063_LOGEN_SP1, 0xe8, 0xd4, FLAG_A | FLAG_G, },
12465 { BWN_B2063_LOGEN_SP2, 0xa7, 0x53, FLAG_A | FLAG_G, },
12466 { BWN_B2063_LOGEN_SP4, 0xf0, 0xf, FLAG_A | FLAG_G, },
12467 { BWN_B2063_G_RX_SP1, 0x1f, 0x5e, FLAG_G, },
12468 { BWN_B2063_G_RX_SP2, 0x7f, 0x7e, FLAG_G, },
12469 { BWN_B2063_G_RX_SP3, 0x30, 0xf0, FLAG_G, },
12470 { BWN_B2063_G_RX_SP7, 0x7f, 0x7f, FLAG_A | FLAG_G, },
12471 { BWN_B2063_G_RX_SP10, 0xc, 0xc, FLAG_A | FLAG_G, },
12472 { BWN_B2063_A_RX_SP1, 0x3c, 0x3f, FLAG_A, },
12473 { BWN_B2063_A_RX_SP2, 0xfc, 0xfe, FLAG_A, },
12474 { BWN_B2063_A_RX_SP7, 0x8, 0x8, FLAG_A | FLAG_G, },
12475 { BWN_B2063_RX_BB_SP4, 0x60, 0x60, FLAG_A | FLAG_G, },
12476 { BWN_B2063_RX_BB_SP8, 0x30, 0x30, FLAG_A | FLAG_G, },
12477 { BWN_B2063_TX_RF_SP3, 0xc, 0xb, FLAG_A | FLAG_G, },
12478 { BWN_B2063_TX_RF_SP4, 0x10, 0xf, FLAG_A | FLAG_G, },
12479 { BWN_B2063_PA_SP1, 0x3d, 0xfd, FLAG_A | FLAG_G, },
12480 { BWN_B2063_TX_BB_SP1, 0x2, 0x2, FLAG_A | FLAG_G, },
12481 { BWN_B2063_BANDGAP_CTL1, 0x56, 0x56, FLAG_A | FLAG_G, },
12482 { BWN_B2063_JTAG_VCO2, 0xF7, 0xF7, FLAG_A | FLAG_G, },
12483 { BWN_B2063_G_RX_MIX3, 0x71, 0x71, FLAG_A | FLAG_G, },
12484 { BWN_B2063_G_RX_MIX4, 0x71, 0x71, FLAG_A | FLAG_G, },
12485 { BWN_B2063_A_RX_1ST2, 0xf0, 0x30, FLAG_A, },
12486 { BWN_B2063_A_RX_PS6, 0x77, 0x77, FLAG_A | FLAG_G, },
12487 { BWN_B2063_A_RX_MIX4, 0x3, 0x3, FLAG_A | FLAG_G, },
12488 { BWN_B2063_A_RX_MIX5, 0xf, 0xf, FLAG_A | FLAG_G, },
12489 { BWN_B2063_A_RX_MIX6, 0xf, 0xf, FLAG_A | FLAG_G, },
12490 { BWN_B2063_RX_TIA_CTL1, 0x77, 0x77, FLAG_A | FLAG_G, },
12491 { BWN_B2063_RX_TIA_CTL3, 0x77, 0x77, FLAG_A | FLAG_G, },
12492 { BWN_B2063_RX_BB_CTL2, 0x4, 0x4, FLAG_A | FLAG_G, },
12493 { BWN_B2063_PA_CTL1, 0x0, 0x4, FLAG_A, },
12494 { BWN_B2063_VREG_CTL1, 0x3, 0x3, FLAG_A | FLAG_G, },
12495 };
12496 const struct bwn_b206x_rfinit_entry *br;
12497 unsigned int i;
12498
12499 for (i = 0; i < N(bwn_b2063_init_tab); i++) {
12500 br = &bwn_b2063_init_tab[i];
12501 if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12502 if (br->br_flags & FLAG_G)
12503 BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12504 } else {
12505 if (br->br_flags & FLAG_A)
12506 BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12507 }
12508 }
12509#undef FLAG_A
12510#undef FLAG_B
12511}
12512
12513static void
12514bwn_tab_read_multi(struct bwn_mac *mac, uint32_t typenoffset,
12515 int count, void *_data)
12516{
12517 unsigned int i;
12518 uint32_t offset, type;
12519 uint8_t *data = _data;
12520
12521 type = BWN_TAB_GETTYPE(typenoffset);
12522 offset = BWN_TAB_GETOFFSET(typenoffset);
12523 KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12524
12525 BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12526
12527 for (i = 0; i < count; i++) {
12528 switch (type) {
12529 case BWN_TAB_8BIT:
12530 *data = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
12531 data++;
12532 break;
12533 case BWN_TAB_16BIT:
12534 *((uint16_t *)data) = BWN_PHY_READ(mac,
12535 BWN_PHY_TABLEDATALO);
12536 data += 2;
12537 break;
12538 case BWN_TAB_32BIT:
12539 *((uint32_t *)data) = BWN_PHY_READ(mac,
12540 BWN_PHY_TABLEDATAHI);
12541 *((uint32_t *)data) <<= 16;
12542 *((uint32_t *)data) |= BWN_PHY_READ(mac,
12543 BWN_PHY_TABLEDATALO);
12544 data += 4;
12545 break;
12546 default:
12547 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12548 }
12549 }
12550}
12551
12552static void
12553bwn_tab_write_multi(struct bwn_mac *mac, uint32_t typenoffset,
12554 int count, const void *_data)
12555{
12556 uint32_t offset, type, value;
12557 const uint8_t *data = _data;
12558 unsigned int i;
12559
12560 type = BWN_TAB_GETTYPE(typenoffset);
12561 offset = BWN_TAB_GETOFFSET(typenoffset);
12562 KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12563
12564 BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12565
12566 for (i = 0; i < count; i++) {
12567 switch (type) {
12568 case BWN_TAB_8BIT:
12569 value = *data;
12570 data++;
12571 KASSERT(!(value & ~0xff),
12572 ("%s:%d: fail", __func__, __LINE__));
12573 BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12574 break;
12575 case BWN_TAB_16BIT:
12576 value = *((const uint16_t *)data);
12577 data += 2;
12578 KASSERT(!(value & ~0xffff),
12579 ("%s:%d: fail", __func__, __LINE__));
12580 BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12581 break;
12582 case BWN_TAB_32BIT:
12583 value = *((const uint32_t *)data);
12584 data += 4;
12585 BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
12586 BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12587 break;
12588 default:
12589 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12590 }
12591 }
12592}
12593
12594static struct bwn_txgain
12595bwn_phy_lp_get_txgain(struct bwn_mac *mac)
12596{
12597 struct bwn_txgain tg;
12598 uint16_t tmp;
12599
12600 tg.tg_dac = (BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0x380) >> 7;
12601 if (mac->mac_phy.rev < 2) {
12602 tmp = BWN_PHY_READ(mac,
12603 BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL) & 0x7ff;
12604 tg.tg_gm = tmp & 0x0007;
12605 tg.tg_pga = (tmp & 0x0078) >> 3;
12606 tg.tg_pad = (tmp & 0x780) >> 7;
12607 return (tg);
12608 }
12609
12610 tmp = BWN_PHY_READ(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL);
12611 tg.tg_pad = BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0xff;
12612 tg.tg_gm = tmp & 0xff;
12613 tg.tg_pga = (tmp >> 8) & 0xff;
12614 return (tg);
12615}
12616
12617static uint8_t
12618bwn_phy_lp_get_bbmult(struct bwn_mac *mac)
12619{
12620
12621 return (bwn_tab_read(mac, BWN_TAB_2(0, 87)) & 0xff00) >> 8;
12622}
12623
12624static void
12625bwn_phy_lp_set_txgain(struct bwn_mac *mac, struct bwn_txgain *tg)
12626{
12627 uint16_t pa;
12628
12629 if (mac->mac_phy.rev < 2) {
12630 BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0xf800,
12631 (tg->tg_pad << 7) | (tg->tg_pga << 3) | tg->tg_gm);
12632 bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12633 bwn_phy_lp_set_txgain_override(mac);
12634 return;
12635 }
12636
12637 pa = bwn_phy_lp_get_pa_gain(mac);
12638 BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
12639 (tg->tg_pga << 8) | tg->tg_gm);
12640 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0x8000,
12641 tg->tg_pad | (pa << 6));
12642 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xfc), (tg->tg_pga << 8) | tg->tg_gm);
12643 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x8000,
12644 tg->tg_pad | (pa << 8));
12645 bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12646 bwn_phy_lp_set_txgain_override(mac);
12647}
12648
12649static void
12650bwn_phy_lp_set_bbmult(struct bwn_mac *mac, uint8_t bbmult)
12651{
12652
12653 bwn_tab_write(mac, BWN_TAB_2(0, 87), (uint16_t)bbmult << 8);
12654}
12655
12656static void
12657bwn_phy_lp_set_trsw_over(struct bwn_mac *mac, uint8_t tx, uint8_t rx)
12658{
12659 uint16_t trsw = (tx << 1) | rx;
12660
12661 BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffc, trsw);
12662 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x3);
12663}
12664
12665static void
12666bwn_phy_lp_set_rxgain(struct bwn_mac *mac, uint32_t gain)
12667{
12668 struct bwn_softc *sc = mac->mac_sc;
12669 struct ifnet *ifp = sc->sc_ifp;
12670 struct ieee80211com *ic = ifp->if_l2com;
12671 uint16_t ext_lna, high_gain, lna, low_gain, trsw, tmp;
12672
12673 if (mac->mac_phy.rev < 2) {
12674 trsw = gain & 0x1;
12675 lna = (gain & 0xfffc) | ((gain & 0xc) >> 2);
12676 ext_lna = (gain & 2) >> 1;
12677
12678 BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12679 BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12680 0xfbff, ext_lna << 10);
12681 BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12682 0xf7ff, ext_lna << 11);
12683 BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, lna);
12684 } else {
12685 low_gain = gain & 0xffff;
12686 high_gain = (gain >> 16) & 0xf;
12687 ext_lna = (gain >> 21) & 0x1;
12688 trsw = ~(gain >> 20) & 0x1;
12689
12690 BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12691 BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12692 0xfdff, ext_lna << 9);
12693 BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12694 0xfbff, ext_lna << 10);
12695 BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, low_gain);
12696 BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff0, high_gain);
12697 if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12698 tmp = (gain >> 2) & 0x3;
12699 BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12700 0xe7ff, tmp<<11);
12701 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe6), 0xffe7,
12702 tmp << 3);
12703 }
12704 }
12705
12706 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1);
12707 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12708 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12709 if (mac->mac_phy.rev >= 2) {
12710 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
12711 if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12712 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x400);
12713 BWN_PHY_SET(mac, BWN_PHY_OFDM(0xe5), 0x8);
12714 }
12715 return;
12716 }
12717 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x200);
12718}
12719
12720static void
12721bwn_phy_lp_set_deaf(struct bwn_mac *mac, uint8_t user)
12722{
12723 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12724
12725 if (user)
12726 plp->plp_crsusr_off = 1;
12727 else
12728 plp->plp_crssys_off = 1;
12729
12730 BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x80);
12731}
12732
12733static void
12734bwn_phy_lp_clear_deaf(struct bwn_mac *mac, uint8_t user)
12735{
12736 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12737 struct bwn_softc *sc = mac->mac_sc;
12738 struct ifnet *ifp = sc->sc_ifp;
12739 struct ieee80211com *ic = ifp->if_l2com;
12740
12741 if (user)
12742 plp->plp_crsusr_off = 0;
12743 else
12744 plp->plp_crssys_off = 0;
12745
12746 if (plp->plp_crsusr_off || plp->plp_crssys_off)
12747 return;
12748
12749 if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12750 BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x60);
12751 else
12752 BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x20);
12753}
12754
12755static unsigned int
12756bwn_sqrt(struct bwn_mac *mac, unsigned int x)
12757{
12758 /* Table holding (10 * sqrt(x)) for x between 1 and 256. */
12759 static uint8_t sqrt_table[256] = {
12760 10, 14, 17, 20, 22, 24, 26, 28,
12761 30, 31, 33, 34, 36, 37, 38, 40,
12762 41, 42, 43, 44, 45, 46, 47, 48,
12763 50, 50, 51, 52, 53, 54, 55, 56,
12764 57, 58, 59, 60, 60, 61, 62, 63,
12765 64, 64, 65, 66, 67, 67, 68, 69,
12766 70, 70, 71, 72, 72, 73, 74, 74,
12767 75, 76, 76, 77, 78, 78, 79, 80,
12768 80, 81, 81, 82, 83, 83, 84, 84,
12769 85, 86, 86, 87, 87, 88, 88, 89,
12770 90, 90, 91, 91, 92, 92, 93, 93,
12771 94, 94, 95, 95, 96, 96, 97, 97,
12772 98, 98, 99, 100, 100, 100, 101, 101,
12773 102, 102, 103, 103, 104, 104, 105, 105,
12774 106, 106, 107, 107, 108, 108, 109, 109,
12775 110, 110, 110, 111, 111, 112, 112, 113,
12776 113, 114, 114, 114, 115, 115, 116, 116,
12777 117, 117, 117, 118, 118, 119, 119, 120,
12778 120, 120, 121, 121, 122, 122, 122, 123,
12779 123, 124, 124, 124, 125, 125, 126, 126,
12780 126, 127, 127, 128, 128, 128, 129, 129,
12781 130, 130, 130, 131, 131, 131, 132, 132,
12782 133, 133, 133, 134, 134, 134, 135, 135,
12783 136, 136, 136, 137, 137, 137, 138, 138,
12784 138, 139, 139, 140, 140, 140, 141, 141,
12785 141, 142, 142, 142, 143, 143, 143, 144,
12786 144, 144, 145, 145, 145, 146, 146, 146,
12787 147, 147, 147, 148, 148, 148, 149, 149,
12788 150, 150, 150, 150, 151, 151, 151, 152,
12789 152, 152, 153, 153, 153, 154, 154, 154,
12790 155, 155, 155, 156, 156, 156, 157, 157,
12791 157, 158, 158, 158, 159, 159, 159, 160
12792 };
12793
12794 if (x == 0)
12795 return (0);
12796 if (x >= 256) {
12797 unsigned int tmp;
12798
12799 for (tmp = 0; x >= (2 * tmp) + 1; x -= (2 * tmp++) + 1)
12800 /* do nothing */ ;
12801 return (tmp);
12802 }
12803 return (sqrt_table[x - 1] / 10);
12804}
12805
12806static int
12807bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *mac, uint16_t sample)
12808{
12809#define CALC_COEFF(_v, _x, _y, _z) do { \
12810 int _t; \
12811 _t = _x - 20; \
12812 if (_t >= 0) { \
12813 _v = ((_y << (30 - _x)) + (_z >> (1 + _t))) / (_z >> _t); \
12814 } else { \
12815 _v = ((_y << (30 - _x)) + (_z << (-1 - _t))) / (_z << -_t); \
12816 } \
12817} while (0)
12818#define CALC_COEFF2(_v, _x, _y, _z) do { \
12819 int _t; \
12820 _t = _x - 11; \
12821 if (_t >= 0) \
12822 _v = (_y << (31 - _x)) / (_z >> _t); \
12823 else \
12824 _v = (_y << (31 - _x)) / (_z << -_t); \
12825} while (0)
12826 struct bwn_phy_lp_iq_est ie;
12827 uint16_t v0, v1;
12828 int tmp[2], ret;
12829
12830 v1 = BWN_PHY_READ(mac, BWN_PHY_RX_COMP_COEFF_S);
12831 v0 = v1 >> 8;
12832 v1 |= 0xff;
12833
12834 BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, 0x00c0);
12835 BWN_PHY_MASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff);
12836
12837 ret = bwn_phy_lp_rx_iq_est(mac, sample, 32, &ie);
12838 if (ret == 0)
12839 goto done;
12840
12841 if (ie.ie_ipwr + ie.ie_qpwr < 2) {
12842 ret = 0;
12843 goto done;
12844 }
12845
12846 CALC_COEFF(tmp[0], bwn_nbits(ie.ie_iqprod), ie.ie_iqprod, ie.ie_ipwr);
12847 CALC_COEFF2(tmp[1], bwn_nbits(ie.ie_qpwr), ie.ie_qpwr, ie.ie_ipwr);
12848
12849 tmp[1] = -bwn_sqrt(mac, tmp[1] - (tmp[0] * tmp[0]));
12850 v0 = tmp[0] >> 3;
12851 v1 = tmp[1] >> 4;
12852done:
12853 BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, v1);
12854 BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, v0 << 8);
12855 return ret;
12856#undef CALC_COEFF
12857#undef CALC_COEFF2
12858}
12859
12860static void
12861bwn_phy_lp_tblinit_r01(struct bwn_mac *mac)
12862{
12863 static const uint16_t noisescale[] = {
12864 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12865 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa400, 0xa4a4, 0xa4a4,
12866 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12867 0xa4a4, 0xa4a4, 0x00a4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12868 0x0000, 0x0000, 0x4c00, 0x2d36, 0x0000, 0x0000, 0x4c00, 0x2d36,
12869 };
12870 static const uint16_t crsgainnft[] = {
12871 0x0366, 0x036a, 0x036f, 0x0364, 0x0367, 0x036d, 0x0374, 0x037f,
12872 0x036f, 0x037b, 0x038a, 0x0378, 0x0367, 0x036d, 0x0375, 0x0381,
12873 0x0374, 0x0381, 0x0392, 0x03a9, 0x03c4, 0x03e1, 0x0001, 0x001f,
12874 0x0040, 0x005e, 0x007f, 0x009e, 0x00bd, 0x00dd, 0x00fd, 0x011d,
12875 0x013d,
12876 };
12877 static const uint16_t filterctl[] = {
12878 0xa0fc, 0x10fc, 0x10db, 0x20b7, 0xff93, 0x10bf, 0x109b, 0x2077,
12879 0xff53, 0x0127,
12880 };
12881 static const uint32_t psctl[] = {
12882 0x00010000, 0x000000a0, 0x00040000, 0x00000048, 0x08080101,
12883 0x00000080, 0x08080101, 0x00000040, 0x08080101, 0x000000c0,
12884 0x08a81501, 0x000000c0, 0x0fe8fd01, 0x000000c0, 0x08300105,
12885 0x000000c0, 0x08080201, 0x000000c0, 0x08280205, 0x000000c0,
12886 0xe80802fe, 0x000000c7, 0x28080206, 0x000000c0, 0x08080202,
12887 0x000000c0, 0x0ba87602, 0x000000c0, 0x1068013d, 0x000000c0,
12888 0x10280105, 0x000000c0, 0x08880102, 0x000000c0, 0x08280106,
12889 0x000000c0, 0xe80801fd, 0x000000c7, 0xa8080115, 0x000000c0,
12890 };
12891 static const uint16_t ofdmcckgain_r0[] = {
12892 0x0001, 0x0001, 0x0001, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12893 0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12894 0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12895 0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12896 0x755d,
12897 };
12898 static const uint16_t ofdmcckgain_r1[] = {
12899 0x5000, 0x6000, 0x7000, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12900 0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12901 0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12902 0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12903 0x755d,
12904 };
12905 static const uint16_t gaindelta[] = {
12906 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12907 0x0000,
12908 };
12909 static const uint32_t txpwrctl[] = {
12910 0x00000050, 0x0000004f, 0x0000004e, 0x0000004d, 0x0000004c,
12911 0x0000004b, 0x0000004a, 0x00000049, 0x00000048, 0x00000047,
12912 0x00000046, 0x00000045, 0x00000044, 0x00000043, 0x00000042,
12913 0x00000041, 0x00000040, 0x0000003f, 0x0000003e, 0x0000003d,
12914 0x0000003c, 0x0000003b, 0x0000003a, 0x00000039, 0x00000038,
12915 0x00000037, 0x00000036, 0x00000035, 0x00000034, 0x00000033,
12916 0x00000032, 0x00000031, 0x00000030, 0x0000002f, 0x0000002e,
12917 0x0000002d, 0x0000002c, 0x0000002b, 0x0000002a, 0x00000029,
12918 0x00000028, 0x00000027, 0x00000026, 0x00000025, 0x00000024,
12919 0x00000023, 0x00000022, 0x00000021, 0x00000020, 0x0000001f,
12920 0x0000001e, 0x0000001d, 0x0000001c, 0x0000001b, 0x0000001a,
12921 0x00000019, 0x00000018, 0x00000017, 0x00000016, 0x00000015,
12922 0x00000014, 0x00000013, 0x00000012, 0x00000011, 0x00000000,
12923 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12924 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12925 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12926 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12927 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12928 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12929 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12930 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12931 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12932 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12933 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12934 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12935 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12936 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12937 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12938 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12939 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12940 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12941 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12942 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12943 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12944 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12945 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12946 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12947 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12948 0x00000000, 0x00000000, 0x000075a0, 0x000075a0, 0x000075a1,
12949 0x000075a1, 0x000075a2, 0x000075a2, 0x000075a3, 0x000075a3,
12950 0x000074b0, 0x000074b0, 0x000074b1, 0x000074b1, 0x000074b2,
12951 0x000074b2, 0x000074b3, 0x000074b3, 0x00006d20, 0x00006d20,
12952 0x00006d21, 0x00006d21, 0x00006d22, 0x00006d22, 0x00006d23,
12953 0x00006d23, 0x00004660, 0x00004660, 0x00004661, 0x00004661,
12954 0x00004662, 0x00004662, 0x00004663, 0x00004663, 0x00003e60,
12955 0x00003e60, 0x00003e61, 0x00003e61, 0x00003e62, 0x00003e62,
12956 0x00003e63, 0x00003e63, 0x00003660, 0x00003660, 0x00003661,
12957 0x00003661, 0x00003662, 0x00003662, 0x00003663, 0x00003663,
12958 0x00002e60, 0x00002e60, 0x00002e61, 0x00002e61, 0x00002e62,
12959 0x00002e62, 0x00002e63, 0x00002e63, 0x00002660, 0x00002660,
12960 0x00002661, 0x00002661, 0x00002662, 0x00002662, 0x00002663,
12961 0x00002663, 0x000025e0, 0x000025e0, 0x000025e1, 0x000025e1,
12962 0x000025e2, 0x000025e2, 0x000025e3, 0x000025e3, 0x00001de0,
12963 0x00001de0, 0x00001de1, 0x00001de1, 0x00001de2, 0x00001de2,
12964 0x00001de3, 0x00001de3, 0x00001d60, 0x00001d60, 0x00001d61,
12965 0x00001d61, 0x00001d62, 0x00001d62, 0x00001d63, 0x00001d63,
12966 0x00001560, 0x00001560, 0x00001561, 0x00001561, 0x00001562,
12967 0x00001562, 0x00001563, 0x00001563, 0x00000d60, 0x00000d60,
12968 0x00000d61, 0x00000d61, 0x00000d62, 0x00000d62, 0x00000d63,
12969 0x00000d63, 0x00000ce0, 0x00000ce0, 0x00000ce1, 0x00000ce1,
12970 0x00000ce2, 0x00000ce2, 0x00000ce3, 0x00000ce3, 0x00000e10,
12971 0x00000e10, 0x00000e11, 0x00000e11, 0x00000e12, 0x00000e12,
12972 0x00000e13, 0x00000e13, 0x00000bf0, 0x00000bf0, 0x00000bf1,
12973 0x00000bf1, 0x00000bf2, 0x00000bf2, 0x00000bf3, 0x00000bf3,
12974 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12975 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12976 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12977 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12978 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12979 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12980 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12981 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12982 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12983 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12984 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12985 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12986 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12987 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12988 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12989 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12990 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12991 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12992 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12993 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12994 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12995 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12996 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12997 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12998 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12999 0x04000000, 0x04200000, 0x04000000, 0x000000ff, 0x000002fc,
13000 0x0000fa08, 0x00000305, 0x00000206, 0x00000304, 0x0000fb04,
13001 0x0000fcff, 0x000005fb, 0x0000fd01, 0x00000401, 0x00000006,
13002 0x0000ff03, 0x000007fc, 0x0000fc08, 0x00000203, 0x0000fffb,
13003 0x00000600, 0x0000fa01, 0x0000fc03, 0x0000fe06, 0x0000fe00,
13004 0x00000102, 0x000007fd, 0x000004fb, 0x000006ff, 0x000004fd,
13005 0x0000fdfa, 0x000007fb, 0x0000fdfa, 0x0000fa06, 0x00000500,
13006 0x0000f902, 0x000007fa, 0x0000fafa, 0x00000500, 0x000007fa,
13007 0x00000700, 0x00000305, 0x000004ff, 0x00000801, 0x00000503,
13008 0x000005f9, 0x00000404, 0x0000fb08, 0x000005fd, 0x00000501,
13009 0x00000405, 0x0000fb03, 0x000007fc, 0x00000403, 0x00000303,
13010 0x00000402, 0x0000faff, 0x0000fe05, 0x000005fd, 0x0000fe01,
13011 0x000007fa, 0x00000202, 0x00000504, 0x00000102, 0x000008fe,
13012 0x0000fa04, 0x0000fafc, 0x0000fe08, 0x000000f9, 0x000002fa,
13013 0x000003fe, 0x00000304, 0x000004f9, 0x00000100, 0x0000fd06,
13014 0x000008fc, 0x00000701, 0x00000504, 0x0000fdfe, 0x0000fdfc,
13015 0x000003fe, 0x00000704, 0x000002fc, 0x000004f9, 0x0000fdfd,
13016 0x0000fa07, 0x00000205, 0x000003fd, 0x000005fb, 0x000004f9,
13017 0x00000804, 0x0000fc06, 0x0000fcf9, 0x00000100, 0x0000fe05,
13018 0x00000408, 0x0000fb02, 0x00000304, 0x000006fe, 0x000004fa,
13019 0x00000305, 0x000008fc, 0x00000102, 0x000001fd, 0x000004fc,
13020 0x0000fe03, 0x00000701, 0x000001fb, 0x000001f9, 0x00000206,
13021 0x000006fd, 0x00000508, 0x00000700, 0x00000304, 0x000005fe,
13022 0x000005ff, 0x0000fa04, 0x00000303, 0x0000fefb, 0x000007f9,
13023 0x0000fefc, 0x000004fd, 0x000005fc, 0x0000fffd, 0x0000fc08,
13024 0x0000fbf9, 0x0000fd07, 0x000008fb, 0x0000fe02, 0x000006fb,
13025 0x00000702,
13026 };
13027
13028 KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13029
13030 bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13031 bwn_tab_sigsq_tbl);
13032 bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13033 bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(crsgainnft), crsgainnft);
13034 bwn_tab_write_multi(mac, BWN_TAB_2(8, 0), N(filterctl), filterctl);
13035 bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(psctl), psctl);
13036 bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13037 bwn_tab_pllfrac_tbl);
13038 bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13039 bwn_tabl_iqlocal_tbl);
13040 if (mac->mac_phy.rev == 0) {
13041 bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r0),
13042 ofdmcckgain_r0);
13043 bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r0),
13044 ofdmcckgain_r0);
13045 } else {
13046 bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r1),
13047 ofdmcckgain_r1);
13048 bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r1),
13049 ofdmcckgain_r1);
13050 }
13051 bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(gaindelta), gaindelta);
13052 bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(txpwrctl), txpwrctl);
13053}
13054
13055static void
13056bwn_phy_lp_tblinit_r2(struct bwn_mac *mac)
13057{
13058 struct bwn_softc *sc = mac->mac_sc;
13059 int i;
13060 static const uint16_t noisescale[] = {
13061 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13062 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13063 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13064 0x00a4, 0x00a4, 0x0000, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13065 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13066 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13067 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4
13068 };
13069 static const uint32_t filterctl[] = {
13070 0x000141fc, 0x000021fc, 0x000021b7, 0x0000416f, 0x0001ff27,
13071 0x0000217f, 0x00002137, 0x000040ef, 0x0001fea7, 0x0000024f
13072 };
13073 static const uint32_t psctl[] = {
13074 0x00e38e08, 0x00e08e38, 0x00000000, 0x00000000, 0x00000000,
13075 0x00002080, 0x00006180, 0x00003002, 0x00000040, 0x00002042,
13076 0x00180047, 0x00080043, 0x00000041, 0x000020c1, 0x00046006,
13077 0x00042002, 0x00040000, 0x00002003, 0x00180006, 0x00080002
13078 };
13079 static const uint32_t gainidx[] = {
13080 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13081 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13082 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13083 0x00000000, 0x00000000, 0x00000000, 0x10000001, 0x00000000,
13084 0x20000082, 0x00000000, 0x40000104, 0x00000000, 0x60004207,
13085 0x00000001, 0x7000838a, 0x00000001, 0xd021050d, 0x00000001,
13086 0xe041c683, 0x00000001, 0x50828805, 0x00000000, 0x80e34288,
13087 0x00000000, 0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000,
13088 0x12064711, 0x00000001, 0xb0a18612, 0x00000010, 0xe1024794,
13089 0x00000010, 0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011,
13090 0xc1848a9c, 0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21,
13091 0x00000019, 0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019,
13092 0xb36811a6, 0x00000019, 0xf3e89227, 0x00000019, 0x0408d329,
13093 0x0000001a, 0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a,
13094 0x54aa152c, 0x0000001a, 0x64ca55ad, 0x0000001a, 0x00000000,
13095 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13096 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13097 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13098 0x00000000, 0x00000000, 0x10000001, 0x00000000, 0x20000082,
13099 0x00000000, 0x40000104, 0x00000000, 0x60004207, 0x00000001,
13100 0x7000838a, 0x00000001, 0xd021050d, 0x00000001, 0xe041c683,
13101 0x00000001, 0x50828805, 0x00000000, 0x80e34288, 0x00000000,
13102 0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000, 0x12064711,
13103 0x00000001, 0xb0a18612, 0x00000010, 0xe1024794, 0x00000010,
13104 0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011, 0xc1848a9c,
13105 0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21, 0x00000019,
13106 0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019, 0xb36811a6,
13107 0x00000019, 0xf3e89227, 0x00000019, 0x0408d329, 0x0000001a,
13108 0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a, 0x54aa152c,
13109 0x0000001a, 0x64ca55ad, 0x0000001a
13110 };
13111 static const uint16_t auxgainidx[] = {
13112 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13113 0x0000, 0x0001, 0x0002, 0x0004, 0x0016, 0x0000, 0x0000, 0x0000,
13114 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002,
13115 0x0004, 0x0016
13116 };
13117 static const uint16_t swctl[] = {
13118 0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13119 0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13120 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
13121 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018,
13122 0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13123 0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13124 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
13125 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018
13126 };
13127 static const uint8_t hf[] = {
13128 0x4b, 0x36, 0x24, 0x18, 0x49, 0x34, 0x23, 0x17, 0x48,
13129 0x33, 0x23, 0x17, 0x48, 0x33, 0x23, 0x17
13130 };
13131 static const uint32_t gainval[] = {
13132 0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13133 0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13134 0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13135 0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13136 0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13137 0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13138 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13139 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13140 0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13141 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13142 0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13143 0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13144 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000009,
13145 0x000000f1, 0x00000000, 0x00000000
13146 };
13147 static const uint16_t gain[] = {
13148 0x0000, 0x0400, 0x0800, 0x0802, 0x0804, 0x0806, 0x0807, 0x0808,
13149 0x080a, 0x080b, 0x080c, 0x080e, 0x080f, 0x0810, 0x0812, 0x0813,
13150 0x0814, 0x0816, 0x0817, 0x081a, 0x081b, 0x081f, 0x0820, 0x0824,
13151 0x0830, 0x0834, 0x0837, 0x083b, 0x083f, 0x0840, 0x0844, 0x0857,
13152 0x085b, 0x085f, 0x08d7, 0x08db, 0x08df, 0x0957, 0x095b, 0x095f,
13153 0x0b57, 0x0b5b, 0x0b5f, 0x0f5f, 0x135f, 0x175f, 0x0000, 0x0000,
13154 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13155 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13156 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13157 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13158 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13159 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13160 };
13161 static const uint32_t papdeps[] = {
13162 0x00000000, 0x00013ffc, 0x0001dff3, 0x0001bff0, 0x00023fe9,
13163 0x00021fdf, 0x00028fdf, 0x00033fd2, 0x00039fcb, 0x00043fc7,
13164 0x0004efc2, 0x00055fb5, 0x0005cfb0, 0x00063fa8, 0x00068fa3,
13165 0x00071f98, 0x0007ef92, 0x00084f8b, 0x0008df82, 0x00097f77,
13166 0x0009df69, 0x000a3f62, 0x000adf57, 0x000b6f4c, 0x000bff41,
13167 0x000c9f39, 0x000cff30, 0x000dbf27, 0x000e4f1e, 0x000edf16,
13168 0x000f7f13, 0x00102f11, 0x00110f10, 0x0011df11, 0x0012ef15,
13169 0x00143f1c, 0x00158f27, 0x00172f35, 0x00193f47, 0x001baf5f,
13170 0x001e6f7e, 0x0021cfa4, 0x0025bfd2, 0x002a2008, 0x002fb047,
13171 0x00360090, 0x003d40e0, 0x0045c135, 0x004fb189, 0x005ae1d7,
13172 0x0067221d, 0x0075025a, 0x007ff291, 0x007ff2bf, 0x007ff2e3,
13173 0x007ff2ff, 0x007ff315, 0x007ff329, 0x007ff33f, 0x007ff356,
13174 0x007ff36e, 0x007ff39c, 0x007ff441, 0x007ff506
13175 };
13176 static const uint32_t papdmult[] = {
13177 0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13178 0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13179 0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13180 0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13181 0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13182 0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13183 0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13184 0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13185 0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13186 0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13187 0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13188 0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13189 0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13190 };
13191 static const uint32_t gainidx_a0[] = {
13192 0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13193 0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13194 0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13195 0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13196 0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13197 0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13198 0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13199 0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13200 0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13201 0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13202 0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13203 0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13204 0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13205 };
13206 static const uint16_t auxgainidx_a0[] = {
13207 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13208 0x0000, 0x0000, 0x0000, 0x0002, 0x0014, 0x0000, 0x0000, 0x0000,
13209 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13210 0x0002, 0x0014
13211 };
13212 static const uint32_t gainval_a0[] = {
13213 0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13214 0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13215 0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13216 0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13217 0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13218 0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13219 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13220 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13221 0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13222 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13223 0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13224 0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13225 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000f,
13226 0x000000f7, 0x00000000, 0x00000000
13227 };
13228 static const uint16_t gain_a0[] = {
13229 0x0000, 0x0002, 0x0004, 0x0006, 0x0007, 0x0008, 0x000a, 0x000b,
13230 0x000c, 0x000e, 0x000f, 0x0010, 0x0012, 0x0013, 0x0014, 0x0016,
13231 0x0017, 0x001a, 0x001b, 0x001f, 0x0020, 0x0024, 0x0030, 0x0034,
13232 0x0037, 0x003b, 0x003f, 0x0040, 0x0044, 0x0057, 0x005b, 0x005f,
13233 0x00d7, 0x00db, 0x00df, 0x0157, 0x015b, 0x015f, 0x0357, 0x035b,
13234 0x035f, 0x075f, 0x0b5f, 0x0f5f, 0x0000, 0x0000, 0x0000, 0x0000,
13235 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13236 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13237 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13238 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13239 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13240 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13241 };
13242
13243 KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13244
13245 for (i = 0; i < 704; i++)
13246 bwn_tab_write(mac, BWN_TAB_4(7, i), 0);
13247
13248 bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13249 bwn_tab_sigsq_tbl);
13250 bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13251 bwn_tab_write_multi(mac, BWN_TAB_4(11, 0), N(filterctl), filterctl);
13252 bwn_tab_write_multi(mac, BWN_TAB_4(12, 0), N(psctl), psctl);
13253 bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx), gainidx);
13254 bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx), auxgainidx);
13255 bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(swctl), swctl);
13256 bwn_tab_write_multi(mac, BWN_TAB_1(16, 0), N(hf), hf);
13257 bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval), gainval);
13258 bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain), gain);
13259 bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13260 bwn_tab_pllfrac_tbl);
13261 bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13262 bwn_tabl_iqlocal_tbl);
13263 bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(papdeps), papdeps);
13264 bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(papdmult), papdmult);
13265
13266 if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
13267 (siba_get_chiprev(sc->sc_dev) == 0)) {
13268 bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx_a0),
13269 gainidx_a0);
13270 bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx_a0),
13271 auxgainidx_a0);
13272 bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval_a0),
13273 gainval_a0);
13274 bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain_a0), gain_a0);
13275 }
13276}
13277
13278static void
13279bwn_phy_lp_tblinit_txgain(struct bwn_mac *mac)
13280{
13281 struct bwn_softc *sc = mac->mac_sc;
13282 struct ifnet *ifp = sc->sc_ifp;
13283 struct ieee80211com *ic = ifp->if_l2com;
13284 static struct bwn_txgain_entry txgain_r2[] = {
13285 { 255, 255, 203, 0, 152 }, { 255, 255, 203, 0, 147 },
13286 { 255, 255, 203, 0, 143 }, { 255, 255, 203, 0, 139 },
13287 { 255, 255, 203, 0, 135 }, { 255, 255, 203, 0, 131 },
13288 { 255, 255, 203, 0, 128 }, { 255, 255, 203, 0, 124 },
13289 { 255, 255, 203, 0, 121 }, { 255, 255, 203, 0, 117 },
13290 { 255, 255, 203, 0, 114 }, { 255, 255, 203, 0, 111 },
13291 { 255, 255, 203, 0, 107 }, { 255, 255, 203, 0, 104 },
13292 { 255, 255, 203, 0, 101 }, { 255, 255, 203, 0, 99 },
13293 { 255, 255, 203, 0, 96 }, { 255, 255, 203, 0, 93 },
13294 { 255, 255, 203, 0, 90 }, { 255, 255, 203, 0, 88 },
13295 { 255, 255, 203, 0, 85 }, { 255, 255, 203, 0, 83 },
13296 { 255, 255, 203, 0, 81 }, { 255, 255, 203, 0, 78 },
13297 { 255, 255, 203, 0, 76 }, { 255, 255, 203, 0, 74 },
13298 { 255, 255, 203, 0, 72 }, { 255, 255, 203, 0, 70 },
13299 { 255, 255, 203, 0, 68 }, { 255, 255, 203, 0, 66 },
13300 { 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13301 { 255, 255, 192, 0, 64 }, { 255, 255, 186, 0, 64 },
13302 { 255, 255, 181, 0, 64 }, { 255, 255, 176, 0, 64 },
13303 { 255, 255, 171, 0, 64 }, { 255, 255, 166, 0, 64 },
13304 { 255, 255, 161, 0, 64 }, { 255, 255, 157, 0, 64 },
13305 { 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13306 { 255, 255, 144, 0, 64 }, { 255, 255, 140, 0, 64 },
13307 { 255, 255, 136, 0, 64 }, { 255, 255, 132, 0, 64 },
13308 { 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13309 { 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13310 { 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13311 { 255, 255, 108, 0, 64 }, { 255, 255, 105, 0, 64 },
13312 { 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13313 { 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13314 { 255, 255, 91, 0, 64 }, { 255, 255, 88, 0, 64 },
13315 { 255, 255, 86, 0, 64 }, { 255, 255, 83, 0, 64 },
13316 { 255, 255, 81, 0, 64 }, { 255, 255, 79, 0, 64 },
13317 { 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13318 { 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13319 { 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13320 { 255, 255, 64, 0, 64 }, { 255, 248, 64, 0, 64 },
13321 { 255, 248, 62, 0, 64 }, { 255, 241, 62, 0, 64 },
13322 { 255, 241, 60, 0, 64 }, { 255, 234, 60, 0, 64 },
13323 { 255, 234, 59, 0, 64 }, { 255, 227, 59, 0, 64 },
13324 { 255, 227, 57, 0, 64 }, { 255, 221, 57, 0, 64 },
13325 { 255, 221, 55, 0, 64 }, { 255, 215, 55, 0, 64 },
13326 { 255, 215, 54, 0, 64 }, { 255, 208, 54, 0, 64 },
13327 { 255, 208, 52, 0, 64 }, { 255, 203, 52, 0, 64 },
13328 { 255, 203, 51, 0, 64 }, { 255, 197, 51, 0, 64 },
13329 { 255, 197, 49, 0, 64 }, { 255, 191, 49, 0, 64 },
13330 { 255, 191, 48, 0, 64 }, { 255, 186, 48, 0, 64 },
13331 { 255, 186, 47, 0, 64 }, { 255, 181, 47, 0, 64 },
13332 { 255, 181, 45, 0, 64 }, { 255, 175, 45, 0, 64 },
13333 { 255, 175, 44, 0, 64 }, { 255, 170, 44, 0, 64 },
13334 { 255, 170, 43, 0, 64 }, { 255, 166, 43, 0, 64 },
13335 { 255, 166, 42, 0, 64 }, { 255, 161, 42, 0, 64 },
13336 { 255, 161, 40, 0, 64 }, { 255, 156, 40, 0, 64 },
13337 { 255, 156, 39, 0, 64 }, { 255, 152, 39, 0, 64 },
13338 { 255, 152, 38, 0, 64 }, { 255, 148, 38, 0, 64 },
13339 { 255, 148, 37, 0, 64 }, { 255, 143, 37, 0, 64 },
13340 { 255, 143, 36, 0, 64 }, { 255, 139, 36, 0, 64 },
13341 { 255, 139, 35, 0, 64 }, { 255, 135, 35, 0, 64 },
13342 { 255, 135, 34, 0, 64 }, { 255, 132, 34, 0, 64 },
13343 { 255, 132, 33, 0, 64 }, { 255, 128, 33, 0, 64 },
13344 { 255, 128, 32, 0, 64 }, { 255, 124, 32, 0, 64 },
13345 { 255, 124, 31, 0, 64 }, { 255, 121, 31, 0, 64 },
13346 { 255, 121, 30, 0, 64 }, { 255, 117, 30, 0, 64 },
13347 { 255, 117, 29, 0, 64 }, { 255, 114, 29, 0, 64 },
13348 { 255, 114, 29, 0, 64 }, { 255, 111, 29, 0, 64 },
13349 };
13350 static struct bwn_txgain_entry txgain_2ghz_r2[] = {
13351 { 7, 99, 255, 0, 64 }, { 7, 96, 255, 0, 64 },
13352 { 7, 93, 255, 0, 64 }, { 7, 90, 255, 0, 64 },
13353 { 7, 88, 255, 0, 64 }, { 7, 85, 255, 0, 64 },
13354 { 7, 83, 255, 0, 64 }, { 7, 81, 255, 0, 64 },
13355 { 7, 78, 255, 0, 64 }, { 7, 76, 255, 0, 64 },
13356 { 7, 74, 255, 0, 64 }, { 7, 72, 255, 0, 64 },
13357 { 7, 70, 255, 0, 64 }, { 7, 68, 255, 0, 64 },
13358 { 7, 66, 255, 0, 64 }, { 7, 64, 255, 0, 64 },
13359 { 7, 64, 255, 0, 64 }, { 7, 62, 255, 0, 64 },
13360 { 7, 62, 248, 0, 64 }, { 7, 60, 248, 0, 64 },
13361 { 7, 60, 241, 0, 64 }, { 7, 59, 241, 0, 64 },
13362 { 7, 59, 234, 0, 64 }, { 7, 57, 234, 0, 64 },
13363 { 7, 57, 227, 0, 64 }, { 7, 55, 227, 0, 64 },
13364 { 7, 55, 221, 0, 64 }, { 7, 54, 221, 0, 64 },
13365 { 7, 54, 215, 0, 64 }, { 7, 52, 215, 0, 64 },
13366 { 7, 52, 208, 0, 64 }, { 7, 51, 208, 0, 64 },
13367 { 7, 51, 203, 0, 64 }, { 7, 49, 203, 0, 64 },
13368 { 7, 49, 197, 0, 64 }, { 7, 48, 197, 0, 64 },
13369 { 7, 48, 191, 0, 64 }, { 7, 47, 191, 0, 64 },
13370 { 7, 47, 186, 0, 64 }, { 7, 45, 186, 0, 64 },
13371 { 7, 45, 181, 0, 64 }, { 7, 44, 181, 0, 64 },
13372 { 7, 44, 175, 0, 64 }, { 7, 43, 175, 0, 64 },
13373 { 7, 43, 170, 0, 64 }, { 7, 42, 170, 0, 64 },
13374 { 7, 42, 166, 0, 64 }, { 7, 40, 166, 0, 64 },
13375 { 7, 40, 161, 0, 64 }, { 7, 39, 161, 0, 64 },
13376 { 7, 39, 156, 0, 64 }, { 7, 38, 156, 0, 64 },
13377 { 7, 38, 152, 0, 64 }, { 7, 37, 152, 0, 64 },
13378 { 7, 37, 148, 0, 64 }, { 7, 36, 148, 0, 64 },
13379 { 7, 36, 143, 0, 64 }, { 7, 35, 143, 0, 64 },
13380 { 7, 35, 139, 0, 64 }, { 7, 34, 139, 0, 64 },
13381 { 7, 34, 135, 0, 64 }, { 7, 33, 135, 0, 64 },
13382 { 7, 33, 132, 0, 64 }, { 7, 32, 132, 0, 64 },
13383 { 7, 32, 128, 0, 64 }, { 7, 31, 128, 0, 64 },
13384 { 7, 31, 124, 0, 64 }, { 7, 30, 124, 0, 64 },
13385 { 7, 30, 121, 0, 64 }, { 7, 29, 121, 0, 64 },
13386 { 7, 29, 117, 0, 64 }, { 7, 29, 117, 0, 64 },
13387 { 7, 29, 114, 0, 64 }, { 7, 28, 114, 0, 64 },
13388 { 7, 28, 111, 0, 64 }, { 7, 27, 111, 0, 64 },
13389 { 7, 27, 108, 0, 64 }, { 7, 26, 108, 0, 64 },
13390 { 7, 26, 104, 0, 64 }, { 7, 25, 104, 0, 64 },
13391 { 7, 25, 102, 0, 64 }, { 7, 25, 102, 0, 64 },
13392 { 7, 25, 99, 0, 64 }, { 7, 24, 99, 0, 64 },
13393 { 7, 24, 96, 0, 64 }, { 7, 23, 96, 0, 64 },
13394 { 7, 23, 93, 0, 64 }, { 7, 23, 93, 0, 64 },
13395 { 7, 23, 90, 0, 64 }, { 7, 22, 90, 0, 64 },
13396 { 7, 22, 88, 0, 64 }, { 7, 21, 88, 0, 64 },
13397 { 7, 21, 85, 0, 64 }, { 7, 21, 85, 0, 64 },
13398 { 7, 21, 83, 0, 64 }, { 7, 20, 83, 0, 64 },
13399 { 7, 20, 81, 0, 64 }, { 7, 20, 81, 0, 64 },
13400 { 7, 20, 78, 0, 64 }, { 7, 19, 78, 0, 64 },
13401 { 7, 19, 76, 0, 64 }, { 7, 19, 76, 0, 64 },
13402 { 7, 19, 74, 0, 64 }, { 7, 18, 74, 0, 64 },
13403 { 7, 18, 72, 0, 64 }, { 7, 18, 72, 0, 64 },
13404 { 7, 18, 70, 0, 64 }, { 7, 17, 70, 0, 64 },
13405 { 7, 17, 68, 0, 64 }, { 7, 17, 68, 0, 64 },
13406 { 7, 17, 66, 0, 64 }, { 7, 16, 66, 0, 64 },
13407 { 7, 16, 64, 0, 64 }, { 7, 16, 64, 0, 64 },
13408 { 7, 16, 62, 0, 64 }, { 7, 15, 62, 0, 64 },
13409 { 7, 15, 60, 0, 64 }, { 7, 15, 60, 0, 64 },
13410 { 7, 15, 59, 0, 64 }, { 7, 14, 59, 0, 64 },
13411 { 7, 14, 57, 0, 64 }, { 7, 14, 57, 0, 64 },
13412 { 7, 14, 55, 0, 64 }, { 7, 14, 55, 0, 64 },
13413 { 7, 14, 54, 0, 64 }, { 7, 13, 54, 0, 64 },
13414 { 7, 13, 52, 0, 64 }, { 7, 13, 52, 0, 64 },
13415 };
13416 static struct bwn_txgain_entry txgain_5ghz_r2[] = {
13417 { 255, 255, 255, 0, 152 }, { 255, 255, 255, 0, 147 },
13418 { 255, 255, 255, 0, 143 }, { 255, 255, 255, 0, 139 },
13419 { 255, 255, 255, 0, 135 }, { 255, 255, 255, 0, 131 },
13420 { 255, 255, 255, 0, 128 }, { 255, 255, 255, 0, 124 },
13421 { 255, 255, 255, 0, 121 }, { 255, 255, 255, 0, 117 },
13422 { 255, 255, 255, 0, 114 }, { 255, 255, 255, 0, 111 },
13423 { 255, 255, 255, 0, 107 }, { 255, 255, 255, 0, 104 },
13424 { 255, 255, 255, 0, 101 }, { 255, 255, 255, 0, 99 },
13425 { 255, 255, 255, 0, 96 }, { 255, 255, 255, 0, 93 },
13426 { 255, 255, 255, 0, 90 }, { 255, 255, 255, 0, 88 },
13427 { 255, 255, 255, 0, 85 }, { 255, 255, 255, 0, 83 },
13428 { 255, 255, 255, 0, 81 }, { 255, 255, 255, 0, 78 },
13429 { 255, 255, 255, 0, 76 }, { 255, 255, 255, 0, 74 },
13430 { 255, 255, 255, 0, 72 }, { 255, 255, 255, 0, 70 },
13431 { 255, 255, 255, 0, 68 }, { 255, 255, 255, 0, 66 },
13432 { 255, 255, 255, 0, 64 }, { 255, 255, 248, 0, 64 },
13433 { 255, 255, 241, 0, 64 }, { 255, 255, 234, 0, 64 },
13434 { 255, 255, 227, 0, 64 }, { 255, 255, 221, 0, 64 },
13435 { 255, 255, 215, 0, 64 }, { 255, 255, 208, 0, 64 },
13436 { 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13437 { 255, 255, 191, 0, 64 }, { 255, 255, 186, 0, 64 },
13438 { 255, 255, 181, 0, 64 }, { 255, 255, 175, 0, 64 },
13439 { 255, 255, 170, 0, 64 }, { 255, 255, 166, 0, 64 },
13440 { 255, 255, 161, 0, 64 }, { 255, 255, 156, 0, 64 },
13441 { 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13442 { 255, 255, 143, 0, 64 }, { 255, 255, 139, 0, 64 },
13443 { 255, 255, 135, 0, 64 }, { 255, 255, 132, 0, 64 },
13444 { 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13445 { 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13446 { 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13447 { 255, 255, 108, 0, 64 }, { 255, 255, 104, 0, 64 },
13448 { 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13449 { 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13450 { 255, 255, 90, 0, 64 }, { 255, 255, 88, 0, 64 },
13451 { 255, 255, 85, 0, 64 }, { 255, 255, 83, 0, 64 },
13452 { 255, 255, 81, 0, 64 }, { 255, 255, 78, 0, 64 },
13453 { 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13454 { 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13455 { 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13456 { 255, 255, 64, 0, 64 }, { 255, 255, 64, 0, 64 },
13457 { 255, 255, 62, 0, 64 }, { 255, 248, 62, 0, 64 },
13458 { 255, 248, 60, 0, 64 }, { 255, 241, 60, 0, 64 },
13459 { 255, 241, 59, 0, 64 }, { 255, 234, 59, 0, 64 },
13460 { 255, 234, 57, 0, 64 }, { 255, 227, 57, 0, 64 },
13461 { 255, 227, 55, 0, 64 }, { 255, 221, 55, 0, 64 },
13462 { 255, 221, 54, 0, 64 }, { 255, 215, 54, 0, 64 },
13463 { 255, 215, 52, 0, 64 }, { 255, 208, 52, 0, 64 },
13464 { 255, 208, 51, 0, 64 }, { 255, 203, 51, 0, 64 },
13465 { 255, 203, 49, 0, 64 }, { 255, 197, 49, 0, 64 },
13466 { 255, 197, 48, 0, 64 }, { 255, 191, 48, 0, 64 },
13467 { 255, 191, 47, 0, 64 }, { 255, 186, 47, 0, 64 },
13468 { 255, 186, 45, 0, 64 }, { 255, 181, 45, 0, 64 },
13469 { 255, 181, 44, 0, 64 }, { 255, 175, 44, 0, 64 },
13470 { 255, 175, 43, 0, 64 }, { 255, 170, 43, 0, 64 },
13471 { 255, 170, 42, 0, 64 }, { 255, 166, 42, 0, 64 },
13472 { 255, 166, 40, 0, 64 }, { 255, 161, 40, 0, 64 },
13473 { 255, 161, 39, 0, 64 }, { 255, 156, 39, 0, 64 },
13474 { 255, 156, 38, 0, 64 }, { 255, 152, 38, 0, 64 },
13475 { 255, 152, 37, 0, 64 }, { 255, 148, 37, 0, 64 },
13476 { 255, 148, 36, 0, 64 }, { 255, 143, 36, 0, 64 },
13477 { 255, 143, 35, 0, 64 }, { 255, 139, 35, 0, 64 },
13478 { 255, 139, 34, 0, 64 }, { 255, 135, 34, 0, 64 },
13479 { 255, 135, 33, 0, 64 }, { 255, 132, 33, 0, 64 },
13480 { 255, 132, 32, 0, 64 }, { 255, 128, 32, 0, 64 }
13481 };
13482 static struct bwn_txgain_entry txgain_r0[] = {
13483 { 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13484 { 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13485 { 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13486 { 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13487 { 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13488 { 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13489 { 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13490 { 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13491 { 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13492 { 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13493 { 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13494 { 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13495 { 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13496 { 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13497 { 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13498 { 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13499 { 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13500 { 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13501 { 7, 15, 13, 0, 70 }, { 7, 15, 13, 0, 68 },
13502 { 7, 15, 13, 0, 66 }, { 7, 15, 13, 0, 64 },
13503 { 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13504 { 7, 15, 13, 0, 59 }, { 7, 15, 13, 0, 57 },
13505 { 7, 15, 12, 0, 71 }, { 7, 15, 12, 0, 69 },
13506 { 7, 15, 12, 0, 67 }, { 7, 15, 12, 0, 65 },
13507 { 7, 15, 12, 0, 63 }, { 7, 15, 12, 0, 62 },
13508 { 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 58 },
13509 { 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 70 },
13510 { 7, 15, 11, 0, 68 }, { 7, 15, 11, 0, 66 },
13511 { 7, 15, 11, 0, 65 }, { 7, 15, 11, 0, 63 },
13512 { 7, 15, 11, 0, 61 }, { 7, 15, 11, 0, 59 },
13513 { 7, 15, 11, 0, 58 }, { 7, 15, 10, 0, 71 },
13514 { 7, 15, 10, 0, 69 }, { 7, 15, 10, 0, 67 },
13515 { 7, 15, 10, 0, 65 }, { 7, 15, 10, 0, 63 },
13516 { 7, 15, 10, 0, 61 }, { 7, 15, 10, 0, 60 },
13517 { 7, 15, 10, 0, 58 }, { 7, 15, 10, 0, 56 },
13518 { 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13519 { 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13520 { 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 60 },
13521 { 7, 15, 9, 0, 59 }, { 7, 14, 9, 0, 72 },
13522 { 7, 14, 9, 0, 70 }, { 7, 14, 9, 0, 68 },
13523 { 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 64 },
13524 { 7, 14, 9, 0, 62 }, { 7, 14, 9, 0, 60 },
13525 { 7, 14, 9, 0, 59 }, { 7, 13, 9, 0, 72 },
13526 { 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13527 { 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13528 { 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13529 { 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13530 { 7, 13, 8, 0, 72 }, { 7, 13, 8, 0, 70 },
13531 { 7, 13, 8, 0, 68 }, { 7, 13, 8, 0, 66 },
13532 { 7, 13, 8, 0, 64 }, { 7, 13, 8, 0, 62 },
13533 { 7, 13, 8, 0, 60 }, { 7, 13, 8, 0, 59 },
13534 { 7, 12, 8, 0, 72 }, { 7, 12, 8, 0, 70 },
13535 { 7, 12, 8, 0, 68 }, { 7, 12, 8, 0, 66 },
13536 { 7, 12, 8, 0, 64 }, { 7, 12, 8, 0, 62 },
13537 { 7, 12, 8, 0, 61 }, { 7, 12, 8, 0, 59 },
13538 { 7, 12, 7, 0, 73 }, { 7, 12, 7, 0, 71 },
13539 { 7, 12, 7, 0, 69 }, { 7, 12, 7, 0, 67 },
13540 { 7, 12, 7, 0, 65 }, { 7, 12, 7, 0, 63 },
13541 { 7, 12, 7, 0, 61 }, { 7, 12, 7, 0, 59 },
13542 { 7, 11, 7, 0, 72 }, { 7, 11, 7, 0, 70 },
13543 { 7, 11, 7, 0, 68 }, { 7, 11, 7, 0, 66 },
13544 { 7, 11, 7, 0, 65 }, { 7, 11, 7, 0, 63 },
13545 { 7, 11, 7, 0, 61 }, { 7, 11, 7, 0, 59 },
13546 { 7, 11, 6, 0, 73 }, { 7, 11, 6, 0, 71 }
13547 };
13548 static struct bwn_txgain_entry txgain_2ghz_r0[] = {
13549 { 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13550 { 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13551 { 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13552 { 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13553 { 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13554 { 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13555 { 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13556 { 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13557 { 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13558 { 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13559 { 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13560 { 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13561 { 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13562 { 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13563 { 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13564 { 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13565 { 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13566 { 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13567 { 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13568 { 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13569 { 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13570 { 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13571 { 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13572 { 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13573 { 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13574 { 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13575 { 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13576 { 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13577 { 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13578 { 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13579 { 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13580 { 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13581 { 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13582 { 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 },
13583 { 4, 10, 6, 0, 59 }, { 4, 10, 5, 0, 72 },
13584 { 4, 10, 5, 0, 70 }, { 4, 10, 5, 0, 68 },
13585 { 4, 10, 5, 0, 66 }, { 4, 10, 5, 0, 64 },
13586 { 4, 10, 5, 0, 62 }, { 4, 10, 5, 0, 60 },
13587 { 4, 10, 5, 0, 59 }, { 4, 9, 5, 0, 70 },
13588 { 4, 9, 5, 0, 68 }, { 4, 9, 5, 0, 66 },
13589 { 4, 9, 5, 0, 64 }, { 4, 9, 5, 0, 63 },
13590 { 4, 9, 5, 0, 61 }, { 4, 9, 5, 0, 59 },
13591 { 4, 9, 4, 0, 71 }, { 4, 9, 4, 0, 69 },
13592 { 4, 9, 4, 0, 67 }, { 4, 9, 4, 0, 65 },
13593 { 4, 9, 4, 0, 63 }, { 4, 9, 4, 0, 62 },
13594 { 4, 9, 4, 0, 60 }, { 4, 9, 4, 0, 58 },
13595 { 4, 8, 4, 0, 70 }, { 4, 8, 4, 0, 68 },
13596 { 4, 8, 4, 0, 66 }, { 4, 8, 4, 0, 65 },
13597 { 4, 8, 4, 0, 63 }, { 4, 8, 4, 0, 61 },
13598 { 4, 8, 4, 0, 59 }, { 4, 7, 4, 0, 68 },
13599 { 4, 7, 4, 0, 66 }, { 4, 7, 4, 0, 64 },
13600 { 4, 7, 4, 0, 62 }, { 4, 7, 4, 0, 61 },
13601 { 4, 7, 4, 0, 59 }, { 4, 7, 3, 0, 67 },
13602 { 4, 7, 3, 0, 65 }, { 4, 7, 3, 0, 63 },
13603 { 4, 7, 3, 0, 62 }, { 4, 7, 3, 0, 60 },
13604 { 4, 6, 3, 0, 65 }, { 4, 6, 3, 0, 63 },
13605 { 4, 6, 3, 0, 61 }, { 4, 6, 3, 0, 60 },
13606 { 4, 6, 3, 0, 58 }, { 4, 5, 3, 0, 68 },
13607 { 4, 5, 3, 0, 66 }, { 4, 5, 3, 0, 64 },
13608 { 4, 5, 3, 0, 62 }, { 4, 5, 3, 0, 60 },
13609 { 4, 5, 3, 0, 59 }, { 4, 5, 3, 0, 57 },
13610 { 4, 4, 2, 0, 83 }, { 4, 4, 2, 0, 81 },
13611 { 4, 4, 2, 0, 78 }, { 4, 4, 2, 0, 76 },
13612 { 4, 4, 2, 0, 74 }, { 4, 4, 2, 0, 72 }
13613 };
13614 static struct bwn_txgain_entry txgain_5ghz_r0[] = {
13615 { 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13616 { 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13617 { 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13618 { 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13619 { 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13620 { 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13621 { 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13622 { 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13623 { 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13624 { 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13625 { 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13626 { 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13627 { 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13628 { 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13629 { 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13630 { 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13631 { 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13632 { 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13633 { 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13634 { 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13635 { 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13636 { 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13637 { 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13638 { 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13639 { 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13640 { 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13641 { 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13642 { 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13643 { 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13644 { 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13645 { 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13646 { 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13647 { 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13648 { 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13649 { 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13650 { 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13651 { 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13652 { 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13653 { 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13654 { 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13655 { 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13656 { 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13657 { 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13658 { 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13659 { 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13660 { 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13661 { 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13662 { 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13663 { 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13664 { 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13665 { 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13666 { 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13667 { 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13668 { 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13669 { 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13670 { 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13671 { 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13672 { 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13673 { 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13674 { 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13675 { 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13676 { 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13677 { 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13678 { 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13679 };
13680 static struct bwn_txgain_entry txgain_r1[] = {
13681 { 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13682 { 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13683 { 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13684 { 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13685 { 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13686 { 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13687 { 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13688 { 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13689 { 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13690 { 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13691 { 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13692 { 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13693 { 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13694 { 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13695 { 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13696 { 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13697 { 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13698 { 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13699 { 7, 15, 13, 0, 70 }, { 7, 15, 14, 0, 68 },
13700 { 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13701 { 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13702 { 7, 15, 14, 0, 59 }, { 7, 15, 14, 0, 57 },
13703 { 7, 15, 13, 0, 72 }, { 7, 15, 13, 0, 70 },
13704 { 7, 15, 13, 0, 68 }, { 7, 15, 13, 0, 66 },
13705 { 7, 15, 13, 0, 64 }, { 7, 15, 13, 0, 62 },
13706 { 7, 15, 13, 0, 60 }, { 7, 15, 13, 0, 59 },
13707 { 7, 15, 13, 0, 57 }, { 7, 15, 12, 0, 71 },
13708 { 7, 15, 12, 0, 69 }, { 7, 15, 12, 0, 67 },
13709 { 7, 15, 12, 0, 65 }, { 7, 15, 12, 0, 63 },
13710 { 7, 15, 12, 0, 62 }, { 7, 15, 12, 0, 60 },
13711 { 7, 15, 12, 0, 58 }, { 7, 15, 12, 0, 57 },
13712 { 7, 15, 11, 0, 70 }, { 7, 15, 11, 0, 68 },
13713 { 7, 15, 11, 0, 66 }, { 7, 15, 11, 0, 65 },
13714 { 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13715 { 7, 15, 11, 0, 59 }, { 7, 15, 11, 0, 58 },
13716 { 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13717 { 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13718 { 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13719 { 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13720 { 7, 15, 10, 0, 56 }, { 7, 15, 9, 0, 70 },
13721 { 7, 15, 9, 0, 68 }, { 7, 15, 9, 0, 66 },
13722 { 7, 15, 9, 0, 64 }, { 7, 15, 9, 0, 62 },
13723 { 7, 15, 9, 0, 60 }, { 7, 15, 9, 0, 59 },
13724 { 7, 14, 9, 0, 72 }, { 7, 14, 9, 0, 70 },
13725 { 7, 14, 9, 0, 68 }, { 7, 14, 9, 0, 66 },
13726 { 7, 14, 9, 0, 64 }, { 7, 14, 9, 0, 62 },
13727 { 7, 14, 9, 0, 60 }, { 7, 14, 9, 0, 59 },
13728 { 7, 13, 9, 0, 72 }, { 7, 13, 9, 0, 70 },
13729 { 7, 13, 9, 0, 68 }, { 7, 13, 9, 0, 66 },
13730 { 7, 13, 9, 0, 64 }, { 7, 13, 9, 0, 63 },
13731 { 7, 13, 9, 0, 61 }, { 7, 13, 9, 0, 59 },
13732 { 7, 13, 9, 0, 57 }, { 7, 13, 8, 0, 72 },
13733 { 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13734 { 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13735 { 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13736 { 7, 13, 8, 0, 59 }, { 7, 12, 8, 0, 72 },
13737 { 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13738 { 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13739 { 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13740 { 7, 12, 8, 0, 59 }, { 7, 12, 7, 0, 73 },
13741 { 7, 12, 7, 0, 71 }, { 7, 12, 7, 0, 69 },
13742 { 7, 12, 7, 0, 67 }, { 7, 12, 7, 0, 65 },
13743 { 7, 12, 7, 0, 63 }, { 7, 12, 7, 0, 61 },
13744 { 7, 12, 7, 0, 59 }, { 7, 11, 7, 0, 72 },
13745 { 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13746 { 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 65 },
13747 { 7, 11, 7, 0, 63 }, { 7, 11, 7, 0, 61 },
13748 { 7, 11, 7, 0, 59 }, { 7, 11, 6, 0, 73 },
13749 { 7, 11, 6, 0, 71 }
13750 };
13751 static struct bwn_txgain_entry txgain_2ghz_r1[] = {
13752 { 4, 15, 15, 0, 90 }, { 4, 15, 15, 0, 88 },
13753 { 4, 15, 15, 0, 85 }, { 4, 15, 15, 0, 83 },
13754 { 4, 15, 15, 0, 81 }, { 4, 15, 15, 0, 78 },
13755 { 4, 15, 15, 0, 76 }, { 4, 15, 15, 0, 74 },
13756 { 4, 15, 15, 0, 72 }, { 4, 15, 15, 0, 70 },
13757 { 4, 15, 15, 0, 68 }, { 4, 15, 15, 0, 66 },
13758 { 4, 15, 15, 0, 64 }, { 4, 15, 15, 0, 62 },
13759 { 4, 15, 15, 0, 60 }, { 4, 15, 15, 0, 59 },
13760 { 4, 15, 14, 0, 72 }, { 4, 15, 14, 0, 70 },
13761 { 4, 15, 14, 0, 68 }, { 4, 15, 14, 0, 66 },
13762 { 4, 15, 14, 0, 64 }, { 4, 15, 14, 0, 62 },
13763 { 4, 15, 14, 0, 60 }, { 4, 15, 14, 0, 59 },
13764 { 4, 15, 13, 0, 72 }, { 4, 15, 13, 0, 70 },
13765 { 4, 15, 13, 0, 68 }, { 4, 15, 13, 0, 66 },
13766 { 4, 15, 13, 0, 64 }, { 4, 15, 13, 0, 62 },
13767 { 4, 15, 13, 0, 60 }, { 4, 15, 13, 0, 59 },
13768 { 4, 15, 12, 0, 72 }, { 4, 15, 12, 0, 70 },
13769 { 4, 15, 12, 0, 68 }, { 4, 15, 12, 0, 66 },
13770 { 4, 15, 12, 0, 64 }, { 4, 15, 12, 0, 62 },
13771 { 4, 15, 12, 0, 60 }, { 4, 15, 12, 0, 59 },
13772 { 4, 15, 11, 0, 72 }, { 4, 15, 11, 0, 70 },
13773 { 4, 15, 11, 0, 68 }, { 4, 15, 11, 0, 66 },
13774 { 4, 15, 11, 0, 64 }, { 4, 15, 11, 0, 62 },
13775 { 4, 15, 11, 0, 60 }, { 4, 15, 11, 0, 59 },
13776 { 4, 15, 10, 0, 72 }, { 4, 15, 10, 0, 70 },
13777 { 4, 15, 10, 0, 68 }, { 4, 15, 10, 0, 66 },
13778 { 4, 15, 10, 0, 64 }, { 4, 15, 10, 0, 62 },
13779 { 4, 15, 10, 0, 60 }, { 4, 15, 10, 0, 59 },
13780 { 4, 15, 9, 0, 72 }, { 4, 15, 9, 0, 70 },
13781 { 4, 15, 9, 0, 68 }, { 4, 15, 9, 0, 66 },
13782 { 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13783 { 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13784 { 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13785 { 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13786 { 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13787 { 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13788 { 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13789 { 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13790 { 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13791 { 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13792 { 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13793 { 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13794 { 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13795 { 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13796 { 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13797 { 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13798 { 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13799 { 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13800 { 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13801 { 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13802 { 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13803 { 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13804 { 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13805 { 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13806 { 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13807 { 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13808 { 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13809 { 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13810 { 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13811 { 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13812 { 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13813 { 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13814 { 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13815 { 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 }
13816 };
13817 static struct bwn_txgain_entry txgain_5ghz_r1[] = {
13818 { 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13819 { 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13820 { 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13821 { 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13822 { 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13823 { 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13824 { 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13825 { 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13826 { 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13827 { 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13828 { 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13829 { 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13830 { 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13831 { 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13832 { 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13833 { 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13834 { 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13835 { 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13836 { 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13837 { 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13838 { 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13839 { 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13840 { 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13841 { 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13842 { 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13843 { 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13844 { 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13845 { 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13846 { 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13847 { 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13848 { 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13849 { 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13850 { 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13851 { 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13852 { 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13853 { 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13854 { 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13855 { 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13856 { 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13857 { 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13858 { 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13859 { 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13860 { 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13861 { 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13862 { 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13863 { 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13864 { 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13865 { 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13866 { 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13867 { 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13868 { 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13869 { 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13870 { 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13871 { 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13872 { 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13873 { 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13874 { 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13875 { 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13876 { 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13877 { 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13878 { 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13879 { 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13880 { 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13881 { 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13882 };
13883
13884 if (mac->mac_phy.rev != 0 && mac->mac_phy.rev != 1) {
13885 if (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA)
13886 bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r2);
13887 else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13888 bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13889 txgain_2ghz_r2);
13890 else
13891 bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13892 txgain_5ghz_r2);
13893 return;
13894 }
13895
13896 if (mac->mac_phy.rev == 0) {
13897 if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA) ||
13898 (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_HGPA))
13899 bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r0);
13900 else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13901 bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13902 txgain_2ghz_r0);
13903 else
13904 bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13905 txgain_5ghz_r0);
13906 return;
13907 }
13908
13909 if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA) ||
13910 (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_HGPA))
13911 bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r1);
13912 else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13913 bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_2ghz_r1);
13914 else
13915 bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_5ghz_r1);
13916}
13917
13918static void
13919bwn_tab_write(struct bwn_mac *mac, uint32_t typeoffset, uint32_t value)
13920{
13921 uint32_t offset, type;
13922
13923 type = BWN_TAB_GETTYPE(typeoffset);
13924 offset = BWN_TAB_GETOFFSET(typeoffset);
13925 KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
13926
13927 switch (type) {
13928 case BWN_TAB_8BIT:
13929 KASSERT(!(value & ~0xff), ("%s:%d: fail", __func__, __LINE__));
13930 BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13931 BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13932 break;
13933 case BWN_TAB_16BIT:
13934 KASSERT(!(value & ~0xffff),
13935 ("%s:%d: fail", __func__, __LINE__));
13936 BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13937 BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13938 break;
13939 case BWN_TAB_32BIT:
13940 BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13941 BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
13942 BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13943 break;
13944 default:
13945 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
13946 }
13947}
13948
13949static int
13950bwn_phy_lp_loopback(struct bwn_mac *mac)
13951{
13952 struct bwn_phy_lp_iq_est ie;
13953 int i, index = -1;
13954 uint32_t tmp;
13955
13956 memset(&ie, 0, sizeof(ie));
13957
13958 bwn_phy_lp_set_trsw_over(mac, 1, 1);
13959 BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 1);
13960 BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
13961 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
13962 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
13963 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
13964 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x8);
13965 BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, 0x80);
13966 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x80);
13967 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x80);
13968 for (i = 0; i < 32; i++) {
13969 bwn_phy_lp_set_rxgain_idx(mac, i);
13970 bwn_phy_lp_ddfs_turnon(mac, 1, 1, 5, 5, 0);
13971 if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
13972 continue;
13973 tmp = (ie.ie_ipwr + ie.ie_qpwr) / 1000;
13974 if ((tmp > 4000) && (tmp < 10000)) {
13975 index = i;
13976 break;
13977 }
13978 }
13979 bwn_phy_lp_ddfs_turnoff(mac);
13980 return (index);
13981}
13982
13983static void
13984bwn_phy_lp_set_rxgain_idx(struct bwn_mac *mac, uint16_t idx)
13985{
13986
13987 bwn_phy_lp_set_rxgain(mac, bwn_tab_read(mac, BWN_TAB_2(12, idx)));
13988}
13989
13990static void
13991bwn_phy_lp_ddfs_turnon(struct bwn_mac *mac, int i_on, int q_on,
13992 int incr1, int incr2, int scale_idx)
13993{
13994
13995 bwn_phy_lp_ddfs_turnoff(mac);
13996 BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0xff80);
13997 BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0x80ff);
13998 BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0xff80, incr1);
13999 BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0x80ff, incr2 << 8);
14000 BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff7, i_on << 3);
14001 BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xffef, q_on << 4);
14002 BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xff9f, scale_idx << 5);
14003 BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffb);
14004 BWN_PHY_SET(mac, BWN_PHY_AFE_DDFS, 0x2);
14005 BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x20);
14006}
14007
14008static uint8_t
14009bwn_phy_lp_rx_iq_est(struct bwn_mac *mac, uint16_t sample, uint8_t time,
14010 struct bwn_phy_lp_iq_est *ie)
14011{
14012 int i;
14013
14014 BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfff7);
14015 BWN_PHY_WRITE(mac, BWN_PHY_IQ_NUM_SMPLS_ADDR, sample);
14016 BWN_PHY_SETMASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xff00, time);
14017 BWN_PHY_MASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xfeff);
14018 BWN_PHY_SET(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0x200);
14019
14020 for (i = 0; i < 500; i++) {
14021 if (!(BWN_PHY_READ(mac,
14022 BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200))
14023 break;
14024 DELAY(1000);
14025 }
14026 if ((BWN_PHY_READ(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200)) {
14027 BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
14028 return 0;
14029 }
14030
14031 ie->ie_iqprod = BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_HI_ADDR);
14032 ie->ie_iqprod <<= 16;
14033 ie->ie_iqprod |= BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_LO_ADDR);
14034 ie->ie_ipwr = BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_HI_ADDR);
14035 ie->ie_ipwr <<= 16;
14036 ie->ie_ipwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_LO_ADDR);
14037 ie->ie_qpwr = BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_HI_ADDR);
14038 ie->ie_qpwr <<= 16;
14039 ie->ie_qpwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_LO_ADDR);
14040
14041 BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
14042 return 1;
14043}
14044
14045static uint32_t
14046bwn_tab_read(struct bwn_mac *mac, uint32_t typeoffset)
14047{
14048 uint32_t offset, type, value;
14049
14050 type = BWN_TAB_GETTYPE(typeoffset);
14051 offset = BWN_TAB_GETOFFSET(typeoffset);
14052 KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
14053
14054 switch (type) {
14055 case BWN_TAB_8BIT:
14056 BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14057 value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
14058 break;
14059 case BWN_TAB_16BIT:
14060 BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14061 value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
14062 break;
14063 case BWN_TAB_32BIT:
14064 BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14065 value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATAHI);
14066 value <<= 16;
14067 value |= BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
14068 break;
14069 default:
14070 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
14071 value = 0;
14072 }
14073
14074 return (value);
14075}
14076
14077static void
14078bwn_phy_lp_ddfs_turnoff(struct bwn_mac *mac)
14079{
14080
14081 BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffd);
14082 BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0xffdf);
14083}
14084
14085static void
14086bwn_phy_lp_set_txgain_dac(struct bwn_mac *mac, uint16_t dac)
14087{
14088 uint16_t ctl;
14089
14090 ctl = BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0xc7f;
14091 ctl |= dac << 7;
14092 BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf000, ctl);
14093}
14094
14095static void
14096bwn_phy_lp_set_txgain_pa(struct bwn_mac *mac, uint16_t gain)
14097{
14098
14099 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0xe03f, gain << 6);
14100 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x80ff, gain << 8);
14101}
14102
14103static void
14104bwn_phy_lp_set_txgain_override(struct bwn_mac *mac)
14105{
14106
14107 if (mac->mac_phy.rev < 2)
14108 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
14109 else {
14110 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x80);
14111 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x4000);
14112 }
14113 BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x40);
14114}
14115
14116static uint16_t
14117bwn_phy_lp_get_pa_gain(struct bwn_mac *mac)
14118{
14119
14120 return BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0x7f;
14121}
14122
14123static uint8_t
14124bwn_nbits(int32_t val)
14125{
14126 uint32_t tmp;
14127 uint8_t nbits = 0;
14128
14129 for (tmp = abs(val); tmp != 0; tmp >>= 1)
14130 nbits++;
14131 return (nbits);
14132}
14133
14134static void
14135bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *mac, int offset, int count,
14136 struct bwn_txgain_entry *table)
14137{
14138 int i;
14139
14140 for (i = offset; i < count; i++)
14141 bwn_phy_lp_gaintbl_write(mac, i, table[i]);
14142}
14143
14144static void
14145bwn_phy_lp_gaintbl_write(struct bwn_mac *mac, int offset,
14146 struct bwn_txgain_entry data)
14147{
14148
14149 if (mac->mac_phy.rev >= 2)
14150 bwn_phy_lp_gaintbl_write_r2(mac, offset, data);
14151 else
14152 bwn_phy_lp_gaintbl_write_r01(mac, offset, data);
14153}
14154
14155static void
14156bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *mac, int offset,
14157 struct bwn_txgain_entry te)
14158{
14159 struct bwn_softc *sc = mac->mac_sc;
14160 struct ifnet *ifp = sc->sc_ifp;
14161 struct ieee80211com *ic = ifp->if_l2com;
14162 uint32_t tmp;
14163
14164 KASSERT(mac->mac_phy.rev >= 2, ("%s:%d: fail", __func__, __LINE__));
14165
14166 tmp = (te.te_pad << 16) | (te.te_pga << 8) | te.te_gm;
14167 if (mac->mac_phy.rev >= 3) {
14168 tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14169 (0x10 << 24) : (0x70 << 24));
14170 } else {
14171 tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14172 (0x14 << 24) : (0x7f << 24));
14173 }
14174 bwn_tab_write(mac, BWN_TAB_4(7, 0xc0 + offset), tmp);
14175 bwn_tab_write(mac, BWN_TAB_4(7, 0x140 + offset),
14176 te.te_bbmult << 20 | te.te_dac << 28);
14177}
14178
14179static void
14180bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *mac, int offset,
14181 struct bwn_txgain_entry te)
14182{
14183
14184 KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
14185
14186 bwn_tab_write(mac, BWN_TAB_4(10, 0xc0 + offset),
14187 (te.te_pad << 11) | (te.te_pga << 7) | (te.te_gm << 4) |
14188 te.te_dac);
14189 bwn_tab_write(mac, BWN_TAB_4(10, 0x140 + offset), te.te_bbmult << 20);
14190}
14191
14192static void
14193bwn_sysctl_node(struct bwn_softc *sc)
14194{
14195 device_t dev = sc->sc_dev;
14196 struct bwn_mac *mac;
14197 struct bwn_stats *stats;
14198
14199 /* XXX assume that count of MAC is only 1. */
14200
14201 if ((mac = sc->sc_curmac) == NULL)
14202 return;
14203 stats = &mac->mac_stats;
14204
14205 SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
14206 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14207 "linknoise", CTLFLAG_RW, &stats->rts, 0, "Noise level");
14208 SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
14209 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14210 "rts", CTLFLAG_RW, &stats->rts, 0, "RTS");
14211 SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
14212 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14213 "rtsfail", CTLFLAG_RW, &stats->rtsfail, 0, "RTS failed to send");
14214
14215#ifdef BWN_DEBUG
14216 SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14217 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14218 "debug", CTLFLAG_RW, &sc->sc_debug, 0, "Debug flags");
14219#endif
14220}
14221
14222static device_method_t bwn_methods[] = {
14223 /* Device interface */
14224 DEVMETHOD(device_probe, bwn_probe),
14225 DEVMETHOD(device_attach, bwn_attach),
14226 DEVMETHOD(device_detach, bwn_detach),
14227 DEVMETHOD(device_suspend, bwn_suspend),
14228 DEVMETHOD(device_resume, bwn_resume),
14229 KOBJMETHOD_END
14230};
14231static driver_t bwn_driver = {
14232 "bwn",
14233 bwn_methods,
14234 sizeof(struct bwn_softc)
14235};
14236static devclass_t bwn_devclass;
14237DRIVER_MODULE(bwn, siba_bwn, bwn_driver, bwn_devclass, 0, 0);
14238MODULE_DEPEND(bwn, siba_bwn, 1, 1, 1);
14239MODULE_DEPEND(bwn, wlan, 1, 1, 1); /* 802.11 media layer */
14240MODULE_DEPEND(bwn, firmware, 1, 1, 1); /* firmware support */
14241MODULE_DEPEND(bwn, wlan_amrr, 1, 1, 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 227309 2011-11-07 15:43:11Z ed $");
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_phy.h>
71#include <net80211/ieee80211_ratectl.h>
72
73#include <dev/bwn/if_bwnreg.h>
74#include <dev/bwn/if_bwnvar.h>
75
76static SYSCTL_NODE(_hw, OID_AUTO, bwn, CTLFLAG_RD, 0,
77 "Broadcom driver parameters");
78
79/*
80 * Tunable & sysctl variables.
81 */
82
83#ifdef BWN_DEBUG
84static int bwn_debug = 0;
85SYSCTL_INT(_hw_bwn, OID_AUTO, debug, CTLFLAG_RW, &bwn_debug, 0,
86 "Broadcom debugging printfs");
87TUNABLE_INT("hw.bwn.debug", &bwn_debug);
88enum {
89 BWN_DEBUG_XMIT = 0x00000001, /* basic xmit operation */
90 BWN_DEBUG_RECV = 0x00000002, /* basic recv operation */
91 BWN_DEBUG_STATE = 0x00000004, /* 802.11 state transitions */
92 BWN_DEBUG_TXPOW = 0x00000008, /* tx power processing */
93 BWN_DEBUG_RESET = 0x00000010, /* reset processing */
94 BWN_DEBUG_OPS = 0x00000020, /* bwn_ops processing */
95 BWN_DEBUG_BEACON = 0x00000040, /* beacon handling */
96 BWN_DEBUG_WATCHDOG = 0x00000080, /* watchdog timeout */
97 BWN_DEBUG_INTR = 0x00000100, /* ISR */
98 BWN_DEBUG_CALIBRATE = 0x00000200, /* periodic calibration */
99 BWN_DEBUG_NODE = 0x00000400, /* node management */
100 BWN_DEBUG_LED = 0x00000800, /* led management */
101 BWN_DEBUG_CMD = 0x00001000, /* cmd submission */
102 BWN_DEBUG_LO = 0x00002000, /* LO */
103 BWN_DEBUG_FW = 0x00004000, /* firmware */
104 BWN_DEBUG_WME = 0x00008000, /* WME */
105 BWN_DEBUG_RF = 0x00010000, /* RF */
106 BWN_DEBUG_FATAL = 0x80000000, /* fatal errors */
107 BWN_DEBUG_ANY = 0xffffffff
108};
109#define DPRINTF(sc, m, fmt, ...) do { \
110 if (sc->sc_debug & (m)) \
111 printf(fmt, __VA_ARGS__); \
112} while (0)
113#else
114#define DPRINTF(sc, m, fmt, ...) do { (void) sc; } while (0)
115#endif
116
117static int bwn_bfp = 0; /* use "Bad Frames Preemption" */
118SYSCTL_INT(_hw_bwn, OID_AUTO, bfp, CTLFLAG_RW, &bwn_bfp, 0,
119 "uses Bad Frames Preemption");
120static int bwn_bluetooth = 1;
121SYSCTL_INT(_hw_bwn, OID_AUTO, bluetooth, CTLFLAG_RW, &bwn_bluetooth, 0,
122 "turns on Bluetooth Coexistence");
123static int bwn_hwpctl = 0;
124SYSCTL_INT(_hw_bwn, OID_AUTO, hwpctl, CTLFLAG_RW, &bwn_hwpctl, 0,
125 "uses H/W power control");
126static int bwn_msi_disable = 0; /* MSI disabled */
127TUNABLE_INT("hw.bwn.msi_disable", &bwn_msi_disable);
128static int bwn_usedma = 1;
129SYSCTL_INT(_hw_bwn, OID_AUTO, usedma, CTLFLAG_RD, &bwn_usedma, 0,
130 "uses DMA");
131TUNABLE_INT("hw.bwn.usedma", &bwn_usedma);
132static int bwn_wme = 1;
133SYSCTL_INT(_hw_bwn, OID_AUTO, wme, CTLFLAG_RW, &bwn_wme, 0,
134 "uses WME support");
135
136static int bwn_attach_pre(struct bwn_softc *);
137static int bwn_attach_post(struct bwn_softc *);
138static void bwn_sprom_bugfixes(device_t);
139static void bwn_init(void *);
140static int bwn_init_locked(struct bwn_softc *);
141static int bwn_ioctl(struct ifnet *, u_long, caddr_t);
142static void bwn_start(struct ifnet *);
143static int bwn_attach_core(struct bwn_mac *);
144static void bwn_reset_core(struct bwn_mac *, uint32_t);
145static int bwn_phy_getinfo(struct bwn_mac *, int);
146static int bwn_chiptest(struct bwn_mac *);
147static int bwn_setup_channels(struct bwn_mac *, int, int);
148static int bwn_phy_g_attach(struct bwn_mac *);
149static void bwn_phy_g_detach(struct bwn_mac *);
150static void bwn_phy_g_init_pre(struct bwn_mac *);
151static int bwn_phy_g_prepare_hw(struct bwn_mac *);
152static int bwn_phy_g_init(struct bwn_mac *);
153static void bwn_phy_g_exit(struct bwn_mac *);
154static uint16_t bwn_phy_g_read(struct bwn_mac *, uint16_t);
155static void bwn_phy_g_write(struct bwn_mac *, uint16_t,
156 uint16_t);
157static uint16_t bwn_phy_g_rf_read(struct bwn_mac *, uint16_t);
158static void bwn_phy_g_rf_write(struct bwn_mac *, uint16_t,
159 uint16_t);
160static int bwn_phy_g_hwpctl(struct bwn_mac *);
161static void bwn_phy_g_rf_onoff(struct bwn_mac *, int);
162static int bwn_phy_g_switch_channel(struct bwn_mac *, uint32_t);
163static uint32_t bwn_phy_g_get_default_chan(struct bwn_mac *);
164static void bwn_phy_g_set_antenna(struct bwn_mac *, int);
165static int bwn_phy_g_im(struct bwn_mac *, int);
166static int bwn_phy_g_recalc_txpwr(struct bwn_mac *, int);
167static void bwn_phy_g_set_txpwr(struct bwn_mac *);
168static void bwn_phy_g_task_15s(struct bwn_mac *);
169static void bwn_phy_g_task_60s(struct bwn_mac *);
170static uint16_t bwn_phy_g_txctl(struct bwn_mac *);
171static void bwn_phy_switch_analog(struct bwn_mac *, int);
172static uint16_t bwn_shm_read_2(struct bwn_mac *, uint16_t, uint16_t);
173static void bwn_shm_write_2(struct bwn_mac *, uint16_t, uint16_t,
174 uint16_t);
175static uint32_t bwn_shm_read_4(struct bwn_mac *, uint16_t, uint16_t);
176static void bwn_shm_write_4(struct bwn_mac *, uint16_t, uint16_t,
177 uint32_t);
178static void bwn_shm_ctlword(struct bwn_mac *, uint16_t,
179 uint16_t);
180static void bwn_addchannels(struct ieee80211_channel [], int, int *,
181 const struct bwn_channelinfo *, int);
182static int bwn_raw_xmit(struct ieee80211_node *, struct mbuf *,
183 const struct ieee80211_bpf_params *);
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 void bwn_wme_clear(struct bwn_softc *);
189static void bwn_wme_load(struct bwn_mac *);
190static void bwn_wme_loadparams(struct bwn_mac *,
191 const struct wmeParams *, uint16_t);
192static void bwn_scan_start(struct ieee80211com *);
193static void bwn_scan_end(struct ieee80211com *);
194static void bwn_set_channel(struct ieee80211com *);
195static struct ieee80211vap *bwn_vap_create(struct ieee80211com *,
196 const char [IFNAMSIZ], int, int,
197 int, const uint8_t [IEEE80211_ADDR_LEN],
198 const uint8_t [IEEE80211_ADDR_LEN]);
199static void bwn_vap_delete(struct ieee80211vap *);
200static void bwn_stop(struct bwn_softc *, int);
201static void bwn_stop_locked(struct bwn_softc *, int);
202static int bwn_core_init(struct bwn_mac *);
203static void bwn_core_start(struct bwn_mac *);
204static void bwn_core_exit(struct bwn_mac *);
205static void bwn_bt_disable(struct bwn_mac *);
206static int bwn_chip_init(struct bwn_mac *);
207static uint64_t bwn_hf_read(struct bwn_mac *);
208static void bwn_hf_write(struct bwn_mac *, uint64_t);
209static void bwn_set_txretry(struct bwn_mac *, int, int);
210static void bwn_rate_init(struct bwn_mac *);
211static void bwn_set_phytxctl(struct bwn_mac *);
212static void bwn_spu_setdelay(struct bwn_mac *, int);
213static void bwn_bt_enable(struct bwn_mac *);
214static void bwn_set_macaddr(struct bwn_mac *);
215static void bwn_crypt_init(struct bwn_mac *);
216static void bwn_chip_exit(struct bwn_mac *);
217static int bwn_fw_fillinfo(struct bwn_mac *);
218static int bwn_fw_loaducode(struct bwn_mac *);
219static int bwn_gpio_init(struct bwn_mac *);
220static int bwn_fw_loadinitvals(struct bwn_mac *);
221static int bwn_phy_init(struct bwn_mac *);
222static void bwn_set_txantenna(struct bwn_mac *, int);
223static void bwn_set_opmode(struct bwn_mac *);
224static void bwn_rate_write(struct bwn_mac *, uint16_t, int);
225static uint8_t bwn_plcp_getcck(const uint8_t);
226static uint8_t bwn_plcp_getofdm(const uint8_t);
227static void bwn_pio_init(struct bwn_mac *);
228static uint16_t bwn_pio_idx2base(struct bwn_mac *, int);
229static void bwn_pio_set_txqueue(struct bwn_mac *, struct bwn_pio_txqueue *,
230 int);
231static void bwn_pio_setupqueue_rx(struct bwn_mac *,
232 struct bwn_pio_rxqueue *, int);
233static void bwn_destroy_queue_tx(struct bwn_pio_txqueue *);
234static uint16_t bwn_pio_read_2(struct bwn_mac *, struct bwn_pio_txqueue *,
235 uint16_t);
236static void bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *);
237static int bwn_pio_rx(struct bwn_pio_rxqueue *);
238static uint8_t bwn_pio_rxeof(struct bwn_pio_rxqueue *);
239static void bwn_pio_handle_txeof(struct bwn_mac *,
240 const struct bwn_txstatus *);
241static uint16_t bwn_pio_rx_read_2(struct bwn_pio_rxqueue *, uint16_t);
242static uint32_t bwn_pio_rx_read_4(struct bwn_pio_rxqueue *, uint16_t);
243static void bwn_pio_rx_write_2(struct bwn_pio_rxqueue *, uint16_t,
244 uint16_t);
245static void bwn_pio_rx_write_4(struct bwn_pio_rxqueue *, uint16_t,
246 uint32_t);
247static int bwn_pio_tx_start(struct bwn_mac *, struct ieee80211_node *,
248 struct mbuf *);
249static struct bwn_pio_txqueue *bwn_pio_select(struct bwn_mac *, uint8_t);
250static uint32_t bwn_pio_write_multi_4(struct bwn_mac *,
251 struct bwn_pio_txqueue *, uint32_t, const void *, int);
252static void bwn_pio_write_4(struct bwn_mac *, struct bwn_pio_txqueue *,
253 uint16_t, uint32_t);
254static uint16_t bwn_pio_write_multi_2(struct bwn_mac *,
255 struct bwn_pio_txqueue *, uint16_t, const void *, int);
256static uint16_t bwn_pio_write_mbuf_2(struct bwn_mac *,
257 struct bwn_pio_txqueue *, uint16_t, struct mbuf *);
258static struct bwn_pio_txqueue *bwn_pio_parse_cookie(struct bwn_mac *,
259 uint16_t, struct bwn_pio_txpkt **);
260static void bwn_dma_init(struct bwn_mac *);
261static void bwn_dma_rxdirectfifo(struct bwn_mac *, int, uint8_t);
262static int bwn_dma_mask2type(uint64_t);
263static uint64_t bwn_dma_mask(struct bwn_mac *);
264static uint16_t bwn_dma_base(int, int);
265static void bwn_dma_ringfree(struct bwn_dma_ring **);
266static void bwn_dma_32_getdesc(struct bwn_dma_ring *,
267 int, struct bwn_dmadesc_generic **,
268 struct bwn_dmadesc_meta **);
269static void bwn_dma_32_setdesc(struct bwn_dma_ring *,
270 struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int,
271 int, int);
272static void bwn_dma_32_start_transfer(struct bwn_dma_ring *, int);
273static void bwn_dma_32_suspend(struct bwn_dma_ring *);
274static void bwn_dma_32_resume(struct bwn_dma_ring *);
275static int bwn_dma_32_get_curslot(struct bwn_dma_ring *);
276static void bwn_dma_32_set_curslot(struct bwn_dma_ring *, int);
277static void bwn_dma_64_getdesc(struct bwn_dma_ring *,
278 int, struct bwn_dmadesc_generic **,
279 struct bwn_dmadesc_meta **);
280static void bwn_dma_64_setdesc(struct bwn_dma_ring *,
281 struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int,
282 int, int);
283static void bwn_dma_64_start_transfer(struct bwn_dma_ring *, int);
284static void bwn_dma_64_suspend(struct bwn_dma_ring *);
285static void bwn_dma_64_resume(struct bwn_dma_ring *);
286static int bwn_dma_64_get_curslot(struct bwn_dma_ring *);
287static void bwn_dma_64_set_curslot(struct bwn_dma_ring *, int);
288static int bwn_dma_allocringmemory(struct bwn_dma_ring *);
289static void bwn_dma_setup(struct bwn_dma_ring *);
290static void bwn_dma_free_ringmemory(struct bwn_dma_ring *);
291static void bwn_dma_cleanup(struct bwn_dma_ring *);
292static void bwn_dma_free_descbufs(struct bwn_dma_ring *);
293static int bwn_dma_tx_reset(struct bwn_mac *, uint16_t, int);
294static void bwn_dma_rx(struct bwn_dma_ring *);
295static int bwn_dma_rx_reset(struct bwn_mac *, uint16_t, int);
296static void bwn_dma_free_descbuf(struct bwn_dma_ring *,
297 struct bwn_dmadesc_meta *);
298static void bwn_dma_set_redzone(struct bwn_dma_ring *, struct mbuf *);
299static int bwn_dma_gettype(struct bwn_mac *);
300static void bwn_dma_ring_addr(void *, bus_dma_segment_t *, int, int);
301static int bwn_dma_freeslot(struct bwn_dma_ring *);
302static int bwn_dma_nextslot(struct bwn_dma_ring *, int);
303static void bwn_dma_rxeof(struct bwn_dma_ring *, int *);
304static int bwn_dma_newbuf(struct bwn_dma_ring *,
305 struct bwn_dmadesc_generic *, struct bwn_dmadesc_meta *,
306 int);
307static void bwn_dma_buf_addr(void *, bus_dma_segment_t *, int,
308 bus_size_t, int);
309static uint8_t bwn_dma_check_redzone(struct bwn_dma_ring *, struct mbuf *);
310static void bwn_dma_handle_txeof(struct bwn_mac *,
311 const struct bwn_txstatus *);
312static int bwn_dma_tx_start(struct bwn_mac *, struct ieee80211_node *,
313 struct mbuf *);
314static int bwn_dma_getslot(struct bwn_dma_ring *);
315static struct bwn_dma_ring *bwn_dma_select(struct bwn_mac *,
316 uint8_t);
317static int bwn_dma_attach(struct bwn_mac *);
318static struct bwn_dma_ring *bwn_dma_ringsetup(struct bwn_mac *,
319 int, int, int);
320static struct bwn_dma_ring *bwn_dma_parse_cookie(struct bwn_mac *,
321 const struct bwn_txstatus *, uint16_t, int *);
322static void bwn_dma_free(struct bwn_mac *);
323static void bwn_phy_g_init_sub(struct bwn_mac *);
324static uint8_t bwn_has_hwpctl(struct bwn_mac *);
325static void bwn_phy_init_b5(struct bwn_mac *);
326static void bwn_phy_init_b6(struct bwn_mac *);
327static void bwn_phy_init_a(struct bwn_mac *);
328static void bwn_loopback_calcgain(struct bwn_mac *);
329static uint16_t bwn_rf_init_bcm2050(struct bwn_mac *);
330static void bwn_lo_g_init(struct bwn_mac *);
331static void bwn_lo_g_adjust(struct bwn_mac *);
332static void bwn_lo_get_powervector(struct bwn_mac *);
333static struct bwn_lo_calib *bwn_lo_calibset(struct bwn_mac *,
334 const struct bwn_bbatt *, const struct bwn_rfatt *);
335static void bwn_lo_write(struct bwn_mac *, struct bwn_loctl *);
336static void bwn_phy_hwpctl_init(struct bwn_mac *);
337static void bwn_phy_g_switch_chan(struct bwn_mac *, int, uint8_t);
338static void bwn_phy_g_set_txpwr_sub(struct bwn_mac *,
339 const struct bwn_bbatt *, const struct bwn_rfatt *,
340 uint8_t);
341static void bwn_phy_g_set_bbatt(struct bwn_mac *, uint16_t);
342static uint16_t bwn_rf_2050_rfoverval(struct bwn_mac *, uint16_t, uint32_t);
343static void bwn_spu_workaround(struct bwn_mac *, uint8_t);
344static void bwn_wa_init(struct bwn_mac *);
345static void bwn_ofdmtab_write_2(struct bwn_mac *, uint16_t, uint16_t,
346 uint16_t);
347static void bwn_dummy_transmission(struct bwn_mac *, int, int);
348static void bwn_ofdmtab_write_4(struct bwn_mac *, uint16_t, uint16_t,
349 uint32_t);
350static void bwn_gtab_write(struct bwn_mac *, uint16_t, uint16_t,
351 uint16_t);
352static void bwn_ram_write(struct bwn_mac *, uint16_t, uint32_t);
353static void bwn_mac_suspend(struct bwn_mac *);
354static void bwn_mac_enable(struct bwn_mac *);
355static void bwn_psctl(struct bwn_mac *, uint32_t);
356static int16_t bwn_nrssi_read(struct bwn_mac *, uint16_t);
357static void bwn_nrssi_offset(struct bwn_mac *);
358static void bwn_nrssi_threshold(struct bwn_mac *);
359static void bwn_nrssi_slope_11g(struct bwn_mac *);
360static void bwn_set_all_gains(struct bwn_mac *, int16_t, int16_t,
361 int16_t);
362static void bwn_set_original_gains(struct bwn_mac *);
363static void bwn_hwpctl_early_init(struct bwn_mac *);
364static void bwn_hwpctl_init_gphy(struct bwn_mac *);
365static uint16_t bwn_phy_g_chan2freq(uint8_t);
366static int bwn_fw_gets(struct bwn_mac *, enum bwn_fwtype);
367static int bwn_fw_get(struct bwn_mac *, enum bwn_fwtype,
368 const char *, struct bwn_fwfile *);
369static void bwn_release_firmware(struct bwn_mac *);
370static void bwn_do_release_fw(struct bwn_fwfile *);
371static uint16_t bwn_fwcaps_read(struct bwn_mac *);
372static int bwn_fwinitvals_write(struct bwn_mac *,
373 const struct bwn_fwinitvals *, size_t, size_t);
374static int bwn_switch_channel(struct bwn_mac *, int);
375static uint16_t bwn_ant2phy(int);
376static void bwn_mac_write_bssid(struct bwn_mac *);
377static void bwn_mac_setfilter(struct bwn_mac *, uint16_t,
378 const uint8_t *);
379static void bwn_key_dowrite(struct bwn_mac *, uint8_t, uint8_t,
380 const uint8_t *, size_t, const uint8_t *);
381static void bwn_key_macwrite(struct bwn_mac *, uint8_t,
382 const uint8_t *);
383static void bwn_key_write(struct bwn_mac *, uint8_t, uint8_t,
384 const uint8_t *);
385static void bwn_phy_exit(struct bwn_mac *);
386static void bwn_core_stop(struct bwn_mac *);
387static int bwn_switch_band(struct bwn_softc *,
388 struct ieee80211_channel *);
389static void bwn_phy_reset(struct bwn_mac *);
390static int bwn_newstate(struct ieee80211vap *, enum ieee80211_state, int);
391static void bwn_set_pretbtt(struct bwn_mac *);
392static int bwn_intr(void *);
393static void bwn_intrtask(void *, int);
394static void bwn_restart(struct bwn_mac *, const char *);
395static void bwn_intr_ucode_debug(struct bwn_mac *);
396static void bwn_intr_tbtt_indication(struct bwn_mac *);
397static void bwn_intr_atim_end(struct bwn_mac *);
398static void bwn_intr_beacon(struct bwn_mac *);
399static void bwn_intr_pmq(struct bwn_mac *);
400static void bwn_intr_noise(struct bwn_mac *);
401static void bwn_intr_txeof(struct bwn_mac *);
402static void bwn_hwreset(void *, int);
403static void bwn_handle_fwpanic(struct bwn_mac *);
404static void bwn_load_beacon0(struct bwn_mac *);
405static void bwn_load_beacon1(struct bwn_mac *);
406static uint32_t bwn_jssi_read(struct bwn_mac *);
407static void bwn_noise_gensample(struct bwn_mac *);
408static void bwn_handle_txeof(struct bwn_mac *,
409 const struct bwn_txstatus *);
410static void bwn_rxeof(struct bwn_mac *, struct mbuf *, const void *);
411static void bwn_phy_txpower_check(struct bwn_mac *, uint32_t);
412static void bwn_start_locked(struct ifnet *);
413static int bwn_tx_start(struct bwn_softc *, struct ieee80211_node *,
414 struct mbuf *);
415static int bwn_tx_isfull(struct bwn_softc *, struct mbuf *);
416static int bwn_set_txhdr(struct bwn_mac *,
417 struct ieee80211_node *, struct mbuf *, struct bwn_txhdr *,
418 uint16_t);
419static void bwn_plcp_genhdr(struct bwn_plcp4 *, const uint16_t,
420 const uint8_t);
421static uint8_t bwn_antenna_sanitize(struct bwn_mac *, uint8_t);
422static uint8_t bwn_get_fbrate(uint8_t);
423static int bwn_phy_shm_tssi_read(struct bwn_mac *, uint16_t);
424static void bwn_phy_g_setatt(struct bwn_mac *, int *, int *);
425static void bwn_phy_lock(struct bwn_mac *);
426static void bwn_phy_unlock(struct bwn_mac *);
427static void bwn_rf_lock(struct bwn_mac *);
428static void bwn_rf_unlock(struct bwn_mac *);
429static void bwn_txpwr(void *, int);
430static void bwn_tasks(void *);
431static void bwn_task_15s(struct bwn_mac *);
432static void bwn_task_30s(struct bwn_mac *);
433static void bwn_task_60s(struct bwn_mac *);
434static int bwn_plcp_get_ofdmrate(struct bwn_mac *, struct bwn_plcp6 *,
435 uint8_t);
436static int bwn_plcp_get_cckrate(struct bwn_mac *, struct bwn_plcp6 *);
437static void bwn_rx_radiotap(struct bwn_mac *, struct mbuf *,
438 const struct bwn_rxhdr4 *, struct bwn_plcp6 *, int,
439 int, int);
440static void bwn_tsf_read(struct bwn_mac *, uint64_t *);
441static void bwn_phy_g_dc_lookup_init(struct bwn_mac *, uint8_t);
442static void bwn_set_slot_time(struct bwn_mac *, uint16_t);
443static void bwn_watchdog(void *);
444static void bwn_dma_stop(struct bwn_mac *);
445static void bwn_pio_stop(struct bwn_mac *);
446static void bwn_dma_ringstop(struct bwn_dma_ring **);
447static void bwn_led_attach(struct bwn_mac *);
448static void bwn_led_newstate(struct bwn_mac *, enum ieee80211_state);
449static void bwn_led_event(struct bwn_mac *, int);
450static void bwn_led_blink_start(struct bwn_mac *, int, int);
451static void bwn_led_blink_next(void *);
452static void bwn_led_blink_end(void *);
453static void bwn_rfswitch(void *);
454static void bwn_rf_turnon(struct bwn_mac *);
455static void bwn_rf_turnoff(struct bwn_mac *);
456static void bwn_phy_lp_init_pre(struct bwn_mac *);
457static int bwn_phy_lp_init(struct bwn_mac *);
458static uint16_t bwn_phy_lp_read(struct bwn_mac *, uint16_t);
459static void bwn_phy_lp_write(struct bwn_mac *, uint16_t, uint16_t);
460static void bwn_phy_lp_maskset(struct bwn_mac *, uint16_t, uint16_t,
461 uint16_t);
462static uint16_t bwn_phy_lp_rf_read(struct bwn_mac *, uint16_t);
463static void bwn_phy_lp_rf_write(struct bwn_mac *, uint16_t, uint16_t);
464static void bwn_phy_lp_rf_onoff(struct bwn_mac *, int);
465static int bwn_phy_lp_switch_channel(struct bwn_mac *, uint32_t);
466static uint32_t bwn_phy_lp_get_default_chan(struct bwn_mac *);
467static void bwn_phy_lp_set_antenna(struct bwn_mac *, int);
468static void bwn_phy_lp_task_60s(struct bwn_mac *);
469static void bwn_phy_lp_readsprom(struct bwn_mac *);
470static void bwn_phy_lp_bbinit(struct bwn_mac *);
471static void bwn_phy_lp_txpctl_init(struct bwn_mac *);
472static void bwn_phy_lp_calib(struct bwn_mac *);
473static void bwn_phy_lp_switch_analog(struct bwn_mac *, int);
474static int bwn_phy_lp_b2062_switch_channel(struct bwn_mac *, uint8_t);
475static int bwn_phy_lp_b2063_switch_channel(struct bwn_mac *, uint8_t);
476static void bwn_phy_lp_set_anafilter(struct bwn_mac *, uint8_t);
477static void bwn_phy_lp_set_gaintbl(struct bwn_mac *, uint32_t);
478static void bwn_phy_lp_digflt_save(struct bwn_mac *);
479static void bwn_phy_lp_get_txpctlmode(struct bwn_mac *);
480static void bwn_phy_lp_set_txpctlmode(struct bwn_mac *, uint8_t);
481static void bwn_phy_lp_bugfix(struct bwn_mac *);
482static void bwn_phy_lp_digflt_restore(struct bwn_mac *);
483static void bwn_phy_lp_tblinit(struct bwn_mac *);
484static void bwn_phy_lp_bbinit_r2(struct bwn_mac *);
485static void bwn_phy_lp_bbinit_r01(struct bwn_mac *);
486static void bwn_phy_lp_b2062_init(struct bwn_mac *);
487static void bwn_phy_lp_b2063_init(struct bwn_mac *);
488static void bwn_phy_lp_rxcal_r2(struct bwn_mac *);
489static void bwn_phy_lp_rccal_r12(struct bwn_mac *);
490static void bwn_phy_lp_set_rccap(struct bwn_mac *);
491static uint32_t bwn_phy_lp_roundup(uint32_t, uint32_t, uint8_t);
492static void bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *);
493static void bwn_phy_lp_b2062_vco_calib(struct bwn_mac *);
494static void bwn_tab_write_multi(struct bwn_mac *, uint32_t, int,
495 const void *);
496static void bwn_tab_read_multi(struct bwn_mac *, uint32_t, int, void *);
497static struct bwn_txgain
498 bwn_phy_lp_get_txgain(struct bwn_mac *);
499static uint8_t bwn_phy_lp_get_bbmult(struct bwn_mac *);
500static void bwn_phy_lp_set_txgain(struct bwn_mac *, struct bwn_txgain *);
501static void bwn_phy_lp_set_bbmult(struct bwn_mac *, uint8_t);
502static void bwn_phy_lp_set_trsw_over(struct bwn_mac *, uint8_t, uint8_t);
503static void bwn_phy_lp_set_rxgain(struct bwn_mac *, uint32_t);
504static void bwn_phy_lp_set_deaf(struct bwn_mac *, uint8_t);
505static int bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *, uint16_t);
506static void bwn_phy_lp_clear_deaf(struct bwn_mac *, uint8_t);
507static void bwn_phy_lp_tblinit_r01(struct bwn_mac *);
508static void bwn_phy_lp_tblinit_r2(struct bwn_mac *);
509static void bwn_phy_lp_tblinit_txgain(struct bwn_mac *);
510static void bwn_tab_write(struct bwn_mac *, uint32_t, uint32_t);
511static void bwn_phy_lp_b2062_tblinit(struct bwn_mac *);
512static void bwn_phy_lp_b2063_tblinit(struct bwn_mac *);
513static int bwn_phy_lp_loopback(struct bwn_mac *);
514static void bwn_phy_lp_set_rxgain_idx(struct bwn_mac *, uint16_t);
515static void bwn_phy_lp_ddfs_turnon(struct bwn_mac *, int, int, int, int,
516 int);
517static uint8_t bwn_phy_lp_rx_iq_est(struct bwn_mac *, uint16_t, uint8_t,
518 struct bwn_phy_lp_iq_est *);
519static void bwn_phy_lp_ddfs_turnoff(struct bwn_mac *);
520static uint32_t bwn_tab_read(struct bwn_mac *, uint32_t);
521static void bwn_phy_lp_set_txgain_dac(struct bwn_mac *, uint16_t);
522static void bwn_phy_lp_set_txgain_pa(struct bwn_mac *, uint16_t);
523static void bwn_phy_lp_set_txgain_override(struct bwn_mac *);
524static uint16_t bwn_phy_lp_get_pa_gain(struct bwn_mac *);
525static uint8_t bwn_nbits(int32_t);
526static void bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *, int, int,
527 struct bwn_txgain_entry *);
528static void bwn_phy_lp_gaintbl_write(struct bwn_mac *, int,
529 struct bwn_txgain_entry);
530static void bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *, int,
531 struct bwn_txgain_entry);
532static void bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *, int,
533 struct bwn_txgain_entry);
534static void bwn_sysctl_node(struct bwn_softc *);
535
536static struct resource_spec bwn_res_spec_legacy[] = {
537 { SYS_RES_IRQ, 0, RF_ACTIVE | RF_SHAREABLE },
538 { -1, 0, 0 }
539};
540
541static struct resource_spec bwn_res_spec_msi[] = {
542 { SYS_RES_IRQ, 1, RF_ACTIVE },
543 { -1, 0, 0 }
544};
545
546static const struct bwn_channelinfo bwn_chantable_bg = {
547 .channels = {
548 { 2412, 1, 30 }, { 2417, 2, 30 }, { 2422, 3, 30 },
549 { 2427, 4, 30 }, { 2432, 5, 30 }, { 2437, 6, 30 },
550 { 2442, 7, 30 }, { 2447, 8, 30 }, { 2452, 9, 30 },
551 { 2457, 10, 30 }, { 2462, 11, 30 }, { 2467, 12, 30 },
552 { 2472, 13, 30 }, { 2484, 14, 30 } },
553 .nchannels = 14
554};
555
556static const struct bwn_channelinfo bwn_chantable_a = {
557 .channels = {
558 { 5170, 34, 30 }, { 5180, 36, 30 }, { 5190, 38, 30 },
559 { 5200, 40, 30 }, { 5210, 42, 30 }, { 5220, 44, 30 },
560 { 5230, 46, 30 }, { 5240, 48, 30 }, { 5260, 52, 30 },
561 { 5280, 56, 30 }, { 5300, 60, 30 }, { 5320, 64, 30 },
562 { 5500, 100, 30 }, { 5520, 104, 30 }, { 5540, 108, 30 },
563 { 5560, 112, 30 }, { 5580, 116, 30 }, { 5600, 120, 30 },
564 { 5620, 124, 30 }, { 5640, 128, 30 }, { 5660, 132, 30 },
565 { 5680, 136, 30 }, { 5700, 140, 30 }, { 5745, 149, 30 },
566 { 5765, 153, 30 }, { 5785, 157, 30 }, { 5805, 161, 30 },
567 { 5825, 165, 30 }, { 5920, 184, 30 }, { 5940, 188, 30 },
568 { 5960, 192, 30 }, { 5980, 196, 30 }, { 6000, 200, 30 },
569 { 6020, 204, 30 }, { 6040, 208, 30 }, { 6060, 212, 30 },
570 { 6080, 216, 30 } },
571 .nchannels = 37
572};
573
574static const struct bwn_channelinfo bwn_chantable_n = {
575 .channels = {
576 { 5160, 32, 30 }, { 5170, 34, 30 }, { 5180, 36, 30 },
577 { 5190, 38, 30 }, { 5200, 40, 30 }, { 5210, 42, 30 },
578 { 5220, 44, 30 }, { 5230, 46, 30 }, { 5240, 48, 30 },
579 { 5250, 50, 30 }, { 5260, 52, 30 }, { 5270, 54, 30 },
580 { 5280, 56, 30 }, { 5290, 58, 30 }, { 5300, 60, 30 },
581 { 5310, 62, 30 }, { 5320, 64, 30 }, { 5330, 66, 30 },
582 { 5340, 68, 30 }, { 5350, 70, 30 }, { 5360, 72, 30 },
583 { 5370, 74, 30 }, { 5380, 76, 30 }, { 5390, 78, 30 },
584 { 5400, 80, 30 }, { 5410, 82, 30 }, { 5420, 84, 30 },
585 { 5430, 86, 30 }, { 5440, 88, 30 }, { 5450, 90, 30 },
586 { 5460, 92, 30 }, { 5470, 94, 30 }, { 5480, 96, 30 },
587 { 5490, 98, 30 }, { 5500, 100, 30 }, { 5510, 102, 30 },
588 { 5520, 104, 30 }, { 5530, 106, 30 }, { 5540, 108, 30 },
589 { 5550, 110, 30 }, { 5560, 112, 30 }, { 5570, 114, 30 },
590 { 5580, 116, 30 }, { 5590, 118, 30 }, { 5600, 120, 30 },
591 { 5610, 122, 30 }, { 5620, 124, 30 }, { 5630, 126, 30 },
592 { 5640, 128, 30 }, { 5650, 130, 30 }, { 5660, 132, 30 },
593 { 5670, 134, 30 }, { 5680, 136, 30 }, { 5690, 138, 30 },
594 { 5700, 140, 30 }, { 5710, 142, 30 }, { 5720, 144, 30 },
595 { 5725, 145, 30 }, { 5730, 146, 30 }, { 5735, 147, 30 },
596 { 5740, 148, 30 }, { 5745, 149, 30 }, { 5750, 150, 30 },
597 { 5755, 151, 30 }, { 5760, 152, 30 }, { 5765, 153, 30 },
598 { 5770, 154, 30 }, { 5775, 155, 30 }, { 5780, 156, 30 },
599 { 5785, 157, 30 }, { 5790, 158, 30 }, { 5795, 159, 30 },
600 { 5800, 160, 30 }, { 5805, 161, 30 }, { 5810, 162, 30 },
601 { 5815, 163, 30 }, { 5820, 164, 30 }, { 5825, 165, 30 },
602 { 5830, 166, 30 }, { 5840, 168, 30 }, { 5850, 170, 30 },
603 { 5860, 172, 30 }, { 5870, 174, 30 }, { 5880, 176, 30 },
604 { 5890, 178, 30 }, { 5900, 180, 30 }, { 5910, 182, 30 },
605 { 5920, 184, 30 }, { 5930, 186, 30 }, { 5940, 188, 30 },
606 { 5950, 190, 30 }, { 5960, 192, 30 }, { 5970, 194, 30 },
607 { 5980, 196, 30 }, { 5990, 198, 30 }, { 6000, 200, 30 },
608 { 6010, 202, 30 }, { 6020, 204, 30 }, { 6030, 206, 30 },
609 { 6040, 208, 30 }, { 6050, 210, 30 }, { 6060, 212, 30 },
610 { 6070, 214, 30 }, { 6080, 216, 30 }, { 6090, 218, 30 },
611 { 6100, 220, 30 }, { 6110, 222, 30 }, { 6120, 224, 30 },
612 { 6130, 226, 30 }, { 6140, 228, 30 } },
613 .nchannels = 110
614};
615
616static const uint8_t bwn_b2063_chantable_data[33][12] = {
617 { 0x6f, 0x3c, 0x3c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
618 { 0x6f, 0x2c, 0x2c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
619 { 0x6f, 0x1c, 0x1c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
620 { 0x6e, 0x1c, 0x1c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
621 { 0x6e, 0xc, 0xc, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
622 { 0x6a, 0xc, 0xc, 0, 0x2, 0x5, 0xd, 0xd, 0x77, 0x80, 0x20, 0 },
623 { 0x6a, 0xc, 0xc, 0, 0x1, 0x5, 0xd, 0xc, 0x77, 0x80, 0x20, 0 },
624 { 0x6a, 0xc, 0xc, 0, 0x1, 0x4, 0xc, 0xc, 0x77, 0x80, 0x20, 0 },
625 { 0x69, 0xc, 0xc, 0, 0x1, 0x4, 0xc, 0xc, 0x77, 0x70, 0x20, 0 },
626 { 0x69, 0xc, 0xc, 0, 0x1, 0x4, 0xb, 0xc, 0x77, 0x70, 0x20, 0 },
627 { 0x69, 0xc, 0xc, 0, 0, 0x4, 0xb, 0xb, 0x77, 0x60, 0x20, 0 },
628 { 0x69, 0xc, 0xc, 0, 0, 0x3, 0xa, 0xb, 0x77, 0x60, 0x20, 0 },
629 { 0x69, 0xc, 0xc, 0, 0, 0x3, 0xa, 0xa, 0x77, 0x60, 0x20, 0 },
630 { 0x68, 0xc, 0xc, 0, 0, 0x2, 0x9, 0x9, 0x77, 0x60, 0x20, 0 },
631 { 0x68, 0xc, 0xc, 0, 0, 0x1, 0x8, 0x8, 0x77, 0x50, 0x10, 0 },
632 { 0x67, 0xc, 0xc, 0, 0, 0, 0x8, 0x8, 0x77, 0x50, 0x10, 0 },
633 { 0x64, 0xc, 0xc, 0, 0, 0, 0x2, 0x1, 0x77, 0x20, 0, 0 },
634 { 0x64, 0xc, 0xc, 0, 0, 0, 0x1, 0x1, 0x77, 0x20, 0, 0 },
635 { 0x63, 0xc, 0xc, 0, 0, 0, 0x1, 0, 0x77, 0x10, 0, 0 },
636 { 0x63, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0x10, 0, 0 },
637 { 0x62, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0x10, 0, 0 },
638 { 0x62, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
639 { 0x61, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
640 { 0x60, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
641 { 0x6e, 0xc, 0xc, 0, 0x9, 0xe, 0xf, 0xf, 0x77, 0xc0, 0x50, 0 },
642 { 0x6e, 0xc, 0xc, 0, 0x9, 0xd, 0xf, 0xf, 0x77, 0xb0, 0x50, 0 },
643 { 0x6e, 0xc, 0xc, 0, 0x8, 0xc, 0xf, 0xf, 0x77, 0xb0, 0x50, 0 },
644 { 0x6d, 0xc, 0xc, 0, 0x8, 0xc, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
645 { 0x6d, 0xc, 0xc, 0, 0x8, 0xb, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
646 { 0x6d, 0xc, 0xc, 0, 0x8, 0xa, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
647 { 0x6c, 0xc, 0xc, 0, 0x7, 0x9, 0xf, 0xf, 0x77, 0x90, 0x40, 0 },
648 { 0x6c, 0xc, 0xc, 0, 0x6, 0x8, 0xf, 0xf, 0x77, 0x90, 0x40, 0 },
649 { 0x6c, 0xc, 0xc, 0, 0x5, 0x8, 0xf, 0xf, 0x77, 0x90, 0x40, 0 }
650};
651
652static const struct bwn_b206x_chan bwn_b2063_chantable[] = {
653 { 1, 2412, bwn_b2063_chantable_data[0] },
654 { 2, 2417, bwn_b2063_chantable_data[0] },
655 { 3, 2422, bwn_b2063_chantable_data[0] },
656 { 4, 2427, bwn_b2063_chantable_data[1] },
657 { 5, 2432, bwn_b2063_chantable_data[1] },
658 { 6, 2437, bwn_b2063_chantable_data[1] },
659 { 7, 2442, bwn_b2063_chantable_data[1] },
660 { 8, 2447, bwn_b2063_chantable_data[1] },
661 { 9, 2452, bwn_b2063_chantable_data[2] },
662 { 10, 2457, bwn_b2063_chantable_data[2] },
663 { 11, 2462, bwn_b2063_chantable_data[3] },
664 { 12, 2467, bwn_b2063_chantable_data[3] },
665 { 13, 2472, bwn_b2063_chantable_data[3] },
666 { 14, 2484, bwn_b2063_chantable_data[4] },
667 { 34, 5170, bwn_b2063_chantable_data[5] },
668 { 36, 5180, bwn_b2063_chantable_data[6] },
669 { 38, 5190, bwn_b2063_chantable_data[7] },
670 { 40, 5200, bwn_b2063_chantable_data[8] },
671 { 42, 5210, bwn_b2063_chantable_data[9] },
672 { 44, 5220, bwn_b2063_chantable_data[10] },
673 { 46, 5230, bwn_b2063_chantable_data[11] },
674 { 48, 5240, bwn_b2063_chantable_data[12] },
675 { 52, 5260, bwn_b2063_chantable_data[13] },
676 { 56, 5280, bwn_b2063_chantable_data[14] },
677 { 60, 5300, bwn_b2063_chantable_data[14] },
678 { 64, 5320, bwn_b2063_chantable_data[15] },
679 { 100, 5500, bwn_b2063_chantable_data[16] },
680 { 104, 5520, bwn_b2063_chantable_data[17] },
681 { 108, 5540, bwn_b2063_chantable_data[18] },
682 { 112, 5560, bwn_b2063_chantable_data[19] },
683 { 116, 5580, bwn_b2063_chantable_data[20] },
684 { 120, 5600, bwn_b2063_chantable_data[21] },
685 { 124, 5620, bwn_b2063_chantable_data[21] },
686 { 128, 5640, bwn_b2063_chantable_data[22] },
687 { 132, 5660, bwn_b2063_chantable_data[22] },
688 { 136, 5680, bwn_b2063_chantable_data[22] },
689 { 140, 5700, bwn_b2063_chantable_data[23] },
690 { 149, 5745, bwn_b2063_chantable_data[23] },
691 { 153, 5765, bwn_b2063_chantable_data[23] },
692 { 157, 5785, bwn_b2063_chantable_data[23] },
693 { 161, 5805, bwn_b2063_chantable_data[23] },
694 { 165, 5825, bwn_b2063_chantable_data[23] },
695 { 184, 4920, bwn_b2063_chantable_data[24] },
696 { 188, 4940, bwn_b2063_chantable_data[25] },
697 { 192, 4960, bwn_b2063_chantable_data[26] },
698 { 196, 4980, bwn_b2063_chantable_data[27] },
699 { 200, 5000, bwn_b2063_chantable_data[28] },
700 { 204, 5020, bwn_b2063_chantable_data[29] },
701 { 208, 5040, bwn_b2063_chantable_data[30] },
702 { 212, 5060, bwn_b2063_chantable_data[31] },
703 { 216, 5080, bwn_b2063_chantable_data[32] }
704};
705
706static const uint8_t bwn_b2062_chantable_data[22][12] = {
707 { 0xff, 0xff, 0xb5, 0x1b, 0x24, 0x32, 0x32, 0x88, 0x88, 0, 0, 0 },
708 { 0, 0x22, 0x20, 0x84, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
709 { 0, 0x11, 0x10, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
710 { 0, 0, 0, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
711 { 0, 0x11, 0x20, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
712 { 0, 0x11, 0x10, 0x84, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
713 { 0, 0x11, 0, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
714 { 0, 0, 0, 0x63, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
715 { 0, 0, 0, 0x62, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
716 { 0, 0, 0, 0x30, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
717 { 0, 0, 0, 0x20, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
718 { 0, 0, 0, 0x10, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
719 { 0, 0, 0, 0, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
720 { 0x55, 0x77, 0x90, 0xf7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
721 { 0x44, 0x77, 0x80, 0xe7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
722 { 0x44, 0x66, 0x80, 0xe7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
723 { 0x33, 0x66, 0x70, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
724 { 0x22, 0x55, 0x60, 0xd7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
725 { 0x22, 0x55, 0x60, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
726 { 0x22, 0x44, 0x50, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
727 { 0x11, 0x44, 0x50, 0xa5, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
728 { 0, 0x44, 0x40, 0xb6, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 }
729};
730
731static const struct bwn_b206x_chan bwn_b2062_chantable[] = {
732 { 1, 2412, bwn_b2062_chantable_data[0] },
733 { 2, 2417, bwn_b2062_chantable_data[0] },
734 { 3, 2422, bwn_b2062_chantable_data[0] },
735 { 4, 2427, bwn_b2062_chantable_data[0] },
736 { 5, 2432, bwn_b2062_chantable_data[0] },
737 { 6, 2437, bwn_b2062_chantable_data[0] },
738 { 7, 2442, bwn_b2062_chantable_data[0] },
739 { 8, 2447, bwn_b2062_chantable_data[0] },
740 { 9, 2452, bwn_b2062_chantable_data[0] },
741 { 10, 2457, bwn_b2062_chantable_data[0] },
742 { 11, 2462, bwn_b2062_chantable_data[0] },
743 { 12, 2467, bwn_b2062_chantable_data[0] },
744 { 13, 2472, bwn_b2062_chantable_data[0] },
745 { 14, 2484, bwn_b2062_chantable_data[0] },
746 { 34, 5170, bwn_b2062_chantable_data[1] },
747 { 38, 5190, bwn_b2062_chantable_data[2] },
748 { 42, 5210, bwn_b2062_chantable_data[2] },
749 { 46, 5230, bwn_b2062_chantable_data[3] },
750 { 36, 5180, bwn_b2062_chantable_data[4] },
751 { 40, 5200, bwn_b2062_chantable_data[5] },
752 { 44, 5220, bwn_b2062_chantable_data[6] },
753 { 48, 5240, bwn_b2062_chantable_data[3] },
754 { 52, 5260, bwn_b2062_chantable_data[3] },
755 { 56, 5280, bwn_b2062_chantable_data[3] },
756 { 60, 5300, bwn_b2062_chantable_data[7] },
757 { 64, 5320, bwn_b2062_chantable_data[8] },
758 { 100, 5500, bwn_b2062_chantable_data[9] },
759 { 104, 5520, bwn_b2062_chantable_data[10] },
760 { 108, 5540, bwn_b2062_chantable_data[10] },
761 { 112, 5560, bwn_b2062_chantable_data[10] },
762 { 116, 5580, bwn_b2062_chantable_data[11] },
763 { 120, 5600, bwn_b2062_chantable_data[12] },
764 { 124, 5620, bwn_b2062_chantable_data[12] },
765 { 128, 5640, bwn_b2062_chantable_data[12] },
766 { 132, 5660, bwn_b2062_chantable_data[12] },
767 { 136, 5680, bwn_b2062_chantable_data[12] },
768 { 140, 5700, bwn_b2062_chantable_data[12] },
769 { 149, 5745, bwn_b2062_chantable_data[12] },
770 { 153, 5765, bwn_b2062_chantable_data[12] },
771 { 157, 5785, bwn_b2062_chantable_data[12] },
772 { 161, 5805, bwn_b2062_chantable_data[12] },
773 { 165, 5825, bwn_b2062_chantable_data[12] },
774 { 184, 4920, bwn_b2062_chantable_data[13] },
775 { 188, 4940, bwn_b2062_chantable_data[14] },
776 { 192, 4960, bwn_b2062_chantable_data[15] },
777 { 196, 4980, bwn_b2062_chantable_data[16] },
778 { 200, 5000, bwn_b2062_chantable_data[17] },
779 { 204, 5020, bwn_b2062_chantable_data[18] },
780 { 208, 5040, bwn_b2062_chantable_data[19] },
781 { 212, 5060, bwn_b2062_chantable_data[20] },
782 { 216, 5080, bwn_b2062_chantable_data[21] }
783};
784
785/* for LP PHY */
786static const struct bwn_rxcompco bwn_rxcompco_5354[] = {
787 { 1, -66, 15 }, { 2, -66, 15 }, { 3, -66, 15 }, { 4, -66, 15 },
788 { 5, -66, 15 }, { 6, -66, 15 }, { 7, -66, 14 }, { 8, -66, 14 },
789 { 9, -66, 14 }, { 10, -66, 14 }, { 11, -66, 14 }, { 12, -66, 13 },
790 { 13, -66, 13 }, { 14, -66, 13 },
791};
792
793/* for LP PHY */
794static const struct bwn_rxcompco bwn_rxcompco_r12[] = {
795 { 1, -64, 13 }, { 2, -64, 13 }, { 3, -64, 13 }, { 4, -64, 13 },
796 { 5, -64, 12 }, { 6, -64, 12 }, { 7, -64, 12 }, { 8, -64, 12 },
797 { 9, -64, 12 }, { 10, -64, 11 }, { 11, -64, 11 }, { 12, -64, 11 },
798 { 13, -64, 11 }, { 14, -64, 10 }, { 34, -62, 24 }, { 38, -62, 24 },
799 { 42, -62, 24 }, { 46, -62, 23 }, { 36, -62, 24 }, { 40, -62, 24 },
800 { 44, -62, 23 }, { 48, -62, 23 }, { 52, -62, 23 }, { 56, -62, 22 },
801 { 60, -62, 22 }, { 64, -62, 22 }, { 100, -62, 16 }, { 104, -62, 16 },
802 { 108, -62, 15 }, { 112, -62, 14 }, { 116, -62, 14 }, { 120, -62, 13 },
803 { 124, -62, 12 }, { 128, -62, 12 }, { 132, -62, 12 }, { 136, -62, 11 },
804 { 140, -62, 10 }, { 149, -61, 9 }, { 153, -61, 9 }, { 157, -61, 9 },
805 { 161, -61, 8 }, { 165, -61, 8 }, { 184, -62, 25 }, { 188, -62, 25 },
806 { 192, -62, 25 }, { 196, -62, 25 }, { 200, -62, 25 }, { 204, -62, 25 },
807 { 208, -62, 25 }, { 212, -62, 25 }, { 216, -62, 26 },
808};
809
810static const struct bwn_rxcompco bwn_rxcompco_r2 = { 0, -64, 0 };
811
812static const uint8_t bwn_tab_sigsq_tbl[] = {
813 0xde, 0xdc, 0xda, 0xd8, 0xd6, 0xd4, 0xd2, 0xcf, 0xcd,
814 0xca, 0xc7, 0xc4, 0xc1, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
815 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0x00,
816 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
817 0xbe, 0xbe, 0xbe, 0xbe, 0xc1, 0xc4, 0xc7, 0xca, 0xcd,
818 0xcf, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
819};
820
821static const uint8_t bwn_tab_pllfrac_tbl[] = {
822 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x80,
823 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
824};
825
826static const uint16_t bwn_tabl_iqlocal_tbl[] = {
827 0x0200, 0x0300, 0x0400, 0x0600, 0x0800, 0x0b00, 0x1000, 0x1001, 0x1002,
828 0x1003, 0x1004, 0x1005, 0x1006, 0x1007, 0x1707, 0x2007, 0x2d07, 0x4007,
829 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
830 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0200, 0x0300, 0x0400, 0x0600,
831 0x0800, 0x0b00, 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006,
832 0x1007, 0x1707, 0x2007, 0x2d07, 0x4007, 0x0000, 0x0000, 0x0000, 0x0000,
833 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
834 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
835 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
836 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4000, 0x0000, 0x0000,
837 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
838 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
839};
840
841static const uint16_t bwn_tab_noise_g1[] = BWN_TAB_NOISE_G1;
842static const uint16_t bwn_tab_noise_g2[] = BWN_TAB_NOISE_G2;
843static const uint16_t bwn_tab_noisescale_g1[] = BWN_TAB_NOISESCALE_G1;
844static const uint16_t bwn_tab_noisescale_g2[] = BWN_TAB_NOISESCALE_G2;
845static const uint16_t bwn_tab_noisescale_g3[] = BWN_TAB_NOISESCALE_G3;
846const uint8_t bwn_bitrev_table[256] = BWN_BITREV_TABLE;
847
848#define VENDOR_LED_ACT(vendor) \
849{ \
850 .vid = PCI_VENDOR_##vendor, \
851 .led_act = { BWN_VENDOR_LED_ACT_##vendor } \
852}
853
854static const struct {
855 uint16_t vid;
856 uint8_t led_act[BWN_LED_MAX];
857} bwn_vendor_led_act[] = {
858 VENDOR_LED_ACT(COMPAQ),
859 VENDOR_LED_ACT(ASUSTEK)
860};
861
862static const uint8_t bwn_default_led_act[BWN_LED_MAX] =
863 { BWN_VENDOR_LED_ACT_DEFAULT };
864
865#undef VENDOR_LED_ACT
866
867static const struct {
868 int on_dur;
869 int off_dur;
870} bwn_led_duration[109] = {
871 [0] = { 400, 100 },
872 [2] = { 150, 75 },
873 [4] = { 90, 45 },
874 [11] = { 66, 34 },
875 [12] = { 53, 26 },
876 [18] = { 42, 21 },
877 [22] = { 35, 17 },
878 [24] = { 32, 16 },
879 [36] = { 21, 10 },
880 [48] = { 16, 8 },
881 [72] = { 11, 5 },
882 [96] = { 9, 4 },
883 [108] = { 7, 3 }
884};
885
886static const uint16_t bwn_wme_shm_offsets[] = {
887 [0] = BWN_WME_BESTEFFORT,
888 [1] = BWN_WME_BACKGROUND,
889 [2] = BWN_WME_VOICE,
890 [3] = BWN_WME_VIDEO,
891};
892
893static const struct siba_devid bwn_devs[] = {
894 SIBA_DEV(BROADCOM, 80211, 5, "Revision 5"),
895 SIBA_DEV(BROADCOM, 80211, 6, "Revision 6"),
896 SIBA_DEV(BROADCOM, 80211, 7, "Revision 7"),
897 SIBA_DEV(BROADCOM, 80211, 9, "Revision 9"),
898 SIBA_DEV(BROADCOM, 80211, 10, "Revision 10"),
899 SIBA_DEV(BROADCOM, 80211, 11, "Revision 11"),
900 SIBA_DEV(BROADCOM, 80211, 13, "Revision 13"),
901 SIBA_DEV(BROADCOM, 80211, 15, "Revision 15"),
902 SIBA_DEV(BROADCOM, 80211, 16, "Revision 16")
903};
904
905static int
906bwn_probe(device_t dev)
907{
908 int i;
909
910 for (i = 0; i < sizeof(bwn_devs) / sizeof(bwn_devs[0]); i++) {
911 if (siba_get_vendor(dev) == bwn_devs[i].sd_vendor &&
912 siba_get_device(dev) == bwn_devs[i].sd_device &&
913 siba_get_revid(dev) == bwn_devs[i].sd_rev)
914 return (BUS_PROBE_DEFAULT);
915 }
916
917 return (ENXIO);
918}
919
920static int
921bwn_attach(device_t dev)
922{
923 struct bwn_mac *mac;
924 struct bwn_softc *sc = device_get_softc(dev);
925 int error, i, msic, reg;
926
927 sc->sc_dev = dev;
928#ifdef BWN_DEBUG
929 sc->sc_debug = bwn_debug;
930#endif
931
932 if ((sc->sc_flags & BWN_FLAG_ATTACHED) == 0) {
933 error = bwn_attach_pre(sc);
934 if (error != 0)
935 return (error);
936 bwn_sprom_bugfixes(dev);
937 sc->sc_flags |= BWN_FLAG_ATTACHED;
938 }
939
940 if (!TAILQ_EMPTY(&sc->sc_maclist)) {
941 if (siba_get_pci_device(dev) != 0x4313 &&
942 siba_get_pci_device(dev) != 0x431a &&
943 siba_get_pci_device(dev) != 0x4321) {
944 device_printf(sc->sc_dev,
945 "skip 802.11 cores\n");
946 return (ENODEV);
947 }
948 }
949
950 mac = (struct bwn_mac *)malloc(sizeof(*mac), M_DEVBUF,
951 M_NOWAIT | M_ZERO);
952 if (mac == NULL)
953 return (ENOMEM);
954 mac->mac_sc = sc;
955 mac->mac_status = BWN_MAC_STATUS_UNINIT;
956 if (bwn_bfp != 0)
957 mac->mac_flags |= BWN_MAC_FLAG_BADFRAME_PREEMP;
958
959 TASK_INIT(&mac->mac_hwreset, 0, bwn_hwreset, mac);
960 TASK_INIT(&mac->mac_intrtask, 0, bwn_intrtask, mac);
961 TASK_INIT(&mac->mac_txpower, 0, bwn_txpwr, mac);
962
963 error = bwn_attach_core(mac);
964 if (error)
965 goto fail0;
966 bwn_led_attach(mac);
967
968 device_printf(sc->sc_dev, "WLAN (chipid %#x rev %u) "
969 "PHY (analog %d type %d rev %d) RADIO (manuf %#x ver %#x rev %d)\n",
970 siba_get_chipid(sc->sc_dev), siba_get_revid(sc->sc_dev),
971 mac->mac_phy.analog, mac->mac_phy.type, mac->mac_phy.rev,
972 mac->mac_phy.rf_manuf, mac->mac_phy.rf_ver,
973 mac->mac_phy.rf_rev);
974 if (mac->mac_flags & BWN_MAC_FLAG_DMA)
975 device_printf(sc->sc_dev, "DMA (%d bits)\n",
976 mac->mac_method.dma.dmatype);
977 else
978 device_printf(sc->sc_dev, "PIO\n");
979
980 /*
981 * setup PCI resources and interrupt.
982 */
983 if (pci_find_cap(dev, PCIY_EXPRESS, ®) == 0) {
984 msic = pci_msi_count(dev);
985 if (bootverbose)
986 device_printf(sc->sc_dev, "MSI count : %d\n", msic);
987 } else
988 msic = 0;
989
990 mac->mac_intr_spec = bwn_res_spec_legacy;
991 if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0) {
992 if (pci_alloc_msi(dev, &msic) == 0) {
993 device_printf(sc->sc_dev,
994 "Using %d MSI messages\n", msic);
995 mac->mac_intr_spec = bwn_res_spec_msi;
996 mac->mac_msi = 1;
997 }
998 }
999
1000 error = bus_alloc_resources(dev, mac->mac_intr_spec,
1001 mac->mac_res_irq);
1002 if (error) {
1003 device_printf(sc->sc_dev,
1004 "couldn't allocate IRQ resources (%d)\n", error);
1005 goto fail1;
1006 }
1007
1008 if (mac->mac_msi == 0)
1009 error = bus_setup_intr(dev, mac->mac_res_irq[0],
1010 INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac,
1011 &mac->mac_intrhand[0]);
1012 else {
1013 for (i = 0; i < BWN_MSI_MESSAGES; i++) {
1014 error = bus_setup_intr(dev, mac->mac_res_irq[i],
1015 INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac,
1016 &mac->mac_intrhand[i]);
1017 if (error != 0) {
1018 device_printf(sc->sc_dev,
1019 "couldn't setup interrupt (%d)\n", error);
1020 break;
1021 }
1022 }
1023 }
1024
1025 TAILQ_INSERT_TAIL(&sc->sc_maclist, mac, mac_list);
1026
1027 /*
1028 * calls attach-post routine
1029 */
1030 if ((sc->sc_flags & BWN_FLAG_ATTACHED) != 0)
1031 bwn_attach_post(sc);
1032
1033 return (0);
1034fail1:
1035 if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0)
1036 pci_release_msi(dev);
1037fail0:
1038 free(mac, M_DEVBUF);
1039 return (error);
1040}
1041
1042static int
1043bwn_is_valid_ether_addr(uint8_t *addr)
1044{
1045 char zero_addr[6] = { 0, 0, 0, 0, 0, 0 };
1046
1047 if ((addr[0] & 1) || (!bcmp(addr, zero_addr, ETHER_ADDR_LEN)))
1048 return (FALSE);
1049
1050 return (TRUE);
1051}
1052
1053static int
1054bwn_attach_post(struct bwn_softc *sc)
1055{
1056 struct ieee80211com *ic;
1057 struct ifnet *ifp = sc->sc_ifp;
1058
1059 ic = ifp->if_l2com;
1060 ic->ic_ifp = ifp;
1061 /* XXX not right but it's not used anywhere important */
1062 ic->ic_phytype = IEEE80211_T_OFDM;
1063 ic->ic_opmode = IEEE80211_M_STA;
1064 ic->ic_caps =
1065 IEEE80211_C_STA /* station mode supported */
1066 | IEEE80211_C_MONITOR /* monitor mode */
1067 | IEEE80211_C_AHDEMO /* adhoc demo mode */
1068 | IEEE80211_C_SHPREAMBLE /* short preamble supported */
1069 | IEEE80211_C_SHSLOT /* short slot time supported */
1070 | IEEE80211_C_WME /* WME/WMM supported */
1071 | IEEE80211_C_WPA /* capable of WPA1+WPA2 */
1072 | IEEE80211_C_BGSCAN /* capable of bg scanning */
1073 | IEEE80211_C_TXPMGT /* capable of txpow mgt */
1074 ;
1075
1076 ic->ic_flags_ext |= IEEE80211_FEXT_SWBMISS; /* s/w bmiss */
1077
1078 /* call MI attach routine. */
1079 ieee80211_ifattach(ic,
1080 bwn_is_valid_ether_addr(siba_sprom_get_mac_80211a(sc->sc_dev)) ?
1081 siba_sprom_get_mac_80211a(sc->sc_dev) :
1082 siba_sprom_get_mac_80211bg(sc->sc_dev));
1083
1084 ic->ic_headroom = sizeof(struct bwn_txhdr);
1085
1086 /* override default methods */
1087 ic->ic_raw_xmit = bwn_raw_xmit;
1088 ic->ic_updateslot = bwn_updateslot;
1089 ic->ic_update_promisc = bwn_update_promisc;
1090 ic->ic_wme.wme_update = bwn_wme_update;
1091
1092 ic->ic_scan_start = bwn_scan_start;
1093 ic->ic_scan_end = bwn_scan_end;
1094 ic->ic_set_channel = bwn_set_channel;
1095
1096 ic->ic_vap_create = bwn_vap_create;
1097 ic->ic_vap_delete = bwn_vap_delete;
1098
1099 ieee80211_radiotap_attach(ic,
1100 &sc->sc_tx_th.wt_ihdr, sizeof(sc->sc_tx_th),
1101 BWN_TX_RADIOTAP_PRESENT,
1102 &sc->sc_rx_th.wr_ihdr, sizeof(sc->sc_rx_th),
1103 BWN_RX_RADIOTAP_PRESENT);
1104
1105 bwn_sysctl_node(sc);
1106
1107 if (bootverbose)
1108 ieee80211_announce(ic);
1109 return (0);
1110}
1111
1112static void
1113bwn_phy_detach(struct bwn_mac *mac)
1114{
1115
1116 if (mac->mac_phy.detach != NULL)
1117 mac->mac_phy.detach(mac);
1118}
1119
1120static int
1121bwn_detach(device_t dev)
1122{
1123 struct bwn_softc *sc = device_get_softc(dev);
1124 struct bwn_mac *mac = sc->sc_curmac;
1125 struct ifnet *ifp = sc->sc_ifp;
1126 struct ieee80211com *ic = ifp->if_l2com;
1127 int i;
1128
1129 sc->sc_flags |= BWN_FLAG_INVALID;
1130
1131 if (device_is_attached(sc->sc_dev)) {
1132 bwn_stop(sc, 1);
1133 bwn_dma_free(mac);
1134 callout_drain(&sc->sc_led_blink_ch);
1135 callout_drain(&sc->sc_rfswitch_ch);
1136 callout_drain(&sc->sc_task_ch);
1137 callout_drain(&sc->sc_watchdog_ch);
1138 bwn_phy_detach(mac);
1139 if (ifp != NULL) {
1140 ieee80211_draintask(ic, &mac->mac_hwreset);
1141 ieee80211_draintask(ic, &mac->mac_txpower);
1142 ieee80211_ifdetach(ic);
1143 if_free(ifp);
1144 }
1145 }
1146 taskqueue_drain(sc->sc_tq, &mac->mac_intrtask);
1147 taskqueue_free(sc->sc_tq);
1148
1149 for (i = 0; i < BWN_MSI_MESSAGES; i++) {
1150 if (mac->mac_intrhand[i] != NULL) {
1151 bus_teardown_intr(dev, mac->mac_res_irq[i],
1152 mac->mac_intrhand[i]);
1153 mac->mac_intrhand[i] = NULL;
1154 }
1155 }
1156 bus_release_resources(dev, mac->mac_intr_spec, mac->mac_res_irq);
1157 if (mac->mac_msi != 0)
1158 pci_release_msi(dev);
1159
1160 BWN_LOCK_DESTROY(sc);
1161 return (0);
1162}
1163
1164static int
1165bwn_attach_pre(struct bwn_softc *sc)
1166{
1167 struct ifnet *ifp;
1168 int error = 0;
1169
1170 BWN_LOCK_INIT(sc);
1171 TAILQ_INIT(&sc->sc_maclist);
1172 callout_init_mtx(&sc->sc_rfswitch_ch, &sc->sc_mtx, 0);
1173 callout_init_mtx(&sc->sc_task_ch, &sc->sc_mtx, 0);
1174 callout_init_mtx(&sc->sc_watchdog_ch, &sc->sc_mtx, 0);
1175
1176 sc->sc_tq = taskqueue_create_fast("bwn_taskq", M_NOWAIT,
1177 taskqueue_thread_enqueue, &sc->sc_tq);
1178 taskqueue_start_threads(&sc->sc_tq, 1, PI_NET,
1179 "%s taskq", device_get_nameunit(sc->sc_dev));
1180
1181 ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
1182 if (ifp == NULL) {
1183 device_printf(sc->sc_dev, "can not if_alloc()\n");
1184 error = ENOSPC;
1185 goto fail;
1186 }
1187
1188 /* set these up early for if_printf use */
1189 if_initname(ifp, device_get_name(sc->sc_dev),
1190 device_get_unit(sc->sc_dev));
1191
1192 ifp->if_softc = sc;
1193 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
1194 ifp->if_init = bwn_init;
1195 ifp->if_ioctl = bwn_ioctl;
1196 ifp->if_start = bwn_start;
1197 IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
1198 ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
1199 IFQ_SET_READY(&ifp->if_snd);
1200
1201 return (0);
1202
1203fail: BWN_LOCK_DESTROY(sc);
1204 return (error);
1205}
1206
1207static void
1208bwn_sprom_bugfixes(device_t dev)
1209{
1210#define BWN_ISDEV(_vendor, _device, _subvendor, _subdevice) \
1211 ((siba_get_pci_vendor(dev) == PCI_VENDOR_##_vendor) && \
1212 (siba_get_pci_device(dev) == _device) && \
1213 (siba_get_pci_subvendor(dev) == PCI_VENDOR_##_subvendor) && \
1214 (siba_get_pci_subdevice(dev) == _subdevice))
1215
1216 if (siba_get_pci_subvendor(dev) == PCI_VENDOR_APPLE &&
1217 siba_get_pci_subdevice(dev) == 0x4e &&
1218 siba_get_pci_revid(dev) > 0x40)
1219 siba_sprom_set_bf_lo(dev,
1220 siba_sprom_get_bf_lo(dev) | BWN_BFL_PACTRL);
1221 if (siba_get_pci_subvendor(dev) == SIBA_BOARDVENDOR_DELL &&
1222 siba_get_chipid(dev) == 0x4301 && siba_get_pci_revid(dev) == 0x74)
1223 siba_sprom_set_bf_lo(dev,
1224 siba_sprom_get_bf_lo(dev) | BWN_BFL_BTCOEXIST);
1225 if (siba_get_type(dev) == SIBA_TYPE_PCI) {
1226 if (BWN_ISDEV(BROADCOM, 0x4318, ASUSTEK, 0x100f) ||
1227 BWN_ISDEV(BROADCOM, 0x4320, DELL, 0x0003) ||
1228 BWN_ISDEV(BROADCOM, 0x4320, HP, 0x12f8) ||
1229 BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0013) ||
1230 BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0014) ||
1231 BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0015) ||
1232 BWN_ISDEV(BROADCOM, 0x4320, MOTOROLA, 0x7010))
1233 siba_sprom_set_bf_lo(dev,
1234 siba_sprom_get_bf_lo(dev) & ~BWN_BFL_BTCOEXIST);
1235 }
1236#undef BWN_ISDEV
1237}
1238
1239static int
1240bwn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1241{
1242#define IS_RUNNING(ifp) \
1243 ((ifp->if_flags & IFF_UP) && (ifp->if_drv_flags & IFF_DRV_RUNNING))
1244 struct bwn_softc *sc = ifp->if_softc;
1245 struct ieee80211com *ic = ifp->if_l2com;
1246 struct ifreq *ifr = (struct ifreq *)data;
1247 int error = 0, startall;
1248
1249 switch (cmd) {
1250 case SIOCSIFFLAGS:
1251 startall = 0;
1252 if (IS_RUNNING(ifp)) {
1253 bwn_update_promisc(ifp);
1254 } else if (ifp->if_flags & IFF_UP) {
1255 if ((sc->sc_flags & BWN_FLAG_INVALID) == 0) {
1256 bwn_init(sc);
1257 startall = 1;
1258 }
1259 } else
1260 bwn_stop(sc, 1);
1261 if (startall)
1262 ieee80211_start_all(ic);
1263 break;
1264 case SIOCGIFMEDIA:
1265 error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
1266 break;
1267 case SIOCGIFADDR:
1268 error = ether_ioctl(ifp, cmd, data);
1269 break;
1270 default:
1271 error = EINVAL;
1272 break;
1273 }
1274 return (error);
1275}
1276
1277static void
1278bwn_start(struct ifnet *ifp)
1279{
1280 struct bwn_softc *sc = ifp->if_softc;
1281
1282 BWN_LOCK(sc);
1283 bwn_start_locked(ifp);
1284 BWN_UNLOCK(sc);
1285}
1286
1287static void
1288bwn_start_locked(struct ifnet *ifp)
1289{
1290 struct bwn_softc *sc = ifp->if_softc;
1291 struct bwn_mac *mac = sc->sc_curmac;
1292 struct ieee80211_frame *wh;
1293 struct ieee80211_node *ni;
1294 struct ieee80211_key *k;
1295 struct mbuf *m;
1296
1297 BWN_ASSERT_LOCKED(sc);
1298
1299 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || mac == NULL ||
1300 mac->mac_status < BWN_MAC_STATUS_STARTED)
1301 return;
1302
1303 for (;;) {
1304 IFQ_DRV_DEQUEUE(&ifp->if_snd, m); /* XXX: LOCK */
1305 if (m == NULL)
1306 break;
1307
1308 if (bwn_tx_isfull(sc, m))
1309 break;
1310 ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
1311 if (ni == NULL) {
1312 device_printf(sc->sc_dev, "unexpected NULL ni\n");
1313 m_freem(m);
1314 ifp->if_oerrors++;
1315 continue;
1316 }
1317 KASSERT(ni != NULL, ("%s:%d: fail", __func__, __LINE__));
1318 wh = mtod(m, struct ieee80211_frame *);
1319 if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
1320 k = ieee80211_crypto_encap(ni, m);
1321 if (k == NULL) {
1322 ieee80211_free_node(ni);
1323 m_freem(m);
1324 ifp->if_oerrors++;
1325 continue;
1326 }
1327 }
1328 wh = NULL; /* Catch any invalid use */
1329
1330 if (bwn_tx_start(sc, ni, m) != 0) {
1331 if (ni != NULL)
1332 ieee80211_free_node(ni);
1333 ifp->if_oerrors++;
1334 continue;
1335 }
1336
1337 sc->sc_watchdog_timer = 5;
1338 }
1339}
1340
1341static int
1342bwn_tx_isfull(struct bwn_softc *sc, struct mbuf *m)
1343{
1344 struct bwn_dma_ring *dr;
1345 struct bwn_mac *mac = sc->sc_curmac;
1346 struct bwn_pio_txqueue *tq;
1347 struct ifnet *ifp = sc->sc_ifp;
1348 int pktlen = roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1349
1350 BWN_ASSERT_LOCKED(sc);
1351
1352 if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
1353 dr = bwn_dma_select(mac, M_WME_GETAC(m));
1354 if (dr->dr_stop == 1 ||
1355 bwn_dma_freeslot(dr) < BWN_TX_SLOTS_PER_FRAME) {
1356 dr->dr_stop = 1;
1357 goto full;
1358 }
1359 } else {
1360 tq = bwn_pio_select(mac, M_WME_GETAC(m));
1361 if (tq->tq_free == 0 || pktlen > tq->tq_size ||
1362 pktlen > (tq->tq_size - tq->tq_used)) {
1363 tq->tq_stop = 1;
1364 goto full;
1365 }
1366 }
1367 return (0);
1368full:
1369 IFQ_DRV_PREPEND(&ifp->if_snd, m);
1370 ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1371 return (1);
1372}
1373
1374static int
1375bwn_tx_start(struct bwn_softc *sc, struct ieee80211_node *ni, struct mbuf *m)
1376{
1377 struct bwn_mac *mac = sc->sc_curmac;
1378 int error;
1379
1380 BWN_ASSERT_LOCKED(sc);
1381
1382 if (m->m_pkthdr.len < IEEE80211_MIN_LEN || mac == NULL) {
1383 m_freem(m);
1384 return (ENXIO);
1385 }
1386
1387 error = (mac->mac_flags & BWN_MAC_FLAG_DMA) ?
1388 bwn_dma_tx_start(mac, ni, m) : bwn_pio_tx_start(mac, ni, m);
1389 if (error) {
1390 m_freem(m);
1391 return (error);
1392 }
1393 return (0);
1394}
1395
1396static int
1397bwn_pio_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1398{
1399 struct bwn_pio_txpkt *tp;
1400 struct bwn_pio_txqueue *tq = bwn_pio_select(mac, M_WME_GETAC(m));
1401 struct bwn_softc *sc = mac->mac_sc;
1402 struct bwn_txhdr txhdr;
1403 struct mbuf *m_new;
1404 uint32_t ctl32;
1405 int error;
1406 uint16_t ctl16;
1407
1408 BWN_ASSERT_LOCKED(sc);
1409
1410 /* XXX TODO send packets after DTIM */
1411
1412 KASSERT(!TAILQ_EMPTY(&tq->tq_pktlist), ("%s: fail", __func__));
1413 tp = TAILQ_FIRST(&tq->tq_pktlist);
1414 tp->tp_ni = ni;
1415 tp->tp_m = m;
1416
1417 error = bwn_set_txhdr(mac, ni, m, &txhdr, BWN_PIO_COOKIE(tq, tp));
1418 if (error) {
1419 device_printf(sc->sc_dev, "tx fail\n");
1420 return (error);
1421 }
1422
1423 TAILQ_REMOVE(&tq->tq_pktlist, tp, tp_list);
1424 tq->tq_used += roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1425 tq->tq_free--;
1426
1427 if (siba_get_revid(sc->sc_dev) >= 8) {
1428 /*
1429 * XXX please removes m_defrag(9)
1430 */
1431 m_new = m_defrag(m, M_DONTWAIT);
1432 if (m_new == NULL) {
1433 device_printf(sc->sc_dev,
1434 "%s: can't defrag TX buffer\n",
1435 __func__);
1436 return (ENOBUFS);
1437 }
1438 if (m_new->m_next != NULL)
1439 device_printf(sc->sc_dev,
1440 "TODO: fragmented packets for PIO\n");
1441 tp->tp_m = m_new;
1442
1443 /* send HEADER */
1444 ctl32 = bwn_pio_write_multi_4(mac, tq,
1445 (BWN_PIO_READ_4(mac, tq, BWN_PIO8_TXCTL) |
1446 BWN_PIO8_TXCTL_FRAMEREADY) & ~BWN_PIO8_TXCTL_EOF,
1447 (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1448 /* send BODY */
1449 ctl32 = bwn_pio_write_multi_4(mac, tq, ctl32,
1450 mtod(m_new, const void *), m_new->m_pkthdr.len);
1451 bwn_pio_write_4(mac, tq, BWN_PIO_TXCTL,
1452 ctl32 | BWN_PIO8_TXCTL_EOF);
1453 } else {
1454 ctl16 = bwn_pio_write_multi_2(mac, tq,
1455 (bwn_pio_read_2(mac, tq, BWN_PIO_TXCTL) |
1456 BWN_PIO_TXCTL_FRAMEREADY) & ~BWN_PIO_TXCTL_EOF,
1457 (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1458 ctl16 = bwn_pio_write_mbuf_2(mac, tq, ctl16, m);
1459 BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL,
1460 ctl16 | BWN_PIO_TXCTL_EOF);
1461 }
1462
1463 return (0);
1464}
1465
1466static struct bwn_pio_txqueue *
1467bwn_pio_select(struct bwn_mac *mac, uint8_t prio)
1468{
1469
1470 if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
1471 return (&mac->mac_method.pio.wme[WME_AC_BE]);
1472
1473 switch (prio) {
1474 case 0:
1475 return (&mac->mac_method.pio.wme[WME_AC_BE]);
1476 case 1:
1477 return (&mac->mac_method.pio.wme[WME_AC_BK]);
1478 case 2:
1479 return (&mac->mac_method.pio.wme[WME_AC_VI]);
1480 case 3:
1481 return (&mac->mac_method.pio.wme[WME_AC_VO]);
1482 }
1483 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
1484 return (NULL);
1485}
1486
1487static int
1488bwn_dma_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1489{
1490#define BWN_GET_TXHDRCACHE(slot) \
1491 &(txhdr_cache[(slot / BWN_TX_SLOTS_PER_FRAME) * BWN_HDRSIZE(mac)])
1492 struct bwn_dma *dma = &mac->mac_method.dma;
1493 struct bwn_dma_ring *dr = bwn_dma_select(mac, M_WME_GETAC(m));
1494 struct bwn_dmadesc_generic *desc;
1495 struct bwn_dmadesc_meta *mt;
1496 struct bwn_softc *sc = mac->mac_sc;
1497 struct ifnet *ifp = sc->sc_ifp;
1498 uint8_t *txhdr_cache = (uint8_t *)dr->dr_txhdr_cache;
1499 int error, slot, backup[2] = { dr->dr_curslot, dr->dr_usedslot };
1500
1501 BWN_ASSERT_LOCKED(sc);
1502 KASSERT(!dr->dr_stop, ("%s:%d: fail", __func__, __LINE__));
1503
1504 /* XXX send after DTIM */
1505
1506 slot = bwn_dma_getslot(dr);
1507 dr->getdesc(dr, slot, &desc, &mt);
1508 KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_HEADER,
1509 ("%s:%d: fail", __func__, __LINE__));
1510
1511 error = bwn_set_txhdr(dr->dr_mac, ni, m,
1512 (struct bwn_txhdr *)BWN_GET_TXHDRCACHE(slot),
1513 BWN_DMA_COOKIE(dr, slot));
1514 if (error)
1515 goto fail;
1516 error = bus_dmamap_load(dr->dr_txring_dtag, mt->mt_dmap,
1517 BWN_GET_TXHDRCACHE(slot), BWN_HDRSIZE(mac), bwn_dma_ring_addr,
1518 &mt->mt_paddr, BUS_DMA_NOWAIT);
1519 if (error) {
1520 if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
1521 __func__, error);
1522 goto fail;
1523 }
1524 bus_dmamap_sync(dr->dr_txring_dtag, mt->mt_dmap,
1525 BUS_DMASYNC_PREWRITE);
1526 dr->setdesc(dr, desc, mt->mt_paddr, BWN_HDRSIZE(mac), 1, 0, 0);
1527 bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1528 BUS_DMASYNC_PREWRITE);
1529
1530 slot = bwn_dma_getslot(dr);
1531 dr->getdesc(dr, slot, &desc, &mt);
1532 KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_BODY &&
1533 mt->mt_islast == 1, ("%s:%d: fail", __func__, __LINE__));
1534 mt->mt_m = m;
1535 mt->mt_ni = ni;
1536
1537 error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap, m,
1538 bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1539 if (error && error != EFBIG) {
1540 if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
1541 __func__, error);
1542 goto fail;
1543 }
1544 if (error) { /* error == EFBIG */
1545 struct mbuf *m_new;
1546
1547 m_new = m_defrag(m, M_DONTWAIT);
1548 if (m_new == NULL) {
1549 if_printf(ifp, "%s: can't defrag TX buffer\n",
1550 __func__);
1551 error = ENOBUFS;
1552 goto fail;
1553 } else {
1554 m = m_new;
1555 }
1556
1557 mt->mt_m = m;
1558 error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap,
1559 m, bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1560 if (error) {
1561 if_printf(ifp, "%s: can't load TX buffer (2) %d\n",
1562 __func__, error);
1563 goto fail;
1564 }
1565 }
1566 bus_dmamap_sync(dma->txbuf_dtag, mt->mt_dmap, BUS_DMASYNC_PREWRITE);
1567 dr->setdesc(dr, desc, mt->mt_paddr, m->m_pkthdr.len, 0, 1, 1);
1568 bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1569 BUS_DMASYNC_PREWRITE);
1570
1571 /* XXX send after DTIM */
1572
1573 dr->start_transfer(dr, bwn_dma_nextslot(dr, slot));
1574 return (0);
1575fail:
1576 dr->dr_curslot = backup[0];
1577 dr->dr_usedslot = backup[1];
1578 return (error);
1579#undef BWN_GET_TXHDRCACHE
1580}
1581
1582static void
1583bwn_watchdog(void *arg)
1584{
1585 struct bwn_softc *sc = arg;
1586 struct ifnet *ifp = sc->sc_ifp;
1587
1588 if (sc->sc_watchdog_timer != 0 && --sc->sc_watchdog_timer == 0) {
1589 if_printf(ifp, "device timeout\n");
1590 ifp->if_oerrors++;
1591 }
1592 callout_schedule(&sc->sc_watchdog_ch, hz);
1593}
1594
1595static int
1596bwn_attach_core(struct bwn_mac *mac)
1597{
1598 struct bwn_softc *sc = mac->mac_sc;
1599 int error, have_bg = 0, have_a = 0;
1600 uint32_t high;
1601
1602 KASSERT(siba_get_revid(sc->sc_dev) >= 5,
1603 ("unsupported revision %d", siba_get_revid(sc->sc_dev)));
1604
1605 siba_powerup(sc->sc_dev, 0);
1606
1607 high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH);
1608 bwn_reset_core(mac,
1609 (high & BWN_TGSHIGH_HAVE_2GHZ) ? BWN_TGSLOW_SUPPORT_G : 0);
1610 error = bwn_phy_getinfo(mac, high);
1611 if (error)
1612 goto fail;
1613
1614 have_a = (high & BWN_TGSHIGH_HAVE_5GHZ) ? 1 : 0;
1615 have_bg = (high & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1616 if (siba_get_pci_device(sc->sc_dev) != 0x4312 &&
1617 siba_get_pci_device(sc->sc_dev) != 0x4319 &&
1618 siba_get_pci_device(sc->sc_dev) != 0x4324) {
1619 have_a = have_bg = 0;
1620 if (mac->mac_phy.type == BWN_PHYTYPE_A)
1621 have_a = 1;
1622 else if (mac->mac_phy.type == BWN_PHYTYPE_G ||
1623 mac->mac_phy.type == BWN_PHYTYPE_N ||
1624 mac->mac_phy.type == BWN_PHYTYPE_LP)
1625 have_bg = 1;
1626 else
1627 KASSERT(0 == 1, ("%s: unknown phy type (%d)", __func__,
1628 mac->mac_phy.type));
1629 }
1630 /* XXX turns off PHY A because it's not supported */
1631 if (mac->mac_phy.type != BWN_PHYTYPE_LP &&
1632 mac->mac_phy.type != BWN_PHYTYPE_N) {
1633 have_a = 0;
1634 have_bg = 1;
1635 }
1636
1637 if (mac->mac_phy.type == BWN_PHYTYPE_G) {
1638 mac->mac_phy.attach = bwn_phy_g_attach;
1639 mac->mac_phy.detach = bwn_phy_g_detach;
1640 mac->mac_phy.prepare_hw = bwn_phy_g_prepare_hw;
1641 mac->mac_phy.init_pre = bwn_phy_g_init_pre;
1642 mac->mac_phy.init = bwn_phy_g_init;
1643 mac->mac_phy.exit = bwn_phy_g_exit;
1644 mac->mac_phy.phy_read = bwn_phy_g_read;
1645 mac->mac_phy.phy_write = bwn_phy_g_write;
1646 mac->mac_phy.rf_read = bwn_phy_g_rf_read;
1647 mac->mac_phy.rf_write = bwn_phy_g_rf_write;
1648 mac->mac_phy.use_hwpctl = bwn_phy_g_hwpctl;
1649 mac->mac_phy.rf_onoff = bwn_phy_g_rf_onoff;
1650 mac->mac_phy.switch_analog = bwn_phy_switch_analog;
1651 mac->mac_phy.switch_channel = bwn_phy_g_switch_channel;
1652 mac->mac_phy.get_default_chan = bwn_phy_g_get_default_chan;
1653 mac->mac_phy.set_antenna = bwn_phy_g_set_antenna;
1654 mac->mac_phy.set_im = bwn_phy_g_im;
1655 mac->mac_phy.recalc_txpwr = bwn_phy_g_recalc_txpwr;
1656 mac->mac_phy.set_txpwr = bwn_phy_g_set_txpwr;
1657 mac->mac_phy.task_15s = bwn_phy_g_task_15s;
1658 mac->mac_phy.task_60s = bwn_phy_g_task_60s;
1659 } else if (mac->mac_phy.type == BWN_PHYTYPE_LP) {
1660 mac->mac_phy.init_pre = bwn_phy_lp_init_pre;
1661 mac->mac_phy.init = bwn_phy_lp_init;
1662 mac->mac_phy.phy_read = bwn_phy_lp_read;
1663 mac->mac_phy.phy_write = bwn_phy_lp_write;
1664 mac->mac_phy.phy_maskset = bwn_phy_lp_maskset;
1665 mac->mac_phy.rf_read = bwn_phy_lp_rf_read;
1666 mac->mac_phy.rf_write = bwn_phy_lp_rf_write;
1667 mac->mac_phy.rf_onoff = bwn_phy_lp_rf_onoff;
1668 mac->mac_phy.switch_analog = bwn_phy_lp_switch_analog;
1669 mac->mac_phy.switch_channel = bwn_phy_lp_switch_channel;
1670 mac->mac_phy.get_default_chan = bwn_phy_lp_get_default_chan;
1671 mac->mac_phy.set_antenna = bwn_phy_lp_set_antenna;
1672 mac->mac_phy.task_60s = bwn_phy_lp_task_60s;
1673 } else {
1674 device_printf(sc->sc_dev, "unsupported PHY type (%d)\n",
1675 mac->mac_phy.type);
1676 error = ENXIO;
1677 goto fail;
1678 }
1679
1680 mac->mac_phy.gmode = have_bg;
1681 if (mac->mac_phy.attach != NULL) {
1682 error = mac->mac_phy.attach(mac);
1683 if (error) {
1684 device_printf(sc->sc_dev, "failed\n");
1685 goto fail;
1686 }
1687 }
1688
1689 bwn_reset_core(mac, have_bg ? BWN_TGSLOW_SUPPORT_G : 0);
1690
1691 error = bwn_chiptest(mac);
1692 if (error)
1693 goto fail;
1694 error = bwn_setup_channels(mac, have_bg, have_a);
1695 if (error) {
1696 device_printf(sc->sc_dev, "failed to setup channels\n");
1697 goto fail;
1698 }
1699
1700 if (sc->sc_curmac == NULL)
1701 sc->sc_curmac = mac;
1702
1703 error = bwn_dma_attach(mac);
1704 if (error != 0) {
1705 device_printf(sc->sc_dev, "failed to initialize DMA\n");
1706 goto fail;
1707 }
1708
1709 mac->mac_phy.switch_analog(mac, 0);
1710
1711 siba_dev_down(sc->sc_dev, 0);
1712fail:
1713 siba_powerdown(sc->sc_dev);
1714 return (error);
1715}
1716
1717static void
1718bwn_reset_core(struct bwn_mac *mac, uint32_t flags)
1719{
1720 struct bwn_softc *sc = mac->mac_sc;
1721 uint32_t low, ctl;
1722
1723 flags |= (BWN_TGSLOW_PHYCLOCK_ENABLE | BWN_TGSLOW_PHYRESET);
1724
1725 siba_dev_up(sc->sc_dev, flags);
1726 DELAY(2000);
1727
1728 low = (siba_read_4(sc->sc_dev, SIBA_TGSLOW) | SIBA_TGSLOW_FGC) &
1729 ~BWN_TGSLOW_PHYRESET;
1730 siba_write_4(sc->sc_dev, SIBA_TGSLOW, low);
1731 siba_read_4(sc->sc_dev, SIBA_TGSLOW);
1732 DELAY(1000);
1733 siba_write_4(sc->sc_dev, SIBA_TGSLOW, low & ~SIBA_TGSLOW_FGC);
1734 siba_read_4(sc->sc_dev, SIBA_TGSLOW);
1735 DELAY(1000);
1736
1737 if (mac->mac_phy.switch_analog != NULL)
1738 mac->mac_phy.switch_analog(mac, 1);
1739
1740 ctl = BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GMODE;
1741 if (flags & BWN_TGSLOW_SUPPORT_G)
1742 ctl |= BWN_MACCTL_GMODE;
1743 BWN_WRITE_4(mac, BWN_MACCTL, ctl | BWN_MACCTL_IHR_ON);
1744}
1745
1746static int
1747bwn_phy_getinfo(struct bwn_mac *mac, int tgshigh)
1748{
1749 struct bwn_phy *phy = &mac->mac_phy;
1750 struct bwn_softc *sc = mac->mac_sc;
1751 uint32_t tmp;
1752
1753 /* PHY */
1754 tmp = BWN_READ_2(mac, BWN_PHYVER);
1755 phy->gmode = (tgshigh & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1756 phy->rf_on = 1;
1757 phy->analog = (tmp & BWN_PHYVER_ANALOG) >> 12;
1758 phy->type = (tmp & BWN_PHYVER_TYPE) >> 8;
1759 phy->rev = (tmp & BWN_PHYVER_VERSION);
1760 if ((phy->type == BWN_PHYTYPE_A && phy->rev >= 4) ||
1761 (phy->type == BWN_PHYTYPE_B && phy->rev != 2 &&
1762 phy->rev != 4 && phy->rev != 6 && phy->rev != 7) ||
1763 (phy->type == BWN_PHYTYPE_G && phy->rev > 9) ||
1764 (phy->type == BWN_PHYTYPE_N && phy->rev > 4) ||
1765 (phy->type == BWN_PHYTYPE_LP && phy->rev > 2))
1766 goto unsupphy;
1767
1768 /* RADIO */
1769 if (siba_get_chipid(sc->sc_dev) == 0x4317) {
1770 if (siba_get_chiprev(sc->sc_dev) == 0)
1771 tmp = 0x3205017f;
1772 else if (siba_get_chiprev(sc->sc_dev) == 1)
1773 tmp = 0x4205017f;
1774 else
1775 tmp = 0x5205017f;
1776 } else {
1777 BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1778 tmp = BWN_READ_2(mac, BWN_RFDATALO);
1779 BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1780 tmp |= (uint32_t)BWN_READ_2(mac, BWN_RFDATAHI) << 16;
1781 }
1782 phy->rf_rev = (tmp & 0xf0000000) >> 28;
1783 phy->rf_ver = (tmp & 0x0ffff000) >> 12;
1784 phy->rf_manuf = (tmp & 0x00000fff);
1785 if (phy->rf_manuf != 0x17f) /* 0x17f is broadcom */
1786 goto unsupradio;
1787 if ((phy->type == BWN_PHYTYPE_A && (phy->rf_ver != 0x2060 ||
1788 phy->rf_rev != 1 || phy->rf_manuf != 0x17f)) ||
1789 (phy->type == BWN_PHYTYPE_B && (phy->rf_ver & 0xfff0) != 0x2050) ||
1790 (phy->type == BWN_PHYTYPE_G && phy->rf_ver != 0x2050) ||
1791 (phy->type == BWN_PHYTYPE_N &&
1792 phy->rf_ver != 0x2055 && phy->rf_ver != 0x2056) ||
1793 (phy->type == BWN_PHYTYPE_LP &&
1794 phy->rf_ver != 0x2062 && phy->rf_ver != 0x2063))
1795 goto unsupradio;
1796
1797 return (0);
1798unsupphy:
1799 device_printf(sc->sc_dev, "unsupported PHY (type %#x, rev %#x, "
1800 "analog %#x)\n",
1801 phy->type, phy->rev, phy->analog);
1802 return (ENXIO);
1803unsupradio:
1804 device_printf(sc->sc_dev, "unsupported radio (manuf %#x, ver %#x, "
1805 "rev %#x)\n",
1806 phy->rf_manuf, phy->rf_ver, phy->rf_rev);
1807 return (ENXIO);
1808}
1809
1810static int
1811bwn_chiptest(struct bwn_mac *mac)
1812{
1813#define TESTVAL0 0x55aaaa55
1814#define TESTVAL1 0xaa5555aa
1815 struct bwn_softc *sc = mac->mac_sc;
1816 uint32_t v, backup;
1817
1818 BWN_LOCK(sc);
1819
1820 backup = bwn_shm_read_4(mac, BWN_SHARED, 0);
1821
1822 bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL0);
1823 if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL0)
1824 goto error;
1825 bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL1);
1826 if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL1)
1827 goto error;
1828
1829 bwn_shm_write_4(mac, BWN_SHARED, 0, backup);
1830
1831 if ((siba_get_revid(sc->sc_dev) >= 3) &&
1832 (siba_get_revid(sc->sc_dev) <= 10)) {
1833 BWN_WRITE_2(mac, BWN_TSF_CFP_START, 0xaaaa);
1834 BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0xccccbbbb);
1835 if (BWN_READ_2(mac, BWN_TSF_CFP_START_LOW) != 0xbbbb)
1836 goto error;
1837 if (BWN_READ_2(mac, BWN_TSF_CFP_START_HIGH) != 0xcccc)
1838 goto error;
1839 }
1840 BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0);
1841
1842 v = BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_GMODE;
1843 if (v != (BWN_MACCTL_GMODE | BWN_MACCTL_IHR_ON))
1844 goto error;
1845
1846 BWN_UNLOCK(sc);
1847 return (0);
1848error:
1849 BWN_UNLOCK(sc);
1850 device_printf(sc->sc_dev, "failed to validate the chipaccess\n");
1851 return (ENODEV);
1852}
1853
1854#define IEEE80211_CHAN_HTG (IEEE80211_CHAN_HT | IEEE80211_CHAN_G)
1855#define IEEE80211_CHAN_HTA (IEEE80211_CHAN_HT | IEEE80211_CHAN_A)
1856
1857static int
1858bwn_setup_channels(struct bwn_mac *mac, int have_bg, int have_a)
1859{
1860 struct bwn_softc *sc = mac->mac_sc;
1861 struct ifnet *ifp = sc->sc_ifp;
1862 struct ieee80211com *ic = ifp->if_l2com;
1863
1864 memset(ic->ic_channels, 0, sizeof(ic->ic_channels));
1865 ic->ic_nchans = 0;
1866
1867 if (have_bg)
1868 bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1869 &ic->ic_nchans, &bwn_chantable_bg, IEEE80211_CHAN_G);
1870 if (mac->mac_phy.type == BWN_PHYTYPE_N) {
1871 if (have_a)
1872 bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1873 &ic->ic_nchans, &bwn_chantable_n,
1874 IEEE80211_CHAN_HTA);
1875 } else {
1876 if (have_a)
1877 bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1878 &ic->ic_nchans, &bwn_chantable_a,
1879 IEEE80211_CHAN_A);
1880 }
1881
1882 mac->mac_phy.supports_2ghz = have_bg;
1883 mac->mac_phy.supports_5ghz = have_a;
1884
1885 return (ic->ic_nchans == 0 ? ENXIO : 0);
1886}
1887
1888static uint32_t
1889bwn_shm_read_4(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1890{
1891 uint32_t ret;
1892
1893 BWN_ASSERT_LOCKED(mac->mac_sc);
1894
1895 if (way == BWN_SHARED) {
1896 KASSERT((offset & 0x0001) == 0,
1897 ("%s:%d warn", __func__, __LINE__));
1898 if (offset & 0x0003) {
1899 bwn_shm_ctlword(mac, way, offset >> 2);
1900 ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1901 ret <<= 16;
1902 bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1903 ret |= BWN_READ_2(mac, BWN_SHM_DATA);
1904 goto out;
1905 }
1906 offset >>= 2;
1907 }
1908 bwn_shm_ctlword(mac, way, offset);
1909 ret = BWN_READ_4(mac, BWN_SHM_DATA);
1910out:
1911 return (ret);
1912}
1913
1914static uint16_t
1915bwn_shm_read_2(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1916{
1917 uint16_t ret;
1918
1919 BWN_ASSERT_LOCKED(mac->mac_sc);
1920
1921 if (way == BWN_SHARED) {
1922 KASSERT((offset & 0x0001) == 0,
1923 ("%s:%d warn", __func__, __LINE__));
1924 if (offset & 0x0003) {
1925 bwn_shm_ctlword(mac, way, offset >> 2);
1926 ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1927 goto out;
1928 }
1929 offset >>= 2;
1930 }
1931 bwn_shm_ctlword(mac, way, offset);
1932 ret = BWN_READ_2(mac, BWN_SHM_DATA);
1933out:
1934
1935 return (ret);
1936}
1937
1938static void
1939bwn_shm_ctlword(struct bwn_mac *mac, uint16_t way,
1940 uint16_t offset)
1941{
1942 uint32_t control;
1943
1944 control = way;
1945 control <<= 16;
1946 control |= offset;
1947 BWN_WRITE_4(mac, BWN_SHM_CONTROL, control);
1948}
1949
1950static void
1951bwn_shm_write_4(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1952 uint32_t value)
1953{
1954 BWN_ASSERT_LOCKED(mac->mac_sc);
1955
1956 if (way == BWN_SHARED) {
1957 KASSERT((offset & 0x0001) == 0,
1958 ("%s:%d warn", __func__, __LINE__));
1959 if (offset & 0x0003) {
1960 bwn_shm_ctlword(mac, way, offset >> 2);
1961 BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED,
1962 (value >> 16) & 0xffff);
1963 bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1964 BWN_WRITE_2(mac, BWN_SHM_DATA, value & 0xffff);
1965 return;
1966 }
1967 offset >>= 2;
1968 }
1969 bwn_shm_ctlword(mac, way, offset);
1970 BWN_WRITE_4(mac, BWN_SHM_DATA, value);
1971}
1972
1973static void
1974bwn_shm_write_2(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1975 uint16_t value)
1976{
1977 BWN_ASSERT_LOCKED(mac->mac_sc);
1978
1979 if (way == BWN_SHARED) {
1980 KASSERT((offset & 0x0001) == 0,
1981 ("%s:%d warn", __func__, __LINE__));
1982 if (offset & 0x0003) {
1983 bwn_shm_ctlword(mac, way, offset >> 2);
1984 BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED, value);
1985 return;
1986 }
1987 offset >>= 2;
1988 }
1989 bwn_shm_ctlword(mac, way, offset);
1990 BWN_WRITE_2(mac, BWN_SHM_DATA, value);
1991}
1992
1993static void
1994bwn_addchan(struct ieee80211_channel *c, int freq, int flags, int ieee,
1995 int txpow)
1996{
1997
1998 c->ic_freq = freq;
1999 c->ic_flags = flags;
2000 c->ic_ieee = ieee;
2001 c->ic_minpower = 0;
2002 c->ic_maxpower = 2 * txpow;
2003 c->ic_maxregpower = txpow;
2004}
2005
2006static void
2007bwn_addchannels(struct ieee80211_channel chans[], int maxchans, int *nchans,
2008 const struct bwn_channelinfo *ci, int flags)
2009{
2010 struct ieee80211_channel *c;
2011 int i;
2012
2013 c = &chans[*nchans];
2014
2015 for (i = 0; i < ci->nchannels; i++) {
2016 const struct bwn_channel *hc;
2017
2018 hc = &ci->channels[i];
2019 if (*nchans >= maxchans)
2020 break;
2021 bwn_addchan(c, hc->freq, flags, hc->ieee, hc->maxTxPow);
2022 c++, (*nchans)++;
2023 if (flags == IEEE80211_CHAN_G || flags == IEEE80211_CHAN_HTG) {
2024 /* g channel have a separate b-only entry */
2025 if (*nchans >= maxchans)
2026 break;
2027 c[0] = c[-1];
2028 c[-1].ic_flags = IEEE80211_CHAN_B;
2029 c++, (*nchans)++;
2030 }
2031 if (flags == IEEE80211_CHAN_HTG) {
2032 /* HT g channel have a separate g-only entry */
2033 if (*nchans >= maxchans)
2034 break;
2035 c[-1].ic_flags = IEEE80211_CHAN_G;
2036 c[0] = c[-1];
2037 c[0].ic_flags &= ~IEEE80211_CHAN_HT;
2038 c[0].ic_flags |= IEEE80211_CHAN_HT20; /* HT20 */
2039 c++, (*nchans)++;
2040 }
2041 if (flags == IEEE80211_CHAN_HTA) {
2042 /* HT a channel have a separate a-only entry */
2043 if (*nchans >= maxchans)
2044 break;
2045 c[-1].ic_flags = IEEE80211_CHAN_A;
2046 c[0] = c[-1];
2047 c[0].ic_flags &= ~IEEE80211_CHAN_HT;
2048 c[0].ic_flags |= IEEE80211_CHAN_HT20; /* HT20 */
2049 c++, (*nchans)++;
2050 }
2051 }
2052}
2053
2054static int
2055bwn_phy_g_attach(struct bwn_mac *mac)
2056{
2057 struct bwn_softc *sc = mac->mac_sc;
2058 struct bwn_phy *phy = &mac->mac_phy;
2059 struct bwn_phy_g *pg = &phy->phy_g;
2060 unsigned int i;
2061 int16_t pab0, pab1, pab2;
2062 static int8_t bwn_phy_g_tssi2dbm_table[] = BWN_PHY_G_TSSI2DBM_TABLE;
2063 int8_t bg;
2064
2065 bg = (int8_t)siba_sprom_get_tssi_bg(sc->sc_dev);
2066 pab0 = (int16_t)siba_sprom_get_pa0b0(sc->sc_dev);
2067 pab1 = (int16_t)siba_sprom_get_pa0b1(sc->sc_dev);
2068 pab2 = (int16_t)siba_sprom_get_pa0b2(sc->sc_dev);
2069
2070 if ((siba_get_chipid(sc->sc_dev) == 0x4301) && (phy->rf_ver != 0x2050))
2071 device_printf(sc->sc_dev, "not supported anymore\n");
2072
2073 pg->pg_flags = 0;
2074 if (pab0 == 0 || pab1 == 0 || pab2 == 0 || pab0 == -1 || pab1 == -1 ||
2075 pab2 == -1) {
2076 pg->pg_idletssi = 52;
2077 pg->pg_tssi2dbm = bwn_phy_g_tssi2dbm_table;
2078 return (0);
2079 }
2080
2081 pg->pg_idletssi = (bg == 0 || bg == -1) ? 62 : bg;
2082 pg->pg_tssi2dbm = (uint8_t *)malloc(64, M_DEVBUF, M_NOWAIT | M_ZERO);
2083 if (pg->pg_tssi2dbm == NULL) {
2084 device_printf(sc->sc_dev, "failed to allocate buffer\n");
2085 return (ENOMEM);
2086 }
2087 for (i = 0; i < 64; i++) {
2088 int32_t m1, m2, f, q, delta;
2089 int8_t j = 0;
2090
2091 m1 = BWN_TSSI2DBM(16 * pab0 + i * pab1, 32);
2092 m2 = MAX(BWN_TSSI2DBM(32768 + i * pab2, 256), 1);
2093 f = 256;
2094
2095 do {
2096 if (j > 15) {
2097 device_printf(sc->sc_dev,
2098 "failed to generate tssi2dBm\n");
2099 free(pg->pg_tssi2dbm, M_DEVBUF);
2100 return (ENOMEM);
2101 }
2102 q = BWN_TSSI2DBM(f * 4096 - BWN_TSSI2DBM(m2 * f, 16) *
2103 f, 2048);
2104 delta = abs(q - f);
2105 f = q;
2106 j++;
2107 } while (delta >= 2);
2108
2109 pg->pg_tssi2dbm[i] = MIN(MAX(BWN_TSSI2DBM(m1 * f, 8192), -127),
2110 128);
2111 }
2112
2113 pg->pg_flags |= BWN_PHY_G_FLAG_TSSITABLE_ALLOC;
2114 return (0);
2115}
2116
2117static void
2118bwn_phy_g_detach(struct bwn_mac *mac)
2119{
2120 struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
2121
2122 if (pg->pg_flags & BWN_PHY_G_FLAG_TSSITABLE_ALLOC) {
2123 free(pg->pg_tssi2dbm, M_DEVBUF);
2124 pg->pg_tssi2dbm = NULL;
2125 }
2126 pg->pg_flags = 0;
2127}
2128
2129static void
2130bwn_phy_g_init_pre(struct bwn_mac *mac)
2131{
2132 struct bwn_phy *phy = &mac->mac_phy;
2133 struct bwn_phy_g *pg = &phy->phy_g;
2134 void *tssi2dbm;
2135 int idletssi;
2136 unsigned int i;
2137
2138 tssi2dbm = pg->pg_tssi2dbm;
2139 idletssi = pg->pg_idletssi;
2140
2141 memset(pg, 0, sizeof(*pg));
2142
2143 pg->pg_tssi2dbm = tssi2dbm;
2144 pg->pg_idletssi = idletssi;
2145
2146 memset(pg->pg_minlowsig, 0xff, sizeof(pg->pg_minlowsig));
2147
2148 for (i = 0; i < N(pg->pg_nrssi); i++)
2149 pg->pg_nrssi[i] = -1000;
2150 for (i = 0; i < N(pg->pg_nrssi_lt); i++)
2151 pg->pg_nrssi_lt[i] = i;
2152 pg->pg_lofcal = 0xffff;
2153 pg->pg_initval = 0xffff;
2154 pg->pg_immode = BWN_IMMODE_NONE;
2155 pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_UNKNOWN;
2156 pg->pg_avgtssi = 0xff;
2157
2158 pg->pg_loctl.tx_bias = 0xff;
2159 TAILQ_INIT(&pg->pg_loctl.calib_list);
2160}
2161
2162static int
2163bwn_phy_g_prepare_hw(struct bwn_mac *mac)
2164{
2165 struct bwn_phy *phy = &mac->mac_phy;
2166 struct bwn_phy_g *pg = &phy->phy_g;
2167 struct bwn_softc *sc = mac->mac_sc;
2168 struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2169 static const struct bwn_rfatt rfatt0[] = {
2170 { 3, 0 }, { 1, 0 }, { 5, 0 }, { 7, 0 }, { 9, 0 }, { 2, 0 },
2171 { 0, 0 }, { 4, 0 }, { 6, 0 }, { 8, 0 }, { 1, 1 }, { 2, 1 },
2172 { 3, 1 }, { 4, 1 }
2173 };
2174 static const struct bwn_rfatt rfatt1[] = {
2175 { 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 10, 1 }, { 12, 1 },
2176 { 14, 1 }
2177 };
2178 static const struct bwn_rfatt rfatt2[] = {
2179 { 0, 1 }, { 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 9, 1 },
2180 { 9, 1 }
2181 };
2182 static const struct bwn_bbatt bbatt_0[] = {
2183 { 0 }, { 1 }, { 2 }, { 3 }, { 4 }, { 5 }, { 6 }, { 7 }, { 8 }
2184 };
2185
2186 KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
2187
2188 if (phy->rf_ver == 0x2050 && phy->rf_rev < 6)
2189 pg->pg_bbatt.att = 0;
2190 else
2191 pg->pg_bbatt.att = 2;
2192
2193 /* prepare Radio Attenuation */
2194 pg->pg_rfatt.padmix = 0;
2195
2196 if (siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM &&
2197 siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BCM4309G) {
2198 if (siba_get_pci_revid(sc->sc_dev) < 0x43) {
2199 pg->pg_rfatt.att = 2;
2200 goto done;
2201 } else if (siba_get_pci_revid(sc->sc_dev) < 0x51) {
2202 pg->pg_rfatt.att = 3;
2203 goto done;
2204 }
2205 }
2206
2207 if (phy->type == BWN_PHYTYPE_A) {
2208 pg->pg_rfatt.att = 0x60;
2209 goto done;
2210 }
2211
2212 switch (phy->rf_ver) {
2213 case 0x2050:
2214 switch (phy->rf_rev) {
2215 case 0:
2216 pg->pg_rfatt.att = 5;
2217 goto done;
2218 case 1:
2219 if (phy->type == BWN_PHYTYPE_G) {
2220 if (siba_get_pci_subvendor(sc->sc_dev) ==
2221 SIBA_BOARDVENDOR_BCM &&
2222 siba_get_pci_subdevice(sc->sc_dev) ==
2223 SIBA_BOARD_BCM4309G &&
2224 siba_get_pci_revid(sc->sc_dev) >= 30)
2225 pg->pg_rfatt.att = 3;
2226 else if (siba_get_pci_subvendor(sc->sc_dev) ==
2227 SIBA_BOARDVENDOR_BCM &&
2228 siba_get_pci_subdevice(sc->sc_dev) ==
2229 SIBA_BOARD_BU4306)
2230 pg->pg_rfatt.att = 3;
2231 else
2232 pg->pg_rfatt.att = 1;
2233 } else {
2234 if (siba_get_pci_subvendor(sc->sc_dev) ==
2235 SIBA_BOARDVENDOR_BCM &&
2236 siba_get_pci_subdevice(sc->sc_dev) ==
2237 SIBA_BOARD_BCM4309G &&
2238 siba_get_pci_revid(sc->sc_dev) >= 30)
2239 pg->pg_rfatt.att = 7;
2240 else
2241 pg->pg_rfatt.att = 6;
2242 }
2243 goto done;
2244 case 2:
2245 if (phy->type == BWN_PHYTYPE_G) {
2246 if (siba_get_pci_subvendor(sc->sc_dev) ==
2247 SIBA_BOARDVENDOR_BCM &&
2248 siba_get_pci_subdevice(sc->sc_dev) ==
2249 SIBA_BOARD_BCM4309G &&
2250 siba_get_pci_revid(sc->sc_dev) >= 30)
2251 pg->pg_rfatt.att = 3;
2252 else if (siba_get_pci_subvendor(sc->sc_dev) ==
2253 SIBA_BOARDVENDOR_BCM &&
2254 siba_get_pci_subdevice(sc->sc_dev) ==
2255 SIBA_BOARD_BU4306)
2256 pg->pg_rfatt.att = 5;
2257 else if (siba_get_chipid(sc->sc_dev) == 0x4320)
2258 pg->pg_rfatt.att = 4;
2259 else
2260 pg->pg_rfatt.att = 3;
2261 } else
2262 pg->pg_rfatt.att = 6;
2263 goto done;
2264 case 3:
2265 pg->pg_rfatt.att = 5;
2266 goto done;
2267 case 4:
2268 case 5:
2269 pg->pg_rfatt.att = 1;
2270 goto done;
2271 case 6:
2272 case 7:
2273 pg->pg_rfatt.att = 5;
2274 goto done;
2275 case 8:
2276 pg->pg_rfatt.att = 0xa;
2277 pg->pg_rfatt.padmix = 1;
2278 goto done;
2279 case 9:
2280 default:
2281 pg->pg_rfatt.att = 5;
2282 goto done;
2283 }
2284 break;
2285 case 0x2053:
2286 switch (phy->rf_rev) {
2287 case 1:
2288 pg->pg_rfatt.att = 6;
2289 goto done;
2290 }
2291 break;
2292 }
2293 pg->pg_rfatt.att = 5;
2294done:
2295 pg->pg_txctl = (bwn_phy_g_txctl(mac) << 4);
2296
2297 if (!bwn_has_hwpctl(mac)) {
2298 lo->rfatt.array = rfatt0;
2299 lo->rfatt.len = N(rfatt0);
2300 lo->rfatt.min = 0;
2301 lo->rfatt.max = 9;
2302 goto genbbatt;
2303 }
2304 if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
2305 lo->rfatt.array = rfatt1;
2306 lo->rfatt.len = N(rfatt1);
2307 lo->rfatt.min = 0;
2308 lo->rfatt.max = 14;
2309 goto genbbatt;
2310 }
2311 lo->rfatt.array = rfatt2;
2312 lo->rfatt.len = N(rfatt2);
2313 lo->rfatt.min = 0;
2314 lo->rfatt.max = 9;
2315genbbatt:
2316 lo->bbatt.array = bbatt_0;
2317 lo->bbatt.len = N(bbatt_0);
2318 lo->bbatt.min = 0;
2319 lo->bbatt.max = 8;
2320
2321 BWN_READ_4(mac, BWN_MACCTL);
2322 if (phy->rev == 1) {
2323 phy->gmode = 0;
2324 bwn_reset_core(mac, 0);
2325 bwn_phy_g_init_sub(mac);
2326 phy->gmode = 1;
2327 bwn_reset_core(mac, BWN_TGSLOW_SUPPORT_G);
2328 }
2329 return (0);
2330}
2331
2332static uint16_t
2333bwn_phy_g_txctl(struct bwn_mac *mac)
2334{
2335 struct bwn_phy *phy = &mac->mac_phy;
2336
2337 if (phy->rf_ver != 0x2050)
2338 return (0);
2339 if (phy->rf_rev == 1)
2340 return (BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX);
2341 if (phy->rf_rev < 6)
2342 return (BWN_TXCTL_PA2DB);
2343 if (phy->rf_rev == 8)
2344 return (BWN_TXCTL_TXMIX);
2345 return (0);
2346}
2347
2348static int
2349bwn_phy_g_init(struct bwn_mac *mac)
2350{
2351
2352 bwn_phy_g_init_sub(mac);
2353 return (0);
2354}
2355
2356static void
2357bwn_phy_g_exit(struct bwn_mac *mac)
2358{
2359 struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
2360 struct bwn_lo_calib *cal, *tmp;
2361
2362 if (lo == NULL)
2363 return;
2364 TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
2365 TAILQ_REMOVE(&lo->calib_list, cal, list);
2366 free(cal, M_DEVBUF);
2367 }
2368}
2369
2370static uint16_t
2371bwn_phy_g_read(struct bwn_mac *mac, uint16_t reg)
2372{
2373
2374 BWN_WRITE_2(mac, BWN_PHYCTL, reg);
2375 return (BWN_READ_2(mac, BWN_PHYDATA));
2376}
2377
2378static void
2379bwn_phy_g_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
2380{
2381
2382 BWN_WRITE_2(mac, BWN_PHYCTL, reg);
2383 BWN_WRITE_2(mac, BWN_PHYDATA, value);
2384}
2385
2386static uint16_t
2387bwn_phy_g_rf_read(struct bwn_mac *mac, uint16_t reg)
2388{
2389
2390 KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
2391 BWN_WRITE_2(mac, BWN_RFCTL, reg | 0x80);
2392 return (BWN_READ_2(mac, BWN_RFDATALO));
2393}
2394
2395static void
2396bwn_phy_g_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
2397{
2398
2399 KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
2400 BWN_WRITE_2(mac, BWN_RFCTL, reg);
2401 BWN_WRITE_2(mac, BWN_RFDATALO, value);
2402}
2403
2404static int
2405bwn_phy_g_hwpctl(struct bwn_mac *mac)
2406{
2407
2408 return (mac->mac_phy.rev >= 6);
2409}
2410
2411static void
2412bwn_phy_g_rf_onoff(struct bwn_mac *mac, int on)
2413{
2414 struct bwn_phy *phy = &mac->mac_phy;
2415 struct bwn_phy_g *pg = &phy->phy_g;
2416 unsigned int channel;
2417 uint16_t rfover, rfoverval;
2418
2419 if (on) {
2420 if (phy->rf_on)
2421 return;
2422
2423 BWN_PHY_WRITE(mac, 0x15, 0x8000);
2424 BWN_PHY_WRITE(mac, 0x15, 0xcc00);
2425 BWN_PHY_WRITE(mac, 0x15, (phy->gmode ? 0xc0 : 0x0));
2426 if (pg->pg_flags & BWN_PHY_G_FLAG_RADIOCTX_VALID) {
2427 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
2428 pg->pg_radioctx_over);
2429 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
2430 pg->pg_radioctx_overval);
2431 pg->pg_flags &= ~BWN_PHY_G_FLAG_RADIOCTX_VALID;
2432 }
2433 channel = phy->chan;
2434 bwn_phy_g_switch_chan(mac, 6, 1);
2435 bwn_phy_g_switch_chan(mac, channel, 0);
2436 return;
2437 }
2438
2439 rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
2440 rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
2441 pg->pg_radioctx_over = rfover;
2442 pg->pg_radioctx_overval = rfoverval;
2443 pg->pg_flags |= BWN_PHY_G_FLAG_RADIOCTX_VALID;
2444 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover | 0x008c);
2445 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval & 0xff73);
2446}
2447
2448static int
2449bwn_phy_g_switch_channel(struct bwn_mac *mac, uint32_t newchan)
2450{
2451
2452 if ((newchan < 1) || (newchan > 14))
2453 return (EINVAL);
2454 bwn_phy_g_switch_chan(mac, newchan, 0);
2455
2456 return (0);
2457}
2458
2459static uint32_t
2460bwn_phy_g_get_default_chan(struct bwn_mac *mac)
2461{
2462
2463 return (1);
2464}
2465
2466static void
2467bwn_phy_g_set_antenna(struct bwn_mac *mac, int antenna)
2468{
2469 struct bwn_phy *phy = &mac->mac_phy;
2470 uint64_t hf;
2471 int autodiv = 0;
2472 uint16_t tmp;
2473
2474 if (antenna == BWN_ANTAUTO0 || antenna == BWN_ANTAUTO1)
2475 autodiv = 1;
2476
2477 hf = bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER;
2478 bwn_hf_write(mac, hf);
2479
2480 BWN_PHY_WRITE(mac, BWN_PHY_BBANDCFG,
2481 (BWN_PHY_READ(mac, BWN_PHY_BBANDCFG) & ~BWN_PHY_BBANDCFG_RXANT) |
2482 ((autodiv ? BWN_ANTAUTO1 : antenna)
2483 << BWN_PHY_BBANDCFG_RXANT_SHIFT));
2484
2485 if (autodiv) {
2486 tmp = BWN_PHY_READ(mac, BWN_PHY_ANTDWELL);
2487 if (antenna == BWN_ANTAUTO1)
2488 tmp &= ~BWN_PHY_ANTDWELL_AUTODIV1;
2489 else
2490 tmp |= BWN_PHY_ANTDWELL_AUTODIV1;
2491 BWN_PHY_WRITE(mac, BWN_PHY_ANTDWELL, tmp);
2492 }
2493 tmp = BWN_PHY_READ(mac, BWN_PHY_ANTWRSETT);
2494 if (autodiv)
2495 tmp |= BWN_PHY_ANTWRSETT_ARXDIV;
2496 else
2497 tmp &= ~BWN_PHY_ANTWRSETT_ARXDIV;
2498 BWN_PHY_WRITE(mac, BWN_PHY_ANTWRSETT, tmp);
2499 if (phy->rev >= 2) {
2500 BWN_PHY_WRITE(mac, BWN_PHY_OFDM61,
2501 BWN_PHY_READ(mac, BWN_PHY_OFDM61) | BWN_PHY_OFDM61_10);
2502 BWN_PHY_WRITE(mac, BWN_PHY_DIVSRCHGAINBACK,
2503 (BWN_PHY_READ(mac, BWN_PHY_DIVSRCHGAINBACK) & 0xff00) |
2504 0x15);
2505 if (phy->rev == 2)
2506 BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED, 8);
2507 else
2508 BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED,
2509 (BWN_PHY_READ(mac, BWN_PHY_ADIVRELATED) & 0xff00) |
2510 8);
2511 }
2512 if (phy->rev >= 6)
2513 BWN_PHY_WRITE(mac, BWN_PHY_OFDM9B, 0xdc);
2514
2515 hf |= BWN_HF_UCODE_ANTDIV_HELPER;
2516 bwn_hf_write(mac, hf);
2517}
2518
2519static int
2520bwn_phy_g_im(struct bwn_mac *mac, int mode)
2521{
2522 struct bwn_phy *phy = &mac->mac_phy;
2523 struct bwn_phy_g *pg = &phy->phy_g;
2524
2525 KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2526 KASSERT(mode == BWN_IMMODE_NONE, ("%s: fail", __func__));
2527
2528 if (phy->rev == 0 || !phy->gmode)
2529 return (ENODEV);
2530
2531 pg->pg_aci_wlan_automatic = 0;
2532 return (0);
2533}
2534
2535static int
2536bwn_phy_g_recalc_txpwr(struct bwn_mac *mac, int ignore_tssi)
2537{
2538 struct bwn_phy *phy = &mac->mac_phy;
2539 struct bwn_phy_g *pg = &phy->phy_g;
2540 struct bwn_softc *sc = mac->mac_sc;
2541 unsigned int tssi;
2542 int cck, ofdm;
2543 int power;
2544 int rfatt, bbatt;
2545 unsigned int max;
2546
2547 KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2548
2549 cck = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_CCK);
2550 ofdm = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_OFDM_G);
2551 if (cck < 0 && ofdm < 0) {
2552 if (ignore_tssi == 0)
2553 return (BWN_TXPWR_RES_DONE);
2554 cck = 0;
2555 ofdm = 0;
2556 }
2557 tssi = (cck < 0) ? ofdm : ((ofdm < 0) ? cck : (cck + ofdm) / 2);
2558 if (pg->pg_avgtssi != 0xff)
2559 tssi = (tssi + pg->pg_avgtssi) / 2;
2560 pg->pg_avgtssi = tssi;
2561 KASSERT(tssi < BWN_TSSI_MAX, ("%s:%d: fail", __func__, __LINE__));
2562
2563 max = siba_sprom_get_maxpwr_bg(sc->sc_dev);
2564 if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
2565 max -= 3;
2566 if (max >= 120) {
2567 device_printf(sc->sc_dev, "invalid max TX-power value\n");
2568 max = 80;
2569 siba_sprom_set_maxpwr_bg(sc->sc_dev, max);
2570 }
2571
2572 power = MIN(MAX((phy->txpower < 0) ? 0 : (phy->txpower << 2), 0), max) -
2573 (pg->pg_tssi2dbm[MIN(MAX(pg->pg_idletssi - pg->pg_curtssi +
2574 tssi, 0x00), 0x3f)]);
2575 if (power == 0)
2576 return (BWN_TXPWR_RES_DONE);
2577
2578 rfatt = -((power + 7) / 8);
2579 bbatt = (-(power / 2)) - (4 * rfatt);
2580 if ((rfatt == 0) && (bbatt == 0))
2581 return (BWN_TXPWR_RES_DONE);
2582 pg->pg_bbatt_delta = bbatt;
2583 pg->pg_rfatt_delta = rfatt;
2584 return (BWN_TXPWR_RES_NEED_ADJUST);
2585}
2586
2587static void
2588bwn_phy_g_set_txpwr(struct bwn_mac *mac)
2589{
2590 struct bwn_phy *phy = &mac->mac_phy;
2591 struct bwn_phy_g *pg = &phy->phy_g;
2592 struct bwn_softc *sc = mac->mac_sc;
2593 int rfatt, bbatt;
2594 uint8_t txctl;
2595
2596 bwn_mac_suspend(mac);
2597
2598 BWN_ASSERT_LOCKED(sc);
2599
2600 bbatt = pg->pg_bbatt.att;
2601 bbatt += pg->pg_bbatt_delta;
2602 rfatt = pg->pg_rfatt.att;
2603 rfatt += pg->pg_rfatt_delta;
2604
2605 bwn_phy_g_setatt(mac, &bbatt, &rfatt);
2606 txctl = pg->pg_txctl;
2607 if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 2)) {
2608 if (rfatt <= 1) {
2609 if (txctl == 0) {
2610 txctl = BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX;
2611 rfatt += 2;
2612 bbatt += 2;
2613 } else if (siba_sprom_get_bf_lo(sc->sc_dev) &
2614 BWN_BFL_PACTRL) {
2615 bbatt += 4 * (rfatt - 2);
2616 rfatt = 2;
2617 }
2618 } else if (rfatt > 4 && txctl) {
2619 txctl = 0;
2620 if (bbatt < 3) {
2621 rfatt -= 3;
2622 bbatt += 2;
2623 } else {
2624 rfatt -= 2;
2625 bbatt -= 2;
2626 }
2627 }
2628 }
2629 pg->pg_txctl = txctl;
2630 bwn_phy_g_setatt(mac, &bbatt, &rfatt);
2631 pg->pg_rfatt.att = rfatt;
2632 pg->pg_bbatt.att = bbatt;
2633
2634 DPRINTF(sc, BWN_DEBUG_TXPOW, "%s: adjust TX power\n", __func__);
2635
2636 bwn_phy_lock(mac);
2637 bwn_rf_lock(mac);
2638 bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
2639 pg->pg_txctl);
2640 bwn_rf_unlock(mac);
2641 bwn_phy_unlock(mac);
2642
2643 bwn_mac_enable(mac);
2644}
2645
2646static void
2647bwn_phy_g_task_15s(struct bwn_mac *mac)
2648{
2649 struct bwn_phy *phy = &mac->mac_phy;
2650 struct bwn_phy_g *pg = &phy->phy_g;
2651 struct bwn_softc *sc = mac->mac_sc;
2652 struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2653 unsigned long expire, now;
2654 struct bwn_lo_calib *cal, *tmp;
2655 uint8_t expired = 0;
2656
2657 bwn_mac_suspend(mac);
2658
2659 if (lo == NULL)
2660 goto fail;
2661
2662 BWN_GETTIME(now);
2663 if (bwn_has_hwpctl(mac)) {
2664 expire = now - BWN_LO_PWRVEC_EXPIRE;
2665 if (time_before(lo->pwr_vec_read_time, expire)) {
2666 bwn_lo_get_powervector(mac);
2667 bwn_phy_g_dc_lookup_init(mac, 0);
2668 }
2669 goto fail;
2670 }
2671
2672 expire = now - BWN_LO_CALIB_EXPIRE;
2673 TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
2674 if (!time_before(cal->calib_time, expire))
2675 continue;
2676 if (BWN_BBATTCMP(&cal->bbatt, &pg->pg_bbatt) &&
2677 BWN_RFATTCMP(&cal->rfatt, &pg->pg_rfatt)) {
2678 KASSERT(!expired, ("%s:%d: fail", __func__, __LINE__));
2679 expired = 1;
2680 }
2681
2682 DPRINTF(sc, BWN_DEBUG_LO, "expired BB %u RF %u %u I %d Q %d\n",
2683 cal->bbatt.att, cal->rfatt.att, cal->rfatt.padmix,
2684 cal->ctl.i, cal->ctl.q);
2685
2686 TAILQ_REMOVE(&lo->calib_list, cal, list);
2687 free(cal, M_DEVBUF);
2688 }
2689 if (expired || TAILQ_EMPTY(&lo->calib_list)) {
2690 cal = bwn_lo_calibset(mac, &pg->pg_bbatt,
2691 &pg->pg_rfatt);
2692 if (cal == NULL) {
2693 device_printf(sc->sc_dev,
2694 "failed to recalibrate LO\n");
2695 goto fail;
2696 }
2697 TAILQ_INSERT_TAIL(&lo->calib_list, cal, list);
2698 bwn_lo_write(mac, &cal->ctl);
2699 }
2700
2701fail:
2702 bwn_mac_enable(mac);
2703}
2704
2705static void
2706bwn_phy_g_task_60s(struct bwn_mac *mac)
2707{
2708 struct bwn_phy *phy = &mac->mac_phy;
2709 struct bwn_softc *sc = mac->mac_sc;
2710 uint8_t old = phy->chan;
2711
2712 if (!(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI))
2713 return;
2714
2715 bwn_mac_suspend(mac);
2716 bwn_nrssi_slope_11g(mac);
2717 if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 8)) {
2718 bwn_switch_channel(mac, (old >= 8) ? 1 : 13);
2719 bwn_switch_channel(mac, old);
2720 }
2721 bwn_mac_enable(mac);
2722}
2723
2724static void
2725bwn_phy_switch_analog(struct bwn_mac *mac, int on)
2726{
2727
2728 BWN_WRITE_2(mac, BWN_PHY0, on ? 0 : 0xf4);
2729}
2730
2731static int
2732bwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
2733 const struct ieee80211_bpf_params *params)
2734{
2735 struct ieee80211com *ic = ni->ni_ic;
2736 struct ifnet *ifp = ic->ic_ifp;
2737 struct bwn_softc *sc = ifp->if_softc;
2738 struct bwn_mac *mac = sc->sc_curmac;
2739
2740 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
2741 mac->mac_status < BWN_MAC_STATUS_STARTED) {
2742 ieee80211_free_node(ni);
2743 m_freem(m);
2744 return (ENETDOWN);
2745 }
2746
2747 BWN_LOCK(sc);
2748 if (bwn_tx_isfull(sc, m)) {
2749 ieee80211_free_node(ni);
2750 m_freem(m);
2751 ifp->if_oerrors++;
2752 BWN_UNLOCK(sc);
2753 return (ENOBUFS);
2754 }
2755
2756 if (bwn_tx_start(sc, ni, m) != 0) {
2757 if (ni != NULL)
2758 ieee80211_free_node(ni);
2759 ifp->if_oerrors++;
2760 }
2761 sc->sc_watchdog_timer = 5;
2762 BWN_UNLOCK(sc);
2763 return (0);
2764}
2765
2766/*
2767 * Callback from the 802.11 layer to update the slot time
2768 * based on the current setting. We use it to notify the
2769 * firmware of ERP changes and the f/w takes care of things
2770 * like slot time and preamble.
2771 */
2772static void
2773bwn_updateslot(struct ifnet *ifp)
2774{
2775 struct bwn_softc *sc = ifp->if_softc;
2776 struct ieee80211com *ic = ifp->if_l2com;
2777 struct bwn_mac *mac;
2778
2779 BWN_LOCK(sc);
2780 if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
2781 mac = (struct bwn_mac *)sc->sc_curmac;
2782 bwn_set_slot_time(mac,
2783 (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20);
2784 }
2785 BWN_UNLOCK(sc);
2786}
2787
2788/*
2789 * Callback from the 802.11 layer after a promiscuous mode change.
2790 * Note this interface does not check the operating mode as this
2791 * is an internal callback and we are expected to honor the current
2792 * state (e.g. this is used for setting the interface in promiscuous
2793 * mode when operating in hostap mode to do ACS).
2794 */
2795static void
2796bwn_update_promisc(struct ifnet *ifp)
2797{
2798 struct bwn_softc *sc = ifp->if_softc;
2799 struct bwn_mac *mac = sc->sc_curmac;
2800
2801 BWN_LOCK(sc);
2802 mac = sc->sc_curmac;
2803 if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2804 if (ifp->if_flags & IFF_PROMISC)
2805 sc->sc_filters |= BWN_MACCTL_PROMISC;
2806 else
2807 sc->sc_filters &= ~BWN_MACCTL_PROMISC;
2808 bwn_set_opmode(mac);
2809 }
2810 BWN_UNLOCK(sc);
2811}
2812
2813/*
2814 * Callback from the 802.11 layer to update WME parameters.
2815 */
2816static int
2817bwn_wme_update(struct ieee80211com *ic)
2818{
2819 struct bwn_softc *sc = ic->ic_ifp->if_softc;
2820 struct bwn_mac *mac = sc->sc_curmac;
2821 struct wmeParams *wmep;
2822 int i;
2823
2824 BWN_LOCK(sc);
2825 mac = sc->sc_curmac;
2826 if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2827 bwn_mac_suspend(mac);
2828 for (i = 0; i < N(sc->sc_wmeParams); i++) {
2829 wmep = &ic->ic_wme.wme_chanParams.cap_wmeParams[i];
2830 bwn_wme_loadparams(mac, wmep, bwn_wme_shm_offsets[i]);
2831 }
2832 bwn_mac_enable(mac);
2833 }
2834 BWN_UNLOCK(sc);
2835 return (0);
2836}
2837
2838static void
2839bwn_scan_start(struct ieee80211com *ic)
2840{
2841 struct ifnet *ifp = ic->ic_ifp;
2842 struct bwn_softc *sc = ifp->if_softc;
2843 struct bwn_mac *mac;
2844
2845 BWN_LOCK(sc);
2846 mac = sc->sc_curmac;
2847 if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2848 sc->sc_filters |= BWN_MACCTL_BEACON_PROMISC;
2849 bwn_set_opmode(mac);
2850 /* disable CFP update during scan */
2851 bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_SKIP_CFP_UPDATE);
2852 }
2853 BWN_UNLOCK(sc);
2854}
2855
2856static void
2857bwn_scan_end(struct ieee80211com *ic)
2858{
2859 struct ifnet *ifp = ic->ic_ifp;
2860 struct bwn_softc *sc = ifp->if_softc;
2861 struct bwn_mac *mac;
2862
2863 BWN_LOCK(sc);
2864 mac = sc->sc_curmac;
2865 if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2866 sc->sc_filters &= ~BWN_MACCTL_BEACON_PROMISC;
2867 bwn_set_opmode(mac);
2868 bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_SKIP_CFP_UPDATE);
2869 }
2870 BWN_UNLOCK(sc);
2871}
2872
2873static void
2874bwn_set_channel(struct ieee80211com *ic)
2875{
2876 struct ifnet *ifp = ic->ic_ifp;
2877 struct bwn_softc *sc = ifp->if_softc;
2878 struct bwn_mac *mac = sc->sc_curmac;
2879 struct bwn_phy *phy = &mac->mac_phy;
2880 int chan, error;
2881
2882 BWN_LOCK(sc);
2883
2884 error = bwn_switch_band(sc, ic->ic_curchan);
2885 if (error)
2886 goto fail;
2887 bwn_mac_suspend(mac);
2888 bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
2889 chan = ieee80211_chan2ieee(ic, ic->ic_curchan);
2890 if (chan != phy->chan)
2891 bwn_switch_channel(mac, chan);
2892
2893 /* TX power level */
2894 if (ic->ic_curchan->ic_maxpower != 0 &&
2895 ic->ic_curchan->ic_maxpower != phy->txpower) {
2896 phy->txpower = ic->ic_curchan->ic_maxpower / 2;
2897 bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME |
2898 BWN_TXPWR_IGNORE_TSSI);
2899 }
2900
2901 bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
2902 if (phy->set_antenna)
2903 phy->set_antenna(mac, BWN_ANT_DEFAULT);
2904
2905 if (sc->sc_rf_enabled != phy->rf_on) {
2906 if (sc->sc_rf_enabled) {
2907 bwn_rf_turnon(mac);
2908 if (!(mac->mac_flags & BWN_MAC_FLAG_RADIO_ON))
2909 device_printf(sc->sc_dev,
2910 "please turn on the RF switch\n");
2911 } else
2912 bwn_rf_turnoff(mac);
2913 }
2914
2915 bwn_mac_enable(mac);
2916
2917fail:
2918 /*
2919 * Setup radio tap channel freq and flags
2920 */
2921 sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq =
2922 htole16(ic->ic_curchan->ic_freq);
2923 sc->sc_tx_th.wt_chan_flags = sc->sc_rx_th.wr_chan_flags =
2924 htole16(ic->ic_curchan->ic_flags & 0xffff);
2925
2926 BWN_UNLOCK(sc);
2927}
2928
2929static struct ieee80211vap *
2930bwn_vap_create(struct ieee80211com *ic,
2931 const char name[IFNAMSIZ], int unit, int opmode, int flags,
2932 const uint8_t bssid[IEEE80211_ADDR_LEN],
2933 const uint8_t mac0[IEEE80211_ADDR_LEN])
2934{
2935 struct ifnet *ifp = ic->ic_ifp;
2936 struct bwn_softc *sc = ifp->if_softc;
2937 struct ieee80211vap *vap;
2938 struct bwn_vap *bvp;
2939 uint8_t mac[IEEE80211_ADDR_LEN];
2940
2941 IEEE80211_ADDR_COPY(mac, mac0);
2942 switch (opmode) {
2943 case IEEE80211_M_HOSTAP:
2944 case IEEE80211_M_MBSS:
2945 case IEEE80211_M_STA:
2946 case IEEE80211_M_WDS:
2947 case IEEE80211_M_MONITOR:
2948 case IEEE80211_M_IBSS:
2949 case IEEE80211_M_AHDEMO:
2950 break;
2951 default:
2952 return (NULL);
2953 }
2954
2955 IEEE80211_ADDR_COPY(sc->sc_macaddr, mac0);
2956
2957 bvp = (struct bwn_vap *) malloc(sizeof(struct bwn_vap),
2958 M_80211_VAP, M_NOWAIT | M_ZERO);
2959 if (bvp == NULL) {
2960 device_printf(sc->sc_dev, "failed to allocate a buffer\n");
2961 return (NULL);
2962 }
2963 vap = &bvp->bv_vap;
2964 ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
2965 IEEE80211_ADDR_COPY(vap->iv_myaddr, mac);
2966 /* override with driver methods */
2967 bvp->bv_newstate = vap->iv_newstate;
2968 vap->iv_newstate = bwn_newstate;
2969
2970 /* override max aid so sta's cannot assoc when we're out of sta id's */
2971 vap->iv_max_aid = BWN_STAID_MAX;
2972
2973 ieee80211_ratectl_init(vap);
2974
2975 /* complete setup */
2976 ieee80211_vap_attach(vap, ieee80211_media_change,
2977 ieee80211_media_status);
2978 return (vap);
2979}
2980
2981static void
2982bwn_vap_delete(struct ieee80211vap *vap)
2983{
2984 struct bwn_vap *bvp = BWN_VAP(vap);
2985
2986 ieee80211_ratectl_deinit(vap);
2987 ieee80211_vap_detach(vap);
2988 free(bvp, M_80211_VAP);
2989}
2990
2991static void
2992bwn_init(void *arg)
2993{
2994 struct bwn_softc *sc = arg;
2995 struct ifnet *ifp = sc->sc_ifp;
2996 struct ieee80211com *ic = ifp->if_l2com;
2997 int error = 0;
2998
2999 DPRINTF(sc, BWN_DEBUG_ANY, "%s: if_flags 0x%x\n",
3000 __func__, ifp->if_flags);
3001
3002 BWN_LOCK(sc);
3003 error = bwn_init_locked(sc);
3004 BWN_UNLOCK(sc);
3005
3006 if (error == 0)
3007 ieee80211_start_all(ic); /* start all vap's */
3008}
3009
3010static int
3011bwn_init_locked(struct bwn_softc *sc)
3012{
3013 struct bwn_mac *mac;
3014 struct ifnet *ifp = sc->sc_ifp;
3015 int error;
3016
3017 BWN_ASSERT_LOCKED(sc);
3018
3019 bzero(sc->sc_bssid, IEEE80211_ADDR_LEN);
3020 sc->sc_flags |= BWN_FLAG_NEED_BEACON_TP;
3021 sc->sc_filters = 0;
3022 bwn_wme_clear(sc);
3023 sc->sc_beacons[0] = sc->sc_beacons[1] = 0;
3024 sc->sc_rf_enabled = 1;
3025
3026 mac = sc->sc_curmac;
3027 if (mac->mac_status == BWN_MAC_STATUS_UNINIT) {
3028 error = bwn_core_init(mac);
3029 if (error != 0)
3030 return (error);
3031 }
3032 if (mac->mac_status == BWN_MAC_STATUS_INITED)
3033 bwn_core_start(mac);
3034
3035 bwn_set_opmode(mac);
3036 bwn_set_pretbtt(mac);
3037 bwn_spu_setdelay(mac, 0);
3038 bwn_set_macaddr(mac);
3039
3040 ifp->if_drv_flags |= IFF_DRV_RUNNING;
3041 callout_reset(&sc->sc_rfswitch_ch, hz, bwn_rfswitch, sc);
3042 callout_reset(&sc->sc_watchdog_ch, hz, bwn_watchdog, sc);
3043
3044 return (0);
3045}
3046
3047static void
3048bwn_stop(struct bwn_softc *sc, int statechg)
3049{
3050
3051 BWN_LOCK(sc);
3052 bwn_stop_locked(sc, statechg);
3053 BWN_UNLOCK(sc);
3054}
3055
3056static void
3057bwn_stop_locked(struct bwn_softc *sc, int statechg)
3058{
3059 struct bwn_mac *mac = sc->sc_curmac;
3060 struct ifnet *ifp = sc->sc_ifp;
3061
3062 BWN_ASSERT_LOCKED(sc);
3063
3064 if (mac->mac_status >= BWN_MAC_STATUS_INITED) {
3065 /* XXX FIXME opmode not based on VAP */
3066 bwn_set_opmode(mac);
3067 bwn_set_macaddr(mac);
3068 }
3069
3070 if (mac->mac_status >= BWN_MAC_STATUS_STARTED)
3071 bwn_core_stop(mac);
3072
3073 callout_stop(&sc->sc_led_blink_ch);
3074 sc->sc_led_blinking = 0;
3075
3076 bwn_core_exit(mac);
3077 sc->sc_rf_enabled = 0;
3078
3079 ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
3080}
3081
3082static void
3083bwn_wme_clear(struct bwn_softc *sc)
3084{
3085#define MS(_v, _f) (((_v) & _f) >> _f##_S)
3086 struct wmeParams *p;
3087 unsigned int i;
3088
3089 KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
3090 ("%s:%d: fail", __func__, __LINE__));
3091
3092 for (i = 0; i < N(sc->sc_wmeParams); i++) {
3093 p = &(sc->sc_wmeParams[i]);
3094
3095 switch (bwn_wme_shm_offsets[i]) {
3096 case BWN_WME_VOICE:
3097 p->wmep_txopLimit = 0;
3098 p->wmep_aifsn = 2;
3099 /* XXX FIXME: log2(cwmin) */
3100 p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3101 p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3102 break;
3103 case BWN_WME_VIDEO:
3104 p->wmep_txopLimit = 0;
3105 p->wmep_aifsn = 2;
3106 /* XXX FIXME: log2(cwmin) */
3107 p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3108 p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3109 break;
3110 case BWN_WME_BESTEFFORT:
3111 p->wmep_txopLimit = 0;
3112 p->wmep_aifsn = 3;
3113 /* XXX FIXME: log2(cwmin) */
3114 p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3115 p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3116 break;
3117 case BWN_WME_BACKGROUND:
3118 p->wmep_txopLimit = 0;
3119 p->wmep_aifsn = 7;
3120 /* XXX FIXME: log2(cwmin) */
3121 p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3122 p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3123 break;
3124 default:
3125 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3126 }
3127 }
3128}
3129
3130static int
3131bwn_core_init(struct bwn_mac *mac)
3132{
3133 struct bwn_softc *sc = mac->mac_sc;
3134 uint64_t hf;
3135 int error;
3136
3137 KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3138 ("%s:%d: fail", __func__, __LINE__));
3139
3140 siba_powerup(sc->sc_dev, 0);
3141 if (!siba_dev_isup(sc->sc_dev))
3142 bwn_reset_core(mac,
3143 mac->mac_phy.gmode ? BWN_TGSLOW_SUPPORT_G : 0);
3144
3145 mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
3146 mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
3147 mac->mac_phy.hwpctl = (bwn_hwpctl) ? 1 : 0;
3148 BWN_GETTIME(mac->mac_phy.nexttime);
3149 mac->mac_phy.txerrors = BWN_TXERROR_MAX;
3150 bzero(&mac->mac_stats, sizeof(mac->mac_stats));
3151 mac->mac_stats.link_noise = -95;
3152 mac->mac_reason_intr = 0;
3153 bzero(mac->mac_reason, sizeof(mac->mac_reason));
3154 mac->mac_intr_mask = BWN_INTR_MASKTEMPLATE;
3155#ifdef BWN_DEBUG
3156 if (sc->sc_debug & BWN_DEBUG_XMIT)
3157 mac->mac_intr_mask &= ~BWN_INTR_PHY_TXERR;
3158#endif
3159 mac->mac_suspended = 1;
3160 mac->mac_task_state = 0;
3161 memset(&mac->mac_noise, 0, sizeof(mac->mac_noise));
3162
3163 mac->mac_phy.init_pre(mac);
3164
3165 siba_pcicore_intr(sc->sc_dev);
3166
3167 siba_fix_imcfglobug(sc->sc_dev);
3168 bwn_bt_disable(mac);
3169 if (mac->mac_phy.prepare_hw) {
3170 error = mac->mac_phy.prepare_hw(mac);
3171 if (error)
3172 goto fail0;
3173 }
3174 error = bwn_chip_init(mac);
3175 if (error)
3176 goto fail0;
3177 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_COREREV,
3178 siba_get_revid(sc->sc_dev));
3179 hf = bwn_hf_read(mac);
3180 if (mac->mac_phy.type == BWN_PHYTYPE_G) {
3181 hf |= BWN_HF_GPHY_SYM_WORKAROUND;
3182 if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
3183 hf |= BWN_HF_PAGAINBOOST_OFDM_ON;
3184 if (mac->mac_phy.rev == 1)
3185 hf |= BWN_HF_GPHY_DC_CANCELFILTER;
3186 }
3187 if (mac->mac_phy.rf_ver == 0x2050) {
3188 if (mac->mac_phy.rf_rev < 6)
3189 hf |= BWN_HF_FORCE_VCO_RECALC;
3190 if (mac->mac_phy.rf_rev == 6)
3191 hf |= BWN_HF_4318_TSSI;
3192 }
3193 if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW)
3194 hf |= BWN_HF_SLOWCLOCK_REQ_OFF;
3195 if ((siba_get_type(sc->sc_dev) == SIBA_TYPE_PCI) &&
3196 (siba_get_pcicore_revid(sc->sc_dev) <= 10))
3197 hf |= BWN_HF_PCI_SLOWCLOCK_WORKAROUND;
3198 hf &= ~BWN_HF_SKIP_CFP_UPDATE;
3199 bwn_hf_write(mac, hf);
3200
3201 bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
3202 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SHORT_RETRY_FALLBACK, 3);
3203 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_LONG_RETRY_FALLBACK, 2);
3204 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_MAXTIME, 1);
3205
3206 bwn_rate_init(mac);
3207 bwn_set_phytxctl(mac);
3208
3209 bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MIN,
3210 (mac->mac_phy.type == BWN_PHYTYPE_B) ? 0x1f : 0xf);
3211 bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MAX, 0x3ff);
3212
3213 if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
3214 bwn_pio_init(mac);
3215 else
3216 bwn_dma_init(mac);
3217 bwn_wme_init(mac);
3218 bwn_spu_setdelay(mac, 1);
3219 bwn_bt_enable(mac);
3220
3221 siba_powerup(sc->sc_dev,
3222 !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW));
3223 bwn_set_macaddr(mac);
3224 bwn_crypt_init(mac);
3225
3226 /* XXX LED initializatin */
3227
3228 mac->mac_status = BWN_MAC_STATUS_INITED;
3229
3230 return (error);
3231
3232fail0:
3233 siba_powerdown(sc->sc_dev);
3234 KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3235 ("%s:%d: fail", __func__, __LINE__));
3236 return (error);
3237}
3238
3239static void
3240bwn_core_start(struct bwn_mac *mac)
3241{
3242 struct bwn_softc *sc = mac->mac_sc;
3243 uint32_t tmp;
3244
3245 KASSERT(mac->mac_status == BWN_MAC_STATUS_INITED,
3246 ("%s:%d: fail", __func__, __LINE__));
3247
3248 if (siba_get_revid(sc->sc_dev) < 5)
3249 return;
3250
3251 while (1) {
3252 tmp = BWN_READ_4(mac, BWN_XMITSTAT_0);
3253 if (!(tmp & 0x00000001))
3254 break;
3255 tmp = BWN_READ_4(mac, BWN_XMITSTAT_1);
3256 }
3257
3258 bwn_mac_enable(mac);
3259 BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
3260 callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
3261
3262 mac->mac_status = BWN_MAC_STATUS_STARTED;
3263}
3264
3265static void
3266bwn_core_exit(struct bwn_mac *mac)
3267{
3268 struct bwn_softc *sc = mac->mac_sc;
3269 uint32_t macctl;
3270
3271 BWN_ASSERT_LOCKED(mac->mac_sc);
3272
3273 KASSERT(mac->mac_status <= BWN_MAC_STATUS_INITED,
3274 ("%s:%d: fail", __func__, __LINE__));
3275
3276 if (mac->mac_status != BWN_MAC_STATUS_INITED)
3277 return;
3278 mac->mac_status = BWN_MAC_STATUS_UNINIT;
3279
3280 macctl = BWN_READ_4(mac, BWN_MACCTL);
3281 macctl &= ~BWN_MACCTL_MCODE_RUN;
3282 macctl |= BWN_MACCTL_MCODE_JMP0;
3283 BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3284
3285 bwn_dma_stop(mac);
3286 bwn_pio_stop(mac);
3287 bwn_chip_exit(mac);
3288 mac->mac_phy.switch_analog(mac, 0);
3289 siba_dev_down(sc->sc_dev, 0);
3290 siba_powerdown(sc->sc_dev);
3291}
3292
3293static void
3294bwn_bt_disable(struct bwn_mac *mac)
3295{
3296 struct bwn_softc *sc = mac->mac_sc;
3297
3298 (void)sc;
3299 /* XXX do nothing yet */
3300}
3301
3302static int
3303bwn_chip_init(struct bwn_mac *mac)
3304{
3305 struct bwn_softc *sc = mac->mac_sc;
3306 struct bwn_phy *phy = &mac->mac_phy;
3307 uint32_t macctl;
3308 int error;
3309
3310 macctl = BWN_MACCTL_IHR_ON | BWN_MACCTL_SHM_ON | BWN_MACCTL_STA;
3311 if (phy->gmode)
3312 macctl |= BWN_MACCTL_GMODE;
3313 BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3314
3315 error = bwn_fw_fillinfo(mac);
3316 if (error)
3317 return (error);
3318 error = bwn_fw_loaducode(mac);
3319 if (error)
3320 return (error);
3321
3322 error = bwn_gpio_init(mac);
3323 if (error)
3324 return (error);
3325
3326 error = bwn_fw_loadinitvals(mac);
3327 if (error) {
3328 siba_gpio_set(sc->sc_dev, 0);
3329 return (error);
3330 }
3331 phy->switch_analog(mac, 1);
3332 error = bwn_phy_init(mac);
3333 if (error) {
3334 siba_gpio_set(sc->sc_dev, 0);
3335 return (error);
3336 }
3337 if (phy->set_im)
3338 phy->set_im(mac, BWN_IMMODE_NONE);
3339 if (phy->set_antenna)
3340 phy->set_antenna(mac, BWN_ANT_DEFAULT);
3341 bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
3342
3343 if (phy->type == BWN_PHYTYPE_B)
3344 BWN_WRITE_2(mac, 0x005e, BWN_READ_2(mac, 0x005e) | 0x0004);
3345 BWN_WRITE_4(mac, 0x0100, 0x01000000);
3346 if (siba_get_revid(sc->sc_dev) < 5)
3347 BWN_WRITE_4(mac, 0x010c, 0x01000000);
3348
3349 BWN_WRITE_4(mac, BWN_MACCTL,
3350 BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_STA);
3351 BWN_WRITE_4(mac, BWN_MACCTL,
3352 BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_STA);
3353 bwn_shm_write_2(mac, BWN_SHARED, 0x0074, 0x0000);
3354
3355 bwn_set_opmode(mac);
3356 if (siba_get_revid(sc->sc_dev) < 3) {
3357 BWN_WRITE_2(mac, 0x060e, 0x0000);
3358 BWN_WRITE_2(mac, 0x0610, 0x8000);
3359 BWN_WRITE_2(mac, 0x0604, 0x0000);
3360 BWN_WRITE_2(mac, 0x0606, 0x0200);
3361 } else {
3362 BWN_WRITE_4(mac, 0x0188, 0x80000000);
3363 BWN_WRITE_4(mac, 0x018c, 0x02000000);
3364 }
3365 BWN_WRITE_4(mac, BWN_INTR_REASON, 0x00004000);
3366 BWN_WRITE_4(mac, BWN_DMA0_INTR_MASK, 0x0001dc00);
3367 BWN_WRITE_4(mac, BWN_DMA1_INTR_MASK, 0x0000dc00);
3368 BWN_WRITE_4(mac, BWN_DMA2_INTR_MASK, 0x0000dc00);
3369 BWN_WRITE_4(mac, BWN_DMA3_INTR_MASK, 0x0001dc00);
3370 BWN_WRITE_4(mac, BWN_DMA4_INTR_MASK, 0x0000dc00);
3371 BWN_WRITE_4(mac, BWN_DMA5_INTR_MASK, 0x0000dc00);
3372 siba_write_4(sc->sc_dev, SIBA_TGSLOW,
3373 siba_read_4(sc->sc_dev, SIBA_TGSLOW) | 0x00100000);
3374 BWN_WRITE_2(mac, BWN_POWERUP_DELAY, siba_get_cc_powerdelay(sc->sc_dev));
3375 return (error);
3376}
3377
3378/* read hostflags */
3379static uint64_t
3380bwn_hf_read(struct bwn_mac *mac)
3381{
3382 uint64_t ret;
3383
3384 ret = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFHI);
3385 ret <<= 16;
3386 ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFMI);
3387 ret <<= 16;
3388 ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO);
3389 return (ret);
3390}
3391
3392static void
3393bwn_hf_write(struct bwn_mac *mac, uint64_t value)
3394{
3395
3396 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFLO,
3397 (value & 0x00000000ffffull));
3398 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFMI,
3399 (value & 0x0000ffff0000ull) >> 16);
3400 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFHI,
3401 (value & 0xffff00000000ULL) >> 32);
3402}
3403
3404static void
3405bwn_set_txretry(struct bwn_mac *mac, int s, int l)
3406{
3407
3408 bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_SHORT_RETRY, MIN(s, 0xf));
3409 bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_LONG_RETRY, MIN(l, 0xf));
3410}
3411
3412static void
3413bwn_rate_init(struct bwn_mac *mac)
3414{
3415
3416 switch (mac->mac_phy.type) {
3417 case BWN_PHYTYPE_A:
3418 case BWN_PHYTYPE_G:
3419 case BWN_PHYTYPE_LP:
3420 case BWN_PHYTYPE_N:
3421 bwn_rate_write(mac, BWN_OFDM_RATE_6MB, 1);
3422 bwn_rate_write(mac, BWN_OFDM_RATE_12MB, 1);
3423 bwn_rate_write(mac, BWN_OFDM_RATE_18MB, 1);
3424 bwn_rate_write(mac, BWN_OFDM_RATE_24MB, 1);
3425 bwn_rate_write(mac, BWN_OFDM_RATE_36MB, 1);
3426 bwn_rate_write(mac, BWN_OFDM_RATE_48MB, 1);
3427 bwn_rate_write(mac, BWN_OFDM_RATE_54MB, 1);
3428 if (mac->mac_phy.type == BWN_PHYTYPE_A)
3429 break;
3430 /* FALLTHROUGH */
3431 case BWN_PHYTYPE_B:
3432 bwn_rate_write(mac, BWN_CCK_RATE_1MB, 0);
3433 bwn_rate_write(mac, BWN_CCK_RATE_2MB, 0);
3434 bwn_rate_write(mac, BWN_CCK_RATE_5MB, 0);
3435 bwn_rate_write(mac, BWN_CCK_RATE_11MB, 0);
3436 break;
3437 default:
3438 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3439 }
3440}
3441
3442static void
3443bwn_rate_write(struct bwn_mac *mac, uint16_t rate, int ofdm)
3444{
3445 uint16_t offset;
3446
3447 if (ofdm) {
3448 offset = 0x480;
3449 offset += (bwn_plcp_getofdm(rate) & 0x000f) * 2;
3450 } else {
3451 offset = 0x4c0;
3452 offset += (bwn_plcp_getcck(rate) & 0x000f) * 2;
3453 }
3454 bwn_shm_write_2(mac, BWN_SHARED, offset + 0x20,
3455 bwn_shm_read_2(mac, BWN_SHARED, offset));
3456}
3457
3458static uint8_t
3459bwn_plcp_getcck(const uint8_t bitrate)
3460{
3461
3462 switch (bitrate) {
3463 case BWN_CCK_RATE_1MB:
3464 return (0x0a);
3465 case BWN_CCK_RATE_2MB:
3466 return (0x14);
3467 case BWN_CCK_RATE_5MB:
3468 return (0x37);
3469 case BWN_CCK_RATE_11MB:
3470 return (0x6e);
3471 }
3472 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3473 return (0);
3474}
3475
3476static uint8_t
3477bwn_plcp_getofdm(const uint8_t bitrate)
3478{
3479
3480 switch (bitrate) {
3481 case BWN_OFDM_RATE_6MB:
3482 return (0xb);
3483 case BWN_OFDM_RATE_9MB:
3484 return (0xf);
3485 case BWN_OFDM_RATE_12MB:
3486 return (0xa);
3487 case BWN_OFDM_RATE_18MB:
3488 return (0xe);
3489 case BWN_OFDM_RATE_24MB:
3490 return (0x9);
3491 case BWN_OFDM_RATE_36MB:
3492 return (0xd);
3493 case BWN_OFDM_RATE_48MB:
3494 return (0x8);
3495 case BWN_OFDM_RATE_54MB:
3496 return (0xc);
3497 }
3498 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3499 return (0);
3500}
3501
3502static void
3503bwn_set_phytxctl(struct bwn_mac *mac)
3504{
3505 uint16_t ctl;
3506
3507 ctl = (BWN_TX_PHY_ENC_CCK | BWN_TX_PHY_ANT01AUTO |
3508 BWN_TX_PHY_TXPWR);
3509 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_BEACON_PHYCTL, ctl);
3510 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, ctl);
3511 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, ctl);
3512}
3513
3514static void
3515bwn_pio_init(struct bwn_mac *mac)
3516{
3517 struct bwn_pio *pio = &mac->mac_method.pio;
3518
3519 BWN_WRITE_4(mac, BWN_MACCTL, BWN_READ_4(mac, BWN_MACCTL)
3520 & ~BWN_MACCTL_BIGENDIAN);
3521 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RX_PADOFFSET, 0);
3522
3523 bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BK], 0);
3524 bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BE], 1);
3525 bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VI], 2);
3526 bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VO], 3);
3527 bwn_pio_set_txqueue(mac, &pio->mcast, 4);
3528 bwn_pio_setupqueue_rx(mac, &pio->rx, 0);
3529}
3530
3531static void
3532bwn_pio_set_txqueue(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3533 int index)
3534{
3535 struct bwn_pio_txpkt *tp;
3536 struct bwn_softc *sc = mac->mac_sc;
3537 unsigned int i;
3538
3539 tq->tq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_TXQOFFSET(mac);
3540 tq->tq_index = index;
3541
3542 tq->tq_free = BWN_PIO_MAX_TXPACKETS;
3543 if (siba_get_revid(sc->sc_dev) >= 8)
3544 tq->tq_size = 1920;
3545 else {
3546 tq->tq_size = bwn_pio_read_2(mac, tq, BWN_PIO_TXQBUFSIZE);
3547 tq->tq_size -= 80;
3548 }
3549
3550 TAILQ_INIT(&tq->tq_pktlist);
3551 for (i = 0; i < N(tq->tq_pkts); i++) {
3552 tp = &(tq->tq_pkts[i]);
3553 tp->tp_index = i;
3554 tp->tp_queue = tq;
3555 TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
3556 }
3557}
3558
3559static uint16_t
3560bwn_pio_idx2base(struct bwn_mac *mac, int index)
3561{
3562 struct bwn_softc *sc = mac->mac_sc;
3563 static const uint16_t bases[] = {
3564 BWN_PIO_BASE0,
3565 BWN_PIO_BASE1,
3566 BWN_PIO_BASE2,
3567 BWN_PIO_BASE3,
3568 BWN_PIO_BASE4,
3569 BWN_PIO_BASE5,
3570 BWN_PIO_BASE6,
3571 BWN_PIO_BASE7,
3572 };
3573 static const uint16_t bases_rev11[] = {
3574 BWN_PIO11_BASE0,
3575 BWN_PIO11_BASE1,
3576 BWN_PIO11_BASE2,
3577 BWN_PIO11_BASE3,
3578 BWN_PIO11_BASE4,
3579 BWN_PIO11_BASE5,
3580 };
3581
3582 if (siba_get_revid(sc->sc_dev) >= 11) {
3583 if (index >= N(bases_rev11))
3584 device_printf(sc->sc_dev, "%s: warning\n", __func__);
3585 return (bases_rev11[index]);
3586 }
3587 if (index >= N(bases))
3588 device_printf(sc->sc_dev, "%s: warning\n", __func__);
3589 return (bases[index]);
3590}
3591
3592static void
3593bwn_pio_setupqueue_rx(struct bwn_mac *mac, struct bwn_pio_rxqueue *prq,
3594 int index)
3595{
3596 struct bwn_softc *sc = mac->mac_sc;
3597
3598 prq->prq_mac = mac;
3599 prq->prq_rev = siba_get_revid(sc->sc_dev);
3600 prq->prq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_RXQOFFSET(mac);
3601 bwn_dma_rxdirectfifo(mac, index, 1);
3602}
3603
3604static void
3605bwn_destroy_pioqueue_tx(struct bwn_pio_txqueue *tq)
3606{
3607 if (tq == NULL)
3608 return;
3609 bwn_pio_cancel_tx_packets(tq);
3610}
3611
3612static void
3613bwn_destroy_queue_tx(struct bwn_pio_txqueue *pio)
3614{
3615
3616 bwn_destroy_pioqueue_tx(pio);
3617}
3618
3619static uint16_t
3620bwn_pio_read_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3621 uint16_t offset)
3622{
3623
3624 return (BWN_READ_2(mac, tq->tq_base + offset));
3625}
3626
3627static void
3628bwn_dma_rxdirectfifo(struct bwn_mac *mac, int idx, uint8_t enable)
3629{
3630 uint32_t ctl;
3631 int type;
3632 uint16_t base;
3633
3634 type = bwn_dma_mask2type(bwn_dma_mask(mac));
3635 base = bwn_dma_base(type, idx);
3636 if (type == BWN_DMA_64BIT) {
3637 ctl = BWN_READ_4(mac, base + BWN_DMA64_RXCTL);
3638 ctl &= ~BWN_DMA64_RXDIRECTFIFO;
3639 if (enable)
3640 ctl |= BWN_DMA64_RXDIRECTFIFO;
3641 BWN_WRITE_4(mac, base + BWN_DMA64_RXCTL, ctl);
3642 } else {
3643 ctl = BWN_READ_4(mac, base + BWN_DMA32_RXCTL);
3644 ctl &= ~BWN_DMA32_RXDIRECTFIFO;
3645 if (enable)
3646 ctl |= BWN_DMA32_RXDIRECTFIFO;
3647 BWN_WRITE_4(mac, base + BWN_DMA32_RXCTL, ctl);
3648 }
3649}
3650
3651static uint64_t
3652bwn_dma_mask(struct bwn_mac *mac)
3653{
3654 uint32_t tmp;
3655 uint16_t base;
3656
3657 tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
3658 if (tmp & SIBA_TGSHIGH_DMA64)
3659 return (BWN_DMA_BIT_MASK(64));
3660 base = bwn_dma_base(0, 0);
3661 BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
3662 tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
3663 if (tmp & BWN_DMA32_TXADDREXT_MASK)
3664 return (BWN_DMA_BIT_MASK(32));
3665
3666 return (BWN_DMA_BIT_MASK(30));
3667}
3668
3669static int
3670bwn_dma_mask2type(uint64_t dmamask)
3671{
3672
3673 if (dmamask == BWN_DMA_BIT_MASK(30))
3674 return (BWN_DMA_30BIT);
3675 if (dmamask == BWN_DMA_BIT_MASK(32))
3676 return (BWN_DMA_32BIT);
3677 if (dmamask == BWN_DMA_BIT_MASK(64))
3678 return (BWN_DMA_64BIT);
3679 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3680 return (BWN_DMA_30BIT);
3681}
3682
3683static void
3684bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *tq)
3685{
3686 struct bwn_pio_txpkt *tp;
3687 unsigned int i;
3688
3689 for (i = 0; i < N(tq->tq_pkts); i++) {
3690 tp = &(tq->tq_pkts[i]);
3691 if (tp->tp_m) {
3692 m_freem(tp->tp_m);
3693 tp->tp_m = NULL;
3694 }
3695 }
3696}
3697
3698static uint16_t
3699bwn_dma_base(int type, int controller_idx)
3700{
3701 static const uint16_t map64[] = {
3702 BWN_DMA64_BASE0,
3703 BWN_DMA64_BASE1,
3704 BWN_DMA64_BASE2,
3705 BWN_DMA64_BASE3,
3706 BWN_DMA64_BASE4,
3707 BWN_DMA64_BASE5,
3708 };
3709 static const uint16_t map32[] = {
3710 BWN_DMA32_BASE0,
3711 BWN_DMA32_BASE1,
3712 BWN_DMA32_BASE2,
3713 BWN_DMA32_BASE3,
3714 BWN_DMA32_BASE4,
3715 BWN_DMA32_BASE5,
3716 };
3717
3718 if (type == BWN_DMA_64BIT) {
3719 KASSERT(controller_idx >= 0 && controller_idx < N(map64),
3720 ("%s:%d: fail", __func__, __LINE__));
3721 return (map64[controller_idx]);
3722 }
3723 KASSERT(controller_idx >= 0 && controller_idx < N(map32),
3724 ("%s:%d: fail", __func__, __LINE__));
3725 return (map32[controller_idx]);
3726}
3727
3728static void
3729bwn_dma_init(struct bwn_mac *mac)
3730{
3731 struct bwn_dma *dma = &mac->mac_method.dma;
3732
3733 /* setup TX DMA channels. */
3734 bwn_dma_setup(dma->wme[WME_AC_BK]);
3735 bwn_dma_setup(dma->wme[WME_AC_BE]);
3736 bwn_dma_setup(dma->wme[WME_AC_VI]);
3737 bwn_dma_setup(dma->wme[WME_AC_VO]);
3738 bwn_dma_setup(dma->mcast);
3739 /* setup RX DMA channel. */
3740 bwn_dma_setup(dma->rx);
3741}
3742
3743static struct bwn_dma_ring *
3744bwn_dma_ringsetup(struct bwn_mac *mac, int controller_index,
3745 int for_tx, int type)
3746{
3747 struct bwn_dma *dma = &mac->mac_method.dma;
3748 struct bwn_dma_ring *dr;
3749 struct bwn_dmadesc_generic *desc;
3750 struct bwn_dmadesc_meta *mt;
3751 struct bwn_softc *sc = mac->mac_sc;
3752 int error, i;
3753
3754 dr = malloc(sizeof(*dr), M_DEVBUF, M_NOWAIT | M_ZERO);
3755 if (dr == NULL)
3756 goto out;
3757 dr->dr_numslots = BWN_RXRING_SLOTS;
3758 if (for_tx)
3759 dr->dr_numslots = BWN_TXRING_SLOTS;
3760
3761 dr->dr_meta = malloc(dr->dr_numslots * sizeof(struct bwn_dmadesc_meta),
3762 M_DEVBUF, M_NOWAIT | M_ZERO);
3763 if (dr->dr_meta == NULL)
3764 goto fail0;
3765
3766 dr->dr_type = type;
3767 dr->dr_mac = mac;
3768 dr->dr_base = bwn_dma_base(type, controller_index);
3769 dr->dr_index = controller_index;
3770 if (type == BWN_DMA_64BIT) {
3771 dr->getdesc = bwn_dma_64_getdesc;
3772 dr->setdesc = bwn_dma_64_setdesc;
3773 dr->start_transfer = bwn_dma_64_start_transfer;
3774 dr->suspend = bwn_dma_64_suspend;
3775 dr->resume = bwn_dma_64_resume;
3776 dr->get_curslot = bwn_dma_64_get_curslot;
3777 dr->set_curslot = bwn_dma_64_set_curslot;
3778 } else {
3779 dr->getdesc = bwn_dma_32_getdesc;
3780 dr->setdesc = bwn_dma_32_setdesc;
3781 dr->start_transfer = bwn_dma_32_start_transfer;
3782 dr->suspend = bwn_dma_32_suspend;
3783 dr->resume = bwn_dma_32_resume;
3784 dr->get_curslot = bwn_dma_32_get_curslot;
3785 dr->set_curslot = bwn_dma_32_set_curslot;
3786 }
3787 if (for_tx) {
3788 dr->dr_tx = 1;
3789 dr->dr_curslot = -1;
3790 } else {
3791 if (dr->dr_index == 0) {
3792 dr->dr_rx_bufsize = BWN_DMA0_RX_BUFFERSIZE;
3793 dr->dr_frameoffset = BWN_DMA0_RX_FRAMEOFFSET;
3794 } else
3795 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3796 }
3797
3798 error = bwn_dma_allocringmemory(dr);
3799 if (error)
3800 goto fail2;
3801
3802 if (for_tx) {
3803 /*
3804 * Assumption: BWN_TXRING_SLOTS can be divided by
3805 * BWN_TX_SLOTS_PER_FRAME
3806 */
3807 KASSERT(BWN_TXRING_SLOTS % BWN_TX_SLOTS_PER_FRAME == 0,
3808 ("%s:%d: fail", __func__, __LINE__));
3809
3810 dr->dr_txhdr_cache =
3811 malloc((dr->dr_numslots / BWN_TX_SLOTS_PER_FRAME) *
3812 BWN_HDRSIZE(mac), M_DEVBUF, M_NOWAIT | M_ZERO);
3813 KASSERT(dr->dr_txhdr_cache != NULL,
3814 ("%s:%d: fail", __func__, __LINE__));
3815
3816 /*
3817 * Create TX ring DMA stuffs
3818 */
3819 error = bus_dma_tag_create(dma->parent_dtag,
3820 BWN_ALIGN, 0,
3821 BUS_SPACE_MAXADDR,
3822 BUS_SPACE_MAXADDR,
3823 NULL, NULL,
3824 BWN_HDRSIZE(mac),
3825 1,
3826 BUS_SPACE_MAXSIZE_32BIT,
3827 0,
3828 NULL, NULL,
3829 &dr->dr_txring_dtag);
3830 if (error) {
3831 device_printf(sc->sc_dev,
3832 "can't create TX ring DMA tag: TODO frees\n");
3833 goto fail1;
3834 }
3835
3836 for (i = 0; i < dr->dr_numslots; i += 2) {
3837 dr->getdesc(dr, i, &desc, &mt);
3838
3839 mt->mt_txtype = BWN_DMADESC_METATYPE_HEADER;
3840 mt->mt_m = NULL;
3841 mt->mt_ni = NULL;
3842 mt->mt_islast = 0;
3843 error = bus_dmamap_create(dr->dr_txring_dtag, 0,
3844 &mt->mt_dmap);
3845 if (error) {
3846 device_printf(sc->sc_dev,
3847 "can't create RX buf DMA map\n");
3848 goto fail1;
3849 }
3850
3851 dr->getdesc(dr, i + 1, &desc, &mt);
3852
3853 mt->mt_txtype = BWN_DMADESC_METATYPE_BODY;
3854 mt->mt_m = NULL;
3855 mt->mt_ni = NULL;
3856 mt->mt_islast = 1;
3857 error = bus_dmamap_create(dma->txbuf_dtag, 0,
3858 &mt->mt_dmap);
3859 if (error) {
3860 device_printf(sc->sc_dev,
3861 "can't create RX buf DMA map\n");
3862 goto fail1;
3863 }
3864 }
3865 } else {
3866 error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3867 &dr->dr_spare_dmap);
3868 if (error) {
3869 device_printf(sc->sc_dev,
3870 "can't create RX buf DMA map\n");
3871 goto out; /* XXX wrong! */
3872 }
3873
3874 for (i = 0; i < dr->dr_numslots; i++) {
3875 dr->getdesc(dr, i, &desc, &mt);
3876
3877 error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3878 &mt->mt_dmap);
3879 if (error) {
3880 device_printf(sc->sc_dev,
3881 "can't create RX buf DMA map\n");
3882 goto out; /* XXX wrong! */
3883 }
3884 error = bwn_dma_newbuf(dr, desc, mt, 1);
3885 if (error) {
3886 device_printf(sc->sc_dev,
3887 "failed to allocate RX buf\n");
3888 goto out; /* XXX wrong! */
3889 }
3890 }
3891
3892 bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
3893 BUS_DMASYNC_PREWRITE);
3894
3895 dr->dr_usedslot = dr->dr_numslots;
3896 }
3897
3898 out:
3899 return (dr);
3900
3901fail2:
3902 free(dr->dr_txhdr_cache, M_DEVBUF);
3903fail1:
3904 free(dr->dr_meta, M_DEVBUF);
3905fail0:
3906 free(dr, M_DEVBUF);
3907 return (NULL);
3908}
3909
3910static void
3911bwn_dma_ringfree(struct bwn_dma_ring **dr)
3912{
3913
3914 if (dr == NULL)
3915 return;
3916
3917 bwn_dma_free_descbufs(*dr);
3918 bwn_dma_free_ringmemory(*dr);
3919
3920 free((*dr)->dr_txhdr_cache, M_DEVBUF);
3921 free((*dr)->dr_meta, M_DEVBUF);
3922 free(*dr, M_DEVBUF);
3923
3924 *dr = NULL;
3925}
3926
3927static void
3928bwn_dma_32_getdesc(struct bwn_dma_ring *dr, int slot,
3929 struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
3930{
3931 struct bwn_dmadesc32 *desc;
3932
3933 *meta = &(dr->dr_meta[slot]);
3934 desc = dr->dr_ring_descbase;
3935 desc = &(desc[slot]);
3936
3937 *gdesc = (struct bwn_dmadesc_generic *)desc;
3938}
3939
3940static void
3941bwn_dma_32_setdesc(struct bwn_dma_ring *dr,
3942 struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
3943 int start, int end, int irq)
3944{
3945 struct bwn_dmadesc32 *descbase = dr->dr_ring_descbase;
3946 struct bwn_softc *sc = dr->dr_mac->mac_sc;
3947 uint32_t addr, addrext, ctl;
3948 int slot;
3949
3950 slot = (int)(&(desc->dma.dma32) - descbase);
3951 KASSERT(slot >= 0 && slot < dr->dr_numslots,
3952 ("%s:%d: fail", __func__, __LINE__));
3953
3954 addr = (uint32_t) (dmaaddr & ~SIBA_DMA_TRANSLATION_MASK);
3955 addrext = (uint32_t) (dmaaddr & SIBA_DMA_TRANSLATION_MASK) >> 30;
3956 addr |= siba_dma_translation(sc->sc_dev);
3957 ctl = bufsize & BWN_DMA32_DCTL_BYTECNT;
3958 if (slot == dr->dr_numslots - 1)
3959 ctl |= BWN_DMA32_DCTL_DTABLEEND;
3960 if (start)
3961 ctl |= BWN_DMA32_DCTL_FRAMESTART;
3962 if (end)
3963 ctl |= BWN_DMA32_DCTL_FRAMEEND;
3964 if (irq)
3965 ctl |= BWN_DMA32_DCTL_IRQ;
3966 ctl |= (addrext << BWN_DMA32_DCTL_ADDREXT_SHIFT)
3967 & BWN_DMA32_DCTL_ADDREXT_MASK;
3968
3969 desc->dma.dma32.control = htole32(ctl);
3970 desc->dma.dma32.address = htole32(addr);
3971}
3972
3973static void
3974bwn_dma_32_start_transfer(struct bwn_dma_ring *dr, int slot)
3975{
3976
3977 BWN_DMA_WRITE(dr, BWN_DMA32_TXINDEX,
3978 (uint32_t)(slot * sizeof(struct bwn_dmadesc32)));
3979}
3980
3981static void
3982bwn_dma_32_suspend(struct bwn_dma_ring *dr)
3983{
3984
3985 BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
3986 BWN_DMA_READ(dr, BWN_DMA32_TXCTL) | BWN_DMA32_TXSUSPEND);
3987}
3988
3989static void
3990bwn_dma_32_resume(struct bwn_dma_ring *dr)
3991{
3992
3993 BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
3994 BWN_DMA_READ(dr, BWN_DMA32_TXCTL) & ~BWN_DMA32_TXSUSPEND);
3995}
3996
3997static int
3998bwn_dma_32_get_curslot(struct bwn_dma_ring *dr)
3999{
4000 uint32_t val;
4001
4002 val = BWN_DMA_READ(dr, BWN_DMA32_RXSTATUS);
4003 val &= BWN_DMA32_RXDPTR;
4004
4005 return (val / sizeof(struct bwn_dmadesc32));
4006}
4007
4008static void
4009bwn_dma_32_set_curslot(struct bwn_dma_ring *dr, int slot)
4010{
4011
4012 BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX,
4013 (uint32_t) (slot * sizeof(struct bwn_dmadesc32)));
4014}
4015
4016static void
4017bwn_dma_64_getdesc(struct bwn_dma_ring *dr, int slot,
4018 struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
4019{
4020 struct bwn_dmadesc64 *desc;
4021
4022 *meta = &(dr->dr_meta[slot]);
4023 desc = dr->dr_ring_descbase;
4024 desc = &(desc[slot]);
4025
4026 *gdesc = (struct bwn_dmadesc_generic *)desc;
4027}
4028
4029static void
4030bwn_dma_64_setdesc(struct bwn_dma_ring *dr,
4031 struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
4032 int start, int end, int irq)
4033{
4034 struct bwn_dmadesc64 *descbase = dr->dr_ring_descbase;
4035 struct bwn_softc *sc = dr->dr_mac->mac_sc;
4036 int slot;
4037 uint32_t ctl0 = 0, ctl1 = 0;
4038 uint32_t addrlo, addrhi;
4039 uint32_t addrext;
4040
4041 slot = (int)(&(desc->dma.dma64) - descbase);
4042 KASSERT(slot >= 0 && slot < dr->dr_numslots,
4043 ("%s:%d: fail", __func__, __LINE__));
4044
4045 addrlo = (uint32_t) (dmaaddr & 0xffffffff);
4046 addrhi = (((uint64_t) dmaaddr >> 32) & ~SIBA_DMA_TRANSLATION_MASK);
4047 addrext = (((uint64_t) dmaaddr >> 32) & SIBA_DMA_TRANSLATION_MASK) >>
4048 30;
4049 addrhi |= (siba_dma_translation(sc->sc_dev) << 1);
4050 if (slot == dr->dr_numslots - 1)
4051 ctl0 |= BWN_DMA64_DCTL0_DTABLEEND;
4052 if (start)
4053 ctl0 |= BWN_DMA64_DCTL0_FRAMESTART;
4054 if (end)
4055 ctl0 |= BWN_DMA64_DCTL0_FRAMEEND;
4056 if (irq)
4057 ctl0 |= BWN_DMA64_DCTL0_IRQ;
4058 ctl1 |= bufsize & BWN_DMA64_DCTL1_BYTECNT;
4059 ctl1 |= (addrext << BWN_DMA64_DCTL1_ADDREXT_SHIFT)
4060 & BWN_DMA64_DCTL1_ADDREXT_MASK;
4061
4062 desc->dma.dma64.control0 = htole32(ctl0);
4063 desc->dma.dma64.control1 = htole32(ctl1);
4064 desc->dma.dma64.address_low = htole32(addrlo);
4065 desc->dma.dma64.address_high = htole32(addrhi);
4066}
4067
4068static void
4069bwn_dma_64_start_transfer(struct bwn_dma_ring *dr, int slot)
4070{
4071
4072 BWN_DMA_WRITE(dr, BWN_DMA64_TXINDEX,
4073 (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4074}
4075
4076static void
4077bwn_dma_64_suspend(struct bwn_dma_ring *dr)
4078{
4079
4080 BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
4081 BWN_DMA_READ(dr, BWN_DMA64_TXCTL) | BWN_DMA64_TXSUSPEND);
4082}
4083
4084static void
4085bwn_dma_64_resume(struct bwn_dma_ring *dr)
4086{
4087
4088 BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
4089 BWN_DMA_READ(dr, BWN_DMA64_TXCTL) & ~BWN_DMA64_TXSUSPEND);
4090}
4091
4092static int
4093bwn_dma_64_get_curslot(struct bwn_dma_ring *dr)
4094{
4095 uint32_t val;
4096
4097 val = BWN_DMA_READ(dr, BWN_DMA64_RXSTATUS);
4098 val &= BWN_DMA64_RXSTATDPTR;
4099
4100 return (val / sizeof(struct bwn_dmadesc64));
4101}
4102
4103static void
4104bwn_dma_64_set_curslot(struct bwn_dma_ring *dr, int slot)
4105{
4106
4107 BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX,
4108 (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4109}
4110
4111static int
4112bwn_dma_allocringmemory(struct bwn_dma_ring *dr)
4113{
4114 struct bwn_mac *mac = dr->dr_mac;
4115 struct bwn_dma *dma = &mac->mac_method.dma;
4116 struct bwn_softc *sc = mac->mac_sc;
4117 int error;
4118
4119 error = bus_dma_tag_create(dma->parent_dtag,
4120 BWN_ALIGN, 0,
4121 BUS_SPACE_MAXADDR,
4122 BUS_SPACE_MAXADDR,
4123 NULL, NULL,
4124 BWN_DMA_RINGMEMSIZE,
4125 1,
4126 BUS_SPACE_MAXSIZE_32BIT,
4127 0,
4128 NULL, NULL,
4129 &dr->dr_ring_dtag);
4130 if (error) {
4131 device_printf(sc->sc_dev,
4132 "can't create TX ring DMA tag: TODO frees\n");
4133 return (-1);
4134 }
4135
4136 error = bus_dmamem_alloc(dr->dr_ring_dtag,
4137 &dr->dr_ring_descbase, BUS_DMA_WAITOK | BUS_DMA_ZERO,
4138 &dr->dr_ring_dmap);
4139 if (error) {
4140 device_printf(sc->sc_dev,
4141 "can't allocate DMA mem: TODO frees\n");
4142 return (-1);
4143 }
4144 error = bus_dmamap_load(dr->dr_ring_dtag, dr->dr_ring_dmap,
4145 dr->dr_ring_descbase, BWN_DMA_RINGMEMSIZE,
4146 bwn_dma_ring_addr, &dr->dr_ring_dmabase, BUS_DMA_NOWAIT);
4147 if (error) {
4148 device_printf(sc->sc_dev,
4149 "can't load DMA mem: TODO free\n");
4150 return (-1);
4151 }
4152
4153 return (0);
4154}
4155
4156static void
4157bwn_dma_setup(struct bwn_dma_ring *dr)
4158{
4159 struct bwn_softc *sc = dr->dr_mac->mac_sc;
4160 uint64_t ring64;
4161 uint32_t addrext, ring32, value;
4162 uint32_t trans = siba_dma_translation(sc->sc_dev);
4163
4164 if (dr->dr_tx) {
4165 dr->dr_curslot = -1;
4166
4167 if (dr->dr_type == BWN_DMA_64BIT) {
4168 ring64 = (uint64_t)(dr->dr_ring_dmabase);
4169 addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK)
4170 >> 30;
4171 value = BWN_DMA64_TXENABLE;
4172 value |= (addrext << BWN_DMA64_TXADDREXT_SHIFT)
4173 & BWN_DMA64_TXADDREXT_MASK;
4174 BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL, value);
4175 BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO,
4176 (ring64 & 0xffffffff));
4177 BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI,
4178 ((ring64 >> 32) &
4179 ~SIBA_DMA_TRANSLATION_MASK) | (trans << 1));
4180 } else {
4181 ring32 = (uint32_t)(dr->dr_ring_dmabase);
4182 addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4183 value = BWN_DMA32_TXENABLE;
4184 value |= (addrext << BWN_DMA32_TXADDREXT_SHIFT)
4185 & BWN_DMA32_TXADDREXT_MASK;
4186 BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL, value);
4187 BWN_DMA_WRITE(dr, BWN_DMA32_TXRING,
4188 (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4189 }
4190 return;
4191 }
4192
4193 /*
4194 * set for RX
4195 */
4196 dr->dr_usedslot = dr->dr_numslots;
4197
4198 if (dr->dr_type == BWN_DMA_64BIT) {
4199 ring64 = (uint64_t)(dr->dr_ring_dmabase);
4200 addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK) >> 30;
4201 value = (dr->dr_frameoffset << BWN_DMA64_RXFROFF_SHIFT);
4202 value |= BWN_DMA64_RXENABLE;
4203 value |= (addrext << BWN_DMA64_RXADDREXT_SHIFT)
4204 & BWN_DMA64_RXADDREXT_MASK;
4205 BWN_DMA_WRITE(dr, BWN_DMA64_RXCTL, value);
4206 BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, (ring64 & 0xffffffff));
4207 BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI,
4208 ((ring64 >> 32) & ~SIBA_DMA_TRANSLATION_MASK)
4209 | (trans << 1));
4210 BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX, dr->dr_numslots *
4211 sizeof(struct bwn_dmadesc64));
4212 } else {
4213 ring32 = (uint32_t)(dr->dr_ring_dmabase);
4214 addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4215 value = (dr->dr_frameoffset << BWN_DMA32_RXFROFF_SHIFT);
4216 value |= BWN_DMA32_RXENABLE;
4217 value |= (addrext << BWN_DMA32_RXADDREXT_SHIFT)
4218 & BWN_DMA32_RXADDREXT_MASK;
4219 BWN_DMA_WRITE(dr, BWN_DMA32_RXCTL, value);
4220 BWN_DMA_WRITE(dr, BWN_DMA32_RXRING,
4221 (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4222 BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX, dr->dr_numslots *
4223 sizeof(struct bwn_dmadesc32));
4224 }
4225}
4226
4227static void
4228bwn_dma_free_ringmemory(struct bwn_dma_ring *dr)
4229{
4230
4231 bus_dmamap_unload(dr->dr_ring_dtag, dr->dr_ring_dmap);
4232 bus_dmamem_free(dr->dr_ring_dtag, dr->dr_ring_descbase,
4233 dr->dr_ring_dmap);
4234}
4235
4236static void
4237bwn_dma_cleanup(struct bwn_dma_ring *dr)
4238{
4239
4240 if (dr->dr_tx) {
4241 bwn_dma_tx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4242 if (dr->dr_type == BWN_DMA_64BIT) {
4243 BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO, 0);
4244 BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI, 0);
4245 } else
4246 BWN_DMA_WRITE(dr, BWN_DMA32_TXRING, 0);
4247 } else {
4248 bwn_dma_rx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4249 if (dr->dr_type == BWN_DMA_64BIT) {
4250 BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, 0);
4251 BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI, 0);
4252 } else
4253 BWN_DMA_WRITE(dr, BWN_DMA32_RXRING, 0);
4254 }
4255}
4256
4257static void
4258bwn_dma_free_descbufs(struct bwn_dma_ring *dr)
4259{
4260 struct bwn_dmadesc_generic *desc;
4261 struct bwn_dmadesc_meta *meta;
4262 struct bwn_mac *mac = dr->dr_mac;
4263 struct bwn_dma *dma = &mac->mac_method.dma;
4264 struct bwn_softc *sc = mac->mac_sc;
4265 int i;
4266
4267 if (!dr->dr_usedslot)
4268 return;
4269 for (i = 0; i < dr->dr_numslots; i++) {
4270 dr->getdesc(dr, i, &desc, &meta);
4271
4272 if (meta->mt_m == NULL) {
4273 if (!dr->dr_tx)
4274 device_printf(sc->sc_dev, "%s: not TX?\n",
4275 __func__);
4276 continue;
4277 }
4278 if (dr->dr_tx) {
4279 if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
4280 bus_dmamap_unload(dr->dr_txring_dtag,
4281 meta->mt_dmap);
4282 else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
4283 bus_dmamap_unload(dma->txbuf_dtag,
4284 meta->mt_dmap);
4285 } else
4286 bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
4287 bwn_dma_free_descbuf(dr, meta);
4288 }
4289}
4290
4291static int
4292bwn_dma_tx_reset(struct bwn_mac *mac, uint16_t base,
4293 int type)
4294{
4295 struct bwn_softc *sc = mac->mac_sc;
4296 uint32_t value;
4297 int i;
4298 uint16_t offset;
4299
4300 for (i = 0; i < 10; i++) {
4301 offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4302 BWN_DMA32_TXSTATUS;
4303 value = BWN_READ_4(mac, base + offset);
4304 if (type == BWN_DMA_64BIT) {
4305 value &= BWN_DMA64_TXSTAT;
4306 if (value == BWN_DMA64_TXSTAT_DISABLED ||
4307 value == BWN_DMA64_TXSTAT_IDLEWAIT ||
4308 value == BWN_DMA64_TXSTAT_STOPPED)
4309 break;
4310 } else {
4311 value &= BWN_DMA32_TXSTATE;
4312 if (value == BWN_DMA32_TXSTAT_DISABLED ||
4313 value == BWN_DMA32_TXSTAT_IDLEWAIT ||
4314 value == BWN_DMA32_TXSTAT_STOPPED)
4315 break;
4316 }
4317 DELAY(1000);
4318 }
4319 offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXCTL : BWN_DMA32_TXCTL;
4320 BWN_WRITE_4(mac, base + offset, 0);
4321 for (i = 0; i < 10; i++) {
4322 offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4323 BWN_DMA32_TXSTATUS;
4324 value = BWN_READ_4(mac, base + offset);
4325 if (type == BWN_DMA_64BIT) {
4326 value &= BWN_DMA64_TXSTAT;
4327 if (value == BWN_DMA64_TXSTAT_DISABLED) {
4328 i = -1;
4329 break;
4330 }
4331 } else {
4332 value &= BWN_DMA32_TXSTATE;
4333 if (value == BWN_DMA32_TXSTAT_DISABLED) {
4334 i = -1;
4335 break;
4336 }
4337 }
4338 DELAY(1000);
4339 }
4340 if (i != -1) {
4341 device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4342 return (ENODEV);
4343 }
4344 DELAY(1000);
4345
4346 return (0);
4347}
4348
4349static int
4350bwn_dma_rx_reset(struct bwn_mac *mac, uint16_t base,
4351 int type)
4352{
4353 struct bwn_softc *sc = mac->mac_sc;
4354 uint32_t value;
4355 int i;
4356 uint16_t offset;
4357
4358 offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXCTL : BWN_DMA32_RXCTL;
4359 BWN_WRITE_4(mac, base + offset, 0);
4360 for (i = 0; i < 10; i++) {
4361 offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXSTATUS :
4362 BWN_DMA32_RXSTATUS;
4363 value = BWN_READ_4(mac, base + offset);
4364 if (type == BWN_DMA_64BIT) {
4365 value &= BWN_DMA64_RXSTAT;
4366 if (value == BWN_DMA64_RXSTAT_DISABLED) {
4367 i = -1;
4368 break;
4369 }
4370 } else {
4371 value &= BWN_DMA32_RXSTATE;
4372 if (value == BWN_DMA32_RXSTAT_DISABLED) {
4373 i = -1;
4374 break;
4375 }
4376 }
4377 DELAY(1000);
4378 }
4379 if (i != -1) {
4380 device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4381 return (ENODEV);
4382 }
4383
4384 return (0);
4385}
4386
4387static void
4388bwn_dma_free_descbuf(struct bwn_dma_ring *dr,
4389 struct bwn_dmadesc_meta *meta)
4390{
4391
4392 if (meta->mt_m != NULL) {
4393 m_freem(meta->mt_m);
4394 meta->mt_m = NULL;
4395 }
4396 if (meta->mt_ni != NULL) {
4397 ieee80211_free_node(meta->mt_ni);
4398 meta->mt_ni = NULL;
4399 }
4400}
4401
4402static void
4403bwn_dma_set_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4404{
4405 struct bwn_rxhdr4 *rxhdr;
4406 unsigned char *frame;
4407
4408 rxhdr = mtod(m, struct bwn_rxhdr4 *);
4409 rxhdr->frame_len = 0;
4410
4411 KASSERT(dr->dr_rx_bufsize >= dr->dr_frameoffset +
4412 sizeof(struct bwn_plcp6) + 2,
4413 ("%s:%d: fail", __func__, __LINE__));
4414 frame = mtod(m, char *) + dr->dr_frameoffset;
4415 memset(frame, 0xff, sizeof(struct bwn_plcp6) + 2 /* padding */);
4416}
4417
4418static uint8_t
4419bwn_dma_check_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4420{
4421 unsigned char *f = mtod(m, char *) + dr->dr_frameoffset;
4422
4423 return ((f[0] & f[1] & f[2] & f[3] & f[4] & f[5] & f[6] & f[7])
4424 == 0xff);
4425}
4426
4427static void
4428bwn_wme_init(struct bwn_mac *mac)
4429{
4430
4431 bwn_wme_load(mac);
4432
4433 /* enable WME support. */
4434 bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_EDCF);
4435 BWN_WRITE_2(mac, BWN_IFSCTL, BWN_READ_2(mac, BWN_IFSCTL) |
4436 BWN_IFSCTL_USE_EDCF);
4437}
4438
4439static void
4440bwn_spu_setdelay(struct bwn_mac *mac, int idle)
4441{
4442 struct bwn_softc *sc = mac->mac_sc;
4443 struct ieee80211com *ic = sc->sc_ifp->if_l2com;
4444 uint16_t delay; /* microsec */
4445
4446 delay = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 3700 : 1050;
4447 if (ic->ic_opmode == IEEE80211_M_IBSS || idle)
4448 delay = 500;
4449 if ((mac->mac_phy.rf_ver == 0x2050) && (mac->mac_phy.rf_rev == 8))
4450 delay = max(delay, (uint16_t)2400);
4451
4452 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SPU_WAKEUP, delay);
4453}
4454
4455static void
4456bwn_bt_enable(struct bwn_mac *mac)
4457{
4458 struct bwn_softc *sc = mac->mac_sc;
4459 uint64_t hf;
4460
4461 if (bwn_bluetooth == 0)
4462 return;
4463 if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCOEXIST) == 0)
4464 return;
4465 if (mac->mac_phy.type != BWN_PHYTYPE_B && !mac->mac_phy.gmode)
4466 return;
4467
4468 hf = bwn_hf_read(mac);
4469 if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCMOD)
4470 hf |= BWN_HF_BT_COEXISTALT;
4471 else
4472 hf |= BWN_HF_BT_COEXIST;
4473 bwn_hf_write(mac, hf);
4474}
4475
4476static void
4477bwn_set_macaddr(struct bwn_mac *mac)
4478{
4479
4480 bwn_mac_write_bssid(mac);
4481 bwn_mac_setfilter(mac, BWN_MACFILTER_SELF, mac->mac_sc->sc_macaddr);
4482}
4483
4484static void
4485bwn_clear_keys(struct bwn_mac *mac)
4486{
4487 int i;
4488
4489 for (i = 0; i < mac->mac_max_nr_keys; i++) {
4490 KASSERT(i >= 0 && i < mac->mac_max_nr_keys,
4491 ("%s:%d: fail", __func__, __LINE__));
4492
4493 bwn_key_dowrite(mac, i, BWN_SEC_ALGO_NONE,
4494 NULL, BWN_SEC_KEYSIZE, NULL);
4495 if ((i <= 3) && !BWN_SEC_NEWAPI(mac)) {
4496 bwn_key_dowrite(mac, i + 4, BWN_SEC_ALGO_NONE,
4497 NULL, BWN_SEC_KEYSIZE, NULL);
4498 }
4499 mac->mac_key[i].keyconf = NULL;
4500 }
4501}
4502
4503static void
4504bwn_crypt_init(struct bwn_mac *mac)
4505{
4506 struct bwn_softc *sc = mac->mac_sc;
4507
4508 mac->mac_max_nr_keys = (siba_get_revid(sc->sc_dev) >= 5) ? 58 : 20;
4509 KASSERT(mac->mac_max_nr_keys <= N(mac->mac_key),
4510 ("%s:%d: fail", __func__, __LINE__));
4511 mac->mac_ktp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_KEY_TABLEP);
4512 mac->mac_ktp *= 2;
4513 if (siba_get_revid(sc->sc_dev) >= 5)
4514 BWN_WRITE_2(mac, BWN_RCMTA_COUNT, mac->mac_max_nr_keys - 8);
4515 bwn_clear_keys(mac);
4516}
4517
4518static void
4519bwn_chip_exit(struct bwn_mac *mac)
4520{
4521 struct bwn_softc *sc = mac->mac_sc;
4522
4523 bwn_phy_exit(mac);
4524 siba_gpio_set(sc->sc_dev, 0);
4525}
4526
4527static int
4528bwn_fw_fillinfo(struct bwn_mac *mac)
4529{
4530 int error;
4531
4532 error = bwn_fw_gets(mac, BWN_FWTYPE_DEFAULT);
4533 if (error == 0)
4534 return (0);
4535 error = bwn_fw_gets(mac, BWN_FWTYPE_OPENSOURCE);
4536 if (error == 0)
4537 return (0);
4538 return (error);
4539}
4540
4541static int
4542bwn_gpio_init(struct bwn_mac *mac)
4543{
4544 struct bwn_softc *sc = mac->mac_sc;
4545 uint32_t mask = 0x1f, set = 0xf, value;
4546
4547 BWN_WRITE_4(mac, BWN_MACCTL,
4548 BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GPOUT_MASK);
4549 BWN_WRITE_2(mac, BWN_GPIO_MASK,
4550 BWN_READ_2(mac, BWN_GPIO_MASK) | 0x000f);
4551
4552 if (siba_get_chipid(sc->sc_dev) == 0x4301) {
4553 mask |= 0x0060;
4554 set |= 0x0060;
4555 }
4556 if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL) {
4557 BWN_WRITE_2(mac, BWN_GPIO_MASK,
4558 BWN_READ_2(mac, BWN_GPIO_MASK) | 0x0200);
4559 mask |= 0x0200;
4560 set |= 0x0200;
4561 }
4562 if (siba_get_revid(sc->sc_dev) >= 2)
4563 mask |= 0x0010;
4564
4565 value = siba_gpio_get(sc->sc_dev);
4566 if (value == -1)
4567 return (0);
4568 siba_gpio_set(sc->sc_dev, (value & mask) | set);
4569
4570 return (0);
4571}
4572
4573static int
4574bwn_fw_loadinitvals(struct bwn_mac *mac)
4575{
4576#define GETFWOFFSET(fwp, offset) \
4577 ((const struct bwn_fwinitvals *)((const char *)fwp.fw->data + offset))
4578 const size_t hdr_len = sizeof(struct bwn_fwhdr);
4579 const struct bwn_fwhdr *hdr;
4580 struct bwn_fw *fw = &mac->mac_fw;
4581 int error;
4582
4583 hdr = (const struct bwn_fwhdr *)(fw->initvals.fw->data);
4584 error = bwn_fwinitvals_write(mac, GETFWOFFSET(fw->initvals, hdr_len),
4585 be32toh(hdr->size), fw->initvals.fw->datasize - hdr_len);
4586 if (error)
4587 return (error);
4588 if (fw->initvals_band.fw) {
4589 hdr = (const struct bwn_fwhdr *)(fw->initvals_band.fw->data);
4590 error = bwn_fwinitvals_write(mac,
4591 GETFWOFFSET(fw->initvals_band, hdr_len),
4592 be32toh(hdr->size),
4593 fw->initvals_band.fw->datasize - hdr_len);
4594 }
4595 return (error);
4596#undef GETFWOFFSET
4597}
4598
4599static int
4600bwn_phy_init(struct bwn_mac *mac)
4601{
4602 struct bwn_softc *sc = mac->mac_sc;
4603 int error;
4604
4605 mac->mac_phy.chan = mac->mac_phy.get_default_chan(mac);
4606 mac->mac_phy.rf_onoff(mac, 1);
4607 error = mac->mac_phy.init(mac);
4608 if (error) {
4609 device_printf(sc->sc_dev, "PHY init failed\n");
4610 goto fail0;
4611 }
4612 error = bwn_switch_channel(mac,
4613 mac->mac_phy.get_default_chan(mac));
4614 if (error) {
4615 device_printf(sc->sc_dev,
4616 "failed to switch default channel\n");
4617 goto fail1;
4618 }
4619 return (0);
4620fail1:
4621 if (mac->mac_phy.exit)
4622 mac->mac_phy.exit(mac);
4623fail0:
4624 mac->mac_phy.rf_onoff(mac, 0);
4625
4626 return (error);
4627}
4628
4629static void
4630bwn_set_txantenna(struct bwn_mac *mac, int antenna)
4631{
4632 uint16_t ant;
4633 uint16_t tmp;
4634
4635 ant = bwn_ant2phy(antenna);
4636
4637 /* For ACK/CTS */
4638 tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL);
4639 tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4640 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, tmp);
4641 /* For Probe Resposes */
4642 tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL);
4643 tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4644 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, tmp);
4645}
4646
4647static void
4648bwn_set_opmode(struct bwn_mac *mac)
4649{
4650 struct bwn_softc *sc = mac->mac_sc;
4651 struct ifnet *ifp = sc->sc_ifp;
4652 struct ieee80211com *ic = ifp->if_l2com;
4653 uint32_t ctl;
4654 uint16_t cfp_pretbtt;
4655
4656 ctl = BWN_READ_4(mac, BWN_MACCTL);
4657 ctl &= ~(BWN_MACCTL_HOSTAP | BWN_MACCTL_PASS_CTL |
4658 BWN_MACCTL_PASS_BADPLCP | BWN_MACCTL_PASS_BADFCS |
4659 BWN_MACCTL_PROMISC | BWN_MACCTL_BEACON_PROMISC);
4660 ctl |= BWN_MACCTL_STA;
4661
4662 if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
4663 ic->ic_opmode == IEEE80211_M_MBSS)
4664 ctl |= BWN_MACCTL_HOSTAP;
4665 else if (ic->ic_opmode == IEEE80211_M_IBSS)
4666 ctl &= ~BWN_MACCTL_STA;
4667 ctl |= sc->sc_filters;
4668
4669 if (siba_get_revid(sc->sc_dev) <= 4)
4670 ctl |= BWN_MACCTL_PROMISC;
4671
4672 BWN_WRITE_4(mac, BWN_MACCTL, ctl);
4673
4674 cfp_pretbtt = 2;
4675 if ((ctl & BWN_MACCTL_STA) && !(ctl & BWN_MACCTL_HOSTAP)) {
4676 if (siba_get_chipid(sc->sc_dev) == 0x4306 &&
4677 siba_get_chiprev(sc->sc_dev) == 3)
4678 cfp_pretbtt = 100;
4679 else
4680 cfp_pretbtt = 50;
4681 }
4682 BWN_WRITE_2(mac, 0x612, cfp_pretbtt);
4683}
4684
4685static int
4686bwn_dma_gettype(struct bwn_mac *mac)
4687{
4688 uint32_t tmp;
4689 uint16_t base;
4690
4691 tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
4692 if (tmp & SIBA_TGSHIGH_DMA64)
4693 return (BWN_DMA_64BIT);
4694 base = bwn_dma_base(0, 0);
4695 BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
4696 tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
4697 if (tmp & BWN_DMA32_TXADDREXT_MASK)
4698 return (BWN_DMA_32BIT);
4699
4700 return (BWN_DMA_30BIT);
4701}
4702
4703static void
4704bwn_dma_ring_addr(void *arg, bus_dma_segment_t *seg, int nseg, int error)
4705{
4706 if (!error) {
4707 KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
4708 *((bus_addr_t *)arg) = seg->ds_addr;
4709 }
4710}
4711
4712static void
4713bwn_phy_g_init_sub(struct bwn_mac *mac)
4714{
4715 struct bwn_phy *phy = &mac->mac_phy;
4716 struct bwn_phy_g *pg = &phy->phy_g;
4717 struct bwn_softc *sc = mac->mac_sc;
4718 uint16_t i, tmp;
4719
4720 if (phy->rev == 1)
4721 bwn_phy_init_b5(mac);
4722 else
4723 bwn_phy_init_b6(mac);
4724
4725 if (phy->rev >= 2 || phy->gmode)
4726 bwn_phy_init_a(mac);
4727
4728 if (phy->rev >= 2) {
4729 BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, 0);
4730 BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, 0);
4731 }
4732 if (phy->rev == 2) {
4733 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
4734 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4735 }
4736 if (phy->rev > 5) {
4737 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x400);
4738 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4739 }
4740 if (phy->gmode || phy->rev >= 2) {
4741 tmp = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
4742 tmp &= BWN_PHYVER_VERSION;
4743 if (tmp == 3 || tmp == 5) {
4744 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc2), 0x1816);
4745 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc3), 0x8006);
4746 }
4747 if (tmp == 5) {
4748 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xcc), 0x00ff,
4749 0x1f00);
4750 }
4751 }
4752 if ((phy->rev <= 2 && phy->gmode) || phy->rev >= 2)
4753 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x7e), 0x78);
4754 if (phy->rf_rev == 8) {
4755 BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x80);
4756 BWN_PHY_SET(mac, BWN_PHY_OFDM(0x3e), 0x4);
4757 }
4758 if (BWN_HAS_LOOPBACK(phy))
4759 bwn_loopback_calcgain(mac);
4760
4761 if (phy->rf_rev != 8) {
4762 if (pg->pg_initval == 0xffff)
4763 pg->pg_initval = bwn_rf_init_bcm2050(mac);
4764 else
4765 BWN_RF_WRITE(mac, 0x0078, pg->pg_initval);
4766 }
4767 bwn_lo_g_init(mac);
4768 if (BWN_HAS_TXMAG(phy)) {
4769 BWN_RF_WRITE(mac, 0x52,
4770 (BWN_RF_READ(mac, 0x52) & 0xff00)
4771 | pg->pg_loctl.tx_bias |
4772 pg->pg_loctl.tx_magn);
4773 } else {
4774 BWN_RF_SETMASK(mac, 0x52, 0xfff0, pg->pg_loctl.tx_bias);
4775 }
4776 if (phy->rev >= 6) {
4777 BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x36), 0x0fff,
4778 (pg->pg_loctl.tx_bias << 12));
4779 }
4780 if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
4781 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8075);
4782 else
4783 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x807f);
4784 if (phy->rev < 2)
4785 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x101);
4786 else
4787 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x202);
4788 if (phy->gmode || phy->rev >= 2) {
4789 bwn_lo_g_adjust(mac);
4790 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
4791 }
4792
4793 if (!(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI)) {
4794 for (i = 0; i < 64; i++) {
4795 BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, i);
4796 BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_DATA,
4797 (uint16_t)MIN(MAX(bwn_nrssi_read(mac, i) - 0xffff,
4798 -32), 31));
4799 }
4800 bwn_nrssi_threshold(mac);
4801 } else if (phy->gmode || phy->rev >= 2) {
4802 if (pg->pg_nrssi[0] == -1000) {
4803 KASSERT(pg->pg_nrssi[1] == -1000,
4804 ("%s:%d: fail", __func__, __LINE__));
4805 bwn_nrssi_slope_11g(mac);
4806 } else
4807 bwn_nrssi_threshold(mac);
4808 }
4809 if (phy->rf_rev == 8)
4810 BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x05), 0x3230);
4811 bwn_phy_hwpctl_init(mac);
4812 if ((siba_get_chipid(sc->sc_dev) == 0x4306
4813 && siba_get_chippkg(sc->sc_dev) == 2) || 0) {
4814 BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0xbfff);
4815 BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xc3), 0x7fff);
4816 }
4817}
4818
4819static uint8_t
4820bwn_has_hwpctl(struct bwn_mac *mac)
4821{
4822
4823 if (mac->mac_phy.hwpctl == 0 || mac->mac_phy.use_hwpctl == NULL)
4824 return (0);
4825 return (mac->mac_phy.use_hwpctl(mac));
4826}
4827
4828static void
4829bwn_phy_init_b5(struct bwn_mac *mac)
4830{
4831 struct bwn_phy *phy = &mac->mac_phy;
4832 struct bwn_phy_g *pg = &phy->phy_g;
4833 struct bwn_softc *sc = mac->mac_sc;
4834 uint16_t offset, value;
4835 uint8_t old_channel;
4836
4837 if (phy->analog == 1)
4838 BWN_RF_SET(mac, 0x007a, 0x0050);
4839 if ((siba_get_pci_subvendor(sc->sc_dev) != SIBA_BOARDVENDOR_BCM) &&
4840 (siba_get_pci_subdevice(sc->sc_dev) != SIBA_BOARD_BU4306)) {
4841 value = 0x2120;
4842 for (offset = 0x00a8; offset < 0x00c7; offset++) {
4843 BWN_PHY_WRITE(mac, offset, value);
4844 value += 0x202;
4845 }
4846 }
4847 BWN_PHY_SETMASK(mac, 0x0035, 0xf0ff, 0x0700);
4848 if (phy->rf_ver == 0x2050)
4849 BWN_PHY_WRITE(mac, 0x0038, 0x0667);
4850
4851 if (phy->gmode || phy->rev >= 2) {
4852 if (phy->rf_ver == 0x2050) {
4853 BWN_RF_SET(mac, 0x007a, 0x0020);
4854 BWN_RF_SET(mac, 0x0051, 0x0004);
4855 }
4856 BWN_WRITE_2(mac, BWN_PHY_RADIO, 0x0000);
4857
4858 BWN_PHY_SET(mac, 0x0802, 0x0100);
4859 BWN_PHY_SET(mac, 0x042b, 0x2000);
4860
4861 BWN_PHY_WRITE(mac, 0x001c, 0x186a);
4862
4863 BWN_PHY_SETMASK(mac, 0x0013, 0x00ff, 0x1900);
4864 BWN_PHY_SETMASK(mac, 0x0035, 0xffc0, 0x0064);
4865 BWN_PHY_SETMASK(mac, 0x005d, 0xff80, 0x000a);
4866 }
4867
4868 if (mac->mac_flags & BWN_MAC_FLAG_BADFRAME_PREEMP)
4869 BWN_PHY_SET(mac, BWN_PHY_RADIO_BITFIELD, (1 << 11));
4870
4871 if (phy->analog == 1) {
4872 BWN_PHY_WRITE(mac, 0x0026, 0xce00);
4873 BWN_PHY_WRITE(mac, 0x0021, 0x3763);
4874 BWN_PHY_WRITE(mac, 0x0022, 0x1bc3);
4875 BWN_PHY_WRITE(mac, 0x0023, 0x06f9);
4876 BWN_PHY_WRITE(mac, 0x0024, 0x037e);
4877 } else
4878 BWN_PHY_WRITE(mac, 0x0026, 0xcc00);
4879 BWN_PHY_WRITE(mac, 0x0030, 0x00c6);
4880 BWN_WRITE_2(mac, 0x03ec, 0x3f22);
4881
4882 if (phy->analog == 1)
4883 BWN_PHY_WRITE(mac, 0x0020, 0x3e1c);
4884 else
4885 BWN_PHY_WRITE(mac, 0x0020, 0x301c);
4886
4887 if (phy->analog == 0)
4888 BWN_WRITE_2(mac, 0x03e4, 0x3000);
4889
4890 old_channel = phy->chan;
4891 bwn_phy_g_switch_chan(mac, 7, 0);
4892
4893 if (phy->rf_ver != 0x2050) {
4894 BWN_RF_WRITE(mac, 0x0075, 0x0080);
4895 BWN_RF_WRITE(mac, 0x0079, 0x0081);
4896 }
4897
4898 BWN_RF_WRITE(mac, 0x0050, 0x0020);
4899 BWN_RF_WRITE(mac, 0x0050, 0x0023);
4900
4901 if (phy->rf_ver == 0x2050) {
4902 BWN_RF_WRITE(mac, 0x0050, 0x0020);
4903 BWN_RF_WRITE(mac, 0x005a, 0x0070);
4904 }
4905
4906 BWN_RF_WRITE(mac, 0x005b, 0x007b);
4907 BWN_RF_WRITE(mac, 0x005c, 0x00b0);
4908 BWN_RF_SET(mac, 0x007a, 0x0007);
4909
4910 bwn_phy_g_switch_chan(mac, old_channel, 0);
4911 BWN_PHY_WRITE(mac, 0x0014, 0x0080);
4912 BWN_PHY_WRITE(mac, 0x0032, 0x00ca);
4913 BWN_PHY_WRITE(mac, 0x002a, 0x88a3);
4914
4915 bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
4916 pg->pg_txctl);
4917
4918 if (phy->rf_ver == 0x2050)
4919 BWN_RF_WRITE(mac, 0x005d, 0x000d);
4920
4921 BWN_WRITE_2(mac, 0x03e4, (BWN_READ_2(mac, 0x03e4) & 0xffc0) | 0x0004);
4922}
4923
4924static void
4925bwn_loopback_calcgain(struct bwn_mac *mac)
4926{
4927 struct bwn_phy *phy = &mac->mac_phy;
4928 struct bwn_phy_g *pg = &phy->phy_g;
4929 struct bwn_softc *sc = mac->mac_sc;
4930 uint16_t backup_phy[16] = { 0 };
4931 uint16_t backup_radio[3];
4932 uint16_t backup_bband;
4933 uint16_t i, j, loop_i_max;
4934 uint16_t trsw_rx;
4935 uint16_t loop1_outer_done, loop1_inner_done;
4936
4937 backup_phy[0] = BWN_PHY_READ(mac, BWN_PHY_CRS0);
4938 backup_phy[1] = BWN_PHY_READ(mac, BWN_PHY_CCKBBANDCFG);
4939 backup_phy[2] = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
4940 backup_phy[3] = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
4941 if (phy->rev != 1) {
4942 backup_phy[4] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
4943 backup_phy[5] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
4944 }
4945 backup_phy[6] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
4946 backup_phy[7] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
4947 backup_phy[8] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
4948 backup_phy[9] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x0a));
4949 backup_phy[10] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x03));
4950 backup_phy[11] = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
4951 backup_phy[12] = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
4952 backup_phy[13] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2b));
4953 backup_phy[14] = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
4954 backup_phy[15] = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
4955 backup_bband = pg->pg_bbatt.att;
4956 backup_radio[0] = BWN_RF_READ(mac, 0x52);
4957 backup_radio[1] = BWN_RF_READ(mac, 0x43);
4958 backup_radio[2] = BWN_RF_READ(mac, 0x7a);
4959
4960 BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x3fff);
4961 BWN_PHY_SET(mac, BWN_PHY_CCKBBANDCFG, 0x8000);
4962 BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0002);
4963 BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffd);
4964 BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0001);
4965 BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffe);
4966 if (phy->rev != 1) {
4967 BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0001);
4968 BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffe);
4969 BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0002);
4970 BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffd);
4971 }
4972 BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x000c);
4973 BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x000c);
4974 BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0030);
4975 BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xffcf, 0x10);
4976
4977 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0780);
4978 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
4979 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
4980
4981 BWN_PHY_SET(mac, BWN_PHY_CCK(0x0a), 0x2000);
4982 if (phy->rev != 1) {
4983 BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0004);
4984 BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffb);
4985 }
4986 BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xff9f, 0x40);
4987
4988 if (phy->rf_rev == 8)
4989 BWN_RF_WRITE(mac, 0x43, 0x000f);
4990 else {
4991 BWN_RF_WRITE(mac, 0x52, 0);
4992 BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x9);
4993 }
4994 bwn_phy_g_set_bbatt(mac, 11);
4995
4996 if (phy->rev >= 3)
4997 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
4998 else
4999 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
5000 BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
5001
5002 BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xffc0, 0x01);
5003 BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xc0ff, 0x800);
5004
5005 BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0100);
5006 BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xcfff);
5007
5008 if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA) {
5009 if (phy->rev >= 7) {
5010 BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0800);
5011 BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x8000);
5012 }
5013 }
5014 BWN_RF_MASK(mac, 0x7a, 0x00f7);
5015
5016 j = 0;
5017 loop_i_max = (phy->rf_rev == 8) ? 15 : 9;
5018 for (i = 0; i < loop_i_max; i++) {
5019 for (j = 0; j < 16; j++) {
5020 BWN_RF_WRITE(mac, 0x43, i);
5021 BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff,
5022 (j << 8));
5023 BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
5024 BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
5025 DELAY(20);
5026 if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
5027 goto done0;
5028 }
5029 }
5030done0:
5031 loop1_outer_done = i;
5032 loop1_inner_done = j;
5033 if (j >= 8) {
5034 BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x30);
5035 trsw_rx = 0x1b;
5036 for (j = j - 8; j < 16; j++) {
5037 BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff, j << 8);
5038 BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
5039 BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
5040 DELAY(20);
5041 trsw_rx -= 3;
5042 if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
5043 goto done1;
5044 }
5045 } else
5046 trsw_rx = 0x18;
5047done1:
5048
5049 if (phy->rev != 1) {
5050 BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, backup_phy[4]);
5051 BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, backup_phy[5]);
5052 }
5053 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), backup_phy[6]);
5054 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), backup_phy[7]);
5055 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), backup_phy[8]);
5056 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x0a), backup_phy[9]);
5057 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x03), backup_phy[10]);
5058 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, backup_phy[11]);
5059 BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, backup_phy[12]);
5060 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), backup_phy[13]);
5061 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, backup_phy[14]);
5062
5063 bwn_phy_g_set_bbatt(mac, backup_bband);
5064
5065 BWN_RF_WRITE(mac, 0x52, backup_radio[0]);
5066 BWN_RF_WRITE(mac, 0x43, backup_radio[1]);
5067 BWN_RF_WRITE(mac, 0x7a, backup_radio[2]);
5068
5069 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2] | 0x0003);
5070 DELAY(10);
5071 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2]);
5072 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, backup_phy[3]);
5073 BWN_PHY_WRITE(mac, BWN_PHY_CRS0, backup_phy[0]);
5074 BWN_PHY_WRITE(mac, BWN_PHY_CCKBBANDCFG, backup_phy[1]);
5075
5076 pg->pg_max_lb_gain =
5077 ((loop1_inner_done * 6) - (loop1_outer_done * 4)) - 11;
5078 pg->pg_trsw_rx_gain = trsw_rx * 2;
5079}
5080
5081static uint16_t
5082bwn_rf_init_bcm2050(struct bwn_mac *mac)
5083{
5084 struct bwn_phy *phy = &mac->mac_phy;
5085 uint32_t tmp1 = 0, tmp2 = 0;
5086 uint16_t rcc, i, j, pgactl, cck0, cck1, cck2, cck3, rfover, rfoverval,
5087 analogover, analogoverval, crs0, classctl, lomask, loctl, syncctl,
5088 radio0, radio1, radio2, reg0, reg1, reg2, radio78, reg, index;
5089 static const uint8_t rcc_table[] = {
5090 0x02, 0x03, 0x01, 0x0f,
5091 0x06, 0x07, 0x05, 0x0f,
5092 0x0a, 0x0b, 0x09, 0x0f,
5093 0x0e, 0x0f, 0x0d, 0x0f,
5094 };
5095
5096 loctl = lomask = reg0 = classctl = crs0 = analogoverval = analogover =
5097 rfoverval = rfover = cck3 = 0;
5098 radio0 = BWN_RF_READ(mac, 0x43);
5099 radio1 = BWN_RF_READ(mac, 0x51);
5100 radio2 = BWN_RF_READ(mac, 0x52);
5101 pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
5102 cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
5103 cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
5104 cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
5105
5106 if (phy->type == BWN_PHYTYPE_B) {
5107 cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
5108 reg0 = BWN_READ_2(mac, 0x3ec);
5109
5110 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0xff);
5111 BWN_WRITE_2(mac, 0x3ec, 0x3f3f);
5112 } else if (phy->gmode || phy->rev >= 2) {
5113 rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
5114 rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
5115 analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
5116 analogoverval = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
5117 crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
5118 classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
5119
5120 BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
5121 BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
5122 BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
5123 BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
5124 if (BWN_HAS_LOOPBACK(phy)) {
5125 lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
5126 loctl = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
5127 if (phy->rev >= 3)
5128 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
5129 else
5130 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
5131 BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
5132 }
5133
5134 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5135 bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5136 BWN_LPD(0, 1, 1)));
5137 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
5138 bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVER, 0));
5139 }
5140 BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2) | 0x8000);
5141
5142 syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
5143 BWN_PHY_MASK(mac, BWN_PHY_SYNCCTL, 0xff7f);
5144 reg1 = BWN_READ_2(mac, 0x3e6);
5145 reg2 = BWN_READ_2(mac, 0x3f4);
5146
5147 if (phy->analog == 0)
5148 BWN_WRITE_2(mac, 0x03e6, 0x0122);
5149 else {
5150 if (phy->analog >= 2)
5151 BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xffbf, 0x40);
5152 BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
5153 (BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000));
5154 }
5155
5156 reg = BWN_RF_READ(mac, 0x60);
5157 index = (reg & 0x001e) >> 1;
5158 rcc = (((rcc_table[index] << 1) | (reg & 0x0001)) | 0x0020);
5159
5160 if (phy->type == BWN_PHYTYPE_B)
5161 BWN_RF_WRITE(mac, 0x78, 0x26);
5162 if (phy->gmode || phy->rev >= 2) {
5163 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5164 bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5165 BWN_LPD(0, 1, 1)));
5166 }
5167 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfaf);
5168 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1403);
5169 if (phy->gmode || phy->rev >= 2) {
5170 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5171 bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5172 BWN_LPD(0, 0, 1)));
5173 }
5174 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfa0);
5175 BWN_RF_SET(mac, 0x51, 0x0004);
5176 if (phy->rf_rev == 8)
5177 BWN_RF_WRITE(mac, 0x43, 0x1f);
5178 else {
5179 BWN_RF_WRITE(mac, 0x52, 0);
5180 BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x0009);
5181 }
5182 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5183
5184 for (i = 0; i < 16; i++) {
5185 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0480);
5186 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5187 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5188 if (phy->gmode || phy->rev >= 2) {
5189 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5190 bwn_rf_2050_rfoverval(mac,
5191 BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5192 }
5193 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5194 DELAY(10);
5195 if (phy->gmode || phy->rev >= 2) {
5196 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5197 bwn_rf_2050_rfoverval(mac,
5198 BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5199 }
5200 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5201 DELAY(10);
5202 if (phy->gmode || phy->rev >= 2) {
5203 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5204 bwn_rf_2050_rfoverval(mac,
5205 BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5206 }
5207 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5208 DELAY(20);
5209 tmp1 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5210 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5211 if (phy->gmode || phy->rev >= 2) {
5212 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5213 bwn_rf_2050_rfoverval(mac,
5214 BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5215 }
5216 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5217 }
5218 DELAY(10);
5219
5220 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5221 tmp1++;
5222 tmp1 >>= 9;
5223
5224 for (i = 0; i < 16; i++) {
5225 radio78 = (BWN_BITREV4(i) << 1) | 0x0020;
5226 BWN_RF_WRITE(mac, 0x78, radio78);
5227 DELAY(10);
5228 for (j = 0; j < 16; j++) {
5229 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0d80);
5230 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5231 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5232 if (phy->gmode || phy->rev >= 2) {
5233 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5234 bwn_rf_2050_rfoverval(mac,
5235 BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5236 }
5237 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5238 DELAY(10);
5239 if (phy->gmode || phy->rev >= 2) {
5240 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5241 bwn_rf_2050_rfoverval(mac,
5242 BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5243 }
5244 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5245 DELAY(10);
5246 if (phy->gmode || phy->rev >= 2) {
5247 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5248 bwn_rf_2050_rfoverval(mac,
5249 BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5250 }
5251 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5252 DELAY(10);
5253 tmp2 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5254 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
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, 1)));
5259 }
5260 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5261 }
5262 tmp2++;
5263 tmp2 >>= 8;
5264 if (tmp1 < tmp2)
5265 break;
5266 }
5267
5268 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pgactl);
5269 BWN_RF_WRITE(mac, 0x51, radio1);
5270 BWN_RF_WRITE(mac, 0x52, radio2);
5271 BWN_RF_WRITE(mac, 0x43, radio0);
5272 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), cck0);
5273 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), cck1);
5274 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), cck2);
5275 BWN_WRITE_2(mac, 0x3e6, reg1);
5276 if (phy->analog != 0)
5277 BWN_WRITE_2(mac, 0x3f4, reg2);
5278 BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, syncctl);
5279 bwn_spu_workaround(mac, phy->chan);
5280 if (phy->type == BWN_PHYTYPE_B) {
5281 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), cck3);
5282 BWN_WRITE_2(mac, 0x3ec, reg0);
5283 } else if (phy->gmode) {
5284 BWN_WRITE_2(mac, BWN_PHY_RADIO,
5285 BWN_READ_2(mac, BWN_PHY_RADIO)
5286 & 0x7fff);
5287 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover);
5288 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval);
5289 BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, analogover);
5290 BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
5291 analogoverval);
5292 BWN_PHY_WRITE(mac, BWN_PHY_CRS0, crs0);
5293 BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, classctl);
5294 if (BWN_HAS_LOOPBACK(phy)) {
5295 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, lomask);
5296 BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, loctl);
5297 }
5298 }
5299
5300 return ((i > 15) ? radio78 : rcc);
5301}
5302
5303static void
5304bwn_phy_init_b6(struct bwn_mac *mac)
5305{
5306 struct bwn_phy *phy = &mac->mac_phy;
5307 struct bwn_phy_g *pg = &phy->phy_g;
5308 struct bwn_softc *sc = mac->mac_sc;
5309 uint16_t offset, val;
5310 uint8_t old_channel;
5311
5312 KASSERT(!(phy->rf_rev == 6 || phy->rf_rev == 7),
5313 ("%s:%d: fail", __func__, __LINE__));
5314
5315 BWN_PHY_WRITE(mac, 0x003e, 0x817a);
5316 BWN_RF_WRITE(mac, 0x007a, BWN_RF_READ(mac, 0x007a) | 0x0058);
5317 if (phy->rf_rev == 4 || phy->rf_rev == 5) {
5318 BWN_RF_WRITE(mac, 0x51, 0x37);
5319 BWN_RF_WRITE(mac, 0x52, 0x70);
5320 BWN_RF_WRITE(mac, 0x53, 0xb3);
5321 BWN_RF_WRITE(mac, 0x54, 0x9b);
5322 BWN_RF_WRITE(mac, 0x5a, 0x88);
5323 BWN_RF_WRITE(mac, 0x5b, 0x88);
5324 BWN_RF_WRITE(mac, 0x5d, 0x88);
5325 BWN_RF_WRITE(mac, 0x5e, 0x88);
5326 BWN_RF_WRITE(mac, 0x7d, 0x88);
5327 bwn_hf_write(mac,
5328 bwn_hf_read(mac) | BWN_HF_TSSI_RESET_PSM_WORKAROUN);
5329 }
5330 if (phy->rf_rev == 8) {
5331 BWN_RF_WRITE(mac, 0x51, 0);
5332 BWN_RF_WRITE(mac, 0x52, 0x40);
5333 BWN_RF_WRITE(mac, 0x53, 0xb7);
5334 BWN_RF_WRITE(mac, 0x54, 0x98);
5335 BWN_RF_WRITE(mac, 0x5a, 0x88);
5336 BWN_RF_WRITE(mac, 0x5b, 0x6b);
5337 BWN_RF_WRITE(mac, 0x5c, 0x0f);
5338 if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_ALTIQ) {
5339 BWN_RF_WRITE(mac, 0x5d, 0xfa);
5340 BWN_RF_WRITE(mac, 0x5e, 0xd8);
5341 } else {
5342 BWN_RF_WRITE(mac, 0x5d, 0xf5);
5343 BWN_RF_WRITE(mac, 0x5e, 0xb8);
5344 }
5345 BWN_RF_WRITE(mac, 0x0073, 0x0003);
5346 BWN_RF_WRITE(mac, 0x007d, 0x00a8);
5347 BWN_RF_WRITE(mac, 0x007c, 0x0001);
5348 BWN_RF_WRITE(mac, 0x007e, 0x0008);
5349 }
5350 for (val = 0x1e1f, offset = 0x0088; offset < 0x0098; offset++) {
5351 BWN_PHY_WRITE(mac, offset, val);
5352 val -= 0x0202;
5353 }
5354 for (val = 0x3e3f, offset = 0x0098; offset < 0x00a8; offset++) {
5355 BWN_PHY_WRITE(mac, offset, val);
5356 val -= 0x0202;
5357 }
5358 for (val = 0x2120, offset = 0x00a8; offset < 0x00c8; offset++) {
5359 BWN_PHY_WRITE(mac, offset, (val & 0x3f3f));
5360 val += 0x0202;
5361 }
5362 if (phy->type == BWN_PHYTYPE_G) {
5363 BWN_RF_SET(mac, 0x007a, 0x0020);
5364 BWN_RF_SET(mac, 0x0051, 0x0004);
5365 BWN_PHY_SET(mac, 0x0802, 0x0100);
5366 BWN_PHY_SET(mac, 0x042b, 0x2000);
5367 BWN_PHY_WRITE(mac, 0x5b, 0);
5368 BWN_PHY_WRITE(mac, 0x5c, 0);
5369 }
5370
5371 old_channel = phy->chan;
5372 bwn_phy_g_switch_chan(mac, (old_channel >= 8) ? 1 : 13, 0);
5373
5374 BWN_RF_WRITE(mac, 0x0050, 0x0020);
5375 BWN_RF_WRITE(mac, 0x0050, 0x0023);
5376 DELAY(40);
5377 if (phy->rf_rev < 6 || phy->rf_rev == 8) {
5378 BWN_RF_WRITE(mac, 0x7c, BWN_RF_READ(mac, 0x7c) | 0x0002);
5379 BWN_RF_WRITE(mac, 0x50, 0x20);
5380 }
5381 if (phy->rf_rev <= 2) {
5382 BWN_RF_WRITE(mac, 0x7c, 0x20);
5383 BWN_RF_WRITE(mac, 0x5a, 0x70);
5384 BWN_RF_WRITE(mac, 0x5b, 0x7b);
5385 BWN_RF_WRITE(mac, 0x5c, 0xb0);
5386 }
5387 BWN_RF_SETMASK(mac, 0x007a, 0x00f8, 0x0007);
5388
5389 bwn_phy_g_switch_chan(mac, old_channel, 0);
5390
5391 BWN_PHY_WRITE(mac, 0x0014, 0x0200);
5392 if (phy->rf_rev >= 6)
5393 BWN_PHY_WRITE(mac, 0x2a, 0x88c2);
5394 else
5395 BWN_PHY_WRITE(mac, 0x2a, 0x8ac0);
5396 BWN_PHY_WRITE(mac, 0x0038, 0x0668);
5397 bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
5398 pg->pg_txctl);
5399 if (phy->rf_rev <= 5)
5400 BWN_PHY_SETMASK(mac, 0x5d, 0xff80, 0x0003);
5401 if (phy->rf_rev <= 2)
5402 BWN_RF_WRITE(mac, 0x005d, 0x000d);
5403
5404 if (phy->analog == 4) {
5405 BWN_WRITE_2(mac, 0x3e4, 9);
5406 BWN_PHY_MASK(mac, 0x61, 0x0fff);
5407 } else
5408 BWN_PHY_SETMASK(mac, 0x0002, 0xffc0, 0x0004);
5409 if (phy->type == BWN_PHYTYPE_B)
5410 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5411 else if (phy->type == BWN_PHYTYPE_G)
5412 BWN_WRITE_2(mac, 0x03e6, 0x0);
5413}
5414
5415static void
5416bwn_phy_init_a(struct bwn_mac *mac)
5417{
5418 struct bwn_phy *phy = &mac->mac_phy;
5419 struct bwn_softc *sc = mac->mac_sc;
5420
5421 KASSERT(phy->type == BWN_PHYTYPE_A || phy->type == BWN_PHYTYPE_G,
5422 ("%s:%d: fail", __func__, __LINE__));
5423
5424 if (phy->rev >= 6) {
5425 if (phy->type == BWN_PHYTYPE_A)
5426 BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x1000);
5427 if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) & BWN_PHY_ENCORE_EN)
5428 BWN_PHY_SET(mac, BWN_PHY_ENCORE, 0x0010);
5429 else
5430 BWN_PHY_MASK(mac, BWN_PHY_ENCORE, ~0x1010);
5431 }
5432
5433 bwn_wa_init(mac);
5434
5435 if (phy->type == BWN_PHYTYPE_G &&
5436 (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL))
5437 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x6e), 0xe000, 0x3cf);
5438}
5439
5440static void
5441bwn_wa_write_noisescale(struct bwn_mac *mac, const uint16_t *nst)
5442{
5443 int i;
5444
5445 for (i = 0; i < BWN_TAB_NOISESCALE_SIZE; i++)
5446 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_NOISESCALE, i, nst[i]);
5447}
5448
5449static void
5450bwn_wa_agc(struct bwn_mac *mac)
5451{
5452 struct bwn_phy *phy = &mac->mac_phy;
5453
5454 if (phy->rev == 1) {
5455 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 0, 254);
5456 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 1, 13);
5457 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 2, 19);
5458 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 3, 25);
5459 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 0, 0x2710);
5460 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 1, 0x9b83);
5461 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 2, 0x9b83);
5462 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 3, 0x0f8d);
5463 BWN_PHY_WRITE(mac, BWN_PHY_LMS, 4);
5464 } else {
5465 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 0, 254);
5466 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 1, 13);
5467 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 2, 19);
5468 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 3, 25);
5469 }
5470
5471 BWN_PHY_SETMASK(mac, BWN_PHY_CCKSHIFTBITS_WA, (uint16_t)~0xff00,
5472 0x5700);
5473 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x007f, 0x000f);
5474 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x3f80, 0x2b80);
5475 BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, 0xf0ff, 0x0300);
5476 BWN_RF_SET(mac, 0x7a, 0x0008);
5477 BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x000f, 0x0008);
5478 BWN_PHY_SETMASK(mac, BWN_PHY_P1P2GAIN, ~0x0f00, 0x0600);
5479 BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x0f00, 0x0700);
5480 BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x0f00, 0x0100);
5481 if (phy->rev == 1)
5482 BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x000f, 0x0007);
5483 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x00ff, 0x001c);
5484 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x3f00, 0x0200);
5485 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), ~0x00ff, 0x001c);
5486 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x00ff, 0x0020);
5487 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x3f00, 0x0200);
5488 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x82), ~0x00ff, 0x002e);
5489 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), (uint16_t)~0xff00, 0x1a00);
5490 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), ~0x00ff, 0x0028);
5491 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), (uint16_t)~0xff00, 0x2c00);
5492 if (phy->rev == 1) {
5493 BWN_PHY_WRITE(mac, BWN_PHY_PEAK_COUNT, 0x092b);
5494 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e, 0x0002);
5495 } else {
5496 BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e);
5497 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x1f), 0x287a);
5498 BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL, ~0x000f, 0x0004);
5499 if (phy->rev >= 6) {
5500 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x22), 0x287a);
5501 BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL,
5502 (uint16_t)~0xf000, 0x3000);
5503 }
5504 }
5505 BWN_PHY_SETMASK(mac, BWN_PHY_DIVSRCHIDX, 0x8080, 0x7874);
5506 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8e), 0x1c00);
5507 if (phy->rev == 1) {
5508 BWN_PHY_SETMASK(mac, BWN_PHY_DIVP1P2GAIN, ~0x0f00, 0x0600);
5509 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8b), 0x005e);
5510 BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, ~0x00ff, 0x001e);
5511 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8d), 0x0002);
5512 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 0, 0);
5513 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 1, 7);
5514 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 2, 16);
5515 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 3, 28);
5516 } else {
5517 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 0, 0);
5518 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 1, 7);
5519 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 2, 16);
5520 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 3, 28);
5521 }
5522 if (phy->rev >= 6) {
5523 BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x0003);
5524 BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x1000);
5525 }
5526 BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
5527}
5528
5529static void
5530bwn_wa_grev1(struct bwn_mac *mac)
5531{
5532 struct bwn_phy *phy = &mac->mac_phy;
5533 int i;
5534 static const uint16_t bwn_tab_finefreqg[] = BWN_TAB_FINEFREQ_G;
5535 static const uint32_t bwn_tab_retard[] = BWN_TAB_RETARD;
5536 static const uint32_t bwn_tab_rotor[] = BWN_TAB_ROTOR;
5537
5538 KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5539
5540 /* init CRSTHRES and ANTDWELL */
5541 if (phy->rev == 1) {
5542 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5543 } else if (phy->rev == 2) {
5544 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5545 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5546 BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5547 } else {
5548 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5549 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5550 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5551 BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5552 }
5553 BWN_PHY_SETMASK(mac, BWN_PHY_CRS0, ~0x03c0, 0xd000);
5554 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x2c), 0x005a);
5555 BWN_PHY_WRITE(mac, BWN_PHY_CCKSHIFTBITS, 0x0026);
5556
5557 /* XXX support PHY-A??? */
5558 for (i = 0; i < N(bwn_tab_finefreqg); i++)
5559 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DACRFPABB, i,
5560 bwn_tab_finefreqg[i]);
5561
5562 /* XXX support PHY-A??? */
5563 if (phy->rev == 1)
5564 for (i = 0; i < N(bwn_tab_noise_g1); i++)
5565 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5566 bwn_tab_noise_g1[i]);
5567 else
5568 for (i = 0; i < N(bwn_tab_noise_g2); i++)
5569 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5570 bwn_tab_noise_g2[i]);
5571
5572
5573 for (i = 0; i < N(bwn_tab_rotor); i++)
5574 bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ROTOR, i,
5575 bwn_tab_rotor[i]);
5576
5577 /* XXX support PHY-A??? */
5578 if (phy->rev >= 6) {
5579 if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5580 BWN_PHY_ENCORE_EN)
5581 bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5582 else
5583 bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5584 } else
5585 bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5586
5587 for (i = 0; i < N(bwn_tab_retard); i++)
5588 bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ADVRETARD, i,
5589 bwn_tab_retard[i]);
5590
5591 if (phy->rev == 1) {
5592 for (i = 0; i < 16; i++)
5593 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1,
5594 i, 0x0020);
5595 } else {
5596 for (i = 0; i < 32; i++)
5597 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5598 }
5599
5600 bwn_wa_agc(mac);
5601}
5602
5603static void
5604bwn_wa_grev26789(struct bwn_mac *mac)
5605{
5606 struct bwn_phy *phy = &mac->mac_phy;
5607 int i;
5608 static const uint16_t bwn_tab_sigmasqr2[] = BWN_TAB_SIGMASQR2;
5609 uint16_t ofdmrev;
5610
5611 KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5612
5613 bwn_gtab_write(mac, BWN_GTAB_ORIGTR, 0, 0xc480);
5614
5615 /* init CRSTHRES and ANTDWELL */
5616 if (phy->rev == 1)
5617 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5618 else if (phy->rev == 2) {
5619 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5620 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5621 BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5622 } else {
5623 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5624 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5625 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5626 BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5627 }
5628
5629 for (i = 0; i < 64; i++)
5630 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_RSSI, i, i);
5631
5632 /* XXX support PHY-A??? */
5633 if (phy->rev == 1)
5634 for (i = 0; i < N(bwn_tab_noise_g1); i++)
5635 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5636 bwn_tab_noise_g1[i]);
5637 else
5638 for (i = 0; i < N(bwn_tab_noise_g2); i++)
5639 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5640 bwn_tab_noise_g2[i]);
5641
5642 /* XXX support PHY-A??? */
5643 if (phy->rev >= 6) {
5644 if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5645 BWN_PHY_ENCORE_EN)
5646 bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5647 else
5648 bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5649 } else
5650 bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5651
5652 for (i = 0; i < N(bwn_tab_sigmasqr2); i++)
5653 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_MINSIGSQ, i,
5654 bwn_tab_sigmasqr2[i]);
5655
5656 if (phy->rev == 1) {
5657 for (i = 0; i < 16; i++)
5658 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1, i,
5659 0x0020);
5660 } else {
5661 for (i = 0; i < 32; i++)
5662 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5663 }
5664
5665 bwn_wa_agc(mac);
5666
5667 ofdmrev = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM) & BWN_PHYVER_VERSION;
5668 if (ofdmrev > 2) {
5669 if (phy->type == BWN_PHYTYPE_A)
5670 BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1808);
5671 else
5672 BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1000);
5673 } else {
5674 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 3, 0x1044);
5675 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 4, 0x7201);
5676 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 6, 0x0040);
5677 }
5678
5679 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 2, 15);
5680 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 3, 20);
5681}
5682
5683static void
5684bwn_wa_init(struct bwn_mac *mac)
5685{
5686 struct bwn_phy *phy = &mac->mac_phy;
5687 struct bwn_softc *sc = mac->mac_sc;
5688
5689 KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5690
5691 switch (phy->rev) {
5692 case 1:
5693 bwn_wa_grev1(mac);
5694 break;
5695 case 2:
5696 case 6:
5697 case 7:
5698 case 8:
5699 case 9:
5700 bwn_wa_grev26789(mac);
5701 break;
5702 default:
5703 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5704 }
5705
5706 if (siba_get_pci_subvendor(sc->sc_dev) != SIBA_BOARDVENDOR_BCM ||
5707 siba_get_pci_subdevice(sc->sc_dev) != SIBA_BOARD_BU4306 ||
5708 siba_get_pci_revid(sc->sc_dev) != 0x17) {
5709 if (phy->rev < 2) {
5710 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 1,
5711 0x0002);
5712 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 2,
5713 0x0001);
5714 } else {
5715 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 1, 0x0002);
5716 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 2, 0x0001);
5717 if ((siba_sprom_get_bf_lo(sc->sc_dev) &
5718 BWN_BFL_EXTLNA) &&
5719 (phy->rev >= 7)) {
5720 BWN_PHY_MASK(mac, BWN_PHY_EXTG(0x11), 0xf7ff);
5721 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5722 0x0020, 0x0001);
5723 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5724 0x0021, 0x0001);
5725 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5726 0x0022, 0x0001);
5727 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5728 0x0023, 0x0000);
5729 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5730 0x0000, 0x0000);
5731 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5732 0x0003, 0x0002);
5733 }
5734 }
5735 }
5736 if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM) {
5737 BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, 0x3120);
5738 BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, 0xc480);
5739 }
5740
5741 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 0, 0);
5742 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 1, 0);
5743}
5744
5745static void
5746bwn_ofdmtab_write_2(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5747 uint16_t value)
5748{
5749 struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5750 uint16_t addr;
5751
5752 addr = table + offset;
5753 if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5754 (addr - 1 != pg->pg_ofdmtab_addr)) {
5755 BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5756 pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5757 }
5758 pg->pg_ofdmtab_addr = addr;
5759 BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5760}
5761
5762static void
5763bwn_ofdmtab_write_4(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5764 uint32_t value)
5765{
5766 struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5767 uint16_t addr;
5768
5769 addr = table + offset;
5770 if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5771 (addr - 1 != pg->pg_ofdmtab_addr)) {
5772 BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5773 pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5774 }
5775 pg->pg_ofdmtab_addr = addr;
5776
5777 BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5778 BWN_PHY_WRITE(mac, BWN_PHY_OTABLEQ, (value >> 16));
5779}
5780
5781static void
5782bwn_gtab_write(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5783 uint16_t value)
5784{
5785
5786 BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, table + offset);
5787 BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, value);
5788}
5789
5790static void
5791bwn_dummy_transmission(struct bwn_mac *mac, int ofdm, int paon)
5792{
5793 struct bwn_phy *phy = &mac->mac_phy;
5794 struct bwn_softc *sc = mac->mac_sc;
5795 unsigned int i, max_loop;
5796 uint16_t value;
5797 uint32_t buffer[5] = {
5798 0x00000000, 0x00d40000, 0x00000000, 0x01000000, 0x00000000
5799 };
5800
5801 if (ofdm) {
5802 max_loop = 0x1e;
5803 buffer[0] = 0x000201cc;
5804 } else {
5805 max_loop = 0xfa;
5806 buffer[0] = 0x000b846e;
5807 }
5808
5809 BWN_ASSERT_LOCKED(mac->mac_sc);
5810
5811 for (i = 0; i < 5; i++)
5812 bwn_ram_write(mac, i * 4, buffer[i]);
5813
5814 BWN_WRITE_2(mac, 0x0568, 0x0000);
5815 BWN_WRITE_2(mac, 0x07c0,
5816 (siba_get_revid(sc->sc_dev) < 11) ? 0x0000 : 0x0100);
5817 value = ((phy->type == BWN_PHYTYPE_A) ? 0x41 : 0x40);
5818 BWN_WRITE_2(mac, 0x050c, value);
5819 if (phy->type == BWN_PHYTYPE_LP)
5820 BWN_WRITE_2(mac, 0x0514, 0x1a02);
5821 BWN_WRITE_2(mac, 0x0508, 0x0000);
5822 BWN_WRITE_2(mac, 0x050a, 0x0000);
5823 BWN_WRITE_2(mac, 0x054c, 0x0000);
5824 BWN_WRITE_2(mac, 0x056a, 0x0014);
5825 BWN_WRITE_2(mac, 0x0568, 0x0826);
5826 BWN_WRITE_2(mac, 0x0500, 0x0000);
5827 if (phy->type == BWN_PHYTYPE_LP)
5828 BWN_WRITE_2(mac, 0x0502, 0x0050);
5829 else
5830 BWN_WRITE_2(mac, 0x0502, 0x0030);
5831
5832 if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5833 BWN_RF_WRITE(mac, 0x0051, 0x0017);
5834 for (i = 0x00; i < max_loop; i++) {
5835 value = BWN_READ_2(mac, 0x050e);
5836 if (value & 0x0080)
5837 break;
5838 DELAY(10);
5839 }
5840 for (i = 0x00; i < 0x0a; i++) {
5841 value = BWN_READ_2(mac, 0x050e);
5842 if (value & 0x0400)
5843 break;
5844 DELAY(10);
5845 }
5846 for (i = 0x00; i < 0x19; i++) {
5847 value = BWN_READ_2(mac, 0x0690);
5848 if (!(value & 0x0100))
5849 break;
5850 DELAY(10);
5851 }
5852 if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5853 BWN_RF_WRITE(mac, 0x0051, 0x0037);
5854}
5855
5856static void
5857bwn_ram_write(struct bwn_mac *mac, uint16_t offset, uint32_t val)
5858{
5859 uint32_t macctl;
5860
5861 KASSERT(offset % 4 == 0, ("%s:%d: fail", __func__, __LINE__));
5862
5863 macctl = BWN_READ_4(mac, BWN_MACCTL);
5864 if (macctl & BWN_MACCTL_BIGENDIAN)
5865 printf("TODO: need swap\n");
5866
5867 BWN_WRITE_4(mac, BWN_RAM_CONTROL, offset);
5868 BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
5869 BWN_WRITE_4(mac, BWN_RAM_DATA, val);
5870}
5871
5872static void
5873bwn_lo_write(struct bwn_mac *mac, struct bwn_loctl *ctl)
5874{
5875 uint16_t value;
5876
5877 KASSERT(mac->mac_phy.type == BWN_PHYTYPE_G,
5878 ("%s:%d: fail", __func__, __LINE__));
5879
5880 value = (uint8_t) (ctl->q);
5881 value |= ((uint8_t) (ctl->i)) << 8;
5882 BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, value);
5883}
5884
5885static uint16_t
5886bwn_lo_calcfeed(struct bwn_mac *mac,
5887 uint16_t lna, uint16_t pga, uint16_t trsw_rx)
5888{
5889 struct bwn_phy *phy = &mac->mac_phy;
5890 struct bwn_softc *sc = mac->mac_sc;
5891 uint16_t rfover;
5892 uint16_t feedthrough;
5893
5894 if (phy->gmode) {
5895 lna <<= BWN_PHY_RFOVERVAL_LNA_SHIFT;
5896 pga <<= BWN_PHY_RFOVERVAL_PGA_SHIFT;
5897
5898 KASSERT((lna & ~BWN_PHY_RFOVERVAL_LNA) == 0,
5899 ("%s:%d: fail", __func__, __LINE__));
5900 KASSERT((pga & ~BWN_PHY_RFOVERVAL_PGA) == 0,
5901 ("%s:%d: fail", __func__, __LINE__));
5902
5903 trsw_rx &= (BWN_PHY_RFOVERVAL_TRSWRX | BWN_PHY_RFOVERVAL_BW);
5904
5905 rfover = BWN_PHY_RFOVERVAL_UNK | pga | lna | trsw_rx;
5906 if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA) &&
5907 phy->rev > 6)
5908 rfover |= BWN_PHY_RFOVERVAL_EXTLNA;
5909
5910 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
5911 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5912 DELAY(10);
5913 rfover |= BWN_PHY_RFOVERVAL_BW_LBW;
5914 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5915 DELAY(10);
5916 rfover |= BWN_PHY_RFOVERVAL_BW_LPF;
5917 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5918 DELAY(10);
5919 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xf300);
5920 } else {
5921 pga |= BWN_PHY_PGACTL_UNKNOWN;
5922 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5923 DELAY(10);
5924 pga |= BWN_PHY_PGACTL_LOWBANDW;
5925 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5926 DELAY(10);
5927 pga |= BWN_PHY_PGACTL_LPF;
5928 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5929 }
5930 DELAY(21);
5931 feedthrough = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5932
5933 return (feedthrough);
5934}
5935
5936static uint16_t
5937bwn_lo_txctl_regtable(struct bwn_mac *mac,
5938 uint16_t *value, uint16_t *pad_mix_gain)
5939{
5940 struct bwn_phy *phy = &mac->mac_phy;
5941 uint16_t reg, v, padmix;
5942
5943 if (phy->type == BWN_PHYTYPE_B) {
5944 v = 0x30;
5945 if (phy->rf_rev <= 5) {
5946 reg = 0x43;
5947 padmix = 0;
5948 } else {
5949 reg = 0x52;
5950 padmix = 5;
5951 }
5952 } else {
5953 if (phy->rev >= 2 && phy->rf_rev == 8) {
5954 reg = 0x43;
5955 v = 0x10;
5956 padmix = 2;
5957 } else {
5958 reg = 0x52;
5959 v = 0x30;
5960 padmix = 5;
5961 }
5962 }
5963 if (value)
5964 *value = v;
5965 if (pad_mix_gain)
5966 *pad_mix_gain = padmix;
5967
5968 return (reg);
5969}
5970
5971static void
5972bwn_lo_measure_txctl_values(struct bwn_mac *mac)
5973{
5974 struct bwn_phy *phy = &mac->mac_phy;
5975 struct bwn_phy_g *pg = &phy->phy_g;
5976 struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
5977 uint16_t reg, mask;
5978 uint16_t trsw_rx, pga;
5979 uint16_t rf_pctl_reg;
5980
5981 static const uint8_t tx_bias_values[] = {
5982 0x09, 0x08, 0x0a, 0x01, 0x00,
5983 0x02, 0x05, 0x04, 0x06,
5984 };
5985 static const uint8_t tx_magn_values[] = {
5986 0x70, 0x40,
5987 };
5988
5989 if (!BWN_HAS_LOOPBACK(phy)) {
5990 rf_pctl_reg = 6;
5991 trsw_rx = 2;
5992 pga = 0;
5993 } else {
5994 int lb_gain;
5995
5996 trsw_rx = 0;
5997 lb_gain = pg->pg_max_lb_gain / 2;
5998 if (lb_gain > 10) {
5999 rf_pctl_reg = 0;
6000 pga = abs(10 - lb_gain) / 6;
6001 pga = MIN(MAX(pga, 0), 15);
6002 } else {
6003 int cmp_val;
6004 int tmp;
6005
6006 pga = 0;
6007 cmp_val = 0x24;
6008 if ((phy->rev >= 2) &&
6009 (phy->rf_ver == 0x2050) && (phy->rf_rev == 8))
6010 cmp_val = 0x3c;
6011 tmp = lb_gain;
6012 if ((10 - lb_gain) < cmp_val)
6013 tmp = (10 - lb_gain);
6014 if (tmp < 0)
6015 tmp += 6;
6016 else
6017 tmp += 3;
6018 cmp_val /= 4;
6019 tmp /= 4;
6020 if (tmp >= cmp_val)
6021 rf_pctl_reg = cmp_val;
6022 else
6023 rf_pctl_reg = tmp;
6024 }
6025 }
6026 BWN_RF_SETMASK(mac, 0x43, 0xfff0, rf_pctl_reg);
6027 bwn_phy_g_set_bbatt(mac, 2);
6028
6029 reg = bwn_lo_txctl_regtable(mac, &mask, NULL);
6030 mask = ~mask;
6031 BWN_RF_MASK(mac, reg, mask);
6032
6033 if (BWN_HAS_TXMAG(phy)) {
6034 int i, j;
6035 int feedthrough;
6036 int min_feedth = 0xffff;
6037 uint8_t tx_magn, tx_bias;
6038
6039 for (i = 0; i < N(tx_magn_values); i++) {
6040 tx_magn = tx_magn_values[i];
6041 BWN_RF_SETMASK(mac, 0x52, 0xff0f, tx_magn);
6042 for (j = 0; j < N(tx_bias_values); j++) {
6043 tx_bias = tx_bias_values[j];
6044 BWN_RF_SETMASK(mac, 0x52, 0xfff0, tx_bias);
6045 feedthrough = bwn_lo_calcfeed(mac, 0, pga,
6046 trsw_rx);
6047 if (feedthrough < min_feedth) {
6048 lo->tx_bias = tx_bias;
6049 lo->tx_magn = tx_magn;
6050 min_feedth = feedthrough;
6051 }
6052 if (lo->tx_bias == 0)
6053 break;
6054 }
6055 BWN_RF_WRITE(mac, 0x52,
6056 (BWN_RF_READ(mac, 0x52)
6057 & 0xff00) | lo->tx_bias | lo->
6058 tx_magn);
6059 }
6060 } else {
6061 lo->tx_magn = 0;
6062 lo->tx_bias = 0;
6063 BWN_RF_MASK(mac, 0x52, 0xfff0);
6064 }
6065
6066 BWN_GETTIME(lo->txctl_measured_time);
6067}
6068
6069static void
6070bwn_lo_get_powervector(struct bwn_mac *mac)
6071{
6072 struct bwn_phy *phy = &mac->mac_phy;
6073 struct bwn_phy_g *pg = &phy->phy_g;
6074 struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6075 int i;
6076 uint64_t tmp;
6077 uint64_t power_vector = 0;
6078
6079 for (i = 0; i < 8; i += 2) {
6080 tmp = bwn_shm_read_2(mac, BWN_SHARED, 0x310 + i);
6081 power_vector |= (tmp << (i * 8));
6082 bwn_shm_write_2(mac, BWN_SHARED, 0x310 + i, 0);
6083 }
6084 if (power_vector)
6085 lo->power_vector = power_vector;
6086
6087 BWN_GETTIME(lo->pwr_vec_read_time);
6088}
6089
6090static void
6091bwn_lo_measure_gain_values(struct bwn_mac *mac, int16_t max_rx_gain,
6092 int use_trsw_rx)
6093{
6094 struct bwn_phy *phy = &mac->mac_phy;
6095 struct bwn_phy_g *pg = &phy->phy_g;
6096 uint16_t tmp;
6097
6098 if (max_rx_gain < 0)
6099 max_rx_gain = 0;
6100
6101 if (BWN_HAS_LOOPBACK(phy)) {
6102 int trsw_rx = 0;
6103 int trsw_rx_gain;
6104
6105 if (use_trsw_rx) {
6106 trsw_rx_gain = pg->pg_trsw_rx_gain / 2;
6107 if (max_rx_gain >= trsw_rx_gain) {
6108 trsw_rx_gain = max_rx_gain - trsw_rx_gain;
6109 trsw_rx = 0x20;
6110 }
6111 } else
6112 trsw_rx_gain = max_rx_gain;
6113 if (trsw_rx_gain < 9) {
6114 pg->pg_lna_lod_gain = 0;
6115 } else {
6116 pg->pg_lna_lod_gain = 1;
6117 trsw_rx_gain -= 8;
6118 }
6119 trsw_rx_gain = MIN(MAX(trsw_rx_gain, 0), 0x2d);
6120 pg->pg_pga_gain = trsw_rx_gain / 3;
6121 if (pg->pg_pga_gain >= 5) {
6122 pg->pg_pga_gain -= 5;
6123 pg->pg_lna_gain = 2;
6124 } else
6125 pg->pg_lna_gain = 0;
6126 } else {
6127 pg->pg_lna_gain = 0;
6128 pg->pg_trsw_rx_gain = 0x20;
6129 if (max_rx_gain >= 0x14) {
6130 pg->pg_lna_lod_gain = 1;
6131 pg->pg_pga_gain = 2;
6132 } else if (max_rx_gain >= 0x12) {
6133 pg->pg_lna_lod_gain = 1;
6134 pg->pg_pga_gain = 1;
6135 } else if (max_rx_gain >= 0xf) {
6136 pg->pg_lna_lod_gain = 1;
6137 pg->pg_pga_gain = 0;
6138 } else {
6139 pg->pg_lna_lod_gain = 0;
6140 pg->pg_pga_gain = 0;
6141 }
6142 }
6143
6144 tmp = BWN_RF_READ(mac, 0x7a);
6145 if (pg->pg_lna_lod_gain == 0)
6146 tmp &= ~0x0008;
6147 else
6148 tmp |= 0x0008;
6149 BWN_RF_WRITE(mac, 0x7a, tmp);
6150}
6151
6152static void
6153bwn_lo_save(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6154{
6155 struct bwn_phy *phy = &mac->mac_phy;
6156 struct bwn_phy_g *pg = &phy->phy_g;
6157 struct bwn_softc *sc = mac->mac_sc;
6158 struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6159 struct timespec ts;
6160 uint16_t tmp;
6161
6162 if (bwn_has_hwpctl(mac)) {
6163 sav->phy_lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
6164 sav->phy_extg = BWN_PHY_READ(mac, BWN_PHY_EXTG(0x01));
6165 sav->phy_dacctl_hwpctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6166 sav->phy_cck4 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x14));
6167 sav->phy_hpwr_tssictl = BWN_PHY_READ(mac, BWN_PHY_HPWR_TSSICTL);
6168
6169 BWN_PHY_SET(mac, BWN_PHY_HPWR_TSSICTL, 0x100);
6170 BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x40);
6171 BWN_PHY_SET(mac, BWN_PHY_DACCTL, 0x40);
6172 BWN_PHY_SET(mac, BWN_PHY_CCK(0x14), 0x200);
6173 }
6174 if (phy->type == BWN_PHYTYPE_B &&
6175 phy->rf_ver == 0x2050 && phy->rf_rev < 6) {
6176 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x16), 0x410);
6177 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x17), 0x820);
6178 }
6179 if (phy->rev >= 2) {
6180 sav->phy_analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
6181 sav->phy_analogoverval =
6182 BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
6183 sav->phy_rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
6184 sav->phy_rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
6185 sav->phy_classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
6186 sav->phy_cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x3e));
6187 sav->phy_crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
6188
6189 BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
6190 BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
6191 BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
6192 BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
6193 if (phy->type == BWN_PHYTYPE_G) {
6194 if ((phy->rev >= 7) &&
6195 (siba_sprom_get_bf_lo(sc->sc_dev) &
6196 BWN_BFL_EXTLNA)) {
6197 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x933);
6198 } else {
6199 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x133);
6200 }
6201 } else {
6202 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
6203 }
6204 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), 0);
6205 }
6206 sav->reg0 = BWN_READ_2(mac, 0x3f4);
6207 sav->reg1 = BWN_READ_2(mac, 0x3e2);
6208 sav->rf0 = BWN_RF_READ(mac, 0x43);
6209 sav->rf1 = BWN_RF_READ(mac, 0x7a);
6210 sav->phy_pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
6211 sav->phy_cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2a));
6212 sav->phy_syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
6213 sav->phy_dacctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6214
6215 if (!BWN_HAS_TXMAG(phy)) {
6216 sav->rf2 = BWN_RF_READ(mac, 0x52);
6217 sav->rf2 &= 0x00f0;
6218 }
6219 if (phy->type == BWN_PHYTYPE_B) {
6220 sav->phy_cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
6221 sav->phy_cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x06));
6222 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0x00ff);
6223 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), 0x3f3f);
6224 } else {
6225 BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2)
6226 | 0x8000);
6227 }
6228 BWN_WRITE_2(mac, 0x3f4, BWN_READ_2(mac, 0x3f4)
6229 & 0xf000);
6230
6231 tmp =
6232 (phy->type == BWN_PHYTYPE_G) ? BWN_PHY_LO_MASK : BWN_PHY_CCK(0x2e);
6233 BWN_PHY_WRITE(mac, tmp, 0x007f);
6234
6235 tmp = sav->phy_syncctl;
6236 BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, tmp & 0xff7f);
6237 tmp = sav->rf1;
6238 BWN_RF_WRITE(mac, 0x007a, tmp & 0xfff0);
6239
6240 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), 0x8a3);
6241 if (phy->type == BWN_PHYTYPE_G ||
6242 (phy->type == BWN_PHYTYPE_B &&
6243 phy->rf_ver == 0x2050 && phy->rf_rev >= 6)) {
6244 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1003);
6245 } else
6246 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x0802);
6247 if (phy->rev >= 2)
6248 bwn_dummy_transmission(mac, 0, 1);
6249 bwn_phy_g_switch_chan(mac, 6, 0);
6250 BWN_RF_READ(mac, 0x51);
6251 if (phy->type == BWN_PHYTYPE_G)
6252 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0);
6253
6254 nanouptime(&ts);
6255 if (time_before(lo->txctl_measured_time,
6256 (ts.tv_nsec / 1000000 + ts.tv_sec * 1000) - BWN_LO_TXCTL_EXPIRE))
6257 bwn_lo_measure_txctl_values(mac);
6258
6259 if (phy->type == BWN_PHYTYPE_G && phy->rev >= 3)
6260 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc078);
6261 else {
6262 if (phy->type == BWN_PHYTYPE_B)
6263 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6264 else
6265 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
6266 }
6267}
6268
6269static void
6270bwn_lo_restore(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6271{
6272 struct bwn_phy *phy = &mac->mac_phy;
6273 struct bwn_phy_g *pg = &phy->phy_g;
6274 uint16_t tmp;
6275
6276 if (phy->rev >= 2) {
6277 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
6278 tmp = (pg->pg_pga_gain << 8);
6279 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa0);
6280 DELAY(5);
6281 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa2);
6282 DELAY(2);
6283 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa3);
6284 } else {
6285 tmp = (pg->pg_pga_gain | 0xefa0);
6286 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, tmp);
6287 }
6288 if (phy->type == BWN_PHYTYPE_G) {
6289 if (phy->rev >= 3)
6290 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0xc078);
6291 else
6292 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6293 if (phy->rev >= 2)
6294 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0202);
6295 else
6296 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0101);
6297 }
6298 BWN_WRITE_2(mac, 0x3f4, sav->reg0);
6299 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, sav->phy_pgactl);
6300 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), sav->phy_cck2);
6301 BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, sav->phy_syncctl);
6302 BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl);
6303 BWN_RF_WRITE(mac, 0x43, sav->rf0);
6304 BWN_RF_WRITE(mac, 0x7a, sav->rf1);
6305 if (!BWN_HAS_TXMAG(phy)) {
6306 tmp = sav->rf2;
6307 BWN_RF_SETMASK(mac, 0x52, 0xff0f, tmp);
6308 }
6309 BWN_WRITE_2(mac, 0x3e2, sav->reg1);
6310 if (phy->type == BWN_PHYTYPE_B &&
6311 phy->rf_ver == 0x2050 && phy->rf_rev <= 5) {
6312 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), sav->phy_cck0);
6313 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), sav->phy_cck1);
6314 }
6315 if (phy->rev >= 2) {
6316 BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, sav->phy_analogover);
6317 BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
6318 sav->phy_analogoverval);
6319 BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, sav->phy_classctl);
6320 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, sav->phy_rfover);
6321 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, sav->phy_rfoverval);
6322 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), sav->phy_cck3);
6323 BWN_PHY_WRITE(mac, BWN_PHY_CRS0, sav->phy_crs0);
6324 }
6325 if (bwn_has_hwpctl(mac)) {
6326 tmp = (sav->phy_lomask & 0xbfff);
6327 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, tmp);
6328 BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x01), sav->phy_extg);
6329 BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl_hwpctl);
6330 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x14), sav->phy_cck4);
6331 BWN_PHY_WRITE(mac, BWN_PHY_HPWR_TSSICTL, sav->phy_hpwr_tssictl);
6332 }
6333 bwn_phy_g_switch_chan(mac, sav->old_channel, 1);
6334}
6335
6336static int
6337bwn_lo_probe_loctl(struct bwn_mac *mac,
6338 struct bwn_loctl *probe, struct bwn_lo_g_sm *d)
6339{
6340 struct bwn_phy *phy = &mac->mac_phy;
6341 struct bwn_phy_g *pg = &phy->phy_g;
6342 struct bwn_loctl orig, test;
6343 struct bwn_loctl prev = { -100, -100 };
6344 static const struct bwn_loctl modifiers[] = {
6345 { 1, 1,}, { 1, 0,}, { 1, -1,}, { 0, -1,},
6346 { -1, -1,}, { -1, 0,}, { -1, 1,}, { 0, 1,}
6347 };
6348 int begin, end, lower = 0, i;
6349 uint16_t feedth;
6350
6351 if (d->curstate == 0) {
6352 begin = 1;
6353 end = 8;
6354 } else if (d->curstate % 2 == 0) {
6355 begin = d->curstate - 1;
6356 end = d->curstate + 1;
6357 } else {
6358 begin = d->curstate - 2;
6359 end = d->curstate + 2;
6360 }
6361 if (begin < 1)
6362 begin += 8;
6363 if (end > 8)
6364 end -= 8;
6365
6366 memcpy(&orig, probe, sizeof(struct bwn_loctl));
6367 i = begin;
6368 d->curstate = i;
6369 while (1) {
6370 KASSERT(i >= 1 && i <= 8, ("%s:%d: fail", __func__, __LINE__));
6371 memcpy(&test, &orig, sizeof(struct bwn_loctl));
6372 test.i += modifiers[i - 1].i * d->multipler;
6373 test.q += modifiers[i - 1].q * d->multipler;
6374 if ((test.i != prev.i || test.q != prev.q) &&
6375 (abs(test.i) <= 16 && abs(test.q) <= 16)) {
6376 bwn_lo_write(mac, &test);
6377 feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6378 pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6379 if (feedth < d->feedth) {
6380 memcpy(probe, &test,
6381 sizeof(struct bwn_loctl));
6382 lower = 1;
6383 d->feedth = feedth;
6384 if (d->nmeasure < 2 && !BWN_HAS_LOOPBACK(phy))
6385 break;
6386 }
6387 }
6388 memcpy(&prev, &test, sizeof(prev));
6389 if (i == end)
6390 break;
6391 if (i == 8)
6392 i = 1;
6393 else
6394 i++;
6395 d->curstate = i;
6396 }
6397
6398 return (lower);
6399}
6400
6401static void
6402bwn_lo_probe_sm(struct bwn_mac *mac, struct bwn_loctl *loctl, int *rxgain)
6403{
6404 struct bwn_phy *phy = &mac->mac_phy;
6405 struct bwn_phy_g *pg = &phy->phy_g;
6406 struct bwn_lo_g_sm d;
6407 struct bwn_loctl probe;
6408 int lower, repeat, cnt = 0;
6409 uint16_t feedth;
6410
6411 d.nmeasure = 0;
6412 d.multipler = 1;
6413 if (BWN_HAS_LOOPBACK(phy))
6414 d.multipler = 3;
6415
6416 memcpy(&d.loctl, loctl, sizeof(struct bwn_loctl));
6417 repeat = (BWN_HAS_LOOPBACK(phy)) ? 4 : 1;
6418
6419 do {
6420 bwn_lo_write(mac, &d.loctl);
6421 feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6422 pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6423 if (feedth < 0x258) {
6424 if (feedth >= 0x12c)
6425 *rxgain += 6;
6426 else
6427 *rxgain += 3;
6428 feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6429 pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6430 }
6431 d.feedth = feedth;
6432 d.curstate = 0;
6433 do {
6434 KASSERT(d.curstate >= 0 && d.curstate <= 8,
6435 ("%s:%d: fail", __func__, __LINE__));
6436 memcpy(&probe, &d.loctl,
6437 sizeof(struct bwn_loctl));
6438 lower = bwn_lo_probe_loctl(mac, &probe, &d);
6439 if (!lower)
6440 break;
6441 if ((probe.i == d.loctl.i) && (probe.q == d.loctl.q))
6442 break;
6443 memcpy(&d.loctl, &probe, sizeof(struct bwn_loctl));
6444 d.nmeasure++;
6445 } while (d.nmeasure < 24);
6446 memcpy(loctl, &d.loctl, sizeof(struct bwn_loctl));
6447
6448 if (BWN_HAS_LOOPBACK(phy)) {
6449 if (d.feedth > 0x1194)
6450 *rxgain -= 6;
6451 else if (d.feedth < 0x5dc)
6452 *rxgain += 3;
6453 if (cnt == 0) {
6454 if (d.feedth <= 0x5dc) {
6455 d.multipler = 1;
6456 cnt++;
6457 } else
6458 d.multipler = 2;
6459 } else if (cnt == 2)
6460 d.multipler = 1;
6461 }
6462 bwn_lo_measure_gain_values(mac, *rxgain, BWN_HAS_LOOPBACK(phy));
6463 } while (++cnt < repeat);
6464}
6465
6466static struct bwn_lo_calib *
6467bwn_lo_calibset(struct bwn_mac *mac,
6468 const struct bwn_bbatt *bbatt, const struct bwn_rfatt *rfatt)
6469{
6470 struct bwn_phy *phy = &mac->mac_phy;
6471 struct bwn_phy_g *pg = &phy->phy_g;
6472 struct bwn_loctl loctl = { 0, 0 };
6473 struct bwn_lo_calib *cal;
6474 struct bwn_lo_g_value sval = { 0 };
6475 int rxgain;
6476 uint16_t pad, reg, value;
6477
6478 sval.old_channel = phy->chan;
6479 bwn_mac_suspend(mac);
6480 bwn_lo_save(mac, &sval);
6481
6482 reg = bwn_lo_txctl_regtable(mac, &value, &pad);
6483 BWN_RF_SETMASK(mac, 0x43, 0xfff0, rfatt->att);
6484 BWN_RF_SETMASK(mac, reg, ~value, (rfatt->padmix ? value :0));
6485
6486 rxgain = (rfatt->att * 2) + (bbatt->att / 2);
6487 if (rfatt->padmix)
6488 rxgain -= pad;
6489 if (BWN_HAS_LOOPBACK(phy))
6490 rxgain += pg->pg_max_lb_gain;
6491 bwn_lo_measure_gain_values(mac, rxgain, BWN_HAS_LOOPBACK(phy));
6492 bwn_phy_g_set_bbatt(mac, bbatt->att);
6493 bwn_lo_probe_sm(mac, &loctl, &rxgain);
6494
6495 bwn_lo_restore(mac, &sval);
6496 bwn_mac_enable(mac);
6497
6498 cal = malloc(sizeof(*cal), M_DEVBUF, M_NOWAIT | M_ZERO);
6499 if (!cal) {
6500 device_printf(mac->mac_sc->sc_dev, "out of memory\n");
6501 return (NULL);
6502 }
6503 memcpy(&cal->bbatt, bbatt, sizeof(*bbatt));
6504 memcpy(&cal->rfatt, rfatt, sizeof(*rfatt));
6505 memcpy(&cal->ctl, &loctl, sizeof(loctl));
6506
6507 BWN_GETTIME(cal->calib_time);
6508
6509 return (cal);
6510}
6511
6512static struct bwn_lo_calib *
6513bwn_lo_get_calib(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
6514 const struct bwn_rfatt *rfatt)
6515{
6516 struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
6517 struct bwn_lo_calib *c;
6518
6519 TAILQ_FOREACH(c, &lo->calib_list, list) {
6520 if (!BWN_BBATTCMP(&c->bbatt, bbatt))
6521 continue;
6522 if (!BWN_RFATTCMP(&c->rfatt, rfatt))
6523 continue;
6524 return (c);
6525 }
6526
6527 c = bwn_lo_calibset(mac, bbatt, rfatt);
6528 if (!c)
6529 return (NULL);
6530 TAILQ_INSERT_TAIL(&lo->calib_list, c, list);
6531
6532 return (c);
6533}
6534
6535static void
6536bwn_phy_g_dc_lookup_init(struct bwn_mac *mac, uint8_t update)
6537{
6538 struct bwn_phy *phy = &mac->mac_phy;
6539 struct bwn_phy_g *pg = &phy->phy_g;
6540 struct bwn_softc *sc = mac->mac_sc;
6541 struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6542 const struct bwn_rfatt *rfatt;
6543 const struct bwn_bbatt *bbatt;
6544 uint64_t pvector;
6545 int i;
6546 int rf_offset, bb_offset;
6547 uint8_t changed = 0;
6548
6549 KASSERT(BWN_DC_LT_SIZE == 32, ("%s:%d: fail", __func__, __LINE__));
6550 KASSERT(lo->rfatt.len * lo->bbatt.len <= 64,
6551 ("%s:%d: fail", __func__, __LINE__));
6552
6553 pvector = lo->power_vector;
6554 if (!update && !pvector)
6555 return;
6556
6557 bwn_mac_suspend(mac);
6558
6559 for (i = 0; i < BWN_DC_LT_SIZE * 2; i++) {
6560 struct bwn_lo_calib *cal;
6561 int idx;
6562 uint16_t val;
6563
6564 if (!update && !(pvector & (((uint64_t)1ULL) << i)))
6565 continue;
6566 bb_offset = i / lo->rfatt.len;
6567 rf_offset = i % lo->rfatt.len;
6568 bbatt = &(lo->bbatt.array[bb_offset]);
6569 rfatt = &(lo->rfatt.array[rf_offset]);
6570
6571 cal = bwn_lo_calibset(mac, bbatt, rfatt);
6572 if (!cal) {
6573 device_printf(sc->sc_dev, "LO: Could not "
6574 "calibrate DC table entry\n");
6575 continue;
6576 }
6577 val = (uint8_t)(cal->ctl.q);
6578 val |= ((uint8_t)(cal->ctl.i)) << 4;
6579 free(cal, M_DEVBUF);
6580
6581 idx = i / 2;
6582 if (i % 2)
6583 lo->dc_lt[idx] = (lo->dc_lt[idx] & 0x00ff)
6584 | ((val & 0x00ff) << 8);
6585 else
6586 lo->dc_lt[idx] = (lo->dc_lt[idx] & 0xff00)
6587 | (val & 0x00ff);
6588 changed = 1;
6589 }
6590 if (changed) {
6591 for (i = 0; i < BWN_DC_LT_SIZE; i++)
6592 BWN_PHY_WRITE(mac, 0x3a0 + i, lo->dc_lt[i]);
6593 }
6594 bwn_mac_enable(mac);
6595}
6596
6597static void
6598bwn_lo_fixup_rfatt(struct bwn_rfatt *rf)
6599{
6600
6601 if (!rf->padmix)
6602 return;
6603 if ((rf->att != 1) && (rf->att != 2) && (rf->att != 3))
6604 rf->att = 4;
6605}
6606
6607static void
6608bwn_lo_g_adjust(struct bwn_mac *mac)
6609{
6610 struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
6611 struct bwn_lo_calib *cal;
6612 struct bwn_rfatt rf;
6613
6614 memcpy(&rf, &pg->pg_rfatt, sizeof(rf));
6615 bwn_lo_fixup_rfatt(&rf);
6616
6617 cal = bwn_lo_get_calib(mac, &pg->pg_bbatt, &rf);
6618 if (!cal)
6619 return;
6620 bwn_lo_write(mac, &cal->ctl);
6621}
6622
6623static void
6624bwn_lo_g_init(struct bwn_mac *mac)
6625{
6626
6627 if (!bwn_has_hwpctl(mac))
6628 return;
6629
6630 bwn_lo_get_powervector(mac);
6631 bwn_phy_g_dc_lookup_init(mac, 1);
6632}
6633
6634static void
6635bwn_mac_suspend(struct bwn_mac *mac)
6636{
6637 struct bwn_softc *sc = mac->mac_sc;
6638 int i;
6639 uint32_t tmp;
6640
6641 KASSERT(mac->mac_suspended >= 0,
6642 ("%s:%d: fail", __func__, __LINE__));
6643
6644 if (mac->mac_suspended == 0) {
6645 bwn_psctl(mac, BWN_PS_AWAKE);
6646 BWN_WRITE_4(mac, BWN_MACCTL,
6647 BWN_READ_4(mac, BWN_MACCTL)
6648 & ~BWN_MACCTL_ON);
6649 BWN_READ_4(mac, BWN_MACCTL);
6650 for (i = 35; i; i--) {
6651 tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6652 if (tmp & BWN_INTR_MAC_SUSPENDED)
6653 goto out;
6654 DELAY(10);
6655 }
6656 for (i = 40; i; i--) {
6657 tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6658 if (tmp & BWN_INTR_MAC_SUSPENDED)
6659 goto out;
6660 DELAY(1000);
6661 }
6662 device_printf(sc->sc_dev, "MAC suspend failed\n");
6663 }
6664out:
6665 mac->mac_suspended++;
6666}
6667
6668static void
6669bwn_mac_enable(struct bwn_mac *mac)
6670{
6671 struct bwn_softc *sc = mac->mac_sc;
6672 uint16_t state;
6673
6674 state = bwn_shm_read_2(mac, BWN_SHARED,
6675 BWN_SHARED_UCODESTAT);
6676 if (state != BWN_SHARED_UCODESTAT_SUSPEND &&
6677 state != BWN_SHARED_UCODESTAT_SLEEP)
6678 device_printf(sc->sc_dev, "warn: firmware state (%d)\n", state);
6679
6680 mac->mac_suspended--;
6681 KASSERT(mac->mac_suspended >= 0,
6682 ("%s:%d: fail", __func__, __LINE__));
6683 if (mac->mac_suspended == 0) {
6684 BWN_WRITE_4(mac, BWN_MACCTL,
6685 BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_ON);
6686 BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_MAC_SUSPENDED);
6687 BWN_READ_4(mac, BWN_MACCTL);
6688 BWN_READ_4(mac, BWN_INTR_REASON);
6689 bwn_psctl(mac, 0);
6690 }
6691}
6692
6693static void
6694bwn_psctl(struct bwn_mac *mac, uint32_t flags)
6695{
6696 struct bwn_softc *sc = mac->mac_sc;
6697 int i;
6698 uint16_t ucstat;
6699
6700 KASSERT(!((flags & BWN_PS_ON) && (flags & BWN_PS_OFF)),
6701 ("%s:%d: fail", __func__, __LINE__));
6702 KASSERT(!((flags & BWN_PS_AWAKE) && (flags & BWN_PS_ASLEEP)),
6703 ("%s:%d: fail", __func__, __LINE__));
6704
6705 /* XXX forcibly awake and hwps-off */
6706
6707 BWN_WRITE_4(mac, BWN_MACCTL,
6708 (BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_AWAKE) &
6709 ~BWN_MACCTL_HWPS);
6710 BWN_READ_4(mac, BWN_MACCTL);
6711 if (siba_get_revid(sc->sc_dev) >= 5) {
6712 for (i = 0; i < 100; i++) {
6713 ucstat = bwn_shm_read_2(mac, BWN_SHARED,
6714 BWN_SHARED_UCODESTAT);
6715 if (ucstat != BWN_SHARED_UCODESTAT_SLEEP)
6716 break;
6717 DELAY(10);
6718 }
6719 }
6720}
6721
6722static int16_t
6723bwn_nrssi_read(struct bwn_mac *mac, uint16_t offset)
6724{
6725
6726 BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, offset);
6727 return ((int16_t)BWN_PHY_READ(mac, BWN_PHY_NRSSI_DATA));
6728}
6729
6730static void
6731bwn_nrssi_threshold(struct bwn_mac *mac)
6732{
6733 struct bwn_phy *phy = &mac->mac_phy;
6734 struct bwn_phy_g *pg = &phy->phy_g;
6735 struct bwn_softc *sc = mac->mac_sc;
6736 int32_t a, b;
6737 int16_t tmp16;
6738 uint16_t tmpu16;
6739
6740 KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
6741
6742 if (phy->gmode && (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI)) {
6743 if (!pg->pg_aci_wlan_automatic && pg->pg_aci_enable) {
6744 a = 0x13;
6745 b = 0x12;
6746 } else {
6747 a = 0xe;
6748 b = 0x11;
6749 }
6750
6751 a = a * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6752 a += (pg->pg_nrssi[0] << 6);
6753 a += (a < 32) ? 31 : 32;
6754 a = a >> 6;
6755 a = MIN(MAX(a, -31), 31);
6756
6757 b = b * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6758 b += (pg->pg_nrssi[0] << 6);
6759 if (b < 32)
6760 b += 31;
6761 else
6762 b += 32;
6763 b = b >> 6;
6764 b = MIN(MAX(b, -31), 31);
6765
6766 tmpu16 = BWN_PHY_READ(mac, 0x048a) & 0xf000;
6767 tmpu16 |= ((uint32_t)b & 0x0000003f);
6768 tmpu16 |= (((uint32_t)a & 0x0000003f) << 6);
6769 BWN_PHY_WRITE(mac, 0x048a, tmpu16);
6770 return;
6771 }
6772
6773 tmp16 = bwn_nrssi_read(mac, 0x20);
6774 if (tmp16 >= 0x20)
6775 tmp16 -= 0x40;
6776 BWN_PHY_SETMASK(mac, 0x048a, 0xf000, (tmp16 < 3) ? 0x09eb : 0x0aed);
6777}
6778
6779static void
6780bwn_nrssi_slope_11g(struct bwn_mac *mac)
6781{
6782#define SAVE_RF_MAX 3
6783#define SAVE_PHY_COMM_MAX 4
6784#define SAVE_PHY3_MAX 8
6785 static const uint16_t save_rf_regs[SAVE_RF_MAX] =
6786 { 0x7a, 0x52, 0x43 };
6787 static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] =
6788 { 0x15, 0x5a, 0x59, 0x58 };
6789 static const uint16_t save_phy3_regs[SAVE_PHY3_MAX] = {
6790 0x002e, 0x002f, 0x080f, BWN_PHY_G_LOCTL,
6791 0x0801, 0x0060, 0x0014, 0x0478
6792 };
6793 struct bwn_phy *phy = &mac->mac_phy;
6794 struct bwn_phy_g *pg = &phy->phy_g;
6795 int32_t i, tmp32, phy3_idx = 0;
6796 uint16_t delta, tmp;
6797 uint16_t save_rf[SAVE_RF_MAX];
6798 uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
6799 uint16_t save_phy3[SAVE_PHY3_MAX];
6800 uint16_t ant_div, phy0, chan_ex;
6801 int16_t nrssi0, nrssi1;
6802
6803 KASSERT(phy->type == BWN_PHYTYPE_G,
6804 ("%s:%d: fail", __func__, __LINE__));
6805
6806 if (phy->rf_rev >= 9)
6807 return;
6808 if (phy->rf_rev == 8)
6809 bwn_nrssi_offset(mac);
6810
6811 BWN_PHY_MASK(mac, BWN_PHY_G_CRS, 0x7fff);
6812 BWN_PHY_MASK(mac, 0x0802, 0xfffc);
6813
6814 /*
6815 * Save RF/PHY registers for later restoration
6816 */
6817 ant_div = BWN_READ_2(mac, 0x03e2);
6818 BWN_WRITE_2(mac, 0x03e2, BWN_READ_2(mac, 0x03e2) | 0x8000);
6819 for (i = 0; i < SAVE_RF_MAX; ++i)
6820 save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
6821 for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6822 save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
6823
6824 phy0 = BWN_READ_2(mac, BWN_PHY0);
6825 chan_ex = BWN_READ_2(mac, BWN_CHANNEL_EXT);
6826 if (phy->rev >= 3) {
6827 for (i = 0; i < SAVE_PHY3_MAX; ++i)
6828 save_phy3[i] = BWN_PHY_READ(mac, save_phy3_regs[i]);
6829 BWN_PHY_WRITE(mac, 0x002e, 0);
6830 BWN_PHY_WRITE(mac, BWN_PHY_G_LOCTL, 0);
6831 switch (phy->rev) {
6832 case 4:
6833 case 6:
6834 case 7:
6835 BWN_PHY_SET(mac, 0x0478, 0x0100);
6836 BWN_PHY_SET(mac, 0x0801, 0x0040);
6837 break;
6838 case 3:
6839 case 5:
6840 BWN_PHY_MASK(mac, 0x0801, 0xffbf);
6841 break;
6842 }
6843 BWN_PHY_SET(mac, 0x0060, 0x0040);
6844 BWN_PHY_SET(mac, 0x0014, 0x0200);
6845 }
6846 /*
6847 * Calculate nrssi0
6848 */
6849 BWN_RF_SET(mac, 0x007a, 0x0070);
6850 bwn_set_all_gains(mac, 0, 8, 0);
6851 BWN_RF_MASK(mac, 0x007a, 0x00f7);
6852 if (phy->rev >= 2) {
6853 BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0030);
6854 BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0010);
6855 }
6856 BWN_RF_SET(mac, 0x007a, 0x0080);
6857 DELAY(20);
6858
6859 nrssi0 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6860 if (nrssi0 >= 0x0020)
6861 nrssi0 -= 0x0040;
6862
6863 /*
6864 * Calculate nrssi1
6865 */
6866 BWN_RF_MASK(mac, 0x007a, 0x007f);
6867 if (phy->rev >= 2)
6868 BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
6869
6870 BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
6871 BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000);
6872 BWN_RF_SET(mac, 0x007a, 0x000f);
6873 BWN_PHY_WRITE(mac, 0x0015, 0xf330);
6874 if (phy->rev >= 2) {
6875 BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0020);
6876 BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0020);
6877 }
6878
6879 bwn_set_all_gains(mac, 3, 0, 1);
6880 if (phy->rf_rev == 8) {
6881 BWN_RF_WRITE(mac, 0x0043, 0x001f);
6882 } else {
6883 tmp = BWN_RF_READ(mac, 0x0052) & 0xff0f;
6884 BWN_RF_WRITE(mac, 0x0052, tmp | 0x0060);
6885 tmp = BWN_RF_READ(mac, 0x0043) & 0xfff0;
6886 BWN_RF_WRITE(mac, 0x0043, tmp | 0x0009);
6887 }
6888 BWN_PHY_WRITE(mac, 0x005a, 0x0480);
6889 BWN_PHY_WRITE(mac, 0x0059, 0x0810);
6890 BWN_PHY_WRITE(mac, 0x0058, 0x000d);
6891 DELAY(20);
6892 nrssi1 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6893
6894 /*
6895 * Install calculated narrow RSSI values
6896 */
6897 if (nrssi1 >= 0x0020)
6898 nrssi1 -= 0x0040;
6899 if (nrssi0 == nrssi1)
6900 pg->pg_nrssi_slope = 0x00010000;
6901 else
6902 pg->pg_nrssi_slope = 0x00400000 / (nrssi0 - nrssi1);
6903 if (nrssi0 >= -4) {
6904 pg->pg_nrssi[0] = nrssi1;
6905 pg->pg_nrssi[1] = nrssi0;
6906 }
6907
6908 /*
6909 * Restore saved RF/PHY registers
6910 */
6911 if (phy->rev >= 3) {
6912 for (phy3_idx = 0; phy3_idx < 4; ++phy3_idx) {
6913 BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
6914 save_phy3[phy3_idx]);
6915 }
6916 }
6917 if (phy->rev >= 2) {
6918 BWN_PHY_MASK(mac, 0x0812, 0xffcf);
6919 BWN_PHY_MASK(mac, 0x0811, 0xffcf);
6920 }
6921
6922 for (i = 0; i < SAVE_RF_MAX; ++i)
6923 BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
6924
6925 BWN_WRITE_2(mac, 0x03e2, ant_div);
6926 BWN_WRITE_2(mac, 0x03e6, phy0);
6927 BWN_WRITE_2(mac, BWN_CHANNEL_EXT, chan_ex);
6928
6929 for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6930 BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
6931
6932 bwn_spu_workaround(mac, phy->chan);
6933 BWN_PHY_SET(mac, 0x0802, (0x0001 | 0x0002));
6934 bwn_set_original_gains(mac);
6935 BWN_PHY_SET(mac, BWN_PHY_G_CRS, 0x8000);
6936 if (phy->rev >= 3) {
6937 for (; phy3_idx < SAVE_PHY3_MAX; ++phy3_idx) {
6938 BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
6939 save_phy3[phy3_idx]);
6940 }
6941 }
6942
6943 delta = 0x1f - pg->pg_nrssi[0];
6944 for (i = 0; i < 64; i++) {
6945 tmp32 = (((i - delta) * pg->pg_nrssi_slope) / 0x10000) + 0x3a;
6946 tmp32 = MIN(MAX(tmp32, 0), 0x3f);
6947 pg->pg_nrssi_lt[i] = tmp32;
6948 }
6949
6950 bwn_nrssi_threshold(mac);
6951#undef SAVE_RF_MAX
6952#undef SAVE_PHY_COMM_MAX
6953#undef SAVE_PHY3_MAX
6954}
6955
6956static void
6957bwn_nrssi_offset(struct bwn_mac *mac)
6958{
6959#define SAVE_RF_MAX 2
6960#define SAVE_PHY_COMM_MAX 10
6961#define SAVE_PHY6_MAX 8
6962 static const uint16_t save_rf_regs[SAVE_RF_MAX] =
6963 { 0x7a, 0x43 };
6964 static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] = {
6965 0x0001, 0x0811, 0x0812, 0x0814,
6966 0x0815, 0x005a, 0x0059, 0x0058,
6967 0x000a, 0x0003
6968 };
6969 static const uint16_t save_phy6_regs[SAVE_PHY6_MAX] = {
6970 0x002e, 0x002f, 0x080f, 0x0810,
6971 0x0801, 0x0060, 0x0014, 0x0478
6972 };
6973 struct bwn_phy *phy = &mac->mac_phy;
6974 int i, phy6_idx = 0;
6975 uint16_t save_rf[SAVE_RF_MAX];
6976 uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
6977 uint16_t save_phy6[SAVE_PHY6_MAX];
6978 int16_t nrssi;
6979 uint16_t saved = 0xffff;
6980
6981 for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6982 save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
6983 for (i = 0; i < SAVE_RF_MAX; ++i)
6984 save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
6985
6986 BWN_PHY_MASK(mac, 0x0429, 0x7fff);
6987 BWN_PHY_SETMASK(mac, 0x0001, 0x3fff, 0x4000);
6988 BWN_PHY_SET(mac, 0x0811, 0x000c);
6989 BWN_PHY_SETMASK(mac, 0x0812, 0xfff3, 0x0004);
6990 BWN_PHY_MASK(mac, 0x0802, ~(0x1 | 0x2));
6991 if (phy->rev >= 6) {
6992 for (i = 0; i < SAVE_PHY6_MAX; ++i)
6993 save_phy6[i] = BWN_PHY_READ(mac, save_phy6_regs[i]);
6994
6995 BWN_PHY_WRITE(mac, 0x002e, 0);
6996 BWN_PHY_WRITE(mac, 0x002f, 0);
6997 BWN_PHY_WRITE(mac, 0x080f, 0);
6998 BWN_PHY_WRITE(mac, 0x0810, 0);
6999 BWN_PHY_SET(mac, 0x0478, 0x0100);
7000 BWN_PHY_SET(mac, 0x0801, 0x0040);
7001 BWN_PHY_SET(mac, 0x0060, 0x0040);
7002 BWN_PHY_SET(mac, 0x0014, 0x0200);
7003 }
7004 BWN_RF_SET(mac, 0x007a, 0x0070);
7005 BWN_RF_SET(mac, 0x007a, 0x0080);
7006 DELAY(30);
7007
7008 nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
7009 if (nrssi >= 0x20)
7010 nrssi -= 0x40;
7011 if (nrssi == 31) {
7012 for (i = 7; i >= 4; i--) {
7013 BWN_RF_WRITE(mac, 0x007b, i);
7014 DELAY(20);
7015 nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) &
7016 0x003f);
7017 if (nrssi >= 0x20)
7018 nrssi -= 0x40;
7019 if (nrssi < 31 && saved == 0xffff)
7020 saved = i;
7021 }
7022 if (saved == 0xffff)
7023 saved = 4;
7024 } else {
7025 BWN_RF_MASK(mac, 0x007a, 0x007f);
7026 if (phy->rev != 1) {
7027 BWN_PHY_SET(mac, 0x0814, 0x0001);
7028 BWN_PHY_MASK(mac, 0x0815, 0xfffe);
7029 }
7030 BWN_PHY_SET(mac, 0x0811, 0x000c);
7031 BWN_PHY_SET(mac, 0x0812, 0x000c);
7032 BWN_PHY_SET(mac, 0x0811, 0x0030);
7033 BWN_PHY_SET(mac, 0x0812, 0x0030);
7034 BWN_PHY_WRITE(mac, 0x005a, 0x0480);
7035 BWN_PHY_WRITE(mac, 0x0059, 0x0810);
7036 BWN_PHY_WRITE(mac, 0x0058, 0x000d);
7037 if (phy->rev == 0)
7038 BWN_PHY_WRITE(mac, 0x0003, 0x0122);
7039 else
7040 BWN_PHY_SET(mac, 0x000a, 0x2000);
7041 if (phy->rev != 1) {
7042 BWN_PHY_SET(mac, 0x0814, 0x0004);
7043 BWN_PHY_MASK(mac, 0x0815, 0xfffb);
7044 }
7045 BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
7046 BWN_RF_SET(mac, 0x007a, 0x000f);
7047 bwn_set_all_gains(mac, 3, 0, 1);
7048 BWN_RF_SETMASK(mac, 0x0043, 0x00f0, 0x000f);
7049 DELAY(30);
7050 nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
7051 if (nrssi >= 0x20)
7052 nrssi -= 0x40;
7053 if (nrssi == -32) {
7054 for (i = 0; i < 4; i++) {
7055 BWN_RF_WRITE(mac, 0x007b, i);
7056 DELAY(20);
7057 nrssi = (int16_t)((BWN_PHY_READ(mac,
7058 0x047f) >> 8) & 0x003f);
7059 if (nrssi >= 0x20)
7060 nrssi -= 0x40;
7061 if (nrssi > -31 && saved == 0xffff)
7062 saved = i;
7063 }
7064 if (saved == 0xffff)
7065 saved = 3;
7066 } else
7067 saved = 0;
7068 }
7069 BWN_RF_WRITE(mac, 0x007b, saved);
7070
7071 /*
7072 * Restore saved RF/PHY registers
7073 */
7074 if (phy->rev >= 6) {
7075 for (phy6_idx = 0; phy6_idx < 4; ++phy6_idx) {
7076 BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
7077 save_phy6[phy6_idx]);
7078 }
7079 }
7080 if (phy->rev != 1) {
7081 for (i = 3; i < 5; i++)
7082 BWN_PHY_WRITE(mac, save_phy_comm_regs[i],
7083 save_phy_comm[i]);
7084 }
7085 for (i = 5; i < SAVE_PHY_COMM_MAX; i++)
7086 BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
7087
7088 for (i = SAVE_RF_MAX - 1; i >= 0; --i)
7089 BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
7090
7091 BWN_PHY_WRITE(mac, 0x0802, BWN_PHY_READ(mac, 0x0802) | 0x1 | 0x2);
7092 BWN_PHY_SET(mac, 0x0429, 0x8000);
7093 bwn_set_original_gains(mac);
7094 if (phy->rev >= 6) {
7095 for (; phy6_idx < SAVE_PHY6_MAX; ++phy6_idx) {
7096 BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
7097 save_phy6[phy6_idx]);
7098 }
7099 }
7100
7101 BWN_PHY_WRITE(mac, save_phy_comm_regs[0], save_phy_comm[0]);
7102 BWN_PHY_WRITE(mac, save_phy_comm_regs[2], save_phy_comm[2]);
7103 BWN_PHY_WRITE(mac, save_phy_comm_regs[1], save_phy_comm[1]);
7104}
7105
7106static void
7107bwn_set_all_gains(struct bwn_mac *mac, int16_t first, int16_t second,
7108 int16_t third)
7109{
7110 struct bwn_phy *phy = &mac->mac_phy;
7111 uint16_t i;
7112 uint16_t start = 0x08, end = 0x18;
7113 uint16_t tmp;
7114 uint16_t table;
7115
7116 if (phy->rev <= 1) {
7117 start = 0x10;
7118 end = 0x20;
7119 }
7120
7121 table = BWN_OFDMTAB_GAINX;
7122 if (phy->rev <= 1)
7123 table = BWN_OFDMTAB_GAINX_R1;
7124 for (i = 0; i < 4; i++)
7125 bwn_ofdmtab_write_2(mac, table, i, first);
7126
7127 for (i = start; i < end; i++)
7128 bwn_ofdmtab_write_2(mac, table, i, second);
7129
7130 if (third != -1) {
7131 tmp = ((uint16_t) third << 14) | ((uint16_t) third << 6);
7132 BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, tmp);
7133 BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, tmp);
7134 BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, tmp);
7135 }
7136 bwn_dummy_transmission(mac, 0, 1);
7137}
7138
7139static void
7140bwn_set_original_gains(struct bwn_mac *mac)
7141{
7142 struct bwn_phy *phy = &mac->mac_phy;
7143 uint16_t i, tmp;
7144 uint16_t table;
7145 uint16_t start = 0x0008, end = 0x0018;
7146
7147 if (phy->rev <= 1) {
7148 start = 0x0010;
7149 end = 0x0020;
7150 }
7151
7152 table = BWN_OFDMTAB_GAINX;
7153 if (phy->rev <= 1)
7154 table = BWN_OFDMTAB_GAINX_R1;
7155 for (i = 0; i < 4; i++) {
7156 tmp = (i & 0xfffc);
7157 tmp |= (i & 0x0001) << 1;
7158 tmp |= (i & 0x0002) >> 1;
7159
7160 bwn_ofdmtab_write_2(mac, table, i, tmp);
7161 }
7162
7163 for (i = start; i < end; i++)
7164 bwn_ofdmtab_write_2(mac, table, i, i - start);
7165
7166 BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, 0x4040);
7167 BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, 0x4040);
7168 BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, 0x4000);
7169 bwn_dummy_transmission(mac, 0, 1);
7170}
7171
7172static void
7173bwn_phy_hwpctl_init(struct bwn_mac *mac)
7174{
7175 struct bwn_phy *phy = &mac->mac_phy;
7176 struct bwn_phy_g *pg = &phy->phy_g;
7177 struct bwn_rfatt old_rfatt, rfatt;
7178 struct bwn_bbatt old_bbatt, bbatt;
7179 struct bwn_softc *sc = mac->mac_sc;
7180 uint8_t old_txctl = 0;
7181
7182 KASSERT(phy->type == BWN_PHYTYPE_G,
7183 ("%s:%d: fail", __func__, __LINE__));
7184
7185 if ((siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM) &&
7186 (siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306))
7187 return;
7188
7189 BWN_PHY_WRITE(mac, 0x0028, 0x8018);
7190
7191 BWN_WRITE_2(mac, BWN_PHY0, BWN_READ_2(mac, BWN_PHY0) & 0xffdf);
7192
7193 if (!phy->gmode)
7194 return;
7195 bwn_hwpctl_early_init(mac);
7196 if (pg->pg_curtssi == 0) {
7197 if (phy->rf_ver == 0x2050 && phy->analog == 0) {
7198 BWN_RF_SETMASK(mac, 0x0076, 0x00f7, 0x0084);
7199 } else {
7200 memcpy(&old_rfatt, &pg->pg_rfatt, sizeof(old_rfatt));
7201 memcpy(&old_bbatt, &pg->pg_bbatt, sizeof(old_bbatt));
7202 old_txctl = pg->pg_txctl;
7203
7204 bbatt.att = 11;
7205 if (phy->rf_rev == 8) {
7206 rfatt.att = 15;
7207 rfatt.padmix = 1;
7208 } else {
7209 rfatt.att = 9;
7210 rfatt.padmix = 0;
7211 }
7212 bwn_phy_g_set_txpwr_sub(mac, &bbatt, &rfatt, 0);
7213 }
7214 bwn_dummy_transmission(mac, 0, 1);
7215 pg->pg_curtssi = BWN_PHY_READ(mac, BWN_PHY_TSSI);
7216 if (phy->rf_ver == 0x2050 && phy->analog == 0)
7217 BWN_RF_MASK(mac, 0x0076, 0xff7b);
7218 else
7219 bwn_phy_g_set_txpwr_sub(mac, &old_bbatt,
7220 &old_rfatt, old_txctl);
7221 }
7222 bwn_hwpctl_init_gphy(mac);
7223
7224 /* clear TSSI */
7225 bwn_shm_write_2(mac, BWN_SHARED, 0x0058, 0x7f7f);
7226 bwn_shm_write_2(mac, BWN_SHARED, 0x005a, 0x7f7f);
7227 bwn_shm_write_2(mac, BWN_SHARED, 0x0070, 0x7f7f);
7228 bwn_shm_write_2(mac, BWN_SHARED, 0x0072, 0x7f7f);
7229}
7230
7231static void
7232bwn_hwpctl_early_init(struct bwn_mac *mac)
7233{
7234 struct bwn_phy *phy = &mac->mac_phy;
7235
7236 if (!bwn_has_hwpctl(mac)) {
7237 BWN_PHY_WRITE(mac, 0x047a, 0xc111);
7238 return;
7239 }
7240
7241 BWN_PHY_MASK(mac, 0x0036, 0xfeff);
7242 BWN_PHY_WRITE(mac, 0x002f, 0x0202);
7243 BWN_PHY_SET(mac, 0x047c, 0x0002);
7244 BWN_PHY_SET(mac, 0x047a, 0xf000);
7245 if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
7246 BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7247 BWN_PHY_SET(mac, 0x005d, 0x8000);
7248 BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7249 BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7250 BWN_PHY_SET(mac, 0x0036, 0x0400);
7251 } else {
7252 BWN_PHY_SET(mac, 0x0036, 0x0200);
7253 BWN_PHY_SET(mac, 0x0036, 0x0400);
7254 BWN_PHY_MASK(mac, 0x005d, 0x7fff);
7255 BWN_PHY_MASK(mac, 0x004f, 0xfffe);
7256 BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7257 BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7258 BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7259 }
7260}
7261
7262static void
7263bwn_hwpctl_init_gphy(struct bwn_mac *mac)
7264{
7265 struct bwn_phy *phy = &mac->mac_phy;
7266 struct bwn_phy_g *pg = &phy->phy_g;
7267 struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7268 int i;
7269 uint16_t nr_written = 0, tmp, value;
7270 uint8_t rf, bb;
7271
7272 if (!bwn_has_hwpctl(mac)) {
7273 bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_HW_POWERCTL);
7274 return;
7275 }
7276
7277 BWN_PHY_SETMASK(mac, 0x0036, 0xffc0,
7278 (pg->pg_idletssi - pg->pg_curtssi));
7279 BWN_PHY_SETMASK(mac, 0x0478, 0xff00,
7280 (pg->pg_idletssi - pg->pg_curtssi));
7281
7282 for (i = 0; i < 32; i++)
7283 bwn_ofdmtab_write_2(mac, 0x3c20, i, pg->pg_tssi2dbm[i]);
7284 for (i = 32; i < 64; i++)
7285 bwn_ofdmtab_write_2(mac, 0x3c00, i - 32, pg->pg_tssi2dbm[i]);
7286 for (i = 0; i < 64; i += 2) {
7287 value = (uint16_t) pg->pg_tssi2dbm[i];
7288 value |= ((uint16_t) pg->pg_tssi2dbm[i + 1]) << 8;
7289 BWN_PHY_WRITE(mac, 0x380 + (i / 2), value);
7290 }
7291
7292 for (rf = 0; rf < lo->rfatt.len; rf++) {
7293 for (bb = 0; bb < lo->bbatt.len; bb++) {
7294 if (nr_written >= 0x40)
7295 return;
7296 tmp = lo->bbatt.array[bb].att;
7297 tmp <<= 8;
7298 if (phy->rf_rev == 8)
7299 tmp |= 0x50;
7300 else
7301 tmp |= 0x40;
7302 tmp |= lo->rfatt.array[rf].att;
7303 BWN_PHY_WRITE(mac, 0x3c0 + nr_written, tmp);
7304 nr_written++;
7305 }
7306 }
7307
7308 BWN_PHY_MASK(mac, 0x0060, 0xffbf);
7309 BWN_PHY_WRITE(mac, 0x0014, 0x0000);
7310
7311 KASSERT(phy->rev >= 6, ("%s:%d: fail", __func__, __LINE__));
7312 BWN_PHY_SET(mac, 0x0478, 0x0800);
7313 BWN_PHY_MASK(mac, 0x0478, 0xfeff);
7314 BWN_PHY_MASK(mac, 0x0801, 0xffbf);
7315
7316 bwn_phy_g_dc_lookup_init(mac, 1);
7317 bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_HW_POWERCTL);
7318}
7319
7320static void
7321bwn_phy_g_switch_chan(struct bwn_mac *mac, int channel, uint8_t spu)
7322{
7323 struct bwn_softc *sc = mac->mac_sc;
7324
7325 if (spu != 0)
7326 bwn_spu_workaround(mac, channel);
7327
7328 BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7329
7330 if (channel == 14) {
7331 if (siba_sprom_get_ccode(sc->sc_dev) == SIBA_CCODE_JAPAN)
7332 bwn_hf_write(mac,
7333 bwn_hf_read(mac) & ~BWN_HF_JAPAN_CHAN14_OFF);
7334 else
7335 bwn_hf_write(mac,
7336 bwn_hf_read(mac) | BWN_HF_JAPAN_CHAN14_OFF);
7337 BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7338 BWN_READ_2(mac, BWN_CHANNEL_EXT) | (1 << 11));
7339 return;
7340 }
7341
7342 BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7343 BWN_READ_2(mac, BWN_CHANNEL_EXT) & 0xf7bf);
7344}
7345
7346static uint16_t
7347bwn_phy_g_chan2freq(uint8_t channel)
7348{
7349 static const uint8_t bwn_phy_g_rf_channels[] = BWN_PHY_G_RF_CHANNELS;
7350
7351 KASSERT(channel >= 1 && channel <= 14,
7352 ("%s:%d: fail", __func__, __LINE__));
7353
7354 return (bwn_phy_g_rf_channels[channel - 1]);
7355}
7356
7357static void
7358bwn_phy_g_set_txpwr_sub(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
7359 const struct bwn_rfatt *rfatt, uint8_t txctl)
7360{
7361 struct bwn_phy *phy = &mac->mac_phy;
7362 struct bwn_phy_g *pg = &phy->phy_g;
7363 struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7364 uint16_t bb, rf;
7365 uint16_t tx_bias, tx_magn;
7366
7367 bb = bbatt->att;
7368 rf = rfatt->att;
7369 tx_bias = lo->tx_bias;
7370 tx_magn = lo->tx_magn;
7371 if (tx_bias == 0xff)
7372 tx_bias = 0;
7373
7374 pg->pg_txctl = txctl;
7375 memmove(&pg->pg_rfatt, rfatt, sizeof(*rfatt));
7376 pg->pg_rfatt.padmix = (txctl & BWN_TXCTL_TXMIX) ? 1 : 0;
7377 memmove(&pg->pg_bbatt, bbatt, sizeof(*bbatt));
7378 bwn_phy_g_set_bbatt(mac, bb);
7379 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RADIO_ATT, rf);
7380 if (phy->rf_ver == 0x2050 && phy->rf_rev == 8)
7381 BWN_RF_WRITE(mac, 0x43, (rf & 0x000f) | (txctl & 0x0070));
7382 else {
7383 BWN_RF_SETMASK(mac, 0x43, 0xfff0, (rf & 0x000f));
7384 BWN_RF_SETMASK(mac, 0x52, ~0x0070, (txctl & 0x0070));
7385 }
7386 if (BWN_HAS_TXMAG(phy))
7387 BWN_RF_WRITE(mac, 0x52, tx_magn | tx_bias);
7388 else
7389 BWN_RF_SETMASK(mac, 0x52, 0xfff0, (tx_bias & 0x000f));
7390 bwn_lo_g_adjust(mac);
7391}
7392
7393static void
7394bwn_phy_g_set_bbatt(struct bwn_mac *mac,
7395 uint16_t bbatt)
7396{
7397 struct bwn_phy *phy = &mac->mac_phy;
7398
7399 if (phy->analog == 0) {
7400 BWN_WRITE_2(mac, BWN_PHY0,
7401 (BWN_READ_2(mac, BWN_PHY0) & 0xfff0) | bbatt);
7402 return;
7403 }
7404 if (phy->analog > 1) {
7405 BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xffc3, bbatt << 2);
7406 return;
7407 }
7408 BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xff87, bbatt << 3);
7409}
7410
7411static uint16_t
7412bwn_rf_2050_rfoverval(struct bwn_mac *mac, uint16_t reg, uint32_t lpd)
7413{
7414 struct bwn_phy *phy = &mac->mac_phy;
7415 struct bwn_phy_g *pg = &phy->phy_g;
7416 struct bwn_softc *sc = mac->mac_sc;
7417 int max_lb_gain;
7418 uint16_t extlna;
7419 uint16_t i;
7420
7421 if (phy->gmode == 0)
7422 return (0);
7423
7424 if (BWN_HAS_LOOPBACK(phy)) {
7425 max_lb_gain = pg->pg_max_lb_gain;
7426 max_lb_gain += (phy->rf_rev == 8) ? 0x3e : 0x26;
7427 if (max_lb_gain >= 0x46) {
7428 extlna = 0x3000;
7429 max_lb_gain -= 0x46;
7430 } else if (max_lb_gain >= 0x3a) {
7431 extlna = 0x1000;
7432 max_lb_gain -= 0x3a;
7433 } else if (max_lb_gain >= 0x2e) {
7434 extlna = 0x2000;
7435 max_lb_gain -= 0x2e;
7436 } else {
7437 extlna = 0;
7438 max_lb_gain -= 0x10;
7439 }
7440
7441 for (i = 0; i < 16; i++) {
7442 max_lb_gain -= (i * 6);
7443 if (max_lb_gain < 6)
7444 break;
7445 }
7446
7447 if ((phy->rev < 7) ||
7448 !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA)) {
7449 if (reg == BWN_PHY_RFOVER) {
7450 return (0x1b3);
7451 } else if (reg == BWN_PHY_RFOVERVAL) {
7452 extlna |= (i << 8);
7453 switch (lpd) {
7454 case BWN_LPD(0, 1, 1):
7455 return (0x0f92);
7456 case BWN_LPD(0, 0, 1):
7457 case BWN_LPD(1, 0, 1):
7458 return (0x0092 | extlna);
7459 case BWN_LPD(1, 0, 0):
7460 return (0x0093 | extlna);
7461 }
7462 KASSERT(0 == 1,
7463 ("%s:%d: fail", __func__, __LINE__));
7464 }
7465 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7466 } else {
7467 if (reg == BWN_PHY_RFOVER)
7468 return (0x9b3);
7469 if (reg == BWN_PHY_RFOVERVAL) {
7470 if (extlna)
7471 extlna |= 0x8000;
7472 extlna |= (i << 8);
7473 switch (lpd) {
7474 case BWN_LPD(0, 1, 1):
7475 return (0x8f92);
7476 case BWN_LPD(0, 0, 1):
7477 return (0x8092 | extlna);
7478 case BWN_LPD(1, 0, 1):
7479 return (0x2092 | extlna);
7480 case BWN_LPD(1, 0, 0):
7481 return (0x2093 | extlna);
7482 }
7483 KASSERT(0 == 1,
7484 ("%s:%d: fail", __func__, __LINE__));
7485 }
7486 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7487 }
7488 return (0);
7489 }
7490
7491 if ((phy->rev < 7) ||
7492 !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA)) {
7493 if (reg == BWN_PHY_RFOVER) {
7494 return (0x1b3);
7495 } else if (reg == BWN_PHY_RFOVERVAL) {
7496 switch (lpd) {
7497 case BWN_LPD(0, 1, 1):
7498 return (0x0fb2);
7499 case BWN_LPD(0, 0, 1):
7500 return (0x00b2);
7501 case BWN_LPD(1, 0, 1):
7502 return (0x30b2);
7503 case BWN_LPD(1, 0, 0):
7504 return (0x30b3);
7505 }
7506 KASSERT(0 == 1,
7507 ("%s:%d: fail", __func__, __LINE__));
7508 }
7509 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7510 } else {
7511 if (reg == BWN_PHY_RFOVER) {
7512 return (0x9b3);
7513 } else if (reg == BWN_PHY_RFOVERVAL) {
7514 switch (lpd) {
7515 case BWN_LPD(0, 1, 1):
7516 return (0x8fb2);
7517 case BWN_LPD(0, 0, 1):
7518 return (0x80b2);
7519 case BWN_LPD(1, 0, 1):
7520 return (0x20b2);
7521 case BWN_LPD(1, 0, 0):
7522 return (0x20b3);
7523 }
7524 KASSERT(0 == 1,
7525 ("%s:%d: fail", __func__, __LINE__));
7526 }
7527 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7528 }
7529 return (0);
7530}
7531
7532static void
7533bwn_spu_workaround(struct bwn_mac *mac, uint8_t channel)
7534{
7535
7536 if (mac->mac_phy.rf_ver != 0x2050 || mac->mac_phy.rf_rev >= 6)
7537 return;
7538 BWN_WRITE_2(mac, BWN_CHANNEL, (channel <= 10) ?
7539 bwn_phy_g_chan2freq(channel + 4) : bwn_phy_g_chan2freq(1));
7540 DELAY(1000);
7541 BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7542}
7543
7544static int
7545bwn_fw_gets(struct bwn_mac *mac, enum bwn_fwtype type)
7546{
7547 struct bwn_softc *sc = mac->mac_sc;
7548 struct bwn_fw *fw = &mac->mac_fw;
7549 const uint8_t rev = siba_get_revid(sc->sc_dev);
7550 const char *filename;
7551 uint32_t high;
7552 int error;
7553
7554 /* microcode */
7555 if (rev >= 5 && rev <= 10)
7556 filename = "ucode5";
7557 else if (rev >= 11 && rev <= 12)
7558 filename = "ucode11";
7559 else if (rev == 13)
7560 filename = "ucode13";
7561 else if (rev == 14)
7562 filename = "ucode14";
7563 else if (rev >= 15)
7564 filename = "ucode15";
7565 else {
7566 device_printf(sc->sc_dev, "no ucode for rev %d\n", rev);
7567 bwn_release_firmware(mac);
7568 return (EOPNOTSUPP);
7569 }
7570 error = bwn_fw_get(mac, type, filename, &fw->ucode);
7571 if (error) {
7572 bwn_release_firmware(mac);
7573 return (error);
7574 }
7575
7576 /* PCM */
7577 KASSERT(fw->no_pcmfile == 0, ("%s:%d fail", __func__, __LINE__));
7578 if (rev >= 5 && rev <= 10) {
7579 error = bwn_fw_get(mac, type, "pcm5", &fw->pcm);
7580 if (error == ENOENT)
7581 fw->no_pcmfile = 1;
7582 else if (error) {
7583 bwn_release_firmware(mac);
7584 return (error);
7585 }
7586 } else if (rev < 11) {
7587 device_printf(sc->sc_dev, "no PCM for rev %d\n", rev);
7588 return (EOPNOTSUPP);
7589 }
7590
7591 /* initvals */
7592 high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH);
7593 switch (mac->mac_phy.type) {
7594 case BWN_PHYTYPE_A:
7595 if (rev < 5 || rev > 10)
7596 goto fail1;
7597 if (high & BWN_TGSHIGH_HAVE_2GHZ)
7598 filename = "a0g1initvals5";
7599 else
7600 filename = "a0g0initvals5";
7601 break;
7602 case BWN_PHYTYPE_G:
7603 if (rev >= 5 && rev <= 10)
7604 filename = "b0g0initvals5";
7605 else if (rev >= 13)
7606 filename = "b0g0initvals13";
7607 else
7608 goto fail1;
7609 break;
7610 case BWN_PHYTYPE_LP:
7611 if (rev == 13)
7612 filename = "lp0initvals13";
7613 else if (rev == 14)
7614 filename = "lp0initvals14";
7615 else if (rev >= 15)
7616 filename = "lp0initvals15";
7617 else
7618 goto fail1;
7619 break;
7620 case BWN_PHYTYPE_N:
7621 if (rev >= 11 && rev <= 12)
7622 filename = "n0initvals11";
7623 else
7624 goto fail1;
7625 break;
7626 default:
7627 goto fail1;
7628 }
7629 error = bwn_fw_get(mac, type, filename, &fw->initvals);
7630 if (error) {
7631 bwn_release_firmware(mac);
7632 return (error);
7633 }
7634
7635 /* bandswitch initvals */
7636 switch (mac->mac_phy.type) {
7637 case BWN_PHYTYPE_A:
7638 if (rev >= 5 && rev <= 10) {
7639 if (high & BWN_TGSHIGH_HAVE_2GHZ)
7640 filename = "a0g1bsinitvals5";
7641 else
7642 filename = "a0g0bsinitvals5";
7643 } else if (rev >= 11)
7644 filename = NULL;
7645 else
7646 goto fail1;
7647 break;
7648 case BWN_PHYTYPE_G:
7649 if (rev >= 5 && rev <= 10)
7650 filename = "b0g0bsinitvals5";
7651 else if (rev >= 11)
7652 filename = NULL;
7653 else
7654 goto fail1;
7655 break;
7656 case BWN_PHYTYPE_LP:
7657 if (rev == 13)
7658 filename = "lp0bsinitvals13";
7659 else if (rev == 14)
7660 filename = "lp0bsinitvals14";
7661 else if (rev >= 15)
7662 filename = "lp0bsinitvals15";
7663 else
7664 goto fail1;
7665 break;
7666 case BWN_PHYTYPE_N:
7667 if (rev >= 11 && rev <= 12)
7668 filename = "n0bsinitvals11";
7669 else
7670 goto fail1;
7671 break;
7672 default:
7673 goto fail1;
7674 }
7675 error = bwn_fw_get(mac, type, filename, &fw->initvals_band);
7676 if (error) {
7677 bwn_release_firmware(mac);
7678 return (error);
7679 }
7680 return (0);
7681fail1:
7682 device_printf(sc->sc_dev, "no INITVALS for rev %d\n", rev);
7683 bwn_release_firmware(mac);
7684 return (EOPNOTSUPP);
7685}
7686
7687static int
7688bwn_fw_get(struct bwn_mac *mac, enum bwn_fwtype type,
7689 const char *name, struct bwn_fwfile *bfw)
7690{
7691 const struct bwn_fwhdr *hdr;
7692 struct bwn_softc *sc = mac->mac_sc;
7693 const struct firmware *fw;
7694 char namebuf[64];
7695
7696 if (name == NULL) {
7697 bwn_do_release_fw(bfw);
7698 return (0);
7699 }
7700 if (bfw->filename != NULL) {
7701 if (bfw->type == type && (strcmp(bfw->filename, name) == 0))
7702 return (0);
7703 bwn_do_release_fw(bfw);
7704 }
7705
7706 snprintf(namebuf, sizeof(namebuf), "bwn%s_v4_%s%s",
7707 (type == BWN_FWTYPE_OPENSOURCE) ? "-open" : "",
7708 (mac->mac_phy.type == BWN_PHYTYPE_LP) ? "lp_" : "", name);
7709 /* XXX Sleeping on "fwload" with the non-sleepable locks held */
7710 fw = firmware_get(namebuf);
7711 if (fw == NULL) {
7712 device_printf(sc->sc_dev, "the fw file(%s) not found\n",
7713 namebuf);
7714 return (ENOENT);
7715 }
7716 if (fw->datasize < sizeof(struct bwn_fwhdr))
7717 goto fail;
7718 hdr = (const struct bwn_fwhdr *)(fw->data);
7719 switch (hdr->type) {
7720 case BWN_FWTYPE_UCODE:
7721 case BWN_FWTYPE_PCM:
7722 if (be32toh(hdr->size) !=
7723 (fw->datasize - sizeof(struct bwn_fwhdr)))
7724 goto fail;
7725 /* FALLTHROUGH */
7726 case BWN_FWTYPE_IV:
7727 if (hdr->ver != 1)
7728 goto fail;
7729 break;
7730 default:
7731 goto fail;
7732 }
7733 bfw->filename = name;
7734 bfw->fw = fw;
7735 bfw->type = type;
7736 return (0);
7737fail:
7738 device_printf(sc->sc_dev, "the fw file(%s) format error\n", namebuf);
7739 if (fw != NULL)
7740 firmware_put(fw, FIRMWARE_UNLOAD);
7741 return (EPROTO);
7742}
7743
7744static void
7745bwn_release_firmware(struct bwn_mac *mac)
7746{
7747
7748 bwn_do_release_fw(&mac->mac_fw.ucode);
7749 bwn_do_release_fw(&mac->mac_fw.pcm);
7750 bwn_do_release_fw(&mac->mac_fw.initvals);
7751 bwn_do_release_fw(&mac->mac_fw.initvals_band);
7752}
7753
7754static void
7755bwn_do_release_fw(struct bwn_fwfile *bfw)
7756{
7757
7758 if (bfw->fw != NULL)
7759 firmware_put(bfw->fw, FIRMWARE_UNLOAD);
7760 bfw->fw = NULL;
7761 bfw->filename = NULL;
7762}
7763
7764static int
7765bwn_fw_loaducode(struct bwn_mac *mac)
7766{
7767#define GETFWOFFSET(fwp, offset) \
7768 ((const uint32_t *)((const char *)fwp.fw->data + offset))
7769#define GETFWSIZE(fwp, offset) \
7770 ((fwp.fw->datasize - offset) / sizeof(uint32_t))
7771 struct bwn_softc *sc = mac->mac_sc;
7772 const uint32_t *data;
7773 unsigned int i;
7774 uint32_t ctl;
7775 uint16_t date, fwcaps, time;
7776 int error = 0;
7777
7778 ctl = BWN_READ_4(mac, BWN_MACCTL);
7779 ctl |= BWN_MACCTL_MCODE_JMP0;
7780 KASSERT(!(ctl & BWN_MACCTL_MCODE_RUN), ("%s:%d: fail", __func__,
7781 __LINE__));
7782 BWN_WRITE_4(mac, BWN_MACCTL, ctl);
7783 for (i = 0; i < 64; i++)
7784 bwn_shm_write_2(mac, BWN_SCRATCH, i, 0);
7785 for (i = 0; i < 4096; i += 2)
7786 bwn_shm_write_2(mac, BWN_SHARED, i, 0);
7787
7788 data = GETFWOFFSET(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7789 bwn_shm_ctlword(mac, BWN_UCODE | BWN_SHARED_AUTOINC, 0x0000);
7790 for (i = 0; i < GETFWSIZE(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7791 i++) {
7792 BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7793 DELAY(10);
7794 }
7795
7796 if (mac->mac_fw.pcm.fw) {
7797 data = GETFWOFFSET(mac->mac_fw.pcm, sizeof(struct bwn_fwhdr));
7798 bwn_shm_ctlword(mac, BWN_HW, 0x01ea);
7799 BWN_WRITE_4(mac, BWN_SHM_DATA, 0x00004000);
7800 bwn_shm_ctlword(mac, BWN_HW, 0x01eb);
7801 for (i = 0; i < GETFWSIZE(mac->mac_fw.pcm,
7802 sizeof(struct bwn_fwhdr)); i++) {
7803 BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7804 DELAY(10);
7805 }
7806 }
7807
7808 BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_ALL);
7809 BWN_WRITE_4(mac, BWN_MACCTL,
7810 (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_JMP0) |
7811 BWN_MACCTL_MCODE_RUN);
7812
7813 for (i = 0; i < 21; i++) {
7814 if (BWN_READ_4(mac, BWN_INTR_REASON) == BWN_INTR_MAC_SUSPENDED)
7815 break;
7816 if (i >= 20) {
7817 device_printf(sc->sc_dev, "ucode timeout\n");
7818 error = ENXIO;
7819 goto error;
7820 }
7821 DELAY(50000);
7822 }
7823 BWN_READ_4(mac, BWN_INTR_REASON);
7824
7825 mac->mac_fw.rev = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_REV);
7826 if (mac->mac_fw.rev <= 0x128) {
7827 device_printf(sc->sc_dev, "the firmware is too old\n");
7828 error = EOPNOTSUPP;
7829 goto error;
7830 }
7831 mac->mac_fw.patch = bwn_shm_read_2(mac, BWN_SHARED,
7832 BWN_SHARED_UCODE_PATCH);
7833 date = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_DATE);
7834 mac->mac_fw.opensource = (date == 0xffff);
7835 if (bwn_wme != 0)
7836 mac->mac_flags |= BWN_MAC_FLAG_WME;
7837 mac->mac_flags |= BWN_MAC_FLAG_HWCRYPTO;
7838
7839 time = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_TIME);
7840 if (mac->mac_fw.opensource == 0) {
7841 device_printf(sc->sc_dev,
7842 "firmware version (rev %u patch %u date %#x time %#x)\n",
7843 mac->mac_fw.rev, mac->mac_fw.patch, date, time);
7844 if (mac->mac_fw.no_pcmfile)
7845 device_printf(sc->sc_dev,
7846 "no HW crypto acceleration due to pcm5\n");
7847 } else {
7848 mac->mac_fw.patch = time;
7849 fwcaps = bwn_fwcaps_read(mac);
7850 if (!(fwcaps & BWN_FWCAPS_HWCRYPTO) || mac->mac_fw.no_pcmfile) {
7851 device_printf(sc->sc_dev,
7852 "disabling HW crypto acceleration\n");
7853 mac->mac_flags &= ~BWN_MAC_FLAG_HWCRYPTO;
7854 }
7855 if (!(fwcaps & BWN_FWCAPS_WME)) {
7856 device_printf(sc->sc_dev, "disabling WME support\n");
7857 mac->mac_flags &= ~BWN_MAC_FLAG_WME;
7858 }
7859 }
7860
7861 if (BWN_ISOLDFMT(mac))
7862 device_printf(sc->sc_dev, "using old firmware image\n");
7863
7864 return (0);
7865
7866error:
7867 BWN_WRITE_4(mac, BWN_MACCTL,
7868 (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_RUN) |
7869 BWN_MACCTL_MCODE_JMP0);
7870
7871 return (error);
7872#undef GETFWSIZE
7873#undef GETFWOFFSET
7874}
7875
7876/* OpenFirmware only */
7877static uint16_t
7878bwn_fwcaps_read(struct bwn_mac *mac)
7879{
7880
7881 KASSERT(mac->mac_fw.opensource == 1,
7882 ("%s:%d: fail", __func__, __LINE__));
7883 return (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_FWCAPS));
7884}
7885
7886static int
7887bwn_fwinitvals_write(struct bwn_mac *mac, const struct bwn_fwinitvals *ivals,
7888 size_t count, size_t array_size)
7889{
7890#define GET_NEXTIV16(iv) \
7891 ((const struct bwn_fwinitvals *)((const uint8_t *)(iv) + \
7892 sizeof(uint16_t) + sizeof(uint16_t)))
7893#define GET_NEXTIV32(iv) \
7894 ((const struct bwn_fwinitvals *)((const uint8_t *)(iv) + \
7895 sizeof(uint16_t) + sizeof(uint32_t)))
7896 struct bwn_softc *sc = mac->mac_sc;
7897 const struct bwn_fwinitvals *iv;
7898 uint16_t offset;
7899 size_t i;
7900 uint8_t bit32;
7901
7902 KASSERT(sizeof(struct bwn_fwinitvals) == 6,
7903 ("%s:%d: fail", __func__, __LINE__));
7904 iv = ivals;
7905 for (i = 0; i < count; i++) {
7906 if (array_size < sizeof(iv->offset_size))
7907 goto fail;
7908 array_size -= sizeof(iv->offset_size);
7909 offset = be16toh(iv->offset_size);
7910 bit32 = (offset & BWN_FWINITVALS_32BIT) ? 1 : 0;
7911 offset &= BWN_FWINITVALS_OFFSET_MASK;
7912 if (offset >= 0x1000)
7913 goto fail;
7914 if (bit32) {
7915 if (array_size < sizeof(iv->data.d32))
7916 goto fail;
7917 array_size -= sizeof(iv->data.d32);
7918 BWN_WRITE_4(mac, offset, be32toh(iv->data.d32));
7919 iv = GET_NEXTIV32(iv);
7920 } else {
7921
7922 if (array_size < sizeof(iv->data.d16))
7923 goto fail;
7924 array_size -= sizeof(iv->data.d16);
7925 BWN_WRITE_2(mac, offset, be16toh(iv->data.d16));
7926
7927 iv = GET_NEXTIV16(iv);
7928 }
7929 }
7930 if (array_size != 0)
7931 goto fail;
7932 return (0);
7933fail:
7934 device_printf(sc->sc_dev, "initvals: invalid format\n");
7935 return (EPROTO);
7936#undef GET_NEXTIV16
7937#undef GET_NEXTIV32
7938}
7939
7940static int
7941bwn_switch_channel(struct bwn_mac *mac, int chan)
7942{
7943 struct bwn_phy *phy = &(mac->mac_phy);
7944 struct bwn_softc *sc = mac->mac_sc;
7945 struct ifnet *ifp = sc->sc_ifp;
7946 struct ieee80211com *ic = ifp->if_l2com;
7947 uint16_t channelcookie, savedcookie;
7948 int error;
7949
7950 if (chan == 0xffff)
7951 chan = phy->get_default_chan(mac);
7952
7953 channelcookie = chan;
7954 if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan))
7955 channelcookie |= 0x100;
7956 savedcookie = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_CHAN);
7957 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, channelcookie);
7958 error = phy->switch_channel(mac, chan);
7959 if (error)
7960 goto fail;
7961
7962 mac->mac_phy.chan = chan;
7963 DELAY(8000);
7964 return (0);
7965fail:
7966 device_printf(sc->sc_dev, "failed to switch channel\n");
7967 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, savedcookie);
7968 return (error);
7969}
7970
7971static uint16_t
7972bwn_ant2phy(int antenna)
7973{
7974
7975 switch (antenna) {
7976 case BWN_ANT0:
7977 return (BWN_TX_PHY_ANT0);
7978 case BWN_ANT1:
7979 return (BWN_TX_PHY_ANT1);
7980 case BWN_ANT2:
7981 return (BWN_TX_PHY_ANT2);
7982 case BWN_ANT3:
7983 return (BWN_TX_PHY_ANT3);
7984 case BWN_ANTAUTO:
7985 return (BWN_TX_PHY_ANT01AUTO);
7986 }
7987 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7988 return (0);
7989}
7990
7991static void
7992bwn_wme_load(struct bwn_mac *mac)
7993{
7994 struct bwn_softc *sc = mac->mac_sc;
7995 int i;
7996
7997 KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
7998 ("%s:%d: fail", __func__, __LINE__));
7999
8000 bwn_mac_suspend(mac);
8001 for (i = 0; i < N(sc->sc_wmeParams); i++)
8002 bwn_wme_loadparams(mac, &(sc->sc_wmeParams[i]),
8003 bwn_wme_shm_offsets[i]);
8004 bwn_mac_enable(mac);
8005}
8006
8007static void
8008bwn_wme_loadparams(struct bwn_mac *mac,
8009 const struct wmeParams *p, uint16_t shm_offset)
8010{
8011#define SM(_v, _f) (((_v) << _f##_S) & _f)
8012 struct bwn_softc *sc = mac->mac_sc;
8013 uint16_t params[BWN_NR_WMEPARAMS];
8014 int slot, tmp;
8015 unsigned int i;
8016
8017 slot = BWN_READ_2(mac, BWN_RNG) &
8018 SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8019
8020 memset(¶ms, 0, sizeof(params));
8021
8022 DPRINTF(sc, BWN_DEBUG_WME, "wmep_txopLimit %d wmep_logcwmin %d "
8023 "wmep_logcwmax %d wmep_aifsn %d\n", p->wmep_txopLimit,
8024 p->wmep_logcwmin, p->wmep_logcwmax, p->wmep_aifsn);
8025
8026 params[BWN_WMEPARAM_TXOP] = p->wmep_txopLimit * 32;
8027 params[BWN_WMEPARAM_CWMIN] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8028 params[BWN_WMEPARAM_CWMAX] = SM(p->wmep_logcwmax, WME_PARAM_LOGCWMAX);
8029 params[BWN_WMEPARAM_CWCUR] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8030 params[BWN_WMEPARAM_AIFS] = p->wmep_aifsn;
8031 params[BWN_WMEPARAM_BSLOTS] = slot;
8032 params[BWN_WMEPARAM_REGGAP] = slot + p->wmep_aifsn;
8033
8034 for (i = 0; i < N(params); i++) {
8035 if (i == BWN_WMEPARAM_STATUS) {
8036 tmp = bwn_shm_read_2(mac, BWN_SHARED,
8037 shm_offset + (i * 2));
8038 tmp |= 0x100;
8039 bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
8040 tmp);
8041 } else {
8042 bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
8043 params[i]);
8044 }
8045 }
8046}
8047
8048static void
8049bwn_mac_write_bssid(struct bwn_mac *mac)
8050{
8051 struct bwn_softc *sc = mac->mac_sc;
8052 uint32_t tmp;
8053 int i;
8054 uint8_t mac_bssid[IEEE80211_ADDR_LEN * 2];
8055
8056 bwn_mac_setfilter(mac, BWN_MACFILTER_BSSID, sc->sc_bssid);
8057 memcpy(mac_bssid, sc->sc_macaddr, IEEE80211_ADDR_LEN);
8058 memcpy(mac_bssid + IEEE80211_ADDR_LEN, sc->sc_bssid,
8059 IEEE80211_ADDR_LEN);
8060
8061 for (i = 0; i < N(mac_bssid); i += sizeof(uint32_t)) {
8062 tmp = (uint32_t) (mac_bssid[i + 0]);
8063 tmp |= (uint32_t) (mac_bssid[i + 1]) << 8;
8064 tmp |= (uint32_t) (mac_bssid[i + 2]) << 16;
8065 tmp |= (uint32_t) (mac_bssid[i + 3]) << 24;
8066 bwn_ram_write(mac, 0x20 + i, tmp);
8067 }
8068}
8069
8070static void
8071bwn_mac_setfilter(struct bwn_mac *mac, uint16_t offset,
8072 const uint8_t *macaddr)
8073{
8074 static const uint8_t zero[IEEE80211_ADDR_LEN] = { 0 };
8075 uint16_t data;
8076
8077 if (!mac)
8078 macaddr = zero;
8079
8080 offset |= 0x0020;
8081 BWN_WRITE_2(mac, BWN_MACFILTER_CONTROL, offset);
8082
8083 data = macaddr[0];
8084 data |= macaddr[1] << 8;
8085 BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8086 data = macaddr[2];
8087 data |= macaddr[3] << 8;
8088 BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8089 data = macaddr[4];
8090 data |= macaddr[5] << 8;
8091 BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8092}
8093
8094static void
8095bwn_key_dowrite(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8096 const uint8_t *key, size_t key_len, const uint8_t *mac_addr)
8097{
8098 uint8_t buf[BWN_SEC_KEYSIZE] = { 0, };
8099 uint8_t per_sta_keys_start = 8;
8100
8101 if (BWN_SEC_NEWAPI(mac))
8102 per_sta_keys_start = 4;
8103
8104 KASSERT(index < mac->mac_max_nr_keys,
8105 ("%s:%d: fail", __func__, __LINE__));
8106 KASSERT(key_len <= BWN_SEC_KEYSIZE,
8107 ("%s:%d: fail", __func__, __LINE__));
8108
8109 if (index >= per_sta_keys_start)
8110 bwn_key_macwrite(mac, index, NULL);
8111 if (key)
8112 memcpy(buf, key, key_len);
8113 bwn_key_write(mac, index, algorithm, buf);
8114 if (index >= per_sta_keys_start)
8115 bwn_key_macwrite(mac, index, mac_addr);
8116
8117 mac->mac_key[index].algorithm = algorithm;
8118}
8119
8120static void
8121bwn_key_macwrite(struct bwn_mac *mac, uint8_t index, const uint8_t *addr)
8122{
8123 struct bwn_softc *sc = mac->mac_sc;
8124 uint32_t addrtmp[2] = { 0, 0 };
8125 uint8_t start = 8;
8126
8127 if (BWN_SEC_NEWAPI(mac))
8128 start = 4;
8129
8130 KASSERT(index >= start,
8131 ("%s:%d: fail", __func__, __LINE__));
8132 index -= start;
8133
8134 if (addr) {
8135 addrtmp[0] = addr[0];
8136 addrtmp[0] |= ((uint32_t) (addr[1]) << 8);
8137 addrtmp[0] |= ((uint32_t) (addr[2]) << 16);
8138 addrtmp[0] |= ((uint32_t) (addr[3]) << 24);
8139 addrtmp[1] = addr[4];
8140 addrtmp[1] |= ((uint32_t) (addr[5]) << 8);
8141 }
8142
8143 if (siba_get_revid(sc->sc_dev) >= 5) {
8144 bwn_shm_write_4(mac, BWN_RCMTA, (index * 2) + 0, addrtmp[0]);
8145 bwn_shm_write_2(mac, BWN_RCMTA, (index * 2) + 1, addrtmp[1]);
8146 } else {
8147 if (index >= 8) {
8148 bwn_shm_write_4(mac, BWN_SHARED,
8149 BWN_SHARED_PSM + (index * 6) + 0, addrtmp[0]);
8150 bwn_shm_write_2(mac, BWN_SHARED,
8151 BWN_SHARED_PSM + (index * 6) + 4, addrtmp[1]);
8152 }
8153 }
8154}
8155
8156static void
8157bwn_key_write(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8158 const uint8_t *key)
8159{
8160 unsigned int i;
8161 uint32_t offset;
8162 uint16_t kidx, value;
8163
8164 kidx = BWN_SEC_KEY2FW(mac, index);
8165 bwn_shm_write_2(mac, BWN_SHARED,
8166 BWN_SHARED_KEYIDX_BLOCK + (kidx * 2), (kidx << 4) | algorithm);
8167
8168 offset = mac->mac_ktp + (index * BWN_SEC_KEYSIZE);
8169 for (i = 0; i < BWN_SEC_KEYSIZE; i += 2) {
8170 value = key[i];
8171 value |= (uint16_t)(key[i + 1]) << 8;
8172 bwn_shm_write_2(mac, BWN_SHARED, offset + i, value);
8173 }
8174}
8175
8176static void
8177bwn_phy_exit(struct bwn_mac *mac)
8178{
8179
8180 mac->mac_phy.rf_onoff(mac, 0);
8181 if (mac->mac_phy.exit != NULL)
8182 mac->mac_phy.exit(mac);
8183}
8184
8185static void
8186bwn_dma_free(struct bwn_mac *mac)
8187{
8188 struct bwn_dma *dma;
8189
8190 if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
8191 return;
8192 dma = &mac->mac_method.dma;
8193
8194 bwn_dma_ringfree(&dma->rx);
8195 bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
8196 bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
8197 bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
8198 bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
8199 bwn_dma_ringfree(&dma->mcast);
8200}
8201
8202static void
8203bwn_core_stop(struct bwn_mac *mac)
8204{
8205 struct bwn_softc *sc = mac->mac_sc;
8206
8207 BWN_ASSERT_LOCKED(sc);
8208
8209 if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8210 return;
8211
8212 callout_stop(&sc->sc_rfswitch_ch);
8213 callout_stop(&sc->sc_task_ch);
8214 callout_stop(&sc->sc_watchdog_ch);
8215 sc->sc_watchdog_timer = 0;
8216 BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8217 BWN_READ_4(mac, BWN_INTR_MASK);
8218 bwn_mac_suspend(mac);
8219
8220 mac->mac_status = BWN_MAC_STATUS_INITED;
8221}
8222
8223static int
8224bwn_switch_band(struct bwn_softc *sc, struct ieee80211_channel *chan)
8225{
8226 struct bwn_mac *up_dev = NULL;
8227 struct bwn_mac *down_dev;
8228 struct bwn_mac *mac;
8229 int err, status;
8230 uint8_t gmode;
8231
8232 BWN_ASSERT_LOCKED(sc);
8233
8234 TAILQ_FOREACH(mac, &sc->sc_maclist, mac_list) {
8235 if (IEEE80211_IS_CHAN_2GHZ(chan) &&
8236 mac->mac_phy.supports_2ghz) {
8237 up_dev = mac;
8238 gmode = 1;
8239 } else if (IEEE80211_IS_CHAN_5GHZ(chan) &&
8240 mac->mac_phy.supports_5ghz) {
8241 up_dev = mac;
8242 gmode = 0;
8243 } else {
8244 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8245 return (EINVAL);
8246 }
8247 if (up_dev != NULL)
8248 break;
8249 }
8250 if (up_dev == NULL) {
8251 device_printf(sc->sc_dev, "Could not find a device\n");
8252 return (ENODEV);
8253 }
8254 if (up_dev == sc->sc_curmac && sc->sc_curmac->mac_phy.gmode == gmode)
8255 return (0);
8256
8257 device_printf(sc->sc_dev, "switching to %s-GHz band\n",
8258 IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8259
8260 down_dev = sc->sc_curmac;
8261 status = down_dev->mac_status;
8262 if (status >= BWN_MAC_STATUS_STARTED)
8263 bwn_core_stop(down_dev);
8264 if (status >= BWN_MAC_STATUS_INITED)
8265 bwn_core_exit(down_dev);
8266
8267 if (down_dev != up_dev)
8268 bwn_phy_reset(down_dev);
8269
8270 up_dev->mac_phy.gmode = gmode;
8271 if (status >= BWN_MAC_STATUS_INITED) {
8272 err = bwn_core_init(up_dev);
8273 if (err) {
8274 device_printf(sc->sc_dev,
8275 "fatal: failed to initialize for %s-GHz\n",
8276 IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8277 goto fail;
8278 }
8279 }
8280 if (status >= BWN_MAC_STATUS_STARTED)
8281 bwn_core_start(up_dev);
8282 KASSERT(up_dev->mac_status == status, ("%s: fail", __func__));
8283 sc->sc_curmac = up_dev;
8284
8285 return (0);
8286fail:
8287 sc->sc_curmac = NULL;
8288 return (err);
8289}
8290
8291static void
8292bwn_rf_turnon(struct bwn_mac *mac)
8293{
8294
8295 bwn_mac_suspend(mac);
8296 mac->mac_phy.rf_onoff(mac, 1);
8297 mac->mac_phy.rf_on = 1;
8298 bwn_mac_enable(mac);
8299}
8300
8301static void
8302bwn_rf_turnoff(struct bwn_mac *mac)
8303{
8304
8305 bwn_mac_suspend(mac);
8306 mac->mac_phy.rf_onoff(mac, 0);
8307 mac->mac_phy.rf_on = 0;
8308 bwn_mac_enable(mac);
8309}
8310
8311static void
8312bwn_phy_reset(struct bwn_mac *mac)
8313{
8314 struct bwn_softc *sc = mac->mac_sc;
8315
8316 siba_write_4(sc->sc_dev, SIBA_TGSLOW,
8317 ((siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~BWN_TGSLOW_SUPPORT_G) |
8318 BWN_TGSLOW_PHYRESET) | SIBA_TGSLOW_FGC);
8319 DELAY(1000);
8320 siba_write_4(sc->sc_dev, SIBA_TGSLOW,
8321 (siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~SIBA_TGSLOW_FGC) |
8322 BWN_TGSLOW_PHYRESET);
8323 DELAY(1000);
8324}
8325
8326static int
8327bwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
8328{
8329 struct bwn_vap *bvp = BWN_VAP(vap);
8330 struct ieee80211com *ic= vap->iv_ic;
8331 struct ifnet *ifp = ic->ic_ifp;
8332 enum ieee80211_state ostate = vap->iv_state;
8333 struct bwn_softc *sc = ifp->if_softc;
8334 struct bwn_mac *mac = sc->sc_curmac;
8335 int error;
8336
8337 DPRINTF(sc, BWN_DEBUG_STATE, "%s: %s -> %s\n", __func__,
8338 ieee80211_state_name[vap->iv_state],
8339 ieee80211_state_name[nstate]);
8340
8341 error = bvp->bv_newstate(vap, nstate, arg);
8342 if (error != 0)
8343 return (error);
8344
8345 BWN_LOCK(sc);
8346
8347 bwn_led_newstate(mac, nstate);
8348
8349 /*
8350 * Clear the BSSID when we stop a STA
8351 */
8352 if (vap->iv_opmode == IEEE80211_M_STA) {
8353 if (ostate == IEEE80211_S_RUN && nstate != IEEE80211_S_RUN) {
8354 /*
8355 * Clear out the BSSID. If we reassociate to
8356 * the same AP, this will reinialize things
8357 * correctly...
8358 */
8359 if (ic->ic_opmode == IEEE80211_M_STA &&
8360 (sc->sc_flags & BWN_FLAG_INVALID) == 0) {
8361 memset(sc->sc_bssid, 0, IEEE80211_ADDR_LEN);
8362 bwn_set_macaddr(mac);
8363 }
8364 }
8365 }
8366
8367 if (vap->iv_opmode == IEEE80211_M_MONITOR ||
8368 vap->iv_opmode == IEEE80211_M_AHDEMO) {
8369 /* XXX nothing to do? */
8370 } else if (nstate == IEEE80211_S_RUN) {
8371 memcpy(sc->sc_bssid, vap->iv_bss->ni_bssid, IEEE80211_ADDR_LEN);
8372 memcpy(sc->sc_macaddr, IF_LLADDR(ifp), IEEE80211_ADDR_LEN);
8373 bwn_set_opmode(mac);
8374 bwn_set_pretbtt(mac);
8375 bwn_spu_setdelay(mac, 0);
8376 bwn_set_macaddr(mac);
8377 }
8378
8379 BWN_UNLOCK(sc);
8380
8381 return (error);
8382}
8383
8384static void
8385bwn_set_pretbtt(struct bwn_mac *mac)
8386{
8387 struct bwn_softc *sc = mac->mac_sc;
8388 struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8389 uint16_t pretbtt;
8390
8391 if (ic->ic_opmode == IEEE80211_M_IBSS)
8392 pretbtt = 2;
8393 else
8394 pretbtt = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 120 : 250;
8395 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PRETBTT, pretbtt);
8396 BWN_WRITE_2(mac, BWN_TSF_CFP_PRETBTT, pretbtt);
8397}
8398
8399static int
8400bwn_intr(void *arg)
8401{
8402 struct bwn_mac *mac = arg;
8403 struct bwn_softc *sc = mac->mac_sc;
8404 uint32_t reason;
8405
8406 if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
8407 (sc->sc_flags & BWN_FLAG_INVALID))
8408 return (FILTER_STRAY);
8409
8410 reason = BWN_READ_4(mac, BWN_INTR_REASON);
8411 if (reason == 0xffffffff) /* shared IRQ */
8412 return (FILTER_STRAY);
8413 reason &= mac->mac_intr_mask;
8414 if (reason == 0)
8415 return (FILTER_HANDLED);
8416
8417 mac->mac_reason[0] = BWN_READ_4(mac, BWN_DMA0_REASON) & 0x0001dc00;
8418 mac->mac_reason[1] = BWN_READ_4(mac, BWN_DMA1_REASON) & 0x0000dc00;
8419 mac->mac_reason[2] = BWN_READ_4(mac, BWN_DMA2_REASON) & 0x0000dc00;
8420 mac->mac_reason[3] = BWN_READ_4(mac, BWN_DMA3_REASON) & 0x0001dc00;
8421 mac->mac_reason[4] = BWN_READ_4(mac, BWN_DMA4_REASON) & 0x0000dc00;
8422 BWN_WRITE_4(mac, BWN_INTR_REASON, reason);
8423 BWN_WRITE_4(mac, BWN_DMA0_REASON, mac->mac_reason[0]);
8424 BWN_WRITE_4(mac, BWN_DMA1_REASON, mac->mac_reason[1]);
8425 BWN_WRITE_4(mac, BWN_DMA2_REASON, mac->mac_reason[2]);
8426 BWN_WRITE_4(mac, BWN_DMA3_REASON, mac->mac_reason[3]);
8427 BWN_WRITE_4(mac, BWN_DMA4_REASON, mac->mac_reason[4]);
8428
8429 /* Disable interrupts. */
8430 BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8431
8432 mac->mac_reason_intr = reason;
8433
8434 BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8435 BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8436
8437 taskqueue_enqueue_fast(sc->sc_tq, &mac->mac_intrtask);
8438 return (FILTER_HANDLED);
8439}
8440
8441static void
8442bwn_intrtask(void *arg, int npending)
8443{
8444 struct bwn_mac *mac = arg;
8445 struct bwn_softc *sc = mac->mac_sc;
8446 struct ifnet *ifp = sc->sc_ifp;
8447 uint32_t merged = 0;
8448 int i, tx = 0, rx = 0;
8449
8450 BWN_LOCK(sc);
8451 if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
8452 (sc->sc_flags & BWN_FLAG_INVALID)) {
8453 BWN_UNLOCK(sc);
8454 return;
8455 }
8456
8457 for (i = 0; i < N(mac->mac_reason); i++)
8458 merged |= mac->mac_reason[i];
8459
8460 if (mac->mac_reason_intr & BWN_INTR_MAC_TXERR)
8461 device_printf(sc->sc_dev, "MAC trans error\n");
8462
8463 if (mac->mac_reason_intr & BWN_INTR_PHY_TXERR) {
8464 DPRINTF(sc, BWN_DEBUG_INTR, "%s: PHY trans error\n", __func__);
8465 mac->mac_phy.txerrors--;
8466 if (mac->mac_phy.txerrors == 0) {
8467 mac->mac_phy.txerrors = BWN_TXERROR_MAX;
8468 bwn_restart(mac, "PHY TX errors");
8469 }
8470 }
8471
8472 if (merged & (BWN_DMAINTR_FATALMASK | BWN_DMAINTR_NONFATALMASK)) {
8473 if (merged & BWN_DMAINTR_FATALMASK) {
8474 device_printf(sc->sc_dev,
8475 "Fatal DMA error: %#x %#x %#x %#x %#x %#x\n",
8476 mac->mac_reason[0], mac->mac_reason[1],
8477 mac->mac_reason[2], mac->mac_reason[3],
8478 mac->mac_reason[4], mac->mac_reason[5]);
8479 bwn_restart(mac, "DMA error");
8480 BWN_UNLOCK(sc);
8481 return;
8482 }
8483 if (merged & BWN_DMAINTR_NONFATALMASK) {
8484 device_printf(sc->sc_dev,
8485 "DMA error: %#x %#x %#x %#x %#x %#x\n",
8486 mac->mac_reason[0], mac->mac_reason[1],
8487 mac->mac_reason[2], mac->mac_reason[3],
8488 mac->mac_reason[4], mac->mac_reason[5]);
8489 }
8490 }
8491
8492 if (mac->mac_reason_intr & BWN_INTR_UCODE_DEBUG)
8493 bwn_intr_ucode_debug(mac);
8494 if (mac->mac_reason_intr & BWN_INTR_TBTT_INDI)
8495 bwn_intr_tbtt_indication(mac);
8496 if (mac->mac_reason_intr & BWN_INTR_ATIM_END)
8497 bwn_intr_atim_end(mac);
8498 if (mac->mac_reason_intr & BWN_INTR_BEACON)
8499 bwn_intr_beacon(mac);
8500 if (mac->mac_reason_intr & BWN_INTR_PMQ)
8501 bwn_intr_pmq(mac);
8502 if (mac->mac_reason_intr & BWN_INTR_NOISESAMPLE_OK)
8503 bwn_intr_noise(mac);
8504
8505 if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
8506 if (mac->mac_reason[0] & BWN_DMAINTR_RX_DONE) {
8507 bwn_dma_rx(mac->mac_method.dma.rx);
8508 rx = 1;
8509 }
8510 } else
8511 rx = bwn_pio_rx(&mac->mac_method.pio.rx);
8512
8513 KASSERT(!(mac->mac_reason[1] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8514 KASSERT(!(mac->mac_reason[2] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8515 KASSERT(!(mac->mac_reason[3] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8516 KASSERT(!(mac->mac_reason[4] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8517 KASSERT(!(mac->mac_reason[5] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8518
8519 if (mac->mac_reason_intr & BWN_INTR_TX_OK) {
8520 bwn_intr_txeof(mac);
8521 tx = 1;
8522 }
8523
8524 BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
8525
8526 if (sc->sc_blink_led != NULL && sc->sc_led_blink) {
8527 int evt = BWN_LED_EVENT_NONE;
8528
8529 if (tx && rx) {
8530 if (sc->sc_rx_rate > sc->sc_tx_rate)
8531 evt = BWN_LED_EVENT_RX;
8532 else
8533 evt = BWN_LED_EVENT_TX;
8534 } else if (tx) {
8535 evt = BWN_LED_EVENT_TX;
8536 } else if (rx) {
8537 evt = BWN_LED_EVENT_RX;
8538 } else if (rx == 0) {
8539 evt = BWN_LED_EVENT_POLL;
8540 }
8541
8542 if (evt != BWN_LED_EVENT_NONE)
8543 bwn_led_event(mac, evt);
8544 }
8545
8546 if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0) {
8547 if (!IFQ_IS_EMPTY(&ifp->if_snd))
8548 bwn_start_locked(ifp);
8549 }
8550
8551 BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8552 BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8553
8554 BWN_UNLOCK(sc);
8555}
8556
8557static void
8558bwn_restart(struct bwn_mac *mac, const char *msg)
8559{
8560 struct bwn_softc *sc = mac->mac_sc;
8561 struct ifnet *ifp = sc->sc_ifp;
8562 struct ieee80211com *ic = ifp->if_l2com;
8563
8564 if (mac->mac_status < BWN_MAC_STATUS_INITED)
8565 return;
8566
8567 device_printf(sc->sc_dev, "HW reset: %s\n", msg);
8568 ieee80211_runtask(ic, &mac->mac_hwreset);
8569}
8570
8571static void
8572bwn_intr_ucode_debug(struct bwn_mac *mac)
8573{
8574 struct bwn_softc *sc = mac->mac_sc;
8575 uint16_t reason;
8576
8577 if (mac->mac_fw.opensource == 0)
8578 return;
8579
8580 reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG);
8581 switch (reason) {
8582 case BWN_DEBUGINTR_PANIC:
8583 bwn_handle_fwpanic(mac);
8584 break;
8585 case BWN_DEBUGINTR_DUMP_SHM:
8586 device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_SHM\n");
8587 break;
8588 case BWN_DEBUGINTR_DUMP_REGS:
8589 device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_REGS\n");
8590 break;
8591 case BWN_DEBUGINTR_MARKER:
8592 device_printf(sc->sc_dev, "BWN_DEBUGINTR_MARKER\n");
8593 break;
8594 default:
8595 device_printf(sc->sc_dev,
8596 "ucode debug unknown reason: %#x\n", reason);
8597 }
8598
8599 bwn_shm_write_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG,
8600 BWN_DEBUGINTR_ACK);
8601}
8602
8603static void
8604bwn_intr_tbtt_indication(struct bwn_mac *mac)
8605{
8606 struct bwn_softc *sc = mac->mac_sc;
8607 struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8608
8609 if (ic->ic_opmode != IEEE80211_M_HOSTAP)
8610 bwn_psctl(mac, 0);
8611 if (ic->ic_opmode == IEEE80211_M_IBSS)
8612 mac->mac_flags |= BWN_MAC_FLAG_DFQVALID;
8613}
8614
8615static void
8616bwn_intr_atim_end(struct bwn_mac *mac)
8617{
8618
8619 if (mac->mac_flags & BWN_MAC_FLAG_DFQVALID) {
8620 BWN_WRITE_4(mac, BWN_MACCMD,
8621 BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_DFQ_VALID);
8622 mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
8623 }
8624}
8625
8626static void
8627bwn_intr_beacon(struct bwn_mac *mac)
8628{
8629 struct bwn_softc *sc = mac->mac_sc;
8630 struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8631 uint32_t cmd, beacon0, beacon1;
8632
8633 if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
8634 ic->ic_opmode == IEEE80211_M_MBSS)
8635 return;
8636
8637 mac->mac_intr_mask &= ~BWN_INTR_BEACON;
8638
8639 cmd = BWN_READ_4(mac, BWN_MACCMD);
8640 beacon0 = (cmd & BWN_MACCMD_BEACON0_VALID);
8641 beacon1 = (cmd & BWN_MACCMD_BEACON1_VALID);
8642
8643 if (beacon0 && beacon1) {
8644 BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_BEACON);
8645 mac->mac_intr_mask |= BWN_INTR_BEACON;
8646 return;
8647 }
8648
8649 if (sc->sc_flags & BWN_FLAG_NEED_BEACON_TP) {
8650 sc->sc_flags &= ~BWN_FLAG_NEED_BEACON_TP;
8651 bwn_load_beacon0(mac);
8652 bwn_load_beacon1(mac);
8653 cmd = BWN_READ_4(mac, BWN_MACCMD);
8654 cmd |= BWN_MACCMD_BEACON0_VALID;
8655 BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8656 } else {
8657 if (!beacon0) {
8658 bwn_load_beacon0(mac);
8659 cmd = BWN_READ_4(mac, BWN_MACCMD);
8660 cmd |= BWN_MACCMD_BEACON0_VALID;
8661 BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8662 } else if (!beacon1) {
8663 bwn_load_beacon1(mac);
8664 cmd = BWN_READ_4(mac, BWN_MACCMD);
8665 cmd |= BWN_MACCMD_BEACON1_VALID;
8666 BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8667 }
8668 }
8669}
8670
8671static void
8672bwn_intr_pmq(struct bwn_mac *mac)
8673{
8674 uint32_t tmp;
8675
8676 while (1) {
8677 tmp = BWN_READ_4(mac, BWN_PS_STATUS);
8678 if (!(tmp & 0x00000008))
8679 break;
8680 }
8681 BWN_WRITE_2(mac, BWN_PS_STATUS, 0x0002);
8682}
8683
8684static void
8685bwn_intr_noise(struct bwn_mac *mac)
8686{
8687 struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
8688 uint16_t tmp;
8689 uint8_t noise[4];
8690 uint8_t i, j;
8691 int32_t average;
8692
8693 if (mac->mac_phy.type != BWN_PHYTYPE_G)
8694 return;
8695
8696 KASSERT(mac->mac_noise.noi_running, ("%s: fail", __func__));
8697 *((uint32_t *)noise) = htole32(bwn_jssi_read(mac));
8698 if (noise[0] == 0x7f || noise[1] == 0x7f || noise[2] == 0x7f ||
8699 noise[3] == 0x7f)
8700 goto new;
8701
8702 KASSERT(mac->mac_noise.noi_nsamples < 8,
8703 ("%s:%d: fail", __func__, __LINE__));
8704 i = mac->mac_noise.noi_nsamples;
8705 noise[0] = MIN(MAX(noise[0], 0), N(pg->pg_nrssi_lt) - 1);
8706 noise[1] = MIN(MAX(noise[1], 0), N(pg->pg_nrssi_lt) - 1);
8707 noise[2] = MIN(MAX(noise[2], 0), N(pg->pg_nrssi_lt) - 1);
8708 noise[3] = MIN(MAX(noise[3], 0), N(pg->pg_nrssi_lt) - 1);
8709 mac->mac_noise.noi_samples[i][0] = pg->pg_nrssi_lt[noise[0]];
8710 mac->mac_noise.noi_samples[i][1] = pg->pg_nrssi_lt[noise[1]];
8711 mac->mac_noise.noi_samples[i][2] = pg->pg_nrssi_lt[noise[2]];
8712 mac->mac_noise.noi_samples[i][3] = pg->pg_nrssi_lt[noise[3]];
8713 mac->mac_noise.noi_nsamples++;
8714 if (mac->mac_noise.noi_nsamples == 8) {
8715 average = 0;
8716 for (i = 0; i < 8; i++) {
8717 for (j = 0; j < 4; j++)
8718 average += mac->mac_noise.noi_samples[i][j];
8719 }
8720 average = (((average / 32) * 125) + 64) / 128;
8721 tmp = (bwn_shm_read_2(mac, BWN_SHARED, 0x40c) / 128) & 0x1f;
8722 if (tmp >= 8)
8723 average += 2;
8724 else
8725 average -= 25;
8726 average -= (tmp == 8) ? 72 : 48;
8727
8728 mac->mac_stats.link_noise = average;
8729 mac->mac_noise.noi_running = 0;
8730 return;
8731 }
8732new:
8733 bwn_noise_gensample(mac);
8734}
8735
8736static int
8737bwn_pio_rx(struct bwn_pio_rxqueue *prq)
8738{
8739 struct bwn_mac *mac = prq->prq_mac;
8740 struct bwn_softc *sc = mac->mac_sc;
8741 unsigned int i;
8742
8743 BWN_ASSERT_LOCKED(sc);
8744
8745 if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8746 return (0);
8747
8748 for (i = 0; i < 5000; i++) {
8749 if (bwn_pio_rxeof(prq) == 0)
8750 break;
8751 }
8752 if (i >= 5000)
8753 device_printf(sc->sc_dev, "too many RX frames in PIO mode\n");
8754 return ((i > 0) ? 1 : 0);
8755}
8756
8757static void
8758bwn_dma_rx(struct bwn_dma_ring *dr)
8759{
8760 int slot, curslot;
8761
8762 KASSERT(!dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
8763 curslot = dr->get_curslot(dr);
8764 KASSERT(curslot >= 0 && curslot < dr->dr_numslots,
8765 ("%s:%d: fail", __func__, __LINE__));
8766
8767 slot = dr->dr_curslot;
8768 for (; slot != curslot; slot = bwn_dma_nextslot(dr, slot))
8769 bwn_dma_rxeof(dr, &slot);
8770
8771 bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
8772 BUS_DMASYNC_PREWRITE);
8773
8774 dr->set_curslot(dr, slot);
8775 dr->dr_curslot = slot;
8776}
8777
8778static void
8779bwn_intr_txeof(struct bwn_mac *mac)
8780{
8781 struct bwn_txstatus stat;
8782 uint32_t stat0, stat1;
8783 uint16_t tmp;
8784
8785 BWN_ASSERT_LOCKED(mac->mac_sc);
8786
8787 while (1) {
8788 stat0 = BWN_READ_4(mac, BWN_XMITSTAT_0);
8789 if (!(stat0 & 0x00000001))
8790 break;
8791 stat1 = BWN_READ_4(mac, BWN_XMITSTAT_1);
8792
8793 stat.cookie = (stat0 >> 16);
8794 stat.seq = (stat1 & 0x0000ffff);
8795 stat.phy_stat = ((stat1 & 0x00ff0000) >> 16);
8796 tmp = (stat0 & 0x0000ffff);
8797 stat.framecnt = ((tmp & 0xf000) >> 12);
8798 stat.rtscnt = ((tmp & 0x0f00) >> 8);
8799 stat.sreason = ((tmp & 0x001c) >> 2);
8800 stat.pm = (tmp & 0x0080) ? 1 : 0;
8801 stat.im = (tmp & 0x0040) ? 1 : 0;
8802 stat.ampdu = (tmp & 0x0020) ? 1 : 0;
8803 stat.ack = (tmp & 0x0002) ? 1 : 0;
8804
8805 bwn_handle_txeof(mac, &stat);
8806 }
8807}
8808
8809static void
8810bwn_hwreset(void *arg, int npending)
8811{
8812 struct bwn_mac *mac = arg;
8813 struct bwn_softc *sc = mac->mac_sc;
8814 int error = 0;
8815 int prev_status;
8816
8817 BWN_LOCK(sc);
8818
8819 prev_status = mac->mac_status;
8820 if (prev_status >= BWN_MAC_STATUS_STARTED)
8821 bwn_core_stop(mac);
8822 if (prev_status >= BWN_MAC_STATUS_INITED)
8823 bwn_core_exit(mac);
8824
8825 if (prev_status >= BWN_MAC_STATUS_INITED) {
8826 error = bwn_core_init(mac);
8827 if (error)
8828 goto out;
8829 }
8830 if (prev_status >= BWN_MAC_STATUS_STARTED)
8831 bwn_core_start(mac);
8832out:
8833 if (error) {
8834 device_printf(sc->sc_dev, "%s: failed (%d)\n", __func__, error);
8835 sc->sc_curmac = NULL;
8836 }
8837 BWN_UNLOCK(sc);
8838}
8839
8840static void
8841bwn_handle_fwpanic(struct bwn_mac *mac)
8842{
8843 struct bwn_softc *sc = mac->mac_sc;
8844 uint16_t reason;
8845
8846 reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_FWPANIC_REASON_REG);
8847 device_printf(sc->sc_dev,"fw panic (%u)\n", reason);
8848
8849 if (reason == BWN_FWPANIC_RESTART)
8850 bwn_restart(mac, "ucode panic");
8851}
8852
8853static void
8854bwn_load_beacon0(struct bwn_mac *mac)
8855{
8856
8857 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8858}
8859
8860static void
8861bwn_load_beacon1(struct bwn_mac *mac)
8862{
8863
8864 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8865}
8866
8867static uint32_t
8868bwn_jssi_read(struct bwn_mac *mac)
8869{
8870 uint32_t val = 0;
8871
8872 val = bwn_shm_read_2(mac, BWN_SHARED, 0x08a);
8873 val <<= 16;
8874 val |= bwn_shm_read_2(mac, BWN_SHARED, 0x088);
8875
8876 return (val);
8877}
8878
8879static void
8880bwn_noise_gensample(struct bwn_mac *mac)
8881{
8882 uint32_t jssi = 0x7f7f7f7f;
8883
8884 bwn_shm_write_2(mac, BWN_SHARED, 0x088, (jssi & 0x0000ffff));
8885 bwn_shm_write_2(mac, BWN_SHARED, 0x08a, (jssi & 0xffff0000) >> 16);
8886 BWN_WRITE_4(mac, BWN_MACCMD,
8887 BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_BGNOISE);
8888}
8889
8890static int
8891bwn_dma_freeslot(struct bwn_dma_ring *dr)
8892{
8893 BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8894
8895 return (dr->dr_numslots - dr->dr_usedslot);
8896}
8897
8898static int
8899bwn_dma_nextslot(struct bwn_dma_ring *dr, int slot)
8900{
8901 BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8902
8903 KASSERT(slot >= -1 && slot <= dr->dr_numslots - 1,
8904 ("%s:%d: fail", __func__, __LINE__));
8905 if (slot == dr->dr_numslots - 1)
8906 return (0);
8907 return (slot + 1);
8908}
8909
8910static void
8911bwn_dma_rxeof(struct bwn_dma_ring *dr, int *slot)
8912{
8913 struct bwn_mac *mac = dr->dr_mac;
8914 struct bwn_softc *sc = mac->mac_sc;
8915 struct bwn_dma *dma = &mac->mac_method.dma;
8916 struct bwn_dmadesc_generic *desc;
8917 struct bwn_dmadesc_meta *meta;
8918 struct bwn_rxhdr4 *rxhdr;
8919 struct ifnet *ifp = sc->sc_ifp;
8920 struct mbuf *m;
8921 uint32_t macstat;
8922 int32_t tmp;
8923 int cnt = 0;
8924 uint16_t len;
8925
8926 dr->getdesc(dr, *slot, &desc, &meta);
8927
8928 bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap, BUS_DMASYNC_POSTREAD);
8929 m = meta->mt_m;
8930
8931 if (bwn_dma_newbuf(dr, desc, meta, 0)) {
8932 ifp->if_ierrors++;
8933 return;
8934 }
8935
8936 rxhdr = mtod(m, struct bwn_rxhdr4 *);
8937 len = le16toh(rxhdr->frame_len);
8938 if (len <= 0) {
8939 ifp->if_ierrors++;
8940 return;
8941 }
8942 if (bwn_dma_check_redzone(dr, m)) {
8943 device_printf(sc->sc_dev, "redzone error.\n");
8944 bwn_dma_set_redzone(dr, m);
8945 bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
8946 BUS_DMASYNC_PREWRITE);
8947 return;
8948 }
8949 if (len > dr->dr_rx_bufsize) {
8950 tmp = len;
8951 while (1) {
8952 dr->getdesc(dr, *slot, &desc, &meta);
8953 bwn_dma_set_redzone(dr, meta->mt_m);
8954 bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
8955 BUS_DMASYNC_PREWRITE);
8956 *slot = bwn_dma_nextslot(dr, *slot);
8957 cnt++;
8958 tmp -= dr->dr_rx_bufsize;
8959 if (tmp <= 0)
8960 break;
8961 }
8962 device_printf(sc->sc_dev, "too small buffer "
8963 "(len %u buffer %u dropped %d)\n",
8964 len, dr->dr_rx_bufsize, cnt);
8965 return;
8966 }
8967 macstat = le32toh(rxhdr->mac_status);
8968 if (macstat & BWN_RX_MAC_FCSERR) {
8969 if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
8970 device_printf(sc->sc_dev, "RX drop\n");
8971 return;
8972 }
8973 }
8974
8975 m->m_pkthdr.rcvif = ifp;
8976 m->m_len = m->m_pkthdr.len = len + dr->dr_frameoffset;
8977 m_adj(m, dr->dr_frameoffset);
8978
8979 bwn_rxeof(dr->dr_mac, m, rxhdr);
8980}
8981
8982static void
8983bwn_handle_txeof(struct bwn_mac *mac, const struct bwn_txstatus *status)
8984{
8985 struct bwn_dma_ring *dr;
8986 struct bwn_dmadesc_generic *desc;
8987 struct bwn_dmadesc_meta *meta;
8988 struct bwn_pio_txqueue *tq;
8989 struct bwn_pio_txpkt *tp = NULL;
8990 struct bwn_softc *sc = mac->mac_sc;
8991 struct bwn_stats *stats = &mac->mac_stats;
8992 struct ieee80211_node *ni;
8993 struct ieee80211vap *vap;
8994 int retrycnt = 0, slot;
8995
8996 BWN_ASSERT_LOCKED(mac->mac_sc);
8997
8998 if (status->im)
8999 device_printf(sc->sc_dev, "TODO: STATUS IM\n");
9000 if (status->ampdu)
9001 device_printf(sc->sc_dev, "TODO: STATUS AMPDU\n");
9002 if (status->rtscnt) {
9003 if (status->rtscnt == 0xf)
9004 stats->rtsfail++;
9005 else
9006 stats->rts++;
9007 }
9008
9009 if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
9010 if (status->ack) {
9011 dr = bwn_dma_parse_cookie(mac, status,
9012 status->cookie, &slot);
9013 if (dr == NULL) {
9014 device_printf(sc->sc_dev,
9015 "failed to parse cookie\n");
9016 return;
9017 }
9018 while (1) {
9019 dr->getdesc(dr, slot, &desc, &meta);
9020 if (meta->mt_islast) {
9021 ni = meta->mt_ni;
9022 vap = ni->ni_vap;
9023 ieee80211_ratectl_tx_complete(vap, ni,
9024 status->ack ?
9025 IEEE80211_RATECTL_TX_SUCCESS :
9026 IEEE80211_RATECTL_TX_FAILURE,
9027 &retrycnt, 0);
9028 break;
9029 }
9030 slot = bwn_dma_nextslot(dr, slot);
9031 }
9032 }
9033 bwn_dma_handle_txeof(mac, status);
9034 } else {
9035 if (status->ack) {
9036 tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9037 if (tq == NULL) {
9038 device_printf(sc->sc_dev,
9039 "failed to parse cookie\n");
9040 return;
9041 }
9042 ni = tp->tp_ni;
9043 vap = ni->ni_vap;
9044 ieee80211_ratectl_tx_complete(vap, ni,
9045 status->ack ?
9046 IEEE80211_RATECTL_TX_SUCCESS :
9047 IEEE80211_RATECTL_TX_FAILURE,
9048 &retrycnt, 0);
9049 }
9050 bwn_pio_handle_txeof(mac, status);
9051 }
9052
9053 bwn_phy_txpower_check(mac, 0);
9054}
9055
9056static uint8_t
9057bwn_pio_rxeof(struct bwn_pio_rxqueue *prq)
9058{
9059 struct bwn_mac *mac = prq->prq_mac;
9060 struct bwn_softc *sc = mac->mac_sc;
9061 struct bwn_rxhdr4 rxhdr;
9062 struct ifnet *ifp = sc->sc_ifp;
9063 struct mbuf *m;
9064 uint32_t ctl32, macstat, v32;
9065 unsigned int i, padding;
9066 uint16_t ctl16, len, totlen, v16;
9067 unsigned char *mp;
9068 char *data;
9069
9070 memset(&rxhdr, 0, sizeof(rxhdr));
9071
9072 if (prq->prq_rev >= 8) {
9073 ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
9074 if (!(ctl32 & BWN_PIO8_RXCTL_FRAMEREADY))
9075 return (0);
9076 bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9077 BWN_PIO8_RXCTL_FRAMEREADY);
9078 for (i = 0; i < 10; i++) {
9079 ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
9080 if (ctl32 & BWN_PIO8_RXCTL_DATAREADY)
9081 goto ready;
9082 DELAY(10);
9083 }
9084 } else {
9085 ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
9086 if (!(ctl16 & BWN_PIO_RXCTL_FRAMEREADY))
9087 return (0);
9088 bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL,
9089 BWN_PIO_RXCTL_FRAMEREADY);
9090 for (i = 0; i < 10; i++) {
9091 ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
9092 if (ctl16 & BWN_PIO_RXCTL_DATAREADY)
9093 goto ready;
9094 DELAY(10);
9095 }
9096 }
9097 device_printf(sc->sc_dev, "%s: timed out\n", __func__);
9098 return (1);
9099ready:
9100 if (prq->prq_rev >= 8)
9101 siba_read_multi_4(sc->sc_dev, &rxhdr, sizeof(rxhdr),
9102 prq->prq_base + BWN_PIO8_RXDATA);
9103 else
9104 siba_read_multi_2(sc->sc_dev, &rxhdr, sizeof(rxhdr),
9105 prq->prq_base + BWN_PIO_RXDATA);
9106 len = le16toh(rxhdr.frame_len);
9107 if (len > 0x700) {
9108 device_printf(sc->sc_dev, "%s: len is too big\n", __func__);
9109 goto error;
9110 }
9111 if (len == 0) {
9112 device_printf(sc->sc_dev, "%s: len is 0\n", __func__);
9113 goto error;
9114 }
9115
9116 macstat = le32toh(rxhdr.mac_status);
9117 if (macstat & BWN_RX_MAC_FCSERR) {
9118 if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
9119 device_printf(sc->sc_dev, "%s: FCS error", __func__);
9120 goto error;
9121 }
9122 }
9123
9124 padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9125 totlen = len + padding;
9126 KASSERT(totlen <= MCLBYTES, ("too big..\n"));
9127 m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
9128 if (m == NULL) {
9129 device_printf(sc->sc_dev, "%s: out of memory", __func__);
9130 goto error;
9131 }
9132 mp = mtod(m, unsigned char *);
9133 if (prq->prq_rev >= 8) {
9134 siba_read_multi_4(sc->sc_dev, mp, (totlen & ~3),
9135 prq->prq_base + BWN_PIO8_RXDATA);
9136 if (totlen & 3) {
9137 v32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXDATA);
9138 data = &(mp[totlen - 1]);
9139 switch (totlen & 3) {
9140 case 3:
9141 *data = (v32 >> 16);
9142 data--;
9143 case 2:
9144 *data = (v32 >> 8);
9145 data--;
9146 case 1:
9147 *data = v32;
9148 }
9149 }
9150 } else {
9151 siba_read_multi_2(sc->sc_dev, mp, (totlen & ~1),
9152 prq->prq_base + BWN_PIO_RXDATA);
9153 if (totlen & 1) {
9154 v16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXDATA);
9155 mp[totlen - 1] = v16;
9156 }
9157 }
9158
9159 m->m_pkthdr.rcvif = ifp;
9160 m->m_len = m->m_pkthdr.len = totlen;
9161
9162 bwn_rxeof(prq->prq_mac, m, &rxhdr);
9163
9164 return (1);
9165error:
9166 if (prq->prq_rev >= 8)
9167 bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9168 BWN_PIO8_RXCTL_DATAREADY);
9169 else
9170 bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL, BWN_PIO_RXCTL_DATAREADY);
9171 return (1);
9172}
9173
9174static int
9175bwn_dma_newbuf(struct bwn_dma_ring *dr, struct bwn_dmadesc_generic *desc,
9176 struct bwn_dmadesc_meta *meta, int init)
9177{
9178 struct bwn_mac *mac = dr->dr_mac;
9179 struct bwn_dma *dma = &mac->mac_method.dma;
9180 struct bwn_rxhdr4 *hdr;
9181 bus_dmamap_t map;
9182 bus_addr_t paddr;
9183 struct mbuf *m;
9184 int error;
9185
9186 m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
9187 if (m == NULL) {
9188 error = ENOBUFS;
9189
9190 /*
9191 * If the NIC is up and running, we need to:
9192 * - Clear RX buffer's header.
9193 * - Restore RX descriptor settings.
9194 */
9195 if (init)
9196 return (error);
9197 else
9198 goto back;
9199 }
9200 m->m_len = m->m_pkthdr.len = MCLBYTES;
9201
9202 bwn_dma_set_redzone(dr, m);
9203
9204 /*
9205 * Try to load RX buf into temporary DMA map
9206 */
9207 error = bus_dmamap_load_mbuf(dma->rxbuf_dtag, dr->dr_spare_dmap, m,
9208 bwn_dma_buf_addr, &paddr, BUS_DMA_NOWAIT);
9209 if (error) {
9210 m_freem(m);
9211
9212 /*
9213 * See the comment above
9214 */
9215 if (init)
9216 return (error);
9217 else
9218 goto back;
9219 }
9220
9221 if (!init)
9222 bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
9223 meta->mt_m = m;
9224 meta->mt_paddr = paddr;
9225
9226 /*
9227 * Swap RX buf's DMA map with the loaded temporary one
9228 */
9229 map = meta->mt_dmap;
9230 meta->mt_dmap = dr->dr_spare_dmap;
9231 dr->dr_spare_dmap = map;
9232
9233back:
9234 /*
9235 * Clear RX buf header
9236 */
9237 hdr = mtod(meta->mt_m, struct bwn_rxhdr4 *);
9238 bzero(hdr, sizeof(*hdr));
9239 bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
9240 BUS_DMASYNC_PREWRITE);
9241
9242 /*
9243 * Setup RX buf descriptor
9244 */
9245 dr->setdesc(dr, desc, paddr, meta->mt_m->m_len -
9246 sizeof(*hdr), 0, 0, 0);
9247 return (error);
9248}
9249
9250static void
9251bwn_dma_buf_addr(void *arg, bus_dma_segment_t *seg, int nseg,
9252 bus_size_t mapsz __unused, int error)
9253{
9254
9255 if (!error) {
9256 KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
9257 *((bus_addr_t *)arg) = seg->ds_addr;
9258 }
9259}
9260
9261static int
9262bwn_hwrate2ieeerate(int rate)
9263{
9264
9265 switch (rate) {
9266 case BWN_CCK_RATE_1MB:
9267 return (2);
9268 case BWN_CCK_RATE_2MB:
9269 return (4);
9270 case BWN_CCK_RATE_5MB:
9271 return (11);
9272 case BWN_CCK_RATE_11MB:
9273 return (22);
9274 case BWN_OFDM_RATE_6MB:
9275 return (12);
9276 case BWN_OFDM_RATE_9MB:
9277 return (18);
9278 case BWN_OFDM_RATE_12MB:
9279 return (24);
9280 case BWN_OFDM_RATE_18MB:
9281 return (36);
9282 case BWN_OFDM_RATE_24MB:
9283 return (48);
9284 case BWN_OFDM_RATE_36MB:
9285 return (72);
9286 case BWN_OFDM_RATE_48MB:
9287 return (96);
9288 case BWN_OFDM_RATE_54MB:
9289 return (108);
9290 default:
9291 printf("Ooops\n");
9292 return (0);
9293 }
9294}
9295
9296static void
9297bwn_rxeof(struct bwn_mac *mac, struct mbuf *m, const void *_rxhdr)
9298{
9299 const struct bwn_rxhdr4 *rxhdr = _rxhdr;
9300 struct bwn_plcp6 *plcp;
9301 struct bwn_softc *sc = mac->mac_sc;
9302 struct ieee80211_frame_min *wh;
9303 struct ieee80211_node *ni;
9304 struct ifnet *ifp = sc->sc_ifp;
9305 struct ieee80211com *ic = ifp->if_l2com;
9306 uint32_t macstat;
9307 int padding, rate, rssi = 0, noise = 0, type;
9308 uint16_t phytype, phystat0, phystat3, chanstat;
9309 unsigned char *mp = mtod(m, unsigned char *);
9310 static int rx_mac_dec_rpt = 0;
9311
9312 BWN_ASSERT_LOCKED(sc);
9313
9314 phystat0 = le16toh(rxhdr->phy_status0);
9315 phystat3 = le16toh(rxhdr->phy_status3);
9316 macstat = le32toh(rxhdr->mac_status);
9317 chanstat = le16toh(rxhdr->channel);
9318 phytype = chanstat & BWN_RX_CHAN_PHYTYPE;
9319
9320 if (macstat & BWN_RX_MAC_FCSERR)
9321 device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_FCS_CRC\n");
9322 if (phystat0 & (BWN_RX_PHYST0_PLCPHCF | BWN_RX_PHYST0_PLCPFV))
9323 device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_PLCP_CRC\n");
9324 if (macstat & BWN_RX_MAC_DECERR)
9325 goto drop;
9326
9327 padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9328 if (m->m_pkthdr.len < (sizeof(struct bwn_plcp6) + padding)) {
9329 device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9330 m->m_pkthdr.len);
9331 goto drop;
9332 }
9333 plcp = (struct bwn_plcp6 *)(mp + padding);
9334 m_adj(m, sizeof(struct bwn_plcp6) + padding);
9335 if (m->m_pkthdr.len < IEEE80211_MIN_LEN) {
9336 device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9337 m->m_pkthdr.len);
9338 goto drop;
9339 }
9340 wh = mtod(m, struct ieee80211_frame_min *);
9341
9342 if (macstat & BWN_RX_MAC_DEC && rx_mac_dec_rpt++ < 50)
9343 device_printf(sc->sc_dev,
9344 "RX decryption attempted (old %d keyidx %#x)\n",
9345 BWN_ISOLDFMT(mac),
9346 (macstat & BWN_RX_MAC_KEYIDX) >> BWN_RX_MAC_KEYIDX_SHIFT);
9347
9348 /* XXX calculating RSSI & noise & antenna */
9349
9350 if (phystat0 & BWN_RX_PHYST0_OFDM)
9351 rate = bwn_plcp_get_ofdmrate(mac, plcp,
9352 phytype == BWN_PHYTYPE_A);
9353 else
9354 rate = bwn_plcp_get_cckrate(mac, plcp);
9355 if (rate == -1) {
9356 if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADPLCP))
9357 goto drop;
9358 }
9359 sc->sc_rx_rate = bwn_hwrate2ieeerate(rate);
9360
9361 /* RX radio tap */
9362 if (ieee80211_radiotap_active(ic))
9363 bwn_rx_radiotap(mac, m, rxhdr, plcp, rate, rssi, noise);
9364 m_adj(m, -IEEE80211_CRC_LEN);
9365
9366 rssi = rxhdr->phy.abg.rssi; /* XXX incorrect RSSI calculation? */
9367 noise = mac->mac_stats.link_noise;
9368
9369 ifp->if_ipackets++;
9370
9371 BWN_UNLOCK(sc);
9372
9373 ni = ieee80211_find_rxnode(ic, wh);
9374 if (ni != NULL) {
9375 type = ieee80211_input(ni, m, rssi, noise);
9376 ieee80211_free_node(ni);
9377 } else
9378 type = ieee80211_input_all(ic, m, rssi, noise);
9379
9380 BWN_LOCK(sc);
9381 return;
9382drop:
9383 device_printf(sc->sc_dev, "%s: dropped\n", __func__);
9384}
9385
9386static void
9387bwn_dma_handle_txeof(struct bwn_mac *mac,
9388 const struct bwn_txstatus *status)
9389{
9390 struct bwn_dma *dma = &mac->mac_method.dma;
9391 struct bwn_dma_ring *dr;
9392 struct bwn_dmadesc_generic *desc;
9393 struct bwn_dmadesc_meta *meta;
9394 struct bwn_softc *sc = mac->mac_sc;
9395 struct ieee80211_node *ni;
9396 struct ifnet *ifp = sc->sc_ifp;
9397 struct mbuf *m;
9398 int slot;
9399
9400 BWN_ASSERT_LOCKED(sc);
9401
9402 dr = bwn_dma_parse_cookie(mac, status, status->cookie, &slot);
9403 if (dr == NULL) {
9404 device_printf(sc->sc_dev, "failed to parse cookie\n");
9405 return;
9406 }
9407 KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
9408
9409 while (1) {
9410 KASSERT(slot >= 0 && slot < dr->dr_numslots,
9411 ("%s:%d: fail", __func__, __LINE__));
9412 dr->getdesc(dr, slot, &desc, &meta);
9413
9414 if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
9415 bus_dmamap_unload(dr->dr_txring_dtag, meta->mt_dmap);
9416 else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
9417 bus_dmamap_unload(dma->txbuf_dtag, meta->mt_dmap);
9418
9419 if (meta->mt_islast) {
9420 KASSERT(meta->mt_m != NULL,
9421 ("%s:%d: fail", __func__, __LINE__));
9422
9423 ni = meta->mt_ni;
9424 m = meta->mt_m;
9425 if (ni != NULL) {
9426 /*
9427 * Do any tx complete callback. Note this must
9428 * be done before releasing the node reference.
9429 */
9430 if (m->m_flags & M_TXCB)
9431 ieee80211_process_callback(ni, m, 0);
9432 ieee80211_free_node(ni);
9433 meta->mt_ni = NULL;
9434 }
9435 m_freem(m);
9436 meta->mt_m = NULL;
9437 } else {
9438 KASSERT(meta->mt_m == NULL,
9439 ("%s:%d: fail", __func__, __LINE__));
9440 }
9441
9442 dr->dr_usedslot--;
9443 if (meta->mt_islast) {
9444 ifp->if_opackets++;
9445 break;
9446 }
9447 slot = bwn_dma_nextslot(dr, slot);
9448 }
9449 sc->sc_watchdog_timer = 0;
9450 if (dr->dr_stop) {
9451 KASSERT(bwn_dma_freeslot(dr) >= BWN_TX_SLOTS_PER_FRAME,
9452 ("%s:%d: fail", __func__, __LINE__));
9453 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
9454 dr->dr_stop = 0;
9455 }
9456}
9457
9458static void
9459bwn_pio_handle_txeof(struct bwn_mac *mac,
9460 const struct bwn_txstatus *status)
9461{
9462 struct bwn_pio_txqueue *tq;
9463 struct bwn_pio_txpkt *tp = NULL;
9464 struct bwn_softc *sc = mac->mac_sc;
9465 struct ifnet *ifp = sc->sc_ifp;
9466
9467 BWN_ASSERT_LOCKED(sc);
9468
9469 tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9470 if (tq == NULL)
9471 return;
9472
9473 tq->tq_used -= roundup(tp->tp_m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
9474 tq->tq_free++;
9475
9476 if (tp->tp_ni != NULL) {
9477 /*
9478 * Do any tx complete callback. Note this must
9479 * be done before releasing the node reference.
9480 */
9481 if (tp->tp_m->m_flags & M_TXCB)
9482 ieee80211_process_callback(tp->tp_ni, tp->tp_m, 0);
9483 ieee80211_free_node(tp->tp_ni);
9484 tp->tp_ni = NULL;
9485 }
9486 m_freem(tp->tp_m);
9487 tp->tp_m = NULL;
9488 TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
9489
9490 ifp->if_opackets++;
9491
9492 sc->sc_watchdog_timer = 0;
9493 if (tq->tq_stop) {
9494 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
9495 tq->tq_stop = 0;
9496 }
9497}
9498
9499static void
9500bwn_phy_txpower_check(struct bwn_mac *mac, uint32_t flags)
9501{
9502 struct bwn_softc *sc = mac->mac_sc;
9503 struct bwn_phy *phy = &mac->mac_phy;
9504 struct ifnet *ifp = sc->sc_ifp;
9505 struct ieee80211com *ic = ifp->if_l2com;
9506 unsigned long now;
9507 int result;
9508
9509 BWN_GETTIME(now);
9510
9511 if (!(flags & BWN_TXPWR_IGNORE_TIME) && time_before(now, phy->nexttime))
9512 return;
9513 phy->nexttime = now + 2 * 1000;
9514
9515 if (siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM &&
9516 siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306)
9517 return;
9518
9519 if (phy->recalc_txpwr != NULL) {
9520 result = phy->recalc_txpwr(mac,
9521 (flags & BWN_TXPWR_IGNORE_TSSI) ? 1 : 0);
9522 if (result == BWN_TXPWR_RES_DONE)
9523 return;
9524 KASSERT(result == BWN_TXPWR_RES_NEED_ADJUST,
9525 ("%s: fail", __func__));
9526 KASSERT(phy->set_txpwr != NULL, ("%s: fail", __func__));
9527
9528 ieee80211_runtask(ic, &mac->mac_txpower);
9529 }
9530}
9531
9532static uint16_t
9533bwn_pio_rx_read_2(struct bwn_pio_rxqueue *prq, uint16_t offset)
9534{
9535
9536 return (BWN_READ_2(prq->prq_mac, prq->prq_base + offset));
9537}
9538
9539static uint32_t
9540bwn_pio_rx_read_4(struct bwn_pio_rxqueue *prq, uint16_t offset)
9541{
9542
9543 return (BWN_READ_4(prq->prq_mac, prq->prq_base + offset));
9544}
9545
9546static void
9547bwn_pio_rx_write_2(struct bwn_pio_rxqueue *prq, uint16_t offset, uint16_t value)
9548{
9549
9550 BWN_WRITE_2(prq->prq_mac, prq->prq_base + offset, value);
9551}
9552
9553static void
9554bwn_pio_rx_write_4(struct bwn_pio_rxqueue *prq, uint16_t offset, uint32_t value)
9555{
9556
9557 BWN_WRITE_4(prq->prq_mac, prq->prq_base + offset, value);
9558}
9559
9560static int
9561bwn_ieeerate2hwrate(struct bwn_softc *sc, int rate)
9562{
9563
9564 switch (rate) {
9565 /* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
9566 case 12:
9567 return (BWN_OFDM_RATE_6MB);
9568 case 18:
9569 return (BWN_OFDM_RATE_9MB);
9570 case 24:
9571 return (BWN_OFDM_RATE_12MB);
9572 case 36:
9573 return (BWN_OFDM_RATE_18MB);
9574 case 48:
9575 return (BWN_OFDM_RATE_24MB);
9576 case 72:
9577 return (BWN_OFDM_RATE_36MB);
9578 case 96:
9579 return (BWN_OFDM_RATE_48MB);
9580 case 108:
9581 return (BWN_OFDM_RATE_54MB);
9582 /* CCK rates (NB: not IEEE std, device-specific) */
9583 case 2:
9584 return (BWN_CCK_RATE_1MB);
9585 case 4:
9586 return (BWN_CCK_RATE_2MB);
9587 case 11:
9588 return (BWN_CCK_RATE_5MB);
9589 case 22:
9590 return (BWN_CCK_RATE_11MB);
9591 }
9592
9593 device_printf(sc->sc_dev, "unsupported rate %d\n", rate);
9594 return (BWN_CCK_RATE_1MB);
9595}
9596
9597static int
9598bwn_set_txhdr(struct bwn_mac *mac, struct ieee80211_node *ni,
9599 struct mbuf *m, struct bwn_txhdr *txhdr, uint16_t cookie)
9600{
9601 const struct bwn_phy *phy = &mac->mac_phy;
9602 struct bwn_softc *sc = mac->mac_sc;
9603 struct ieee80211_frame *wh;
9604 struct ieee80211_frame *protwh;
9605 struct ieee80211_frame_cts *cts;
9606 struct ieee80211_frame_rts *rts;
9607 const struct ieee80211_txparam *tp;
9608 struct ieee80211vap *vap = ni->ni_vap;
9609 struct ifnet *ifp = sc->sc_ifp;
9610 struct ieee80211com *ic = ifp->if_l2com;
9611 struct mbuf *mprot;
9612 unsigned int len;
9613 uint32_t macctl = 0;
9614 int protdur, rts_rate, rts_rate_fb, ismcast, isshort, rix, type;
9615 uint16_t phyctl = 0;
9616 uint8_t rate, rate_fb;
9617
9618 wh = mtod(m, struct ieee80211_frame *);
9619 memset(txhdr, 0, sizeof(*txhdr));
9620
9621 type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
9622 ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
9623 isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0;
9624
9625 /*
9626 * Find TX rate
9627 */
9628 tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)];
9629 if (type != IEEE80211_FC0_TYPE_DATA || (m->m_flags & M_EAPOL))
9630 rate = rate_fb = tp->mgmtrate;
9631 else if (ismcast)
9632 rate = rate_fb = tp->mcastrate;
9633 else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
9634 rate = rate_fb = tp->ucastrate;
9635 else {
9636 rix = ieee80211_ratectl_rate(ni, NULL, 0);
9637 rate = ni->ni_txrate;
9638
9639 if (rix > 0)
9640 rate_fb = ni->ni_rates.rs_rates[rix - 1] &
9641 IEEE80211_RATE_VAL;
9642 else
9643 rate_fb = rate;
9644 }
9645
9646 sc->sc_tx_rate = rate;
9647
9648 rate = bwn_ieeerate2hwrate(sc, rate);
9649 rate_fb = bwn_ieeerate2hwrate(sc, rate_fb);
9650
9651 txhdr->phyrate = (BWN_ISOFDMRATE(rate)) ? bwn_plcp_getofdm(rate) :
9652 bwn_plcp_getcck(rate);
9653 bcopy(wh->i_fc, txhdr->macfc, sizeof(txhdr->macfc));
9654 bcopy(wh->i_addr1, txhdr->addr1, IEEE80211_ADDR_LEN);
9655
9656 if ((rate_fb == rate) ||
9657 (*(u_int16_t *)wh->i_dur & htole16(0x8000)) ||
9658 (*(u_int16_t *)wh->i_dur == htole16(0)))
9659 txhdr->dur_fb = *(u_int16_t *)wh->i_dur;
9660 else
9661 txhdr->dur_fb = ieee80211_compute_duration(ic->ic_rt,
9662 m->m_pkthdr.len, rate, isshort);
9663
9664 /* XXX TX encryption */
9665 bwn_plcp_genhdr(BWN_ISOLDFMT(mac) ?
9666 (struct bwn_plcp4 *)(&txhdr->body.old.plcp) :
9667 (struct bwn_plcp4 *)(&txhdr->body.new.plcp),
9668 m->m_pkthdr.len + IEEE80211_CRC_LEN, rate);
9669 bwn_plcp_genhdr((struct bwn_plcp4 *)(&txhdr->plcp_fb),
9670 m->m_pkthdr.len + IEEE80211_CRC_LEN, rate_fb);
9671
9672 txhdr->eftypes |= (BWN_ISOFDMRATE(rate_fb)) ? BWN_TX_EFT_FB_OFDM :
9673 BWN_TX_EFT_FB_CCK;
9674 txhdr->chan = phy->chan;
9675 phyctl |= (BWN_ISOFDMRATE(rate)) ? BWN_TX_PHY_ENC_OFDM :
9676 BWN_TX_PHY_ENC_CCK;
9677 if (isshort && (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9678 rate == BWN_CCK_RATE_11MB))
9679 phyctl |= BWN_TX_PHY_SHORTPRMBL;
9680
9681 /* XXX TX antenna selection */
9682
9683 switch (bwn_antenna_sanitize(mac, 0)) {
9684 case 0:
9685 phyctl |= BWN_TX_PHY_ANT01AUTO;
9686 break;
9687 case 1:
9688 phyctl |= BWN_TX_PHY_ANT0;
9689 break;
9690 case 2:
9691 phyctl |= BWN_TX_PHY_ANT1;
9692 break;
9693 case 3:
9694 phyctl |= BWN_TX_PHY_ANT2;
9695 break;
9696 case 4:
9697 phyctl |= BWN_TX_PHY_ANT3;
9698 break;
9699 default:
9700 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9701 }
9702
9703 if (!ismcast)
9704 macctl |= BWN_TX_MAC_ACK;
9705
9706 macctl |= (BWN_TX_MAC_HWSEQ | BWN_TX_MAC_START_MSDU);
9707 if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
9708 m->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold)
9709 macctl |= BWN_TX_MAC_LONGFRAME;
9710
9711 if (ic->ic_flags & IEEE80211_F_USEPROT) {
9712 /* XXX RTS rate is always 1MB??? */
9713 rts_rate = BWN_CCK_RATE_1MB;
9714 rts_rate_fb = bwn_get_fbrate(rts_rate);
9715
9716 protdur = ieee80211_compute_duration(ic->ic_rt,
9717 m->m_pkthdr.len, rate, isshort) +
9718 + ieee80211_ack_duration(ic->ic_rt, rate, isshort);
9719
9720 if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) {
9721 cts = (struct ieee80211_frame_cts *)(BWN_ISOLDFMT(mac) ?
9722 (txhdr->body.old.rts_frame) :
9723 (txhdr->body.new.rts_frame));
9724 mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr,
9725 protdur);
9726 KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9727 bcopy(mtod(mprot, uint8_t *), (uint8_t *)cts,
9728 mprot->m_pkthdr.len);
9729 m_freem(mprot);
9730 macctl |= BWN_TX_MAC_SEND_CTSTOSELF;
9731 len = sizeof(struct ieee80211_frame_cts);
9732 } else {
9733 rts = (struct ieee80211_frame_rts *)(BWN_ISOLDFMT(mac) ?
9734 (txhdr->body.old.rts_frame) :
9735 (txhdr->body.new.rts_frame));
9736 protdur += ieee80211_ack_duration(ic->ic_rt, rate,
9737 isshort);
9738 mprot = ieee80211_alloc_rts(ic, wh->i_addr1,
9739 wh->i_addr2, protdur);
9740 KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9741 bcopy(mtod(mprot, uint8_t *), (uint8_t *)rts,
9742 mprot->m_pkthdr.len);
9743 m_freem(mprot);
9744 macctl |= BWN_TX_MAC_SEND_RTSCTS;
9745 len = sizeof(struct ieee80211_frame_rts);
9746 }
9747 len += IEEE80211_CRC_LEN;
9748 bwn_plcp_genhdr((struct bwn_plcp4 *)((BWN_ISOLDFMT(mac)) ?
9749 &txhdr->body.old.rts_plcp :
9750 &txhdr->body.new.rts_plcp), len, rts_rate);
9751 bwn_plcp_genhdr((struct bwn_plcp4 *)&txhdr->rts_plcp_fb, len,
9752 rts_rate_fb);
9753
9754 protwh = (struct ieee80211_frame *)(BWN_ISOLDFMT(mac) ?
9755 (&txhdr->body.old.rts_frame) :
9756 (&txhdr->body.new.rts_frame));
9757 txhdr->rts_dur_fb = *(u_int16_t *)protwh->i_dur;
9758
9759 if (BWN_ISOFDMRATE(rts_rate)) {
9760 txhdr->eftypes |= BWN_TX_EFT_RTS_OFDM;
9761 txhdr->phyrate_rts = bwn_plcp_getofdm(rts_rate);
9762 } else {
9763 txhdr->eftypes |= BWN_TX_EFT_RTS_CCK;
9764 txhdr->phyrate_rts = bwn_plcp_getcck(rts_rate);
9765 }
9766 txhdr->eftypes |= (BWN_ISOFDMRATE(rts_rate_fb)) ?
9767 BWN_TX_EFT_RTS_FBOFDM : BWN_TX_EFT_RTS_FBCCK;
9768 }
9769
9770 if (BWN_ISOLDFMT(mac))
9771 txhdr->body.old.cookie = htole16(cookie);
9772 else
9773 txhdr->body.new.cookie = htole16(cookie);
9774
9775 txhdr->macctl = htole32(macctl);
9776 txhdr->phyctl = htole16(phyctl);
9777
9778 /*
9779 * TX radio tap
9780 */
9781 if (ieee80211_radiotap_active_vap(vap)) {
9782 sc->sc_tx_th.wt_flags = 0;
9783 if (wh->i_fc[1] & IEEE80211_FC1_WEP)
9784 sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP;
9785 if (isshort &&
9786 (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9787 rate == BWN_CCK_RATE_11MB))
9788 sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
9789 sc->sc_tx_th.wt_rate = rate;
9790
9791 ieee80211_radiotap_tx(vap, m);
9792 }
9793
9794 return (0);
9795}
9796
9797static void
9798bwn_plcp_genhdr(struct bwn_plcp4 *plcp, const uint16_t octets,
9799 const uint8_t rate)
9800{
9801 uint32_t d, plen;
9802 uint8_t *raw = plcp->o.raw;
9803
9804 if (BWN_ISOFDMRATE(rate)) {
9805 d = bwn_plcp_getofdm(rate);
9806 KASSERT(!(octets & 0xf000),
9807 ("%s:%d: fail", __func__, __LINE__));
9808 d |= (octets << 5);
9809 plcp->o.data = htole32(d);
9810 } else {
9811 plen = octets * 16 / rate;
9812 if ((octets * 16 % rate) > 0) {
9813 plen++;
9814 if ((rate == BWN_CCK_RATE_11MB)
9815 && ((octets * 8 % 11) < 4)) {
9816 raw[1] = 0x84;
9817 } else
9818 raw[1] = 0x04;
9819 } else
9820 raw[1] = 0x04;
9821 plcp->o.data |= htole32(plen << 16);
9822 raw[0] = bwn_plcp_getcck(rate);
9823 }
9824}
9825
9826static uint8_t
9827bwn_antenna_sanitize(struct bwn_mac *mac, uint8_t n)
9828{
9829 struct bwn_softc *sc = mac->mac_sc;
9830 uint8_t mask;
9831
9832 if (n == 0)
9833 return (0);
9834 if (mac->mac_phy.gmode)
9835 mask = siba_sprom_get_ant_bg(sc->sc_dev);
9836 else
9837 mask = siba_sprom_get_ant_a(sc->sc_dev);
9838 if (!(mask & (1 << (n - 1))))
9839 return (0);
9840 return (n);
9841}
9842
9843static uint8_t
9844bwn_get_fbrate(uint8_t bitrate)
9845{
9846 switch (bitrate) {
9847 case BWN_CCK_RATE_1MB:
9848 return (BWN_CCK_RATE_1MB);
9849 case BWN_CCK_RATE_2MB:
9850 return (BWN_CCK_RATE_1MB);
9851 case BWN_CCK_RATE_5MB:
9852 return (BWN_CCK_RATE_2MB);
9853 case BWN_CCK_RATE_11MB:
9854 return (BWN_CCK_RATE_5MB);
9855 case BWN_OFDM_RATE_6MB:
9856 return (BWN_CCK_RATE_5MB);
9857 case BWN_OFDM_RATE_9MB:
9858 return (BWN_OFDM_RATE_6MB);
9859 case BWN_OFDM_RATE_12MB:
9860 return (BWN_OFDM_RATE_9MB);
9861 case BWN_OFDM_RATE_18MB:
9862 return (BWN_OFDM_RATE_12MB);
9863 case BWN_OFDM_RATE_24MB:
9864 return (BWN_OFDM_RATE_18MB);
9865 case BWN_OFDM_RATE_36MB:
9866 return (BWN_OFDM_RATE_24MB);
9867 case BWN_OFDM_RATE_48MB:
9868 return (BWN_OFDM_RATE_36MB);
9869 case BWN_OFDM_RATE_54MB:
9870 return (BWN_OFDM_RATE_48MB);
9871 }
9872 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9873 return (0);
9874}
9875
9876static uint32_t
9877bwn_pio_write_multi_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9878 uint32_t ctl, const void *_data, int len)
9879{
9880 struct bwn_softc *sc = mac->mac_sc;
9881 uint32_t value = 0;
9882 const uint8_t *data = _data;
9883
9884 ctl |= BWN_PIO8_TXCTL_0_7 | BWN_PIO8_TXCTL_8_15 |
9885 BWN_PIO8_TXCTL_16_23 | BWN_PIO8_TXCTL_24_31;
9886 bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9887
9888 siba_write_multi_4(sc->sc_dev, data, (len & ~3),
9889 tq->tq_base + BWN_PIO8_TXDATA);
9890 if (len & 3) {
9891 ctl &= ~(BWN_PIO8_TXCTL_8_15 | BWN_PIO8_TXCTL_16_23 |
9892 BWN_PIO8_TXCTL_24_31);
9893 data = &(data[len - 1]);
9894 switch (len & 3) {
9895 case 3:
9896 ctl |= BWN_PIO8_TXCTL_16_23;
9897 value |= (uint32_t)(*data) << 16;
9898 data--;
9899 case 2:
9900 ctl |= BWN_PIO8_TXCTL_8_15;
9901 value |= (uint32_t)(*data) << 8;
9902 data--;
9903 case 1:
9904 value |= (uint32_t)(*data);
9905 }
9906 bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9907 bwn_pio_write_4(mac, tq, BWN_PIO8_TXDATA, value);
9908 }
9909
9910 return (ctl);
9911}
9912
9913static void
9914bwn_pio_write_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9915 uint16_t offset, uint32_t value)
9916{
9917
9918 BWN_WRITE_4(mac, tq->tq_base + offset, value);
9919}
9920
9921static uint16_t
9922bwn_pio_write_multi_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9923 uint16_t ctl, const void *_data, int len)
9924{
9925 struct bwn_softc *sc = mac->mac_sc;
9926 const uint8_t *data = _data;
9927
9928 ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
9929 BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9930
9931 siba_write_multi_2(sc->sc_dev, data, (len & ~1),
9932 tq->tq_base + BWN_PIO_TXDATA);
9933 if (len & 1) {
9934 ctl &= ~BWN_PIO_TXCTL_WRITEHI;
9935 BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9936 BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data[len - 1]);
9937 }
9938
9939 return (ctl);
9940}
9941
9942static uint16_t
9943bwn_pio_write_mbuf_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9944 uint16_t ctl, struct mbuf *m0)
9945{
9946 int i, j = 0;
9947 uint16_t data = 0;
9948 const uint8_t *buf;
9949 struct mbuf *m = m0;
9950
9951 ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
9952 BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9953
9954 for (; m != NULL; m = m->m_next) {
9955 buf = mtod(m, const uint8_t *);
9956 for (i = 0; i < m->m_len; i++) {
9957 if (!((j++) % 2))
9958 data |= buf[i];
9959 else {
9960 data |= (buf[i] << 8);
9961 BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
9962 data = 0;
9963 }
9964 }
9965 }
9966 if (m0->m_pkthdr.len % 2) {
9967 ctl &= ~BWN_PIO_TXCTL_WRITEHI;
9968 BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9969 BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
9970 }
9971
9972 return (ctl);
9973}
9974
9975static void
9976bwn_set_slot_time(struct bwn_mac *mac, uint16_t time)
9977{
9978
9979 if (mac->mac_phy.type != BWN_PHYTYPE_G)
9980 return;
9981 BWN_WRITE_2(mac, 0x684, 510 + time);
9982 bwn_shm_write_2(mac, BWN_SHARED, 0x0010, time);
9983}
9984
9985static struct bwn_dma_ring *
9986bwn_dma_select(struct bwn_mac *mac, uint8_t prio)
9987{
9988
9989 if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
9990 return (mac->mac_method.dma.wme[WME_AC_BE]);
9991
9992 switch (prio) {
9993 case 3:
9994 return (mac->mac_method.dma.wme[WME_AC_VO]);
9995 case 2:
9996 return (mac->mac_method.dma.wme[WME_AC_VI]);
9997 case 0:
9998 return (mac->mac_method.dma.wme[WME_AC_BE]);
9999 case 1:
10000 return (mac->mac_method.dma.wme[WME_AC_BK]);
10001 }
10002 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
10003 return (NULL);
10004}
10005
10006static int
10007bwn_dma_getslot(struct bwn_dma_ring *dr)
10008{
10009 int slot;
10010
10011 BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
10012
10013 KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
10014 KASSERT(!(dr->dr_stop), ("%s:%d: fail", __func__, __LINE__));
10015 KASSERT(bwn_dma_freeslot(dr) != 0, ("%s:%d: fail", __func__, __LINE__));
10016
10017 slot = bwn_dma_nextslot(dr, dr->dr_curslot);
10018 KASSERT(!(slot & ~0x0fff), ("%s:%d: fail", __func__, __LINE__));
10019 dr->dr_curslot = slot;
10020 dr->dr_usedslot++;
10021
10022 return (slot);
10023}
10024
10025static int
10026bwn_phy_shm_tssi_read(struct bwn_mac *mac, uint16_t shm_offset)
10027{
10028 const uint8_t ofdm = (shm_offset != BWN_SHARED_TSSI_CCK);
10029 unsigned int a, b, c, d;
10030 unsigned int avg;
10031 uint32_t tmp;
10032
10033 tmp = bwn_shm_read_4(mac, BWN_SHARED, shm_offset);
10034 a = tmp & 0xff;
10035 b = (tmp >> 8) & 0xff;
10036 c = (tmp >> 16) & 0xff;
10037 d = (tmp >> 24) & 0xff;
10038 if (a == 0 || a == BWN_TSSI_MAX || b == 0 || b == BWN_TSSI_MAX ||
10039 c == 0 || c == BWN_TSSI_MAX || d == 0 || d == BWN_TSSI_MAX)
10040 return (ENOENT);
10041 bwn_shm_write_4(mac, BWN_SHARED, shm_offset,
10042 BWN_TSSI_MAX | (BWN_TSSI_MAX << 8) |
10043 (BWN_TSSI_MAX << 16) | (BWN_TSSI_MAX << 24));
10044
10045 if (ofdm) {
10046 a = (a + 32) & 0x3f;
10047 b = (b + 32) & 0x3f;
10048 c = (c + 32) & 0x3f;
10049 d = (d + 32) & 0x3f;
10050 }
10051
10052 avg = (a + b + c + d + 2) / 4;
10053 if (ofdm) {
10054 if (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO)
10055 & BWN_HF_4DB_CCK_POWERBOOST)
10056 avg = (avg >= 13) ? (avg - 13) : 0;
10057 }
10058 return (avg);
10059}
10060
10061static void
10062bwn_phy_g_setatt(struct bwn_mac *mac, int *bbattp, int *rfattp)
10063{
10064 struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
10065 int rfatt = *rfattp;
10066 int bbatt = *bbattp;
10067
10068 while (1) {
10069 if (rfatt > lo->rfatt.max && bbatt > lo->bbatt.max - 4)
10070 break;
10071 if (rfatt < lo->rfatt.min && bbatt < lo->bbatt.min + 4)
10072 break;
10073 if (bbatt > lo->bbatt.max && rfatt > lo->rfatt.max - 1)
10074 break;
10075 if (bbatt < lo->bbatt.min && rfatt < lo->rfatt.min + 1)
10076 break;
10077 if (bbatt > lo->bbatt.max) {
10078 bbatt -= 4;
10079 rfatt += 1;
10080 continue;
10081 }
10082 if (bbatt < lo->bbatt.min) {
10083 bbatt += 4;
10084 rfatt -= 1;
10085 continue;
10086 }
10087 if (rfatt > lo->rfatt.max) {
10088 rfatt -= 1;
10089 bbatt += 4;
10090 continue;
10091 }
10092 if (rfatt < lo->rfatt.min) {
10093 rfatt += 1;
10094 bbatt -= 4;
10095 continue;
10096 }
10097 break;
10098 }
10099
10100 *rfattp = MIN(MAX(rfatt, lo->rfatt.min), lo->rfatt.max);
10101 *bbattp = MIN(MAX(bbatt, lo->bbatt.min), lo->bbatt.max);
10102}
10103
10104static void
10105bwn_phy_lock(struct bwn_mac *mac)
10106{
10107 struct bwn_softc *sc = mac->mac_sc;
10108 struct ieee80211com *ic = sc->sc_ifp->if_l2com;
10109
10110 KASSERT(siba_get_revid(sc->sc_dev) >= 3,
10111 ("%s: unsupported rev %d", __func__, siba_get_revid(sc->sc_dev)));
10112
10113 if (ic->ic_opmode != IEEE80211_M_HOSTAP)
10114 bwn_psctl(mac, BWN_PS_AWAKE);
10115}
10116
10117static void
10118bwn_phy_unlock(struct bwn_mac *mac)
10119{
10120 struct bwn_softc *sc = mac->mac_sc;
10121 struct ieee80211com *ic = sc->sc_ifp->if_l2com;
10122
10123 KASSERT(siba_get_revid(sc->sc_dev) >= 3,
10124 ("%s: unsupported rev %d", __func__, siba_get_revid(sc->sc_dev)));
10125
10126 if (ic->ic_opmode != IEEE80211_M_HOSTAP)
10127 bwn_psctl(mac, 0);
10128}
10129
10130static void
10131bwn_rf_lock(struct bwn_mac *mac)
10132{
10133
10134 BWN_WRITE_4(mac, BWN_MACCTL,
10135 BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_RADIO_LOCK);
10136 BWN_READ_4(mac, BWN_MACCTL);
10137 DELAY(10);
10138}
10139
10140static void
10141bwn_rf_unlock(struct bwn_mac *mac)
10142{
10143
10144 BWN_READ_2(mac, BWN_PHYVER);
10145 BWN_WRITE_4(mac, BWN_MACCTL,
10146 BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_RADIO_LOCK);
10147}
10148
10149static struct bwn_pio_txqueue *
10150bwn_pio_parse_cookie(struct bwn_mac *mac, uint16_t cookie,
10151 struct bwn_pio_txpkt **pack)
10152{
10153 struct bwn_pio *pio = &mac->mac_method.pio;
10154 struct bwn_pio_txqueue *tq = NULL;
10155 unsigned int index;
10156
10157 switch (cookie & 0xf000) {
10158 case 0x1000:
10159 tq = &pio->wme[WME_AC_BK];
10160 break;
10161 case 0x2000:
10162 tq = &pio->wme[WME_AC_BE];
10163 break;
10164 case 0x3000:
10165 tq = &pio->wme[WME_AC_VI];
10166 break;
10167 case 0x4000:
10168 tq = &pio->wme[WME_AC_VO];
10169 break;
10170 case 0x5000:
10171 tq = &pio->mcast;
10172 break;
10173 }
10174 KASSERT(tq != NULL, ("%s:%d: fail", __func__, __LINE__));
10175 if (tq == NULL)
10176 return (NULL);
10177 index = (cookie & 0x0fff);
10178 KASSERT(index < N(tq->tq_pkts), ("%s:%d: fail", __func__, __LINE__));
10179 if (index >= N(tq->tq_pkts))
10180 return (NULL);
10181 *pack = &tq->tq_pkts[index];
10182 KASSERT(*pack != NULL, ("%s:%d: fail", __func__, __LINE__));
10183 return (tq);
10184}
10185
10186static void
10187bwn_txpwr(void *arg, int npending)
10188{
10189 struct bwn_mac *mac = arg;
10190 struct bwn_softc *sc = mac->mac_sc;
10191
10192 BWN_LOCK(sc);
10193 if (mac && mac->mac_status >= BWN_MAC_STATUS_STARTED &&
10194 mac->mac_phy.set_txpwr != NULL)
10195 mac->mac_phy.set_txpwr(mac);
10196 BWN_UNLOCK(sc);
10197}
10198
10199static void
10200bwn_task_15s(struct bwn_mac *mac)
10201{
10202 uint16_t reg;
10203
10204 if (mac->mac_fw.opensource) {
10205 reg = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG);
10206 if (reg) {
10207 bwn_restart(mac, "fw watchdog");
10208 return;
10209 }
10210 bwn_shm_write_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG, 1);
10211 }
10212 if (mac->mac_phy.task_15s)
10213 mac->mac_phy.task_15s(mac);
10214
10215 mac->mac_phy.txerrors = BWN_TXERROR_MAX;
10216}
10217
10218static void
10219bwn_task_30s(struct bwn_mac *mac)
10220{
10221
10222 if (mac->mac_phy.type != BWN_PHYTYPE_G || mac->mac_noise.noi_running)
10223 return;
10224 mac->mac_noise.noi_running = 1;
10225 mac->mac_noise.noi_nsamples = 0;
10226
10227 bwn_noise_gensample(mac);
10228}
10229
10230static void
10231bwn_task_60s(struct bwn_mac *mac)
10232{
10233
10234 if (mac->mac_phy.task_60s)
10235 mac->mac_phy.task_60s(mac);
10236 bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME);
10237}
10238
10239static void
10240bwn_tasks(void *arg)
10241{
10242 struct bwn_mac *mac = arg;
10243 struct bwn_softc *sc = mac->mac_sc;
10244
10245 BWN_ASSERT_LOCKED(sc);
10246 if (mac->mac_status != BWN_MAC_STATUS_STARTED)
10247 return;
10248
10249 if (mac->mac_task_state % 4 == 0)
10250 bwn_task_60s(mac);
10251 if (mac->mac_task_state % 2 == 0)
10252 bwn_task_30s(mac);
10253 bwn_task_15s(mac);
10254
10255 mac->mac_task_state++;
10256 callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
10257}
10258
10259static int
10260bwn_plcp_get_ofdmrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp, uint8_t a)
10261{
10262 struct bwn_softc *sc = mac->mac_sc;
10263
10264 KASSERT(a == 0, ("not support APHY\n"));
10265
10266 switch (plcp->o.raw[0] & 0xf) {
10267 case 0xb:
10268 return (BWN_OFDM_RATE_6MB);
10269 case 0xf:
10270 return (BWN_OFDM_RATE_9MB);
10271 case 0xa:
10272 return (BWN_OFDM_RATE_12MB);
10273 case 0xe:
10274 return (BWN_OFDM_RATE_18MB);
10275 case 0x9:
10276 return (BWN_OFDM_RATE_24MB);
10277 case 0xd:
10278 return (BWN_OFDM_RATE_36MB);
10279 case 0x8:
10280 return (BWN_OFDM_RATE_48MB);
10281 case 0xc:
10282 return (BWN_OFDM_RATE_54MB);
10283 }
10284 device_printf(sc->sc_dev, "incorrect OFDM rate %d\n",
10285 plcp->o.raw[0] & 0xf);
10286 return (-1);
10287}
10288
10289static int
10290bwn_plcp_get_cckrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp)
10291{
10292 struct bwn_softc *sc = mac->mac_sc;
10293
10294 switch (plcp->o.raw[0]) {
10295 case 0x0a:
10296 return (BWN_CCK_RATE_1MB);
10297 case 0x14:
10298 return (BWN_CCK_RATE_2MB);
10299 case 0x37:
10300 return (BWN_CCK_RATE_5MB);
10301 case 0x6e:
10302 return (BWN_CCK_RATE_11MB);
10303 }
10304 device_printf(sc->sc_dev, "incorrect CCK rate %d\n", plcp->o.raw[0]);
10305 return (-1);
10306}
10307
10308static void
10309bwn_rx_radiotap(struct bwn_mac *mac, struct mbuf *m,
10310 const struct bwn_rxhdr4 *rxhdr, struct bwn_plcp6 *plcp, int rate,
10311 int rssi, int noise)
10312{
10313 struct bwn_softc *sc = mac->mac_sc;
10314 const struct ieee80211_frame_min *wh;
10315 uint64_t tsf;
10316 uint16_t low_mactime_now;
10317
10318 if (htole16(rxhdr->phy_status0) & BWN_RX_PHYST0_SHORTPRMBL)
10319 sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
10320
10321 wh = mtod(m, const struct ieee80211_frame_min *);
10322 if (wh->i_fc[1] & IEEE80211_FC1_WEP)
10323 sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_WEP;
10324
10325 bwn_tsf_read(mac, &tsf);
10326 low_mactime_now = tsf;
10327 tsf = tsf & ~0xffffULL;
10328 tsf += le16toh(rxhdr->mac_time);
10329 if (low_mactime_now < le16toh(rxhdr->mac_time))
10330 tsf -= 0x10000;
10331
10332 sc->sc_rx_th.wr_tsf = tsf;
10333 sc->sc_rx_th.wr_rate = rate;
10334 sc->sc_rx_th.wr_antsignal = rssi;
10335 sc->sc_rx_th.wr_antnoise = noise;
10336}
10337
10338static void
10339bwn_tsf_read(struct bwn_mac *mac, uint64_t *tsf)
10340{
10341 uint32_t low, high;
10342
10343 KASSERT(siba_get_revid(mac->mac_sc->sc_dev) >= 3,
10344 ("%s:%d: fail", __func__, __LINE__));
10345
10346 low = BWN_READ_4(mac, BWN_REV3PLUS_TSF_LOW);
10347 high = BWN_READ_4(mac, BWN_REV3PLUS_TSF_HIGH);
10348 *tsf = high;
10349 *tsf <<= 32;
10350 *tsf |= low;
10351}
10352
10353static int
10354bwn_dma_attach(struct bwn_mac *mac)
10355{
10356 struct bwn_dma *dma = &mac->mac_method.dma;
10357 struct bwn_softc *sc = mac->mac_sc;
10358 bus_addr_t lowaddr = 0;
10359 int error;
10360
10361 if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
10362 return (0);
10363
10364 KASSERT(siba_get_revid(sc->sc_dev) >= 5, ("%s: fail", __func__));
10365
10366 mac->mac_flags |= BWN_MAC_FLAG_DMA;
10367
10368 dma->dmatype = bwn_dma_gettype(mac);
10369 if (dma->dmatype == BWN_DMA_30BIT)
10370 lowaddr = BWN_BUS_SPACE_MAXADDR_30BIT;
10371 else if (dma->dmatype == BWN_DMA_32BIT)
10372 lowaddr = BUS_SPACE_MAXADDR_32BIT;
10373 else
10374 lowaddr = BUS_SPACE_MAXADDR;
10375
10376 /*
10377 * Create top level DMA tag
10378 */
10379 error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), /* parent */
10380 BWN_ALIGN, 0, /* alignment, bounds */
10381 lowaddr, /* lowaddr */
10382 BUS_SPACE_MAXADDR, /* highaddr */
10383 NULL, NULL, /* filter, filterarg */
10384 MAXBSIZE, /* maxsize */
10385 BUS_SPACE_UNRESTRICTED, /* nsegments */
10386 BUS_SPACE_MAXSIZE, /* maxsegsize */
10387 0, /* flags */
10388 NULL, NULL, /* lockfunc, lockarg */
10389 &dma->parent_dtag);
10390 if (error) {
10391 device_printf(sc->sc_dev, "can't create parent DMA tag\n");
10392 return (error);
10393 }
10394
10395 /*
10396 * Create TX/RX mbuf DMA tag
10397 */
10398 error = bus_dma_tag_create(dma->parent_dtag,
10399 1,
10400 0,
10401 BUS_SPACE_MAXADDR,
10402 BUS_SPACE_MAXADDR,
10403 NULL, NULL,
10404 MCLBYTES,
10405 1,
10406 BUS_SPACE_MAXSIZE_32BIT,
10407 0,
10408 NULL, NULL,
10409 &dma->rxbuf_dtag);
10410 if (error) {
10411 device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10412 goto fail0;
10413 }
10414 error = bus_dma_tag_create(dma->parent_dtag,
10415 1,
10416 0,
10417 BUS_SPACE_MAXADDR,
10418 BUS_SPACE_MAXADDR,
10419 NULL, NULL,
10420 MCLBYTES,
10421 1,
10422 BUS_SPACE_MAXSIZE_32BIT,
10423 0,
10424 NULL, NULL,
10425 &dma->txbuf_dtag);
10426 if (error) {
10427 device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10428 goto fail1;
10429 }
10430
10431 dma->wme[WME_AC_BK] = bwn_dma_ringsetup(mac, 0, 1, dma->dmatype);
10432 if (!dma->wme[WME_AC_BK])
10433 goto fail2;
10434
10435 dma->wme[WME_AC_BE] = bwn_dma_ringsetup(mac, 1, 1, dma->dmatype);
10436 if (!dma->wme[WME_AC_BE])
10437 goto fail3;
10438
10439 dma->wme[WME_AC_VI] = bwn_dma_ringsetup(mac, 2, 1, dma->dmatype);
10440 if (!dma->wme[WME_AC_VI])
10441 goto fail4;
10442
10443 dma->wme[WME_AC_VO] = bwn_dma_ringsetup(mac, 3, 1, dma->dmatype);
10444 if (!dma->wme[WME_AC_VO])
10445 goto fail5;
10446
10447 dma->mcast = bwn_dma_ringsetup(mac, 4, 1, dma->dmatype);
10448 if (!dma->mcast)
10449 goto fail6;
10450 dma->rx = bwn_dma_ringsetup(mac, 0, 0, dma->dmatype);
10451 if (!dma->rx)
10452 goto fail7;
10453
10454 return (error);
10455
10456fail7: bwn_dma_ringfree(&dma->mcast);
10457fail6: bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
10458fail5: bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
10459fail4: bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
10460fail3: bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
10461fail2: bus_dma_tag_destroy(dma->txbuf_dtag);
10462fail1: bus_dma_tag_destroy(dma->rxbuf_dtag);
10463fail0: bus_dma_tag_destroy(dma->parent_dtag);
10464 return (error);
10465}
10466
10467static struct bwn_dma_ring *
10468bwn_dma_parse_cookie(struct bwn_mac *mac, const struct bwn_txstatus *status,
10469 uint16_t cookie, int *slot)
10470{
10471 struct bwn_dma *dma = &mac->mac_method.dma;
10472 struct bwn_dma_ring *dr;
10473 struct bwn_softc *sc = mac->mac_sc;
10474
10475 BWN_ASSERT_LOCKED(mac->mac_sc);
10476
10477 switch (cookie & 0xf000) {
10478 case 0x1000:
10479 dr = dma->wme[WME_AC_BK];
10480 break;
10481 case 0x2000:
10482 dr = dma->wme[WME_AC_BE];
10483 break;
10484 case 0x3000:
10485 dr = dma->wme[WME_AC_VI];
10486 break;
10487 case 0x4000:
10488 dr = dma->wme[WME_AC_VO];
10489 break;
10490 case 0x5000:
10491 dr = dma->mcast;
10492 break;
10493 default:
10494 dr = NULL;
10495 KASSERT(0 == 1,
10496 ("invalid cookie value %d", cookie & 0xf000));
10497 }
10498 *slot = (cookie & 0x0fff);
10499 if (*slot < 0 || *slot >= dr->dr_numslots) {
10500 /*
10501 * XXX FIXME: sometimes H/W returns TX DONE events duplicately
10502 * that it occurs events which have same H/W sequence numbers.
10503 * When it's occurred just prints a WARNING msgs and ignores.
10504 */
10505 KASSERT(status->seq == dma->lastseq,
10506 ("%s:%d: fail", __func__, __LINE__));
10507 device_printf(sc->sc_dev,
10508 "out of slot ranges (0 < %d < %d)\n", *slot,
10509 dr->dr_numslots);
10510 return (NULL);
10511 }
10512 dma->lastseq = status->seq;
10513 return (dr);
10514}
10515
10516static void
10517bwn_dma_stop(struct bwn_mac *mac)
10518{
10519 struct bwn_dma *dma;
10520
10521 if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
10522 return;
10523 dma = &mac->mac_method.dma;
10524
10525 bwn_dma_ringstop(&dma->rx);
10526 bwn_dma_ringstop(&dma->wme[WME_AC_BK]);
10527 bwn_dma_ringstop(&dma->wme[WME_AC_BE]);
10528 bwn_dma_ringstop(&dma->wme[WME_AC_VI]);
10529 bwn_dma_ringstop(&dma->wme[WME_AC_VO]);
10530 bwn_dma_ringstop(&dma->mcast);
10531}
10532
10533static void
10534bwn_dma_ringstop(struct bwn_dma_ring **dr)
10535{
10536
10537 if (dr == NULL)
10538 return;
10539
10540 bwn_dma_cleanup(*dr);
10541}
10542
10543static void
10544bwn_pio_stop(struct bwn_mac *mac)
10545{
10546 struct bwn_pio *pio;
10547
10548 if (mac->mac_flags & BWN_MAC_FLAG_DMA)
10549 return;
10550 pio = &mac->mac_method.pio;
10551
10552 bwn_destroy_queue_tx(&pio->mcast);
10553 bwn_destroy_queue_tx(&pio->wme[WME_AC_VO]);
10554 bwn_destroy_queue_tx(&pio->wme[WME_AC_VI]);
10555 bwn_destroy_queue_tx(&pio->wme[WME_AC_BE]);
10556 bwn_destroy_queue_tx(&pio->wme[WME_AC_BK]);
10557}
10558
10559static void
10560bwn_led_attach(struct bwn_mac *mac)
10561{
10562 struct bwn_softc *sc = mac->mac_sc;
10563 const uint8_t *led_act = NULL;
10564 uint16_t val[BWN_LED_MAX];
10565 int i;
10566
10567 sc->sc_led_idle = (2350 * hz) / 1000;
10568 sc->sc_led_blink = 1;
10569
10570 for (i = 0; i < N(bwn_vendor_led_act); ++i) {
10571 if (siba_get_pci_subvendor(sc->sc_dev) ==
10572 bwn_vendor_led_act[i].vid) {
10573 led_act = bwn_vendor_led_act[i].led_act;
10574 break;
10575 }
10576 }
10577 if (led_act == NULL)
10578 led_act = bwn_default_led_act;
10579
10580 val[0] = siba_sprom_get_gpio0(sc->sc_dev);
10581 val[1] = siba_sprom_get_gpio1(sc->sc_dev);
10582 val[2] = siba_sprom_get_gpio2(sc->sc_dev);
10583 val[3] = siba_sprom_get_gpio3(sc->sc_dev);
10584
10585 for (i = 0; i < BWN_LED_MAX; ++i) {
10586 struct bwn_led *led = &sc->sc_leds[i];
10587
10588 if (val[i] == 0xff) {
10589 led->led_act = led_act[i];
10590 } else {
10591 if (val[i] & BWN_LED_ACT_LOW)
10592 led->led_flags |= BWN_LED_F_ACTLOW;
10593 led->led_act = val[i] & BWN_LED_ACT_MASK;
10594 }
10595 led->led_mask = (1 << i);
10596
10597 if (led->led_act == BWN_LED_ACT_BLINK_SLOW ||
10598 led->led_act == BWN_LED_ACT_BLINK_POLL ||
10599 led->led_act == BWN_LED_ACT_BLINK) {
10600 led->led_flags |= BWN_LED_F_BLINK;
10601 if (led->led_act == BWN_LED_ACT_BLINK_POLL)
10602 led->led_flags |= BWN_LED_F_POLLABLE;
10603 else if (led->led_act == BWN_LED_ACT_BLINK_SLOW)
10604 led->led_flags |= BWN_LED_F_SLOW;
10605
10606 if (sc->sc_blink_led == NULL) {
10607 sc->sc_blink_led = led;
10608 if (led->led_flags & BWN_LED_F_SLOW)
10609 BWN_LED_SLOWDOWN(sc->sc_led_idle);
10610 }
10611 }
10612
10613 DPRINTF(sc, BWN_DEBUG_LED,
10614 "%dth led, act %d, lowact %d\n", i,
10615 led->led_act, led->led_flags & BWN_LED_F_ACTLOW);
10616 }
10617 callout_init_mtx(&sc->sc_led_blink_ch, &sc->sc_mtx, 0);
10618}
10619
10620static __inline uint16_t
10621bwn_led_onoff(const struct bwn_led *led, uint16_t val, int on)
10622{
10623
10624 if (led->led_flags & BWN_LED_F_ACTLOW)
10625 on = !on;
10626 if (on)
10627 val |= led->led_mask;
10628 else
10629 val &= ~led->led_mask;
10630 return val;
10631}
10632
10633static void
10634bwn_led_newstate(struct bwn_mac *mac, enum ieee80211_state nstate)
10635{
10636 struct bwn_softc *sc = mac->mac_sc;
10637 struct ifnet *ifp = sc->sc_ifp;
10638 struct ieee80211com *ic = ifp->if_l2com;
10639 uint16_t val;
10640 int i;
10641
10642 if (nstate == IEEE80211_S_INIT) {
10643 callout_stop(&sc->sc_led_blink_ch);
10644 sc->sc_led_blinking = 0;
10645 }
10646
10647 if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
10648 return;
10649
10650 val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10651 for (i = 0; i < BWN_LED_MAX; ++i) {
10652 struct bwn_led *led = &sc->sc_leds[i];
10653 int on;
10654
10655 if (led->led_act == BWN_LED_ACT_UNKN ||
10656 led->led_act == BWN_LED_ACT_NULL)
10657 continue;
10658
10659 if ((led->led_flags & BWN_LED_F_BLINK) &&
10660 nstate != IEEE80211_S_INIT)
10661 continue;
10662
10663 switch (led->led_act) {
10664 case BWN_LED_ACT_ON: /* Always on */
10665 on = 1;
10666 break;
10667 case BWN_LED_ACT_OFF: /* Always off */
10668 case BWN_LED_ACT_5GHZ: /* TODO: 11A */
10669 on = 0;
10670 break;
10671 default:
10672 on = 1;
10673 switch (nstate) {
10674 case IEEE80211_S_INIT:
10675 on = 0;
10676 break;
10677 case IEEE80211_S_RUN:
10678 if (led->led_act == BWN_LED_ACT_11G &&
10679 ic->ic_curmode != IEEE80211_MODE_11G)
10680 on = 0;
10681 break;
10682 default:
10683 if (led->led_act == BWN_LED_ACT_ASSOC)
10684 on = 0;
10685 break;
10686 }
10687 break;
10688 }
10689
10690 val = bwn_led_onoff(led, val, on);
10691 }
10692 BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10693}
10694
10695static void
10696bwn_led_event(struct bwn_mac *mac, int event)
10697{
10698 struct bwn_softc *sc = mac->mac_sc;
10699 struct bwn_led *led = sc->sc_blink_led;
10700 int rate;
10701
10702 if (event == BWN_LED_EVENT_POLL) {
10703 if ((led->led_flags & BWN_LED_F_POLLABLE) == 0)
10704 return;
10705 if (ticks - sc->sc_led_ticks < sc->sc_led_idle)
10706 return;
10707 }
10708
10709 sc->sc_led_ticks = ticks;
10710 if (sc->sc_led_blinking)
10711 return;
10712
10713 switch (event) {
10714 case BWN_LED_EVENT_RX:
10715 rate = sc->sc_rx_rate;
10716 break;
10717 case BWN_LED_EVENT_TX:
10718 rate = sc->sc_tx_rate;
10719 break;
10720 case BWN_LED_EVENT_POLL:
10721 rate = 0;
10722 break;
10723 default:
10724 panic("unknown LED event %d\n", event);
10725 break;
10726 }
10727 bwn_led_blink_start(mac, bwn_led_duration[rate].on_dur,
10728 bwn_led_duration[rate].off_dur);
10729}
10730
10731static void
10732bwn_led_blink_start(struct bwn_mac *mac, int on_dur, int off_dur)
10733{
10734 struct bwn_softc *sc = mac->mac_sc;
10735 struct bwn_led *led = sc->sc_blink_led;
10736 uint16_t val;
10737
10738 val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10739 val = bwn_led_onoff(led, val, 1);
10740 BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10741
10742 if (led->led_flags & BWN_LED_F_SLOW) {
10743 BWN_LED_SLOWDOWN(on_dur);
10744 BWN_LED_SLOWDOWN(off_dur);
10745 }
10746
10747 sc->sc_led_blinking = 1;
10748 sc->sc_led_blink_offdur = off_dur;
10749
10750 callout_reset(&sc->sc_led_blink_ch, on_dur, bwn_led_blink_next, mac);
10751}
10752
10753static void
10754bwn_led_blink_next(void *arg)
10755{
10756 struct bwn_mac *mac = arg;
10757 struct bwn_softc *sc = mac->mac_sc;
10758 uint16_t val;
10759
10760 val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10761 val = bwn_led_onoff(sc->sc_blink_led, val, 0);
10762 BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10763
10764 callout_reset(&sc->sc_led_blink_ch, sc->sc_led_blink_offdur,
10765 bwn_led_blink_end, mac);
10766}
10767
10768static void
10769bwn_led_blink_end(void *arg)
10770{
10771 struct bwn_mac *mac = arg;
10772 struct bwn_softc *sc = mac->mac_sc;
10773
10774 sc->sc_led_blinking = 0;
10775}
10776
10777static int
10778bwn_suspend(device_t dev)
10779{
10780 struct bwn_softc *sc = device_get_softc(dev);
10781
10782 bwn_stop(sc, 1);
10783 return (0);
10784}
10785
10786static int
10787bwn_resume(device_t dev)
10788{
10789 struct bwn_softc *sc = device_get_softc(dev);
10790 struct ifnet *ifp = sc->sc_ifp;
10791
10792 if (ifp->if_flags & IFF_UP)
10793 bwn_init(sc);
10794 return (0);
10795}
10796
10797static void
10798bwn_rfswitch(void *arg)
10799{
10800 struct bwn_softc *sc = arg;
10801 struct bwn_mac *mac = sc->sc_curmac;
10802 int cur = 0, prev = 0;
10803
10804 KASSERT(mac->mac_status >= BWN_MAC_STATUS_STARTED,
10805 ("%s: invalid MAC status %d", __func__, mac->mac_status));
10806
10807 if (mac->mac_phy.rf_rev >= 3 || mac->mac_phy.type == BWN_PHYTYPE_LP) {
10808 if (!(BWN_READ_4(mac, BWN_RF_HWENABLED_HI)
10809 & BWN_RF_HWENABLED_HI_MASK))
10810 cur = 1;
10811 } else {
10812 if (BWN_READ_2(mac, BWN_RF_HWENABLED_LO)
10813 & BWN_RF_HWENABLED_LO_MASK)
10814 cur = 1;
10815 }
10816
10817 if (mac->mac_flags & BWN_MAC_FLAG_RADIO_ON)
10818 prev = 1;
10819
10820 if (cur != prev) {
10821 if (cur)
10822 mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
10823 else
10824 mac->mac_flags &= ~BWN_MAC_FLAG_RADIO_ON;
10825
10826 device_printf(sc->sc_dev,
10827 "status of RF switch is changed to %s\n",
10828 cur ? "ON" : "OFF");
10829 if (cur != mac->mac_phy.rf_on) {
10830 if (cur)
10831 bwn_rf_turnon(mac);
10832 else
10833 bwn_rf_turnoff(mac);
10834 }
10835 }
10836
10837 callout_schedule(&sc->sc_rfswitch_ch, hz);
10838}
10839
10840static void
10841bwn_phy_lp_init_pre(struct bwn_mac *mac)
10842{
10843 struct bwn_phy *phy = &mac->mac_phy;
10844 struct bwn_phy_lp *plp = &phy->phy_lp;
10845
10846 plp->plp_antenna = BWN_ANT_DEFAULT;
10847}
10848
10849static int
10850bwn_phy_lp_init(struct bwn_mac *mac)
10851{
10852 static const struct bwn_stxtable tables[] = {
10853 { 2, 6, 0x3d, 3, 0x01 }, { 1, 12, 0x4c, 1, 0x01 },
10854 { 1, 8, 0x50, 0, 0x7f }, { 0, 8, 0x44, 0, 0xff },
10855 { 1, 0, 0x4a, 0, 0xff }, { 0, 4, 0x4d, 0, 0xff },
10856 { 1, 4, 0x4e, 0, 0xff }, { 0, 12, 0x4f, 0, 0x0f },
10857 { 1, 0, 0x4f, 4, 0x0f }, { 3, 0, 0x49, 0, 0x0f },
10858 { 4, 3, 0x46, 4, 0x07 }, { 3, 15, 0x46, 0, 0x01 },
10859 { 4, 0, 0x46, 1, 0x07 }, { 3, 8, 0x48, 4, 0x07 },
10860 { 3, 11, 0x48, 0, 0x0f }, { 3, 4, 0x49, 4, 0x0f },
10861 { 2, 15, 0x45, 0, 0x01 }, { 5, 13, 0x52, 4, 0x07 },
10862 { 6, 0, 0x52, 7, 0x01 }, { 5, 3, 0x41, 5, 0x07 },
10863 { 5, 6, 0x41, 0, 0x0f }, { 5, 10, 0x42, 5, 0x07 },
10864 { 4, 15, 0x42, 0, 0x01 }, { 5, 0, 0x42, 1, 0x07 },
10865 { 4, 11, 0x43, 4, 0x0f }, { 4, 7, 0x43, 0, 0x0f },
10866 { 4, 6, 0x45, 1, 0x01 }, { 2, 7, 0x40, 4, 0x0f },
10867 { 2, 11, 0x40, 0, 0x0f }
10868 };
10869 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
10870 struct bwn_softc *sc = mac->mac_sc;
10871 const struct bwn_stxtable *st;
10872 struct ifnet *ifp = sc->sc_ifp;
10873 struct ieee80211com *ic = ifp->if_l2com;
10874 int i, error;
10875 uint16_t tmp;
10876
10877 bwn_phy_lp_readsprom(mac); /* XXX bad place */
10878 bwn_phy_lp_bbinit(mac);
10879
10880 /* initialize RF */
10881 BWN_PHY_SET(mac, BWN_PHY_4WIRECTL, 0x2);
10882 DELAY(1);
10883 BWN_PHY_MASK(mac, BWN_PHY_4WIRECTL, 0xfffd);
10884 DELAY(1);
10885
10886 if (mac->mac_phy.rf_ver == 0x2062)
10887 bwn_phy_lp_b2062_init(mac);
10888 else {
10889 bwn_phy_lp_b2063_init(mac);
10890
10891 /* synchronize stx table. */
10892 for (i = 0; i < N(tables); i++) {
10893 st = &tables[i];
10894 tmp = BWN_RF_READ(mac, st->st_rfaddr);
10895 tmp >>= st->st_rfshift;
10896 tmp <<= st->st_physhift;
10897 BWN_PHY_SETMASK(mac,
10898 BWN_PHY_OFDM(0xf2 + st->st_phyoffset),
10899 ~(st->st_mask << st->st_physhift), tmp);
10900 }
10901
10902 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf0), 0x5f80);
10903 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf1), 0);
10904 }
10905
10906 /* calibrate RC */
10907 if (mac->mac_phy.rev >= 2)
10908 bwn_phy_lp_rxcal_r2(mac);
10909 else if (!plp->plp_rccap) {
10910 if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
10911 bwn_phy_lp_rccal_r12(mac);
10912 } else
10913 bwn_phy_lp_set_rccap(mac);
10914
10915 error = bwn_phy_lp_switch_channel(mac, 7);
10916 if (error)
10917 device_printf(sc->sc_dev,
10918 "failed to change channel 7 (%d)\n", error);
10919 bwn_phy_lp_txpctl_init(mac);
10920 bwn_phy_lp_calib(mac);
10921 return (0);
10922}
10923
10924static uint16_t
10925bwn_phy_lp_read(struct bwn_mac *mac, uint16_t reg)
10926{
10927
10928 BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10929 return (BWN_READ_2(mac, BWN_PHYDATA));
10930}
10931
10932static void
10933bwn_phy_lp_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
10934{
10935
10936 BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10937 BWN_WRITE_2(mac, BWN_PHYDATA, value);
10938}
10939
10940static void
10941bwn_phy_lp_maskset(struct bwn_mac *mac, uint16_t reg, uint16_t mask,
10942 uint16_t set)
10943{
10944
10945 BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10946 BWN_WRITE_2(mac, BWN_PHYDATA,
10947 (BWN_READ_2(mac, BWN_PHYDATA) & mask) | set);
10948}
10949
10950static uint16_t
10951bwn_phy_lp_rf_read(struct bwn_mac *mac, uint16_t reg)
10952{
10953
10954 KASSERT(reg != 1, ("unaccessible register %d", reg));
10955 if (mac->mac_phy.rev < 2 && reg != 0x4001)
10956 reg |= 0x100;
10957 if (mac->mac_phy.rev >= 2)
10958 reg |= 0x200;
10959 BWN_WRITE_2(mac, BWN_RFCTL, reg);
10960 return BWN_READ_2(mac, BWN_RFDATALO);
10961}
10962
10963static void
10964bwn_phy_lp_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
10965{
10966
10967 KASSERT(reg != 1, ("unaccessible register %d", reg));
10968 BWN_WRITE_2(mac, BWN_RFCTL, reg);
10969 BWN_WRITE_2(mac, BWN_RFDATALO, value);
10970}
10971
10972static void
10973bwn_phy_lp_rf_onoff(struct bwn_mac *mac, int on)
10974{
10975
10976 if (on) {
10977 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xe0ff);
10978 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2,
10979 (mac->mac_phy.rev >= 2) ? 0xf7f7 : 0xffe7);
10980 return;
10981 }
10982
10983 if (mac->mac_phy.rev >= 2) {
10984 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x83ff);
10985 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
10986 BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0x80ff);
10987 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xdfff);
10988 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0808);
10989 return;
10990 }
10991
10992 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xe0ff);
10993 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
10994 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfcff);
10995 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0018);
10996}
10997
10998static int
10999bwn_phy_lp_switch_channel(struct bwn_mac *mac, uint32_t chan)
11000{
11001 struct bwn_phy *phy = &mac->mac_phy;
11002 struct bwn_phy_lp *plp = &phy->phy_lp;
11003 int error;
11004
11005 if (phy->rf_ver == 0x2063) {
11006 error = bwn_phy_lp_b2063_switch_channel(mac, chan);
11007 if (error)
11008 return (error);
11009 } else {
11010 error = bwn_phy_lp_b2062_switch_channel(mac, chan);
11011 if (error)
11012 return (error);
11013 bwn_phy_lp_set_anafilter(mac, chan);
11014 bwn_phy_lp_set_gaintbl(mac, ieee80211_ieee2mhz(chan, 0));
11015 }
11016
11017 plp->plp_chan = chan;
11018 BWN_WRITE_2(mac, BWN_CHANNEL, chan);
11019 return (0);
11020}
11021
11022static uint32_t
11023bwn_phy_lp_get_default_chan(struct bwn_mac *mac)
11024{
11025 struct bwn_softc *sc = mac->mac_sc;
11026 struct ifnet *ifp = sc->sc_ifp;
11027 struct ieee80211com *ic = ifp->if_l2com;
11028
11029 return (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? 1 : 36);
11030}
11031
11032static void
11033bwn_phy_lp_set_antenna(struct bwn_mac *mac, int antenna)
11034{
11035 struct bwn_phy *phy = &mac->mac_phy;
11036 struct bwn_phy_lp *plp = &phy->phy_lp;
11037
11038 if (phy->rev >= 2 || antenna > BWN_ANTAUTO1)
11039 return;
11040
11041 bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER);
11042 BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffd, antenna & 0x2);
11043 BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffe, antenna & 0x1);
11044 bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_UCODE_ANTDIV_HELPER);
11045 plp->plp_antenna = antenna;
11046}
11047
11048static void
11049bwn_phy_lp_task_60s(struct bwn_mac *mac)
11050{
11051
11052 bwn_phy_lp_calib(mac);
11053}
11054
11055static void
11056bwn_phy_lp_readsprom(struct bwn_mac *mac)
11057{
11058 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11059 struct bwn_softc *sc = mac->mac_sc;
11060 struct ifnet *ifp = sc->sc_ifp;
11061 struct ieee80211com *ic = ifp->if_l2com;
11062
11063 if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11064 plp->plp_txisoband_m = siba_sprom_get_tri2g(sc->sc_dev);
11065 plp->plp_bxarch = siba_sprom_get_bxa2g(sc->sc_dev);
11066 plp->plp_rxpwroffset = siba_sprom_get_rxpo2g(sc->sc_dev);
11067 plp->plp_rssivf = siba_sprom_get_rssismf2g(sc->sc_dev);
11068 plp->plp_rssivc = siba_sprom_get_rssismc2g(sc->sc_dev);
11069 plp->plp_rssigs = siba_sprom_get_rssisav2g(sc->sc_dev);
11070 return;
11071 }
11072
11073 plp->plp_txisoband_l = siba_sprom_get_tri5gl(sc->sc_dev);
11074 plp->plp_txisoband_m = siba_sprom_get_tri5g(sc->sc_dev);
11075 plp->plp_txisoband_h = siba_sprom_get_tri5gh(sc->sc_dev);
11076 plp->plp_bxarch = siba_sprom_get_bxa5g(sc->sc_dev);
11077 plp->plp_rxpwroffset = siba_sprom_get_rxpo5g(sc->sc_dev);
11078 plp->plp_rssivf = siba_sprom_get_rssismf5g(sc->sc_dev);
11079 plp->plp_rssivc = siba_sprom_get_rssismc5g(sc->sc_dev);
11080 plp->plp_rssigs = siba_sprom_get_rssisav5g(sc->sc_dev);
11081}
11082
11083static void
11084bwn_phy_lp_bbinit(struct bwn_mac *mac)
11085{
11086
11087 bwn_phy_lp_tblinit(mac);
11088 if (mac->mac_phy.rev >= 2)
11089 bwn_phy_lp_bbinit_r2(mac);
11090 else
11091 bwn_phy_lp_bbinit_r01(mac);
11092}
11093
11094static void
11095bwn_phy_lp_txpctl_init(struct bwn_mac *mac)
11096{
11097 struct bwn_txgain gain_2ghz = { 4, 12, 12, 0 };
11098 struct bwn_txgain gain_5ghz = { 7, 15, 14, 0 };
11099 struct bwn_softc *sc = mac->mac_sc;
11100 struct ifnet *ifp = sc->sc_ifp;
11101 struct ieee80211com *ic = ifp->if_l2com;
11102
11103 bwn_phy_lp_set_txgain(mac,
11104 IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? &gain_2ghz : &gain_5ghz);
11105 bwn_phy_lp_set_bbmult(mac, 150);
11106}
11107
11108static void
11109bwn_phy_lp_calib(struct bwn_mac *mac)
11110{
11111 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11112 struct bwn_softc *sc = mac->mac_sc;
11113 struct ifnet *ifp = sc->sc_ifp;
11114 struct ieee80211com *ic = ifp->if_l2com;
11115 const struct bwn_rxcompco *rc = NULL;
11116 struct bwn_txgain ogain;
11117 int i, omode, oafeovr, orf, obbmult;
11118 uint8_t mode, fc = 0;
11119
11120 if (plp->plp_chanfullcal != plp->plp_chan) {
11121 plp->plp_chanfullcal = plp->plp_chan;
11122 fc = 1;
11123 }
11124
11125 bwn_mac_suspend(mac);
11126
11127 /* BlueTooth Coexistance Override */
11128 BWN_WRITE_2(mac, BWN_BTCOEX_CTL, 0x3);
11129 BWN_WRITE_2(mac, BWN_BTCOEX_TXCTL, 0xff);
11130
11131 if (mac->mac_phy.rev >= 2)
11132 bwn_phy_lp_digflt_save(mac);
11133 bwn_phy_lp_get_txpctlmode(mac);
11134 mode = plp->plp_txpctlmode;
11135 bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11136 if (mac->mac_phy.rev == 0 && mode != BWN_PHYLP_TXPCTL_OFF)
11137 bwn_phy_lp_bugfix(mac);
11138 if (mac->mac_phy.rev >= 2 && fc == 1) {
11139 bwn_phy_lp_get_txpctlmode(mac);
11140 omode = plp->plp_txpctlmode;
11141 oafeovr = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40;
11142 if (oafeovr)
11143 ogain = bwn_phy_lp_get_txgain(mac);
11144 orf = BWN_PHY_READ(mac, BWN_PHY_RF_PWR_OVERRIDE) & 0xff;
11145 obbmult = bwn_phy_lp_get_bbmult(mac);
11146 bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11147 if (oafeovr)
11148 bwn_phy_lp_set_txgain(mac, &ogain);
11149 bwn_phy_lp_set_bbmult(mac, obbmult);
11150 bwn_phy_lp_set_txpctlmode(mac, omode);
11151 BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00, orf);
11152 }
11153 bwn_phy_lp_set_txpctlmode(mac, mode);
11154 if (mac->mac_phy.rev >= 2)
11155 bwn_phy_lp_digflt_restore(mac);
11156
11157 /* do RX IQ Calculation; assumes that noise is true. */
11158 if (siba_get_chipid(sc->sc_dev) == 0x5354) {
11159 for (i = 0; i < N(bwn_rxcompco_5354); i++) {
11160 if (bwn_rxcompco_5354[i].rc_chan == plp->plp_chan)
11161 rc = &bwn_rxcompco_5354[i];
11162 }
11163 } else if (mac->mac_phy.rev >= 2)
11164 rc = &bwn_rxcompco_r2;
11165 else {
11166 for (i = 0; i < N(bwn_rxcompco_r12); i++) {
11167 if (bwn_rxcompco_r12[i].rc_chan == plp->plp_chan)
11168 rc = &bwn_rxcompco_r12[i];
11169 }
11170 }
11171 if (rc == NULL)
11172 goto fail;
11173
11174 BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, rc->rc_c1);
11175 BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, rc->rc_c0 << 8);
11176
11177 bwn_phy_lp_set_trsw_over(mac, 1 /* TX */, 0 /* RX */);
11178
11179 if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11180 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
11181 BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7, 0);
11182 } else {
11183 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
11184 BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf, 0);
11185 }
11186
11187 bwn_phy_lp_set_rxgain(mac, 0x2d5d);
11188 BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11189 BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
11190 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
11191 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
11192 bwn_phy_lp_set_deaf(mac, 0);
11193 /* XXX no checking return value? */
11194 (void)bwn_phy_lp_calc_rx_iq_comp(mac, 0xfff0);
11195 bwn_phy_lp_clear_deaf(mac, 0);
11196 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffc);
11197 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfff7);
11198 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffdf);
11199
11200 /* disable RX GAIN override. */
11201 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffe);
11202 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffef);
11203 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffbf);
11204 if (mac->mac_phy.rev >= 2) {
11205 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11206 if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11207 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfbff);
11208 BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xe5), 0xfff7);
11209 }
11210 } else {
11211 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfdff);
11212 }
11213
11214 BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11215 BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xf7ff);
11216fail:
11217 bwn_mac_enable(mac);
11218}
11219
11220static void
11221bwn_phy_lp_switch_analog(struct bwn_mac *mac, int on)
11222{
11223
11224 if (on) {
11225 BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfff8);
11226 return;
11227 }
11228
11229 BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVRVAL, 0x0007);
11230 BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x0007);
11231}
11232
11233static int
11234bwn_phy_lp_b2063_switch_channel(struct bwn_mac *mac, uint8_t chan)
11235{
11236 static const struct bwn_b206x_chan *bc = NULL;
11237 struct bwn_softc *sc = mac->mac_sc;
11238 uint32_t count, freqref, freqvco, freqxtal, val[3], timeout, timeoutref,
11239 tmp[6];
11240 uint16_t old, scale, tmp16;
11241 int i, div;
11242
11243 for (i = 0; i < N(bwn_b2063_chantable); i++) {
11244 if (bwn_b2063_chantable[i].bc_chan == chan) {
11245 bc = &bwn_b2063_chantable[i];
11246 break;
11247 }
11248 }
11249 if (bc == NULL)
11250 return (EINVAL);
11251
11252 BWN_RF_WRITE(mac, BWN_B2063_LOGEN_VCOBUF1, bc->bc_data[0]);
11253 BWN_RF_WRITE(mac, BWN_B2063_LOGEN_MIXER2, bc->bc_data[1]);
11254 BWN_RF_WRITE(mac, BWN_B2063_LOGEN_BUF2, bc->bc_data[2]);
11255 BWN_RF_WRITE(mac, BWN_B2063_LOGEN_RCCR1, bc->bc_data[3]);
11256 BWN_RF_WRITE(mac, BWN_B2063_A_RX_1ST3, bc->bc_data[4]);
11257 BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND1, bc->bc_data[5]);
11258 BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND4, bc->bc_data[6]);
11259 BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND7, bc->bc_data[7]);
11260 BWN_RF_WRITE(mac, BWN_B2063_A_RX_PS6, bc->bc_data[8]);
11261 BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL2, bc->bc_data[9]);
11262 BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL5, bc->bc_data[10]);
11263 BWN_RF_WRITE(mac, BWN_B2063_PA_CTL11, bc->bc_data[11]);
11264
11265 old = BWN_RF_READ(mac, BWN_B2063_COM15);
11266 BWN_RF_SET(mac, BWN_B2063_COM15, 0x1e);
11267
11268 freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
11269 freqvco = bc->bc_freq << ((bc->bc_freq > 4000) ? 1 : 2);
11270 freqref = freqxtal * 3;
11271 div = (freqxtal <= 26000000 ? 1 : 2);
11272 timeout = ((((8 * freqxtal) / (div * 5000000)) + 1) >> 1) - 1;
11273 timeoutref = ((((8 * freqxtal) / (div * (timeout + 1))) +
11274 999999) / 1000000) + 1;
11275
11276 BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB3, 0x2);
11277 BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB6,
11278 0xfff8, timeout >> 2);
11279 BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11280 0xff9f,timeout << 5);
11281 BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB5, timeoutref);
11282
11283 val[0] = bwn_phy_lp_roundup(freqxtal, 1000000, 16);
11284 val[1] = bwn_phy_lp_roundup(freqxtal, 1000000 * div, 16);
11285 val[2] = bwn_phy_lp_roundup(freqvco, 3, 16);
11286
11287 count = (bwn_phy_lp_roundup(val[2], val[1] + 16, 16) * (timeout + 1) *
11288 (timeoutref + 1)) - 1;
11289 BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11290 0xf0, count >> 8);
11291 BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB8, count & 0xff);
11292
11293 tmp[0] = ((val[2] * 62500) / freqref) << 4;
11294 tmp[1] = ((val[2] * 62500) % freqref) << 4;
11295 while (tmp[1] >= freqref) {
11296 tmp[0]++;
11297 tmp[1] -= freqref;
11298 }
11299 BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG1, 0xffe0, tmp[0] >> 4);
11300 BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfe0f, tmp[0] << 4);
11301 BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfff0, tmp[0] >> 16);
11302 BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG3, (tmp[1] >> 8) & 0xff);
11303 BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG4, tmp[1] & 0xff);
11304
11305 BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF1, 0xb9);
11306 BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF2, 0x88);
11307 BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF3, 0x28);
11308 BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF4, 0x63);
11309
11310 tmp[2] = ((41 * (val[2] - 3000)) /1200) + 27;
11311 tmp[3] = bwn_phy_lp_roundup(132000 * tmp[0], 8451, 16);
11312
11313 if ((tmp[3] + tmp[2] - 1) / tmp[2] > 60) {
11314 scale = 1;
11315 tmp[4] = ((tmp[3] + tmp[2]) / (tmp[2] << 1)) - 8;
11316 } else {
11317 scale = 0;
11318 tmp[4] = ((tmp[3] + (tmp[2] >> 1)) / tmp[2]) - 8;
11319 }
11320 BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffc0, tmp[4]);
11321 BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffbf, scale << 6);
11322
11323 tmp[5] = bwn_phy_lp_roundup(100 * val[0], val[2], 16) * (tmp[4] * 8) *
11324 (scale + 1);
11325 if (tmp[5] > 150)
11326 tmp[5] = 0;
11327
11328 BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffe0, tmp[5]);
11329 BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffdf, scale << 5);
11330
11331 BWN_RF_SETMASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfffb, 0x4);
11332 if (freqxtal > 26000000)
11333 BWN_RF_SET(mac, BWN_B2063_JTAG_XTAL_12, 0x2);
11334 else
11335 BWN_RF_MASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfd);
11336
11337 if (val[0] == 45)
11338 BWN_RF_SET(mac, BWN_B2063_JTAG_VCO1, 0x2);
11339 else
11340 BWN_RF_MASK(mac, BWN_B2063_JTAG_VCO1, 0xfd);
11341
11342 BWN_RF_SET(mac, BWN_B2063_PLL_SP2, 0x3);
11343 DELAY(1);
11344 BWN_RF_MASK(mac, BWN_B2063_PLL_SP2, 0xfffc);
11345
11346 /* VCO Calibration */
11347 BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, ~0x40);
11348 tmp16 = BWN_RF_READ(mac, BWN_B2063_JTAG_CALNRST) & 0xf8;
11349 BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16);
11350 DELAY(1);
11351 BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x4);
11352 DELAY(1);
11353 BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x6);
11354 DELAY(1);
11355 BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x7);
11356 DELAY(300);
11357 BWN_RF_SET(mac, BWN_B2063_PLL_SP1, 0x40);
11358
11359 BWN_RF_WRITE(mac, BWN_B2063_COM15, old);
11360 return (0);
11361}
11362
11363static int
11364bwn_phy_lp_b2062_switch_channel(struct bwn_mac *mac, uint8_t chan)
11365{
11366 struct bwn_softc *sc = mac->mac_sc;
11367 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11368 const struct bwn_b206x_chan *bc = NULL;
11369 uint32_t freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
11370 uint32_t tmp[9];
11371 int i;
11372
11373 for (i = 0; i < N(bwn_b2062_chantable); i++) {
11374 if (bwn_b2062_chantable[i].bc_chan == chan) {
11375 bc = &bwn_b2062_chantable[i];
11376 break;
11377 }
11378 }
11379
11380 if (bc == NULL)
11381 return (EINVAL);
11382
11383 BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL14, 0x04);
11384 BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE0, bc->bc_data[0]);
11385 BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE2, bc->bc_data[1]);
11386 BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE3, bc->bc_data[2]);
11387 BWN_RF_WRITE(mac, BWN_B2062_N_TX_TUNE, bc->bc_data[3]);
11388 BWN_RF_WRITE(mac, BWN_B2062_S_LGENG_CTL1, bc->bc_data[4]);
11389 BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL5, bc->bc_data[5]);
11390 BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL6, bc->bc_data[6]);
11391 BWN_RF_WRITE(mac, BWN_B2062_N_TX_PGA, bc->bc_data[7]);
11392 BWN_RF_WRITE(mac, BWN_B2062_N_TX_PAD, bc->bc_data[8]);
11393
11394 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xcc);
11395 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0x07);
11396 bwn_phy_lp_b2062_reset_pllbias(mac);
11397 tmp[0] = freqxtal / 1000;
11398 tmp[1] = plp->plp_div * 1000;
11399 tmp[2] = tmp[1] * ieee80211_ieee2mhz(chan, 0);
11400 if (ieee80211_ieee2mhz(chan, 0) < 4000)
11401 tmp[2] *= 2;
11402 tmp[3] = 48 * tmp[0];
11403 tmp[5] = tmp[2] / tmp[3];
11404 tmp[6] = tmp[2] % tmp[3];
11405 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL26, tmp[5]);
11406 tmp[4] = tmp[6] * 0x100;
11407 tmp[5] = tmp[4] / tmp[3];
11408 tmp[6] = tmp[4] % tmp[3];
11409 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL27, tmp[5]);
11410 tmp[4] = tmp[6] * 0x100;
11411 tmp[5] = tmp[4] / tmp[3];
11412 tmp[6] = tmp[4] % tmp[3];
11413 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL28, tmp[5]);
11414 tmp[4] = tmp[6] * 0x100;
11415 tmp[5] = tmp[4] / tmp[3];
11416 tmp[6] = tmp[4] % tmp[3];
11417 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL29,
11418 tmp[5] + ((2 * tmp[6]) / tmp[3]));
11419 tmp[7] = BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL19);
11420 tmp[8] = ((2 * tmp[2] * (tmp[7] + 1)) + (3 * tmp[0])) / (6 * tmp[0]);
11421 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL23, (tmp[8] >> 8) + 16);
11422 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL24, tmp[8] & 0xff);
11423
11424 bwn_phy_lp_b2062_vco_calib(mac);
11425 if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11426 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xfc);
11427 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0);
11428 bwn_phy_lp_b2062_reset_pllbias(mac);
11429 bwn_phy_lp_b2062_vco_calib(mac);
11430 if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11431 BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11432 return (EIO);
11433 }
11434 }
11435 BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11436 return (0);
11437}
11438
11439static void
11440bwn_phy_lp_set_anafilter(struct bwn_mac *mac, uint8_t channel)
11441{
11442 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11443 uint16_t tmp = (channel == 14);
11444
11445 if (mac->mac_phy.rev < 2) {
11446 BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xfcff, tmp << 9);
11447 if ((mac->mac_phy.rev == 1) && (plp->plp_rccap))
11448 bwn_phy_lp_set_rccap(mac);
11449 return;
11450 }
11451
11452 BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, 0x3f);
11453}
11454
11455static void
11456bwn_phy_lp_set_gaintbl(struct bwn_mac *mac, uint32_t freq)
11457{
11458 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11459 struct bwn_softc *sc = mac->mac_sc;
11460 struct ifnet *ifp = sc->sc_ifp;
11461 struct ieee80211com *ic = ifp->if_l2com;
11462 uint16_t iso, tmp[3];
11463
11464 KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
11465
11466 if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
11467 iso = plp->plp_txisoband_m;
11468 else if (freq <= 5320)
11469 iso = plp->plp_txisoband_l;
11470 else if (freq <= 5700)
11471 iso = plp->plp_txisoband_m;
11472 else
11473 iso = plp->plp_txisoband_h;
11474
11475 tmp[0] = ((iso - 26) / 12) << 12;
11476 tmp[1] = tmp[0] + 0x1000;
11477 tmp[2] = tmp[0] + 0x2000;
11478
11479 bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), 3, tmp);
11480 bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), 3, tmp);
11481}
11482
11483static void
11484bwn_phy_lp_digflt_save(struct bwn_mac *mac)
11485{
11486 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11487 int i;
11488 static const uint16_t addr[] = {
11489 BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11490 BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11491 BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11492 BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11493 BWN_PHY_OFDM(0xcf),
11494 };
11495 static const uint16_t val[] = {
11496 0xde5e, 0xe832, 0xe331, 0x4d26,
11497 0x0026, 0x1420, 0x0020, 0xfe08,
11498 0x0008,
11499 };
11500
11501 for (i = 0; i < N(addr); i++) {
11502 plp->plp_digfilt[i] = BWN_PHY_READ(mac, addr[i]);
11503 BWN_PHY_WRITE(mac, addr[i], val[i]);
11504 }
11505}
11506
11507static void
11508bwn_phy_lp_get_txpctlmode(struct bwn_mac *mac)
11509{
11510 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11511 struct bwn_softc *sc = mac->mac_sc;
11512 uint16_t ctl;
11513
11514 ctl = BWN_PHY_READ(mac, BWN_PHY_TX_PWR_CTL_CMD);
11515 switch (ctl & BWN_PHY_TX_PWR_CTL_CMD_MODE) {
11516 case BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF:
11517 plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_OFF;
11518 break;
11519 case BWN_PHY_TX_PWR_CTL_CMD_MODE_SW:
11520 plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_SW;
11521 break;
11522 case BWN_PHY_TX_PWR_CTL_CMD_MODE_HW:
11523 plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_HW;
11524 break;
11525 default:
11526 plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_UNKNOWN;
11527 device_printf(sc->sc_dev, "unknown command mode\n");
11528 break;
11529 }
11530}
11531
11532static void
11533bwn_phy_lp_set_txpctlmode(struct bwn_mac *mac, uint8_t mode)
11534{
11535 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11536 uint16_t ctl;
11537 uint8_t old;
11538
11539 bwn_phy_lp_get_txpctlmode(mac);
11540 old = plp->plp_txpctlmode;
11541 if (old == mode)
11542 return;
11543 plp->plp_txpctlmode = mode;
11544
11545 if (old != BWN_PHYLP_TXPCTL_ON_HW && mode == BWN_PHYLP_TXPCTL_ON_HW) {
11546 BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD, 0xff80,
11547 plp->plp_tssiidx);
11548 BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_NNUM,
11549 0x8fff, ((uint16_t)plp->plp_tssinpt << 16));
11550
11551 /* disable TX GAIN override */
11552 if (mac->mac_phy.rev < 2)
11553 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11554 else {
11555 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xff7f);
11556 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xbfff);
11557 }
11558 BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xffbf);
11559
11560 plp->plp_txpwridx = -1;
11561 }
11562 if (mac->mac_phy.rev >= 2) {
11563 if (mode == BWN_PHYLP_TXPCTL_ON_HW)
11564 BWN_PHY_SET(mac, BWN_PHY_OFDM(0xd0), 0x2);
11565 else
11566 BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xd0), 0xfffd);
11567 }
11568
11569 /* writes TX Power Control mode */
11570 switch (plp->plp_txpctlmode) {
11571 case BWN_PHYLP_TXPCTL_OFF:
11572 ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF;
11573 break;
11574 case BWN_PHYLP_TXPCTL_ON_HW:
11575 ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_HW;
11576 break;
11577 case BWN_PHYLP_TXPCTL_ON_SW:
11578 ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_SW;
11579 break;
11580 default:
11581 ctl = 0;
11582 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
11583 }
11584 BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD,
11585 (uint16_t)~BWN_PHY_TX_PWR_CTL_CMD_MODE, ctl);
11586}
11587
11588static void
11589bwn_phy_lp_bugfix(struct bwn_mac *mac)
11590{
11591 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11592 struct bwn_softc *sc = mac->mac_sc;
11593 const unsigned int size = 256;
11594 struct bwn_txgain tg;
11595 uint32_t rxcomp, txgain, coeff, rfpwr, *tabs;
11596 uint16_t tssinpt, tssiidx, value[2];
11597 uint8_t mode;
11598 int8_t txpwridx;
11599
11600 tabs = (uint32_t *)malloc(sizeof(uint32_t) * size, M_DEVBUF,
11601 M_NOWAIT | M_ZERO);
11602 if (tabs == NULL) {
11603 device_printf(sc->sc_dev, "failed to allocate buffer.\n");
11604 return;
11605 }
11606
11607 bwn_phy_lp_get_txpctlmode(mac);
11608 mode = plp->plp_txpctlmode;
11609 txpwridx = plp->plp_txpwridx;
11610 tssinpt = plp->plp_tssinpt;
11611 tssiidx = plp->plp_tssiidx;
11612
11613 bwn_tab_read_multi(mac,
11614 (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11615 BWN_TAB_4(7, 0x140), size, tabs);
11616
11617 bwn_phy_lp_tblinit(mac);
11618 bwn_phy_lp_bbinit(mac);
11619 bwn_phy_lp_txpctl_init(mac);
11620 bwn_phy_lp_rf_onoff(mac, 1);
11621 bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11622
11623 bwn_tab_write_multi(mac,
11624 (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11625 BWN_TAB_4(7, 0x140), size, tabs);
11626
11627 BWN_WRITE_2(mac, BWN_CHANNEL, plp->plp_chan);
11628 plp->plp_tssinpt = tssinpt;
11629 plp->plp_tssiidx = tssiidx;
11630 bwn_phy_lp_set_anafilter(mac, plp->plp_chan);
11631 if (txpwridx != -1) {
11632 /* set TX power by index */
11633 plp->plp_txpwridx = txpwridx;
11634 bwn_phy_lp_get_txpctlmode(mac);
11635 if (plp->plp_txpctlmode != BWN_PHYLP_TXPCTL_OFF)
11636 bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_ON_SW);
11637 if (mac->mac_phy.rev >= 2) {
11638 rxcomp = bwn_tab_read(mac,
11639 BWN_TAB_4(7, txpwridx + 320));
11640 txgain = bwn_tab_read(mac,
11641 BWN_TAB_4(7, txpwridx + 192));
11642 tg.tg_pad = (txgain >> 16) & 0xff;
11643 tg.tg_gm = txgain & 0xff;
11644 tg.tg_pga = (txgain >> 8) & 0xff;
11645 tg.tg_dac = (rxcomp >> 28) & 0xff;
11646 bwn_phy_lp_set_txgain(mac, &tg);
11647 } else {
11648 rxcomp = bwn_tab_read(mac,
11649 BWN_TAB_4(10, txpwridx + 320));
11650 txgain = bwn_tab_read(mac,
11651 BWN_TAB_4(10, txpwridx + 192));
11652 BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
11653 0xf800, (txgain >> 4) & 0x7fff);
11654 bwn_phy_lp_set_txgain_dac(mac, txgain & 0x7);
11655 bwn_phy_lp_set_txgain_pa(mac, (txgain >> 24) & 0x7f);
11656 }
11657 bwn_phy_lp_set_bbmult(mac, (rxcomp >> 20) & 0xff);
11658
11659 /* set TX IQCC */
11660 value[0] = (rxcomp >> 10) & 0x3ff;
11661 value[1] = rxcomp & 0x3ff;
11662 bwn_tab_write_multi(mac, BWN_TAB_2(0, 80), 2, value);
11663
11664 coeff = bwn_tab_read(mac,
11665 (mac->mac_phy.rev >= 2) ? BWN_TAB_4(7, txpwridx + 448) :
11666 BWN_TAB_4(10, txpwridx + 448));
11667 bwn_tab_write(mac, BWN_TAB_2(0, 85), coeff & 0xffff);
11668 if (mac->mac_phy.rev >= 2) {
11669 rfpwr = bwn_tab_read(mac,
11670 BWN_TAB_4(7, txpwridx + 576));
11671 BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00,
11672 rfpwr & 0xffff);
11673 }
11674 bwn_phy_lp_set_txgain_override(mac);
11675 }
11676 if (plp->plp_rccap)
11677 bwn_phy_lp_set_rccap(mac);
11678 bwn_phy_lp_set_antenna(mac, plp->plp_antenna);
11679 bwn_phy_lp_set_txpctlmode(mac, mode);
11680 free(tabs, M_DEVBUF);
11681}
11682
11683static void
11684bwn_phy_lp_digflt_restore(struct bwn_mac *mac)
11685{
11686 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11687 int i;
11688 static const uint16_t addr[] = {
11689 BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11690 BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11691 BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11692 BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11693 BWN_PHY_OFDM(0xcf),
11694 };
11695
11696 for (i = 0; i < N(addr); i++)
11697 BWN_PHY_WRITE(mac, addr[i], plp->plp_digfilt[i]);
11698}
11699
11700static void
11701bwn_phy_lp_tblinit(struct bwn_mac *mac)
11702{
11703 uint32_t freq = ieee80211_ieee2mhz(bwn_phy_lp_get_default_chan(mac), 0);
11704
11705 if (mac->mac_phy.rev < 2) {
11706 bwn_phy_lp_tblinit_r01(mac);
11707 bwn_phy_lp_tblinit_txgain(mac);
11708 bwn_phy_lp_set_gaintbl(mac, freq);
11709 return;
11710 }
11711
11712 bwn_phy_lp_tblinit_r2(mac);
11713 bwn_phy_lp_tblinit_txgain(mac);
11714}
11715
11716struct bwn_wpair {
11717 uint16_t reg;
11718 uint16_t value;
11719};
11720
11721struct bwn_smpair {
11722 uint16_t offset;
11723 uint16_t mask;
11724 uint16_t set;
11725};
11726
11727static void
11728bwn_phy_lp_bbinit_r2(struct bwn_mac *mac)
11729{
11730 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11731 struct bwn_softc *sc = mac->mac_sc;
11732 struct ifnet *ifp = sc->sc_ifp;
11733 struct ieee80211com *ic = ifp->if_l2com;
11734 static const struct bwn_wpair v1[] = {
11735 { BWN_PHY_AFE_DAC_CTL, 0x50 },
11736 { BWN_PHY_AFE_CTL, 0x8800 },
11737 { BWN_PHY_AFE_CTL_OVR, 0 },
11738 { BWN_PHY_AFE_CTL_OVRVAL, 0 },
11739 { BWN_PHY_RF_OVERRIDE_0, 0 },
11740 { BWN_PHY_RF_OVERRIDE_2, 0 },
11741 { BWN_PHY_OFDM(0xf9), 0 },
11742 { BWN_PHY_TR_LOOKUP_1, 0 }
11743 };
11744 static const struct bwn_smpair v2[] = {
11745 { BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0xb4 },
11746 { BWN_PHY_DCOFFSETTRANSIENT, 0xf8ff, 0x200 },
11747 { BWN_PHY_DCOFFSETTRANSIENT, 0xff00, 0x7f },
11748 { BWN_PHY_GAINDIRECTMISMATCH, 0xff0f, 0x40 },
11749 { BWN_PHY_PREAMBLECONFIRMTO, 0xff00, 0x2 }
11750 };
11751 static const struct bwn_smpair v3[] = {
11752 { BWN_PHY_OFDM(0xfe), 0xffe0, 0x1f },
11753 { BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11754 { BWN_PHY_OFDM(0x100), 0xff00, 0x19 },
11755 { BWN_PHY_OFDM(0xff), 0x03ff, 0x3c00 },
11756 { BWN_PHY_OFDM(0xfe), 0xfc1f, 0x3e0 },
11757 { BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11758 { BWN_PHY_OFDM(0x100), 0x00ff, 0x1900 },
11759 { BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800 },
11760 { BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x12 },
11761 { BWN_PHY_GAINMISMATCH, 0x0fff, 0x9000 },
11762
11763 };
11764 int i;
11765
11766 for (i = 0; i < N(v1); i++)
11767 BWN_PHY_WRITE(mac, v1[i].reg, v1[i].value);
11768 BWN_PHY_SET(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x10);
11769 for (i = 0; i < N(v2); i++)
11770 BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask, v2[i].set);
11771
11772 BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x4000);
11773 BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x2000);
11774 BWN_PHY_SET(mac, BWN_PHY_OFDM(0x10a), 0x1);
11775 if (siba_get_pci_revid(sc->sc_dev) >= 0x18) {
11776 bwn_tab_write(mac, BWN_TAB_4(17, 65), 0xec);
11777 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x14);
11778 } else {
11779 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x10);
11780 }
11781 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0xff00, 0xf4);
11782 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0x00ff, 0xf100);
11783 BWN_PHY_WRITE(mac, BWN_PHY_CLIPTHRESH, 0x48);
11784 BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0xff00, 0x46);
11785 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe4), 0xff00, 0x10);
11786 BWN_PHY_SETMASK(mac, BWN_PHY_PWR_THRESH1, 0xfff0, 0x9);
11787 BWN_PHY_MASK(mac, BWN_PHY_GAINDIRECTMISMATCH, ~0xf);
11788 BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5500);
11789 BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0xa0);
11790 BWN_PHY_SETMASK(mac, BWN_PHY_GAINDIRECTMISMATCH, 0xe0ff, 0x300);
11791 BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2a00);
11792 if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11793 (siba_get_chiprev(sc->sc_dev) == 0)) {
11794 BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11795 BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xa);
11796 } else {
11797 BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x1e00);
11798 BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xd);
11799 }
11800 for (i = 0; i < N(v3); i++)
11801 BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask, v3[i].set);
11802 if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11803 (siba_get_chiprev(sc->sc_dev) == 0)) {
11804 bwn_tab_write(mac, BWN_TAB_2(0x08, 0x14), 0);
11805 bwn_tab_write(mac, BWN_TAB_2(0x08, 0x12), 0x40);
11806 }
11807
11808 if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11809 BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x40);
11810 BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0xb00);
11811 BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x6);
11812 BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0x9d00);
11813 BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0xff00, 0xa1);
11814 BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
11815 } else
11816 BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x40);
11817
11818 BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0xff00, 0xb3);
11819 BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00);
11820 BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB, 0xff00, plp->plp_rxpwroffset);
11821 BWN_PHY_SET(mac, BWN_PHY_RESET_CTL, 0x44);
11822 BWN_PHY_WRITE(mac, BWN_PHY_RESET_CTL, 0x80);
11823 BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, 0xa954);
11824 BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_1,
11825 0x2000 | ((uint16_t)plp->plp_rssigs << 10) |
11826 ((uint16_t)plp->plp_rssivc << 4) | plp->plp_rssivf);
11827
11828 if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11829 (siba_get_chiprev(sc->sc_dev) == 0)) {
11830 BWN_PHY_SET(mac, BWN_PHY_AFE_ADC_CTL_0, 0x1c);
11831 BWN_PHY_SETMASK(mac, BWN_PHY_AFE_CTL, 0x00ff, 0x8800);
11832 BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_1, 0xfc3c, 0x0400);
11833 }
11834
11835 bwn_phy_lp_digflt_save(mac);
11836}
11837
11838static void
11839bwn_phy_lp_bbinit_r01(struct bwn_mac *mac)
11840{
11841 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11842 struct bwn_softc *sc = mac->mac_sc;
11843 struct ifnet *ifp = sc->sc_ifp;
11844 struct ieee80211com *ic = ifp->if_l2com;
11845 static const struct bwn_smpair v1[] = {
11846 { BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x0005 },
11847 { BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0x0180 },
11848 { BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x3c00 },
11849 { BWN_PHY_GAINDIRECTMISMATCH, 0xfff0, 0x0005 },
11850 { BWN_PHY_GAIN_MISMATCH_LIMIT, 0xffc0, 0x001a },
11851 { BWN_PHY_CRS_ED_THRESH, 0xff00, 0x00b3 },
11852 { BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00 }
11853 };
11854 static const struct bwn_smpair v2[] = {
11855 { BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11856 { BWN_PHY_TR_LOOKUP_1, 0x3f00, 0x0900 },
11857 { BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11858 { BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11859 { BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x000a },
11860 { BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0400 },
11861 { BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x000a },
11862 { BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0b00 },
11863 { BWN_PHY_TR_LOOKUP_5, 0xffc0, 0x000a },
11864 { BWN_PHY_TR_LOOKUP_5, 0xc0ff, 0x0900 },
11865 { BWN_PHY_TR_LOOKUP_6, 0xffc0, 0x000a },
11866 { BWN_PHY_TR_LOOKUP_6, 0xc0ff, 0x0b00 },
11867 { BWN_PHY_TR_LOOKUP_7, 0xffc0, 0x000a },
11868 { BWN_PHY_TR_LOOKUP_7, 0xc0ff, 0x0900 },
11869 { BWN_PHY_TR_LOOKUP_8, 0xffc0, 0x000a },
11870 { BWN_PHY_TR_LOOKUP_8, 0xc0ff, 0x0b00 }
11871 };
11872 static const struct bwn_smpair v3[] = {
11873 { BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0001 },
11874 { BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0400 },
11875 { BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0001 },
11876 { BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0500 },
11877 { BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11878 { BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0800 },
11879 { BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11880 { BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0a00 }
11881 };
11882 static const struct bwn_smpair v4[] = {
11883 { BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0004 },
11884 { BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0800 },
11885 { BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0004 },
11886 { BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0c00 },
11887 { BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11888 { BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0100 },
11889 { BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11890 { BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0300 }
11891 };
11892 static const struct bwn_smpair v5[] = {
11893 { BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11894 { BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0900 },
11895 { BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11896 { BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11897 { BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0006 },
11898 { BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0500 },
11899 { BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0006 },
11900 { BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0700 }
11901 };
11902 int i;
11903 uint16_t tmp, tmp2;
11904
11905 BWN_PHY_MASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf7ff);
11906 BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL, 0);
11907 BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, 0);
11908 BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, 0);
11909 BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0);
11910 BWN_PHY_SET(mac, BWN_PHY_AFE_DAC_CTL, 0x0004);
11911 BWN_PHY_SETMASK(mac, BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0x0078);
11912 BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800);
11913 BWN_PHY_WRITE(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x0016);
11914 BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_0, 0xfff8, 0x0004);
11915 BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5400);
11916 BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2400);
11917 BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11918 BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0x0006);
11919 BWN_PHY_MASK(mac, BWN_PHY_RX_RADIO_CTL, 0xfffe);
11920 for (i = 0; i < N(v1); i++)
11921 BWN_PHY_SETMASK(mac, v1[i].offset, v1[i].mask, v1[i].set);
11922 BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB,
11923 0xff00, plp->plp_rxpwroffset);
11924 if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM) &&
11925 ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ||
11926 (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_LDO_PAREF))) {
11927 siba_cc_pmu_set_ldovolt(sc->sc_dev, SIBA_LDO_PAREF, 0x28);
11928 siba_cc_pmu_set_ldoparef(sc->sc_dev, 1);
11929 if (mac->mac_phy.rev == 0)
11930 BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT,
11931 0xffcf, 0x0010);
11932 bwn_tab_write(mac, BWN_TAB_2(11, 7), 60);
11933 } else {
11934 siba_cc_pmu_set_ldoparef(sc->sc_dev, 0);
11935 BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT, 0xffcf, 0x0020);
11936 bwn_tab_write(mac, BWN_TAB_2(11, 7), 100);
11937 }
11938 tmp = plp->plp_rssivf | plp->plp_rssivc << 4 | 0xa000;
11939 BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, tmp);
11940 if (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_RSSIINV)
11941 BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x0aaa);
11942 else
11943 BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x02aa);
11944 bwn_tab_write(mac, BWN_TAB_2(11, 1), 24);
11945 BWN_PHY_SETMASK(mac, BWN_PHY_RX_RADIO_CTL,
11946 0xfff9, (plp->plp_bxarch << 1));
11947 if (mac->mac_phy.rev == 1 &&
11948 (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_FEM_BT)) {
11949 for (i = 0; i < N(v2); i++)
11950 BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask,
11951 v2[i].set);
11952 } else if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ||
11953 (siba_get_pci_subdevice(sc->sc_dev) == 0x048a) ||
11954 ((mac->mac_phy.rev == 0) &&
11955 (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM))) {
11956 for (i = 0; i < N(v3); i++)
11957 BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask,
11958 v3[i].set);
11959 } else if (mac->mac_phy.rev == 1 ||
11960 (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM)) {
11961 for (i = 0; i < N(v4); i++)
11962 BWN_PHY_SETMASK(mac, v4[i].offset, v4[i].mask,
11963 v4[i].set);
11964 } else {
11965 for (i = 0; i < N(v5); i++)
11966 BWN_PHY_SETMASK(mac, v5[i].offset, v5[i].mask,
11967 v5[i].set);
11968 }
11969 if (mac->mac_phy.rev == 1 &&
11970 (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_LDO_PAREF)) {
11971 BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_5, BWN_PHY_TR_LOOKUP_1);
11972 BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_6, BWN_PHY_TR_LOOKUP_2);
11973 BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_7, BWN_PHY_TR_LOOKUP_3);
11974 BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_8, BWN_PHY_TR_LOOKUP_4);
11975 }
11976 if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_FEM_BT) &&
11977 (siba_get_chipid(sc->sc_dev) == 0x5354) &&
11978 (siba_get_chippkg(sc->sc_dev) == SIBA_CHIPPACK_BCM4712S)) {
11979 BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0006);
11980 BWN_PHY_WRITE(mac, BWN_PHY_GPIO_SELECT, 0x0005);
11981 BWN_PHY_WRITE(mac, BWN_PHY_GPIO_OUTEN, 0xffff);
11982 bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_PR45960W);
11983 }
11984 if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11985 BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x8000);
11986 BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0040);
11987 BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0xa400);
11988 BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0x0b00);
11989 BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x0007);
11990 BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xfff8, 0x0003);
11991 BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xffc7, 0x0020);
11992 BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
11993 } else {
11994 BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0x7fff);
11995 BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xffbf);
11996 }
11997 if (mac->mac_phy.rev == 1) {
11998 tmp = BWN_PHY_READ(mac, BWN_PHY_CLIPCTRTHRESH);
11999 tmp2 = (tmp & 0x03e0) >> 5;
12000 tmp2 |= tmp2 << 5;
12001 BWN_PHY_WRITE(mac, BWN_PHY_4C3, tmp2);
12002 tmp = BWN_PHY_READ(mac, BWN_PHY_GAINDIRECTMISMATCH);
12003 tmp2 = (tmp & 0x1f00) >> 8;
12004 tmp2 |= tmp2 << 5;
12005 BWN_PHY_WRITE(mac, BWN_PHY_4C4, tmp2);
12006 tmp = BWN_PHY_READ(mac, BWN_PHY_VERYLOWGAINDB);
12007 tmp2 = tmp & 0x00ff;
12008 tmp2 |= tmp << 8;
12009 BWN_PHY_WRITE(mac, BWN_PHY_4C5, tmp2);
12010 }
12011}
12012
12013struct bwn_b2062_freq {
12014 uint16_t freq;
12015 uint8_t value[6];
12016};
12017
12018static void
12019bwn_phy_lp_b2062_init(struct bwn_mac *mac)
12020{
12021#define CALC_CTL7(freq, div) \
12022 (((800000000 * (div) + (freq)) / (2 * (freq)) - 8) & 0xff)
12023#define CALC_CTL18(freq, div) \
12024 ((((100 * (freq) + 16000000 * (div)) / (32000000 * (div))) - 1) & 0xff)
12025#define CALC_CTL19(freq, div) \
12026 ((((2 * (freq) + 1000000 * (div)) / (2000000 * (div))) - 1) & 0xff)
12027 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12028 struct bwn_softc *sc = mac->mac_sc;
12029 struct ifnet *ifp = sc->sc_ifp;
12030 struct ieee80211com *ic = ifp->if_l2com;
12031 static const struct bwn_b2062_freq freqdata_tab[] = {
12032 { 12000, { 6, 6, 6, 6, 10, 6 } },
12033 { 13000, { 4, 4, 4, 4, 11, 7 } },
12034 { 14400, { 3, 3, 3, 3, 12, 7 } },
12035 { 16200, { 3, 3, 3, 3, 13, 8 } },
12036 { 18000, { 2, 2, 2, 2, 14, 8 } },
12037 { 19200, { 1, 1, 1, 1, 14, 9 } }
12038 };
12039 static const struct bwn_wpair v1[] = {
12040 { BWN_B2062_N_TXCTL3, 0 },
12041 { BWN_B2062_N_TXCTL4, 0 },
12042 { BWN_B2062_N_TXCTL5, 0 },
12043 { BWN_B2062_N_TXCTL6, 0 },
12044 { BWN_B2062_N_PDNCTL0, 0x40 },
12045 { BWN_B2062_N_PDNCTL0, 0 },
12046 { BWN_B2062_N_CALIB_TS, 0x10 },
12047 { BWN_B2062_N_CALIB_TS, 0 }
12048 };
12049 const struct bwn_b2062_freq *f = NULL;
12050 uint32_t xtalfreq, ref;
12051 unsigned int i;
12052
12053 bwn_phy_lp_b2062_tblinit(mac);
12054
12055 for (i = 0; i < N(v1); i++)
12056 BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12057 if (mac->mac_phy.rev > 0)
12058 BWN_RF_WRITE(mac, BWN_B2062_S_BG_CTL1,
12059 (BWN_RF_READ(mac, BWN_B2062_N_COM2) >> 1) | 0x80);
12060 if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12061 BWN_RF_SET(mac, BWN_B2062_N_TSSI_CTL0, 0x1);
12062 else
12063 BWN_RF_MASK(mac, BWN_B2062_N_TSSI_CTL0, ~0x1);
12064
12065 KASSERT(siba_get_cc_caps(sc->sc_dev) & SIBA_CC_CAPS_PMU,
12066 ("%s:%d: fail", __func__, __LINE__));
12067 xtalfreq = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
12068 KASSERT(xtalfreq != 0, ("%s:%d: fail", __func__, __LINE__));
12069
12070 if (xtalfreq <= 30000000) {
12071 plp->plp_div = 1;
12072 BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL1, 0xfffb);
12073 } else {
12074 plp->plp_div = 2;
12075 BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL1, 0x4);
12076 }
12077
12078 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL7,
12079 CALC_CTL7(xtalfreq, plp->plp_div));
12080 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL18,
12081 CALC_CTL18(xtalfreq, plp->plp_div));
12082 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL19,
12083 CALC_CTL19(xtalfreq, plp->plp_div));
12084
12085 ref = (1000 * plp->plp_div + 2 * xtalfreq) / (2000 * plp->plp_div);
12086 ref &= 0xffff;
12087 for (i = 0; i < N(freqdata_tab); i++) {
12088 if (ref < freqdata_tab[i].freq) {
12089 f = &freqdata_tab[i];
12090 break;
12091 }
12092 }
12093 if (f == NULL)
12094 f = &freqdata_tab[N(freqdata_tab) - 1];
12095 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL8,
12096 ((uint16_t)(f->value[1]) << 4) | f->value[0]);
12097 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL9,
12098 ((uint16_t)(f->value[3]) << 4) | f->value[2]);
12099 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL10, f->value[4]);
12100 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL11, f->value[5]);
12101#undef CALC_CTL7
12102#undef CALC_CTL18
12103#undef CALC_CTL19
12104}
12105
12106static void
12107bwn_phy_lp_b2063_init(struct bwn_mac *mac)
12108{
12109
12110 bwn_phy_lp_b2063_tblinit(mac);
12111 BWN_RF_WRITE(mac, BWN_B2063_LOGEN_SP5, 0);
12112 BWN_RF_SET(mac, BWN_B2063_COM8, 0x38);
12113 BWN_RF_WRITE(mac, BWN_B2063_REG_SP1, 0x56);
12114 BWN_RF_MASK(mac, BWN_B2063_RX_BB_CTL2, ~0x2);
12115 BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0);
12116 BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP6, 0x20);
12117 BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP9, 0x40);
12118 if (mac->mac_phy.rev == 2) {
12119 BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0xa0);
12120 BWN_RF_WRITE(mac, BWN_B2063_PA_SP4, 0xa0);
12121 BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x18);
12122 } else {
12123 BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0x20);
12124 BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x20);
12125 }
12126}
12127
12128static void
12129bwn_phy_lp_rxcal_r2(struct bwn_mac *mac)
12130{
12131 struct bwn_softc *sc = mac->mac_sc;
12132 static const struct bwn_wpair v1[] = {
12133 { BWN_B2063_RX_BB_SP8, 0x0 },
12134 { BWN_B2063_RC_CALIB_CTL1, 0x7e },
12135 { BWN_B2063_RC_CALIB_CTL1, 0x7c },
12136 { BWN_B2063_RC_CALIB_CTL2, 0x15 },
12137 { BWN_B2063_RC_CALIB_CTL3, 0x70 },
12138 { BWN_B2063_RC_CALIB_CTL4, 0x52 },
12139 { BWN_B2063_RC_CALIB_CTL5, 0x1 },
12140 { BWN_B2063_RC_CALIB_CTL1, 0x7d }
12141 };
12142 static const struct bwn_wpair v2[] = {
12143 { BWN_B2063_TX_BB_SP3, 0x0 },
12144 { BWN_B2063_RC_CALIB_CTL1, 0x7e },
12145 { BWN_B2063_RC_CALIB_CTL1, 0x7c },
12146 { BWN_B2063_RC_CALIB_CTL2, 0x55 },
12147 { BWN_B2063_RC_CALIB_CTL3, 0x76 }
12148 };
12149 uint32_t freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
12150 int i;
12151 uint8_t tmp;
12152
12153 tmp = BWN_RF_READ(mac, BWN_B2063_RX_BB_SP8) & 0xff;
12154
12155 for (i = 0; i < 2; i++)
12156 BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12157 BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, 0xf7);
12158 for (i = 2; i < N(v1); i++)
12159 BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12160 for (i = 0; i < 10000; i++) {
12161 if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12162 break;
12163 DELAY(1000);
12164 }
12165
12166 if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12167 BWN_RF_WRITE(mac, BWN_B2063_RX_BB_SP8, tmp);
12168
12169 tmp = BWN_RF_READ(mac, BWN_B2063_TX_BB_SP3) & 0xff;
12170
12171 for (i = 0; i < N(v2); i++)
12172 BWN_RF_WRITE(mac, v2[i].reg, v2[i].value);
12173 if (freqxtal == 24000000) {
12174 BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0xfc);
12175 BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x0);
12176 } else {
12177 BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0x13);
12178 BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x1);
12179 }
12180 BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0x7d);
12181 for (i = 0; i < 10000; i++) {
12182 if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12183 break;
12184 DELAY(1000);
12185 }
12186 if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12187 BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, tmp);
12188 BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL1, 0x7e);
12189}
12190
12191static void
12192bwn_phy_lp_rccal_r12(struct bwn_mac *mac)
12193{
12194 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12195 struct bwn_softc *sc = mac->mac_sc;
12196 struct bwn_phy_lp_iq_est ie;
12197 struct bwn_txgain tx_gains;
12198 static const uint32_t pwrtbl[21] = {
12199 0x10000, 0x10557, 0x10e2d, 0x113e0, 0x10f22, 0x0ff64,
12200 0x0eda2, 0x0e5d4, 0x0efd1, 0x0fbe8, 0x0b7b8, 0x04b35,
12201 0x01a5e, 0x00a0b, 0x00444, 0x001fd, 0x000ff, 0x00088,
12202 0x0004c, 0x0002c, 0x0001a,
12203 };
12204 uint32_t npwr, ipwr, sqpwr, tmp;
12205 int loopback, i, j, sum, error;
12206 uint16_t save[7];
12207 uint8_t txo, bbmult, txpctlmode;
12208
12209 error = bwn_phy_lp_switch_channel(mac, 7);
12210 if (error)
12211 device_printf(sc->sc_dev,
12212 "failed to change channel to 7 (%d)\n", error);
12213 txo = (BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40) ? 1 : 0;
12214 bbmult = bwn_phy_lp_get_bbmult(mac);
12215 if (txo)
12216 tx_gains = bwn_phy_lp_get_txgain(mac);
12217
12218 save[0] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_0);
12219 save[1] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_VAL_0);
12220 save[2] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR);
12221 save[3] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVRVAL);
12222 save[4] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2);
12223 save[5] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2_VAL);
12224 save[6] = BWN_PHY_READ(mac, BWN_PHY_LP_PHY_CTL);
12225
12226 bwn_phy_lp_get_txpctlmode(mac);
12227 txpctlmode = plp->plp_txpctlmode;
12228 bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
12229
12230 /* disable CRS */
12231 bwn_phy_lp_set_deaf(mac, 1);
12232 bwn_phy_lp_set_trsw_over(mac, 0, 1);
12233 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffb);
12234 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x4);
12235 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7);
12236 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
12237 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x10);
12238 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12239 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf);
12240 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
12241 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffbf);
12242 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12243 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x7);
12244 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x38);
12245 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f);
12246 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x100);
12247 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfdff);
12248 BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL0, 0);
12249 BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL1, 1);
12250 BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL2, 0x20);
12251 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfbff);
12252 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xf7ff);
12253 BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0);
12254 BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, 0x45af);
12255 BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0x3ff);
12256
12257 loopback = bwn_phy_lp_loopback(mac);
12258 if (loopback == -1)
12259 goto done;
12260 bwn_phy_lp_set_rxgain_idx(mac, loopback);
12261 BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xffbf, 0x40);
12262 BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfff8, 0x1);
12263 BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xffc7, 0x8);
12264 BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f, 0xc0);
12265
12266 tmp = 0;
12267 memset(&ie, 0, sizeof(ie));
12268 for (i = 128; i <= 159; i++) {
12269 BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2, i);
12270 sum = 0;
12271 for (j = 5; j <= 25; j++) {
12272 bwn_phy_lp_ddfs_turnon(mac, 1, 1, j, j, 0);
12273 if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
12274 goto done;
12275 sqpwr = ie.ie_ipwr + ie.ie_qpwr;
12276 ipwr = ((pwrtbl[j - 5] >> 3) + 1) >> 1;
12277 npwr = bwn_phy_lp_roundup(sqpwr, (j == 5) ? sqpwr : 0,
12278 12);
12279 sum += ((ipwr - npwr) * (ipwr - npwr));
12280 if ((i == 128) || (sum < tmp)) {
12281 plp->plp_rccap = i;
12282 tmp = sum;
12283 }
12284 }
12285 }
12286 bwn_phy_lp_ddfs_turnoff(mac);
12287done:
12288 /* restore CRS */
12289 bwn_phy_lp_clear_deaf(mac, 1);
12290 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xff80);
12291 BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfc00);
12292
12293 BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_VAL_0, save[1]);
12294 BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, save[0]);
12295 BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVRVAL, save[3]);
12296 BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, save[2]);
12297 BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2_VAL, save[5]);
12298 BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, save[4]);
12299 BWN_PHY_WRITE(mac, BWN_PHY_LP_PHY_CTL, save[6]);
12300
12301 bwn_phy_lp_set_bbmult(mac, bbmult);
12302 if (txo)
12303 bwn_phy_lp_set_txgain(mac, &tx_gains);
12304 bwn_phy_lp_set_txpctlmode(mac, txpctlmode);
12305 if (plp->plp_rccap)
12306 bwn_phy_lp_set_rccap(mac);
12307}
12308
12309static void
12310bwn_phy_lp_set_rccap(struct bwn_mac *mac)
12311{
12312 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12313 uint8_t rc_cap = (plp->plp_rccap & 0x1f) >> 1;
12314
12315 if (mac->mac_phy.rev == 1)
12316 rc_cap = MIN(rc_cap + 5, 15);
12317
12318 BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2,
12319 MAX(plp->plp_rccap - 4, 0x80));
12320 BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, rc_cap | 0x80);
12321 BWN_RF_WRITE(mac, BWN_B2062_S_RXG_CNT16,
12322 ((plp->plp_rccap & 0x1f) >> 2) | 0x80);
12323}
12324
12325static uint32_t
12326bwn_phy_lp_roundup(uint32_t value, uint32_t div, uint8_t pre)
12327{
12328 uint32_t i, q, r;
12329
12330 if (div == 0)
12331 return (0);
12332
12333 for (i = 0, q = value / div, r = value % div; i < pre; i++) {
12334 q <<= 1;
12335 if (r << 1 >= div) {
12336 q++;
12337 r = (r << 1) - div;
12338 }
12339 }
12340 if (r << 1 >= div)
12341 q++;
12342 return (q);
12343}
12344
12345static void
12346bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *mac)
12347{
12348 struct bwn_softc *sc = mac->mac_sc;
12349
12350 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0xff);
12351 DELAY(20);
12352 if (siba_get_chipid(sc->sc_dev) == 0x5354) {
12353 BWN_RF_WRITE(mac, BWN_B2062_N_COM1, 4);
12354 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 4);
12355 } else {
12356 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0);
12357 }
12358 DELAY(5);
12359}
12360
12361static void
12362bwn_phy_lp_b2062_vco_calib(struct bwn_mac *mac)
12363{
12364
12365 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x42);
12366 BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x62);
12367 DELAY(200);
12368}
12369
12370static void
12371bwn_phy_lp_b2062_tblinit(struct bwn_mac *mac)
12372{
12373#define FLAG_A 0x01
12374#define FLAG_G 0x02
12375 struct bwn_softc *sc = mac->mac_sc;
12376 struct ifnet *ifp = sc->sc_ifp;
12377 struct ieee80211com *ic = ifp->if_l2com;
12378 static const struct bwn_b206x_rfinit_entry bwn_b2062_init_tab[] = {
12379 { BWN_B2062_N_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12380 { BWN_B2062_N_PDNCTL1, 0x0, 0xca, FLAG_G, },
12381 { BWN_B2062_N_PDNCTL3, 0x0, 0x0, FLAG_A | FLAG_G, },
12382 { BWN_B2062_N_PDNCTL4, 0x15, 0x2a, FLAG_A | FLAG_G, },
12383 { BWN_B2062_N_LGENC, 0xDB, 0xff, FLAG_A, },
12384 { BWN_B2062_N_LGENATUNE0, 0xdd, 0x0, FLAG_A | FLAG_G, },
12385 { BWN_B2062_N_LGENATUNE2, 0xdd, 0x0, FLAG_A | FLAG_G, },
12386 { BWN_B2062_N_LGENATUNE3, 0x77, 0xB5, FLAG_A | FLAG_G, },
12387 { BWN_B2062_N_LGENACTL3, 0x0, 0xff, FLAG_A | FLAG_G, },
12388 { BWN_B2062_N_LGENACTL7, 0x33, 0x33, FLAG_A | FLAG_G, },
12389 { BWN_B2062_N_RXA_CTL1, 0x0, 0x0, FLAG_G, },
12390 { BWN_B2062_N_RXBB_CTL0, 0x82, 0x80, FLAG_A | FLAG_G, },
12391 { BWN_B2062_N_RXBB_GAIN1, 0x4, 0x4, FLAG_A | FLAG_G, },
12392 { BWN_B2062_N_RXBB_GAIN2, 0x0, 0x0, FLAG_A | FLAG_G, },
12393 { BWN_B2062_N_TXCTL4, 0x3, 0x3, FLAG_A | FLAG_G, },
12394 { BWN_B2062_N_TXCTL5, 0x2, 0x2, FLAG_A | FLAG_G, },
12395 { BWN_B2062_N_TX_TUNE, 0x88, 0x1b, FLAG_A | FLAG_G, },
12396 { BWN_B2062_S_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12397 { BWN_B2062_S_PDS_CTL0, 0xff, 0xff, FLAG_A | FLAG_G, },
12398 { BWN_B2062_S_LGENG_CTL0, 0xf8, 0xd8, FLAG_A | FLAG_G, },
12399 { BWN_B2062_S_LGENG_CTL1, 0x3c, 0x24, FLAG_A | FLAG_G, },
12400 { BWN_B2062_S_LGENG_CTL8, 0x88, 0x80, FLAG_A | FLAG_G, },
12401 { BWN_B2062_S_LGENG_CTL10, 0x88, 0x80, FLAG_A | FLAG_G, },
12402 { BWN_B2062_S_RFPLLCTL0, 0x98, 0x98, FLAG_A | FLAG_G, },
12403 { BWN_B2062_S_RFPLLCTL1, 0x10, 0x10, FLAG_A | FLAG_G, },
12404 { BWN_B2062_S_RFPLLCTL5, 0x43, 0x43, FLAG_A | FLAG_G, },
12405 { BWN_B2062_S_RFPLLCTL6, 0x47, 0x47, FLAG_A | FLAG_G, },
12406 { BWN_B2062_S_RFPLLCTL7, 0xc, 0xc, FLAG_A | FLAG_G, },
12407 { BWN_B2062_S_RFPLLCTL8, 0x11, 0x11, FLAG_A | FLAG_G, },
12408 { BWN_B2062_S_RFPLLCTL9, 0x11, 0x11, FLAG_A | FLAG_G, },
12409 { BWN_B2062_S_RFPLLCTL10, 0xe, 0xe, FLAG_A | FLAG_G, },
12410 { BWN_B2062_S_RFPLLCTL11, 0x8, 0x8, FLAG_A | FLAG_G, },
12411 { BWN_B2062_S_RFPLLCTL12, 0x33, 0x33, FLAG_A | FLAG_G, },
12412 { BWN_B2062_S_RFPLLCTL13, 0xa, 0xa, FLAG_A | FLAG_G, },
12413 { BWN_B2062_S_RFPLLCTL14, 0x6, 0x6, FLAG_A | FLAG_G, },
12414 { BWN_B2062_S_RFPLLCTL18, 0x3e, 0x3e, FLAG_A | FLAG_G, },
12415 { BWN_B2062_S_RFPLLCTL19, 0x13, 0x13, FLAG_A | FLAG_G, },
12416 { BWN_B2062_S_RFPLLCTL21, 0x62, 0x62, FLAG_A | FLAG_G, },
12417 { BWN_B2062_S_RFPLLCTL22, 0x7, 0x7, FLAG_A | FLAG_G, },
12418 { BWN_B2062_S_RFPLLCTL23, 0x16, 0x16, FLAG_A | FLAG_G, },
12419 { BWN_B2062_S_RFPLLCTL24, 0x5c, 0x5c, FLAG_A | FLAG_G, },
12420 { BWN_B2062_S_RFPLLCTL25, 0x95, 0x95, FLAG_A | FLAG_G, },
12421 { BWN_B2062_S_RFPLLCTL30, 0xa0, 0xa0, FLAG_A | FLAG_G, },
12422 { BWN_B2062_S_RFPLLCTL31, 0x4, 0x4, FLAG_A | FLAG_G, },
12423 { BWN_B2062_S_RFPLLCTL33, 0xcc, 0xcc, FLAG_A | FLAG_G, },
12424 { BWN_B2062_S_RFPLLCTL34, 0x7, 0x7, FLAG_A | FLAG_G, },
12425 { BWN_B2062_S_RXG_CNT8, 0xf, 0xf, FLAG_A, },
12426 };
12427 const struct bwn_b206x_rfinit_entry *br;
12428 unsigned int i;
12429
12430 for (i = 0; i < N(bwn_b2062_init_tab); i++) {
12431 br = &bwn_b2062_init_tab[i];
12432 if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12433 if (br->br_flags & FLAG_G)
12434 BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12435 } else {
12436 if (br->br_flags & FLAG_A)
12437 BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12438 }
12439 }
12440#undef FLAG_A
12441#undef FLAG_B
12442}
12443
12444static void
12445bwn_phy_lp_b2063_tblinit(struct bwn_mac *mac)
12446{
12447#define FLAG_A 0x01
12448#define FLAG_G 0x02
12449 struct bwn_softc *sc = mac->mac_sc;
12450 struct ifnet *ifp = sc->sc_ifp;
12451 struct ieee80211com *ic = ifp->if_l2com;
12452 static const struct bwn_b206x_rfinit_entry bwn_b2063_init_tab[] = {
12453 { BWN_B2063_COM1, 0x0, 0x0, FLAG_G, },
12454 { BWN_B2063_COM10, 0x1, 0x0, FLAG_A, },
12455 { BWN_B2063_COM16, 0x0, 0x0, FLAG_G, },
12456 { BWN_B2063_COM17, 0x0, 0x0, FLAG_G, },
12457 { BWN_B2063_COM18, 0x0, 0x0, FLAG_G, },
12458 { BWN_B2063_COM19, 0x0, 0x0, FLAG_G, },
12459 { BWN_B2063_COM20, 0x0, 0x0, FLAG_G, },
12460 { BWN_B2063_COM21, 0x0, 0x0, FLAG_G, },
12461 { BWN_B2063_COM22, 0x0, 0x0, FLAG_G, },
12462 { BWN_B2063_COM23, 0x0, 0x0, FLAG_G, },
12463 { BWN_B2063_COM24, 0x0, 0x0, FLAG_G, },
12464 { BWN_B2063_LOGEN_SP1, 0xe8, 0xd4, FLAG_A | FLAG_G, },
12465 { BWN_B2063_LOGEN_SP2, 0xa7, 0x53, FLAG_A | FLAG_G, },
12466 { BWN_B2063_LOGEN_SP4, 0xf0, 0xf, FLAG_A | FLAG_G, },
12467 { BWN_B2063_G_RX_SP1, 0x1f, 0x5e, FLAG_G, },
12468 { BWN_B2063_G_RX_SP2, 0x7f, 0x7e, FLAG_G, },
12469 { BWN_B2063_G_RX_SP3, 0x30, 0xf0, FLAG_G, },
12470 { BWN_B2063_G_RX_SP7, 0x7f, 0x7f, FLAG_A | FLAG_G, },
12471 { BWN_B2063_G_RX_SP10, 0xc, 0xc, FLAG_A | FLAG_G, },
12472 { BWN_B2063_A_RX_SP1, 0x3c, 0x3f, FLAG_A, },
12473 { BWN_B2063_A_RX_SP2, 0xfc, 0xfe, FLAG_A, },
12474 { BWN_B2063_A_RX_SP7, 0x8, 0x8, FLAG_A | FLAG_G, },
12475 { BWN_B2063_RX_BB_SP4, 0x60, 0x60, FLAG_A | FLAG_G, },
12476 { BWN_B2063_RX_BB_SP8, 0x30, 0x30, FLAG_A | FLAG_G, },
12477 { BWN_B2063_TX_RF_SP3, 0xc, 0xb, FLAG_A | FLAG_G, },
12478 { BWN_B2063_TX_RF_SP4, 0x10, 0xf, FLAG_A | FLAG_G, },
12479 { BWN_B2063_PA_SP1, 0x3d, 0xfd, FLAG_A | FLAG_G, },
12480 { BWN_B2063_TX_BB_SP1, 0x2, 0x2, FLAG_A | FLAG_G, },
12481 { BWN_B2063_BANDGAP_CTL1, 0x56, 0x56, FLAG_A | FLAG_G, },
12482 { BWN_B2063_JTAG_VCO2, 0xF7, 0xF7, FLAG_A | FLAG_G, },
12483 { BWN_B2063_G_RX_MIX3, 0x71, 0x71, FLAG_A | FLAG_G, },
12484 { BWN_B2063_G_RX_MIX4, 0x71, 0x71, FLAG_A | FLAG_G, },
12485 { BWN_B2063_A_RX_1ST2, 0xf0, 0x30, FLAG_A, },
12486 { BWN_B2063_A_RX_PS6, 0x77, 0x77, FLAG_A | FLAG_G, },
12487 { BWN_B2063_A_RX_MIX4, 0x3, 0x3, FLAG_A | FLAG_G, },
12488 { BWN_B2063_A_RX_MIX5, 0xf, 0xf, FLAG_A | FLAG_G, },
12489 { BWN_B2063_A_RX_MIX6, 0xf, 0xf, FLAG_A | FLAG_G, },
12490 { BWN_B2063_RX_TIA_CTL1, 0x77, 0x77, FLAG_A | FLAG_G, },
12491 { BWN_B2063_RX_TIA_CTL3, 0x77, 0x77, FLAG_A | FLAG_G, },
12492 { BWN_B2063_RX_BB_CTL2, 0x4, 0x4, FLAG_A | FLAG_G, },
12493 { BWN_B2063_PA_CTL1, 0x0, 0x4, FLAG_A, },
12494 { BWN_B2063_VREG_CTL1, 0x3, 0x3, FLAG_A | FLAG_G, },
12495 };
12496 const struct bwn_b206x_rfinit_entry *br;
12497 unsigned int i;
12498
12499 for (i = 0; i < N(bwn_b2063_init_tab); i++) {
12500 br = &bwn_b2063_init_tab[i];
12501 if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12502 if (br->br_flags & FLAG_G)
12503 BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12504 } else {
12505 if (br->br_flags & FLAG_A)
12506 BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12507 }
12508 }
12509#undef FLAG_A
12510#undef FLAG_B
12511}
12512
12513static void
12514bwn_tab_read_multi(struct bwn_mac *mac, uint32_t typenoffset,
12515 int count, void *_data)
12516{
12517 unsigned int i;
12518 uint32_t offset, type;
12519 uint8_t *data = _data;
12520
12521 type = BWN_TAB_GETTYPE(typenoffset);
12522 offset = BWN_TAB_GETOFFSET(typenoffset);
12523 KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12524
12525 BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12526
12527 for (i = 0; i < count; i++) {
12528 switch (type) {
12529 case BWN_TAB_8BIT:
12530 *data = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
12531 data++;
12532 break;
12533 case BWN_TAB_16BIT:
12534 *((uint16_t *)data) = BWN_PHY_READ(mac,
12535 BWN_PHY_TABLEDATALO);
12536 data += 2;
12537 break;
12538 case BWN_TAB_32BIT:
12539 *((uint32_t *)data) = BWN_PHY_READ(mac,
12540 BWN_PHY_TABLEDATAHI);
12541 *((uint32_t *)data) <<= 16;
12542 *((uint32_t *)data) |= BWN_PHY_READ(mac,
12543 BWN_PHY_TABLEDATALO);
12544 data += 4;
12545 break;
12546 default:
12547 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12548 }
12549 }
12550}
12551
12552static void
12553bwn_tab_write_multi(struct bwn_mac *mac, uint32_t typenoffset,
12554 int count, const void *_data)
12555{
12556 uint32_t offset, type, value;
12557 const uint8_t *data = _data;
12558 unsigned int i;
12559
12560 type = BWN_TAB_GETTYPE(typenoffset);
12561 offset = BWN_TAB_GETOFFSET(typenoffset);
12562 KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12563
12564 BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12565
12566 for (i = 0; i < count; i++) {
12567 switch (type) {
12568 case BWN_TAB_8BIT:
12569 value = *data;
12570 data++;
12571 KASSERT(!(value & ~0xff),
12572 ("%s:%d: fail", __func__, __LINE__));
12573 BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12574 break;
12575 case BWN_TAB_16BIT:
12576 value = *((const uint16_t *)data);
12577 data += 2;
12578 KASSERT(!(value & ~0xffff),
12579 ("%s:%d: fail", __func__, __LINE__));
12580 BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12581 break;
12582 case BWN_TAB_32BIT:
12583 value = *((const uint32_t *)data);
12584 data += 4;
12585 BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
12586 BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12587 break;
12588 default:
12589 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12590 }
12591 }
12592}
12593
12594static struct bwn_txgain
12595bwn_phy_lp_get_txgain(struct bwn_mac *mac)
12596{
12597 struct bwn_txgain tg;
12598 uint16_t tmp;
12599
12600 tg.tg_dac = (BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0x380) >> 7;
12601 if (mac->mac_phy.rev < 2) {
12602 tmp = BWN_PHY_READ(mac,
12603 BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL) & 0x7ff;
12604 tg.tg_gm = tmp & 0x0007;
12605 tg.tg_pga = (tmp & 0x0078) >> 3;
12606 tg.tg_pad = (tmp & 0x780) >> 7;
12607 return (tg);
12608 }
12609
12610 tmp = BWN_PHY_READ(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL);
12611 tg.tg_pad = BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0xff;
12612 tg.tg_gm = tmp & 0xff;
12613 tg.tg_pga = (tmp >> 8) & 0xff;
12614 return (tg);
12615}
12616
12617static uint8_t
12618bwn_phy_lp_get_bbmult(struct bwn_mac *mac)
12619{
12620
12621 return (bwn_tab_read(mac, BWN_TAB_2(0, 87)) & 0xff00) >> 8;
12622}
12623
12624static void
12625bwn_phy_lp_set_txgain(struct bwn_mac *mac, struct bwn_txgain *tg)
12626{
12627 uint16_t pa;
12628
12629 if (mac->mac_phy.rev < 2) {
12630 BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0xf800,
12631 (tg->tg_pad << 7) | (tg->tg_pga << 3) | tg->tg_gm);
12632 bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12633 bwn_phy_lp_set_txgain_override(mac);
12634 return;
12635 }
12636
12637 pa = bwn_phy_lp_get_pa_gain(mac);
12638 BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
12639 (tg->tg_pga << 8) | tg->tg_gm);
12640 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0x8000,
12641 tg->tg_pad | (pa << 6));
12642 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xfc), (tg->tg_pga << 8) | tg->tg_gm);
12643 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x8000,
12644 tg->tg_pad | (pa << 8));
12645 bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12646 bwn_phy_lp_set_txgain_override(mac);
12647}
12648
12649static void
12650bwn_phy_lp_set_bbmult(struct bwn_mac *mac, uint8_t bbmult)
12651{
12652
12653 bwn_tab_write(mac, BWN_TAB_2(0, 87), (uint16_t)bbmult << 8);
12654}
12655
12656static void
12657bwn_phy_lp_set_trsw_over(struct bwn_mac *mac, uint8_t tx, uint8_t rx)
12658{
12659 uint16_t trsw = (tx << 1) | rx;
12660
12661 BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffc, trsw);
12662 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x3);
12663}
12664
12665static void
12666bwn_phy_lp_set_rxgain(struct bwn_mac *mac, uint32_t gain)
12667{
12668 struct bwn_softc *sc = mac->mac_sc;
12669 struct ifnet *ifp = sc->sc_ifp;
12670 struct ieee80211com *ic = ifp->if_l2com;
12671 uint16_t ext_lna, high_gain, lna, low_gain, trsw, tmp;
12672
12673 if (mac->mac_phy.rev < 2) {
12674 trsw = gain & 0x1;
12675 lna = (gain & 0xfffc) | ((gain & 0xc) >> 2);
12676 ext_lna = (gain & 2) >> 1;
12677
12678 BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12679 BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12680 0xfbff, ext_lna << 10);
12681 BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12682 0xf7ff, ext_lna << 11);
12683 BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, lna);
12684 } else {
12685 low_gain = gain & 0xffff;
12686 high_gain = (gain >> 16) & 0xf;
12687 ext_lna = (gain >> 21) & 0x1;
12688 trsw = ~(gain >> 20) & 0x1;
12689
12690 BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12691 BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12692 0xfdff, ext_lna << 9);
12693 BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12694 0xfbff, ext_lna << 10);
12695 BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, low_gain);
12696 BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff0, high_gain);
12697 if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12698 tmp = (gain >> 2) & 0x3;
12699 BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12700 0xe7ff, tmp<<11);
12701 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe6), 0xffe7,
12702 tmp << 3);
12703 }
12704 }
12705
12706 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1);
12707 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12708 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12709 if (mac->mac_phy.rev >= 2) {
12710 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
12711 if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12712 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x400);
12713 BWN_PHY_SET(mac, BWN_PHY_OFDM(0xe5), 0x8);
12714 }
12715 return;
12716 }
12717 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x200);
12718}
12719
12720static void
12721bwn_phy_lp_set_deaf(struct bwn_mac *mac, uint8_t user)
12722{
12723 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12724
12725 if (user)
12726 plp->plp_crsusr_off = 1;
12727 else
12728 plp->plp_crssys_off = 1;
12729
12730 BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x80);
12731}
12732
12733static void
12734bwn_phy_lp_clear_deaf(struct bwn_mac *mac, uint8_t user)
12735{
12736 struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12737 struct bwn_softc *sc = mac->mac_sc;
12738 struct ifnet *ifp = sc->sc_ifp;
12739 struct ieee80211com *ic = ifp->if_l2com;
12740
12741 if (user)
12742 plp->plp_crsusr_off = 0;
12743 else
12744 plp->plp_crssys_off = 0;
12745
12746 if (plp->plp_crsusr_off || plp->plp_crssys_off)
12747 return;
12748
12749 if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12750 BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x60);
12751 else
12752 BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x20);
12753}
12754
12755static unsigned int
12756bwn_sqrt(struct bwn_mac *mac, unsigned int x)
12757{
12758 /* Table holding (10 * sqrt(x)) for x between 1 and 256. */
12759 static uint8_t sqrt_table[256] = {
12760 10, 14, 17, 20, 22, 24, 26, 28,
12761 30, 31, 33, 34, 36, 37, 38, 40,
12762 41, 42, 43, 44, 45, 46, 47, 48,
12763 50, 50, 51, 52, 53, 54, 55, 56,
12764 57, 58, 59, 60, 60, 61, 62, 63,
12765 64, 64, 65, 66, 67, 67, 68, 69,
12766 70, 70, 71, 72, 72, 73, 74, 74,
12767 75, 76, 76, 77, 78, 78, 79, 80,
12768 80, 81, 81, 82, 83, 83, 84, 84,
12769 85, 86, 86, 87, 87, 88, 88, 89,
12770 90, 90, 91, 91, 92, 92, 93, 93,
12771 94, 94, 95, 95, 96, 96, 97, 97,
12772 98, 98, 99, 100, 100, 100, 101, 101,
12773 102, 102, 103, 103, 104, 104, 105, 105,
12774 106, 106, 107, 107, 108, 108, 109, 109,
12775 110, 110, 110, 111, 111, 112, 112, 113,
12776 113, 114, 114, 114, 115, 115, 116, 116,
12777 117, 117, 117, 118, 118, 119, 119, 120,
12778 120, 120, 121, 121, 122, 122, 122, 123,
12779 123, 124, 124, 124, 125, 125, 126, 126,
12780 126, 127, 127, 128, 128, 128, 129, 129,
12781 130, 130, 130, 131, 131, 131, 132, 132,
12782 133, 133, 133, 134, 134, 134, 135, 135,
12783 136, 136, 136, 137, 137, 137, 138, 138,
12784 138, 139, 139, 140, 140, 140, 141, 141,
12785 141, 142, 142, 142, 143, 143, 143, 144,
12786 144, 144, 145, 145, 145, 146, 146, 146,
12787 147, 147, 147, 148, 148, 148, 149, 149,
12788 150, 150, 150, 150, 151, 151, 151, 152,
12789 152, 152, 153, 153, 153, 154, 154, 154,
12790 155, 155, 155, 156, 156, 156, 157, 157,
12791 157, 158, 158, 158, 159, 159, 159, 160
12792 };
12793
12794 if (x == 0)
12795 return (0);
12796 if (x >= 256) {
12797 unsigned int tmp;
12798
12799 for (tmp = 0; x >= (2 * tmp) + 1; x -= (2 * tmp++) + 1)
12800 /* do nothing */ ;
12801 return (tmp);
12802 }
12803 return (sqrt_table[x - 1] / 10);
12804}
12805
12806static int
12807bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *mac, uint16_t sample)
12808{
12809#define CALC_COEFF(_v, _x, _y, _z) do { \
12810 int _t; \
12811 _t = _x - 20; \
12812 if (_t >= 0) { \
12813 _v = ((_y << (30 - _x)) + (_z >> (1 + _t))) / (_z >> _t); \
12814 } else { \
12815 _v = ((_y << (30 - _x)) + (_z << (-1 - _t))) / (_z << -_t); \
12816 } \
12817} while (0)
12818#define CALC_COEFF2(_v, _x, _y, _z) do { \
12819 int _t; \
12820 _t = _x - 11; \
12821 if (_t >= 0) \
12822 _v = (_y << (31 - _x)) / (_z >> _t); \
12823 else \
12824 _v = (_y << (31 - _x)) / (_z << -_t); \
12825} while (0)
12826 struct bwn_phy_lp_iq_est ie;
12827 uint16_t v0, v1;
12828 int tmp[2], ret;
12829
12830 v1 = BWN_PHY_READ(mac, BWN_PHY_RX_COMP_COEFF_S);
12831 v0 = v1 >> 8;
12832 v1 |= 0xff;
12833
12834 BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, 0x00c0);
12835 BWN_PHY_MASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff);
12836
12837 ret = bwn_phy_lp_rx_iq_est(mac, sample, 32, &ie);
12838 if (ret == 0)
12839 goto done;
12840
12841 if (ie.ie_ipwr + ie.ie_qpwr < 2) {
12842 ret = 0;
12843 goto done;
12844 }
12845
12846 CALC_COEFF(tmp[0], bwn_nbits(ie.ie_iqprod), ie.ie_iqprod, ie.ie_ipwr);
12847 CALC_COEFF2(tmp[1], bwn_nbits(ie.ie_qpwr), ie.ie_qpwr, ie.ie_ipwr);
12848
12849 tmp[1] = -bwn_sqrt(mac, tmp[1] - (tmp[0] * tmp[0]));
12850 v0 = tmp[0] >> 3;
12851 v1 = tmp[1] >> 4;
12852done:
12853 BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, v1);
12854 BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, v0 << 8);
12855 return ret;
12856#undef CALC_COEFF
12857#undef CALC_COEFF2
12858}
12859
12860static void
12861bwn_phy_lp_tblinit_r01(struct bwn_mac *mac)
12862{
12863 static const uint16_t noisescale[] = {
12864 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12865 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa400, 0xa4a4, 0xa4a4,
12866 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12867 0xa4a4, 0xa4a4, 0x00a4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12868 0x0000, 0x0000, 0x4c00, 0x2d36, 0x0000, 0x0000, 0x4c00, 0x2d36,
12869 };
12870 static const uint16_t crsgainnft[] = {
12871 0x0366, 0x036a, 0x036f, 0x0364, 0x0367, 0x036d, 0x0374, 0x037f,
12872 0x036f, 0x037b, 0x038a, 0x0378, 0x0367, 0x036d, 0x0375, 0x0381,
12873 0x0374, 0x0381, 0x0392, 0x03a9, 0x03c4, 0x03e1, 0x0001, 0x001f,
12874 0x0040, 0x005e, 0x007f, 0x009e, 0x00bd, 0x00dd, 0x00fd, 0x011d,
12875 0x013d,
12876 };
12877 static const uint16_t filterctl[] = {
12878 0xa0fc, 0x10fc, 0x10db, 0x20b7, 0xff93, 0x10bf, 0x109b, 0x2077,
12879 0xff53, 0x0127,
12880 };
12881 static const uint32_t psctl[] = {
12882 0x00010000, 0x000000a0, 0x00040000, 0x00000048, 0x08080101,
12883 0x00000080, 0x08080101, 0x00000040, 0x08080101, 0x000000c0,
12884 0x08a81501, 0x000000c0, 0x0fe8fd01, 0x000000c0, 0x08300105,
12885 0x000000c0, 0x08080201, 0x000000c0, 0x08280205, 0x000000c0,
12886 0xe80802fe, 0x000000c7, 0x28080206, 0x000000c0, 0x08080202,
12887 0x000000c0, 0x0ba87602, 0x000000c0, 0x1068013d, 0x000000c0,
12888 0x10280105, 0x000000c0, 0x08880102, 0x000000c0, 0x08280106,
12889 0x000000c0, 0xe80801fd, 0x000000c7, 0xa8080115, 0x000000c0,
12890 };
12891 static const uint16_t ofdmcckgain_r0[] = {
12892 0x0001, 0x0001, 0x0001, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12893 0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12894 0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12895 0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12896 0x755d,
12897 };
12898 static const uint16_t ofdmcckgain_r1[] = {
12899 0x5000, 0x6000, 0x7000, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12900 0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12901 0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12902 0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12903 0x755d,
12904 };
12905 static const uint16_t gaindelta[] = {
12906 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12907 0x0000,
12908 };
12909 static const uint32_t txpwrctl[] = {
12910 0x00000050, 0x0000004f, 0x0000004e, 0x0000004d, 0x0000004c,
12911 0x0000004b, 0x0000004a, 0x00000049, 0x00000048, 0x00000047,
12912 0x00000046, 0x00000045, 0x00000044, 0x00000043, 0x00000042,
12913 0x00000041, 0x00000040, 0x0000003f, 0x0000003e, 0x0000003d,
12914 0x0000003c, 0x0000003b, 0x0000003a, 0x00000039, 0x00000038,
12915 0x00000037, 0x00000036, 0x00000035, 0x00000034, 0x00000033,
12916 0x00000032, 0x00000031, 0x00000030, 0x0000002f, 0x0000002e,
12917 0x0000002d, 0x0000002c, 0x0000002b, 0x0000002a, 0x00000029,
12918 0x00000028, 0x00000027, 0x00000026, 0x00000025, 0x00000024,
12919 0x00000023, 0x00000022, 0x00000021, 0x00000020, 0x0000001f,
12920 0x0000001e, 0x0000001d, 0x0000001c, 0x0000001b, 0x0000001a,
12921 0x00000019, 0x00000018, 0x00000017, 0x00000016, 0x00000015,
12922 0x00000014, 0x00000013, 0x00000012, 0x00000011, 0x00000000,
12923 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12924 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12925 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12926 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12927 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12928 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12929 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12930 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12931 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12932 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12933 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12934 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12935 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12936 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12937 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12938 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12939 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12940 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12941 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12942 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12943 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12944 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12945 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12946 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12947 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12948 0x00000000, 0x00000000, 0x000075a0, 0x000075a0, 0x000075a1,
12949 0x000075a1, 0x000075a2, 0x000075a2, 0x000075a3, 0x000075a3,
12950 0x000074b0, 0x000074b0, 0x000074b1, 0x000074b1, 0x000074b2,
12951 0x000074b2, 0x000074b3, 0x000074b3, 0x00006d20, 0x00006d20,
12952 0x00006d21, 0x00006d21, 0x00006d22, 0x00006d22, 0x00006d23,
12953 0x00006d23, 0x00004660, 0x00004660, 0x00004661, 0x00004661,
12954 0x00004662, 0x00004662, 0x00004663, 0x00004663, 0x00003e60,
12955 0x00003e60, 0x00003e61, 0x00003e61, 0x00003e62, 0x00003e62,
12956 0x00003e63, 0x00003e63, 0x00003660, 0x00003660, 0x00003661,
12957 0x00003661, 0x00003662, 0x00003662, 0x00003663, 0x00003663,
12958 0x00002e60, 0x00002e60, 0x00002e61, 0x00002e61, 0x00002e62,
12959 0x00002e62, 0x00002e63, 0x00002e63, 0x00002660, 0x00002660,
12960 0x00002661, 0x00002661, 0x00002662, 0x00002662, 0x00002663,
12961 0x00002663, 0x000025e0, 0x000025e0, 0x000025e1, 0x000025e1,
12962 0x000025e2, 0x000025e2, 0x000025e3, 0x000025e3, 0x00001de0,
12963 0x00001de0, 0x00001de1, 0x00001de1, 0x00001de2, 0x00001de2,
12964 0x00001de3, 0x00001de3, 0x00001d60, 0x00001d60, 0x00001d61,
12965 0x00001d61, 0x00001d62, 0x00001d62, 0x00001d63, 0x00001d63,
12966 0x00001560, 0x00001560, 0x00001561, 0x00001561, 0x00001562,
12967 0x00001562, 0x00001563, 0x00001563, 0x00000d60, 0x00000d60,
12968 0x00000d61, 0x00000d61, 0x00000d62, 0x00000d62, 0x00000d63,
12969 0x00000d63, 0x00000ce0, 0x00000ce0, 0x00000ce1, 0x00000ce1,
12970 0x00000ce2, 0x00000ce2, 0x00000ce3, 0x00000ce3, 0x00000e10,
12971 0x00000e10, 0x00000e11, 0x00000e11, 0x00000e12, 0x00000e12,
12972 0x00000e13, 0x00000e13, 0x00000bf0, 0x00000bf0, 0x00000bf1,
12973 0x00000bf1, 0x00000bf2, 0x00000bf2, 0x00000bf3, 0x00000bf3,
12974 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12975 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12976 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12977 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12978 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12979 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12980 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12981 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12982 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12983 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12984 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12985 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12986 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12987 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12988 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12989 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12990 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12991 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12992 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12993 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12994 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12995 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12996 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12997 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12998 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12999 0x04000000, 0x04200000, 0x04000000, 0x000000ff, 0x000002fc,
13000 0x0000fa08, 0x00000305, 0x00000206, 0x00000304, 0x0000fb04,
13001 0x0000fcff, 0x000005fb, 0x0000fd01, 0x00000401, 0x00000006,
13002 0x0000ff03, 0x000007fc, 0x0000fc08, 0x00000203, 0x0000fffb,
13003 0x00000600, 0x0000fa01, 0x0000fc03, 0x0000fe06, 0x0000fe00,
13004 0x00000102, 0x000007fd, 0x000004fb, 0x000006ff, 0x000004fd,
13005 0x0000fdfa, 0x000007fb, 0x0000fdfa, 0x0000fa06, 0x00000500,
13006 0x0000f902, 0x000007fa, 0x0000fafa, 0x00000500, 0x000007fa,
13007 0x00000700, 0x00000305, 0x000004ff, 0x00000801, 0x00000503,
13008 0x000005f9, 0x00000404, 0x0000fb08, 0x000005fd, 0x00000501,
13009 0x00000405, 0x0000fb03, 0x000007fc, 0x00000403, 0x00000303,
13010 0x00000402, 0x0000faff, 0x0000fe05, 0x000005fd, 0x0000fe01,
13011 0x000007fa, 0x00000202, 0x00000504, 0x00000102, 0x000008fe,
13012 0x0000fa04, 0x0000fafc, 0x0000fe08, 0x000000f9, 0x000002fa,
13013 0x000003fe, 0x00000304, 0x000004f9, 0x00000100, 0x0000fd06,
13014 0x000008fc, 0x00000701, 0x00000504, 0x0000fdfe, 0x0000fdfc,
13015 0x000003fe, 0x00000704, 0x000002fc, 0x000004f9, 0x0000fdfd,
13016 0x0000fa07, 0x00000205, 0x000003fd, 0x000005fb, 0x000004f9,
13017 0x00000804, 0x0000fc06, 0x0000fcf9, 0x00000100, 0x0000fe05,
13018 0x00000408, 0x0000fb02, 0x00000304, 0x000006fe, 0x000004fa,
13019 0x00000305, 0x000008fc, 0x00000102, 0x000001fd, 0x000004fc,
13020 0x0000fe03, 0x00000701, 0x000001fb, 0x000001f9, 0x00000206,
13021 0x000006fd, 0x00000508, 0x00000700, 0x00000304, 0x000005fe,
13022 0x000005ff, 0x0000fa04, 0x00000303, 0x0000fefb, 0x000007f9,
13023 0x0000fefc, 0x000004fd, 0x000005fc, 0x0000fffd, 0x0000fc08,
13024 0x0000fbf9, 0x0000fd07, 0x000008fb, 0x0000fe02, 0x000006fb,
13025 0x00000702,
13026 };
13027
13028 KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13029
13030 bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13031 bwn_tab_sigsq_tbl);
13032 bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13033 bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(crsgainnft), crsgainnft);
13034 bwn_tab_write_multi(mac, BWN_TAB_2(8, 0), N(filterctl), filterctl);
13035 bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(psctl), psctl);
13036 bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13037 bwn_tab_pllfrac_tbl);
13038 bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13039 bwn_tabl_iqlocal_tbl);
13040 if (mac->mac_phy.rev == 0) {
13041 bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r0),
13042 ofdmcckgain_r0);
13043 bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r0),
13044 ofdmcckgain_r0);
13045 } else {
13046 bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r1),
13047 ofdmcckgain_r1);
13048 bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r1),
13049 ofdmcckgain_r1);
13050 }
13051 bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(gaindelta), gaindelta);
13052 bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(txpwrctl), txpwrctl);
13053}
13054
13055static void
13056bwn_phy_lp_tblinit_r2(struct bwn_mac *mac)
13057{
13058 struct bwn_softc *sc = mac->mac_sc;
13059 int i;
13060 static const uint16_t noisescale[] = {
13061 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13062 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13063 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13064 0x00a4, 0x00a4, 0x0000, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13065 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13066 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13067 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4
13068 };
13069 static const uint32_t filterctl[] = {
13070 0x000141fc, 0x000021fc, 0x000021b7, 0x0000416f, 0x0001ff27,
13071 0x0000217f, 0x00002137, 0x000040ef, 0x0001fea7, 0x0000024f
13072 };
13073 static const uint32_t psctl[] = {
13074 0x00e38e08, 0x00e08e38, 0x00000000, 0x00000000, 0x00000000,
13075 0x00002080, 0x00006180, 0x00003002, 0x00000040, 0x00002042,
13076 0x00180047, 0x00080043, 0x00000041, 0x000020c1, 0x00046006,
13077 0x00042002, 0x00040000, 0x00002003, 0x00180006, 0x00080002
13078 };
13079 static const uint32_t gainidx[] = {
13080 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13081 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13082 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13083 0x00000000, 0x00000000, 0x00000000, 0x10000001, 0x00000000,
13084 0x20000082, 0x00000000, 0x40000104, 0x00000000, 0x60004207,
13085 0x00000001, 0x7000838a, 0x00000001, 0xd021050d, 0x00000001,
13086 0xe041c683, 0x00000001, 0x50828805, 0x00000000, 0x80e34288,
13087 0x00000000, 0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000,
13088 0x12064711, 0x00000001, 0xb0a18612, 0x00000010, 0xe1024794,
13089 0x00000010, 0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011,
13090 0xc1848a9c, 0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21,
13091 0x00000019, 0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019,
13092 0xb36811a6, 0x00000019, 0xf3e89227, 0x00000019, 0x0408d329,
13093 0x0000001a, 0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a,
13094 0x54aa152c, 0x0000001a, 0x64ca55ad, 0x0000001a, 0x00000000,
13095 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13096 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13097 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13098 0x00000000, 0x00000000, 0x10000001, 0x00000000, 0x20000082,
13099 0x00000000, 0x40000104, 0x00000000, 0x60004207, 0x00000001,
13100 0x7000838a, 0x00000001, 0xd021050d, 0x00000001, 0xe041c683,
13101 0x00000001, 0x50828805, 0x00000000, 0x80e34288, 0x00000000,
13102 0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000, 0x12064711,
13103 0x00000001, 0xb0a18612, 0x00000010, 0xe1024794, 0x00000010,
13104 0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011, 0xc1848a9c,
13105 0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21, 0x00000019,
13106 0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019, 0xb36811a6,
13107 0x00000019, 0xf3e89227, 0x00000019, 0x0408d329, 0x0000001a,
13108 0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a, 0x54aa152c,
13109 0x0000001a, 0x64ca55ad, 0x0000001a
13110 };
13111 static const uint16_t auxgainidx[] = {
13112 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13113 0x0000, 0x0001, 0x0002, 0x0004, 0x0016, 0x0000, 0x0000, 0x0000,
13114 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002,
13115 0x0004, 0x0016
13116 };
13117 static const uint16_t swctl[] = {
13118 0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13119 0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13120 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
13121 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018,
13122 0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13123 0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13124 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
13125 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018
13126 };
13127 static const uint8_t hf[] = {
13128 0x4b, 0x36, 0x24, 0x18, 0x49, 0x34, 0x23, 0x17, 0x48,
13129 0x33, 0x23, 0x17, 0x48, 0x33, 0x23, 0x17
13130 };
13131 static const uint32_t gainval[] = {
13132 0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13133 0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13134 0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13135 0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13136 0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13137 0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13138 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13139 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13140 0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13141 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13142 0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13143 0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13144 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000009,
13145 0x000000f1, 0x00000000, 0x00000000
13146 };
13147 static const uint16_t gain[] = {
13148 0x0000, 0x0400, 0x0800, 0x0802, 0x0804, 0x0806, 0x0807, 0x0808,
13149 0x080a, 0x080b, 0x080c, 0x080e, 0x080f, 0x0810, 0x0812, 0x0813,
13150 0x0814, 0x0816, 0x0817, 0x081a, 0x081b, 0x081f, 0x0820, 0x0824,
13151 0x0830, 0x0834, 0x0837, 0x083b, 0x083f, 0x0840, 0x0844, 0x0857,
13152 0x085b, 0x085f, 0x08d7, 0x08db, 0x08df, 0x0957, 0x095b, 0x095f,
13153 0x0b57, 0x0b5b, 0x0b5f, 0x0f5f, 0x135f, 0x175f, 0x0000, 0x0000,
13154 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13155 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13156 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13157 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13158 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13159 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13160 };
13161 static const uint32_t papdeps[] = {
13162 0x00000000, 0x00013ffc, 0x0001dff3, 0x0001bff0, 0x00023fe9,
13163 0x00021fdf, 0x00028fdf, 0x00033fd2, 0x00039fcb, 0x00043fc7,
13164 0x0004efc2, 0x00055fb5, 0x0005cfb0, 0x00063fa8, 0x00068fa3,
13165 0x00071f98, 0x0007ef92, 0x00084f8b, 0x0008df82, 0x00097f77,
13166 0x0009df69, 0x000a3f62, 0x000adf57, 0x000b6f4c, 0x000bff41,
13167 0x000c9f39, 0x000cff30, 0x000dbf27, 0x000e4f1e, 0x000edf16,
13168 0x000f7f13, 0x00102f11, 0x00110f10, 0x0011df11, 0x0012ef15,
13169 0x00143f1c, 0x00158f27, 0x00172f35, 0x00193f47, 0x001baf5f,
13170 0x001e6f7e, 0x0021cfa4, 0x0025bfd2, 0x002a2008, 0x002fb047,
13171 0x00360090, 0x003d40e0, 0x0045c135, 0x004fb189, 0x005ae1d7,
13172 0x0067221d, 0x0075025a, 0x007ff291, 0x007ff2bf, 0x007ff2e3,
13173 0x007ff2ff, 0x007ff315, 0x007ff329, 0x007ff33f, 0x007ff356,
13174 0x007ff36e, 0x007ff39c, 0x007ff441, 0x007ff506
13175 };
13176 static const uint32_t papdmult[] = {
13177 0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13178 0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13179 0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13180 0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13181 0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13182 0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13183 0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13184 0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13185 0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13186 0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13187 0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13188 0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13189 0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13190 };
13191 static const uint32_t gainidx_a0[] = {
13192 0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13193 0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13194 0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13195 0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13196 0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13197 0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13198 0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13199 0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13200 0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13201 0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13202 0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13203 0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13204 0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13205 };
13206 static const uint16_t auxgainidx_a0[] = {
13207 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13208 0x0000, 0x0000, 0x0000, 0x0002, 0x0014, 0x0000, 0x0000, 0x0000,
13209 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13210 0x0002, 0x0014
13211 };
13212 static const uint32_t gainval_a0[] = {
13213 0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13214 0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13215 0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13216 0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13217 0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13218 0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13219 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13220 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13221 0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13222 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13223 0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13224 0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13225 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000f,
13226 0x000000f7, 0x00000000, 0x00000000
13227 };
13228 static const uint16_t gain_a0[] = {
13229 0x0000, 0x0002, 0x0004, 0x0006, 0x0007, 0x0008, 0x000a, 0x000b,
13230 0x000c, 0x000e, 0x000f, 0x0010, 0x0012, 0x0013, 0x0014, 0x0016,
13231 0x0017, 0x001a, 0x001b, 0x001f, 0x0020, 0x0024, 0x0030, 0x0034,
13232 0x0037, 0x003b, 0x003f, 0x0040, 0x0044, 0x0057, 0x005b, 0x005f,
13233 0x00d7, 0x00db, 0x00df, 0x0157, 0x015b, 0x015f, 0x0357, 0x035b,
13234 0x035f, 0x075f, 0x0b5f, 0x0f5f, 0x0000, 0x0000, 0x0000, 0x0000,
13235 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13236 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13237 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13238 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13239 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13240 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13241 };
13242
13243 KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13244
13245 for (i = 0; i < 704; i++)
13246 bwn_tab_write(mac, BWN_TAB_4(7, i), 0);
13247
13248 bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13249 bwn_tab_sigsq_tbl);
13250 bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13251 bwn_tab_write_multi(mac, BWN_TAB_4(11, 0), N(filterctl), filterctl);
13252 bwn_tab_write_multi(mac, BWN_TAB_4(12, 0), N(psctl), psctl);
13253 bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx), gainidx);
13254 bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx), auxgainidx);
13255 bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(swctl), swctl);
13256 bwn_tab_write_multi(mac, BWN_TAB_1(16, 0), N(hf), hf);
13257 bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval), gainval);
13258 bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain), gain);
13259 bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13260 bwn_tab_pllfrac_tbl);
13261 bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13262 bwn_tabl_iqlocal_tbl);
13263 bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(papdeps), papdeps);
13264 bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(papdmult), papdmult);
13265
13266 if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
13267 (siba_get_chiprev(sc->sc_dev) == 0)) {
13268 bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx_a0),
13269 gainidx_a0);
13270 bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx_a0),
13271 auxgainidx_a0);
13272 bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval_a0),
13273 gainval_a0);
13274 bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain_a0), gain_a0);
13275 }
13276}
13277
13278static void
13279bwn_phy_lp_tblinit_txgain(struct bwn_mac *mac)
13280{
13281 struct bwn_softc *sc = mac->mac_sc;
13282 struct ifnet *ifp = sc->sc_ifp;
13283 struct ieee80211com *ic = ifp->if_l2com;
13284 static struct bwn_txgain_entry txgain_r2[] = {
13285 { 255, 255, 203, 0, 152 }, { 255, 255, 203, 0, 147 },
13286 { 255, 255, 203, 0, 143 }, { 255, 255, 203, 0, 139 },
13287 { 255, 255, 203, 0, 135 }, { 255, 255, 203, 0, 131 },
13288 { 255, 255, 203, 0, 128 }, { 255, 255, 203, 0, 124 },
13289 { 255, 255, 203, 0, 121 }, { 255, 255, 203, 0, 117 },
13290 { 255, 255, 203, 0, 114 }, { 255, 255, 203, 0, 111 },
13291 { 255, 255, 203, 0, 107 }, { 255, 255, 203, 0, 104 },
13292 { 255, 255, 203, 0, 101 }, { 255, 255, 203, 0, 99 },
13293 { 255, 255, 203, 0, 96 }, { 255, 255, 203, 0, 93 },
13294 { 255, 255, 203, 0, 90 }, { 255, 255, 203, 0, 88 },
13295 { 255, 255, 203, 0, 85 }, { 255, 255, 203, 0, 83 },
13296 { 255, 255, 203, 0, 81 }, { 255, 255, 203, 0, 78 },
13297 { 255, 255, 203, 0, 76 }, { 255, 255, 203, 0, 74 },
13298 { 255, 255, 203, 0, 72 }, { 255, 255, 203, 0, 70 },
13299 { 255, 255, 203, 0, 68 }, { 255, 255, 203, 0, 66 },
13300 { 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13301 { 255, 255, 192, 0, 64 }, { 255, 255, 186, 0, 64 },
13302 { 255, 255, 181, 0, 64 }, { 255, 255, 176, 0, 64 },
13303 { 255, 255, 171, 0, 64 }, { 255, 255, 166, 0, 64 },
13304 { 255, 255, 161, 0, 64 }, { 255, 255, 157, 0, 64 },
13305 { 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13306 { 255, 255, 144, 0, 64 }, { 255, 255, 140, 0, 64 },
13307 { 255, 255, 136, 0, 64 }, { 255, 255, 132, 0, 64 },
13308 { 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13309 { 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13310 { 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13311 { 255, 255, 108, 0, 64 }, { 255, 255, 105, 0, 64 },
13312 { 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13313 { 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13314 { 255, 255, 91, 0, 64 }, { 255, 255, 88, 0, 64 },
13315 { 255, 255, 86, 0, 64 }, { 255, 255, 83, 0, 64 },
13316 { 255, 255, 81, 0, 64 }, { 255, 255, 79, 0, 64 },
13317 { 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13318 { 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13319 { 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13320 { 255, 255, 64, 0, 64 }, { 255, 248, 64, 0, 64 },
13321 { 255, 248, 62, 0, 64 }, { 255, 241, 62, 0, 64 },
13322 { 255, 241, 60, 0, 64 }, { 255, 234, 60, 0, 64 },
13323 { 255, 234, 59, 0, 64 }, { 255, 227, 59, 0, 64 },
13324 { 255, 227, 57, 0, 64 }, { 255, 221, 57, 0, 64 },
13325 { 255, 221, 55, 0, 64 }, { 255, 215, 55, 0, 64 },
13326 { 255, 215, 54, 0, 64 }, { 255, 208, 54, 0, 64 },
13327 { 255, 208, 52, 0, 64 }, { 255, 203, 52, 0, 64 },
13328 { 255, 203, 51, 0, 64 }, { 255, 197, 51, 0, 64 },
13329 { 255, 197, 49, 0, 64 }, { 255, 191, 49, 0, 64 },
13330 { 255, 191, 48, 0, 64 }, { 255, 186, 48, 0, 64 },
13331 { 255, 186, 47, 0, 64 }, { 255, 181, 47, 0, 64 },
13332 { 255, 181, 45, 0, 64 }, { 255, 175, 45, 0, 64 },
13333 { 255, 175, 44, 0, 64 }, { 255, 170, 44, 0, 64 },
13334 { 255, 170, 43, 0, 64 }, { 255, 166, 43, 0, 64 },
13335 { 255, 166, 42, 0, 64 }, { 255, 161, 42, 0, 64 },
13336 { 255, 161, 40, 0, 64 }, { 255, 156, 40, 0, 64 },
13337 { 255, 156, 39, 0, 64 }, { 255, 152, 39, 0, 64 },
13338 { 255, 152, 38, 0, 64 }, { 255, 148, 38, 0, 64 },
13339 { 255, 148, 37, 0, 64 }, { 255, 143, 37, 0, 64 },
13340 { 255, 143, 36, 0, 64 }, { 255, 139, 36, 0, 64 },
13341 { 255, 139, 35, 0, 64 }, { 255, 135, 35, 0, 64 },
13342 { 255, 135, 34, 0, 64 }, { 255, 132, 34, 0, 64 },
13343 { 255, 132, 33, 0, 64 }, { 255, 128, 33, 0, 64 },
13344 { 255, 128, 32, 0, 64 }, { 255, 124, 32, 0, 64 },
13345 { 255, 124, 31, 0, 64 }, { 255, 121, 31, 0, 64 },
13346 { 255, 121, 30, 0, 64 }, { 255, 117, 30, 0, 64 },
13347 { 255, 117, 29, 0, 64 }, { 255, 114, 29, 0, 64 },
13348 { 255, 114, 29, 0, 64 }, { 255, 111, 29, 0, 64 },
13349 };
13350 static struct bwn_txgain_entry txgain_2ghz_r2[] = {
13351 { 7, 99, 255, 0, 64 }, { 7, 96, 255, 0, 64 },
13352 { 7, 93, 255, 0, 64 }, { 7, 90, 255, 0, 64 },
13353 { 7, 88, 255, 0, 64 }, { 7, 85, 255, 0, 64 },
13354 { 7, 83, 255, 0, 64 }, { 7, 81, 255, 0, 64 },
13355 { 7, 78, 255, 0, 64 }, { 7, 76, 255, 0, 64 },
13356 { 7, 74, 255, 0, 64 }, { 7, 72, 255, 0, 64 },
13357 { 7, 70, 255, 0, 64 }, { 7, 68, 255, 0, 64 },
13358 { 7, 66, 255, 0, 64 }, { 7, 64, 255, 0, 64 },
13359 { 7, 64, 255, 0, 64 }, { 7, 62, 255, 0, 64 },
13360 { 7, 62, 248, 0, 64 }, { 7, 60, 248, 0, 64 },
13361 { 7, 60, 241, 0, 64 }, { 7, 59, 241, 0, 64 },
13362 { 7, 59, 234, 0, 64 }, { 7, 57, 234, 0, 64 },
13363 { 7, 57, 227, 0, 64 }, { 7, 55, 227, 0, 64 },
13364 { 7, 55, 221, 0, 64 }, { 7, 54, 221, 0, 64 },
13365 { 7, 54, 215, 0, 64 }, { 7, 52, 215, 0, 64 },
13366 { 7, 52, 208, 0, 64 }, { 7, 51, 208, 0, 64 },
13367 { 7, 51, 203, 0, 64 }, { 7, 49, 203, 0, 64 },
13368 { 7, 49, 197, 0, 64 }, { 7, 48, 197, 0, 64 },
13369 { 7, 48, 191, 0, 64 }, { 7, 47, 191, 0, 64 },
13370 { 7, 47, 186, 0, 64 }, { 7, 45, 186, 0, 64 },
13371 { 7, 45, 181, 0, 64 }, { 7, 44, 181, 0, 64 },
13372 { 7, 44, 175, 0, 64 }, { 7, 43, 175, 0, 64 },
13373 { 7, 43, 170, 0, 64 }, { 7, 42, 170, 0, 64 },
13374 { 7, 42, 166, 0, 64 }, { 7, 40, 166, 0, 64 },
13375 { 7, 40, 161, 0, 64 }, { 7, 39, 161, 0, 64 },
13376 { 7, 39, 156, 0, 64 }, { 7, 38, 156, 0, 64 },
13377 { 7, 38, 152, 0, 64 }, { 7, 37, 152, 0, 64 },
13378 { 7, 37, 148, 0, 64 }, { 7, 36, 148, 0, 64 },
13379 { 7, 36, 143, 0, 64 }, { 7, 35, 143, 0, 64 },
13380 { 7, 35, 139, 0, 64 }, { 7, 34, 139, 0, 64 },
13381 { 7, 34, 135, 0, 64 }, { 7, 33, 135, 0, 64 },
13382 { 7, 33, 132, 0, 64 }, { 7, 32, 132, 0, 64 },
13383 { 7, 32, 128, 0, 64 }, { 7, 31, 128, 0, 64 },
13384 { 7, 31, 124, 0, 64 }, { 7, 30, 124, 0, 64 },
13385 { 7, 30, 121, 0, 64 }, { 7, 29, 121, 0, 64 },
13386 { 7, 29, 117, 0, 64 }, { 7, 29, 117, 0, 64 },
13387 { 7, 29, 114, 0, 64 }, { 7, 28, 114, 0, 64 },
13388 { 7, 28, 111, 0, 64 }, { 7, 27, 111, 0, 64 },
13389 { 7, 27, 108, 0, 64 }, { 7, 26, 108, 0, 64 },
13390 { 7, 26, 104, 0, 64 }, { 7, 25, 104, 0, 64 },
13391 { 7, 25, 102, 0, 64 }, { 7, 25, 102, 0, 64 },
13392 { 7, 25, 99, 0, 64 }, { 7, 24, 99, 0, 64 },
13393 { 7, 24, 96, 0, 64 }, { 7, 23, 96, 0, 64 },
13394 { 7, 23, 93, 0, 64 }, { 7, 23, 93, 0, 64 },
13395 { 7, 23, 90, 0, 64 }, { 7, 22, 90, 0, 64 },
13396 { 7, 22, 88, 0, 64 }, { 7, 21, 88, 0, 64 },
13397 { 7, 21, 85, 0, 64 }, { 7, 21, 85, 0, 64 },
13398 { 7, 21, 83, 0, 64 }, { 7, 20, 83, 0, 64 },
13399 { 7, 20, 81, 0, 64 }, { 7, 20, 81, 0, 64 },
13400 { 7, 20, 78, 0, 64 }, { 7, 19, 78, 0, 64 },
13401 { 7, 19, 76, 0, 64 }, { 7, 19, 76, 0, 64 },
13402 { 7, 19, 74, 0, 64 }, { 7, 18, 74, 0, 64 },
13403 { 7, 18, 72, 0, 64 }, { 7, 18, 72, 0, 64 },
13404 { 7, 18, 70, 0, 64 }, { 7, 17, 70, 0, 64 },
13405 { 7, 17, 68, 0, 64 }, { 7, 17, 68, 0, 64 },
13406 { 7, 17, 66, 0, 64 }, { 7, 16, 66, 0, 64 },
13407 { 7, 16, 64, 0, 64 }, { 7, 16, 64, 0, 64 },
13408 { 7, 16, 62, 0, 64 }, { 7, 15, 62, 0, 64 },
13409 { 7, 15, 60, 0, 64 }, { 7, 15, 60, 0, 64 },
13410 { 7, 15, 59, 0, 64 }, { 7, 14, 59, 0, 64 },
13411 { 7, 14, 57, 0, 64 }, { 7, 14, 57, 0, 64 },
13412 { 7, 14, 55, 0, 64 }, { 7, 14, 55, 0, 64 },
13413 { 7, 14, 54, 0, 64 }, { 7, 13, 54, 0, 64 },
13414 { 7, 13, 52, 0, 64 }, { 7, 13, 52, 0, 64 },
13415 };
13416 static struct bwn_txgain_entry txgain_5ghz_r2[] = {
13417 { 255, 255, 255, 0, 152 }, { 255, 255, 255, 0, 147 },
13418 { 255, 255, 255, 0, 143 }, { 255, 255, 255, 0, 139 },
13419 { 255, 255, 255, 0, 135 }, { 255, 255, 255, 0, 131 },
13420 { 255, 255, 255, 0, 128 }, { 255, 255, 255, 0, 124 },
13421 { 255, 255, 255, 0, 121 }, { 255, 255, 255, 0, 117 },
13422 { 255, 255, 255, 0, 114 }, { 255, 255, 255, 0, 111 },
13423 { 255, 255, 255, 0, 107 }, { 255, 255, 255, 0, 104 },
13424 { 255, 255, 255, 0, 101 }, { 255, 255, 255, 0, 99 },
13425 { 255, 255, 255, 0, 96 }, { 255, 255, 255, 0, 93 },
13426 { 255, 255, 255, 0, 90 }, { 255, 255, 255, 0, 88 },
13427 { 255, 255, 255, 0, 85 }, { 255, 255, 255, 0, 83 },
13428 { 255, 255, 255, 0, 81 }, { 255, 255, 255, 0, 78 },
13429 { 255, 255, 255, 0, 76 }, { 255, 255, 255, 0, 74 },
13430 { 255, 255, 255, 0, 72 }, { 255, 255, 255, 0, 70 },
13431 { 255, 255, 255, 0, 68 }, { 255, 255, 255, 0, 66 },
13432 { 255, 255, 255, 0, 64 }, { 255, 255, 248, 0, 64 },
13433 { 255, 255, 241, 0, 64 }, { 255, 255, 234, 0, 64 },
13434 { 255, 255, 227, 0, 64 }, { 255, 255, 221, 0, 64 },
13435 { 255, 255, 215, 0, 64 }, { 255, 255, 208, 0, 64 },
13436 { 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13437 { 255, 255, 191, 0, 64 }, { 255, 255, 186, 0, 64 },
13438 { 255, 255, 181, 0, 64 }, { 255, 255, 175, 0, 64 },
13439 { 255, 255, 170, 0, 64 }, { 255, 255, 166, 0, 64 },
13440 { 255, 255, 161, 0, 64 }, { 255, 255, 156, 0, 64 },
13441 { 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13442 { 255, 255, 143, 0, 64 }, { 255, 255, 139, 0, 64 },
13443 { 255, 255, 135, 0, 64 }, { 255, 255, 132, 0, 64 },
13444 { 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13445 { 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13446 { 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13447 { 255, 255, 108, 0, 64 }, { 255, 255, 104, 0, 64 },
13448 { 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13449 { 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13450 { 255, 255, 90, 0, 64 }, { 255, 255, 88, 0, 64 },
13451 { 255, 255, 85, 0, 64 }, { 255, 255, 83, 0, 64 },
13452 { 255, 255, 81, 0, 64 }, { 255, 255, 78, 0, 64 },
13453 { 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13454 { 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13455 { 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13456 { 255, 255, 64, 0, 64 }, { 255, 255, 64, 0, 64 },
13457 { 255, 255, 62, 0, 64 }, { 255, 248, 62, 0, 64 },
13458 { 255, 248, 60, 0, 64 }, { 255, 241, 60, 0, 64 },
13459 { 255, 241, 59, 0, 64 }, { 255, 234, 59, 0, 64 },
13460 { 255, 234, 57, 0, 64 }, { 255, 227, 57, 0, 64 },
13461 { 255, 227, 55, 0, 64 }, { 255, 221, 55, 0, 64 },
13462 { 255, 221, 54, 0, 64 }, { 255, 215, 54, 0, 64 },
13463 { 255, 215, 52, 0, 64 }, { 255, 208, 52, 0, 64 },
13464 { 255, 208, 51, 0, 64 }, { 255, 203, 51, 0, 64 },
13465 { 255, 203, 49, 0, 64 }, { 255, 197, 49, 0, 64 },
13466 { 255, 197, 48, 0, 64 }, { 255, 191, 48, 0, 64 },
13467 { 255, 191, 47, 0, 64 }, { 255, 186, 47, 0, 64 },
13468 { 255, 186, 45, 0, 64 }, { 255, 181, 45, 0, 64 },
13469 { 255, 181, 44, 0, 64 }, { 255, 175, 44, 0, 64 },
13470 { 255, 175, 43, 0, 64 }, { 255, 170, 43, 0, 64 },
13471 { 255, 170, 42, 0, 64 }, { 255, 166, 42, 0, 64 },
13472 { 255, 166, 40, 0, 64 }, { 255, 161, 40, 0, 64 },
13473 { 255, 161, 39, 0, 64 }, { 255, 156, 39, 0, 64 },
13474 { 255, 156, 38, 0, 64 }, { 255, 152, 38, 0, 64 },
13475 { 255, 152, 37, 0, 64 }, { 255, 148, 37, 0, 64 },
13476 { 255, 148, 36, 0, 64 }, { 255, 143, 36, 0, 64 },
13477 { 255, 143, 35, 0, 64 }, { 255, 139, 35, 0, 64 },
13478 { 255, 139, 34, 0, 64 }, { 255, 135, 34, 0, 64 },
13479 { 255, 135, 33, 0, 64 }, { 255, 132, 33, 0, 64 },
13480 { 255, 132, 32, 0, 64 }, { 255, 128, 32, 0, 64 }
13481 };
13482 static struct bwn_txgain_entry txgain_r0[] = {
13483 { 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13484 { 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13485 { 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13486 { 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13487 { 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13488 { 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13489 { 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13490 { 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13491 { 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13492 { 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13493 { 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13494 { 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13495 { 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13496 { 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13497 { 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13498 { 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13499 { 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13500 { 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13501 { 7, 15, 13, 0, 70 }, { 7, 15, 13, 0, 68 },
13502 { 7, 15, 13, 0, 66 }, { 7, 15, 13, 0, 64 },
13503 { 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13504 { 7, 15, 13, 0, 59 }, { 7, 15, 13, 0, 57 },
13505 { 7, 15, 12, 0, 71 }, { 7, 15, 12, 0, 69 },
13506 { 7, 15, 12, 0, 67 }, { 7, 15, 12, 0, 65 },
13507 { 7, 15, 12, 0, 63 }, { 7, 15, 12, 0, 62 },
13508 { 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 58 },
13509 { 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 70 },
13510 { 7, 15, 11, 0, 68 }, { 7, 15, 11, 0, 66 },
13511 { 7, 15, 11, 0, 65 }, { 7, 15, 11, 0, 63 },
13512 { 7, 15, 11, 0, 61 }, { 7, 15, 11, 0, 59 },
13513 { 7, 15, 11, 0, 58 }, { 7, 15, 10, 0, 71 },
13514 { 7, 15, 10, 0, 69 }, { 7, 15, 10, 0, 67 },
13515 { 7, 15, 10, 0, 65 }, { 7, 15, 10, 0, 63 },
13516 { 7, 15, 10, 0, 61 }, { 7, 15, 10, 0, 60 },
13517 { 7, 15, 10, 0, 58 }, { 7, 15, 10, 0, 56 },
13518 { 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13519 { 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13520 { 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 60 },
13521 { 7, 15, 9, 0, 59 }, { 7, 14, 9, 0, 72 },
13522 { 7, 14, 9, 0, 70 }, { 7, 14, 9, 0, 68 },
13523 { 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 64 },
13524 { 7, 14, 9, 0, 62 }, { 7, 14, 9, 0, 60 },
13525 { 7, 14, 9, 0, 59 }, { 7, 13, 9, 0, 72 },
13526 { 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13527 { 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13528 { 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13529 { 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13530 { 7, 13, 8, 0, 72 }, { 7, 13, 8, 0, 70 },
13531 { 7, 13, 8, 0, 68 }, { 7, 13, 8, 0, 66 },
13532 { 7, 13, 8, 0, 64 }, { 7, 13, 8, 0, 62 },
13533 { 7, 13, 8, 0, 60 }, { 7, 13, 8, 0, 59 },
13534 { 7, 12, 8, 0, 72 }, { 7, 12, 8, 0, 70 },
13535 { 7, 12, 8, 0, 68 }, { 7, 12, 8, 0, 66 },
13536 { 7, 12, 8, 0, 64 }, { 7, 12, 8, 0, 62 },
13537 { 7, 12, 8, 0, 61 }, { 7, 12, 8, 0, 59 },
13538 { 7, 12, 7, 0, 73 }, { 7, 12, 7, 0, 71 },
13539 { 7, 12, 7, 0, 69 }, { 7, 12, 7, 0, 67 },
13540 { 7, 12, 7, 0, 65 }, { 7, 12, 7, 0, 63 },
13541 { 7, 12, 7, 0, 61 }, { 7, 12, 7, 0, 59 },
13542 { 7, 11, 7, 0, 72 }, { 7, 11, 7, 0, 70 },
13543 { 7, 11, 7, 0, 68 }, { 7, 11, 7, 0, 66 },
13544 { 7, 11, 7, 0, 65 }, { 7, 11, 7, 0, 63 },
13545 { 7, 11, 7, 0, 61 }, { 7, 11, 7, 0, 59 },
13546 { 7, 11, 6, 0, 73 }, { 7, 11, 6, 0, 71 }
13547 };
13548 static struct bwn_txgain_entry txgain_2ghz_r0[] = {
13549 { 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13550 { 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13551 { 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13552 { 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13553 { 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13554 { 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13555 { 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13556 { 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13557 { 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13558 { 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13559 { 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13560 { 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13561 { 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13562 { 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13563 { 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13564 { 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13565 { 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13566 { 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13567 { 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13568 { 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13569 { 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13570 { 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13571 { 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13572 { 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13573 { 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13574 { 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13575 { 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13576 { 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13577 { 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13578 { 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13579 { 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13580 { 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13581 { 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13582 { 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 },
13583 { 4, 10, 6, 0, 59 }, { 4, 10, 5, 0, 72 },
13584 { 4, 10, 5, 0, 70 }, { 4, 10, 5, 0, 68 },
13585 { 4, 10, 5, 0, 66 }, { 4, 10, 5, 0, 64 },
13586 { 4, 10, 5, 0, 62 }, { 4, 10, 5, 0, 60 },
13587 { 4, 10, 5, 0, 59 }, { 4, 9, 5, 0, 70 },
13588 { 4, 9, 5, 0, 68 }, { 4, 9, 5, 0, 66 },
13589 { 4, 9, 5, 0, 64 }, { 4, 9, 5, 0, 63 },
13590 { 4, 9, 5, 0, 61 }, { 4, 9, 5, 0, 59 },
13591 { 4, 9, 4, 0, 71 }, { 4, 9, 4, 0, 69 },
13592 { 4, 9, 4, 0, 67 }, { 4, 9, 4, 0, 65 },
13593 { 4, 9, 4, 0, 63 }, { 4, 9, 4, 0, 62 },
13594 { 4, 9, 4, 0, 60 }, { 4, 9, 4, 0, 58 },
13595 { 4, 8, 4, 0, 70 }, { 4, 8, 4, 0, 68 },
13596 { 4, 8, 4, 0, 66 }, { 4, 8, 4, 0, 65 },
13597 { 4, 8, 4, 0, 63 }, { 4, 8, 4, 0, 61 },
13598 { 4, 8, 4, 0, 59 }, { 4, 7, 4, 0, 68 },
13599 { 4, 7, 4, 0, 66 }, { 4, 7, 4, 0, 64 },
13600 { 4, 7, 4, 0, 62 }, { 4, 7, 4, 0, 61 },
13601 { 4, 7, 4, 0, 59 }, { 4, 7, 3, 0, 67 },
13602 { 4, 7, 3, 0, 65 }, { 4, 7, 3, 0, 63 },
13603 { 4, 7, 3, 0, 62 }, { 4, 7, 3, 0, 60 },
13604 { 4, 6, 3, 0, 65 }, { 4, 6, 3, 0, 63 },
13605 { 4, 6, 3, 0, 61 }, { 4, 6, 3, 0, 60 },
13606 { 4, 6, 3, 0, 58 }, { 4, 5, 3, 0, 68 },
13607 { 4, 5, 3, 0, 66 }, { 4, 5, 3, 0, 64 },
13608 { 4, 5, 3, 0, 62 }, { 4, 5, 3, 0, 60 },
13609 { 4, 5, 3, 0, 59 }, { 4, 5, 3, 0, 57 },
13610 { 4, 4, 2, 0, 83 }, { 4, 4, 2, 0, 81 },
13611 { 4, 4, 2, 0, 78 }, { 4, 4, 2, 0, 76 },
13612 { 4, 4, 2, 0, 74 }, { 4, 4, 2, 0, 72 }
13613 };
13614 static struct bwn_txgain_entry txgain_5ghz_r0[] = {
13615 { 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13616 { 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13617 { 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13618 { 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13619 { 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13620 { 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13621 { 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13622 { 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13623 { 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13624 { 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13625 { 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13626 { 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13627 { 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13628 { 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13629 { 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13630 { 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13631 { 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13632 { 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13633 { 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13634 { 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13635 { 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13636 { 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13637 { 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13638 { 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13639 { 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13640 { 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13641 { 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13642 { 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13643 { 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13644 { 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13645 { 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13646 { 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13647 { 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13648 { 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13649 { 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13650 { 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13651 { 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13652 { 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13653 { 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13654 { 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13655 { 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13656 { 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13657 { 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13658 { 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13659 { 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13660 { 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13661 { 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13662 { 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13663 { 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13664 { 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13665 { 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13666 { 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13667 { 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13668 { 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13669 { 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13670 { 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13671 { 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13672 { 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13673 { 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13674 { 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13675 { 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13676 { 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13677 { 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13678 { 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13679 };
13680 static struct bwn_txgain_entry txgain_r1[] = {
13681 { 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13682 { 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13683 { 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13684 { 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13685 { 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13686 { 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13687 { 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13688 { 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13689 { 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13690 { 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13691 { 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13692 { 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13693 { 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13694 { 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13695 { 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13696 { 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13697 { 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13698 { 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13699 { 7, 15, 13, 0, 70 }, { 7, 15, 14, 0, 68 },
13700 { 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13701 { 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13702 { 7, 15, 14, 0, 59 }, { 7, 15, 14, 0, 57 },
13703 { 7, 15, 13, 0, 72 }, { 7, 15, 13, 0, 70 },
13704 { 7, 15, 13, 0, 68 }, { 7, 15, 13, 0, 66 },
13705 { 7, 15, 13, 0, 64 }, { 7, 15, 13, 0, 62 },
13706 { 7, 15, 13, 0, 60 }, { 7, 15, 13, 0, 59 },
13707 { 7, 15, 13, 0, 57 }, { 7, 15, 12, 0, 71 },
13708 { 7, 15, 12, 0, 69 }, { 7, 15, 12, 0, 67 },
13709 { 7, 15, 12, 0, 65 }, { 7, 15, 12, 0, 63 },
13710 { 7, 15, 12, 0, 62 }, { 7, 15, 12, 0, 60 },
13711 { 7, 15, 12, 0, 58 }, { 7, 15, 12, 0, 57 },
13712 { 7, 15, 11, 0, 70 }, { 7, 15, 11, 0, 68 },
13713 { 7, 15, 11, 0, 66 }, { 7, 15, 11, 0, 65 },
13714 { 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13715 { 7, 15, 11, 0, 59 }, { 7, 15, 11, 0, 58 },
13716 { 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13717 { 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13718 { 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13719 { 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13720 { 7, 15, 10, 0, 56 }, { 7, 15, 9, 0, 70 },
13721 { 7, 15, 9, 0, 68 }, { 7, 15, 9, 0, 66 },
13722 { 7, 15, 9, 0, 64 }, { 7, 15, 9, 0, 62 },
13723 { 7, 15, 9, 0, 60 }, { 7, 15, 9, 0, 59 },
13724 { 7, 14, 9, 0, 72 }, { 7, 14, 9, 0, 70 },
13725 { 7, 14, 9, 0, 68 }, { 7, 14, 9, 0, 66 },
13726 { 7, 14, 9, 0, 64 }, { 7, 14, 9, 0, 62 },
13727 { 7, 14, 9, 0, 60 }, { 7, 14, 9, 0, 59 },
13728 { 7, 13, 9, 0, 72 }, { 7, 13, 9, 0, 70 },
13729 { 7, 13, 9, 0, 68 }, { 7, 13, 9, 0, 66 },
13730 { 7, 13, 9, 0, 64 }, { 7, 13, 9, 0, 63 },
13731 { 7, 13, 9, 0, 61 }, { 7, 13, 9, 0, 59 },
13732 { 7, 13, 9, 0, 57 }, { 7, 13, 8, 0, 72 },
13733 { 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13734 { 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13735 { 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13736 { 7, 13, 8, 0, 59 }, { 7, 12, 8, 0, 72 },
13737 { 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13738 { 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13739 { 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13740 { 7, 12, 8, 0, 59 }, { 7, 12, 7, 0, 73 },
13741 { 7, 12, 7, 0, 71 }, { 7, 12, 7, 0, 69 },
13742 { 7, 12, 7, 0, 67 }, { 7, 12, 7, 0, 65 },
13743 { 7, 12, 7, 0, 63 }, { 7, 12, 7, 0, 61 },
13744 { 7, 12, 7, 0, 59 }, { 7, 11, 7, 0, 72 },
13745 { 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13746 { 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 65 },
13747 { 7, 11, 7, 0, 63 }, { 7, 11, 7, 0, 61 },
13748 { 7, 11, 7, 0, 59 }, { 7, 11, 6, 0, 73 },
13749 { 7, 11, 6, 0, 71 }
13750 };
13751 static struct bwn_txgain_entry txgain_2ghz_r1[] = {
13752 { 4, 15, 15, 0, 90 }, { 4, 15, 15, 0, 88 },
13753 { 4, 15, 15, 0, 85 }, { 4, 15, 15, 0, 83 },
13754 { 4, 15, 15, 0, 81 }, { 4, 15, 15, 0, 78 },
13755 { 4, 15, 15, 0, 76 }, { 4, 15, 15, 0, 74 },
13756 { 4, 15, 15, 0, 72 }, { 4, 15, 15, 0, 70 },
13757 { 4, 15, 15, 0, 68 }, { 4, 15, 15, 0, 66 },
13758 { 4, 15, 15, 0, 64 }, { 4, 15, 15, 0, 62 },
13759 { 4, 15, 15, 0, 60 }, { 4, 15, 15, 0, 59 },
13760 { 4, 15, 14, 0, 72 }, { 4, 15, 14, 0, 70 },
13761 { 4, 15, 14, 0, 68 }, { 4, 15, 14, 0, 66 },
13762 { 4, 15, 14, 0, 64 }, { 4, 15, 14, 0, 62 },
13763 { 4, 15, 14, 0, 60 }, { 4, 15, 14, 0, 59 },
13764 { 4, 15, 13, 0, 72 }, { 4, 15, 13, 0, 70 },
13765 { 4, 15, 13, 0, 68 }, { 4, 15, 13, 0, 66 },
13766 { 4, 15, 13, 0, 64 }, { 4, 15, 13, 0, 62 },
13767 { 4, 15, 13, 0, 60 }, { 4, 15, 13, 0, 59 },
13768 { 4, 15, 12, 0, 72 }, { 4, 15, 12, 0, 70 },
13769 { 4, 15, 12, 0, 68 }, { 4, 15, 12, 0, 66 },
13770 { 4, 15, 12, 0, 64 }, { 4, 15, 12, 0, 62 },
13771 { 4, 15, 12, 0, 60 }, { 4, 15, 12, 0, 59 },
13772 { 4, 15, 11, 0, 72 }, { 4, 15, 11, 0, 70 },
13773 { 4, 15, 11, 0, 68 }, { 4, 15, 11, 0, 66 },
13774 { 4, 15, 11, 0, 64 }, { 4, 15, 11, 0, 62 },
13775 { 4, 15, 11, 0, 60 }, { 4, 15, 11, 0, 59 },
13776 { 4, 15, 10, 0, 72 }, { 4, 15, 10, 0, 70 },
13777 { 4, 15, 10, 0, 68 }, { 4, 15, 10, 0, 66 },
13778 { 4, 15, 10, 0, 64 }, { 4, 15, 10, 0, 62 },
13779 { 4, 15, 10, 0, 60 }, { 4, 15, 10, 0, 59 },
13780 { 4, 15, 9, 0, 72 }, { 4, 15, 9, 0, 70 },
13781 { 4, 15, 9, 0, 68 }, { 4, 15, 9, 0, 66 },
13782 { 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13783 { 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13784 { 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13785 { 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13786 { 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13787 { 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13788 { 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13789 { 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13790 { 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13791 { 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13792 { 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13793 { 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13794 { 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13795 { 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13796 { 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13797 { 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13798 { 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13799 { 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13800 { 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13801 { 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13802 { 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13803 { 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13804 { 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13805 { 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13806 { 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13807 { 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13808 { 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13809 { 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13810 { 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13811 { 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13812 { 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13813 { 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13814 { 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13815 { 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 }
13816 };
13817 static struct bwn_txgain_entry txgain_5ghz_r1[] = {
13818 { 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13819 { 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13820 { 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13821 { 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13822 { 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13823 { 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13824 { 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13825 { 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13826 { 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13827 { 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13828 { 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13829 { 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13830 { 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13831 { 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13832 { 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13833 { 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13834 { 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13835 { 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13836 { 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13837 { 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13838 { 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13839 { 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13840 { 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13841 { 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13842 { 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13843 { 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13844 { 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13845 { 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13846 { 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13847 { 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13848 { 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13849 { 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13850 { 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13851 { 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13852 { 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13853 { 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13854 { 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13855 { 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13856 { 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13857 { 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13858 { 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13859 { 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13860 { 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13861 { 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13862 { 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13863 { 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13864 { 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13865 { 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13866 { 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13867 { 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13868 { 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13869 { 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13870 { 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13871 { 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13872 { 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13873 { 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13874 { 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13875 { 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13876 { 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13877 { 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13878 { 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13879 { 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13880 { 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13881 { 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13882 };
13883
13884 if (mac->mac_phy.rev != 0 && mac->mac_phy.rev != 1) {
13885 if (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA)
13886 bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r2);
13887 else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13888 bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13889 txgain_2ghz_r2);
13890 else
13891 bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13892 txgain_5ghz_r2);
13893 return;
13894 }
13895
13896 if (mac->mac_phy.rev == 0) {
13897 if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA) ||
13898 (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_HGPA))
13899 bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r0);
13900 else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13901 bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13902 txgain_2ghz_r0);
13903 else
13904 bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13905 txgain_5ghz_r0);
13906 return;
13907 }
13908
13909 if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA) ||
13910 (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_HGPA))
13911 bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r1);
13912 else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13913 bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_2ghz_r1);
13914 else
13915 bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_5ghz_r1);
13916}
13917
13918static void
13919bwn_tab_write(struct bwn_mac *mac, uint32_t typeoffset, uint32_t value)
13920{
13921 uint32_t offset, type;
13922
13923 type = BWN_TAB_GETTYPE(typeoffset);
13924 offset = BWN_TAB_GETOFFSET(typeoffset);
13925 KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
13926
13927 switch (type) {
13928 case BWN_TAB_8BIT:
13929 KASSERT(!(value & ~0xff), ("%s:%d: fail", __func__, __LINE__));
13930 BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13931 BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13932 break;
13933 case BWN_TAB_16BIT:
13934 KASSERT(!(value & ~0xffff),
13935 ("%s:%d: fail", __func__, __LINE__));
13936 BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13937 BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13938 break;
13939 case BWN_TAB_32BIT:
13940 BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13941 BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
13942 BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13943 break;
13944 default:
13945 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
13946 }
13947}
13948
13949static int
13950bwn_phy_lp_loopback(struct bwn_mac *mac)
13951{
13952 struct bwn_phy_lp_iq_est ie;
13953 int i, index = -1;
13954 uint32_t tmp;
13955
13956 memset(&ie, 0, sizeof(ie));
13957
13958 bwn_phy_lp_set_trsw_over(mac, 1, 1);
13959 BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 1);
13960 BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
13961 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
13962 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
13963 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
13964 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x8);
13965 BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, 0x80);
13966 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x80);
13967 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x80);
13968 for (i = 0; i < 32; i++) {
13969 bwn_phy_lp_set_rxgain_idx(mac, i);
13970 bwn_phy_lp_ddfs_turnon(mac, 1, 1, 5, 5, 0);
13971 if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
13972 continue;
13973 tmp = (ie.ie_ipwr + ie.ie_qpwr) / 1000;
13974 if ((tmp > 4000) && (tmp < 10000)) {
13975 index = i;
13976 break;
13977 }
13978 }
13979 bwn_phy_lp_ddfs_turnoff(mac);
13980 return (index);
13981}
13982
13983static void
13984bwn_phy_lp_set_rxgain_idx(struct bwn_mac *mac, uint16_t idx)
13985{
13986
13987 bwn_phy_lp_set_rxgain(mac, bwn_tab_read(mac, BWN_TAB_2(12, idx)));
13988}
13989
13990static void
13991bwn_phy_lp_ddfs_turnon(struct bwn_mac *mac, int i_on, int q_on,
13992 int incr1, int incr2, int scale_idx)
13993{
13994
13995 bwn_phy_lp_ddfs_turnoff(mac);
13996 BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0xff80);
13997 BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0x80ff);
13998 BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0xff80, incr1);
13999 BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0x80ff, incr2 << 8);
14000 BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff7, i_on << 3);
14001 BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xffef, q_on << 4);
14002 BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xff9f, scale_idx << 5);
14003 BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffb);
14004 BWN_PHY_SET(mac, BWN_PHY_AFE_DDFS, 0x2);
14005 BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x20);
14006}
14007
14008static uint8_t
14009bwn_phy_lp_rx_iq_est(struct bwn_mac *mac, uint16_t sample, uint8_t time,
14010 struct bwn_phy_lp_iq_est *ie)
14011{
14012 int i;
14013
14014 BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfff7);
14015 BWN_PHY_WRITE(mac, BWN_PHY_IQ_NUM_SMPLS_ADDR, sample);
14016 BWN_PHY_SETMASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xff00, time);
14017 BWN_PHY_MASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xfeff);
14018 BWN_PHY_SET(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0x200);
14019
14020 for (i = 0; i < 500; i++) {
14021 if (!(BWN_PHY_READ(mac,
14022 BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200))
14023 break;
14024 DELAY(1000);
14025 }
14026 if ((BWN_PHY_READ(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200)) {
14027 BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
14028 return 0;
14029 }
14030
14031 ie->ie_iqprod = BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_HI_ADDR);
14032 ie->ie_iqprod <<= 16;
14033 ie->ie_iqprod |= BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_LO_ADDR);
14034 ie->ie_ipwr = BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_HI_ADDR);
14035 ie->ie_ipwr <<= 16;
14036 ie->ie_ipwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_LO_ADDR);
14037 ie->ie_qpwr = BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_HI_ADDR);
14038 ie->ie_qpwr <<= 16;
14039 ie->ie_qpwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_LO_ADDR);
14040
14041 BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
14042 return 1;
14043}
14044
14045static uint32_t
14046bwn_tab_read(struct bwn_mac *mac, uint32_t typeoffset)
14047{
14048 uint32_t offset, type, value;
14049
14050 type = BWN_TAB_GETTYPE(typeoffset);
14051 offset = BWN_TAB_GETOFFSET(typeoffset);
14052 KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
14053
14054 switch (type) {
14055 case BWN_TAB_8BIT:
14056 BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14057 value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
14058 break;
14059 case BWN_TAB_16BIT:
14060 BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14061 value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
14062 break;
14063 case BWN_TAB_32BIT:
14064 BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14065 value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATAHI);
14066 value <<= 16;
14067 value |= BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
14068 break;
14069 default:
14070 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
14071 value = 0;
14072 }
14073
14074 return (value);
14075}
14076
14077static void
14078bwn_phy_lp_ddfs_turnoff(struct bwn_mac *mac)
14079{
14080
14081 BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffd);
14082 BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0xffdf);
14083}
14084
14085static void
14086bwn_phy_lp_set_txgain_dac(struct bwn_mac *mac, uint16_t dac)
14087{
14088 uint16_t ctl;
14089
14090 ctl = BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0xc7f;
14091 ctl |= dac << 7;
14092 BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf000, ctl);
14093}
14094
14095static void
14096bwn_phy_lp_set_txgain_pa(struct bwn_mac *mac, uint16_t gain)
14097{
14098
14099 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0xe03f, gain << 6);
14100 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x80ff, gain << 8);
14101}
14102
14103static void
14104bwn_phy_lp_set_txgain_override(struct bwn_mac *mac)
14105{
14106
14107 if (mac->mac_phy.rev < 2)
14108 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
14109 else {
14110 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x80);
14111 BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x4000);
14112 }
14113 BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x40);
14114}
14115
14116static uint16_t
14117bwn_phy_lp_get_pa_gain(struct bwn_mac *mac)
14118{
14119
14120 return BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0x7f;
14121}
14122
14123static uint8_t
14124bwn_nbits(int32_t val)
14125{
14126 uint32_t tmp;
14127 uint8_t nbits = 0;
14128
14129 for (tmp = abs(val); tmp != 0; tmp >>= 1)
14130 nbits++;
14131 return (nbits);
14132}
14133
14134static void
14135bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *mac, int offset, int count,
14136 struct bwn_txgain_entry *table)
14137{
14138 int i;
14139
14140 for (i = offset; i < count; i++)
14141 bwn_phy_lp_gaintbl_write(mac, i, table[i]);
14142}
14143
14144static void
14145bwn_phy_lp_gaintbl_write(struct bwn_mac *mac, int offset,
14146 struct bwn_txgain_entry data)
14147{
14148
14149 if (mac->mac_phy.rev >= 2)
14150 bwn_phy_lp_gaintbl_write_r2(mac, offset, data);
14151 else
14152 bwn_phy_lp_gaintbl_write_r01(mac, offset, data);
14153}
14154
14155static void
14156bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *mac, int offset,
14157 struct bwn_txgain_entry te)
14158{
14159 struct bwn_softc *sc = mac->mac_sc;
14160 struct ifnet *ifp = sc->sc_ifp;
14161 struct ieee80211com *ic = ifp->if_l2com;
14162 uint32_t tmp;
14163
14164 KASSERT(mac->mac_phy.rev >= 2, ("%s:%d: fail", __func__, __LINE__));
14165
14166 tmp = (te.te_pad << 16) | (te.te_pga << 8) | te.te_gm;
14167 if (mac->mac_phy.rev >= 3) {
14168 tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14169 (0x10 << 24) : (0x70 << 24));
14170 } else {
14171 tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14172 (0x14 << 24) : (0x7f << 24));
14173 }
14174 bwn_tab_write(mac, BWN_TAB_4(7, 0xc0 + offset), tmp);
14175 bwn_tab_write(mac, BWN_TAB_4(7, 0x140 + offset),
14176 te.te_bbmult << 20 | te.te_dac << 28);
14177}
14178
14179static void
14180bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *mac, int offset,
14181 struct bwn_txgain_entry te)
14182{
14183
14184 KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
14185
14186 bwn_tab_write(mac, BWN_TAB_4(10, 0xc0 + offset),
14187 (te.te_pad << 11) | (te.te_pga << 7) | (te.te_gm << 4) |
14188 te.te_dac);
14189 bwn_tab_write(mac, BWN_TAB_4(10, 0x140 + offset), te.te_bbmult << 20);
14190}
14191
14192static void
14193bwn_sysctl_node(struct bwn_softc *sc)
14194{
14195 device_t dev = sc->sc_dev;
14196 struct bwn_mac *mac;
14197 struct bwn_stats *stats;
14198
14199 /* XXX assume that count of MAC is only 1. */
14200
14201 if ((mac = sc->sc_curmac) == NULL)
14202 return;
14203 stats = &mac->mac_stats;
14204
14205 SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
14206 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14207 "linknoise", CTLFLAG_RW, &stats->rts, 0, "Noise level");
14208 SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
14209 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14210 "rts", CTLFLAG_RW, &stats->rts, 0, "RTS");
14211 SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
14212 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14213 "rtsfail", CTLFLAG_RW, &stats->rtsfail, 0, "RTS failed to send");
14214
14215#ifdef BWN_DEBUG
14216 SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14217 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14218 "debug", CTLFLAG_RW, &sc->sc_debug, 0, "Debug flags");
14219#endif
14220}
14221
14222static device_method_t bwn_methods[] = {
14223 /* Device interface */
14224 DEVMETHOD(device_probe, bwn_probe),
14225 DEVMETHOD(device_attach, bwn_attach),
14226 DEVMETHOD(device_detach, bwn_detach),
14227 DEVMETHOD(device_suspend, bwn_suspend),
14228 DEVMETHOD(device_resume, bwn_resume),
14229 KOBJMETHOD_END
14230};
14231static driver_t bwn_driver = {
14232 "bwn",
14233 bwn_methods,
14234 sizeof(struct bwn_softc)
14235};
14236static devclass_t bwn_devclass;
14237DRIVER_MODULE(bwn, siba_bwn, bwn_driver, bwn_devclass, 0, 0);
14238MODULE_DEPEND(bwn, siba_bwn, 1, 1, 1);
14239MODULE_DEPEND(bwn, wlan, 1, 1, 1); /* 802.11 media layer */
14240MODULE_DEPEND(bwn, firmware, 1, 1, 1); /* firmware support */
14241MODULE_DEPEND(bwn, wlan_amrr, 1, 1, 1);