if_bwn.c revision 204983
1203945Sweongyo/*-
2203945Sweongyo * Copyright (c) 2009-2010 Weongyo Jeong <weongyo@freebsd.org>
3203945Sweongyo * All rights reserved.
4203945Sweongyo *
5203945Sweongyo * Redistribution and use in source and binary forms, with or without
6203945Sweongyo * modification, are permitted provided that the following conditions
7203945Sweongyo * are met:
8203945Sweongyo * 1. Redistributions of source code must retain the above copyright
9203945Sweongyo *    notice, this list of conditions and the following disclaimer,
10203945Sweongyo *    without modification.
11203945Sweongyo * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12203945Sweongyo *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13203945Sweongyo *    redistribution must be conditioned upon including a substantially
14203945Sweongyo *    similar Disclaimer requirement for further binary redistribution.
15203945Sweongyo *
16203945Sweongyo * NO WARRANTY
17203945Sweongyo * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18203945Sweongyo * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19203945Sweongyo * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
20203945Sweongyo * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21203945Sweongyo * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
22203945Sweongyo * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23203945Sweongyo * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24203945Sweongyo * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25203945Sweongyo * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26203945Sweongyo * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27203945Sweongyo * THE POSSIBILITY OF SUCH DAMAGES.
28203945Sweongyo */
29203945Sweongyo
30203945Sweongyo#include <sys/cdefs.h>
31203945Sweongyo__FBSDID("$FreeBSD: head/sys/dev/bwn/if_bwn.c 204983 2010-03-10 21:45:40Z yongari $");
32203945Sweongyo
33203945Sweongyo/*
34203945Sweongyo * The Broadcom Wireless LAN controller driver.
35203945Sweongyo */
36203945Sweongyo
37203945Sweongyo#include <sys/param.h>
38203945Sweongyo#include <sys/systm.h>
39203945Sweongyo#include <sys/module.h>
40203945Sweongyo#include <sys/kernel.h>
41203945Sweongyo#include <sys/endian.h>
42203945Sweongyo#include <sys/errno.h>
43203945Sweongyo#include <sys/firmware.h>
44203945Sweongyo#include <sys/lock.h>
45203945Sweongyo#include <sys/mutex.h>
46203945Sweongyo#include <machine/bus.h>
47203945Sweongyo#include <machine/resource.h>
48203945Sweongyo#include <sys/bus.h>
49203945Sweongyo#include <sys/rman.h>
50203945Sweongyo#include <sys/socket.h>
51203945Sweongyo#include <sys/sockio.h>
52203945Sweongyo
53203945Sweongyo#include <net/ethernet.h>
54203945Sweongyo#include <net/if.h>
55203945Sweongyo#include <net/if_arp.h>
56203945Sweongyo#include <net/if_dl.h>
57203945Sweongyo#include <net/if_llc.h>
58203945Sweongyo#include <net/if_media.h>
59203945Sweongyo#include <net/if_types.h>
60203945Sweongyo
61203945Sweongyo#include <dev/pci/pcivar.h>
62203945Sweongyo#include <dev/pci/pcireg.h>
63203945Sweongyo#include <dev/siba/siba_ids.h>
64203945Sweongyo#include <dev/siba/sibareg.h>
65203945Sweongyo#include <dev/siba/sibavar.h>
66203945Sweongyo
67203945Sweongyo#include <net80211/ieee80211_var.h>
68203945Sweongyo#include <net80211/ieee80211_radiotap.h>
69203945Sweongyo#include <net80211/ieee80211_regdomain.h>
70203945Sweongyo#include <net80211/ieee80211_amrr.h>
71203945Sweongyo#include <net80211/ieee80211_phy.h>
72203945Sweongyo
73203945Sweongyo#include <dev/bwn/if_bwnreg.h>
74203945Sweongyo#include <dev/bwn/if_bwnvar.h>
75203945Sweongyo
76203945SweongyoSYSCTL_NODE(_hw, OID_AUTO, bwn, CTLFLAG_RD, 0, "Broadcom driver parameters");
77203945Sweongyo
78203945Sweongyo/*
79203945Sweongyo * Tunable & sysctl variables.
80203945Sweongyo */
81203945Sweongyo
82203945Sweongyo#ifdef BWN_DEBUG
83203945Sweongyostatic	int bwn_debug = 0;
84203945SweongyoSYSCTL_INT(_hw_bwn, OID_AUTO, debug, CTLFLAG_RW, &bwn_debug, 0,
85203945Sweongyo    "Broadcom debugging printfs");
86203945SweongyoTUNABLE_INT("hw.bwn.debug", &bwn_debug);
87203945Sweongyoenum {
88203945Sweongyo	BWN_DEBUG_XMIT		= 0x00000001,	/* basic xmit operation */
89203945Sweongyo	BWN_DEBUG_RECV		= 0x00000002,	/* basic recv operation */
90203945Sweongyo	BWN_DEBUG_STATE		= 0x00000004,	/* 802.11 state transitions */
91203945Sweongyo	BWN_DEBUG_TXPOW		= 0x00000008,	/* tx power processing */
92203945Sweongyo	BWN_DEBUG_RESET		= 0x00000010,	/* reset processing */
93203945Sweongyo	BWN_DEBUG_OPS		= 0x00000020,	/* bwn_ops processing */
94203945Sweongyo	BWN_DEBUG_BEACON	= 0x00000040,	/* beacon handling */
95203945Sweongyo	BWN_DEBUG_WATCHDOG	= 0x00000080,	/* watchdog timeout */
96203945Sweongyo	BWN_DEBUG_INTR		= 0x00000100,	/* ISR */
97203945Sweongyo	BWN_DEBUG_CALIBRATE	= 0x00000200,	/* periodic calibration */
98203945Sweongyo	BWN_DEBUG_NODE		= 0x00000400,	/* node management */
99203945Sweongyo	BWN_DEBUG_LED		= 0x00000800,	/* led management */
100203945Sweongyo	BWN_DEBUG_CMD		= 0x00001000,	/* cmd submission */
101203945Sweongyo	BWN_DEBUG_LO		= 0x00002000,	/* LO */
102203945Sweongyo	BWN_DEBUG_FW		= 0x00004000,	/* firmware */
103203945Sweongyo	BWN_DEBUG_WME		= 0x00008000,	/* WME */
104203945Sweongyo	BWN_DEBUG_RF		= 0x00010000,	/* RF */
105203945Sweongyo	BWN_DEBUG_FATAL		= 0x80000000,	/* fatal errors */
106203945Sweongyo	BWN_DEBUG_ANY		= 0xffffffff
107203945Sweongyo};
108203945Sweongyo#define	DPRINTF(sc, m, fmt, ...) do {			\
109203945Sweongyo	if (sc->sc_debug & (m))				\
110203945Sweongyo		printf(fmt, __VA_ARGS__);		\
111203945Sweongyo} while (0)
112203945Sweongyo#else
113203945Sweongyo#define	DPRINTF(sc, m, fmt, ...) do { (void) sc; } while (0)
114203945Sweongyo#endif
115203945Sweongyo
116203945Sweongyostatic int	bwn_bfp = 0;		/* use "Bad Frames Preemption" */
117203945SweongyoSYSCTL_INT(_hw_bwn, OID_AUTO, bfp, CTLFLAG_RW, &bwn_bfp, 0,
118203945Sweongyo    "uses Bad Frames Preemption");
119203945Sweongyostatic int	bwn_bluetooth = 1;
120203945SweongyoSYSCTL_INT(_hw_bwn, OID_AUTO, bluetooth, CTLFLAG_RW, &bwn_bluetooth, 0,
121203945Sweongyo    "turns on Bluetooth Coexistence");
122203945Sweongyostatic int	bwn_hwpctl = 0;
123203945SweongyoSYSCTL_INT(_hw_bwn, OID_AUTO, hwpctl, CTLFLAG_RW, &bwn_hwpctl, 0,
124203945Sweongyo    "uses H/W power control");
125203945Sweongyostatic int	bwn_msi_disable = 0;		/* MSI disabled  */
126203945SweongyoTUNABLE_INT("hw.bwn.msi_disable", &bwn_msi_disable);
127203945Sweongyostatic int	bwn_usedma = 1;
128203945SweongyoSYSCTL_INT(_hw_bwn, OID_AUTO, usedma, CTLFLAG_RD, &bwn_usedma, 0,
129203945Sweongyo    "uses DMA");
130203945SweongyoTUNABLE_INT("hw.bwn.usedma", &bwn_usedma);
131203945Sweongyostatic int	bwn_wme = 1;
132203945SweongyoSYSCTL_INT(_hw_bwn, OID_AUTO, wme, CTLFLAG_RW, &bwn_wme, 0,
133203945Sweongyo    "uses WME support");
134203945Sweongyo
135203945Sweongyostatic int	bwn_attach_pre(struct bwn_softc *);
136203945Sweongyostatic int	bwn_attach_post(struct bwn_softc *);
137204922Sweongyostatic void	bwn_sprom_bugfixes(device_t);
138203945Sweongyostatic void	bwn_init(void *);
139203945Sweongyostatic int	bwn_init_locked(struct bwn_softc *);
140203945Sweongyostatic int	bwn_ioctl(struct ifnet *, u_long, caddr_t);
141203945Sweongyostatic void	bwn_start(struct ifnet *);
142203945Sweongyostatic int	bwn_attach_core(struct bwn_mac *);
143203945Sweongyostatic void	bwn_reset_core(struct bwn_mac *, uint32_t);
144203945Sweongyostatic int	bwn_phy_getinfo(struct bwn_mac *, int);
145203945Sweongyostatic int	bwn_chiptest(struct bwn_mac *);
146203945Sweongyostatic int	bwn_setup_channels(struct bwn_mac *, int, int);
147203945Sweongyostatic int	bwn_phy_g_attach(struct bwn_mac *);
148203945Sweongyostatic void	bwn_phy_g_detach(struct bwn_mac *);
149203945Sweongyostatic void	bwn_phy_g_init_pre(struct bwn_mac *);
150203945Sweongyostatic int	bwn_phy_g_prepare_hw(struct bwn_mac *);
151203945Sweongyostatic int	bwn_phy_g_init(struct bwn_mac *);
152203945Sweongyostatic void	bwn_phy_g_exit(struct bwn_mac *);
153203945Sweongyostatic uint16_t	bwn_phy_g_read(struct bwn_mac *, uint16_t);
154203945Sweongyostatic void	bwn_phy_g_write(struct bwn_mac *, uint16_t,
155203945Sweongyo		    uint16_t);
156203945Sweongyostatic uint16_t	bwn_phy_g_rf_read(struct bwn_mac *, uint16_t);
157203945Sweongyostatic void	bwn_phy_g_rf_write(struct bwn_mac *, uint16_t,
158203945Sweongyo		    uint16_t);
159203945Sweongyostatic int	bwn_phy_g_hwpctl(struct bwn_mac *);
160203945Sweongyostatic void	bwn_phy_g_rf_onoff(struct bwn_mac *, int);
161203945Sweongyostatic int	bwn_phy_g_switch_channel(struct bwn_mac *, uint32_t);
162203945Sweongyostatic uint32_t	bwn_phy_g_get_default_chan(struct bwn_mac *);
163203945Sweongyostatic void	bwn_phy_g_set_antenna(struct bwn_mac *, int);
164203945Sweongyostatic int	bwn_phy_g_im(struct bwn_mac *, int);
165203945Sweongyostatic int	bwn_phy_g_recalc_txpwr(struct bwn_mac *, int);
166203945Sweongyostatic void	bwn_phy_g_set_txpwr(struct bwn_mac *);
167203945Sweongyostatic void	bwn_phy_g_task_15s(struct bwn_mac *);
168203945Sweongyostatic void	bwn_phy_g_task_60s(struct bwn_mac *);
169203945Sweongyostatic uint16_t	bwn_phy_g_txctl(struct bwn_mac *);
170203945Sweongyostatic void	bwn_phy_switch_analog(struct bwn_mac *, int);
171203945Sweongyostatic uint16_t	bwn_shm_read_2(struct bwn_mac *, uint16_t, uint16_t);
172203945Sweongyostatic void	bwn_shm_write_2(struct bwn_mac *, uint16_t, uint16_t,
173203945Sweongyo		    uint16_t);
174203945Sweongyostatic uint32_t	bwn_shm_read_4(struct bwn_mac *, uint16_t, uint16_t);
175203945Sweongyostatic void	bwn_shm_write_4(struct bwn_mac *, uint16_t, uint16_t,
176203945Sweongyo		    uint32_t);
177203945Sweongyostatic void	bwn_shm_ctlword(struct bwn_mac *, uint16_t,
178203945Sweongyo		    uint16_t);
179203945Sweongyostatic void	bwn_addchannels(struct ieee80211_channel [], int, int *,
180203945Sweongyo		    const struct bwn_channelinfo *, int);
181203945Sweongyostatic int	bwn_raw_xmit(struct ieee80211_node *, struct mbuf *,
182203945Sweongyo		    const struct ieee80211_bpf_params *);
183203945Sweongyostatic void	bwn_newassoc(struct ieee80211_node *, int);
184203945Sweongyostatic void	bwn_updateslot(struct ifnet *);
185203945Sweongyostatic void	bwn_update_promisc(struct ifnet *);
186203945Sweongyostatic void	bwn_wme_init(struct bwn_mac *);
187203945Sweongyostatic int	bwn_wme_update(struct ieee80211com *);
188203945Sweongyostatic struct ieee80211_node *bwn_node_alloc(struct ieee80211vap *,
189203945Sweongyo		    const uint8_t [IEEE80211_ADDR_LEN]);
190203945Sweongyostatic void	bwn_wme_clear(struct bwn_softc *);
191203945Sweongyostatic void	bwn_wme_load(struct bwn_mac *);
192203945Sweongyostatic void	bwn_wme_loadparams(struct bwn_mac *,
193203945Sweongyo		    const struct wmeParams *, uint16_t);
194203945Sweongyostatic void	bwn_node_cleanup(struct ieee80211_node *);
195203945Sweongyostatic void	bwn_scan_start(struct ieee80211com *);
196203945Sweongyostatic void	bwn_scan_end(struct ieee80211com *);
197203945Sweongyostatic void	bwn_set_channel(struct ieee80211com *);
198203945Sweongyostatic struct ieee80211vap *bwn_vap_create(struct ieee80211com *,
199203945Sweongyo		    const char [IFNAMSIZ], int, int,
200203945Sweongyo		    int, const uint8_t [IEEE80211_ADDR_LEN],
201203945Sweongyo		    const uint8_t [IEEE80211_ADDR_LEN]);
202203945Sweongyostatic void	bwn_vap_delete(struct ieee80211vap *);
203203945Sweongyostatic void	bwn_stop(struct bwn_softc *, int);
204203945Sweongyostatic void	bwn_stop_locked(struct bwn_softc *, int);
205203945Sweongyostatic int	bwn_core_init(struct bwn_mac *);
206203945Sweongyostatic void	bwn_core_start(struct bwn_mac *);
207203945Sweongyostatic void	bwn_core_exit(struct bwn_mac *);
208203945Sweongyostatic void	bwn_bt_disable(struct bwn_mac *);
209203945Sweongyostatic int	bwn_chip_init(struct bwn_mac *);
210203945Sweongyostatic uint64_t	bwn_hf_read(struct bwn_mac *);
211203945Sweongyostatic void	bwn_hf_write(struct bwn_mac *, uint64_t);
212203945Sweongyostatic void	bwn_set_txretry(struct bwn_mac *, int, int);
213203945Sweongyostatic void	bwn_rate_init(struct bwn_mac *);
214203945Sweongyostatic void	bwn_set_phytxctl(struct bwn_mac *);
215203945Sweongyostatic void	bwn_spu_setdelay(struct bwn_mac *, int);
216203945Sweongyostatic void	bwn_bt_enable(struct bwn_mac *);
217203945Sweongyostatic void	bwn_set_macaddr(struct bwn_mac *);
218203945Sweongyostatic void	bwn_crypt_init(struct bwn_mac *);
219203945Sweongyostatic void	bwn_chip_exit(struct bwn_mac *);
220203945Sweongyostatic int	bwn_fw_fillinfo(struct bwn_mac *);
221203945Sweongyostatic int	bwn_fw_loaducode(struct bwn_mac *);
222203945Sweongyostatic int	bwn_gpio_init(struct bwn_mac *);
223203945Sweongyostatic int	bwn_fw_loadinitvals(struct bwn_mac *);
224203945Sweongyostatic int	bwn_phy_init(struct bwn_mac *);
225203945Sweongyostatic void	bwn_set_txantenna(struct bwn_mac *, int);
226203945Sweongyostatic void	bwn_set_opmode(struct bwn_mac *);
227203945Sweongyostatic void	bwn_rate_write(struct bwn_mac *, uint16_t, int);
228203945Sweongyostatic uint8_t	bwn_plcp_getcck(const uint8_t);
229203945Sweongyostatic uint8_t	bwn_plcp_getofdm(const uint8_t);
230203945Sweongyostatic void	bwn_pio_init(struct bwn_mac *);
231203945Sweongyostatic uint16_t	bwn_pio_idx2base(struct bwn_mac *, int);
232203945Sweongyostatic void	bwn_pio_set_txqueue(struct bwn_mac *, struct bwn_pio_txqueue *,
233203945Sweongyo		    int);
234203945Sweongyostatic void	bwn_pio_setupqueue_rx(struct bwn_mac *,
235203945Sweongyo		    struct bwn_pio_rxqueue *, int);
236203945Sweongyostatic void	bwn_destroy_queue_tx(struct bwn_pio_txqueue *);
237203945Sweongyostatic uint16_t	bwn_pio_read_2(struct bwn_mac *, struct bwn_pio_txqueue *,
238203945Sweongyo		    uint16_t);
239203945Sweongyostatic void	bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *);
240203945Sweongyostatic int	bwn_pio_rx(struct bwn_pio_rxqueue *);
241203945Sweongyostatic uint8_t	bwn_pio_rxeof(struct bwn_pio_rxqueue *);
242203945Sweongyostatic void	bwn_pio_handle_txeof(struct bwn_mac *,
243203945Sweongyo		    const struct bwn_txstatus *);
244203945Sweongyostatic uint16_t	bwn_pio_rx_read_2(struct bwn_pio_rxqueue *, uint16_t);
245203945Sweongyostatic uint32_t	bwn_pio_rx_read_4(struct bwn_pio_rxqueue *, uint16_t);
246203945Sweongyostatic void	bwn_pio_rx_write_2(struct bwn_pio_rxqueue *, uint16_t,
247203945Sweongyo		    uint16_t);
248203945Sweongyostatic void	bwn_pio_rx_write_4(struct bwn_pio_rxqueue *, uint16_t,
249203945Sweongyo		    uint32_t);
250203945Sweongyostatic int	bwn_pio_tx_start(struct bwn_mac *, struct ieee80211_node *,
251203945Sweongyo		    struct mbuf *);
252203945Sweongyostatic struct bwn_pio_txqueue *bwn_pio_select(struct bwn_mac *, uint8_t);
253203945Sweongyostatic uint32_t	bwn_pio_write_multi_4(struct bwn_mac *,
254203945Sweongyo		    struct bwn_pio_txqueue *, uint32_t, const void *, int);
255203945Sweongyostatic void	bwn_pio_write_4(struct bwn_mac *, struct bwn_pio_txqueue *,
256203945Sweongyo		    uint16_t, uint32_t);
257203945Sweongyostatic uint16_t	bwn_pio_write_multi_2(struct bwn_mac *,
258203945Sweongyo		    struct bwn_pio_txqueue *, uint16_t, const void *, int);
259203945Sweongyostatic uint16_t	bwn_pio_write_mbuf_2(struct bwn_mac *,
260203945Sweongyo		    struct bwn_pio_txqueue *, uint16_t, struct mbuf *);
261203945Sweongyostatic struct bwn_pio_txqueue *bwn_pio_parse_cookie(struct bwn_mac *,
262203945Sweongyo		    uint16_t, struct bwn_pio_txpkt **);
263203945Sweongyostatic void	bwn_dma_init(struct bwn_mac *);
264203945Sweongyostatic void	bwn_dma_rxdirectfifo(struct bwn_mac *, int, uint8_t);
265203945Sweongyostatic int	bwn_dma_mask2type(uint64_t);
266203945Sweongyostatic uint64_t	bwn_dma_mask(struct bwn_mac *);
267203945Sweongyostatic uint16_t	bwn_dma_base(int, int);
268203945Sweongyostatic void	bwn_dma_ringfree(struct bwn_dma_ring **);
269203945Sweongyostatic void	bwn_dma_32_getdesc(struct bwn_dma_ring *,
270203945Sweongyo		    int, struct bwn_dmadesc_generic **,
271203945Sweongyo		    struct bwn_dmadesc_meta **);
272203945Sweongyostatic void	bwn_dma_32_setdesc(struct bwn_dma_ring *,
273203945Sweongyo		    struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int,
274203945Sweongyo		    int, int);
275203945Sweongyostatic void	bwn_dma_32_start_transfer(struct bwn_dma_ring *, int);
276203945Sweongyostatic void	bwn_dma_32_suspend(struct bwn_dma_ring *);
277203945Sweongyostatic void	bwn_dma_32_resume(struct bwn_dma_ring *);
278203945Sweongyostatic int	bwn_dma_32_get_curslot(struct bwn_dma_ring *);
279203945Sweongyostatic void	bwn_dma_32_set_curslot(struct bwn_dma_ring *, int);
280203945Sweongyostatic void	bwn_dma_64_getdesc(struct bwn_dma_ring *,
281203945Sweongyo		    int, struct bwn_dmadesc_generic **,
282203945Sweongyo		    struct bwn_dmadesc_meta **);
283203945Sweongyostatic void	bwn_dma_64_setdesc(struct bwn_dma_ring *,
284203945Sweongyo		    struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int,
285203945Sweongyo		    int, int);
286203945Sweongyostatic void	bwn_dma_64_start_transfer(struct bwn_dma_ring *, int);
287203945Sweongyostatic void	bwn_dma_64_suspend(struct bwn_dma_ring *);
288203945Sweongyostatic void	bwn_dma_64_resume(struct bwn_dma_ring *);
289203945Sweongyostatic int	bwn_dma_64_get_curslot(struct bwn_dma_ring *);
290203945Sweongyostatic void	bwn_dma_64_set_curslot(struct bwn_dma_ring *, int);
291203945Sweongyostatic int	bwn_dma_allocringmemory(struct bwn_dma_ring *);
292203945Sweongyostatic void	bwn_dma_setup(struct bwn_dma_ring *);
293203945Sweongyostatic void	bwn_dma_free_ringmemory(struct bwn_dma_ring *);
294203945Sweongyostatic void	bwn_dma_cleanup(struct bwn_dma_ring *);
295203945Sweongyostatic void	bwn_dma_free_descbufs(struct bwn_dma_ring *);
296203945Sweongyostatic int	bwn_dma_tx_reset(struct bwn_mac *, uint16_t, int);
297203945Sweongyostatic void	bwn_dma_rx(struct bwn_dma_ring *);
298203945Sweongyostatic int	bwn_dma_rx_reset(struct bwn_mac *, uint16_t, int);
299203945Sweongyostatic void	bwn_dma_free_descbuf(struct bwn_dma_ring *,
300203945Sweongyo		    struct bwn_dmadesc_meta *);
301203945Sweongyostatic void	bwn_dma_set_redzone(struct bwn_dma_ring *, struct mbuf *);
302203945Sweongyostatic int	bwn_dma_gettype(struct bwn_mac *);
303203945Sweongyostatic void	bwn_dma_ring_addr(void *, bus_dma_segment_t *, int, int);
304203945Sweongyostatic int	bwn_dma_freeslot(struct bwn_dma_ring *);
305203945Sweongyostatic int	bwn_dma_nextslot(struct bwn_dma_ring *, int);
306203945Sweongyostatic void	bwn_dma_rxeof(struct bwn_dma_ring *, int *);
307203945Sweongyostatic int	bwn_dma_newbuf(struct bwn_dma_ring *,
308203945Sweongyo		    struct bwn_dmadesc_generic *, struct bwn_dmadesc_meta *,
309203945Sweongyo		    int);
310203945Sweongyostatic void	bwn_dma_buf_addr(void *, bus_dma_segment_t *, int,
311203945Sweongyo		    bus_size_t, int);
312203945Sweongyostatic uint8_t	bwn_dma_check_redzone(struct bwn_dma_ring *, struct mbuf *);
313203945Sweongyostatic void	bwn_dma_handle_txeof(struct bwn_mac *,
314203945Sweongyo		    const struct bwn_txstatus *);
315203945Sweongyostatic int	bwn_dma_tx_start(struct bwn_mac *, struct ieee80211_node *,
316203945Sweongyo		    struct mbuf *);
317203945Sweongyostatic int	bwn_dma_getslot(struct bwn_dma_ring *);
318203945Sweongyostatic struct bwn_dma_ring *bwn_dma_select(struct bwn_mac *,
319203945Sweongyo		    uint8_t);
320203945Sweongyostatic int	bwn_dma_attach(struct bwn_mac *);
321203945Sweongyostatic struct bwn_dma_ring *bwn_dma_ringsetup(struct bwn_mac *,
322203945Sweongyo		    int, int, int);
323203945Sweongyostatic struct bwn_dma_ring *bwn_dma_parse_cookie(struct bwn_mac *,
324203945Sweongyo		    const struct bwn_txstatus *, uint16_t, int *);
325203945Sweongyostatic void	bwn_dma_free(struct bwn_mac *);
326203945Sweongyostatic void	bwn_phy_g_init_sub(struct bwn_mac *);
327203945Sweongyostatic uint8_t	bwn_has_hwpctl(struct bwn_mac *);
328203945Sweongyostatic void	bwn_phy_init_b5(struct bwn_mac *);
329203945Sweongyostatic void	bwn_phy_init_b6(struct bwn_mac *);
330203945Sweongyostatic void	bwn_phy_init_a(struct bwn_mac *);
331203945Sweongyostatic void	bwn_loopback_calcgain(struct bwn_mac *);
332203945Sweongyostatic uint16_t	bwn_rf_init_bcm2050(struct bwn_mac *);
333203945Sweongyostatic void	bwn_lo_g_init(struct bwn_mac *);
334203945Sweongyostatic void	bwn_lo_g_adjust(struct bwn_mac *);
335203945Sweongyostatic void	bwn_lo_get_powervector(struct bwn_mac *);
336203945Sweongyostatic struct bwn_lo_calib *bwn_lo_calibset(struct bwn_mac *,
337203945Sweongyo		    const struct bwn_bbatt *, const struct bwn_rfatt *);
338203945Sweongyostatic void	bwn_lo_write(struct bwn_mac *, struct bwn_loctl *);
339203945Sweongyostatic void	bwn_phy_hwpctl_init(struct bwn_mac *);
340203945Sweongyostatic void	bwn_phy_g_switch_chan(struct bwn_mac *, int, uint8_t);
341203945Sweongyostatic void	bwn_phy_g_set_txpwr_sub(struct bwn_mac *,
342203945Sweongyo		    const struct bwn_bbatt *, const struct bwn_rfatt *,
343203945Sweongyo		    uint8_t);
344203945Sweongyostatic void	bwn_phy_g_set_bbatt(struct bwn_mac *, uint16_t);
345203945Sweongyostatic uint16_t	bwn_rf_2050_rfoverval(struct bwn_mac *, uint16_t, uint32_t);
346203945Sweongyostatic void	bwn_spu_workaround(struct bwn_mac *, uint8_t);
347203945Sweongyostatic void	bwn_wa_init(struct bwn_mac *);
348203945Sweongyostatic void	bwn_ofdmtab_write_2(struct bwn_mac *, uint16_t, uint16_t,
349203945Sweongyo		    uint16_t);
350203945Sweongyostatic void	bwn_dummy_transmission(struct bwn_mac *, int, int);
351203945Sweongyostatic void	bwn_ofdmtab_write_4(struct bwn_mac *, uint16_t, uint16_t,
352203945Sweongyo		    uint32_t);
353203945Sweongyostatic void	bwn_gtab_write(struct bwn_mac *, uint16_t, uint16_t,
354203945Sweongyo		    uint16_t);
355203945Sweongyostatic void	bwn_ram_write(struct bwn_mac *, uint16_t, uint32_t);
356203945Sweongyostatic void	bwn_mac_suspend(struct bwn_mac *);
357203945Sweongyostatic void	bwn_mac_enable(struct bwn_mac *);
358203945Sweongyostatic void	bwn_psctl(struct bwn_mac *, uint32_t);
359203945Sweongyostatic int16_t	bwn_nrssi_read(struct bwn_mac *, uint16_t);
360203945Sweongyostatic void	bwn_nrssi_offset(struct bwn_mac *);
361203945Sweongyostatic void	bwn_nrssi_threshold(struct bwn_mac *);
362203945Sweongyostatic void	bwn_nrssi_slope_11g(struct bwn_mac *);
363203945Sweongyostatic void	bwn_set_all_gains(struct bwn_mac *, int16_t, int16_t,
364203945Sweongyo		    int16_t);
365203945Sweongyostatic void	bwn_set_original_gains(struct bwn_mac *);
366203945Sweongyostatic void	bwn_hwpctl_early_init(struct bwn_mac *);
367203945Sweongyostatic void	bwn_hwpctl_init_gphy(struct bwn_mac *);
368203945Sweongyostatic uint16_t	bwn_phy_g_chan2freq(uint8_t);
369203945Sweongyostatic int	bwn_fw_gets(struct bwn_mac *, enum bwn_fwtype);
370203945Sweongyostatic int	bwn_fw_get(struct bwn_mac *, enum bwn_fwtype,
371203945Sweongyo		    const char *, struct bwn_fwfile *);
372203945Sweongyostatic void	bwn_release_firmware(struct bwn_mac *);
373203945Sweongyostatic void	bwn_do_release_fw(struct bwn_fwfile *);
374203945Sweongyostatic uint16_t	bwn_fwcaps_read(struct bwn_mac *);
375203945Sweongyostatic int	bwn_fwinitvals_write(struct bwn_mac *,
376203945Sweongyo		    const struct bwn_fwinitvals *, size_t, size_t);
377203945Sweongyostatic int	bwn_switch_channel(struct bwn_mac *, int);
378203945Sweongyostatic uint16_t	bwn_ant2phy(int);
379203945Sweongyostatic void	bwn_mac_write_bssid(struct bwn_mac *);
380203945Sweongyostatic void	bwn_mac_setfilter(struct bwn_mac *, uint16_t,
381203945Sweongyo		    const uint8_t *);
382203945Sweongyostatic void	bwn_key_dowrite(struct bwn_mac *, uint8_t, uint8_t,
383203945Sweongyo		    const uint8_t *, size_t, const uint8_t *);
384203945Sweongyostatic void	bwn_key_macwrite(struct bwn_mac *, uint8_t,
385203945Sweongyo		    const uint8_t *);
386203945Sweongyostatic void	bwn_key_write(struct bwn_mac *, uint8_t, uint8_t,
387203945Sweongyo		    const uint8_t *);
388203945Sweongyostatic void	bwn_phy_exit(struct bwn_mac *);
389203945Sweongyostatic void	bwn_core_stop(struct bwn_mac *);
390203945Sweongyostatic int	bwn_switch_band(struct bwn_softc *,
391203945Sweongyo		    struct ieee80211_channel *);
392203945Sweongyostatic void	bwn_phy_reset(struct bwn_mac *);
393203945Sweongyostatic int	bwn_newstate(struct ieee80211vap *, enum ieee80211_state, int);
394203945Sweongyostatic void	bwn_set_pretbtt(struct bwn_mac *);
395203945Sweongyostatic int	bwn_intr(void *);
396203945Sweongyostatic void	bwn_intrtask(void *, int);
397203945Sweongyostatic void	bwn_restart(struct bwn_mac *, const char *);
398203945Sweongyostatic void	bwn_intr_ucode_debug(struct bwn_mac *);
399203945Sweongyostatic void	bwn_intr_tbtt_indication(struct bwn_mac *);
400203945Sweongyostatic void	bwn_intr_atim_end(struct bwn_mac *);
401203945Sweongyostatic void	bwn_intr_beacon(struct bwn_mac *);
402203945Sweongyostatic void	bwn_intr_pmq(struct bwn_mac *);
403203945Sweongyostatic void	bwn_intr_noise(struct bwn_mac *);
404203945Sweongyostatic void	bwn_intr_txeof(struct bwn_mac *);
405203945Sweongyostatic void	bwn_hwreset(void *, int);
406203945Sweongyostatic void	bwn_handle_fwpanic(struct bwn_mac *);
407203945Sweongyostatic void	bwn_load_beacon0(struct bwn_mac *);
408203945Sweongyostatic void	bwn_load_beacon1(struct bwn_mac *);
409203945Sweongyostatic uint32_t	bwn_jssi_read(struct bwn_mac *);
410203945Sweongyostatic void	bwn_noise_gensample(struct bwn_mac *);
411203945Sweongyostatic void	bwn_handle_txeof(struct bwn_mac *,
412203945Sweongyo		    const struct bwn_txstatus *);
413203945Sweongyostatic void	bwn_rxeof(struct bwn_mac *, struct mbuf *, const void *);
414203945Sweongyostatic void	bwn_phy_txpower_check(struct bwn_mac *, uint32_t);
415203945Sweongyostatic void	bwn_start_locked(struct ifnet *);
416203945Sweongyostatic int	bwn_tx_start(struct bwn_softc *, struct ieee80211_node *,
417203945Sweongyo		    struct mbuf *);
418203945Sweongyostatic int	bwn_tx_isfull(struct bwn_softc *, struct mbuf *);
419203945Sweongyostatic int	bwn_set_txhdr(struct bwn_mac *,
420203945Sweongyo		    struct ieee80211_node *, struct mbuf *, struct bwn_txhdr *,
421203945Sweongyo		    uint16_t);
422203945Sweongyostatic void	bwn_plcp_genhdr(struct bwn_plcp4 *, const uint16_t,
423203945Sweongyo		    const uint8_t);
424203945Sweongyostatic uint8_t	bwn_antenna_sanitize(struct bwn_mac *, uint8_t);
425203945Sweongyostatic uint8_t	bwn_get_fbrate(uint8_t);
426203945Sweongyostatic int	bwn_phy_shm_tssi_read(struct bwn_mac *, uint16_t);
427203945Sweongyostatic void	bwn_phy_g_setatt(struct bwn_mac *, int *, int *);
428203945Sweongyostatic void	bwn_phy_lock(struct bwn_mac *);
429203945Sweongyostatic void	bwn_phy_unlock(struct bwn_mac *);
430203945Sweongyostatic void	bwn_rf_lock(struct bwn_mac *);
431203945Sweongyostatic void	bwn_rf_unlock(struct bwn_mac *);
432203945Sweongyostatic void	bwn_txpwr(void *, int);
433203945Sweongyostatic void	bwn_tasks(void *);
434203945Sweongyostatic void	bwn_task_15s(struct bwn_mac *);
435203945Sweongyostatic void	bwn_task_30s(struct bwn_mac *);
436203945Sweongyostatic void	bwn_task_60s(struct bwn_mac *);
437203945Sweongyostatic int	bwn_plcp_get_ofdmrate(struct bwn_mac *, struct bwn_plcp6 *,
438203945Sweongyo		    uint8_t);
439203945Sweongyostatic int	bwn_plcp_get_cckrate(struct bwn_mac *, struct bwn_plcp6 *);
440203945Sweongyostatic void	bwn_rx_radiotap(struct bwn_mac *, struct mbuf *,
441203945Sweongyo		    const struct bwn_rxhdr4 *, struct bwn_plcp6 *, int,
442203945Sweongyo		    int, int);
443203945Sweongyostatic void	bwn_tsf_read(struct bwn_mac *, uint64_t *);
444203945Sweongyostatic void	bwn_phy_g_dc_lookup_init(struct bwn_mac *, uint8_t);
445203945Sweongyostatic void	bwn_set_slot_time(struct bwn_mac *, uint16_t);
446203945Sweongyostatic void	bwn_watchdog(void *);
447203945Sweongyostatic void	bwn_dma_stop(struct bwn_mac *);
448203945Sweongyostatic void	bwn_pio_stop(struct bwn_mac *);
449203945Sweongyostatic void	bwn_dma_ringstop(struct bwn_dma_ring **);
450203945Sweongyostatic void	bwn_led_attach(struct bwn_mac *);
451203945Sweongyostatic void	bwn_led_newstate(struct bwn_mac *, enum ieee80211_state);
452203945Sweongyostatic void	bwn_led_event(struct bwn_mac *, int);
453203945Sweongyostatic void	bwn_led_blink_start(struct bwn_mac *, int, int);
454203945Sweongyostatic void	bwn_led_blink_next(void *);
455203945Sweongyostatic void	bwn_led_blink_end(void *);
456203945Sweongyostatic void	bwn_rfswitch(void *);
457203945Sweongyostatic void	bwn_rf_turnon(struct bwn_mac *);
458203945Sweongyostatic void	bwn_rf_turnoff(struct bwn_mac *);
459203945Sweongyostatic void	bwn_phy_lp_init_pre(struct bwn_mac *);
460203945Sweongyostatic int	bwn_phy_lp_init(struct bwn_mac *);
461203945Sweongyostatic uint16_t	bwn_phy_lp_read(struct bwn_mac *, uint16_t);
462203945Sweongyostatic void	bwn_phy_lp_write(struct bwn_mac *, uint16_t, uint16_t);
463203945Sweongyostatic void	bwn_phy_lp_maskset(struct bwn_mac *, uint16_t, uint16_t,
464203945Sweongyo		    uint16_t);
465203945Sweongyostatic uint16_t	bwn_phy_lp_rf_read(struct bwn_mac *, uint16_t);
466203945Sweongyostatic void	bwn_phy_lp_rf_write(struct bwn_mac *, uint16_t, uint16_t);
467203945Sweongyostatic void	bwn_phy_lp_rf_onoff(struct bwn_mac *, int);
468203945Sweongyostatic int	bwn_phy_lp_switch_channel(struct bwn_mac *, uint32_t);
469203945Sweongyostatic uint32_t	bwn_phy_lp_get_default_chan(struct bwn_mac *);
470203945Sweongyostatic void	bwn_phy_lp_set_antenna(struct bwn_mac *, int);
471203945Sweongyostatic void	bwn_phy_lp_task_60s(struct bwn_mac *);
472203945Sweongyostatic void	bwn_phy_lp_readsprom(struct bwn_mac *);
473203945Sweongyostatic void	bwn_phy_lp_bbinit(struct bwn_mac *);
474203945Sweongyostatic void	bwn_phy_lp_txpctl_init(struct bwn_mac *);
475203945Sweongyostatic void	bwn_phy_lp_calib(struct bwn_mac *);
476203945Sweongyostatic void	bwn_phy_lp_switch_analog(struct bwn_mac *, int);
477203945Sweongyostatic int	bwn_phy_lp_b2062_switch_channel(struct bwn_mac *, uint8_t);
478203945Sweongyostatic int	bwn_phy_lp_b2063_switch_channel(struct bwn_mac *, uint8_t);
479203945Sweongyostatic void	bwn_phy_lp_set_anafilter(struct bwn_mac *, uint8_t);
480203945Sweongyostatic void	bwn_phy_lp_set_gaintbl(struct bwn_mac *, uint32_t);
481203945Sweongyostatic void	bwn_phy_lp_digflt_save(struct bwn_mac *);
482203945Sweongyostatic void	bwn_phy_lp_get_txpctlmode(struct bwn_mac *);
483203945Sweongyostatic void	bwn_phy_lp_set_txpctlmode(struct bwn_mac *, uint8_t);
484203945Sweongyostatic void	bwn_phy_lp_bugfix(struct bwn_mac *);
485203945Sweongyostatic void	bwn_phy_lp_digflt_restore(struct bwn_mac *);
486203945Sweongyostatic void	bwn_phy_lp_tblinit(struct bwn_mac *);
487203945Sweongyostatic void	bwn_phy_lp_bbinit_r2(struct bwn_mac *);
488203945Sweongyostatic void	bwn_phy_lp_bbinit_r01(struct bwn_mac *);
489203945Sweongyostatic void	bwn_phy_lp_b2062_init(struct bwn_mac *);
490203945Sweongyostatic void	bwn_phy_lp_b2063_init(struct bwn_mac *);
491203945Sweongyostatic void	bwn_phy_lp_rxcal_r2(struct bwn_mac *);
492203945Sweongyostatic void	bwn_phy_lp_rccal_r12(struct bwn_mac *);
493203945Sweongyostatic void	bwn_phy_lp_set_rccap(struct bwn_mac *);
494203945Sweongyostatic uint32_t	bwn_phy_lp_roundup(uint32_t, uint32_t, uint8_t);
495203945Sweongyostatic void	bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *);
496203945Sweongyostatic void	bwn_phy_lp_b2062_vco_calib(struct bwn_mac *);
497203945Sweongyostatic void	bwn_tab_write_multi(struct bwn_mac *, uint32_t, int,
498203945Sweongyo		    const void *);
499203945Sweongyostatic void	bwn_tab_read_multi(struct bwn_mac *, uint32_t, int, void *);
500203945Sweongyostatic struct bwn_txgain
501203945Sweongyo		bwn_phy_lp_get_txgain(struct bwn_mac *);
502203945Sweongyostatic uint8_t	bwn_phy_lp_get_bbmult(struct bwn_mac *);
503203945Sweongyostatic void	bwn_phy_lp_set_txgain(struct bwn_mac *, struct bwn_txgain *);
504203945Sweongyostatic void	bwn_phy_lp_set_bbmult(struct bwn_mac *, uint8_t);
505203945Sweongyostatic void	bwn_phy_lp_set_trsw_over(struct bwn_mac *, uint8_t, uint8_t);
506203945Sweongyostatic void	bwn_phy_lp_set_rxgain(struct bwn_mac *, uint32_t);
507203945Sweongyostatic void	bwn_phy_lp_set_deaf(struct bwn_mac *, uint8_t);
508203945Sweongyostatic int	bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *, uint16_t);
509203945Sweongyostatic void	bwn_phy_lp_clear_deaf(struct bwn_mac *, uint8_t);
510203945Sweongyostatic void	bwn_phy_lp_tblinit_r01(struct bwn_mac *);
511203945Sweongyostatic void	bwn_phy_lp_tblinit_r2(struct bwn_mac *);
512203945Sweongyostatic void	bwn_phy_lp_tblinit_txgain(struct bwn_mac *);
513203945Sweongyostatic void	bwn_tab_write(struct bwn_mac *, uint32_t, uint32_t);
514203945Sweongyostatic void	bwn_phy_lp_b2062_tblinit(struct bwn_mac *);
515203945Sweongyostatic void	bwn_phy_lp_b2063_tblinit(struct bwn_mac *);
516203945Sweongyostatic int	bwn_phy_lp_loopback(struct bwn_mac *);
517203945Sweongyostatic void	bwn_phy_lp_set_rxgain_idx(struct bwn_mac *, uint16_t);
518203945Sweongyostatic void	bwn_phy_lp_ddfs_turnon(struct bwn_mac *, int, int, int, int,
519203945Sweongyo		    int);
520203945Sweongyostatic uint8_t	bwn_phy_lp_rx_iq_est(struct bwn_mac *, uint16_t, uint8_t,
521203945Sweongyo		    struct bwn_phy_lp_iq_est *);
522203945Sweongyostatic void	bwn_phy_lp_ddfs_turnoff(struct bwn_mac *);
523203945Sweongyostatic uint32_t	bwn_tab_read(struct bwn_mac *, uint32_t);
524203945Sweongyostatic void	bwn_phy_lp_set_txgain_dac(struct bwn_mac *, uint16_t);
525203945Sweongyostatic void	bwn_phy_lp_set_txgain_pa(struct bwn_mac *, uint16_t);
526203945Sweongyostatic void	bwn_phy_lp_set_txgain_override(struct bwn_mac *);
527203945Sweongyostatic uint16_t	bwn_phy_lp_get_pa_gain(struct bwn_mac *);
528203945Sweongyostatic uint8_t	bwn_nbits(int32_t);
529203945Sweongyostatic void	bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *, int, int,
530203945Sweongyo		    struct bwn_txgain_entry *);
531203945Sweongyostatic void	bwn_phy_lp_gaintbl_write(struct bwn_mac *, int,
532203945Sweongyo		    struct bwn_txgain_entry);
533203945Sweongyostatic void	bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *, int,
534203945Sweongyo		    struct bwn_txgain_entry);
535203945Sweongyostatic void	bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *, int,
536203945Sweongyo		    struct bwn_txgain_entry);
537204257Sweongyostatic void	bwn_sysctl_node(struct bwn_softc *);
538203945Sweongyo
539203945Sweongyostatic struct resource_spec bwn_res_spec_legacy[] = {
540203945Sweongyo	{ SYS_RES_IRQ,		0,		RF_ACTIVE | RF_SHAREABLE },
541203945Sweongyo	{ -1,			0,		0 }
542203945Sweongyo};
543203945Sweongyo
544203945Sweongyostatic struct resource_spec bwn_res_spec_msi[] = {
545203945Sweongyo	{ SYS_RES_IRQ,		1,		RF_ACTIVE },
546203945Sweongyo	{ -1,			0,		0 }
547203945Sweongyo};
548203945Sweongyo
549203945Sweongyostatic const struct bwn_channelinfo bwn_chantable_bg = {
550203945Sweongyo	.channels = {
551203945Sweongyo		{ 2412,  1, 30 }, { 2417,  2, 30 }, { 2422,  3, 30 },
552203945Sweongyo		{ 2427,  4, 30 }, { 2432,  5, 30 }, { 2437,  6, 30 },
553203945Sweongyo		{ 2442,  7, 30 }, { 2447,  8, 30 }, { 2452,  9, 30 },
554203945Sweongyo		{ 2457, 10, 30 }, { 2462, 11, 30 }, { 2467, 12, 30 },
555203945Sweongyo		{ 2472, 13, 30 }, { 2484, 14, 30 } },
556203945Sweongyo	.nchannels = 14
557203945Sweongyo};
558203945Sweongyo
559203945Sweongyostatic const struct bwn_channelinfo bwn_chantable_a = {
560203945Sweongyo	.channels = {
561203945Sweongyo		{ 5170,  34, 30 }, { 5180,  36, 30 }, { 5190,  38, 30 },
562203945Sweongyo		{ 5200,  40, 30 }, { 5210,  42, 30 }, { 5220,  44, 30 },
563203945Sweongyo		{ 5230,  46, 30 }, { 5240,  48, 30 }, { 5260,  52, 30 },
564203945Sweongyo		{ 5280,  56, 30 }, { 5300,  60, 30 }, { 5320,  64, 30 },
565203945Sweongyo		{ 5500, 100, 30 }, { 5520, 104, 30 }, { 5540, 108, 30 },
566203945Sweongyo		{ 5560, 112, 30 }, { 5580, 116, 30 }, { 5600, 120, 30 },
567203945Sweongyo		{ 5620, 124, 30 }, { 5640, 128, 30 }, { 5660, 132, 30 },
568203945Sweongyo		{ 5680, 136, 30 }, { 5700, 140, 30 }, { 5745, 149, 30 },
569203945Sweongyo		{ 5765, 153, 30 }, { 5785, 157, 30 }, { 5805, 161, 30 },
570203945Sweongyo		{ 5825, 165, 30 }, { 5920, 184, 30 }, { 5940, 188, 30 },
571203945Sweongyo		{ 5960, 192, 30 }, { 5980, 196, 30 }, { 6000, 200, 30 },
572203945Sweongyo		{ 6020, 204, 30 }, { 6040, 208, 30 }, { 6060, 212, 30 },
573203945Sweongyo		{ 6080, 216, 30 } },
574203945Sweongyo	.nchannels = 37
575203945Sweongyo};
576203945Sweongyo
577203945Sweongyostatic const struct bwn_channelinfo bwn_chantable_n = {
578203945Sweongyo	.channels = {
579203945Sweongyo		{ 5160,  32, 30 }, { 5170,  34, 30 }, { 5180,  36, 30 },
580203945Sweongyo		{ 5190,  38, 30 }, { 5200,  40, 30 }, { 5210,  42, 30 },
581203945Sweongyo		{ 5220,  44, 30 }, { 5230,  46, 30 }, { 5240,  48, 30 },
582203945Sweongyo		{ 5250,  50, 30 }, { 5260,  52, 30 }, { 5270,  54, 30 },
583203945Sweongyo		{ 5280,  56, 30 }, { 5290,  58, 30 }, { 5300,  60, 30 },
584203945Sweongyo		{ 5310,  62, 30 }, { 5320,  64, 30 }, { 5330,  66, 30 },
585203945Sweongyo		{ 5340,  68, 30 }, { 5350,  70, 30 }, { 5360,  72, 30 },
586203945Sweongyo		{ 5370,  74, 30 }, { 5380,  76, 30 }, { 5390,  78, 30 },
587203945Sweongyo		{ 5400,  80, 30 }, { 5410,  82, 30 }, { 5420,  84, 30 },
588203945Sweongyo		{ 5430,  86, 30 }, { 5440,  88, 30 }, { 5450,  90, 30 },
589203945Sweongyo		{ 5460,  92, 30 }, { 5470,  94, 30 }, { 5480,  96, 30 },
590203945Sweongyo		{ 5490,  98, 30 }, { 5500, 100, 30 }, { 5510, 102, 30 },
591203945Sweongyo		{ 5520, 104, 30 }, { 5530, 106, 30 }, { 5540, 108, 30 },
592203945Sweongyo		{ 5550, 110, 30 }, { 5560, 112, 30 }, { 5570, 114, 30 },
593203945Sweongyo		{ 5580, 116, 30 }, { 5590, 118, 30 }, { 5600, 120, 30 },
594203945Sweongyo		{ 5610, 122, 30 }, { 5620, 124, 30 }, { 5630, 126, 30 },
595203945Sweongyo		{ 5640, 128, 30 }, { 5650, 130, 30 }, { 5660, 132, 30 },
596203945Sweongyo		{ 5670, 134, 30 }, { 5680, 136, 30 }, { 5690, 138, 30 },
597203945Sweongyo		{ 5700, 140, 30 }, { 5710, 142, 30 }, { 5720, 144, 30 },
598203945Sweongyo		{ 5725, 145, 30 }, { 5730, 146, 30 }, { 5735, 147, 30 },
599203945Sweongyo		{ 5740, 148, 30 }, { 5745, 149, 30 }, { 5750, 150, 30 },
600203945Sweongyo		{ 5755, 151, 30 }, { 5760, 152, 30 }, { 5765, 153, 30 },
601203945Sweongyo		{ 5770, 154, 30 }, { 5775, 155, 30 }, { 5780, 156, 30 },
602203945Sweongyo		{ 5785, 157, 30 }, { 5790, 158, 30 }, { 5795, 159, 30 },
603203945Sweongyo		{ 5800, 160, 30 }, { 5805, 161, 30 }, { 5810, 162, 30 },
604203945Sweongyo		{ 5815, 163, 30 }, { 5820, 164, 30 }, { 5825, 165, 30 },
605203945Sweongyo		{ 5830, 166, 30 }, { 5840, 168, 30 }, { 5850, 170, 30 },
606203945Sweongyo		{ 5860, 172, 30 }, { 5870, 174, 30 }, { 5880, 176, 30 },
607203945Sweongyo		{ 5890, 178, 30 }, { 5900, 180, 30 }, { 5910, 182, 30 },
608203945Sweongyo		{ 5920, 184, 30 }, { 5930, 186, 30 }, { 5940, 188, 30 },
609203945Sweongyo		{ 5950, 190, 30 }, { 5960, 192, 30 }, { 5970, 194, 30 },
610203945Sweongyo		{ 5980, 196, 30 }, { 5990, 198, 30 }, { 6000, 200, 30 },
611203945Sweongyo		{ 6010, 202, 30 }, { 6020, 204, 30 }, { 6030, 206, 30 },
612203945Sweongyo		{ 6040, 208, 30 }, { 6050, 210, 30 }, { 6060, 212, 30 },
613203945Sweongyo		{ 6070, 214, 30 }, { 6080, 216, 30 }, { 6090, 218, 30 },
614203945Sweongyo		{ 6100, 220, 30 }, { 6110, 222, 30 }, { 6120, 224, 30 },
615203945Sweongyo		{ 6130, 226, 30 }, { 6140, 228, 30 } },
616203945Sweongyo	.nchannels = 110
617203945Sweongyo};
618203945Sweongyo
619203945Sweongyostatic const uint8_t bwn_b2063_chantable_data[33][12] = {
620203945Sweongyo	{ 0x6f, 0x3c, 0x3c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
621203945Sweongyo	{ 0x6f, 0x2c, 0x2c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
622203945Sweongyo	{ 0x6f, 0x1c, 0x1c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
623203945Sweongyo	{ 0x6e, 0x1c, 0x1c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
624203945Sweongyo	{ 0x6e, 0xc, 0xc, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
625203945Sweongyo	{ 0x6a, 0xc, 0xc, 0, 0x2, 0x5, 0xd, 0xd, 0x77, 0x80, 0x20, 0 },
626203945Sweongyo	{ 0x6a, 0xc, 0xc, 0, 0x1, 0x5, 0xd, 0xc, 0x77, 0x80, 0x20, 0 },
627203945Sweongyo	{ 0x6a, 0xc, 0xc, 0, 0x1, 0x4, 0xc, 0xc, 0x77, 0x80, 0x20, 0 },
628203945Sweongyo	{ 0x69, 0xc, 0xc, 0, 0x1, 0x4, 0xc, 0xc, 0x77, 0x70, 0x20, 0 },
629203945Sweongyo	{ 0x69, 0xc, 0xc, 0, 0x1, 0x4, 0xb, 0xc, 0x77, 0x70, 0x20, 0 },
630203945Sweongyo	{ 0x69, 0xc, 0xc, 0, 0, 0x4, 0xb, 0xb, 0x77, 0x60, 0x20, 0 },
631203945Sweongyo	{ 0x69, 0xc, 0xc, 0, 0, 0x3, 0xa, 0xb, 0x77, 0x60, 0x20, 0 },
632203945Sweongyo	{ 0x69, 0xc, 0xc, 0, 0, 0x3, 0xa, 0xa, 0x77, 0x60, 0x20, 0 },
633203945Sweongyo	{ 0x68, 0xc, 0xc, 0, 0, 0x2, 0x9, 0x9, 0x77, 0x60, 0x20, 0 },
634203945Sweongyo	{ 0x68, 0xc, 0xc, 0, 0, 0x1, 0x8, 0x8, 0x77, 0x50, 0x10, 0 },
635203945Sweongyo	{ 0x67, 0xc, 0xc, 0, 0, 0, 0x8, 0x8, 0x77, 0x50, 0x10, 0 },
636203945Sweongyo	{ 0x64, 0xc, 0xc, 0, 0, 0, 0x2, 0x1, 0x77, 0x20, 0, 0 },
637203945Sweongyo	{ 0x64, 0xc, 0xc, 0, 0, 0, 0x1, 0x1, 0x77, 0x20, 0, 0 },
638203945Sweongyo	{ 0x63, 0xc, 0xc, 0, 0, 0, 0x1, 0, 0x77, 0x10, 0, 0 },
639203945Sweongyo	{ 0x63, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0x10, 0, 0 },
640203945Sweongyo	{ 0x62, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0x10, 0, 0 },
641203945Sweongyo	{ 0x62, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
642203945Sweongyo	{ 0x61, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
643203945Sweongyo	{ 0x60, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
644203945Sweongyo	{ 0x6e, 0xc, 0xc, 0, 0x9, 0xe, 0xf, 0xf, 0x77, 0xc0, 0x50, 0 },
645203945Sweongyo	{ 0x6e, 0xc, 0xc, 0, 0x9, 0xd, 0xf, 0xf, 0x77, 0xb0, 0x50, 0 },
646203945Sweongyo	{ 0x6e, 0xc, 0xc, 0, 0x8, 0xc, 0xf, 0xf, 0x77, 0xb0, 0x50, 0 },
647203945Sweongyo	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xc, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
648203945Sweongyo	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xb, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
649203945Sweongyo	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xa, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
650203945Sweongyo	{ 0x6c, 0xc, 0xc, 0, 0x7, 0x9, 0xf, 0xf, 0x77, 0x90, 0x40, 0 },
651203945Sweongyo	{ 0x6c, 0xc, 0xc, 0, 0x6, 0x8, 0xf, 0xf, 0x77, 0x90, 0x40, 0 },
652203945Sweongyo	{ 0x6c, 0xc, 0xc, 0, 0x5, 0x8, 0xf, 0xf, 0x77, 0x90, 0x40, 0 }
653203945Sweongyo};
654203945Sweongyo
655203945Sweongyostatic const struct bwn_b206x_chan bwn_b2063_chantable[] = {
656203945Sweongyo	{ 1, 2412, bwn_b2063_chantable_data[0] },
657203945Sweongyo	{ 2, 2417, bwn_b2063_chantable_data[0] },
658203945Sweongyo	{ 3, 2422, bwn_b2063_chantable_data[0] },
659203945Sweongyo	{ 4, 2427, bwn_b2063_chantable_data[1] },
660203945Sweongyo	{ 5, 2432, bwn_b2063_chantable_data[1] },
661203945Sweongyo	{ 6, 2437, bwn_b2063_chantable_data[1] },
662203945Sweongyo	{ 7, 2442, bwn_b2063_chantable_data[1] },
663203945Sweongyo	{ 8, 2447, bwn_b2063_chantable_data[1] },
664203945Sweongyo	{ 9, 2452, bwn_b2063_chantable_data[2] },
665203945Sweongyo	{ 10, 2457, bwn_b2063_chantable_data[2] },
666203945Sweongyo	{ 11, 2462, bwn_b2063_chantable_data[3] },
667203945Sweongyo	{ 12, 2467, bwn_b2063_chantable_data[3] },
668203945Sweongyo	{ 13, 2472, bwn_b2063_chantable_data[3] },
669203945Sweongyo	{ 14, 2484, bwn_b2063_chantable_data[4] },
670203945Sweongyo	{ 34, 5170, bwn_b2063_chantable_data[5] },
671203945Sweongyo	{ 36, 5180, bwn_b2063_chantable_data[6] },
672203945Sweongyo	{ 38, 5190, bwn_b2063_chantable_data[7] },
673203945Sweongyo	{ 40, 5200, bwn_b2063_chantable_data[8] },
674203945Sweongyo	{ 42, 5210, bwn_b2063_chantable_data[9] },
675203945Sweongyo	{ 44, 5220, bwn_b2063_chantable_data[10] },
676203945Sweongyo	{ 46, 5230, bwn_b2063_chantable_data[11] },
677203945Sweongyo	{ 48, 5240, bwn_b2063_chantable_data[12] },
678203945Sweongyo	{ 52, 5260, bwn_b2063_chantable_data[13] },
679203945Sweongyo	{ 56, 5280, bwn_b2063_chantable_data[14] },
680203945Sweongyo	{ 60, 5300, bwn_b2063_chantable_data[14] },
681203945Sweongyo	{ 64, 5320, bwn_b2063_chantable_data[15] },
682203945Sweongyo	{ 100, 5500, bwn_b2063_chantable_data[16] },
683203945Sweongyo	{ 104, 5520, bwn_b2063_chantable_data[17] },
684203945Sweongyo	{ 108, 5540, bwn_b2063_chantable_data[18] },
685203945Sweongyo	{ 112, 5560, bwn_b2063_chantable_data[19] },
686203945Sweongyo	{ 116, 5580, bwn_b2063_chantable_data[20] },
687203945Sweongyo	{ 120, 5600, bwn_b2063_chantable_data[21] },
688203945Sweongyo	{ 124, 5620, bwn_b2063_chantable_data[21] },
689203945Sweongyo	{ 128, 5640, bwn_b2063_chantable_data[22] },
690203945Sweongyo	{ 132, 5660, bwn_b2063_chantable_data[22] },
691203945Sweongyo	{ 136, 5680, bwn_b2063_chantable_data[22] },
692203945Sweongyo	{ 140, 5700, bwn_b2063_chantable_data[23] },
693203945Sweongyo	{ 149, 5745, bwn_b2063_chantable_data[23] },
694203945Sweongyo	{ 153, 5765, bwn_b2063_chantable_data[23] },
695203945Sweongyo	{ 157, 5785, bwn_b2063_chantable_data[23] },
696203945Sweongyo	{ 161, 5805, bwn_b2063_chantable_data[23] },
697203945Sweongyo	{ 165, 5825, bwn_b2063_chantable_data[23] },
698203945Sweongyo	{ 184, 4920, bwn_b2063_chantable_data[24] },
699203945Sweongyo	{ 188, 4940, bwn_b2063_chantable_data[25] },
700203945Sweongyo	{ 192, 4960, bwn_b2063_chantable_data[26] },
701203945Sweongyo	{ 196, 4980, bwn_b2063_chantable_data[27] },
702203945Sweongyo	{ 200, 5000, bwn_b2063_chantable_data[28] },
703203945Sweongyo	{ 204, 5020, bwn_b2063_chantable_data[29] },
704203945Sweongyo	{ 208, 5040, bwn_b2063_chantable_data[30] },
705203945Sweongyo	{ 212, 5060, bwn_b2063_chantable_data[31] },
706203945Sweongyo	{ 216, 5080, bwn_b2063_chantable_data[32] }
707203945Sweongyo};
708203945Sweongyo
709203945Sweongyostatic const uint8_t bwn_b2062_chantable_data[22][12] = {
710203945Sweongyo	{ 0xff, 0xff, 0xb5, 0x1b, 0x24, 0x32, 0x32, 0x88, 0x88, 0, 0, 0 },
711203945Sweongyo	{ 0, 0x22, 0x20, 0x84, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
712203945Sweongyo	{ 0, 0x11, 0x10, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
713203945Sweongyo	{ 0, 0, 0, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
714203945Sweongyo	{ 0, 0x11, 0x20, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
715203945Sweongyo	{ 0, 0x11, 0x10, 0x84, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
716203945Sweongyo	{ 0, 0x11, 0, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
717203945Sweongyo	{ 0, 0, 0, 0x63, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
718203945Sweongyo	{ 0, 0, 0, 0x62, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
719203945Sweongyo	{ 0, 0, 0, 0x30, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
720203945Sweongyo	{ 0, 0, 0, 0x20, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
721203945Sweongyo	{ 0, 0, 0, 0x10, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
722203945Sweongyo	{ 0, 0, 0, 0, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
723203945Sweongyo	{ 0x55, 0x77, 0x90, 0xf7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
724203945Sweongyo	{ 0x44, 0x77, 0x80, 0xe7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
725203945Sweongyo	{ 0x44, 0x66, 0x80, 0xe7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
726203945Sweongyo	{ 0x33, 0x66, 0x70, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
727203945Sweongyo	{ 0x22, 0x55, 0x60, 0xd7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
728203945Sweongyo	{ 0x22, 0x55, 0x60, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
729203945Sweongyo	{ 0x22, 0x44, 0x50, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
730203945Sweongyo	{ 0x11, 0x44, 0x50, 0xa5, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
731203945Sweongyo	{ 0, 0x44, 0x40, 0xb6, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 }
732203945Sweongyo};
733203945Sweongyo
734203945Sweongyostatic const struct bwn_b206x_chan bwn_b2062_chantable[] = {
735203945Sweongyo	{ 1, 2412, bwn_b2062_chantable_data[0] },
736203945Sweongyo	{ 2, 2417, bwn_b2062_chantable_data[0] },
737203945Sweongyo	{ 3, 2422, bwn_b2062_chantable_data[0] },
738203945Sweongyo	{ 4, 2427, bwn_b2062_chantable_data[0] },
739203945Sweongyo	{ 5, 2432, bwn_b2062_chantable_data[0] },
740203945Sweongyo	{ 6, 2437, bwn_b2062_chantable_data[0] },
741203945Sweongyo	{ 7, 2442, bwn_b2062_chantable_data[0] },
742203945Sweongyo	{ 8, 2447, bwn_b2062_chantable_data[0] },
743203945Sweongyo	{ 9, 2452, bwn_b2062_chantable_data[0] },
744203945Sweongyo	{ 10, 2457, bwn_b2062_chantable_data[0] },
745203945Sweongyo	{ 11, 2462, bwn_b2062_chantable_data[0] },
746203945Sweongyo	{ 12, 2467, bwn_b2062_chantable_data[0] },
747203945Sweongyo	{ 13, 2472, bwn_b2062_chantable_data[0] },
748203945Sweongyo	{ 14, 2484, bwn_b2062_chantable_data[0] },
749203945Sweongyo	{ 34, 5170, bwn_b2062_chantable_data[1] },
750203945Sweongyo	{ 38, 5190, bwn_b2062_chantable_data[2] },
751203945Sweongyo	{ 42, 5210, bwn_b2062_chantable_data[2] },
752203945Sweongyo	{ 46, 5230, bwn_b2062_chantable_data[3] },
753203945Sweongyo	{ 36, 5180, bwn_b2062_chantable_data[4] },
754203945Sweongyo	{ 40, 5200, bwn_b2062_chantable_data[5] },
755203945Sweongyo	{ 44, 5220, bwn_b2062_chantable_data[6] },
756203945Sweongyo	{ 48, 5240, bwn_b2062_chantable_data[3] },
757203945Sweongyo	{ 52, 5260, bwn_b2062_chantable_data[3] },
758203945Sweongyo	{ 56, 5280, bwn_b2062_chantable_data[3] },
759203945Sweongyo	{ 60, 5300, bwn_b2062_chantable_data[7] },
760203945Sweongyo	{ 64, 5320, bwn_b2062_chantable_data[8] },
761203945Sweongyo	{ 100, 5500, bwn_b2062_chantable_data[9] },
762203945Sweongyo	{ 104, 5520, bwn_b2062_chantable_data[10] },
763203945Sweongyo	{ 108, 5540, bwn_b2062_chantable_data[10] },
764203945Sweongyo	{ 112, 5560, bwn_b2062_chantable_data[10] },
765203945Sweongyo	{ 116, 5580, bwn_b2062_chantable_data[11] },
766203945Sweongyo	{ 120, 5600, bwn_b2062_chantable_data[12] },
767203945Sweongyo	{ 124, 5620, bwn_b2062_chantable_data[12] },
768203945Sweongyo	{ 128, 5640, bwn_b2062_chantable_data[12] },
769203945Sweongyo	{ 132, 5660, bwn_b2062_chantable_data[12] },
770203945Sweongyo	{ 136, 5680, bwn_b2062_chantable_data[12] },
771203945Sweongyo	{ 140, 5700, bwn_b2062_chantable_data[12] },
772203945Sweongyo	{ 149, 5745, bwn_b2062_chantable_data[12] },
773203945Sweongyo	{ 153, 5765, bwn_b2062_chantable_data[12] },
774203945Sweongyo	{ 157, 5785, bwn_b2062_chantable_data[12] },
775203945Sweongyo	{ 161, 5805, bwn_b2062_chantable_data[12] },
776203945Sweongyo	{ 165, 5825, bwn_b2062_chantable_data[12] },
777203945Sweongyo	{ 184, 4920, bwn_b2062_chantable_data[13] },
778203945Sweongyo	{ 188, 4940, bwn_b2062_chantable_data[14] },
779203945Sweongyo	{ 192, 4960, bwn_b2062_chantable_data[15] },
780203945Sweongyo	{ 196, 4980, bwn_b2062_chantable_data[16] },
781203945Sweongyo	{ 200, 5000, bwn_b2062_chantable_data[17] },
782203945Sweongyo	{ 204, 5020, bwn_b2062_chantable_data[18] },
783203945Sweongyo	{ 208, 5040, bwn_b2062_chantable_data[19] },
784203945Sweongyo	{ 212, 5060, bwn_b2062_chantable_data[20] },
785203945Sweongyo	{ 216, 5080, bwn_b2062_chantable_data[21] }
786203945Sweongyo};
787203945Sweongyo
788203945Sweongyo/* for LP PHY */
789203945Sweongyostatic const struct bwn_rxcompco bwn_rxcompco_5354[] = {
790203945Sweongyo	{  1, -66, 15 }, {  2, -66, 15 }, {  3, -66, 15 }, {  4, -66, 15 },
791203945Sweongyo	{  5, -66, 15 }, {  6, -66, 15 }, {  7, -66, 14 }, {  8, -66, 14 },
792203945Sweongyo	{  9, -66, 14 }, { 10, -66, 14 }, { 11, -66, 14 }, { 12, -66, 13 },
793203945Sweongyo	{ 13, -66, 13 }, { 14, -66, 13 },
794203945Sweongyo};
795203945Sweongyo
796203945Sweongyo/* for LP PHY */
797203945Sweongyostatic const struct bwn_rxcompco bwn_rxcompco_r12[] = {
798203945Sweongyo	{   1, -64, 13 }, {   2, -64, 13 }, {   3, -64, 13 }, {   4, -64, 13 },
799203945Sweongyo	{   5, -64, 12 }, {   6, -64, 12 }, {   7, -64, 12 }, {   8, -64, 12 },
800203945Sweongyo	{   9, -64, 12 }, {  10, -64, 11 }, {  11, -64, 11 }, {  12, -64, 11 },
801203945Sweongyo	{  13, -64, 11 }, {  14, -64, 10 }, {  34, -62, 24 }, {  38, -62, 24 },
802203945Sweongyo	{  42, -62, 24 }, {  46, -62, 23 }, {  36, -62, 24 }, {  40, -62, 24 },
803203945Sweongyo	{  44, -62, 23 }, {  48, -62, 23 }, {  52, -62, 23 }, {  56, -62, 22 },
804203945Sweongyo	{  60, -62, 22 }, {  64, -62, 22 }, { 100, -62, 16 }, { 104, -62, 16 },
805203945Sweongyo	{ 108, -62, 15 }, { 112, -62, 14 }, { 116, -62, 14 }, { 120, -62, 13 },
806203945Sweongyo	{ 124, -62, 12 }, { 128, -62, 12 }, { 132, -62, 12 }, { 136, -62, 11 },
807203945Sweongyo	{ 140, -62, 10 }, { 149, -61,  9 }, { 153, -61,  9 }, { 157, -61,  9 },
808203945Sweongyo	{ 161, -61,  8 }, { 165, -61,  8 }, { 184, -62, 25 }, { 188, -62, 25 },
809203945Sweongyo	{ 192, -62, 25 }, { 196, -62, 25 }, { 200, -62, 25 }, { 204, -62, 25 },
810203945Sweongyo	{ 208, -62, 25 }, { 212, -62, 25 }, { 216, -62, 26 },
811203945Sweongyo};
812203945Sweongyo
813203945Sweongyostatic const struct bwn_rxcompco bwn_rxcompco_r2 = { 0, -64, 0 };
814203945Sweongyo
815203945Sweongyostatic const uint8_t bwn_tab_sigsq_tbl[] = {
816203945Sweongyo	0xde, 0xdc, 0xda, 0xd8, 0xd6, 0xd4, 0xd2, 0xcf, 0xcd,
817203945Sweongyo	0xca, 0xc7, 0xc4, 0xc1, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
818203945Sweongyo	0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0x00,
819203945Sweongyo	0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
820203945Sweongyo	0xbe, 0xbe, 0xbe, 0xbe, 0xc1, 0xc4, 0xc7, 0xca, 0xcd,
821203945Sweongyo	0xcf, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
822203945Sweongyo};
823203945Sweongyo
824203945Sweongyostatic const uint8_t bwn_tab_pllfrac_tbl[] = {
825203945Sweongyo	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x80,
826203945Sweongyo	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
827203945Sweongyo};
828203945Sweongyo
829203945Sweongyostatic const uint16_t bwn_tabl_iqlocal_tbl[] = {
830203945Sweongyo	0x0200, 0x0300, 0x0400, 0x0600, 0x0800, 0x0b00, 0x1000, 0x1001, 0x1002,
831203945Sweongyo	0x1003, 0x1004, 0x1005, 0x1006, 0x1007, 0x1707, 0x2007, 0x2d07, 0x4007,
832203945Sweongyo	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
833203945Sweongyo	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0200, 0x0300, 0x0400, 0x0600,
834203945Sweongyo	0x0800, 0x0b00, 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006,
835203945Sweongyo	0x1007, 0x1707, 0x2007, 0x2d07, 0x4007, 0x0000, 0x0000, 0x0000, 0x0000,
836203945Sweongyo	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
837203945Sweongyo	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
838203945Sweongyo	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
839203945Sweongyo	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4000, 0x0000, 0x0000,
840203945Sweongyo	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
841203945Sweongyo	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
842203945Sweongyo};
843203945Sweongyo
844203945Sweongyostatic const uint16_t bwn_tab_noise_g1[] = BWN_TAB_NOISE_G1;
845203945Sweongyostatic const uint16_t bwn_tab_noise_g2[] = BWN_TAB_NOISE_G2;
846203945Sweongyostatic const uint16_t bwn_tab_noisescale_g1[] = BWN_TAB_NOISESCALE_G1;
847203945Sweongyostatic const uint16_t bwn_tab_noisescale_g2[] = BWN_TAB_NOISESCALE_G2;
848203945Sweongyostatic const uint16_t bwn_tab_noisescale_g3[] = BWN_TAB_NOISESCALE_G3;
849203945Sweongyoconst uint8_t bwn_bitrev_table[256] = BWN_BITREV_TABLE;
850203945Sweongyo
851203945Sweongyo#define	VENDOR_LED_ACT(vendor)				\
852203945Sweongyo{							\
853203945Sweongyo	.vid = PCI_VENDOR_##vendor,			\
854203945Sweongyo	.led_act = { BWN_VENDOR_LED_ACT_##vendor }	\
855203945Sweongyo}
856203945Sweongyo
857203945Sweongyostatic const struct {
858203945Sweongyo	uint16_t	vid;
859203945Sweongyo	uint8_t		led_act[BWN_LED_MAX];
860203945Sweongyo} bwn_vendor_led_act[] = {
861203945Sweongyo	VENDOR_LED_ACT(COMPAQ),
862203945Sweongyo	VENDOR_LED_ACT(ASUSTEK)
863203945Sweongyo};
864203945Sweongyo
865203945Sweongyostatic const uint8_t bwn_default_led_act[BWN_LED_MAX] =
866203945Sweongyo	{ BWN_VENDOR_LED_ACT_DEFAULT };
867203945Sweongyo
868203945Sweongyo#undef VENDOR_LED_ACT
869203945Sweongyo
870203945Sweongyostatic const struct {
871203945Sweongyo	int		on_dur;
872203945Sweongyo	int		off_dur;
873203945Sweongyo} bwn_led_duration[109] = {
874203945Sweongyo	[0]	= { 400, 100 },
875203945Sweongyo	[2]	= { 150, 75 },
876203945Sweongyo	[4]	= { 90, 45 },
877203945Sweongyo	[11]	= { 66, 34 },
878203945Sweongyo	[12]	= { 53, 26 },
879203945Sweongyo	[18]	= { 42, 21 },
880203945Sweongyo	[22]	= { 35, 17 },
881203945Sweongyo	[24]	= { 32, 16 },
882203945Sweongyo	[36]	= { 21, 10 },
883203945Sweongyo	[48]	= { 16, 8 },
884203945Sweongyo	[72]	= { 11, 5 },
885203945Sweongyo	[96]	= { 9, 4 },
886203945Sweongyo	[108]	= { 7, 3 }
887203945Sweongyo};
888203945Sweongyo
889203945Sweongyostatic const uint16_t bwn_wme_shm_offsets[] = {
890203945Sweongyo	[0] = BWN_WME_BESTEFFORT,
891203945Sweongyo	[1] = BWN_WME_BACKGROUND,
892203945Sweongyo	[2] = BWN_WME_VOICE,
893203945Sweongyo	[3] = BWN_WME_VIDEO,
894203945Sweongyo};
895203945Sweongyo
896203945Sweongyostatic const struct siba_devid bwn_devs[] = {
897203945Sweongyo	SIBA_DEV(BROADCOM, 80211, 5, "Revision 5"),
898203945Sweongyo	SIBA_DEV(BROADCOM, 80211, 6, "Revision 6"),
899203945Sweongyo	SIBA_DEV(BROADCOM, 80211, 7, "Revision 7"),
900203945Sweongyo	SIBA_DEV(BROADCOM, 80211, 9, "Revision 9"),
901203945Sweongyo	SIBA_DEV(BROADCOM, 80211, 10, "Revision 10"),
902203945Sweongyo	SIBA_DEV(BROADCOM, 80211, 11, "Revision 11"),
903203945Sweongyo	SIBA_DEV(BROADCOM, 80211, 13, "Revision 13"),
904203945Sweongyo	SIBA_DEV(BROADCOM, 80211, 15, "Revision 15"),
905203945Sweongyo	SIBA_DEV(BROADCOM, 80211, 16, "Revision 16")
906203945Sweongyo};
907203945Sweongyo
908203945Sweongyostatic int
909203945Sweongyobwn_probe(device_t dev)
910203945Sweongyo{
911203945Sweongyo	int i;
912203945Sweongyo
913203945Sweongyo	for (i = 0; i < sizeof(bwn_devs) / sizeof(bwn_devs[0]); i++) {
914204922Sweongyo		if (siba_get_vendor(dev) == bwn_devs[i].sd_vendor &&
915204922Sweongyo		    siba_get_device(dev) == bwn_devs[i].sd_device &&
916204922Sweongyo		    siba_get_revid(dev) == bwn_devs[i].sd_rev)
917203945Sweongyo			return (BUS_PROBE_DEFAULT);
918203945Sweongyo	}
919203945Sweongyo
920203945Sweongyo	return (ENXIO);
921203945Sweongyo}
922203945Sweongyo
923203945Sweongyostatic int
924203945Sweongyobwn_attach(device_t dev)
925203945Sweongyo{
926203945Sweongyo	struct bwn_mac *mac;
927203945Sweongyo	struct bwn_softc *sc = device_get_softc(dev);
928203945Sweongyo	int error, i, msic, reg;
929203945Sweongyo
930203945Sweongyo	sc->sc_dev = dev;
931203945Sweongyo#ifdef BWN_DEBUG
932203945Sweongyo	sc->sc_debug = bwn_debug;
933203945Sweongyo#endif
934203945Sweongyo
935203945Sweongyo	if ((sc->sc_flags & BWN_FLAG_ATTACHED) == 0) {
936203945Sweongyo		error = bwn_attach_pre(sc);
937203945Sweongyo		if (error != 0)
938203945Sweongyo			return (error);
939204922Sweongyo		bwn_sprom_bugfixes(dev);
940203945Sweongyo		sc->sc_flags |= BWN_FLAG_ATTACHED;
941203945Sweongyo	}
942203945Sweongyo
943203945Sweongyo	if (!TAILQ_EMPTY(&sc->sc_maclist)) {
944204922Sweongyo		if (siba_get_pci_device(dev) != 0x4313 &&
945204922Sweongyo		    siba_get_pci_device(dev) != 0x431a &&
946204922Sweongyo		    siba_get_pci_device(dev) != 0x4321) {
947203945Sweongyo			device_printf(sc->sc_dev,
948203945Sweongyo			    "skip 802.11 cores\n");
949203945Sweongyo			return (ENODEV);
950203945Sweongyo		}
951203945Sweongyo	}
952203945Sweongyo
953203945Sweongyo	mac = (struct bwn_mac *)malloc(sizeof(*mac), M_DEVBUF,
954203945Sweongyo	    M_NOWAIT | M_ZERO);
955203945Sweongyo	if (mac == NULL)
956203945Sweongyo		return (ENOMEM);
957203945Sweongyo	mac->mac_sc = sc;
958203945Sweongyo	mac->mac_status = BWN_MAC_STATUS_UNINIT;
959203945Sweongyo	if (bwn_bfp != 0)
960203945Sweongyo		mac->mac_flags |= BWN_MAC_FLAG_BADFRAME_PREEMP;
961203945Sweongyo
962203945Sweongyo	TASK_INIT(&mac->mac_hwreset, 0, bwn_hwreset, mac);
963203945Sweongyo	TASK_INIT(&mac->mac_intrtask, 0, bwn_intrtask, mac);
964203945Sweongyo	TASK_INIT(&mac->mac_txpower, 0, bwn_txpwr, mac);
965203945Sweongyo
966203945Sweongyo	error = bwn_attach_core(mac);
967203945Sweongyo	if (error)
968203945Sweongyo		goto fail0;
969203945Sweongyo	bwn_led_attach(mac);
970203945Sweongyo
971203945Sweongyo	device_printf(sc->sc_dev, "WLAN (chipid %#x rev %u) "
972203945Sweongyo	    "PHY (analog %d type %d rev %d) RADIO (manuf %#x ver %#x rev %d)\n",
973204922Sweongyo	    siba_get_chipid(sc->sc_dev), siba_get_revid(sc->sc_dev),
974203945Sweongyo	    mac->mac_phy.analog, mac->mac_phy.type, mac->mac_phy.rev,
975203945Sweongyo	    mac->mac_phy.rf_manuf, mac->mac_phy.rf_ver,
976203945Sweongyo	    mac->mac_phy.rf_rev);
977203945Sweongyo	if (mac->mac_flags & BWN_MAC_FLAG_DMA)
978203945Sweongyo		device_printf(sc->sc_dev, "DMA (%d bits)\n",
979203945Sweongyo		    mac->mac_method.dma.dmatype);
980203945Sweongyo	else
981203945Sweongyo		device_printf(sc->sc_dev, "PIO\n");
982203945Sweongyo
983203945Sweongyo	/*
984203945Sweongyo	 * setup PCI resources and interrupt.
985203945Sweongyo	 */
986203945Sweongyo	if (pci_find_extcap(dev, PCIY_EXPRESS, &reg) == 0) {
987203945Sweongyo		msic = pci_msi_count(dev);
988203945Sweongyo		if (bootverbose)
989203945Sweongyo			device_printf(sc->sc_dev, "MSI count : %d\n", msic);
990203945Sweongyo	} else
991203945Sweongyo		msic = 0;
992203945Sweongyo
993203945Sweongyo	mac->mac_intr_spec = bwn_res_spec_legacy;
994203945Sweongyo	if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0) {
995203945Sweongyo		if (pci_alloc_msi(dev, &msic) == 0) {
996203945Sweongyo			device_printf(sc->sc_dev,
997203945Sweongyo			    "Using %d MSI messages\n", msic);
998203945Sweongyo			mac->mac_intr_spec = bwn_res_spec_msi;
999203945Sweongyo			mac->mac_msi = 1;
1000203945Sweongyo		}
1001203945Sweongyo	}
1002203945Sweongyo
1003203945Sweongyo	error = bus_alloc_resources(dev, mac->mac_intr_spec,
1004203945Sweongyo	    mac->mac_res_irq);
1005203945Sweongyo	if (error) {
1006203945Sweongyo		device_printf(sc->sc_dev,
1007203945Sweongyo		    "couldn't allocate IRQ resources (%d)\n", error);
1008203945Sweongyo		goto fail1;
1009203945Sweongyo	}
1010203945Sweongyo
1011203945Sweongyo	if (mac->mac_msi == 0)
1012203945Sweongyo		error = bus_setup_intr(dev, mac->mac_res_irq[0],
1013203945Sweongyo		    INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac,
1014203945Sweongyo		    &mac->mac_intrhand[0]);
1015203945Sweongyo	else {
1016203945Sweongyo		for (i = 0; i < BWN_MSI_MESSAGES; i++) {
1017203945Sweongyo			error = bus_setup_intr(dev, mac->mac_res_irq[i],
1018203945Sweongyo			    INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac,
1019203945Sweongyo			    &mac->mac_intrhand[i]);
1020203945Sweongyo			if (error != 0) {
1021203945Sweongyo				device_printf(sc->sc_dev,
1022203945Sweongyo				    "couldn't setup interrupt (%d)\n", error);
1023203945Sweongyo				break;
1024203945Sweongyo			}
1025203945Sweongyo		}
1026203945Sweongyo	}
1027203945Sweongyo
1028203945Sweongyo	TAILQ_INSERT_TAIL(&sc->sc_maclist, mac, mac_list);
1029203945Sweongyo
1030203945Sweongyo	/*
1031203945Sweongyo	 * calls attach-post routine
1032203945Sweongyo	 */
1033203945Sweongyo	if ((sc->sc_flags & BWN_FLAG_ATTACHED) != 0)
1034203945Sweongyo		bwn_attach_post(sc);
1035203945Sweongyo
1036203945Sweongyo	return (0);
1037203945Sweongyofail1:
1038203945Sweongyo	if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0)
1039203945Sweongyo		pci_release_msi(dev);
1040203945Sweongyofail0:
1041203945Sweongyo	free(mac, M_DEVBUF);
1042203945Sweongyo	return (error);
1043203945Sweongyo}
1044203945Sweongyo
1045203945Sweongyostatic int
1046203945Sweongyobwn_is_valid_ether_addr(uint8_t *addr)
1047203945Sweongyo{
1048203945Sweongyo	char zero_addr[6] = { 0, 0, 0, 0, 0, 0 };
1049203945Sweongyo
1050203945Sweongyo	if ((addr[0] & 1) || (!bcmp(addr, zero_addr, ETHER_ADDR_LEN)))
1051203945Sweongyo		return (FALSE);
1052203945Sweongyo
1053203945Sweongyo	return (TRUE);
1054203945Sweongyo}
1055203945Sweongyo
1056203945Sweongyostatic int
1057203945Sweongyobwn_attach_post(struct bwn_softc *sc)
1058203945Sweongyo{
1059203945Sweongyo	struct ieee80211com *ic;
1060203945Sweongyo	struct ifnet *ifp = sc->sc_ifp;
1061203945Sweongyo
1062203945Sweongyo	ic = ifp->if_l2com;
1063203945Sweongyo	ic->ic_ifp = ifp;
1064203945Sweongyo	/* XXX not right but it's not used anywhere important */
1065203945Sweongyo	ic->ic_phytype = IEEE80211_T_OFDM;
1066203945Sweongyo	ic->ic_opmode = IEEE80211_M_STA;
1067203945Sweongyo	ic->ic_caps =
1068203945Sweongyo		  IEEE80211_C_STA		/* station mode supported */
1069203945Sweongyo		| IEEE80211_C_MONITOR		/* monitor mode */
1070204436Sweongyo		| IEEE80211_C_AHDEMO		/* adhoc demo mode */
1071203945Sweongyo		| IEEE80211_C_SHPREAMBLE	/* short preamble supported */
1072203945Sweongyo		| IEEE80211_C_SHSLOT		/* short slot time supported */
1073203945Sweongyo		| IEEE80211_C_WME		/* WME/WMM supported */
1074203945Sweongyo		| IEEE80211_C_WPA		/* capable of WPA1+WPA2 */
1075203945Sweongyo		| IEEE80211_C_BGSCAN		/* capable of bg scanning */
1076203945Sweongyo		| IEEE80211_C_TXPMGT		/* capable of txpow mgt */
1077203945Sweongyo		;
1078203945Sweongyo
1079203945Sweongyo	/* call MI attach routine. */
1080203945Sweongyo	ieee80211_ifattach(ic,
1081204922Sweongyo	    bwn_is_valid_ether_addr(siba_sprom_get_mac_80211a(sc->sc_dev)) ?
1082204922Sweongyo	    siba_sprom_get_mac_80211a(sc->sc_dev) :
1083204922Sweongyo	    siba_sprom_get_mac_80211bg(sc->sc_dev));
1084203945Sweongyo
1085203945Sweongyo	ic->ic_headroom = sizeof(struct bwn_txhdr);
1086203945Sweongyo
1087203945Sweongyo	/* override default methods */
1088203945Sweongyo	ic->ic_raw_xmit = bwn_raw_xmit;
1089203945Sweongyo	ic->ic_newassoc = bwn_newassoc;
1090203945Sweongyo	ic->ic_updateslot = bwn_updateslot;
1091203945Sweongyo	ic->ic_update_promisc = bwn_update_promisc;
1092203945Sweongyo	ic->ic_wme.wme_update = bwn_wme_update;
1093203945Sweongyo
1094203945Sweongyo	ic->ic_node_alloc = bwn_node_alloc;
1095203945Sweongyo	sc->sc_node_cleanup = ic->ic_node_cleanup;
1096203945Sweongyo	ic->ic_node_cleanup = bwn_node_cleanup;
1097203945Sweongyo
1098203945Sweongyo	ic->ic_scan_start = bwn_scan_start;
1099203945Sweongyo	ic->ic_scan_end = bwn_scan_end;
1100203945Sweongyo	ic->ic_set_channel = bwn_set_channel;
1101203945Sweongyo
1102203945Sweongyo	ic->ic_vap_create = bwn_vap_create;
1103203945Sweongyo	ic->ic_vap_delete = bwn_vap_delete;
1104203945Sweongyo
1105203945Sweongyo	ieee80211_radiotap_attach(ic,
1106203945Sweongyo	    &sc->sc_tx_th.wt_ihdr, sizeof(sc->sc_tx_th),
1107203945Sweongyo	    BWN_TX_RADIOTAP_PRESENT,
1108203945Sweongyo	    &sc->sc_rx_th.wr_ihdr, sizeof(sc->sc_rx_th),
1109203945Sweongyo	    BWN_RX_RADIOTAP_PRESENT);
1110203945Sweongyo
1111204257Sweongyo	bwn_sysctl_node(sc);
1112203945Sweongyo
1113203945Sweongyo	if (bootverbose)
1114203945Sweongyo		ieee80211_announce(ic);
1115203945Sweongyo	return (0);
1116203945Sweongyo}
1117203945Sweongyo
1118203945Sweongyostatic void
1119203945Sweongyobwn_phy_detach(struct bwn_mac *mac)
1120203945Sweongyo{
1121203945Sweongyo
1122203945Sweongyo	if (mac->mac_phy.detach != NULL)
1123203945Sweongyo		mac->mac_phy.detach(mac);
1124203945Sweongyo}
1125203945Sweongyo
1126203945Sweongyostatic int
1127203945Sweongyobwn_detach(device_t dev)
1128203945Sweongyo{
1129203945Sweongyo	struct bwn_softc *sc = device_get_softc(dev);
1130203945Sweongyo	struct bwn_mac *mac = sc->sc_curmac;
1131203945Sweongyo	struct ifnet *ifp = sc->sc_ifp;
1132203945Sweongyo	struct ieee80211com *ic = ifp->if_l2com;
1133203945Sweongyo	int i;
1134203945Sweongyo
1135203945Sweongyo	sc->sc_flags |= BWN_FLAG_INVALID;
1136203945Sweongyo
1137203945Sweongyo	if (device_is_attached(sc->sc_dev)) {
1138203945Sweongyo		bwn_stop(sc, 1);
1139203945Sweongyo		bwn_dma_free(mac);
1140203945Sweongyo		callout_drain(&sc->sc_led_blink_ch);
1141203945Sweongyo		callout_drain(&sc->sc_rfswitch_ch);
1142203945Sweongyo		callout_drain(&sc->sc_task_ch);
1143203945Sweongyo		callout_drain(&sc->sc_watchdog_ch);
1144203945Sweongyo		bwn_phy_detach(mac);
1145203945Sweongyo		if (ifp != NULL) {
1146203945Sweongyo			ieee80211_draintask(ic, &mac->mac_hwreset);
1147203945Sweongyo			ieee80211_draintask(ic, &mac->mac_txpower);
1148203945Sweongyo			ieee80211_ifdetach(ic);
1149203945Sweongyo			if_free(ifp);
1150203945Sweongyo		}
1151203945Sweongyo	}
1152203945Sweongyo	taskqueue_drain(sc->sc_tq, &mac->mac_intrtask);
1153203945Sweongyo	taskqueue_free(sc->sc_tq);
1154203945Sweongyo
1155203945Sweongyo	for (i = 0; i < BWN_MSI_MESSAGES; i++) {
1156203945Sweongyo		if (mac->mac_intrhand[i] != NULL) {
1157203945Sweongyo			bus_teardown_intr(dev, mac->mac_res_irq[i],
1158203945Sweongyo			    mac->mac_intrhand[i]);
1159203945Sweongyo			mac->mac_intrhand[i] = NULL;
1160203945Sweongyo		}
1161203945Sweongyo	}
1162203945Sweongyo	bus_release_resources(dev, mac->mac_intr_spec, mac->mac_res_irq);
1163203945Sweongyo	if (mac->mac_msi != 0)
1164203945Sweongyo		pci_release_msi(dev);
1165203945Sweongyo
1166203945Sweongyo	BWN_LOCK_DESTROY(sc);
1167203945Sweongyo	return (0);
1168203945Sweongyo}
1169203945Sweongyo
1170203945Sweongyostatic int
1171203945Sweongyobwn_attach_pre(struct bwn_softc *sc)
1172203945Sweongyo{
1173203945Sweongyo	struct ifnet *ifp;
1174203945Sweongyo	int error = 0;
1175203945Sweongyo
1176203945Sweongyo	BWN_LOCK_INIT(sc);
1177203945Sweongyo	TAILQ_INIT(&sc->sc_maclist);
1178203945Sweongyo	callout_init_mtx(&sc->sc_rfswitch_ch, &sc->sc_mtx, 0);
1179203945Sweongyo	callout_init_mtx(&sc->sc_task_ch, &sc->sc_mtx, 0);
1180203945Sweongyo	callout_init_mtx(&sc->sc_watchdog_ch, &sc->sc_mtx, 0);
1181203945Sweongyo
1182203945Sweongyo	sc->sc_tq = taskqueue_create_fast("bwn_taskq", M_NOWAIT,
1183203945Sweongyo		taskqueue_thread_enqueue, &sc->sc_tq);
1184203945Sweongyo	taskqueue_start_threads(&sc->sc_tq, 1, PI_NET,
1185203945Sweongyo		"%s taskq", device_get_nameunit(sc->sc_dev));
1186203945Sweongyo
1187203945Sweongyo	ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
1188203945Sweongyo	if (ifp == NULL) {
1189203945Sweongyo		device_printf(sc->sc_dev, "can not if_alloc()\n");
1190203945Sweongyo		error = ENOSPC;
1191203945Sweongyo		goto fail;
1192203945Sweongyo	}
1193203945Sweongyo
1194203945Sweongyo	/* set these up early for if_printf use */
1195203945Sweongyo	if_initname(ifp, device_get_name(sc->sc_dev),
1196203945Sweongyo	    device_get_unit(sc->sc_dev));
1197203945Sweongyo
1198203945Sweongyo	ifp->if_softc = sc;
1199203945Sweongyo	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
1200203945Sweongyo	ifp->if_init = bwn_init;
1201203945Sweongyo	ifp->if_ioctl = bwn_ioctl;
1202203945Sweongyo	ifp->if_start = bwn_start;
1203203945Sweongyo	IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
1204203945Sweongyo	ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
1205203945Sweongyo	IFQ_SET_READY(&ifp->if_snd);
1206203945Sweongyo
1207203945Sweongyo	return (0);
1208203945Sweongyo
1209203945Sweongyofail:	BWN_LOCK_DESTROY(sc);
1210203945Sweongyo	return (error);
1211203945Sweongyo}
1212203945Sweongyo
1213203945Sweongyostatic void
1214204922Sweongyobwn_sprom_bugfixes(device_t dev)
1215203945Sweongyo{
1216203945Sweongyo#define	BWN_ISDEV(_vendor, _device, _subvendor, _subdevice)		\
1217204922Sweongyo	((siba_get_pci_vendor(dev) == PCI_VENDOR_##_vendor) &&		\
1218204922Sweongyo	 (siba_get_pci_device(dev) == _device) &&			\
1219204922Sweongyo	 (siba_get_pci_subvendor(dev) == PCI_VENDOR_##_subvendor) &&	\
1220204922Sweongyo	 (siba_get_pci_subdevice(dev) == _subdevice))
1221203945Sweongyo
1222204922Sweongyo	if (siba_get_pci_subvendor(dev) == PCI_VENDOR_APPLE &&
1223204922Sweongyo	    siba_get_pci_subdevice(dev) == 0x4e &&
1224204922Sweongyo	    siba_get_pci_revid(dev) > 0x40)
1225204922Sweongyo		siba_sprom_set_bf_lo(dev,
1226204922Sweongyo		    siba_sprom_get_bf_lo(dev) | BWN_BFL_PACTRL);
1227204922Sweongyo	if (siba_get_pci_subvendor(dev) == SIBA_BOARDVENDOR_DELL &&
1228204922Sweongyo	    siba_get_chipid(dev) == 0x4301 && siba_get_pci_revid(dev) == 0x74)
1229204922Sweongyo		siba_sprom_set_bf_lo(dev,
1230204922Sweongyo		    siba_sprom_get_bf_lo(dev) | BWN_BFL_BTCOEXIST);
1231204922Sweongyo	if (siba_get_type(dev) == SIBA_TYPE_PCI) {
1232203945Sweongyo		if (BWN_ISDEV(BROADCOM, 0x4318, ASUSTEK, 0x100f) ||
1233203945Sweongyo		    BWN_ISDEV(BROADCOM, 0x4320, DELL, 0x0003) ||
1234203945Sweongyo		    BWN_ISDEV(BROADCOM, 0x4320, HP, 0x12f8) ||
1235203945Sweongyo		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0013) ||
1236203945Sweongyo		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0014) ||
1237203945Sweongyo		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0015) ||
1238203945Sweongyo		    BWN_ISDEV(BROADCOM, 0x4320, MOTOROLA, 0x7010))
1239204922Sweongyo			siba_sprom_set_bf_lo(dev,
1240204922Sweongyo			    siba_sprom_get_bf_lo(dev) & ~BWN_BFL_BTCOEXIST);
1241203945Sweongyo	}
1242203945Sweongyo#undef	BWN_ISDEV
1243203945Sweongyo}
1244203945Sweongyo
1245203945Sweongyostatic int
1246203945Sweongyobwn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1247203945Sweongyo{
1248203945Sweongyo#define	IS_RUNNING(ifp) \
1249203945Sweongyo	((ifp->if_flags & IFF_UP) && (ifp->if_drv_flags & IFF_DRV_RUNNING))
1250203945Sweongyo	struct bwn_softc *sc = ifp->if_softc;
1251203945Sweongyo	struct ieee80211com *ic = ifp->if_l2com;
1252203945Sweongyo	struct ifreq *ifr = (struct ifreq *)data;
1253203945Sweongyo	int error = 0, startall;
1254203945Sweongyo
1255203945Sweongyo	switch (cmd) {
1256203945Sweongyo	case SIOCSIFFLAGS:
1257203945Sweongyo		startall = 0;
1258203945Sweongyo		if (IS_RUNNING(ifp)) {
1259203945Sweongyo			bwn_update_promisc(ifp);
1260203945Sweongyo		} else if (ifp->if_flags & IFF_UP) {
1261203945Sweongyo			if ((sc->sc_flags & BWN_FLAG_INVALID) == 0) {
1262203945Sweongyo				bwn_init(sc);
1263203945Sweongyo				startall = 1;
1264203945Sweongyo			}
1265203945Sweongyo		} else
1266203945Sweongyo			bwn_stop(sc, 1);
1267203945Sweongyo		if (startall)
1268203945Sweongyo			ieee80211_start_all(ic);
1269203945Sweongyo		break;
1270203945Sweongyo	case SIOCGIFMEDIA:
1271203945Sweongyo		error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
1272203945Sweongyo		break;
1273203945Sweongyo	case SIOCGIFADDR:
1274203945Sweongyo		error = ether_ioctl(ifp, cmd, data);
1275203945Sweongyo		break;
1276203945Sweongyo	default:
1277203945Sweongyo		error = EINVAL;
1278203945Sweongyo		break;
1279203945Sweongyo	}
1280203945Sweongyo	return (error);
1281203945Sweongyo}
1282203945Sweongyo
1283203945Sweongyostatic void
1284203945Sweongyobwn_start(struct ifnet *ifp)
1285203945Sweongyo{
1286203945Sweongyo	struct bwn_softc *sc = ifp->if_softc;
1287203945Sweongyo
1288203945Sweongyo	BWN_LOCK(sc);
1289203945Sweongyo	bwn_start_locked(ifp);
1290203945Sweongyo	BWN_UNLOCK(sc);
1291203945Sweongyo}
1292203945Sweongyo
1293203945Sweongyostatic void
1294203945Sweongyobwn_start_locked(struct ifnet *ifp)
1295203945Sweongyo{
1296203945Sweongyo	struct bwn_softc *sc = ifp->if_softc;
1297203945Sweongyo	struct bwn_mac *mac = sc->sc_curmac;
1298203945Sweongyo	struct ieee80211_frame *wh;
1299203945Sweongyo	struct ieee80211_node *ni;
1300203945Sweongyo	struct ieee80211_key *k;
1301203945Sweongyo	struct mbuf *m;
1302203945Sweongyo
1303203945Sweongyo	BWN_ASSERT_LOCKED(sc);
1304203945Sweongyo
1305203945Sweongyo	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || mac == NULL ||
1306203945Sweongyo	    mac->mac_status < BWN_MAC_STATUS_STARTED)
1307203945Sweongyo		return;
1308203945Sweongyo
1309203945Sweongyo	for (;;) {
1310203945Sweongyo		IFQ_DRV_DEQUEUE(&ifp->if_snd, m);	/* XXX: LOCK */
1311203945Sweongyo		if (m == NULL)
1312203945Sweongyo			break;
1313203945Sweongyo
1314203945Sweongyo		if (bwn_tx_isfull(sc, m))
1315203945Sweongyo			break;
1316203945Sweongyo		ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
1317203945Sweongyo		if (ni == NULL) {
1318203945Sweongyo			device_printf(sc->sc_dev, "unexpected NULL ni\n");
1319203945Sweongyo			m_freem(m);
1320203945Sweongyo			ifp->if_oerrors++;
1321203945Sweongyo			continue;
1322203945Sweongyo		}
1323203945Sweongyo		KASSERT(ni != NULL, ("%s:%d: fail", __func__, __LINE__));
1324203945Sweongyo		wh = mtod(m, struct ieee80211_frame *);
1325203945Sweongyo		if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
1326203945Sweongyo			k = ieee80211_crypto_encap(ni, m);
1327203945Sweongyo			if (k == NULL) {
1328203945Sweongyo				ieee80211_free_node(ni);
1329203945Sweongyo				m_freem(m);
1330203945Sweongyo				ifp->if_oerrors++;
1331203945Sweongyo				continue;
1332203945Sweongyo			}
1333203945Sweongyo		}
1334203945Sweongyo		wh = NULL;	/* Catch any invalid use */
1335203945Sweongyo
1336203945Sweongyo		if (bwn_tx_start(sc, ni, m) != 0) {
1337203945Sweongyo			if (ni != NULL)
1338203945Sweongyo				ieee80211_free_node(ni);
1339203945Sweongyo			ifp->if_oerrors++;
1340203945Sweongyo			continue;
1341203945Sweongyo		}
1342203945Sweongyo
1343203945Sweongyo		sc->sc_watchdog_timer = 5;
1344203945Sweongyo	}
1345203945Sweongyo}
1346203945Sweongyo
1347203945Sweongyostatic int
1348203945Sweongyobwn_tx_isfull(struct bwn_softc *sc, struct mbuf *m)
1349203945Sweongyo{
1350203945Sweongyo	struct bwn_dma_ring *dr;
1351203945Sweongyo	struct bwn_mac *mac = sc->sc_curmac;
1352203945Sweongyo	struct bwn_pio_txqueue *tq;
1353203945Sweongyo	struct ifnet *ifp = sc->sc_ifp;
1354203945Sweongyo	int pktlen = roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1355203945Sweongyo
1356203945Sweongyo	BWN_ASSERT_LOCKED(sc);
1357203945Sweongyo
1358203945Sweongyo	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
1359203945Sweongyo		dr = bwn_dma_select(mac, M_WME_GETAC(m));
1360203945Sweongyo		if (dr->dr_stop == 1 ||
1361203945Sweongyo		    bwn_dma_freeslot(dr) < BWN_TX_SLOTS_PER_FRAME) {
1362203945Sweongyo			dr->dr_stop = 1;
1363203945Sweongyo			goto full;
1364203945Sweongyo		}
1365203945Sweongyo	} else {
1366203945Sweongyo		tq = bwn_pio_select(mac, M_WME_GETAC(m));
1367203945Sweongyo		if (tq->tq_free == 0 || pktlen > tq->tq_size ||
1368203945Sweongyo		    pktlen > (tq->tq_size - tq->tq_used)) {
1369203945Sweongyo			tq->tq_stop = 1;
1370203945Sweongyo			goto full;
1371203945Sweongyo		}
1372203945Sweongyo	}
1373203945Sweongyo	return (0);
1374203945Sweongyofull:
1375203945Sweongyo	IFQ_DRV_PREPEND(&ifp->if_snd, m);
1376203945Sweongyo	ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1377203945Sweongyo	return (1);
1378203945Sweongyo}
1379203945Sweongyo
1380203945Sweongyostatic int
1381203945Sweongyobwn_tx_start(struct bwn_softc *sc, struct ieee80211_node *ni, struct mbuf *m)
1382203945Sweongyo{
1383203945Sweongyo	struct bwn_mac *mac = sc->sc_curmac;
1384203945Sweongyo	int error;
1385203945Sweongyo
1386203945Sweongyo	BWN_ASSERT_LOCKED(sc);
1387203945Sweongyo
1388203945Sweongyo	if (m->m_pkthdr.len < IEEE80211_MIN_LEN || mac == NULL) {
1389203945Sweongyo		m_freem(m);
1390203945Sweongyo		return (ENXIO);
1391203945Sweongyo	}
1392203945Sweongyo
1393203945Sweongyo	error = (mac->mac_flags & BWN_MAC_FLAG_DMA) ?
1394203945Sweongyo	    bwn_dma_tx_start(mac, ni, m) : bwn_pio_tx_start(mac, ni, m);
1395203945Sweongyo	if (error) {
1396203945Sweongyo		m_freem(m);
1397203945Sweongyo		return (error);
1398203945Sweongyo	}
1399203945Sweongyo	return (0);
1400203945Sweongyo}
1401203945Sweongyo
1402203945Sweongyostatic int
1403203945Sweongyobwn_pio_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1404203945Sweongyo{
1405203945Sweongyo	struct bwn_pio_txpkt *tp;
1406203945Sweongyo	struct bwn_pio_txqueue *tq = bwn_pio_select(mac, M_WME_GETAC(m));
1407203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
1408203945Sweongyo	struct bwn_txhdr txhdr;
1409203945Sweongyo	struct mbuf *m_new;
1410203945Sweongyo	uint32_t ctl32;
1411203945Sweongyo	int error;
1412203945Sweongyo	uint16_t ctl16;
1413203945Sweongyo
1414203945Sweongyo	BWN_ASSERT_LOCKED(sc);
1415203945Sweongyo
1416203945Sweongyo	/* XXX TODO send packets after DTIM */
1417203945Sweongyo
1418203945Sweongyo	KASSERT(!TAILQ_EMPTY(&tq->tq_pktlist), ("%s: fail", __func__));
1419203945Sweongyo	tp = TAILQ_FIRST(&tq->tq_pktlist);
1420203945Sweongyo	tp->tp_ni = ni;
1421203945Sweongyo	tp->tp_m = m;
1422203945Sweongyo
1423203945Sweongyo	error = bwn_set_txhdr(mac, ni, m, &txhdr, BWN_PIO_COOKIE(tq, tp));
1424203945Sweongyo	if (error) {
1425203945Sweongyo		device_printf(sc->sc_dev, "tx fail\n");
1426203945Sweongyo		return (error);
1427203945Sweongyo	}
1428203945Sweongyo
1429203945Sweongyo	TAILQ_REMOVE(&tq->tq_pktlist, tp, tp_list);
1430203945Sweongyo	tq->tq_used += roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1431203945Sweongyo	tq->tq_free--;
1432203945Sweongyo
1433204922Sweongyo	if (siba_get_revid(sc->sc_dev) >= 8) {
1434203945Sweongyo		/*
1435203945Sweongyo		 * XXX please removes m_defrag(9)
1436203945Sweongyo		 */
1437203945Sweongyo		m_new = m_defrag(m, M_DONTWAIT);
1438203945Sweongyo		if (m_new == NULL) {
1439203945Sweongyo			device_printf(sc->sc_dev,
1440203945Sweongyo			    "%s: can't defrag TX buffer\n",
1441203945Sweongyo			    __func__);
1442203945Sweongyo			return (ENOBUFS);
1443203945Sweongyo		}
1444203945Sweongyo		if (m_new->m_next != NULL)
1445203945Sweongyo			device_printf(sc->sc_dev,
1446203945Sweongyo			    "TODO: fragmented packets for PIO\n");
1447203945Sweongyo		tp->tp_m = m_new;
1448203945Sweongyo
1449203945Sweongyo		/* send HEADER */
1450203945Sweongyo		ctl32 = bwn_pio_write_multi_4(mac, tq,
1451203945Sweongyo		    (BWN_PIO_READ_4(mac, tq, BWN_PIO8_TXCTL) |
1452203945Sweongyo			BWN_PIO8_TXCTL_FRAMEREADY) & ~BWN_PIO8_TXCTL_EOF,
1453203945Sweongyo		    (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1454203945Sweongyo		/* send BODY */
1455203945Sweongyo		ctl32 = bwn_pio_write_multi_4(mac, tq, ctl32,
1456203945Sweongyo		    mtod(m_new, const void *), m_new->m_pkthdr.len);
1457203945Sweongyo		bwn_pio_write_4(mac, tq, BWN_PIO_TXCTL,
1458203945Sweongyo		    ctl32 | BWN_PIO8_TXCTL_EOF);
1459203945Sweongyo	} else {
1460203945Sweongyo		ctl16 = bwn_pio_write_multi_2(mac, tq,
1461203945Sweongyo		    (bwn_pio_read_2(mac, tq, BWN_PIO_TXCTL) |
1462203945Sweongyo			BWN_PIO_TXCTL_FRAMEREADY) & ~BWN_PIO_TXCTL_EOF,
1463203945Sweongyo		    (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1464203945Sweongyo		ctl16 = bwn_pio_write_mbuf_2(mac, tq, ctl16, m);
1465203945Sweongyo		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL,
1466203945Sweongyo		    ctl16 | BWN_PIO_TXCTL_EOF);
1467203945Sweongyo	}
1468203945Sweongyo
1469203945Sweongyo	return (0);
1470203945Sweongyo}
1471203945Sweongyo
1472203945Sweongyostatic struct bwn_pio_txqueue *
1473203945Sweongyobwn_pio_select(struct bwn_mac *mac, uint8_t prio)
1474203945Sweongyo{
1475203945Sweongyo
1476203945Sweongyo	if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
1477203945Sweongyo		return (&mac->mac_method.pio.wme[WME_AC_BE]);
1478203945Sweongyo
1479203945Sweongyo	switch (prio) {
1480203945Sweongyo	case 0:
1481203945Sweongyo		return (&mac->mac_method.pio.wme[WME_AC_BE]);
1482203945Sweongyo	case 1:
1483203945Sweongyo		return (&mac->mac_method.pio.wme[WME_AC_BK]);
1484203945Sweongyo	case 2:
1485203945Sweongyo		return (&mac->mac_method.pio.wme[WME_AC_VI]);
1486203945Sweongyo	case 3:
1487203945Sweongyo		return (&mac->mac_method.pio.wme[WME_AC_VO]);
1488203945Sweongyo	}
1489203945Sweongyo	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
1490204242Simp	return (NULL);
1491203945Sweongyo}
1492203945Sweongyo
1493203945Sweongyostatic int
1494203945Sweongyobwn_dma_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1495203945Sweongyo{
1496203945Sweongyo#define	BWN_GET_TXHDRCACHE(slot)					\
1497203945Sweongyo	&(txhdr_cache[(slot / BWN_TX_SLOTS_PER_FRAME) * BWN_HDRSIZE(mac)])
1498203945Sweongyo	struct bwn_dma *dma = &mac->mac_method.dma;
1499203945Sweongyo	struct bwn_dma_ring *dr = bwn_dma_select(mac, M_WME_GETAC(m));
1500203945Sweongyo	struct bwn_dmadesc_generic *desc;
1501203945Sweongyo	struct bwn_dmadesc_meta *mt;
1502203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
1503203945Sweongyo	struct ifnet *ifp = sc->sc_ifp;
1504203945Sweongyo	uint8_t *txhdr_cache = (uint8_t *)dr->dr_txhdr_cache;
1505203945Sweongyo	int error, slot, backup[2] = { dr->dr_curslot, dr->dr_usedslot };
1506203945Sweongyo
1507203945Sweongyo	BWN_ASSERT_LOCKED(sc);
1508203945Sweongyo	KASSERT(!dr->dr_stop, ("%s:%d: fail", __func__, __LINE__));
1509203945Sweongyo
1510203945Sweongyo	/* XXX send after DTIM */
1511203945Sweongyo
1512203945Sweongyo	slot = bwn_dma_getslot(dr);
1513203945Sweongyo	dr->getdesc(dr, slot, &desc, &mt);
1514203945Sweongyo	KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_HEADER,
1515203945Sweongyo	    ("%s:%d: fail", __func__, __LINE__));
1516203945Sweongyo
1517203945Sweongyo	error = bwn_set_txhdr(dr->dr_mac, ni, m,
1518203945Sweongyo	    (struct bwn_txhdr *)BWN_GET_TXHDRCACHE(slot),
1519203945Sweongyo	    BWN_DMA_COOKIE(dr, slot));
1520203945Sweongyo	if (error)
1521203945Sweongyo		goto fail;
1522203945Sweongyo	error = bus_dmamap_load(dr->dr_txring_dtag, mt->mt_dmap,
1523203945Sweongyo	    BWN_GET_TXHDRCACHE(slot), BWN_HDRSIZE(mac), bwn_dma_ring_addr,
1524203945Sweongyo	    &mt->mt_paddr, BUS_DMA_NOWAIT);
1525203945Sweongyo	if (error) {
1526203945Sweongyo		if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
1527203945Sweongyo		    __func__, error);
1528203945Sweongyo		goto fail;
1529203945Sweongyo	}
1530203945Sweongyo	bus_dmamap_sync(dr->dr_txring_dtag, mt->mt_dmap,
1531203945Sweongyo	    BUS_DMASYNC_PREWRITE);
1532203945Sweongyo	dr->setdesc(dr, desc, mt->mt_paddr, BWN_HDRSIZE(mac), 1, 0, 0);
1533203945Sweongyo	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1534203945Sweongyo	    BUS_DMASYNC_PREWRITE);
1535203945Sweongyo
1536203945Sweongyo	slot = bwn_dma_getslot(dr);
1537203945Sweongyo	dr->getdesc(dr, slot, &desc, &mt);
1538203945Sweongyo	KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_BODY &&
1539203945Sweongyo	    mt->mt_islast == 1, ("%s:%d: fail", __func__, __LINE__));
1540203945Sweongyo	mt->mt_m = m;
1541203945Sweongyo	mt->mt_ni = ni;
1542203945Sweongyo
1543203945Sweongyo	error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap, m,
1544203945Sweongyo	    bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1545203945Sweongyo	if (error && error != EFBIG) {
1546203945Sweongyo		if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
1547203945Sweongyo		    __func__, error);
1548203945Sweongyo		goto fail;
1549203945Sweongyo	}
1550203945Sweongyo	if (error) {    /* error == EFBIG */
1551203945Sweongyo		struct mbuf *m_new;
1552203945Sweongyo
1553203945Sweongyo		m_new = m_defrag(m, M_DONTWAIT);
1554203945Sweongyo		if (m_new == NULL) {
1555203945Sweongyo			if_printf(ifp, "%s: can't defrag TX buffer\n",
1556203945Sweongyo			    __func__);
1557203945Sweongyo			error = ENOBUFS;
1558203945Sweongyo			goto fail;
1559203945Sweongyo		} else {
1560203945Sweongyo			m = m_new;
1561203945Sweongyo		}
1562203945Sweongyo
1563203945Sweongyo		mt->mt_m = m;
1564203945Sweongyo		error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap,
1565203945Sweongyo		    m, bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1566203945Sweongyo		if (error) {
1567203945Sweongyo			if_printf(ifp, "%s: can't load TX buffer (2) %d\n",
1568203945Sweongyo			    __func__, error);
1569203945Sweongyo			goto fail;
1570203945Sweongyo		}
1571203945Sweongyo	}
1572203945Sweongyo	bus_dmamap_sync(dma->txbuf_dtag, mt->mt_dmap, BUS_DMASYNC_PREWRITE);
1573203945Sweongyo	dr->setdesc(dr, desc, mt->mt_paddr, m->m_pkthdr.len, 0, 1, 1);
1574203945Sweongyo	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1575203945Sweongyo	    BUS_DMASYNC_PREWRITE);
1576203945Sweongyo
1577203945Sweongyo	/* XXX send after DTIM */
1578203945Sweongyo
1579203945Sweongyo	dr->start_transfer(dr, bwn_dma_nextslot(dr, slot));
1580203945Sweongyo	return (0);
1581203945Sweongyofail:
1582203945Sweongyo	dr->dr_curslot = backup[0];
1583203945Sweongyo	dr->dr_usedslot = backup[1];
1584203945Sweongyo	return (error);
1585203945Sweongyo#undef BWN_GET_TXHDRCACHE
1586203945Sweongyo}
1587203945Sweongyo
1588203945Sweongyostatic void
1589203945Sweongyobwn_watchdog(void *arg)
1590203945Sweongyo{
1591203945Sweongyo	struct bwn_softc *sc = arg;
1592203945Sweongyo	struct ifnet *ifp = sc->sc_ifp;
1593203945Sweongyo
1594203945Sweongyo	if (sc->sc_watchdog_timer != 0 && --sc->sc_watchdog_timer == 0) {
1595203945Sweongyo		if_printf(ifp, "device timeout\n");
1596203945Sweongyo		ifp->if_oerrors++;
1597203945Sweongyo	}
1598203945Sweongyo	callout_schedule(&sc->sc_watchdog_ch, hz);
1599203945Sweongyo}
1600203945Sweongyo
1601203945Sweongyostatic int
1602203945Sweongyobwn_attach_core(struct bwn_mac *mac)
1603203945Sweongyo{
1604203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
1605203945Sweongyo	int error, have_bg = 0, have_a = 0;
1606203945Sweongyo	uint32_t high;
1607203945Sweongyo
1608204922Sweongyo	KASSERT(siba_get_revid(sc->sc_dev) >= 5,
1609204922Sweongyo	    ("unsupported revision %d", siba_get_revid(sc->sc_dev)));
1610203945Sweongyo
1611204922Sweongyo	siba_powerup(sc->sc_dev, 0);
1612203945Sweongyo
1613204922Sweongyo	high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH);
1614203945Sweongyo	bwn_reset_core(mac,
1615203945Sweongyo	    (high & BWN_TGSHIGH_HAVE_2GHZ) ? BWN_TGSLOW_SUPPORT_G : 0);
1616203945Sweongyo	error = bwn_phy_getinfo(mac, high);
1617203945Sweongyo	if (error)
1618203945Sweongyo		goto fail;
1619203945Sweongyo
1620203945Sweongyo	have_a = (high & BWN_TGSHIGH_HAVE_5GHZ) ? 1 : 0;
1621203945Sweongyo	have_bg = (high & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1622204922Sweongyo	if (siba_get_pci_device(sc->sc_dev) != 0x4312 &&
1623204922Sweongyo	    siba_get_pci_device(sc->sc_dev) != 0x4319 &&
1624204922Sweongyo	    siba_get_pci_device(sc->sc_dev) != 0x4324) {
1625203945Sweongyo		have_a = have_bg = 0;
1626203945Sweongyo		if (mac->mac_phy.type == BWN_PHYTYPE_A)
1627203945Sweongyo			have_a = 1;
1628203945Sweongyo		else if (mac->mac_phy.type == BWN_PHYTYPE_G ||
1629203945Sweongyo		    mac->mac_phy.type == BWN_PHYTYPE_N ||
1630203945Sweongyo		    mac->mac_phy.type == BWN_PHYTYPE_LP)
1631203945Sweongyo			have_bg = 1;
1632203945Sweongyo		else
1633203945Sweongyo			KASSERT(0 == 1, ("%s: unknown phy type (%d)", __func__,
1634203945Sweongyo			    mac->mac_phy.type));
1635203945Sweongyo	}
1636203945Sweongyo	/* XXX turns off PHY A because it's not supported */
1637203945Sweongyo	if (mac->mac_phy.type != BWN_PHYTYPE_LP &&
1638203945Sweongyo	    mac->mac_phy.type != BWN_PHYTYPE_N) {
1639203945Sweongyo		have_a = 0;
1640203945Sweongyo		have_bg = 1;
1641203945Sweongyo	}
1642203945Sweongyo
1643203945Sweongyo	if (mac->mac_phy.type == BWN_PHYTYPE_G) {
1644203945Sweongyo		mac->mac_phy.attach = bwn_phy_g_attach;
1645203945Sweongyo		mac->mac_phy.detach = bwn_phy_g_detach;
1646203945Sweongyo		mac->mac_phy.prepare_hw = bwn_phy_g_prepare_hw;
1647203945Sweongyo		mac->mac_phy.init_pre = bwn_phy_g_init_pre;
1648203945Sweongyo		mac->mac_phy.init = bwn_phy_g_init;
1649203945Sweongyo		mac->mac_phy.exit = bwn_phy_g_exit;
1650203945Sweongyo		mac->mac_phy.phy_read = bwn_phy_g_read;
1651203945Sweongyo		mac->mac_phy.phy_write = bwn_phy_g_write;
1652203945Sweongyo		mac->mac_phy.rf_read = bwn_phy_g_rf_read;
1653203945Sweongyo		mac->mac_phy.rf_write = bwn_phy_g_rf_write;
1654203945Sweongyo		mac->mac_phy.use_hwpctl = bwn_phy_g_hwpctl;
1655203945Sweongyo		mac->mac_phy.rf_onoff = bwn_phy_g_rf_onoff;
1656203945Sweongyo		mac->mac_phy.switch_analog = bwn_phy_switch_analog;
1657203945Sweongyo		mac->mac_phy.switch_channel = bwn_phy_g_switch_channel;
1658203945Sweongyo		mac->mac_phy.get_default_chan = bwn_phy_g_get_default_chan;
1659203945Sweongyo		mac->mac_phy.set_antenna = bwn_phy_g_set_antenna;
1660203945Sweongyo		mac->mac_phy.set_im = bwn_phy_g_im;
1661203945Sweongyo		mac->mac_phy.recalc_txpwr = bwn_phy_g_recalc_txpwr;
1662203945Sweongyo		mac->mac_phy.set_txpwr = bwn_phy_g_set_txpwr;
1663203945Sweongyo		mac->mac_phy.task_15s = bwn_phy_g_task_15s;
1664203945Sweongyo		mac->mac_phy.task_60s = bwn_phy_g_task_60s;
1665203945Sweongyo	} else if (mac->mac_phy.type == BWN_PHYTYPE_LP) {
1666203945Sweongyo		mac->mac_phy.init_pre = bwn_phy_lp_init_pre;
1667203945Sweongyo		mac->mac_phy.init = bwn_phy_lp_init;
1668203945Sweongyo		mac->mac_phy.phy_read = bwn_phy_lp_read;
1669203945Sweongyo		mac->mac_phy.phy_write = bwn_phy_lp_write;
1670203945Sweongyo		mac->mac_phy.phy_maskset = bwn_phy_lp_maskset;
1671203945Sweongyo		mac->mac_phy.rf_read = bwn_phy_lp_rf_read;
1672203945Sweongyo		mac->mac_phy.rf_write = bwn_phy_lp_rf_write;
1673203945Sweongyo		mac->mac_phy.rf_onoff = bwn_phy_lp_rf_onoff;
1674203945Sweongyo		mac->mac_phy.switch_analog = bwn_phy_lp_switch_analog;
1675203945Sweongyo		mac->mac_phy.switch_channel = bwn_phy_lp_switch_channel;
1676203945Sweongyo		mac->mac_phy.get_default_chan = bwn_phy_lp_get_default_chan;
1677203945Sweongyo		mac->mac_phy.set_antenna = bwn_phy_lp_set_antenna;
1678203945Sweongyo		mac->mac_phy.task_60s = bwn_phy_lp_task_60s;
1679203945Sweongyo	} else {
1680203945Sweongyo		device_printf(sc->sc_dev, "unsupported PHY type (%d)\n",
1681203945Sweongyo		    mac->mac_phy.type);
1682203945Sweongyo		error = ENXIO;
1683203945Sweongyo		goto fail;
1684203945Sweongyo	}
1685203945Sweongyo
1686203945Sweongyo	mac->mac_phy.gmode = have_bg;
1687203945Sweongyo	if (mac->mac_phy.attach != NULL) {
1688203945Sweongyo		error = mac->mac_phy.attach(mac);
1689203945Sweongyo		if (error) {
1690203945Sweongyo			device_printf(sc->sc_dev, "failed\n");
1691203945Sweongyo			goto fail;
1692203945Sweongyo		}
1693203945Sweongyo	}
1694203945Sweongyo
1695203945Sweongyo	bwn_reset_core(mac, have_bg ? BWN_TGSLOW_SUPPORT_G : 0);
1696203945Sweongyo
1697203945Sweongyo	error = bwn_chiptest(mac);
1698203945Sweongyo	if (error)
1699203945Sweongyo		goto fail;
1700203945Sweongyo	error = bwn_setup_channels(mac, have_bg, have_a);
1701203945Sweongyo	if (error) {
1702203945Sweongyo		device_printf(sc->sc_dev, "failed to setup channels\n");
1703203945Sweongyo		goto fail;
1704203945Sweongyo	}
1705203945Sweongyo
1706203945Sweongyo	if (sc->sc_curmac == NULL)
1707203945Sweongyo		sc->sc_curmac = mac;
1708203945Sweongyo
1709203945Sweongyo	error = bwn_dma_attach(mac);
1710203945Sweongyo	if (error != 0) {
1711203945Sweongyo		device_printf(sc->sc_dev, "failed to initialize DMA\n");
1712203945Sweongyo		goto fail;
1713203945Sweongyo	}
1714203945Sweongyo
1715203945Sweongyo	mac->mac_phy.switch_analog(mac, 0);
1716203945Sweongyo
1717204922Sweongyo	siba_dev_down(sc->sc_dev, 0);
1718203945Sweongyofail:
1719204922Sweongyo	siba_powerdown(sc->sc_dev);
1720203945Sweongyo	return (error);
1721203945Sweongyo}
1722203945Sweongyo
1723203945Sweongyostatic void
1724203945Sweongyobwn_reset_core(struct bwn_mac *mac, uint32_t flags)
1725203945Sweongyo{
1726204922Sweongyo	struct bwn_softc *sc = mac->mac_sc;
1727203945Sweongyo	uint32_t low, ctl;
1728203945Sweongyo
1729203945Sweongyo	flags |= (BWN_TGSLOW_PHYCLOCK_ENABLE | BWN_TGSLOW_PHYRESET);
1730203945Sweongyo
1731204922Sweongyo	siba_dev_up(sc->sc_dev, flags);
1732203945Sweongyo	DELAY(2000);
1733203945Sweongyo
1734204922Sweongyo	low = (siba_read_4(sc->sc_dev, SIBA_TGSLOW) | SIBA_TGSLOW_FGC) &
1735203945Sweongyo	    ~BWN_TGSLOW_PHYRESET;
1736204922Sweongyo	siba_write_4(sc->sc_dev, SIBA_TGSLOW, low);
1737204922Sweongyo	siba_read_4(sc->sc_dev, SIBA_TGSLOW);
1738203945Sweongyo	DELAY(1000);
1739204922Sweongyo	siba_write_4(sc->sc_dev, SIBA_TGSLOW, low & ~SIBA_TGSLOW_FGC);
1740204922Sweongyo	siba_read_4(sc->sc_dev, SIBA_TGSLOW);
1741203945Sweongyo	DELAY(1000);
1742203945Sweongyo
1743203945Sweongyo	if (mac->mac_phy.switch_analog != NULL)
1744203945Sweongyo		mac->mac_phy.switch_analog(mac, 1);
1745203945Sweongyo
1746203945Sweongyo	ctl = BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GMODE;
1747203945Sweongyo	if (flags & BWN_TGSLOW_SUPPORT_G)
1748203945Sweongyo		ctl |= BWN_MACCTL_GMODE;
1749203945Sweongyo	BWN_WRITE_4(mac, BWN_MACCTL, ctl | BWN_MACCTL_IHR_ON);
1750203945Sweongyo}
1751203945Sweongyo
1752203945Sweongyostatic int
1753203945Sweongyobwn_phy_getinfo(struct bwn_mac *mac, int tgshigh)
1754203945Sweongyo{
1755203945Sweongyo	struct bwn_phy *phy = &mac->mac_phy;
1756203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
1757203945Sweongyo	uint32_t tmp;
1758203945Sweongyo
1759203945Sweongyo	/* PHY */
1760203945Sweongyo	tmp = BWN_READ_2(mac, BWN_PHYVER);
1761203945Sweongyo	phy->gmode = (tgshigh & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1762203945Sweongyo	phy->rf_on = 1;
1763203945Sweongyo	phy->analog = (tmp & BWN_PHYVER_ANALOG) >> 12;
1764203945Sweongyo	phy->type = (tmp & BWN_PHYVER_TYPE) >> 8;
1765203945Sweongyo	phy->rev = (tmp & BWN_PHYVER_VERSION);
1766203945Sweongyo	if ((phy->type == BWN_PHYTYPE_A && phy->rev >= 4) ||
1767203945Sweongyo	    (phy->type == BWN_PHYTYPE_B && phy->rev != 2 &&
1768203945Sweongyo		phy->rev != 4 && phy->rev != 6 && phy->rev != 7) ||
1769203945Sweongyo	    (phy->type == BWN_PHYTYPE_G && phy->rev > 9) ||
1770203945Sweongyo	    (phy->type == BWN_PHYTYPE_N && phy->rev > 4) ||
1771203945Sweongyo	    (phy->type == BWN_PHYTYPE_LP && phy->rev > 2))
1772203945Sweongyo		goto unsupphy;
1773203945Sweongyo
1774203945Sweongyo	/* RADIO */
1775204922Sweongyo	if (siba_get_chipid(sc->sc_dev) == 0x4317) {
1776204922Sweongyo		if (siba_get_chiprev(sc->sc_dev) == 0)
1777203945Sweongyo			tmp = 0x3205017f;
1778204922Sweongyo		else if (siba_get_chiprev(sc->sc_dev) == 1)
1779203945Sweongyo			tmp = 0x4205017f;
1780203945Sweongyo		else
1781203945Sweongyo			tmp = 0x5205017f;
1782203945Sweongyo	} else {
1783203945Sweongyo		BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1784203945Sweongyo		tmp = BWN_READ_2(mac, BWN_RFDATALO);
1785203945Sweongyo		BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1786203945Sweongyo		tmp |= (uint32_t)BWN_READ_2(mac, BWN_RFDATAHI) << 16;
1787203945Sweongyo	}
1788203945Sweongyo	phy->rf_rev = (tmp & 0xf0000000) >> 28;
1789203945Sweongyo	phy->rf_ver = (tmp & 0x0ffff000) >> 12;
1790203945Sweongyo	phy->rf_manuf = (tmp & 0x00000fff);
1791203945Sweongyo	if (phy->rf_manuf != 0x17f)	/* 0x17f is broadcom */
1792203945Sweongyo		goto unsupradio;
1793203945Sweongyo	if ((phy->type == BWN_PHYTYPE_A && (phy->rf_ver != 0x2060 ||
1794203945Sweongyo	     phy->rf_rev != 1 || phy->rf_manuf != 0x17f)) ||
1795203945Sweongyo	    (phy->type == BWN_PHYTYPE_B && (phy->rf_ver & 0xfff0) != 0x2050) ||
1796203945Sweongyo	    (phy->type == BWN_PHYTYPE_G && phy->rf_ver != 0x2050) ||
1797203945Sweongyo	    (phy->type == BWN_PHYTYPE_N &&
1798203945Sweongyo	     phy->rf_ver != 0x2055 && phy->rf_ver != 0x2056) ||
1799203945Sweongyo	    (phy->type == BWN_PHYTYPE_LP &&
1800203945Sweongyo	     phy->rf_ver != 0x2062 && phy->rf_ver != 0x2063))
1801203945Sweongyo		goto unsupradio;
1802203945Sweongyo
1803203945Sweongyo	return (0);
1804203945Sweongyounsupphy:
1805203945Sweongyo	device_printf(sc->sc_dev, "unsupported PHY (type %#x, rev %#x, "
1806203945Sweongyo	    "analog %#x)\n",
1807203945Sweongyo	    phy->type, phy->rev, phy->analog);
1808203945Sweongyo	return (ENXIO);
1809203945Sweongyounsupradio:
1810203945Sweongyo	device_printf(sc->sc_dev, "unsupported radio (manuf %#x, ver %#x, "
1811203945Sweongyo	    "rev %#x)\n",
1812203945Sweongyo	    phy->rf_manuf, phy->rf_ver, phy->rf_rev);
1813203945Sweongyo	return (ENXIO);
1814203945Sweongyo}
1815203945Sweongyo
1816203945Sweongyostatic int
1817203945Sweongyobwn_chiptest(struct bwn_mac *mac)
1818203945Sweongyo{
1819203945Sweongyo#define	TESTVAL0	0x55aaaa55
1820203945Sweongyo#define	TESTVAL1	0xaa5555aa
1821203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
1822203945Sweongyo	uint32_t v, backup;
1823203945Sweongyo
1824203945Sweongyo	BWN_LOCK(sc);
1825203945Sweongyo
1826203945Sweongyo	backup = bwn_shm_read_4(mac, BWN_SHARED, 0);
1827203945Sweongyo
1828203945Sweongyo	bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL0);
1829203945Sweongyo	if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL0)
1830203945Sweongyo		goto error;
1831203945Sweongyo	bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL1);
1832203945Sweongyo	if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL1)
1833203945Sweongyo		goto error;
1834203945Sweongyo
1835203945Sweongyo	bwn_shm_write_4(mac, BWN_SHARED, 0, backup);
1836203945Sweongyo
1837204922Sweongyo	if ((siba_get_revid(sc->sc_dev) >= 3) &&
1838204922Sweongyo	    (siba_get_revid(sc->sc_dev) <= 10)) {
1839203945Sweongyo		BWN_WRITE_2(mac, BWN_TSF_CFP_START, 0xaaaa);
1840203945Sweongyo		BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0xccccbbbb);
1841203945Sweongyo		if (BWN_READ_2(mac, BWN_TSF_CFP_START_LOW) != 0xbbbb)
1842203945Sweongyo			goto error;
1843203945Sweongyo		if (BWN_READ_2(mac, BWN_TSF_CFP_START_HIGH) != 0xcccc)
1844203945Sweongyo			goto error;
1845203945Sweongyo	}
1846203945Sweongyo	BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0);
1847203945Sweongyo
1848203945Sweongyo	v = BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_GMODE;
1849203945Sweongyo	if (v != (BWN_MACCTL_GMODE | BWN_MACCTL_IHR_ON))
1850203945Sweongyo		goto error;
1851203945Sweongyo
1852203945Sweongyo	BWN_UNLOCK(sc);
1853203945Sweongyo	return (0);
1854203945Sweongyoerror:
1855203945Sweongyo	BWN_UNLOCK(sc);
1856203945Sweongyo	device_printf(sc->sc_dev, "failed to validate the chipaccess\n");
1857203945Sweongyo	return (ENODEV);
1858203945Sweongyo}
1859203945Sweongyo
1860203945Sweongyo#define	IEEE80211_CHAN_HTG	(IEEE80211_CHAN_HT | IEEE80211_CHAN_G)
1861203945Sweongyo#define	IEEE80211_CHAN_HTA	(IEEE80211_CHAN_HT | IEEE80211_CHAN_A)
1862203945Sweongyo
1863203945Sweongyostatic int
1864203945Sweongyobwn_setup_channels(struct bwn_mac *mac, int have_bg, int have_a)
1865203945Sweongyo{
1866203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
1867203945Sweongyo	struct ifnet *ifp = sc->sc_ifp;
1868203945Sweongyo	struct ieee80211com *ic = ifp->if_l2com;
1869203945Sweongyo
1870203945Sweongyo	memset(ic->ic_channels, 0, sizeof(ic->ic_channels));
1871203945Sweongyo	ic->ic_nchans = 0;
1872203945Sweongyo
1873203945Sweongyo	if (have_bg)
1874203945Sweongyo		bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1875203945Sweongyo		    &ic->ic_nchans, &bwn_chantable_bg, IEEE80211_CHAN_G);
1876203945Sweongyo	if (mac->mac_phy.type == BWN_PHYTYPE_N) {
1877203945Sweongyo		if (have_a)
1878203945Sweongyo			bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1879203945Sweongyo			    &ic->ic_nchans, &bwn_chantable_n,
1880203945Sweongyo			    IEEE80211_CHAN_HTA);
1881203945Sweongyo	} else {
1882203945Sweongyo		if (have_a)
1883203945Sweongyo			bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1884203945Sweongyo			    &ic->ic_nchans, &bwn_chantable_a,
1885203945Sweongyo			    IEEE80211_CHAN_A);
1886203945Sweongyo	}
1887203945Sweongyo
1888203945Sweongyo	mac->mac_phy.supports_2ghz = have_bg;
1889203945Sweongyo	mac->mac_phy.supports_5ghz = have_a;
1890203945Sweongyo
1891203945Sweongyo	return (ic->ic_nchans == 0 ? ENXIO : 0);
1892203945Sweongyo}
1893203945Sweongyo
1894203945Sweongyostatic uint32_t
1895203945Sweongyobwn_shm_read_4(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1896203945Sweongyo{
1897203945Sweongyo	uint32_t ret;
1898203945Sweongyo
1899204242Simp	BWN_ASSERT_LOCKED(mac->mac_sc);
1900203945Sweongyo
1901203945Sweongyo	if (way == BWN_SHARED) {
1902203945Sweongyo		KASSERT((offset & 0x0001) == 0,
1903203945Sweongyo		    ("%s:%d warn", __func__, __LINE__));
1904203945Sweongyo		if (offset & 0x0003) {
1905203945Sweongyo			bwn_shm_ctlword(mac, way, offset >> 2);
1906203945Sweongyo			ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1907203945Sweongyo			ret <<= 16;
1908203945Sweongyo			bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1909203945Sweongyo			ret |= BWN_READ_2(mac, BWN_SHM_DATA);
1910203945Sweongyo			goto out;
1911203945Sweongyo		}
1912203945Sweongyo		offset >>= 2;
1913203945Sweongyo	}
1914203945Sweongyo	bwn_shm_ctlword(mac, way, offset);
1915203945Sweongyo	ret = BWN_READ_4(mac, BWN_SHM_DATA);
1916203945Sweongyoout:
1917203945Sweongyo	return (ret);
1918203945Sweongyo}
1919203945Sweongyo
1920203945Sweongyostatic uint16_t
1921203945Sweongyobwn_shm_read_2(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1922203945Sweongyo{
1923203945Sweongyo	uint16_t ret;
1924203945Sweongyo
1925204242Simp	BWN_ASSERT_LOCKED(mac->mac_sc);
1926203945Sweongyo
1927203945Sweongyo	if (way == BWN_SHARED) {
1928203945Sweongyo		KASSERT((offset & 0x0001) == 0,
1929203945Sweongyo		    ("%s:%d warn", __func__, __LINE__));
1930203945Sweongyo		if (offset & 0x0003) {
1931203945Sweongyo			bwn_shm_ctlword(mac, way, offset >> 2);
1932203945Sweongyo			ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1933203945Sweongyo			goto out;
1934203945Sweongyo		}
1935203945Sweongyo		offset >>= 2;
1936203945Sweongyo	}
1937203945Sweongyo	bwn_shm_ctlword(mac, way, offset);
1938203945Sweongyo	ret = BWN_READ_2(mac, BWN_SHM_DATA);
1939203945Sweongyoout:
1940203945Sweongyo
1941203945Sweongyo	return (ret);
1942203945Sweongyo}
1943203945Sweongyo
1944203945Sweongyostatic void
1945203945Sweongyobwn_shm_ctlword(struct bwn_mac *mac, uint16_t way,
1946203945Sweongyo    uint16_t offset)
1947203945Sweongyo{
1948203945Sweongyo	uint32_t control;
1949203945Sweongyo
1950203945Sweongyo	control = way;
1951203945Sweongyo	control <<= 16;
1952203945Sweongyo	control |= offset;
1953203945Sweongyo	BWN_WRITE_4(mac, BWN_SHM_CONTROL, control);
1954203945Sweongyo}
1955203945Sweongyo
1956203945Sweongyostatic void
1957203945Sweongyobwn_shm_write_4(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1958203945Sweongyo    uint32_t value)
1959203945Sweongyo{
1960204242Simp	BWN_ASSERT_LOCKED(mac->mac_sc);
1961203945Sweongyo
1962203945Sweongyo	if (way == BWN_SHARED) {
1963203945Sweongyo		KASSERT((offset & 0x0001) == 0,
1964203945Sweongyo		    ("%s:%d warn", __func__, __LINE__));
1965203945Sweongyo		if (offset & 0x0003) {
1966203945Sweongyo			bwn_shm_ctlword(mac, way, offset >> 2);
1967203945Sweongyo			BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED,
1968203945Sweongyo				    (value >> 16) & 0xffff);
1969203945Sweongyo			bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1970203945Sweongyo			BWN_WRITE_2(mac, BWN_SHM_DATA, value & 0xffff);
1971203945Sweongyo			return;
1972203945Sweongyo		}
1973203945Sweongyo		offset >>= 2;
1974203945Sweongyo	}
1975203945Sweongyo	bwn_shm_ctlword(mac, way, offset);
1976203945Sweongyo	BWN_WRITE_4(mac, BWN_SHM_DATA, value);
1977203945Sweongyo}
1978203945Sweongyo
1979203945Sweongyostatic void
1980203945Sweongyobwn_shm_write_2(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1981203945Sweongyo    uint16_t value)
1982203945Sweongyo{
1983204242Simp	BWN_ASSERT_LOCKED(mac->mac_sc);
1984203945Sweongyo
1985203945Sweongyo	if (way == BWN_SHARED) {
1986203945Sweongyo		KASSERT((offset & 0x0001) == 0,
1987203945Sweongyo		    ("%s:%d warn", __func__, __LINE__));
1988203945Sweongyo		if (offset & 0x0003) {
1989203945Sweongyo			bwn_shm_ctlword(mac, way, offset >> 2);
1990203945Sweongyo			BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED, value);
1991203945Sweongyo			return;
1992203945Sweongyo		}
1993203945Sweongyo		offset >>= 2;
1994203945Sweongyo	}
1995203945Sweongyo	bwn_shm_ctlword(mac, way, offset);
1996203945Sweongyo	BWN_WRITE_2(mac, BWN_SHM_DATA, value);
1997203945Sweongyo}
1998203945Sweongyo
1999203945Sweongyostatic void
2000203945Sweongyobwn_addchan(struct ieee80211_channel *c, int freq, int flags, int ieee,
2001203945Sweongyo    int txpow)
2002203945Sweongyo{
2003203945Sweongyo
2004203945Sweongyo	c->ic_freq = freq;
2005203945Sweongyo	c->ic_flags = flags;
2006203945Sweongyo	c->ic_ieee = ieee;
2007203945Sweongyo	c->ic_minpower = 0;
2008203945Sweongyo	c->ic_maxpower = 2 * txpow;
2009203945Sweongyo	c->ic_maxregpower = txpow;
2010203945Sweongyo}
2011203945Sweongyo
2012203945Sweongyostatic void
2013203945Sweongyobwn_addchannels(struct ieee80211_channel chans[], int maxchans, int *nchans,
2014203945Sweongyo    const struct bwn_channelinfo *ci, int flags)
2015203945Sweongyo{
2016203945Sweongyo	struct ieee80211_channel *c;
2017203945Sweongyo	int i;
2018203945Sweongyo
2019203945Sweongyo	c = &chans[*nchans];
2020203945Sweongyo
2021203945Sweongyo	for (i = 0; i < ci->nchannels; i++) {
2022203945Sweongyo		const struct bwn_channel *hc;
2023203945Sweongyo
2024203945Sweongyo		hc = &ci->channels[i];
2025203945Sweongyo		if (*nchans >= maxchans)
2026203945Sweongyo			break;
2027203945Sweongyo		bwn_addchan(c, hc->freq, flags, hc->ieee, hc->maxTxPow);
2028203945Sweongyo		c++, (*nchans)++;
2029203945Sweongyo		if (flags == IEEE80211_CHAN_G || flags == IEEE80211_CHAN_HTG) {
2030203945Sweongyo			/* g channel have a separate b-only entry */
2031203945Sweongyo			if (*nchans >= maxchans)
2032203945Sweongyo				break;
2033203945Sweongyo			c[0] = c[-1];
2034203945Sweongyo			c[-1].ic_flags = IEEE80211_CHAN_B;
2035203945Sweongyo			c++, (*nchans)++;
2036203945Sweongyo		}
2037203945Sweongyo		if (flags == IEEE80211_CHAN_HTG) {
2038203945Sweongyo			/* HT g channel have a separate g-only entry */
2039203945Sweongyo			if (*nchans >= maxchans)
2040203945Sweongyo				break;
2041203945Sweongyo			c[-1].ic_flags = IEEE80211_CHAN_G;
2042203945Sweongyo			c[0] = c[-1];
2043203945Sweongyo			c[0].ic_flags &= ~IEEE80211_CHAN_HT;
2044203945Sweongyo			c[0].ic_flags |= IEEE80211_CHAN_HT20;	/* HT20 */
2045203945Sweongyo			c++, (*nchans)++;
2046203945Sweongyo		}
2047203945Sweongyo		if (flags == IEEE80211_CHAN_HTA) {
2048203945Sweongyo			/* HT a channel have a separate a-only entry */
2049203945Sweongyo			if (*nchans >= maxchans)
2050203945Sweongyo				break;
2051203945Sweongyo			c[-1].ic_flags = IEEE80211_CHAN_A;
2052203945Sweongyo			c[0] = c[-1];
2053203945Sweongyo			c[0].ic_flags &= ~IEEE80211_CHAN_HT;
2054203945Sweongyo			c[0].ic_flags |= IEEE80211_CHAN_HT20;	/* HT20 */
2055203945Sweongyo			c++, (*nchans)++;
2056203945Sweongyo		}
2057203945Sweongyo	}
2058203945Sweongyo}
2059203945Sweongyo
2060203945Sweongyostatic int
2061203945Sweongyobwn_phy_g_attach(struct bwn_mac *mac)
2062203945Sweongyo{
2063203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
2064203945Sweongyo	struct bwn_phy *phy = &mac->mac_phy;
2065203945Sweongyo	struct bwn_phy_g *pg = &phy->phy_g;
2066203945Sweongyo	unsigned int i;
2067204922Sweongyo	int16_t pab0, pab1, pab2;
2068203945Sweongyo	static int8_t bwn_phy_g_tssi2dbm_table[] = BWN_PHY_G_TSSI2DBM_TABLE;
2069204922Sweongyo	int8_t bg;
2070203945Sweongyo
2071204922Sweongyo	bg = (int8_t)siba_sprom_get_tssi_bg(sc->sc_dev);
2072204922Sweongyo	pab0 = (int16_t)siba_sprom_get_pa0b0(sc->sc_dev);
2073204922Sweongyo	pab1 = (int16_t)siba_sprom_get_pa0b1(sc->sc_dev);
2074204922Sweongyo	pab2 = (int16_t)siba_sprom_get_pa0b2(sc->sc_dev);
2075204922Sweongyo
2076204922Sweongyo	if ((siba_get_chipid(sc->sc_dev) == 0x4301) && (phy->rf_ver != 0x2050))
2077203945Sweongyo		device_printf(sc->sc_dev, "not supported anymore\n");
2078203945Sweongyo
2079203945Sweongyo	pg->pg_flags = 0;
2080203945Sweongyo	if (pab0 == 0 || pab1 == 0 || pab2 == 0 || pab0 == -1 || pab1 == -1 ||
2081203945Sweongyo	    pab2 == -1) {
2082203945Sweongyo		pg->pg_idletssi = 52;
2083203945Sweongyo		pg->pg_tssi2dbm = bwn_phy_g_tssi2dbm_table;
2084203945Sweongyo		return (0);
2085203945Sweongyo	}
2086203945Sweongyo
2087203945Sweongyo	pg->pg_idletssi = (bg == 0 || bg == -1) ? 62 : bg;
2088203945Sweongyo	pg->pg_tssi2dbm = (uint8_t *)malloc(64, M_DEVBUF, M_NOWAIT | M_ZERO);
2089203945Sweongyo	if (pg->pg_tssi2dbm == NULL) {
2090203945Sweongyo		device_printf(sc->sc_dev, "failed to allocate buffer\n");
2091203945Sweongyo		return (ENOMEM);
2092203945Sweongyo	}
2093203945Sweongyo	for (i = 0; i < 64; i++) {
2094203945Sweongyo		int32_t m1, m2, f, q, delta;
2095203945Sweongyo		int8_t j = 0;
2096203945Sweongyo
2097203945Sweongyo		m1 = BWN_TSSI2DBM(16 * pab0 + i * pab1, 32);
2098203945Sweongyo		m2 = MAX(BWN_TSSI2DBM(32768 + i * pab2, 256), 1);
2099203945Sweongyo		f = 256;
2100203945Sweongyo
2101203945Sweongyo		do {
2102203945Sweongyo			if (j > 15) {
2103203945Sweongyo				device_printf(sc->sc_dev,
2104203945Sweongyo				    "failed to generate tssi2dBm\n");
2105203945Sweongyo				free(pg->pg_tssi2dbm, M_DEVBUF);
2106203945Sweongyo				return (ENOMEM);
2107203945Sweongyo			}
2108203945Sweongyo			q = BWN_TSSI2DBM(f * 4096 - BWN_TSSI2DBM(m2 * f, 16) *
2109203945Sweongyo			    f, 2048);
2110203945Sweongyo			delta = abs(q - f);
2111203945Sweongyo			f = q;
2112203945Sweongyo			j++;
2113203945Sweongyo		} while (delta >= 2);
2114203945Sweongyo
2115203945Sweongyo		pg->pg_tssi2dbm[i] = MIN(MAX(BWN_TSSI2DBM(m1 * f, 8192), -127),
2116203945Sweongyo		    128);
2117203945Sweongyo	}
2118203945Sweongyo
2119203945Sweongyo	pg->pg_flags |= BWN_PHY_G_FLAG_TSSITABLE_ALLOC;
2120203945Sweongyo	return (0);
2121203945Sweongyo}
2122203945Sweongyo
2123203945Sweongyostatic void
2124203945Sweongyobwn_phy_g_detach(struct bwn_mac *mac)
2125203945Sweongyo{
2126203945Sweongyo	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
2127203945Sweongyo
2128203945Sweongyo	if (pg->pg_flags & BWN_PHY_G_FLAG_TSSITABLE_ALLOC) {
2129203945Sweongyo		free(pg->pg_tssi2dbm, M_DEVBUF);
2130203945Sweongyo		pg->pg_tssi2dbm = NULL;
2131203945Sweongyo	}
2132203945Sweongyo	pg->pg_flags = 0;
2133203945Sweongyo}
2134203945Sweongyo
2135203945Sweongyostatic void
2136203945Sweongyobwn_phy_g_init_pre(struct bwn_mac *mac)
2137203945Sweongyo{
2138203945Sweongyo	struct bwn_phy *phy = &mac->mac_phy;
2139203945Sweongyo	struct bwn_phy_g *pg = &phy->phy_g;
2140203945Sweongyo	void *tssi2dbm;
2141203945Sweongyo	int idletssi;
2142203945Sweongyo	unsigned int i;
2143203945Sweongyo
2144203945Sweongyo	tssi2dbm = pg->pg_tssi2dbm;
2145203945Sweongyo	idletssi = pg->pg_idletssi;
2146203945Sweongyo
2147203945Sweongyo	memset(pg, 0, sizeof(*pg));
2148203945Sweongyo
2149203945Sweongyo	pg->pg_tssi2dbm = tssi2dbm;
2150203945Sweongyo	pg->pg_idletssi = idletssi;
2151203945Sweongyo
2152203945Sweongyo	memset(pg->pg_minlowsig, 0xff, sizeof(pg->pg_minlowsig));
2153203945Sweongyo
2154203945Sweongyo	for (i = 0; i < N(pg->pg_nrssi); i++)
2155203945Sweongyo		pg->pg_nrssi[i] = -1000;
2156203945Sweongyo	for (i = 0; i < N(pg->pg_nrssi_lt); i++)
2157203945Sweongyo		pg->pg_nrssi_lt[i] = i;
2158203945Sweongyo	pg->pg_lofcal = 0xffff;
2159203945Sweongyo	pg->pg_initval = 0xffff;
2160203945Sweongyo	pg->pg_immode = BWN_IMMODE_NONE;
2161203945Sweongyo	pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_UNKNOWN;
2162203945Sweongyo	pg->pg_avgtssi = 0xff;
2163203945Sweongyo
2164203945Sweongyo	pg->pg_loctl.tx_bias = 0xff;
2165203945Sweongyo	TAILQ_INIT(&pg->pg_loctl.calib_list);
2166203945Sweongyo}
2167203945Sweongyo
2168203945Sweongyostatic int
2169203945Sweongyobwn_phy_g_prepare_hw(struct bwn_mac *mac)
2170203945Sweongyo{
2171203945Sweongyo	struct bwn_phy *phy = &mac->mac_phy;
2172203945Sweongyo	struct bwn_phy_g *pg = &phy->phy_g;
2173204922Sweongyo	struct bwn_softc *sc = mac->mac_sc;
2174203945Sweongyo	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2175203945Sweongyo	static const struct bwn_rfatt rfatt0[] = {
2176203945Sweongyo		{ 3, 0 }, { 1, 0 }, { 5, 0 }, { 7, 0 },	{ 9, 0 }, { 2, 0 },
2177203945Sweongyo		{ 0, 0 }, { 4, 0 }, { 6, 0 }, { 8, 0 }, { 1, 1 }, { 2, 1 },
2178203945Sweongyo		{ 3, 1 }, { 4, 1 }
2179203945Sweongyo	};
2180203945Sweongyo	static const struct bwn_rfatt rfatt1[] = {
2181203945Sweongyo		{ 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 10, 1 }, { 12, 1 },
2182203945Sweongyo		{ 14, 1 }
2183203945Sweongyo	};
2184203945Sweongyo	static const struct bwn_rfatt rfatt2[] = {
2185203945Sweongyo		{ 0, 1 }, { 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 9, 1 },
2186203945Sweongyo		{ 9, 1 }
2187203945Sweongyo	};
2188203945Sweongyo	static const struct bwn_bbatt bbatt_0[] = {
2189203945Sweongyo		{ 0 }, { 1 }, { 2 }, { 3 }, { 4 }, { 5 }, { 6 }, { 7 }, { 8 }
2190203945Sweongyo	};
2191203945Sweongyo
2192203945Sweongyo	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
2193203945Sweongyo
2194203945Sweongyo	if (phy->rf_ver == 0x2050 && phy->rf_rev < 6)
2195203945Sweongyo		pg->pg_bbatt.att = 0;
2196203945Sweongyo	else
2197203945Sweongyo		pg->pg_bbatt.att = 2;
2198203945Sweongyo
2199203945Sweongyo	/* prepare Radio Attenuation */
2200203945Sweongyo	pg->pg_rfatt.padmix = 0;
2201203945Sweongyo
2202204922Sweongyo	if (siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM &&
2203204922Sweongyo	    siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BCM4309G) {
2204204922Sweongyo		if (siba_get_pci_revid(sc->sc_dev) < 0x43) {
2205203945Sweongyo			pg->pg_rfatt.att = 2;
2206203945Sweongyo			goto done;
2207204922Sweongyo		} else if (siba_get_pci_revid(sc->sc_dev) < 0x51) {
2208203945Sweongyo			pg->pg_rfatt.att = 3;
2209203945Sweongyo			goto done;
2210203945Sweongyo		}
2211203945Sweongyo	}
2212203945Sweongyo
2213203945Sweongyo	if (phy->type == BWN_PHYTYPE_A) {
2214203945Sweongyo		pg->pg_rfatt.att = 0x60;
2215203945Sweongyo		goto done;
2216203945Sweongyo	}
2217203945Sweongyo
2218203945Sweongyo	switch (phy->rf_ver) {
2219203945Sweongyo	case 0x2050:
2220203945Sweongyo		switch (phy->rf_rev) {
2221203945Sweongyo		case 0:
2222203945Sweongyo			pg->pg_rfatt.att = 5;
2223203945Sweongyo			goto done;
2224203945Sweongyo		case 1:
2225203945Sweongyo			if (phy->type == BWN_PHYTYPE_G) {
2226204922Sweongyo				if (siba_get_pci_subvendor(sc->sc_dev) ==
2227203945Sweongyo				    SIBA_BOARDVENDOR_BCM &&
2228204922Sweongyo				    siba_get_pci_subdevice(sc->sc_dev) ==
2229203945Sweongyo				    SIBA_BOARD_BCM4309G &&
2230204922Sweongyo				    siba_get_pci_revid(sc->sc_dev) >= 30)
2231203945Sweongyo					pg->pg_rfatt.att = 3;
2232204922Sweongyo				else if (siba_get_pci_subvendor(sc->sc_dev) ==
2233203945Sweongyo				    SIBA_BOARDVENDOR_BCM &&
2234204922Sweongyo				    siba_get_pci_subdevice(sc->sc_dev) ==
2235204922Sweongyo				    SIBA_BOARD_BU4306)
2236203945Sweongyo					pg->pg_rfatt.att = 3;
2237203945Sweongyo				else
2238203945Sweongyo					pg->pg_rfatt.att = 1;
2239203945Sweongyo			} else {
2240204922Sweongyo				if (siba_get_pci_subvendor(sc->sc_dev) ==
2241203945Sweongyo				    SIBA_BOARDVENDOR_BCM &&
2242204922Sweongyo				    siba_get_pci_subdevice(sc->sc_dev) ==
2243203945Sweongyo				    SIBA_BOARD_BCM4309G &&
2244204922Sweongyo				    siba_get_pci_revid(sc->sc_dev) >= 30)
2245203945Sweongyo					pg->pg_rfatt.att = 7;
2246203945Sweongyo				else
2247203945Sweongyo					pg->pg_rfatt.att = 6;
2248203945Sweongyo			}
2249203945Sweongyo			goto done;
2250203945Sweongyo		case 2:
2251203945Sweongyo			if (phy->type == BWN_PHYTYPE_G) {
2252204922Sweongyo				if (siba_get_pci_subvendor(sc->sc_dev) ==
2253203945Sweongyo				    SIBA_BOARDVENDOR_BCM &&
2254204922Sweongyo				    siba_get_pci_subdevice(sc->sc_dev) ==
2255203945Sweongyo				    SIBA_BOARD_BCM4309G &&
2256204922Sweongyo				    siba_get_pci_revid(sc->sc_dev) >= 30)
2257203945Sweongyo					pg->pg_rfatt.att = 3;
2258204922Sweongyo				else if (siba_get_pci_subvendor(sc->sc_dev) ==
2259203945Sweongyo				    SIBA_BOARDVENDOR_BCM &&
2260204922Sweongyo				    siba_get_pci_subdevice(sc->sc_dev) ==
2261204922Sweongyo				    SIBA_BOARD_BU4306)
2262203945Sweongyo					pg->pg_rfatt.att = 5;
2263204922Sweongyo				else if (siba_get_chipid(sc->sc_dev) == 0x4320)
2264203945Sweongyo					pg->pg_rfatt.att = 4;
2265203945Sweongyo				else
2266203945Sweongyo					pg->pg_rfatt.att = 3;
2267203945Sweongyo			} else
2268203945Sweongyo				pg->pg_rfatt.att = 6;
2269203945Sweongyo			goto done;
2270203945Sweongyo		case 3:
2271203945Sweongyo			pg->pg_rfatt.att = 5;
2272203945Sweongyo			goto done;
2273203945Sweongyo		case 4:
2274203945Sweongyo		case 5:
2275203945Sweongyo			pg->pg_rfatt.att = 1;
2276203945Sweongyo			goto done;
2277203945Sweongyo		case 6:
2278203945Sweongyo		case 7:
2279203945Sweongyo			pg->pg_rfatt.att = 5;
2280203945Sweongyo			goto done;
2281203945Sweongyo		case 8:
2282203945Sweongyo			pg->pg_rfatt.att = 0xa;
2283203945Sweongyo			pg->pg_rfatt.padmix = 1;
2284203945Sweongyo			goto done;
2285203945Sweongyo		case 9:
2286203945Sweongyo		default:
2287203945Sweongyo			pg->pg_rfatt.att = 5;
2288203945Sweongyo			goto done;
2289203945Sweongyo		}
2290203945Sweongyo		break;
2291203945Sweongyo	case 0x2053:
2292203945Sweongyo		switch (phy->rf_rev) {
2293203945Sweongyo		case 1:
2294203945Sweongyo			pg->pg_rfatt.att = 6;
2295203945Sweongyo			goto done;
2296203945Sweongyo		}
2297203945Sweongyo		break;
2298203945Sweongyo	}
2299203945Sweongyo	pg->pg_rfatt.att = 5;
2300203945Sweongyodone:
2301203945Sweongyo	pg->pg_txctl = (bwn_phy_g_txctl(mac) << 4);
2302203945Sweongyo
2303203945Sweongyo	if (!bwn_has_hwpctl(mac)) {
2304203945Sweongyo		lo->rfatt.array = rfatt0;
2305203945Sweongyo		lo->rfatt.len = N(rfatt0);
2306203945Sweongyo		lo->rfatt.min = 0;
2307203945Sweongyo		lo->rfatt.max = 9;
2308203945Sweongyo		goto genbbatt;
2309203945Sweongyo	}
2310203945Sweongyo	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
2311203945Sweongyo		lo->rfatt.array = rfatt1;
2312203945Sweongyo		lo->rfatt.len = N(rfatt1);
2313203945Sweongyo		lo->rfatt.min = 0;
2314203945Sweongyo		lo->rfatt.max = 14;
2315203945Sweongyo		goto genbbatt;
2316203945Sweongyo	}
2317203945Sweongyo	lo->rfatt.array = rfatt2;
2318203945Sweongyo	lo->rfatt.len = N(rfatt2);
2319203945Sweongyo	lo->rfatt.min = 0;
2320203945Sweongyo	lo->rfatt.max = 9;
2321203945Sweongyogenbbatt:
2322203945Sweongyo	lo->bbatt.array = bbatt_0;
2323203945Sweongyo	lo->bbatt.len = N(bbatt_0);
2324203945Sweongyo	lo->bbatt.min = 0;
2325203945Sweongyo	lo->bbatt.max = 8;
2326203945Sweongyo
2327203945Sweongyo	BWN_READ_4(mac, BWN_MACCTL);
2328203945Sweongyo	if (phy->rev == 1) {
2329203945Sweongyo		phy->gmode = 0;
2330203945Sweongyo		bwn_reset_core(mac, 0);
2331203945Sweongyo		bwn_phy_g_init_sub(mac);
2332203945Sweongyo		phy->gmode = 1;
2333203945Sweongyo		bwn_reset_core(mac, BWN_TGSLOW_SUPPORT_G);
2334203945Sweongyo	}
2335203945Sweongyo	return (0);
2336203945Sweongyo}
2337203945Sweongyo
2338203945Sweongyostatic uint16_t
2339203945Sweongyobwn_phy_g_txctl(struct bwn_mac *mac)
2340203945Sweongyo{
2341203945Sweongyo	struct bwn_phy *phy = &mac->mac_phy;
2342203945Sweongyo
2343203945Sweongyo	if (phy->rf_ver != 0x2050)
2344203945Sweongyo		return (0);
2345203945Sweongyo	if (phy->rf_rev == 1)
2346203945Sweongyo		return (BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX);
2347203945Sweongyo	if (phy->rf_rev < 6)
2348203945Sweongyo		return (BWN_TXCTL_PA2DB);
2349203945Sweongyo	if (phy->rf_rev == 8)
2350203945Sweongyo		return (BWN_TXCTL_TXMIX);
2351203945Sweongyo	return (0);
2352203945Sweongyo}
2353203945Sweongyo
2354203945Sweongyostatic int
2355203945Sweongyobwn_phy_g_init(struct bwn_mac *mac)
2356203945Sweongyo{
2357203945Sweongyo
2358203945Sweongyo	bwn_phy_g_init_sub(mac);
2359203945Sweongyo	return (0);
2360203945Sweongyo}
2361203945Sweongyo
2362203945Sweongyostatic void
2363203945Sweongyobwn_phy_g_exit(struct bwn_mac *mac)
2364203945Sweongyo{
2365203945Sweongyo	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
2366203945Sweongyo	struct bwn_lo_calib *cal, *tmp;
2367203945Sweongyo
2368203945Sweongyo	if (lo == NULL)
2369203945Sweongyo		return;
2370203945Sweongyo	TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
2371203945Sweongyo		TAILQ_REMOVE(&lo->calib_list, cal, list);
2372203945Sweongyo		free(cal, M_DEVBUF);
2373203945Sweongyo	}
2374203945Sweongyo}
2375203945Sweongyo
2376203945Sweongyostatic uint16_t
2377203945Sweongyobwn_phy_g_read(struct bwn_mac *mac, uint16_t reg)
2378203945Sweongyo{
2379203945Sweongyo
2380203945Sweongyo	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
2381203945Sweongyo	return (BWN_READ_2(mac, BWN_PHYDATA));
2382203945Sweongyo}
2383203945Sweongyo
2384203945Sweongyostatic void
2385203945Sweongyobwn_phy_g_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
2386203945Sweongyo{
2387203945Sweongyo
2388203945Sweongyo	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
2389203945Sweongyo	BWN_WRITE_2(mac, BWN_PHYDATA, value);
2390203945Sweongyo}
2391203945Sweongyo
2392203945Sweongyostatic uint16_t
2393203945Sweongyobwn_phy_g_rf_read(struct bwn_mac *mac, uint16_t reg)
2394203945Sweongyo{
2395203945Sweongyo
2396203945Sweongyo	KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
2397203945Sweongyo	BWN_WRITE_2(mac, BWN_RFCTL, reg | 0x80);
2398203945Sweongyo	return (BWN_READ_2(mac, BWN_RFDATALO));
2399203945Sweongyo}
2400203945Sweongyo
2401203945Sweongyostatic void
2402203945Sweongyobwn_phy_g_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
2403203945Sweongyo{
2404203945Sweongyo
2405203945Sweongyo	KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
2406203945Sweongyo	BWN_WRITE_2(mac, BWN_RFCTL, reg);
2407203945Sweongyo	BWN_WRITE_2(mac, BWN_RFDATALO, value);
2408203945Sweongyo}
2409203945Sweongyo
2410203945Sweongyostatic int
2411203945Sweongyobwn_phy_g_hwpctl(struct bwn_mac *mac)
2412203945Sweongyo{
2413203945Sweongyo
2414203945Sweongyo	return (mac->mac_phy.rev >= 6);
2415203945Sweongyo}
2416203945Sweongyo
2417203945Sweongyostatic void
2418203945Sweongyobwn_phy_g_rf_onoff(struct bwn_mac *mac, int on)
2419203945Sweongyo{
2420203945Sweongyo	struct bwn_phy *phy = &mac->mac_phy;
2421203945Sweongyo	struct bwn_phy_g *pg = &phy->phy_g;
2422203945Sweongyo	unsigned int channel;
2423203945Sweongyo	uint16_t rfover, rfoverval;
2424203945Sweongyo
2425203945Sweongyo	if (on) {
2426203945Sweongyo		if (phy->rf_on)
2427203945Sweongyo			return;
2428203945Sweongyo
2429203945Sweongyo		BWN_PHY_WRITE(mac, 0x15, 0x8000);
2430203945Sweongyo		BWN_PHY_WRITE(mac, 0x15, 0xcc00);
2431203945Sweongyo		BWN_PHY_WRITE(mac, 0x15, (phy->gmode ? 0xc0 : 0x0));
2432203945Sweongyo		if (pg->pg_flags & BWN_PHY_G_FLAG_RADIOCTX_VALID) {
2433203945Sweongyo			BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
2434203945Sweongyo			    pg->pg_radioctx_over);
2435203945Sweongyo			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
2436203945Sweongyo			    pg->pg_radioctx_overval);
2437203945Sweongyo			pg->pg_flags &= ~BWN_PHY_G_FLAG_RADIOCTX_VALID;
2438203945Sweongyo		}
2439203945Sweongyo		channel = phy->chan;
2440203945Sweongyo		bwn_phy_g_switch_chan(mac, 6, 1);
2441203945Sweongyo		bwn_phy_g_switch_chan(mac, channel, 0);
2442203945Sweongyo		return;
2443203945Sweongyo	}
2444203945Sweongyo
2445203945Sweongyo	rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
2446203945Sweongyo	rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
2447203945Sweongyo	pg->pg_radioctx_over = rfover;
2448203945Sweongyo	pg->pg_radioctx_overval = rfoverval;
2449203945Sweongyo	pg->pg_flags |= BWN_PHY_G_FLAG_RADIOCTX_VALID;
2450203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover | 0x008c);
2451203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval & 0xff73);
2452203945Sweongyo}
2453203945Sweongyo
2454203945Sweongyostatic int
2455203945Sweongyobwn_phy_g_switch_channel(struct bwn_mac *mac, uint32_t newchan)
2456203945Sweongyo{
2457203945Sweongyo
2458203945Sweongyo	if ((newchan < 1) || (newchan > 14))
2459203945Sweongyo		return (EINVAL);
2460203945Sweongyo	bwn_phy_g_switch_chan(mac, newchan, 0);
2461203945Sweongyo
2462203945Sweongyo	return (0);
2463203945Sweongyo}
2464203945Sweongyo
2465203945Sweongyostatic uint32_t
2466203945Sweongyobwn_phy_g_get_default_chan(struct bwn_mac *mac)
2467203945Sweongyo{
2468203945Sweongyo
2469203945Sweongyo	return (1);
2470203945Sweongyo}
2471203945Sweongyo
2472203945Sweongyostatic void
2473203945Sweongyobwn_phy_g_set_antenna(struct bwn_mac *mac, int antenna)
2474203945Sweongyo{
2475203945Sweongyo	struct bwn_phy *phy = &mac->mac_phy;
2476203945Sweongyo	uint64_t hf;
2477203945Sweongyo	int autodiv = 0;
2478203945Sweongyo	uint16_t tmp;
2479203945Sweongyo
2480203945Sweongyo	if (antenna == BWN_ANTAUTO0 || antenna == BWN_ANTAUTO1)
2481203945Sweongyo		autodiv = 1;
2482203945Sweongyo
2483203945Sweongyo	hf = bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER;
2484203945Sweongyo	bwn_hf_write(mac, hf);
2485203945Sweongyo
2486203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_BBANDCFG,
2487203945Sweongyo	    (BWN_PHY_READ(mac, BWN_PHY_BBANDCFG) & ~BWN_PHY_BBANDCFG_RXANT) |
2488203945Sweongyo	    ((autodiv ? BWN_ANTAUTO1 : antenna)
2489203945Sweongyo		<< BWN_PHY_BBANDCFG_RXANT_SHIFT));
2490203945Sweongyo
2491203945Sweongyo	if (autodiv) {
2492203945Sweongyo		tmp = BWN_PHY_READ(mac, BWN_PHY_ANTDWELL);
2493203945Sweongyo		if (antenna == BWN_ANTAUTO1)
2494203945Sweongyo			tmp &= ~BWN_PHY_ANTDWELL_AUTODIV1;
2495203945Sweongyo		else
2496203945Sweongyo			tmp |= BWN_PHY_ANTDWELL_AUTODIV1;
2497203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_ANTDWELL, tmp);
2498203945Sweongyo	}
2499203945Sweongyo	tmp = BWN_PHY_READ(mac, BWN_PHY_ANTWRSETT);
2500203945Sweongyo	if (autodiv)
2501203945Sweongyo		tmp |= BWN_PHY_ANTWRSETT_ARXDIV;
2502203945Sweongyo	else
2503203945Sweongyo		tmp &= ~BWN_PHY_ANTWRSETT_ARXDIV;
2504203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_ANTWRSETT, tmp);
2505203945Sweongyo	if (phy->rev >= 2) {
2506203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_OFDM61,
2507203945Sweongyo		    BWN_PHY_READ(mac, BWN_PHY_OFDM61) | BWN_PHY_OFDM61_10);
2508203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_DIVSRCHGAINBACK,
2509203945Sweongyo		    (BWN_PHY_READ(mac, BWN_PHY_DIVSRCHGAINBACK) & 0xff00) |
2510203945Sweongyo		    0x15);
2511203945Sweongyo		if (phy->rev == 2)
2512203945Sweongyo			BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED, 8);
2513203945Sweongyo		else
2514203945Sweongyo			BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED,
2515203945Sweongyo			    (BWN_PHY_READ(mac, BWN_PHY_ADIVRELATED) & 0xff00) |
2516203945Sweongyo			    8);
2517203945Sweongyo	}
2518203945Sweongyo	if (phy->rev >= 6)
2519203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_OFDM9B, 0xdc);
2520203945Sweongyo
2521203945Sweongyo	hf |= BWN_HF_UCODE_ANTDIV_HELPER;
2522203945Sweongyo	bwn_hf_write(mac, hf);
2523203945Sweongyo}
2524203945Sweongyo
2525203945Sweongyostatic int
2526203945Sweongyobwn_phy_g_im(struct bwn_mac *mac, int mode)
2527203945Sweongyo{
2528203945Sweongyo	struct bwn_phy *phy = &mac->mac_phy;
2529203945Sweongyo	struct bwn_phy_g *pg = &phy->phy_g;
2530203945Sweongyo
2531203945Sweongyo	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2532203945Sweongyo	KASSERT(mode == BWN_IMMODE_NONE, ("%s: fail", __func__));
2533203945Sweongyo
2534203945Sweongyo	if (phy->rev == 0 || !phy->gmode)
2535203945Sweongyo		return (ENODEV);
2536203945Sweongyo
2537203945Sweongyo	pg->pg_aci_wlan_automatic = 0;
2538203945Sweongyo	return (0);
2539203945Sweongyo}
2540203945Sweongyo
2541203945Sweongyostatic int
2542203945Sweongyobwn_phy_g_recalc_txpwr(struct bwn_mac *mac, int ignore_tssi)
2543203945Sweongyo{
2544203945Sweongyo	struct bwn_phy *phy = &mac->mac_phy;
2545203945Sweongyo	struct bwn_phy_g *pg = &phy->phy_g;
2546203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
2547203945Sweongyo	unsigned int tssi;
2548203945Sweongyo	int cck, ofdm;
2549203945Sweongyo	int power;
2550203945Sweongyo	int rfatt, bbatt;
2551203945Sweongyo	unsigned int max;
2552203945Sweongyo
2553203945Sweongyo	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2554203945Sweongyo
2555203945Sweongyo	cck = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_CCK);
2556203945Sweongyo	ofdm = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_OFDM_G);
2557203945Sweongyo	if (cck < 0 && ofdm < 0) {
2558203945Sweongyo		if (ignore_tssi == 0)
2559203945Sweongyo			return (BWN_TXPWR_RES_DONE);
2560203945Sweongyo		cck = 0;
2561203945Sweongyo		ofdm = 0;
2562203945Sweongyo	}
2563203945Sweongyo	tssi = (cck < 0) ? ofdm : ((ofdm < 0) ? cck : (cck + ofdm) / 2);
2564203945Sweongyo	if (pg->pg_avgtssi != 0xff)
2565203945Sweongyo		tssi = (tssi + pg->pg_avgtssi) / 2;
2566203945Sweongyo	pg->pg_avgtssi = tssi;
2567203945Sweongyo	KASSERT(tssi < BWN_TSSI_MAX, ("%s:%d: fail", __func__, __LINE__));
2568203945Sweongyo
2569204922Sweongyo	max = siba_sprom_get_maxpwr_bg(sc->sc_dev);
2570204922Sweongyo	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
2571203945Sweongyo		max -= 3;
2572203945Sweongyo	if (max >= 120) {
2573203945Sweongyo		device_printf(sc->sc_dev, "invalid max TX-power value\n");
2574204922Sweongyo		max = 80;
2575204922Sweongyo		siba_sprom_set_maxpwr_bg(sc->sc_dev, max);
2576203945Sweongyo	}
2577203945Sweongyo
2578203945Sweongyo	power = MIN(MAX((phy->txpower < 0) ? 0 : (phy->txpower << 2), 0), max) -
2579203945Sweongyo	    (pg->pg_tssi2dbm[MIN(MAX(pg->pg_idletssi - pg->pg_curtssi +
2580203945Sweongyo	     tssi, 0x00), 0x3f)]);
2581203945Sweongyo	if (power == 0)
2582203945Sweongyo		return (BWN_TXPWR_RES_DONE);
2583203945Sweongyo
2584203945Sweongyo	rfatt = -((power + 7) / 8);
2585203945Sweongyo	bbatt = (-(power / 2)) - (4 * rfatt);
2586203945Sweongyo	if ((rfatt == 0) && (bbatt == 0))
2587203945Sweongyo		return (BWN_TXPWR_RES_DONE);
2588203945Sweongyo	pg->pg_bbatt_delta = bbatt;
2589203945Sweongyo	pg->pg_rfatt_delta = rfatt;
2590203945Sweongyo	return (BWN_TXPWR_RES_NEED_ADJUST);
2591203945Sweongyo}
2592203945Sweongyo
2593203945Sweongyostatic void
2594203945Sweongyobwn_phy_g_set_txpwr(struct bwn_mac *mac)
2595203945Sweongyo{
2596203945Sweongyo	struct bwn_phy *phy = &mac->mac_phy;
2597203945Sweongyo	struct bwn_phy_g *pg = &phy->phy_g;
2598203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
2599203945Sweongyo	int rfatt, bbatt;
2600203945Sweongyo	uint8_t txctl;
2601203945Sweongyo
2602203945Sweongyo	bwn_mac_suspend(mac);
2603203945Sweongyo
2604203945Sweongyo	BWN_ASSERT_LOCKED(sc);
2605203945Sweongyo
2606203945Sweongyo	bbatt = pg->pg_bbatt.att;
2607203945Sweongyo	bbatt += pg->pg_bbatt_delta;
2608203945Sweongyo	rfatt = pg->pg_rfatt.att;
2609203945Sweongyo	rfatt += pg->pg_rfatt_delta;
2610203945Sweongyo
2611203945Sweongyo	bwn_phy_g_setatt(mac, &bbatt, &rfatt);
2612203945Sweongyo	txctl = pg->pg_txctl;
2613203945Sweongyo	if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 2)) {
2614203945Sweongyo		if (rfatt <= 1) {
2615203945Sweongyo			if (txctl == 0) {
2616203945Sweongyo				txctl = BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX;
2617203945Sweongyo				rfatt += 2;
2618203945Sweongyo				bbatt += 2;
2619204922Sweongyo			} else if (siba_sprom_get_bf_lo(sc->sc_dev) &
2620204922Sweongyo			    BWN_BFL_PACTRL) {
2621203945Sweongyo				bbatt += 4 * (rfatt - 2);
2622203945Sweongyo				rfatt = 2;
2623203945Sweongyo			}
2624203945Sweongyo		} else if (rfatt > 4 && txctl) {
2625203945Sweongyo			txctl = 0;
2626203945Sweongyo			if (bbatt < 3) {
2627203945Sweongyo				rfatt -= 3;
2628203945Sweongyo				bbatt += 2;
2629203945Sweongyo			} else {
2630203945Sweongyo				rfatt -= 2;
2631203945Sweongyo				bbatt -= 2;
2632203945Sweongyo			}
2633203945Sweongyo		}
2634203945Sweongyo	}
2635203945Sweongyo	pg->pg_txctl = txctl;
2636203945Sweongyo	bwn_phy_g_setatt(mac, &bbatt, &rfatt);
2637203945Sweongyo	pg->pg_rfatt.att = rfatt;
2638203945Sweongyo	pg->pg_bbatt.att = bbatt;
2639203945Sweongyo
2640203945Sweongyo	DPRINTF(sc, BWN_DEBUG_TXPOW, "%s: adjust TX power\n", __func__);
2641203945Sweongyo
2642203945Sweongyo	bwn_phy_lock(mac);
2643203945Sweongyo	bwn_rf_lock(mac);
2644203945Sweongyo	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
2645203945Sweongyo	    pg->pg_txctl);
2646203945Sweongyo	bwn_rf_unlock(mac);
2647203945Sweongyo	bwn_phy_unlock(mac);
2648203945Sweongyo
2649203945Sweongyo	bwn_mac_enable(mac);
2650203945Sweongyo}
2651203945Sweongyo
2652203945Sweongyostatic void
2653203945Sweongyobwn_phy_g_task_15s(struct bwn_mac *mac)
2654203945Sweongyo{
2655203945Sweongyo	struct bwn_phy *phy = &mac->mac_phy;
2656203945Sweongyo	struct bwn_phy_g *pg = &phy->phy_g;
2657203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
2658203945Sweongyo	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2659203945Sweongyo	unsigned long expire, now;
2660203945Sweongyo	struct bwn_lo_calib *cal, *tmp;
2661203945Sweongyo	uint8_t expired = 0;
2662203945Sweongyo
2663203945Sweongyo	bwn_mac_suspend(mac);
2664203945Sweongyo
2665203945Sweongyo	if (lo == NULL)
2666203945Sweongyo		goto fail;
2667203945Sweongyo
2668203945Sweongyo	BWN_GETTIME(now);
2669203945Sweongyo	if (bwn_has_hwpctl(mac)) {
2670203945Sweongyo		expire = now - BWN_LO_PWRVEC_EXPIRE;
2671203945Sweongyo		if (time_before(lo->pwr_vec_read_time, expire)) {
2672203945Sweongyo			bwn_lo_get_powervector(mac);
2673203945Sweongyo			bwn_phy_g_dc_lookup_init(mac, 0);
2674203945Sweongyo		}
2675203945Sweongyo		goto fail;
2676203945Sweongyo	}
2677203945Sweongyo
2678203945Sweongyo	expire = now - BWN_LO_CALIB_EXPIRE;
2679203945Sweongyo	TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
2680203945Sweongyo		if (!time_before(cal->calib_time, expire))
2681203945Sweongyo			continue;
2682203945Sweongyo		if (BWN_BBATTCMP(&cal->bbatt, &pg->pg_bbatt) &&
2683203945Sweongyo		    BWN_RFATTCMP(&cal->rfatt, &pg->pg_rfatt)) {
2684203945Sweongyo			KASSERT(!expired, ("%s:%d: fail", __func__, __LINE__));
2685203945Sweongyo			expired = 1;
2686203945Sweongyo		}
2687203945Sweongyo
2688203945Sweongyo		DPRINTF(sc, BWN_DEBUG_LO, "expired BB %u RF %u %u I %d Q %d\n",
2689203945Sweongyo		    cal->bbatt.att, cal->rfatt.att, cal->rfatt.padmix,
2690203945Sweongyo		    cal->ctl.i, cal->ctl.q);
2691203945Sweongyo
2692203945Sweongyo		TAILQ_REMOVE(&lo->calib_list, cal, list);
2693203945Sweongyo		free(cal, M_DEVBUF);
2694203945Sweongyo	}
2695203945Sweongyo	if (expired || TAILQ_EMPTY(&lo->calib_list)) {
2696203945Sweongyo		cal = bwn_lo_calibset(mac, &pg->pg_bbatt,
2697203945Sweongyo		    &pg->pg_rfatt);
2698203945Sweongyo		if (cal == NULL) {
2699203945Sweongyo			device_printf(sc->sc_dev,
2700203945Sweongyo			    "failed to recalibrate LO\n");
2701203945Sweongyo			goto fail;
2702203945Sweongyo		}
2703203945Sweongyo		TAILQ_INSERT_TAIL(&lo->calib_list, cal, list);
2704203945Sweongyo		bwn_lo_write(mac, &cal->ctl);
2705203945Sweongyo	}
2706203945Sweongyo
2707203945Sweongyofail:
2708203945Sweongyo	bwn_mac_enable(mac);
2709203945Sweongyo}
2710203945Sweongyo
2711203945Sweongyostatic void
2712203945Sweongyobwn_phy_g_task_60s(struct bwn_mac *mac)
2713203945Sweongyo{
2714203945Sweongyo	struct bwn_phy *phy = &mac->mac_phy;
2715204922Sweongyo	struct bwn_softc *sc = mac->mac_sc;
2716203945Sweongyo	uint8_t old = phy->chan;
2717203945Sweongyo
2718204922Sweongyo	if (!(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI))
2719203945Sweongyo		return;
2720203945Sweongyo
2721203945Sweongyo	bwn_mac_suspend(mac);
2722203945Sweongyo	bwn_nrssi_slope_11g(mac);
2723203945Sweongyo	if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 8)) {
2724203945Sweongyo		bwn_switch_channel(mac, (old >= 8) ? 1 : 13);
2725203945Sweongyo		bwn_switch_channel(mac, old);
2726203945Sweongyo	}
2727203945Sweongyo	bwn_mac_enable(mac);
2728203945Sweongyo}
2729203945Sweongyo
2730203945Sweongyostatic void
2731203945Sweongyobwn_phy_switch_analog(struct bwn_mac *mac, int on)
2732203945Sweongyo{
2733203945Sweongyo
2734203945Sweongyo	BWN_WRITE_2(mac, BWN_PHY0, on ? 0 : 0xf4);
2735203945Sweongyo}
2736203945Sweongyo
2737203945Sweongyostatic int
2738203945Sweongyobwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
2739203945Sweongyo	const struct ieee80211_bpf_params *params)
2740203945Sweongyo{
2741203945Sweongyo	struct ieee80211com *ic = ni->ni_ic;
2742203945Sweongyo	struct ifnet *ifp = ic->ic_ifp;
2743203945Sweongyo	struct bwn_softc *sc = ifp->if_softc;
2744203945Sweongyo	struct bwn_mac *mac = sc->sc_curmac;
2745203945Sweongyo
2746203945Sweongyo	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
2747203945Sweongyo	    mac->mac_status < BWN_MAC_STATUS_STARTED) {
2748203945Sweongyo		ieee80211_free_node(ni);
2749203945Sweongyo		m_freem(m);
2750203945Sweongyo		return (ENETDOWN);
2751203945Sweongyo	}
2752203945Sweongyo
2753203945Sweongyo	BWN_LOCK(sc);
2754203945Sweongyo	if (bwn_tx_isfull(sc, m)) {
2755203945Sweongyo		ieee80211_free_node(ni);
2756203945Sweongyo		m_freem(m);
2757203945Sweongyo		ifp->if_oerrors++;
2758203945Sweongyo		BWN_UNLOCK(sc);
2759203945Sweongyo		return (ENOBUFS);
2760203945Sweongyo	}
2761203945Sweongyo
2762203945Sweongyo	if (bwn_tx_start(sc, ni, m) != 0) {
2763203945Sweongyo		if (ni != NULL)
2764203945Sweongyo			ieee80211_free_node(ni);
2765203945Sweongyo		ifp->if_oerrors++;
2766203945Sweongyo	}
2767203945Sweongyo	sc->sc_watchdog_timer = 5;
2768203945Sweongyo	BWN_UNLOCK(sc);
2769203945Sweongyo	return (0);
2770203945Sweongyo}
2771203945Sweongyo
2772203945Sweongyo/*
2773203945Sweongyo * Setup driver-specific state for a newly associated node.
2774203945Sweongyo * Note that we're called also on a re-associate, the isnew
2775203945Sweongyo * param tells us if this is the first time or not.
2776203945Sweongyo */
2777203945Sweongyostatic void
2778203945Sweongyobwn_newassoc(struct ieee80211_node *ni, int isnew)
2779203945Sweongyo{
2780203945Sweongyo	struct ieee80211vap *vap = ni->ni_vap;
2781203945Sweongyo
2782203945Sweongyo	ieee80211_amrr_node_init(&BWN_VAP(vap)->bv_amrr,
2783203945Sweongyo	    &BWN_NODE(ni)->bn_amn, ni);
2784203945Sweongyo}
2785203945Sweongyo
2786203945Sweongyo/*
2787203945Sweongyo * Callback from the 802.11 layer to update the slot time
2788203945Sweongyo * based on the current setting.  We use it to notify the
2789203945Sweongyo * firmware of ERP changes and the f/w takes care of things
2790203945Sweongyo * like slot time and preamble.
2791203945Sweongyo */
2792203945Sweongyostatic void
2793203945Sweongyobwn_updateslot(struct ifnet *ifp)
2794203945Sweongyo{
2795203945Sweongyo	struct bwn_softc *sc = ifp->if_softc;
2796203945Sweongyo	struct ieee80211com *ic = ifp->if_l2com;
2797203945Sweongyo	struct bwn_mac *mac;
2798203945Sweongyo
2799203945Sweongyo	BWN_LOCK(sc);
2800203945Sweongyo	if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
2801203945Sweongyo		mac = (struct bwn_mac *)sc->sc_curmac;
2802203945Sweongyo		bwn_set_slot_time(mac,
2803203945Sweongyo		    (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20);
2804203945Sweongyo	}
2805203945Sweongyo	BWN_UNLOCK(sc);
2806203945Sweongyo}
2807203945Sweongyo
2808203945Sweongyo/*
2809203945Sweongyo * Callback from the 802.11 layer after a promiscuous mode change.
2810203945Sweongyo * Note this interface does not check the operating mode as this
2811203945Sweongyo * is an internal callback and we are expected to honor the current
2812203945Sweongyo * state (e.g. this is used for setting the interface in promiscuous
2813203945Sweongyo * mode when operating in hostap mode to do ACS).
2814203945Sweongyo */
2815203945Sweongyostatic void
2816203945Sweongyobwn_update_promisc(struct ifnet *ifp)
2817203945Sweongyo{
2818203945Sweongyo	struct bwn_softc *sc = ifp->if_softc;
2819203945Sweongyo	struct bwn_mac *mac = sc->sc_curmac;
2820203945Sweongyo
2821203945Sweongyo	BWN_LOCK(sc);
2822203945Sweongyo	mac = sc->sc_curmac;
2823203945Sweongyo	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2824203945Sweongyo		if (ifp->if_flags & IFF_PROMISC)
2825203945Sweongyo			sc->sc_filters |= BWN_MACCTL_PROMISC;
2826203945Sweongyo		else
2827203945Sweongyo			sc->sc_filters &= ~BWN_MACCTL_PROMISC;
2828203945Sweongyo		bwn_set_opmode(mac);
2829203945Sweongyo	}
2830203945Sweongyo	BWN_UNLOCK(sc);
2831203945Sweongyo}
2832203945Sweongyo
2833203945Sweongyo/*
2834203945Sweongyo * Callback from the 802.11 layer to update WME parameters.
2835203945Sweongyo */
2836203945Sweongyostatic int
2837203945Sweongyobwn_wme_update(struct ieee80211com *ic)
2838203945Sweongyo{
2839203945Sweongyo	struct bwn_softc *sc = ic->ic_ifp->if_softc;
2840203945Sweongyo	struct bwn_mac *mac = sc->sc_curmac;
2841203945Sweongyo	struct wmeParams *wmep;
2842203945Sweongyo	int i;
2843203945Sweongyo
2844203945Sweongyo	BWN_LOCK(sc);
2845203945Sweongyo	mac = sc->sc_curmac;
2846203945Sweongyo	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2847203945Sweongyo		bwn_mac_suspend(mac);
2848203945Sweongyo		for (i = 0; i < N(sc->sc_wmeParams); i++) {
2849203945Sweongyo			wmep = &ic->ic_wme.wme_chanParams.cap_wmeParams[i];
2850203945Sweongyo			bwn_wme_loadparams(mac, wmep, bwn_wme_shm_offsets[i]);
2851203945Sweongyo		}
2852203945Sweongyo		bwn_mac_enable(mac);
2853203945Sweongyo	}
2854203945Sweongyo	BWN_UNLOCK(sc);
2855203945Sweongyo	return (0);
2856203945Sweongyo}
2857203945Sweongyo
2858203945Sweongyostatic struct ieee80211_node *
2859203945Sweongyobwn_node_alloc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN])
2860203945Sweongyo{
2861203945Sweongyo	struct ieee80211com *ic = vap->iv_ic;
2862203945Sweongyo	struct bwn_softc *sc = ic->ic_ifp->if_softc;
2863203945Sweongyo	const size_t space = sizeof(struct bwn_node);
2864203945Sweongyo	struct bwn_node *bn;
2865203945Sweongyo
2866203945Sweongyo	bn = malloc(space, M_80211_NODE, M_NOWAIT|M_ZERO);
2867203945Sweongyo	if (bn == NULL) {
2868203945Sweongyo		/* XXX stat+msg */
2869203945Sweongyo		return (NULL);
2870203945Sweongyo	}
2871203945Sweongyo	DPRINTF(sc, BWN_DEBUG_NODE, "%s: bn %p\n", __func__, bn);
2872203945Sweongyo	return (&bn->bn_node);
2873203945Sweongyo}
2874203945Sweongyo
2875203945Sweongyostatic void
2876203945Sweongyobwn_node_cleanup(struct ieee80211_node *ni)
2877203945Sweongyo{
2878203945Sweongyo	struct ieee80211com *ic = ni->ni_ic;
2879203945Sweongyo	struct bwn_softc *sc = ic->ic_ifp->if_softc;
2880203945Sweongyo
2881203945Sweongyo	sc->sc_node_cleanup(ni);
2882203945Sweongyo}
2883203945Sweongyo
2884203945Sweongyostatic void
2885203945Sweongyobwn_scan_start(struct ieee80211com *ic)
2886203945Sweongyo{
2887203945Sweongyo	struct ifnet *ifp = ic->ic_ifp;
2888203945Sweongyo	struct bwn_softc *sc = ifp->if_softc;
2889203945Sweongyo	struct bwn_mac *mac;
2890203945Sweongyo
2891203945Sweongyo	BWN_LOCK(sc);
2892203945Sweongyo	mac = sc->sc_curmac;
2893203945Sweongyo	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2894203945Sweongyo		sc->sc_filters |= BWN_MACCTL_BEACON_PROMISC;
2895203945Sweongyo		bwn_set_opmode(mac);
2896203945Sweongyo		/* disable CFP update during scan */
2897203945Sweongyo		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_SKIP_CFP_UPDATE);
2898203945Sweongyo	}
2899203945Sweongyo	BWN_UNLOCK(sc);
2900203945Sweongyo}
2901203945Sweongyo
2902203945Sweongyostatic void
2903203945Sweongyobwn_scan_end(struct ieee80211com *ic)
2904203945Sweongyo{
2905203945Sweongyo	struct ifnet *ifp = ic->ic_ifp;
2906203945Sweongyo	struct bwn_softc *sc = ifp->if_softc;
2907203945Sweongyo	struct bwn_mac *mac;
2908203945Sweongyo
2909203945Sweongyo	BWN_LOCK(sc);
2910203945Sweongyo	mac = sc->sc_curmac;
2911203945Sweongyo	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2912203945Sweongyo		sc->sc_filters &= ~BWN_MACCTL_BEACON_PROMISC;
2913203945Sweongyo		bwn_set_opmode(mac);
2914203945Sweongyo		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_SKIP_CFP_UPDATE);
2915203945Sweongyo	}
2916203945Sweongyo	BWN_UNLOCK(sc);
2917203945Sweongyo}
2918203945Sweongyo
2919203945Sweongyostatic void
2920203945Sweongyobwn_set_channel(struct ieee80211com *ic)
2921203945Sweongyo{
2922203945Sweongyo	struct ifnet *ifp = ic->ic_ifp;
2923203945Sweongyo	struct bwn_softc *sc = ifp->if_softc;
2924203945Sweongyo	struct bwn_mac *mac = sc->sc_curmac;
2925203945Sweongyo	struct bwn_phy *phy = &mac->mac_phy;
2926203945Sweongyo	int chan, error;
2927203945Sweongyo
2928203945Sweongyo	BWN_LOCK(sc);
2929203945Sweongyo
2930203945Sweongyo	error = bwn_switch_band(sc, ic->ic_curchan);
2931203945Sweongyo	if (error)
2932203945Sweongyo		goto fail;;
2933203945Sweongyo	bwn_mac_suspend(mac);
2934203945Sweongyo	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
2935203945Sweongyo	chan = ieee80211_chan2ieee(ic, ic->ic_curchan);
2936203945Sweongyo	if (chan != phy->chan)
2937203945Sweongyo		bwn_switch_channel(mac, chan);
2938203945Sweongyo
2939203945Sweongyo	/* TX power level */
2940203945Sweongyo	if (ic->ic_curchan->ic_maxpower != 0 &&
2941203945Sweongyo	    ic->ic_curchan->ic_maxpower != phy->txpower) {
2942203945Sweongyo		phy->txpower = ic->ic_curchan->ic_maxpower / 2;
2943203945Sweongyo		bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME |
2944203945Sweongyo		    BWN_TXPWR_IGNORE_TSSI);
2945203945Sweongyo	}
2946203945Sweongyo
2947203945Sweongyo	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
2948203945Sweongyo	if (phy->set_antenna)
2949203945Sweongyo		phy->set_antenna(mac, BWN_ANT_DEFAULT);
2950203945Sweongyo
2951203945Sweongyo	if (sc->sc_rf_enabled != phy->rf_on) {
2952203945Sweongyo		if (sc->sc_rf_enabled) {
2953203945Sweongyo			bwn_rf_turnon(mac);
2954203945Sweongyo			if (!(mac->mac_flags & BWN_MAC_FLAG_RADIO_ON))
2955203945Sweongyo				device_printf(sc->sc_dev,
2956203945Sweongyo				    "please turns on the RF switch\n");
2957203945Sweongyo		} else
2958203945Sweongyo			bwn_rf_turnoff(mac);
2959203945Sweongyo	}
2960203945Sweongyo
2961203945Sweongyo	bwn_mac_enable(mac);
2962203945Sweongyo
2963203945Sweongyofail:
2964203945Sweongyo	/*
2965203945Sweongyo	 * Setup radio tap channel freq and flags
2966203945Sweongyo	 */
2967203945Sweongyo	sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq =
2968203945Sweongyo		htole16(ic->ic_curchan->ic_freq);
2969203945Sweongyo	sc->sc_tx_th.wt_chan_flags = sc->sc_rx_th.wr_chan_flags =
2970203945Sweongyo		htole16(ic->ic_curchan->ic_flags & 0xffff);
2971203945Sweongyo
2972203945Sweongyo	BWN_UNLOCK(sc);
2973203945Sweongyo}
2974203945Sweongyo
2975203945Sweongyostatic struct ieee80211vap *
2976203945Sweongyobwn_vap_create(struct ieee80211com *ic,
2977203945Sweongyo	const char name[IFNAMSIZ], int unit, int opmode, int flags,
2978203945Sweongyo	const uint8_t bssid[IEEE80211_ADDR_LEN],
2979203945Sweongyo	const uint8_t mac0[IEEE80211_ADDR_LEN])
2980203945Sweongyo{
2981203945Sweongyo	struct ifnet *ifp = ic->ic_ifp;
2982203945Sweongyo	struct bwn_softc *sc = ifp->if_softc;
2983203945Sweongyo	struct ieee80211vap *vap;
2984203945Sweongyo	struct bwn_vap *bvp;
2985203945Sweongyo	uint8_t mac[IEEE80211_ADDR_LEN];
2986203945Sweongyo
2987203945Sweongyo	IEEE80211_ADDR_COPY(mac, mac0);
2988203945Sweongyo	switch (opmode) {
2989203945Sweongyo	case IEEE80211_M_HOSTAP:
2990203945Sweongyo	case IEEE80211_M_MBSS:
2991203945Sweongyo	case IEEE80211_M_STA:
2992203945Sweongyo	case IEEE80211_M_WDS:
2993203945Sweongyo	case IEEE80211_M_MONITOR:
2994203945Sweongyo	case IEEE80211_M_IBSS:
2995203945Sweongyo	case IEEE80211_M_AHDEMO:
2996203945Sweongyo		break;
2997203945Sweongyo	default:
2998203945Sweongyo		return (NULL);
2999203945Sweongyo	}
3000203945Sweongyo
3001203945Sweongyo	IEEE80211_ADDR_COPY(sc->sc_macaddr, mac0);
3002203945Sweongyo
3003203945Sweongyo	bvp = (struct bwn_vap *) malloc(sizeof(struct bwn_vap),
3004203945Sweongyo	    M_80211_VAP, M_NOWAIT | M_ZERO);
3005203945Sweongyo	if (bvp == NULL) {
3006203945Sweongyo		device_printf(sc->sc_dev, "failed to allocate a buffer\n");
3007203945Sweongyo		return (NULL);
3008203945Sweongyo	}
3009203945Sweongyo	vap = &bvp->bv_vap;
3010203945Sweongyo	ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
3011203945Sweongyo	IEEE80211_ADDR_COPY(vap->iv_myaddr, mac);
3012203945Sweongyo	/* override with driver methods */
3013203945Sweongyo	bvp->bv_newstate = vap->iv_newstate;
3014203945Sweongyo	vap->iv_newstate = bwn_newstate;
3015203945Sweongyo
3016203945Sweongyo	/* override max aid so sta's cannot assoc when we're out of sta id's */
3017203945Sweongyo	vap->iv_max_aid = BWN_STAID_MAX;
3018203945Sweongyo
3019203945Sweongyo	ieee80211_amrr_init(&bvp->bv_amrr, vap,
3020203945Sweongyo	    IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD,
3021203945Sweongyo	    IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD,
3022203945Sweongyo	    500 /*ms*/);
3023203945Sweongyo
3024203945Sweongyo	/* complete setup */
3025203945Sweongyo	ieee80211_vap_attach(vap, ieee80211_media_change,
3026203945Sweongyo	    ieee80211_media_status);
3027203945Sweongyo	return (vap);
3028203945Sweongyo}
3029203945Sweongyo
3030203945Sweongyostatic void
3031203945Sweongyobwn_vap_delete(struct ieee80211vap *vap)
3032203945Sweongyo{
3033203945Sweongyo	struct bwn_vap *bvp = BWN_VAP(vap);
3034203945Sweongyo
3035203945Sweongyo	ieee80211_amrr_cleanup(&bvp->bv_amrr);
3036203945Sweongyo	ieee80211_vap_detach(vap);
3037203945Sweongyo	free(bvp, M_80211_VAP);
3038203945Sweongyo}
3039203945Sweongyo
3040203945Sweongyostatic void
3041203945Sweongyobwn_init(void *arg)
3042203945Sweongyo{
3043203945Sweongyo	struct bwn_softc *sc = arg;
3044203945Sweongyo	struct ifnet *ifp = sc->sc_ifp;
3045203945Sweongyo	struct ieee80211com *ic = ifp->if_l2com;
3046203945Sweongyo	int error = 0;
3047203945Sweongyo
3048203945Sweongyo	DPRINTF(sc, BWN_DEBUG_ANY, "%s: if_flags 0x%x\n",
3049203945Sweongyo		__func__, ifp->if_flags);
3050203945Sweongyo
3051203945Sweongyo	BWN_LOCK(sc);
3052203945Sweongyo	error = bwn_init_locked(sc);
3053203945Sweongyo	BWN_UNLOCK(sc);
3054203945Sweongyo
3055203945Sweongyo	if (error == 0)
3056203945Sweongyo		ieee80211_start_all(ic);	/* start all vap's */
3057203945Sweongyo}
3058203945Sweongyo
3059203945Sweongyostatic int
3060203945Sweongyobwn_init_locked(struct bwn_softc *sc)
3061203945Sweongyo{
3062203945Sweongyo	struct bwn_mac *mac;
3063203945Sweongyo	struct ifnet *ifp = sc->sc_ifp;
3064203945Sweongyo	int error;
3065203945Sweongyo
3066203945Sweongyo	BWN_ASSERT_LOCKED(sc);
3067203945Sweongyo
3068203945Sweongyo	bzero(sc->sc_bssid, IEEE80211_ADDR_LEN);
3069203945Sweongyo	sc->sc_flags |= BWN_FLAG_NEED_BEACON_TP;
3070203945Sweongyo	sc->sc_filters = 0;
3071203945Sweongyo	bwn_wme_clear(sc);
3072203945Sweongyo	sc->sc_beacons[0] = sc->sc_beacons[1] = 0;
3073203945Sweongyo	sc->sc_rf_enabled = 1;
3074203945Sweongyo
3075203945Sweongyo	mac = sc->sc_curmac;
3076203945Sweongyo	if (mac->mac_status == BWN_MAC_STATUS_UNINIT) {
3077203945Sweongyo		error = bwn_core_init(mac);
3078203945Sweongyo		if (error != 0)
3079203945Sweongyo			return (error);
3080203945Sweongyo	}
3081203945Sweongyo	if (mac->mac_status == BWN_MAC_STATUS_INITED)
3082203945Sweongyo		bwn_core_start(mac);
3083203945Sweongyo
3084203945Sweongyo	bwn_set_opmode(mac);
3085203945Sweongyo	bwn_set_pretbtt(mac);
3086203945Sweongyo	bwn_spu_setdelay(mac, 0);
3087203945Sweongyo	bwn_set_macaddr(mac);
3088203945Sweongyo
3089203945Sweongyo	ifp->if_drv_flags |= IFF_DRV_RUNNING;
3090203945Sweongyo	callout_reset(&sc->sc_rfswitch_ch, hz, bwn_rfswitch, sc);
3091203945Sweongyo	callout_reset(&sc->sc_watchdog_ch, hz, bwn_watchdog, sc);
3092203945Sweongyo
3093203945Sweongyo	return (0);
3094203945Sweongyo}
3095203945Sweongyo
3096203945Sweongyostatic void
3097203945Sweongyobwn_stop(struct bwn_softc *sc, int statechg)
3098203945Sweongyo{
3099203945Sweongyo
3100203945Sweongyo	BWN_LOCK(sc);
3101203945Sweongyo	bwn_stop_locked(sc, statechg);
3102203945Sweongyo	BWN_UNLOCK(sc);
3103203945Sweongyo}
3104203945Sweongyo
3105203945Sweongyostatic void
3106203945Sweongyobwn_stop_locked(struct bwn_softc *sc, int statechg)
3107203945Sweongyo{
3108203945Sweongyo	struct bwn_mac *mac = sc->sc_curmac;
3109203945Sweongyo	struct ifnet *ifp = sc->sc_ifp;
3110203945Sweongyo
3111203945Sweongyo	BWN_ASSERT_LOCKED(sc);
3112203945Sweongyo
3113203945Sweongyo	if (mac->mac_status >= BWN_MAC_STATUS_INITED) {
3114203945Sweongyo		/* XXX FIXME opmode not based on VAP */
3115203945Sweongyo		bwn_set_opmode(mac);
3116203945Sweongyo		bwn_set_macaddr(mac);
3117203945Sweongyo	}
3118203945Sweongyo
3119203945Sweongyo	if (mac->mac_status >= BWN_MAC_STATUS_STARTED)
3120203945Sweongyo		bwn_core_stop(mac);
3121203945Sweongyo
3122203945Sweongyo	callout_stop(&sc->sc_led_blink_ch);
3123203945Sweongyo	sc->sc_led_blinking = 0;
3124203945Sweongyo
3125203945Sweongyo	bwn_core_exit(mac);
3126203945Sweongyo	sc->sc_rf_enabled = 0;
3127203945Sweongyo
3128203945Sweongyo	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
3129203945Sweongyo}
3130203945Sweongyo
3131203945Sweongyostatic void
3132203945Sweongyobwn_wme_clear(struct bwn_softc *sc)
3133203945Sweongyo{
3134203945Sweongyo#define	MS(_v, _f)	(((_v) & _f) >> _f##_S)
3135203945Sweongyo	struct wmeParams *p;
3136203945Sweongyo	unsigned int i;
3137203945Sweongyo
3138203945Sweongyo	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
3139203945Sweongyo	    ("%s:%d: fail", __func__, __LINE__));
3140203945Sweongyo
3141203945Sweongyo	for (i = 0; i < N(sc->sc_wmeParams); i++) {
3142203945Sweongyo		p = &(sc->sc_wmeParams[i]);
3143203945Sweongyo
3144203945Sweongyo		switch (bwn_wme_shm_offsets[i]) {
3145203945Sweongyo		case BWN_WME_VOICE:
3146203945Sweongyo			p->wmep_txopLimit = 0;
3147203945Sweongyo			p->wmep_aifsn = 2;
3148203945Sweongyo			/* XXX FIXME: log2(cwmin) */
3149203945Sweongyo			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3150203945Sweongyo			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3151203945Sweongyo			break;
3152203945Sweongyo		case BWN_WME_VIDEO:
3153203945Sweongyo			p->wmep_txopLimit = 0;
3154203945Sweongyo			p->wmep_aifsn = 2;
3155203945Sweongyo			/* XXX FIXME: log2(cwmin) */
3156203945Sweongyo			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3157203945Sweongyo			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3158203945Sweongyo			break;
3159203945Sweongyo		case BWN_WME_BESTEFFORT:
3160203945Sweongyo			p->wmep_txopLimit = 0;
3161203945Sweongyo			p->wmep_aifsn = 3;
3162203945Sweongyo			/* XXX FIXME: log2(cwmin) */
3163203945Sweongyo			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3164203945Sweongyo			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3165203945Sweongyo			break;
3166203945Sweongyo		case BWN_WME_BACKGROUND:
3167203945Sweongyo			p->wmep_txopLimit = 0;
3168203945Sweongyo			p->wmep_aifsn = 7;
3169203945Sweongyo			/* XXX FIXME: log2(cwmin) */
3170203945Sweongyo			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3171203945Sweongyo			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3172203945Sweongyo			break;
3173203945Sweongyo		default:
3174203945Sweongyo			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3175203945Sweongyo		}
3176203945Sweongyo	}
3177203945Sweongyo}
3178203945Sweongyo
3179203945Sweongyostatic int
3180203945Sweongyobwn_core_init(struct bwn_mac *mac)
3181203945Sweongyo{
3182203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
3183203945Sweongyo	uint64_t hf;
3184203945Sweongyo	int error;
3185203945Sweongyo
3186203945Sweongyo	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3187203945Sweongyo	    ("%s:%d: fail", __func__, __LINE__));
3188203945Sweongyo
3189204922Sweongyo	siba_powerup(sc->sc_dev, 0);
3190204922Sweongyo	if (!siba_dev_isup(sc->sc_dev))
3191203945Sweongyo		bwn_reset_core(mac,
3192203945Sweongyo		    mac->mac_phy.gmode ? BWN_TGSLOW_SUPPORT_G : 0);
3193203945Sweongyo
3194203945Sweongyo	mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
3195203945Sweongyo	mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
3196203945Sweongyo	mac->mac_phy.hwpctl = (bwn_hwpctl) ? 1 : 0;
3197203945Sweongyo	BWN_GETTIME(mac->mac_phy.nexttime);
3198203945Sweongyo	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
3199203945Sweongyo	bzero(&mac->mac_stats, sizeof(mac->mac_stats));
3200203945Sweongyo	mac->mac_stats.link_noise = -95;
3201203945Sweongyo	mac->mac_reason_intr = 0;
3202203945Sweongyo	bzero(mac->mac_reason, sizeof(mac->mac_reason));
3203203945Sweongyo	mac->mac_intr_mask = BWN_INTR_MASKTEMPLATE;
3204203945Sweongyo#ifdef BWN_DEBUG
3205203945Sweongyo	if (sc->sc_debug & BWN_DEBUG_XMIT)
3206203945Sweongyo		mac->mac_intr_mask &= ~BWN_INTR_PHY_TXERR;
3207203945Sweongyo#endif
3208203945Sweongyo	mac->mac_suspended = 1;
3209203945Sweongyo	mac->mac_task_state = 0;
3210203945Sweongyo	memset(&mac->mac_noise, 0, sizeof(mac->mac_noise));
3211203945Sweongyo
3212203945Sweongyo	mac->mac_phy.init_pre(mac);
3213203945Sweongyo
3214204922Sweongyo	siba_pcicore_intr(sc->sc_dev);
3215203945Sweongyo
3216204922Sweongyo	siba_fix_imcfglobug(sc->sc_dev);
3217203945Sweongyo	bwn_bt_disable(mac);
3218203945Sweongyo	if (mac->mac_phy.prepare_hw) {
3219203945Sweongyo		error = mac->mac_phy.prepare_hw(mac);
3220203945Sweongyo		if (error)
3221203945Sweongyo			goto fail0;
3222203945Sweongyo	}
3223203945Sweongyo	error = bwn_chip_init(mac);
3224203945Sweongyo	if (error)
3225203945Sweongyo		goto fail0;
3226203945Sweongyo	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_COREREV,
3227204922Sweongyo	    siba_get_revid(sc->sc_dev));
3228203945Sweongyo	hf = bwn_hf_read(mac);
3229203945Sweongyo	if (mac->mac_phy.type == BWN_PHYTYPE_G) {
3230203945Sweongyo		hf |= BWN_HF_GPHY_SYM_WORKAROUND;
3231204922Sweongyo		if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
3232203945Sweongyo			hf |= BWN_HF_PAGAINBOOST_OFDM_ON;
3233203945Sweongyo		if (mac->mac_phy.rev == 1)
3234203945Sweongyo			hf |= BWN_HF_GPHY_DC_CANCELFILTER;
3235203945Sweongyo	}
3236203945Sweongyo	if (mac->mac_phy.rf_ver == 0x2050) {
3237203945Sweongyo		if (mac->mac_phy.rf_rev < 6)
3238203945Sweongyo			hf |= BWN_HF_FORCE_VCO_RECALC;
3239203945Sweongyo		if (mac->mac_phy.rf_rev == 6)
3240203945Sweongyo			hf |= BWN_HF_4318_TSSI;
3241203945Sweongyo	}
3242204922Sweongyo	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW)
3243203945Sweongyo		hf |= BWN_HF_SLOWCLOCK_REQ_OFF;
3244204922Sweongyo	if ((siba_get_type(sc->sc_dev) == SIBA_TYPE_PCI) &&
3245204922Sweongyo	    (siba_get_pcicore_revid(sc->sc_dev) <= 10))
3246203945Sweongyo		hf |= BWN_HF_PCI_SLOWCLOCK_WORKAROUND;
3247203945Sweongyo	hf &= ~BWN_HF_SKIP_CFP_UPDATE;
3248203945Sweongyo	bwn_hf_write(mac, hf);
3249203945Sweongyo
3250203945Sweongyo	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
3251203945Sweongyo	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SHORT_RETRY_FALLBACK, 3);
3252203945Sweongyo	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_LONG_RETRY_FALLBACK, 2);
3253203945Sweongyo	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_MAXTIME, 1);
3254203945Sweongyo
3255203945Sweongyo	bwn_rate_init(mac);
3256203945Sweongyo	bwn_set_phytxctl(mac);
3257203945Sweongyo
3258203945Sweongyo	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MIN,
3259203945Sweongyo	    (mac->mac_phy.type == BWN_PHYTYPE_B) ? 0x1f : 0xf);
3260203945Sweongyo	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MAX, 0x3ff);
3261203945Sweongyo
3262204922Sweongyo	if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
3263203945Sweongyo		bwn_pio_init(mac);
3264203945Sweongyo	else
3265203945Sweongyo		bwn_dma_init(mac);
3266203945Sweongyo	if (error)
3267203945Sweongyo		goto fail1;
3268203945Sweongyo	bwn_wme_init(mac);
3269203945Sweongyo	bwn_spu_setdelay(mac, 1);
3270203945Sweongyo	bwn_bt_enable(mac);
3271203945Sweongyo
3272204922Sweongyo	siba_powerup(sc->sc_dev,
3273204922Sweongyo	    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW));
3274203945Sweongyo	bwn_set_macaddr(mac);
3275203945Sweongyo	bwn_crypt_init(mac);
3276203945Sweongyo
3277203945Sweongyo	/* XXX LED initializatin */
3278203945Sweongyo
3279203945Sweongyo	mac->mac_status = BWN_MAC_STATUS_INITED;
3280203945Sweongyo
3281203945Sweongyo	return (error);
3282203945Sweongyo
3283203945Sweongyofail1:
3284203945Sweongyo	bwn_chip_exit(mac);
3285203945Sweongyofail0:
3286204922Sweongyo	siba_powerdown(sc->sc_dev);
3287203945Sweongyo	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3288203945Sweongyo	    ("%s:%d: fail", __func__, __LINE__));
3289203945Sweongyo	return (error);
3290203945Sweongyo}
3291203945Sweongyo
3292203945Sweongyostatic void
3293203945Sweongyobwn_core_start(struct bwn_mac *mac)
3294203945Sweongyo{
3295203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
3296203945Sweongyo	uint32_t tmp;
3297203945Sweongyo
3298203945Sweongyo	KASSERT(mac->mac_status == BWN_MAC_STATUS_INITED,
3299203945Sweongyo	    ("%s:%d: fail", __func__, __LINE__));
3300203945Sweongyo
3301204922Sweongyo	if (siba_get_revid(sc->sc_dev) < 5)
3302203945Sweongyo		return;
3303203945Sweongyo
3304203945Sweongyo	while (1) {
3305203945Sweongyo		tmp = BWN_READ_4(mac, BWN_XMITSTAT_0);
3306203945Sweongyo		if (!(tmp & 0x00000001))
3307203945Sweongyo			break;
3308203945Sweongyo		tmp = BWN_READ_4(mac, BWN_XMITSTAT_1);
3309203945Sweongyo	}
3310203945Sweongyo
3311203945Sweongyo	bwn_mac_enable(mac);
3312203945Sweongyo	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
3313203945Sweongyo	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
3314203945Sweongyo
3315203945Sweongyo	mac->mac_status = BWN_MAC_STATUS_STARTED;
3316203945Sweongyo}
3317203945Sweongyo
3318203945Sweongyostatic void
3319203945Sweongyobwn_core_exit(struct bwn_mac *mac)
3320203945Sweongyo{
3321204922Sweongyo	struct bwn_softc *sc = mac->mac_sc;
3322203945Sweongyo	uint32_t macctl;
3323203945Sweongyo
3324204242Simp	BWN_ASSERT_LOCKED(mac->mac_sc);
3325203945Sweongyo
3326203945Sweongyo	KASSERT(mac->mac_status <= BWN_MAC_STATUS_INITED,
3327203945Sweongyo	    ("%s:%d: fail", __func__, __LINE__));
3328203945Sweongyo
3329203945Sweongyo	if (mac->mac_status != BWN_MAC_STATUS_INITED)
3330203945Sweongyo		return;
3331203945Sweongyo	mac->mac_status = BWN_MAC_STATUS_UNINIT;
3332203945Sweongyo
3333203945Sweongyo	macctl = BWN_READ_4(mac, BWN_MACCTL);
3334203945Sweongyo	macctl &= ~BWN_MACCTL_MCODE_RUN;
3335203945Sweongyo	macctl |= BWN_MACCTL_MCODE_JMP0;
3336203945Sweongyo	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3337203945Sweongyo
3338203945Sweongyo	bwn_dma_stop(mac);
3339203945Sweongyo	bwn_pio_stop(mac);
3340203945Sweongyo	bwn_chip_exit(mac);
3341203945Sweongyo	mac->mac_phy.switch_analog(mac, 0);
3342204922Sweongyo	siba_dev_down(sc->sc_dev, 0);
3343204922Sweongyo	siba_powerdown(sc->sc_dev);
3344203945Sweongyo}
3345203945Sweongyo
3346203945Sweongyostatic void
3347203945Sweongyobwn_bt_disable(struct bwn_mac *mac)
3348203945Sweongyo{
3349203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
3350203945Sweongyo
3351203945Sweongyo	(void)sc;
3352203945Sweongyo	/* XXX do nothing yet */
3353203945Sweongyo}
3354203945Sweongyo
3355203945Sweongyostatic int
3356203945Sweongyobwn_chip_init(struct bwn_mac *mac)
3357203945Sweongyo{
3358204922Sweongyo	struct bwn_softc *sc = mac->mac_sc;
3359203945Sweongyo	struct bwn_phy *phy = &mac->mac_phy;
3360203945Sweongyo	uint32_t macctl;
3361203945Sweongyo	int error;
3362203945Sweongyo
3363203945Sweongyo	macctl = BWN_MACCTL_IHR_ON | BWN_MACCTL_SHM_ON | BWN_MACCTL_STA;
3364203945Sweongyo	if (phy->gmode)
3365203945Sweongyo		macctl |= BWN_MACCTL_GMODE;
3366203945Sweongyo	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3367203945Sweongyo
3368203945Sweongyo	error = bwn_fw_fillinfo(mac);
3369203945Sweongyo	if (error)
3370203945Sweongyo		return (error);
3371203945Sweongyo	error = bwn_fw_loaducode(mac);
3372203945Sweongyo	if (error)
3373203945Sweongyo		return (error);
3374203945Sweongyo
3375203945Sweongyo	error = bwn_gpio_init(mac);
3376203945Sweongyo	if (error)
3377203945Sweongyo		return (error);
3378203945Sweongyo
3379203945Sweongyo	error = bwn_fw_loadinitvals(mac);
3380203945Sweongyo	if (error) {
3381204922Sweongyo		siba_gpio_set(sc->sc_dev, 0);
3382203945Sweongyo		return (error);
3383203945Sweongyo	}
3384203945Sweongyo	phy->switch_analog(mac, 1);
3385203945Sweongyo	error = bwn_phy_init(mac);
3386203945Sweongyo	if (error) {
3387204922Sweongyo		siba_gpio_set(sc->sc_dev, 0);
3388203945Sweongyo		return (error);
3389203945Sweongyo	}
3390203945Sweongyo	if (phy->set_im)
3391203945Sweongyo		phy->set_im(mac, BWN_IMMODE_NONE);
3392203945Sweongyo	if (phy->set_antenna)
3393203945Sweongyo		phy->set_antenna(mac, BWN_ANT_DEFAULT);
3394203945Sweongyo	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
3395203945Sweongyo
3396203945Sweongyo	if (phy->type == BWN_PHYTYPE_B)
3397203945Sweongyo		BWN_WRITE_2(mac, 0x005e, BWN_READ_2(mac, 0x005e) | 0x0004);
3398203945Sweongyo	BWN_WRITE_4(mac, 0x0100, 0x01000000);
3399204922Sweongyo	if (siba_get_revid(sc->sc_dev) < 5)
3400203945Sweongyo		BWN_WRITE_4(mac, 0x010c, 0x01000000);
3401203945Sweongyo
3402203945Sweongyo	BWN_WRITE_4(mac, BWN_MACCTL,
3403203945Sweongyo	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_STA);
3404203945Sweongyo	BWN_WRITE_4(mac, BWN_MACCTL,
3405203945Sweongyo	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_STA);
3406203945Sweongyo	bwn_shm_write_2(mac, BWN_SHARED, 0x0074, 0x0000);
3407203945Sweongyo
3408203945Sweongyo	bwn_set_opmode(mac);
3409204922Sweongyo	if (siba_get_revid(sc->sc_dev) < 3) {
3410203945Sweongyo		BWN_WRITE_2(mac, 0x060e, 0x0000);
3411203945Sweongyo		BWN_WRITE_2(mac, 0x0610, 0x8000);
3412203945Sweongyo		BWN_WRITE_2(mac, 0x0604, 0x0000);
3413203945Sweongyo		BWN_WRITE_2(mac, 0x0606, 0x0200);
3414203945Sweongyo	} else {
3415203945Sweongyo		BWN_WRITE_4(mac, 0x0188, 0x80000000);
3416203945Sweongyo		BWN_WRITE_4(mac, 0x018c, 0x02000000);
3417203945Sweongyo	}
3418203945Sweongyo	BWN_WRITE_4(mac, BWN_INTR_REASON, 0x00004000);
3419203945Sweongyo	BWN_WRITE_4(mac, BWN_DMA0_INTR_MASK, 0x0001dc00);
3420203945Sweongyo	BWN_WRITE_4(mac, BWN_DMA1_INTR_MASK, 0x0000dc00);
3421203945Sweongyo	BWN_WRITE_4(mac, BWN_DMA2_INTR_MASK, 0x0000dc00);
3422203945Sweongyo	BWN_WRITE_4(mac, BWN_DMA3_INTR_MASK, 0x0001dc00);
3423203945Sweongyo	BWN_WRITE_4(mac, BWN_DMA4_INTR_MASK, 0x0000dc00);
3424203945Sweongyo	BWN_WRITE_4(mac, BWN_DMA5_INTR_MASK, 0x0000dc00);
3425204922Sweongyo	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
3426204922Sweongyo	    siba_read_4(sc->sc_dev, SIBA_TGSLOW) | 0x00100000);
3427204922Sweongyo	BWN_WRITE_2(mac, BWN_POWERUP_DELAY, siba_get_cc_powerdelay(sc->sc_dev));
3428203945Sweongyo	return (error);
3429203945Sweongyo}
3430203945Sweongyo
3431203945Sweongyo/* read hostflags */
3432203945Sweongyostatic uint64_t
3433203945Sweongyobwn_hf_read(struct bwn_mac *mac)
3434203945Sweongyo{
3435203945Sweongyo	uint64_t ret;
3436203945Sweongyo
3437203945Sweongyo	ret = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFHI);
3438203945Sweongyo	ret <<= 16;
3439203945Sweongyo	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFMI);
3440203945Sweongyo	ret <<= 16;
3441203945Sweongyo	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO);
3442203945Sweongyo	return (ret);
3443203945Sweongyo}
3444203945Sweongyo
3445203945Sweongyostatic void
3446203945Sweongyobwn_hf_write(struct bwn_mac *mac, uint64_t value)
3447203945Sweongyo{
3448203945Sweongyo
3449203945Sweongyo	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFLO,
3450203945Sweongyo	    (value & 0x00000000ffffull));
3451203945Sweongyo	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFMI,
3452203945Sweongyo	    (value & 0x0000ffff0000ull) >> 16);
3453203945Sweongyo	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFHI,
3454203945Sweongyo	    (value & 0xffff00000000ULL) >> 32);
3455203945Sweongyo}
3456203945Sweongyo
3457203945Sweongyostatic void
3458203945Sweongyobwn_set_txretry(struct bwn_mac *mac, int s, int l)
3459203945Sweongyo{
3460203945Sweongyo
3461203945Sweongyo	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_SHORT_RETRY, MIN(s, 0xf));
3462203945Sweongyo	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_LONG_RETRY, MIN(l, 0xf));
3463203945Sweongyo}
3464203945Sweongyo
3465203945Sweongyostatic void
3466203945Sweongyobwn_rate_init(struct bwn_mac *mac)
3467203945Sweongyo{
3468203945Sweongyo
3469203945Sweongyo	switch (mac->mac_phy.type) {
3470203945Sweongyo	case BWN_PHYTYPE_A:
3471203945Sweongyo	case BWN_PHYTYPE_G:
3472203945Sweongyo	case BWN_PHYTYPE_LP:
3473203945Sweongyo	case BWN_PHYTYPE_N:
3474203945Sweongyo		bwn_rate_write(mac, BWN_OFDM_RATE_6MB, 1);
3475203945Sweongyo		bwn_rate_write(mac, BWN_OFDM_RATE_12MB, 1);
3476203945Sweongyo		bwn_rate_write(mac, BWN_OFDM_RATE_18MB, 1);
3477203945Sweongyo		bwn_rate_write(mac, BWN_OFDM_RATE_24MB, 1);
3478203945Sweongyo		bwn_rate_write(mac, BWN_OFDM_RATE_36MB, 1);
3479203945Sweongyo		bwn_rate_write(mac, BWN_OFDM_RATE_48MB, 1);
3480203945Sweongyo		bwn_rate_write(mac, BWN_OFDM_RATE_54MB, 1);
3481203945Sweongyo		if (mac->mac_phy.type == BWN_PHYTYPE_A)
3482203945Sweongyo			break;
3483203945Sweongyo		/* FALLTHROUGH */
3484203945Sweongyo	case BWN_PHYTYPE_B:
3485203945Sweongyo		bwn_rate_write(mac, BWN_CCK_RATE_1MB, 0);
3486203945Sweongyo		bwn_rate_write(mac, BWN_CCK_RATE_2MB, 0);
3487203945Sweongyo		bwn_rate_write(mac, BWN_CCK_RATE_5MB, 0);
3488203945Sweongyo		bwn_rate_write(mac, BWN_CCK_RATE_11MB, 0);
3489203945Sweongyo		break;
3490203945Sweongyo	default:
3491203945Sweongyo		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3492203945Sweongyo	}
3493203945Sweongyo}
3494203945Sweongyo
3495203945Sweongyostatic void
3496203945Sweongyobwn_rate_write(struct bwn_mac *mac, uint16_t rate, int ofdm)
3497203945Sweongyo{
3498203945Sweongyo	uint16_t offset;
3499203945Sweongyo
3500203945Sweongyo	if (ofdm) {
3501203945Sweongyo		offset = 0x480;
3502203945Sweongyo		offset += (bwn_plcp_getofdm(rate) & 0x000f) * 2;
3503203945Sweongyo	} else {
3504203945Sweongyo		offset = 0x4c0;
3505203945Sweongyo		offset += (bwn_plcp_getcck(rate) & 0x000f) * 2;
3506203945Sweongyo	}
3507203945Sweongyo	bwn_shm_write_2(mac, BWN_SHARED, offset + 0x20,
3508203945Sweongyo	    bwn_shm_read_2(mac, BWN_SHARED, offset));
3509203945Sweongyo}
3510203945Sweongyo
3511203945Sweongyostatic uint8_t
3512203945Sweongyobwn_plcp_getcck(const uint8_t bitrate)
3513203945Sweongyo{
3514203945Sweongyo
3515203945Sweongyo	switch (bitrate) {
3516203945Sweongyo	case BWN_CCK_RATE_1MB:
3517203945Sweongyo		return (0x0a);
3518203945Sweongyo	case BWN_CCK_RATE_2MB:
3519203945Sweongyo		return (0x14);
3520203945Sweongyo	case BWN_CCK_RATE_5MB:
3521203945Sweongyo		return (0x37);
3522203945Sweongyo	case BWN_CCK_RATE_11MB:
3523203945Sweongyo		return (0x6e);
3524203945Sweongyo	}
3525203945Sweongyo	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3526203945Sweongyo	return (0);
3527203945Sweongyo}
3528203945Sweongyo
3529203945Sweongyostatic uint8_t
3530203945Sweongyobwn_plcp_getofdm(const uint8_t bitrate)
3531203945Sweongyo{
3532203945Sweongyo
3533203945Sweongyo	switch (bitrate) {
3534203945Sweongyo	case BWN_OFDM_RATE_6MB:
3535203945Sweongyo		return (0xb);
3536203945Sweongyo	case BWN_OFDM_RATE_9MB:
3537203945Sweongyo		return (0xf);
3538203945Sweongyo	case BWN_OFDM_RATE_12MB:
3539203945Sweongyo		return (0xa);
3540203945Sweongyo	case BWN_OFDM_RATE_18MB:
3541203945Sweongyo		return (0xe);
3542203945Sweongyo	case BWN_OFDM_RATE_24MB:
3543203945Sweongyo		return (0x9);
3544203945Sweongyo	case BWN_OFDM_RATE_36MB:
3545203945Sweongyo		return (0xd);
3546203945Sweongyo	case BWN_OFDM_RATE_48MB:
3547203945Sweongyo		return (0x8);
3548203945Sweongyo	case BWN_OFDM_RATE_54MB:
3549203945Sweongyo		return (0xc);
3550203945Sweongyo	}
3551203945Sweongyo	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3552203945Sweongyo	return (0);
3553203945Sweongyo}
3554203945Sweongyo
3555203945Sweongyostatic void
3556203945Sweongyobwn_set_phytxctl(struct bwn_mac *mac)
3557203945Sweongyo{
3558203945Sweongyo	uint16_t ctl;
3559203945Sweongyo
3560203945Sweongyo	ctl = (BWN_TX_PHY_ENC_CCK | BWN_TX_PHY_ANT01AUTO |
3561203945Sweongyo	    BWN_TX_PHY_TXPWR);
3562203945Sweongyo	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_BEACON_PHYCTL, ctl);
3563203945Sweongyo	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, ctl);
3564203945Sweongyo	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, ctl);
3565203945Sweongyo}
3566203945Sweongyo
3567203945Sweongyostatic void
3568203945Sweongyobwn_pio_init(struct bwn_mac *mac)
3569203945Sweongyo{
3570203945Sweongyo	struct bwn_pio *pio = &mac->mac_method.pio;
3571203945Sweongyo
3572203945Sweongyo	BWN_WRITE_4(mac, BWN_MACCTL, BWN_READ_4(mac, BWN_MACCTL)
3573203945Sweongyo	    & ~BWN_MACCTL_BIGENDIAN);
3574203945Sweongyo	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RX_PADOFFSET, 0);
3575203945Sweongyo
3576203945Sweongyo	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BK], 0);
3577203945Sweongyo	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BE], 1);
3578203945Sweongyo	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VI], 2);
3579203945Sweongyo	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VO], 3);
3580203945Sweongyo	bwn_pio_set_txqueue(mac, &pio->mcast, 4);
3581203945Sweongyo	bwn_pio_setupqueue_rx(mac, &pio->rx, 0);
3582203945Sweongyo}
3583203945Sweongyo
3584203945Sweongyostatic void
3585203945Sweongyobwn_pio_set_txqueue(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3586203945Sweongyo    int index)
3587203945Sweongyo{
3588203945Sweongyo	struct bwn_pio_txpkt *tp;
3589204922Sweongyo	struct bwn_softc *sc = mac->mac_sc;
3590203945Sweongyo	unsigned int i;
3591203945Sweongyo
3592203945Sweongyo	tq->tq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_TXQOFFSET(mac);
3593203945Sweongyo	tq->tq_index = index;
3594203945Sweongyo
3595203945Sweongyo	tq->tq_free = BWN_PIO_MAX_TXPACKETS;
3596204922Sweongyo	if (siba_get_revid(sc->sc_dev) >= 8)
3597203945Sweongyo		tq->tq_size = 1920;
3598203945Sweongyo	else {
3599203945Sweongyo		tq->tq_size = bwn_pio_read_2(mac, tq, BWN_PIO_TXQBUFSIZE);
3600203945Sweongyo		tq->tq_size -= 80;
3601203945Sweongyo	}
3602203945Sweongyo
3603203945Sweongyo	TAILQ_INIT(&tq->tq_pktlist);
3604203945Sweongyo	for (i = 0; i < N(tq->tq_pkts); i++) {
3605203945Sweongyo		tp = &(tq->tq_pkts[i]);
3606203945Sweongyo		tp->tp_index = i;
3607203945Sweongyo		tp->tp_queue = tq;
3608203945Sweongyo		TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
3609203945Sweongyo	}
3610203945Sweongyo}
3611203945Sweongyo
3612203945Sweongyostatic uint16_t
3613203945Sweongyobwn_pio_idx2base(struct bwn_mac *mac, int index)
3614203945Sweongyo{
3615203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
3616203945Sweongyo	static const uint16_t bases[] = {
3617203945Sweongyo		BWN_PIO_BASE0,
3618203945Sweongyo		BWN_PIO_BASE1,
3619203945Sweongyo		BWN_PIO_BASE2,
3620203945Sweongyo		BWN_PIO_BASE3,
3621203945Sweongyo		BWN_PIO_BASE4,
3622203945Sweongyo		BWN_PIO_BASE5,
3623203945Sweongyo		BWN_PIO_BASE6,
3624203945Sweongyo		BWN_PIO_BASE7,
3625203945Sweongyo	};
3626203945Sweongyo	static const uint16_t bases_rev11[] = {
3627203945Sweongyo		BWN_PIO11_BASE0,
3628203945Sweongyo		BWN_PIO11_BASE1,
3629203945Sweongyo		BWN_PIO11_BASE2,
3630203945Sweongyo		BWN_PIO11_BASE3,
3631203945Sweongyo		BWN_PIO11_BASE4,
3632203945Sweongyo		BWN_PIO11_BASE5,
3633203945Sweongyo	};
3634203945Sweongyo
3635204922Sweongyo	if (siba_get_revid(sc->sc_dev) >= 11) {
3636203945Sweongyo		if (index >= N(bases_rev11))
3637203945Sweongyo			device_printf(sc->sc_dev, "%s: warning\n", __func__);
3638203945Sweongyo		return (bases_rev11[index]);
3639203945Sweongyo	}
3640203945Sweongyo	if (index >= N(bases))
3641203945Sweongyo		device_printf(sc->sc_dev, "%s: warning\n", __func__);
3642203945Sweongyo	return (bases[index]);
3643203945Sweongyo}
3644203945Sweongyo
3645203945Sweongyostatic void
3646203945Sweongyobwn_pio_setupqueue_rx(struct bwn_mac *mac, struct bwn_pio_rxqueue *prq,
3647203945Sweongyo    int index)
3648203945Sweongyo{
3649204922Sweongyo	struct bwn_softc *sc = mac->mac_sc;
3650203945Sweongyo
3651203945Sweongyo	prq->prq_mac = mac;
3652204922Sweongyo	prq->prq_rev = siba_get_revid(sc->sc_dev);
3653203945Sweongyo	prq->prq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_RXQOFFSET(mac);
3654203945Sweongyo	bwn_dma_rxdirectfifo(mac, index, 1);
3655203945Sweongyo}
3656203945Sweongyo
3657203945Sweongyostatic void
3658203945Sweongyobwn_destroy_pioqueue_tx(struct bwn_pio_txqueue *tq)
3659203945Sweongyo{
3660203945Sweongyo	if (tq == NULL)
3661203945Sweongyo		return;
3662203945Sweongyo	bwn_pio_cancel_tx_packets(tq);
3663203945Sweongyo}
3664203945Sweongyo
3665203945Sweongyostatic void
3666203945Sweongyobwn_destroy_queue_tx(struct bwn_pio_txqueue *pio)
3667203945Sweongyo{
3668203945Sweongyo
3669203945Sweongyo	bwn_destroy_pioqueue_tx(pio);
3670203945Sweongyo}
3671203945Sweongyo
3672203945Sweongyostatic uint16_t
3673203945Sweongyobwn_pio_read_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3674203945Sweongyo    uint16_t offset)
3675203945Sweongyo{
3676203945Sweongyo
3677203945Sweongyo	return (BWN_READ_2(mac, tq->tq_base + offset));
3678203945Sweongyo}
3679203945Sweongyo
3680203945Sweongyostatic void
3681203945Sweongyobwn_dma_rxdirectfifo(struct bwn_mac *mac, int idx, uint8_t enable)
3682203945Sweongyo{
3683203945Sweongyo	uint32_t ctl;
3684203945Sweongyo	int type;
3685203945Sweongyo	uint16_t base;
3686203945Sweongyo
3687203945Sweongyo	type = bwn_dma_mask2type(bwn_dma_mask(mac));
3688203945Sweongyo	base = bwn_dma_base(type, idx);
3689203945Sweongyo	if (type == BWN_DMA_64BIT) {
3690203945Sweongyo		ctl = BWN_READ_4(mac, base + BWN_DMA64_RXCTL);
3691203945Sweongyo		ctl &= ~BWN_DMA64_RXDIRECTFIFO;
3692203945Sweongyo		if (enable)
3693203945Sweongyo			ctl |= BWN_DMA64_RXDIRECTFIFO;
3694203945Sweongyo		BWN_WRITE_4(mac, base + BWN_DMA64_RXCTL, ctl);
3695203945Sweongyo	} else {
3696203945Sweongyo		ctl = BWN_READ_4(mac, base + BWN_DMA32_RXCTL);
3697203945Sweongyo		ctl &= ~BWN_DMA32_RXDIRECTFIFO;
3698203945Sweongyo		if (enable)
3699203945Sweongyo			ctl |= BWN_DMA32_RXDIRECTFIFO;
3700203945Sweongyo		BWN_WRITE_4(mac, base + BWN_DMA32_RXCTL, ctl);
3701203945Sweongyo	}
3702203945Sweongyo}
3703203945Sweongyo
3704203945Sweongyostatic uint64_t
3705203945Sweongyobwn_dma_mask(struct bwn_mac *mac)
3706203945Sweongyo{
3707203945Sweongyo	uint32_t tmp;
3708203945Sweongyo	uint16_t base;
3709203945Sweongyo
3710203945Sweongyo	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
3711203945Sweongyo	if (tmp & SIBA_TGSHIGH_DMA64)
3712203945Sweongyo		return (BWN_DMA_BIT_MASK(64));
3713203945Sweongyo	base = bwn_dma_base(0, 0);
3714203945Sweongyo	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
3715203945Sweongyo	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
3716203945Sweongyo	if (tmp & BWN_DMA32_TXADDREXT_MASK)
3717203945Sweongyo		return (BWN_DMA_BIT_MASK(32));
3718203945Sweongyo
3719203945Sweongyo	return (BWN_DMA_BIT_MASK(30));
3720203945Sweongyo}
3721203945Sweongyo
3722203945Sweongyostatic int
3723203945Sweongyobwn_dma_mask2type(uint64_t dmamask)
3724203945Sweongyo{
3725203945Sweongyo
3726203945Sweongyo	if (dmamask == BWN_DMA_BIT_MASK(30))
3727203945Sweongyo		return (BWN_DMA_30BIT);
3728203945Sweongyo	if (dmamask == BWN_DMA_BIT_MASK(32))
3729203945Sweongyo		return (BWN_DMA_32BIT);
3730203945Sweongyo	if (dmamask == BWN_DMA_BIT_MASK(64))
3731203945Sweongyo		return (BWN_DMA_64BIT);
3732203945Sweongyo	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3733203945Sweongyo	return (BWN_DMA_30BIT);
3734203945Sweongyo}
3735203945Sweongyo
3736203945Sweongyostatic void
3737203945Sweongyobwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *tq)
3738203945Sweongyo{
3739203945Sweongyo	struct bwn_pio_txpkt *tp;
3740203945Sweongyo	unsigned int i;
3741203945Sweongyo
3742203945Sweongyo	for (i = 0; i < N(tq->tq_pkts); i++) {
3743203945Sweongyo		tp = &(tq->tq_pkts[i]);
3744203945Sweongyo		if (tp->tp_m) {
3745203945Sweongyo			m_freem(tp->tp_m);
3746203945Sweongyo			tp->tp_m = NULL;
3747203945Sweongyo		}
3748203945Sweongyo	}
3749203945Sweongyo}
3750203945Sweongyo
3751203945Sweongyostatic uint16_t
3752203945Sweongyobwn_dma_base(int type, int controller_idx)
3753203945Sweongyo{
3754203945Sweongyo	static const uint16_t map64[] = {
3755203945Sweongyo		BWN_DMA64_BASE0,
3756203945Sweongyo		BWN_DMA64_BASE1,
3757203945Sweongyo		BWN_DMA64_BASE2,
3758203945Sweongyo		BWN_DMA64_BASE3,
3759203945Sweongyo		BWN_DMA64_BASE4,
3760203945Sweongyo		BWN_DMA64_BASE5,
3761203945Sweongyo	};
3762203945Sweongyo	static const uint16_t map32[] = {
3763203945Sweongyo		BWN_DMA32_BASE0,
3764203945Sweongyo		BWN_DMA32_BASE1,
3765203945Sweongyo		BWN_DMA32_BASE2,
3766203945Sweongyo		BWN_DMA32_BASE3,
3767203945Sweongyo		BWN_DMA32_BASE4,
3768203945Sweongyo		BWN_DMA32_BASE5,
3769203945Sweongyo	};
3770203945Sweongyo
3771203945Sweongyo	if (type == BWN_DMA_64BIT) {
3772203945Sweongyo		KASSERT(controller_idx >= 0 && controller_idx < N(map64),
3773203945Sweongyo		    ("%s:%d: fail", __func__, __LINE__));
3774203945Sweongyo		return (map64[controller_idx]);
3775203945Sweongyo	}
3776203945Sweongyo	KASSERT(controller_idx >= 0 && controller_idx < N(map32),
3777203945Sweongyo	    ("%s:%d: fail", __func__, __LINE__));
3778203945Sweongyo	return (map32[controller_idx]);
3779203945Sweongyo}
3780203945Sweongyo
3781203945Sweongyostatic void
3782203945Sweongyobwn_dma_init(struct bwn_mac *mac)
3783203945Sweongyo{
3784203945Sweongyo	struct bwn_dma *dma = &mac->mac_method.dma;
3785203945Sweongyo
3786203945Sweongyo	/* setup TX DMA channels. */
3787203945Sweongyo	bwn_dma_setup(dma->wme[WME_AC_BK]);
3788203945Sweongyo	bwn_dma_setup(dma->wme[WME_AC_BE]);
3789203945Sweongyo	bwn_dma_setup(dma->wme[WME_AC_VI]);
3790203945Sweongyo	bwn_dma_setup(dma->wme[WME_AC_VO]);
3791203945Sweongyo	bwn_dma_setup(dma->mcast);
3792203945Sweongyo	/* setup RX DMA channel. */
3793203945Sweongyo	bwn_dma_setup(dma->rx);
3794203945Sweongyo}
3795203945Sweongyo
3796203945Sweongyostatic struct bwn_dma_ring *
3797203945Sweongyobwn_dma_ringsetup(struct bwn_mac *mac, int controller_index,
3798203945Sweongyo    int for_tx, int type)
3799203945Sweongyo{
3800203945Sweongyo	struct bwn_dma *dma = &mac->mac_method.dma;
3801203945Sweongyo	struct bwn_dma_ring *dr;
3802203945Sweongyo	struct bwn_dmadesc_generic *desc;
3803203945Sweongyo	struct bwn_dmadesc_meta *mt;
3804203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
3805203945Sweongyo	int error, i;
3806203945Sweongyo
3807203945Sweongyo	dr = malloc(sizeof(*dr), M_DEVBUF, M_NOWAIT | M_ZERO);
3808203945Sweongyo	if (dr == NULL)
3809203945Sweongyo		goto out;
3810203945Sweongyo	dr->dr_numslots = BWN_RXRING_SLOTS;
3811203945Sweongyo	if (for_tx)
3812203945Sweongyo		dr->dr_numslots = BWN_TXRING_SLOTS;
3813203945Sweongyo
3814203945Sweongyo	dr->dr_meta = malloc(dr->dr_numslots * sizeof(struct bwn_dmadesc_meta),
3815203945Sweongyo	    M_DEVBUF, M_NOWAIT | M_ZERO);
3816203945Sweongyo	if (dr->dr_meta == NULL)
3817203945Sweongyo		goto fail0;
3818203945Sweongyo
3819203945Sweongyo	dr->dr_type = type;
3820203945Sweongyo	dr->dr_mac = mac;
3821203945Sweongyo	dr->dr_base = bwn_dma_base(type, controller_index);
3822203945Sweongyo	dr->dr_index = controller_index;
3823203945Sweongyo	if (type == BWN_DMA_64BIT) {
3824203945Sweongyo		dr->getdesc = bwn_dma_64_getdesc;
3825203945Sweongyo		dr->setdesc = bwn_dma_64_setdesc;
3826203945Sweongyo		dr->start_transfer = bwn_dma_64_start_transfer;
3827203945Sweongyo		dr->suspend = bwn_dma_64_suspend;
3828203945Sweongyo		dr->resume = bwn_dma_64_resume;
3829203945Sweongyo		dr->get_curslot = bwn_dma_64_get_curslot;
3830203945Sweongyo		dr->set_curslot = bwn_dma_64_set_curslot;
3831203945Sweongyo	} else {
3832203945Sweongyo		dr->getdesc = bwn_dma_32_getdesc;
3833203945Sweongyo		dr->setdesc = bwn_dma_32_setdesc;
3834203945Sweongyo		dr->start_transfer = bwn_dma_32_start_transfer;
3835203945Sweongyo		dr->suspend = bwn_dma_32_suspend;
3836203945Sweongyo		dr->resume = bwn_dma_32_resume;
3837203945Sweongyo		dr->get_curslot = bwn_dma_32_get_curslot;
3838203945Sweongyo		dr->set_curslot = bwn_dma_32_set_curslot;
3839203945Sweongyo	}
3840203945Sweongyo	if (for_tx) {
3841203945Sweongyo		dr->dr_tx = 1;
3842203945Sweongyo		dr->dr_curslot = -1;
3843203945Sweongyo	} else {
3844203945Sweongyo		if (dr->dr_index == 0) {
3845203945Sweongyo			dr->dr_rx_bufsize = BWN_DMA0_RX_BUFFERSIZE;
3846203945Sweongyo			dr->dr_frameoffset = BWN_DMA0_RX_FRAMEOFFSET;
3847203945Sweongyo		} else
3848203945Sweongyo			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3849203945Sweongyo	}
3850203945Sweongyo
3851203945Sweongyo	error = bwn_dma_allocringmemory(dr);
3852203945Sweongyo	if (error)
3853203945Sweongyo		goto fail2;
3854203945Sweongyo
3855203945Sweongyo	if (for_tx) {
3856203945Sweongyo		/*
3857203945Sweongyo		 * Assumption: BWN_TXRING_SLOTS can be divided by
3858203945Sweongyo		 * BWN_TX_SLOTS_PER_FRAME
3859203945Sweongyo		 */
3860203945Sweongyo		KASSERT(BWN_TXRING_SLOTS % BWN_TX_SLOTS_PER_FRAME == 0,
3861203945Sweongyo		    ("%s:%d: fail", __func__, __LINE__));
3862203945Sweongyo
3863203945Sweongyo		dr->dr_txhdr_cache =
3864203945Sweongyo		    malloc((dr->dr_numslots / BWN_TX_SLOTS_PER_FRAME) *
3865203945Sweongyo			BWN_HDRSIZE(mac), M_DEVBUF, M_NOWAIT | M_ZERO);
3866203945Sweongyo		KASSERT(dr->dr_txhdr_cache != NULL,
3867203945Sweongyo		    ("%s:%d: fail", __func__, __LINE__));
3868203945Sweongyo
3869203945Sweongyo		/*
3870203945Sweongyo		 * Create TX ring DMA stuffs
3871203945Sweongyo		 */
3872203945Sweongyo		error = bus_dma_tag_create(dma->parent_dtag,
3873203945Sweongyo				    BWN_ALIGN, 0,
3874203945Sweongyo				    BUS_SPACE_MAXADDR,
3875203945Sweongyo				    BUS_SPACE_MAXADDR,
3876203945Sweongyo				    NULL, NULL,
3877203945Sweongyo				    BWN_HDRSIZE(mac),
3878203945Sweongyo				    1,
3879203945Sweongyo				    BUS_SPACE_MAXSIZE_32BIT,
3880203945Sweongyo				    0,
3881203945Sweongyo				    NULL, NULL,
3882203945Sweongyo				    &dr->dr_txring_dtag);
3883203945Sweongyo		if (error) {
3884203945Sweongyo			device_printf(sc->sc_dev,
3885203945Sweongyo			    "can't create TX ring DMA tag: TODO frees\n");
3886203945Sweongyo			goto fail1;
3887203945Sweongyo		}
3888203945Sweongyo
3889203945Sweongyo		for (i = 0; i < dr->dr_numslots; i += 2) {
3890203945Sweongyo			dr->getdesc(dr, i, &desc, &mt);
3891203945Sweongyo
3892203945Sweongyo			mt->mt_txtype = BWN_DMADESC_METATYPE_HEADER;
3893203945Sweongyo			mt->mt_m = NULL;
3894203945Sweongyo			mt->mt_ni = NULL;
3895203945Sweongyo			mt->mt_islast = 0;
3896203945Sweongyo			error = bus_dmamap_create(dr->dr_txring_dtag, 0,
3897203945Sweongyo			    &mt->mt_dmap);
3898203945Sweongyo			if (error) {
3899203945Sweongyo				device_printf(sc->sc_dev,
3900203945Sweongyo				     "can't create RX buf DMA map\n");
3901203945Sweongyo				goto fail1;
3902203945Sweongyo			}
3903203945Sweongyo
3904203945Sweongyo			dr->getdesc(dr, i + 1, &desc, &mt);
3905203945Sweongyo
3906203945Sweongyo			mt->mt_txtype = BWN_DMADESC_METATYPE_BODY;
3907203945Sweongyo			mt->mt_m = NULL;
3908203945Sweongyo			mt->mt_ni = NULL;
3909203945Sweongyo			mt->mt_islast = 1;
3910203945Sweongyo			error = bus_dmamap_create(dma->txbuf_dtag, 0,
3911203945Sweongyo			    &mt->mt_dmap);
3912203945Sweongyo			if (error) {
3913203945Sweongyo				device_printf(sc->sc_dev,
3914203945Sweongyo				     "can't create RX buf DMA map\n");
3915203945Sweongyo				goto fail1;
3916203945Sweongyo			}
3917203945Sweongyo		}
3918203945Sweongyo	} else {
3919203945Sweongyo		error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3920203945Sweongyo		    &dr->dr_spare_dmap);
3921203945Sweongyo		if (error) {
3922203945Sweongyo			device_printf(sc->sc_dev,
3923203945Sweongyo			    "can't create RX buf DMA map\n");
3924203945Sweongyo			goto out;		/* XXX wrong! */
3925203945Sweongyo		}
3926203945Sweongyo
3927203945Sweongyo		for (i = 0; i < dr->dr_numslots; i++) {
3928203945Sweongyo			dr->getdesc(dr, i, &desc, &mt);
3929203945Sweongyo
3930203945Sweongyo			error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3931203945Sweongyo			    &mt->mt_dmap);
3932203945Sweongyo			if (error) {
3933203945Sweongyo				device_printf(sc->sc_dev,
3934203945Sweongyo				    "can't create RX buf DMA map\n");
3935203945Sweongyo				goto out;	/* XXX wrong! */
3936203945Sweongyo			}
3937203945Sweongyo			error = bwn_dma_newbuf(dr, desc, mt, 1);
3938203945Sweongyo			if (error) {
3939203945Sweongyo				device_printf(sc->sc_dev,
3940203945Sweongyo				    "failed to allocate RX buf\n");
3941203945Sweongyo				goto out;	/* XXX wrong! */
3942203945Sweongyo			}
3943203945Sweongyo		}
3944203945Sweongyo
3945203945Sweongyo		bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
3946203945Sweongyo		    BUS_DMASYNC_PREWRITE);
3947203945Sweongyo
3948203945Sweongyo		dr->dr_usedslot = dr->dr_numslots;
3949203945Sweongyo	}
3950203945Sweongyo
3951203945Sweongyo      out:
3952203945Sweongyo	return (dr);
3953203945Sweongyo
3954203945Sweongyofail2:
3955203945Sweongyo	free(dr->dr_txhdr_cache, M_DEVBUF);
3956203945Sweongyofail1:
3957203945Sweongyo	free(dr->dr_meta, M_DEVBUF);
3958203945Sweongyofail0:
3959203945Sweongyo	free(dr, M_DEVBUF);
3960203945Sweongyo	return (NULL);
3961203945Sweongyo}
3962203945Sweongyo
3963203945Sweongyostatic void
3964203945Sweongyobwn_dma_ringfree(struct bwn_dma_ring **dr)
3965203945Sweongyo{
3966203945Sweongyo
3967203945Sweongyo	if (dr == NULL)
3968203945Sweongyo		return;
3969203945Sweongyo
3970203945Sweongyo	bwn_dma_free_descbufs(*dr);
3971203945Sweongyo	bwn_dma_free_ringmemory(*dr);
3972203945Sweongyo
3973203945Sweongyo	free((*dr)->dr_txhdr_cache, M_DEVBUF);
3974203945Sweongyo	free((*dr)->dr_meta, M_DEVBUF);
3975203945Sweongyo	free(*dr, M_DEVBUF);
3976203945Sweongyo
3977203945Sweongyo	*dr = NULL;
3978203945Sweongyo}
3979203945Sweongyo
3980203945Sweongyostatic void
3981203945Sweongyobwn_dma_32_getdesc(struct bwn_dma_ring *dr, int slot,
3982203945Sweongyo    struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
3983203945Sweongyo{
3984203945Sweongyo	struct bwn_dmadesc32 *desc;
3985203945Sweongyo
3986203945Sweongyo	*meta = &(dr->dr_meta[slot]);
3987203945Sweongyo	desc = dr->dr_ring_descbase;
3988203945Sweongyo	desc = &(desc[slot]);
3989203945Sweongyo
3990203945Sweongyo	*gdesc = (struct bwn_dmadesc_generic *)desc;
3991203945Sweongyo}
3992203945Sweongyo
3993203945Sweongyostatic void
3994203945Sweongyobwn_dma_32_setdesc(struct bwn_dma_ring *dr,
3995203945Sweongyo    struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
3996203945Sweongyo    int start, int end, int irq)
3997203945Sweongyo{
3998203945Sweongyo	struct bwn_dmadesc32 *descbase = dr->dr_ring_descbase;
3999204922Sweongyo	struct bwn_softc *sc = dr->dr_mac->mac_sc;
4000203945Sweongyo	uint32_t addr, addrext, ctl;
4001203945Sweongyo	int slot;
4002203945Sweongyo
4003203945Sweongyo	slot = (int)(&(desc->dma.dma32) - descbase);
4004203945Sweongyo	KASSERT(slot >= 0 && slot < dr->dr_numslots,
4005203945Sweongyo	    ("%s:%d: fail", __func__, __LINE__));
4006203945Sweongyo
4007203945Sweongyo	addr = (uint32_t) (dmaaddr & ~SIBA_DMA_TRANSLATION_MASK);
4008203945Sweongyo	addrext = (uint32_t) (dmaaddr & SIBA_DMA_TRANSLATION_MASK) >> 30;
4009204922Sweongyo	addr |= siba_dma_translation(sc->sc_dev);
4010203945Sweongyo	ctl = bufsize & BWN_DMA32_DCTL_BYTECNT;
4011203945Sweongyo	if (slot == dr->dr_numslots - 1)
4012203945Sweongyo		ctl |= BWN_DMA32_DCTL_DTABLEEND;
4013203945Sweongyo	if (start)
4014203945Sweongyo		ctl |= BWN_DMA32_DCTL_FRAMESTART;
4015203945Sweongyo	if (end)
4016203945Sweongyo		ctl |= BWN_DMA32_DCTL_FRAMEEND;
4017203945Sweongyo	if (irq)
4018203945Sweongyo		ctl |= BWN_DMA32_DCTL_IRQ;
4019203945Sweongyo	ctl |= (addrext << BWN_DMA32_DCTL_ADDREXT_SHIFT)
4020203945Sweongyo	    & BWN_DMA32_DCTL_ADDREXT_MASK;
4021203945Sweongyo
4022203945Sweongyo	desc->dma.dma32.control = htole32(ctl);
4023203945Sweongyo	desc->dma.dma32.address = htole32(addr);
4024203945Sweongyo}
4025203945Sweongyo
4026203945Sweongyostatic void
4027203945Sweongyobwn_dma_32_start_transfer(struct bwn_dma_ring *dr, int slot)
4028203945Sweongyo{
4029203945Sweongyo
4030203945Sweongyo	BWN_DMA_WRITE(dr, BWN_DMA32_TXINDEX,
4031203945Sweongyo	    (uint32_t)(slot * sizeof(struct bwn_dmadesc32)));
4032203945Sweongyo}
4033203945Sweongyo
4034203945Sweongyostatic void
4035203945Sweongyobwn_dma_32_suspend(struct bwn_dma_ring *dr)
4036203945Sweongyo{
4037203945Sweongyo
4038203945Sweongyo	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
4039203945Sweongyo	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) | BWN_DMA32_TXSUSPEND);
4040203945Sweongyo}
4041203945Sweongyo
4042203945Sweongyostatic void
4043203945Sweongyobwn_dma_32_resume(struct bwn_dma_ring *dr)
4044203945Sweongyo{
4045203945Sweongyo
4046203945Sweongyo	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
4047203945Sweongyo	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) & ~BWN_DMA32_TXSUSPEND);
4048203945Sweongyo}
4049203945Sweongyo
4050203945Sweongyostatic int
4051203945Sweongyobwn_dma_32_get_curslot(struct bwn_dma_ring *dr)
4052203945Sweongyo{
4053203945Sweongyo	uint32_t val;
4054203945Sweongyo
4055203945Sweongyo	val = BWN_DMA_READ(dr, BWN_DMA32_RXSTATUS);
4056203945Sweongyo	val &= BWN_DMA32_RXDPTR;
4057203945Sweongyo
4058203945Sweongyo	return (val / sizeof(struct bwn_dmadesc32));
4059203945Sweongyo}
4060203945Sweongyo
4061203945Sweongyostatic void
4062203945Sweongyobwn_dma_32_set_curslot(struct bwn_dma_ring *dr, int slot)
4063203945Sweongyo{
4064203945Sweongyo
4065203945Sweongyo	BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX,
4066203945Sweongyo	    (uint32_t) (slot * sizeof(struct bwn_dmadesc32)));
4067203945Sweongyo}
4068203945Sweongyo
4069203945Sweongyostatic void
4070203945Sweongyobwn_dma_64_getdesc(struct bwn_dma_ring *dr, int slot,
4071203945Sweongyo    struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
4072203945Sweongyo{
4073203945Sweongyo	struct bwn_dmadesc64 *desc;
4074203945Sweongyo
4075203945Sweongyo	*meta = &(dr->dr_meta[slot]);
4076203945Sweongyo	desc = dr->dr_ring_descbase;
4077203945Sweongyo	desc = &(desc[slot]);
4078203945Sweongyo
4079203945Sweongyo	*gdesc = (struct bwn_dmadesc_generic *)desc;
4080203945Sweongyo}
4081203945Sweongyo
4082203945Sweongyostatic void
4083203945Sweongyobwn_dma_64_setdesc(struct bwn_dma_ring *dr,
4084203945Sweongyo    struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
4085203945Sweongyo    int start, int end, int irq)
4086203945Sweongyo{
4087203945Sweongyo	struct bwn_dmadesc64 *descbase = dr->dr_ring_descbase;
4088204922Sweongyo	struct bwn_softc *sc = dr->dr_mac->mac_sc;
4089203945Sweongyo	int slot;
4090203945Sweongyo	uint32_t ctl0 = 0, ctl1 = 0;
4091203945Sweongyo	uint32_t addrlo, addrhi;
4092203945Sweongyo	uint32_t addrext;
4093203945Sweongyo
4094203945Sweongyo	slot = (int)(&(desc->dma.dma64) - descbase);
4095203945Sweongyo	KASSERT(slot >= 0 && slot < dr->dr_numslots,
4096203945Sweongyo	    ("%s:%d: fail", __func__, __LINE__));
4097203945Sweongyo
4098203945Sweongyo	addrlo = (uint32_t) (dmaaddr & 0xffffffff);
4099203945Sweongyo	addrhi = (((uint64_t) dmaaddr >> 32) & ~SIBA_DMA_TRANSLATION_MASK);
4100203945Sweongyo	addrext = (((uint64_t) dmaaddr >> 32) & SIBA_DMA_TRANSLATION_MASK) >>
4101203945Sweongyo	    30;
4102204922Sweongyo	addrhi |= (siba_dma_translation(sc->sc_dev) << 1);
4103203945Sweongyo	if (slot == dr->dr_numslots - 1)
4104203945Sweongyo		ctl0 |= BWN_DMA64_DCTL0_DTABLEEND;
4105203945Sweongyo	if (start)
4106203945Sweongyo		ctl0 |= BWN_DMA64_DCTL0_FRAMESTART;
4107203945Sweongyo	if (end)
4108203945Sweongyo		ctl0 |= BWN_DMA64_DCTL0_FRAMEEND;
4109203945Sweongyo	if (irq)
4110203945Sweongyo		ctl0 |= BWN_DMA64_DCTL0_IRQ;
4111203945Sweongyo	ctl1 |= bufsize & BWN_DMA64_DCTL1_BYTECNT;
4112203945Sweongyo	ctl1 |= (addrext << BWN_DMA64_DCTL1_ADDREXT_SHIFT)
4113203945Sweongyo	    & BWN_DMA64_DCTL1_ADDREXT_MASK;
4114203945Sweongyo
4115203945Sweongyo	desc->dma.dma64.control0 = htole32(ctl0);
4116203945Sweongyo	desc->dma.dma64.control1 = htole32(ctl1);
4117203945Sweongyo	desc->dma.dma64.address_low = htole32(addrlo);
4118203945Sweongyo	desc->dma.dma64.address_high = htole32(addrhi);
4119203945Sweongyo}
4120203945Sweongyo
4121203945Sweongyostatic void
4122203945Sweongyobwn_dma_64_start_transfer(struct bwn_dma_ring *dr, int slot)
4123203945Sweongyo{
4124203945Sweongyo
4125203945Sweongyo	BWN_DMA_WRITE(dr, BWN_DMA64_TXINDEX,
4126203945Sweongyo	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4127203945Sweongyo}
4128203945Sweongyo
4129203945Sweongyostatic void
4130203945Sweongyobwn_dma_64_suspend(struct bwn_dma_ring *dr)
4131203945Sweongyo{
4132203945Sweongyo
4133203945Sweongyo	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
4134203945Sweongyo	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) | BWN_DMA64_TXSUSPEND);
4135203945Sweongyo}
4136203945Sweongyo
4137203945Sweongyostatic void
4138203945Sweongyobwn_dma_64_resume(struct bwn_dma_ring *dr)
4139203945Sweongyo{
4140203945Sweongyo
4141203945Sweongyo	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
4142203945Sweongyo	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) & ~BWN_DMA64_TXSUSPEND);
4143203945Sweongyo}
4144203945Sweongyo
4145203945Sweongyostatic int
4146203945Sweongyobwn_dma_64_get_curslot(struct bwn_dma_ring *dr)
4147203945Sweongyo{
4148203945Sweongyo	uint32_t val;
4149203945Sweongyo
4150203945Sweongyo	val = BWN_DMA_READ(dr, BWN_DMA64_RXSTATUS);
4151203945Sweongyo	val &= BWN_DMA64_RXSTATDPTR;
4152203945Sweongyo
4153203945Sweongyo	return (val / sizeof(struct bwn_dmadesc64));
4154203945Sweongyo}
4155203945Sweongyo
4156203945Sweongyostatic void
4157203945Sweongyobwn_dma_64_set_curslot(struct bwn_dma_ring *dr, int slot)
4158203945Sweongyo{
4159203945Sweongyo
4160203945Sweongyo	BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX,
4161203945Sweongyo	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4162203945Sweongyo}
4163203945Sweongyo
4164203945Sweongyostatic int
4165203945Sweongyobwn_dma_allocringmemory(struct bwn_dma_ring *dr)
4166203945Sweongyo{
4167203945Sweongyo	struct bwn_mac *mac = dr->dr_mac;
4168203945Sweongyo	struct bwn_dma *dma = &mac->mac_method.dma;
4169203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
4170203945Sweongyo	int error;
4171203945Sweongyo
4172203945Sweongyo	error = bus_dma_tag_create(dma->parent_dtag,
4173203945Sweongyo			    BWN_ALIGN, 0,
4174203945Sweongyo			    BUS_SPACE_MAXADDR,
4175203945Sweongyo			    BUS_SPACE_MAXADDR,
4176203945Sweongyo			    NULL, NULL,
4177203945Sweongyo			    BWN_DMA_RINGMEMSIZE,
4178203945Sweongyo			    1,
4179203945Sweongyo			    BUS_SPACE_MAXSIZE_32BIT,
4180203945Sweongyo			    0,
4181203945Sweongyo			    NULL, NULL,
4182203945Sweongyo			    &dr->dr_ring_dtag);
4183203945Sweongyo	if (error) {
4184203945Sweongyo		device_printf(sc->sc_dev,
4185203945Sweongyo		    "can't create TX ring DMA tag: TODO frees\n");
4186203945Sweongyo		return (-1);
4187203945Sweongyo	}
4188203945Sweongyo
4189203945Sweongyo	error = bus_dmamem_alloc(dr->dr_ring_dtag,
4190203945Sweongyo	    &dr->dr_ring_descbase, BUS_DMA_WAITOK | BUS_DMA_ZERO,
4191203945Sweongyo	    &dr->dr_ring_dmap);
4192203945Sweongyo	if (error) {
4193203945Sweongyo		device_printf(sc->sc_dev,
4194203945Sweongyo		    "can't allocate DMA mem: TODO frees\n");
4195203945Sweongyo		return (-1);
4196203945Sweongyo	}
4197203945Sweongyo	error = bus_dmamap_load(dr->dr_ring_dtag, dr->dr_ring_dmap,
4198203945Sweongyo	    dr->dr_ring_descbase, BWN_DMA_RINGMEMSIZE,
4199203945Sweongyo	    bwn_dma_ring_addr, &dr->dr_ring_dmabase, BUS_DMA_NOWAIT);
4200203945Sweongyo	if (error) {
4201203945Sweongyo		device_printf(sc->sc_dev,
4202203945Sweongyo		    "can't load DMA mem: TODO free\n");
4203203945Sweongyo		return (-1);
4204203945Sweongyo	}
4205203945Sweongyo
4206203945Sweongyo	return (0);
4207203945Sweongyo}
4208203945Sweongyo
4209203945Sweongyostatic void
4210203945Sweongyobwn_dma_setup(struct bwn_dma_ring *dr)
4211203945Sweongyo{
4212204922Sweongyo	struct bwn_softc *sc = dr->dr_mac->mac_sc;
4213203945Sweongyo	uint64_t ring64;
4214203945Sweongyo	uint32_t addrext, ring32, value;
4215204922Sweongyo	uint32_t trans = siba_dma_translation(sc->sc_dev);
4216203945Sweongyo
4217203945Sweongyo	if (dr->dr_tx) {
4218203945Sweongyo		dr->dr_curslot = -1;
4219203945Sweongyo
4220203945Sweongyo		if (dr->dr_type == BWN_DMA_64BIT) {
4221203945Sweongyo			ring64 = (uint64_t)(dr->dr_ring_dmabase);
4222203945Sweongyo			addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK)
4223203945Sweongyo			    >> 30;
4224203945Sweongyo			value = BWN_DMA64_TXENABLE;
4225203945Sweongyo			value |= (addrext << BWN_DMA64_TXADDREXT_SHIFT)
4226203945Sweongyo			    & BWN_DMA64_TXADDREXT_MASK;
4227203945Sweongyo			BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL, value);
4228203945Sweongyo			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO,
4229203945Sweongyo			    (ring64 & 0xffffffff));
4230203945Sweongyo			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI,
4231203945Sweongyo			    ((ring64 >> 32) &
4232203945Sweongyo			    ~SIBA_DMA_TRANSLATION_MASK) | (trans << 1));
4233203945Sweongyo		} else {
4234203945Sweongyo			ring32 = (uint32_t)(dr->dr_ring_dmabase);
4235203945Sweongyo			addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4236203945Sweongyo			value = BWN_DMA32_TXENABLE;
4237203945Sweongyo			value |= (addrext << BWN_DMA32_TXADDREXT_SHIFT)
4238203945Sweongyo			    & BWN_DMA32_TXADDREXT_MASK;
4239203945Sweongyo			BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL, value);
4240203945Sweongyo			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING,
4241203945Sweongyo			    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4242203945Sweongyo		}
4243203945Sweongyo		return;
4244203945Sweongyo	}
4245203945Sweongyo
4246203945Sweongyo	/*
4247203945Sweongyo	 * set for RX
4248203945Sweongyo	 */
4249203945Sweongyo	dr->dr_usedslot = dr->dr_numslots;
4250203945Sweongyo
4251203945Sweongyo	if (dr->dr_type == BWN_DMA_64BIT) {
4252203945Sweongyo		ring64 = (uint64_t)(dr->dr_ring_dmabase);
4253203945Sweongyo		addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK) >> 30;
4254203945Sweongyo		value = (dr->dr_frameoffset << BWN_DMA64_RXFROFF_SHIFT);
4255203945Sweongyo		value |= BWN_DMA64_RXENABLE;
4256203945Sweongyo		value |= (addrext << BWN_DMA64_RXADDREXT_SHIFT)
4257203945Sweongyo		    & BWN_DMA64_RXADDREXT_MASK;
4258203945Sweongyo		BWN_DMA_WRITE(dr, BWN_DMA64_RXCTL, value);
4259203945Sweongyo		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, (ring64 & 0xffffffff));
4260203945Sweongyo		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI,
4261203945Sweongyo		    ((ring64 >> 32) & ~SIBA_DMA_TRANSLATION_MASK)
4262203945Sweongyo		    | (trans << 1));
4263203945Sweongyo		BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX, dr->dr_numslots *
4264203945Sweongyo		    sizeof(struct bwn_dmadesc64));
4265203945Sweongyo	} else {
4266203945Sweongyo		ring32 = (uint32_t)(dr->dr_ring_dmabase);
4267203945Sweongyo		addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4268203945Sweongyo		value = (dr->dr_frameoffset << BWN_DMA32_RXFROFF_SHIFT);
4269203945Sweongyo		value |= BWN_DMA32_RXENABLE;
4270203945Sweongyo		value |= (addrext << BWN_DMA32_RXADDREXT_SHIFT)
4271203945Sweongyo		    & BWN_DMA32_RXADDREXT_MASK;
4272203945Sweongyo		BWN_DMA_WRITE(dr, BWN_DMA32_RXCTL, value);
4273203945Sweongyo		BWN_DMA_WRITE(dr, BWN_DMA32_RXRING,
4274203945Sweongyo		    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4275203945Sweongyo		BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX, dr->dr_numslots *
4276203945Sweongyo		    sizeof(struct bwn_dmadesc32));
4277203945Sweongyo	}
4278203945Sweongyo}
4279203945Sweongyo
4280203945Sweongyostatic void
4281203945Sweongyobwn_dma_free_ringmemory(struct bwn_dma_ring *dr)
4282203945Sweongyo{
4283203945Sweongyo
4284203945Sweongyo	bus_dmamap_unload(dr->dr_ring_dtag, dr->dr_ring_dmap);
4285203945Sweongyo	bus_dmamem_free(dr->dr_ring_dtag, dr->dr_ring_descbase,
4286203945Sweongyo	    dr->dr_ring_dmap);
4287203945Sweongyo}
4288203945Sweongyo
4289203945Sweongyostatic void
4290203945Sweongyobwn_dma_cleanup(struct bwn_dma_ring *dr)
4291203945Sweongyo{
4292203945Sweongyo
4293203945Sweongyo	if (dr->dr_tx) {
4294203945Sweongyo		bwn_dma_tx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4295203945Sweongyo		if (dr->dr_type == BWN_DMA_64BIT) {
4296203945Sweongyo			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO, 0);
4297203945Sweongyo			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI, 0);
4298203945Sweongyo		} else
4299203945Sweongyo			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING, 0);
4300203945Sweongyo	} else {
4301203945Sweongyo		bwn_dma_rx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4302203945Sweongyo		if (dr->dr_type == BWN_DMA_64BIT) {
4303203945Sweongyo			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, 0);
4304203945Sweongyo			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI, 0);
4305203945Sweongyo		} else
4306203945Sweongyo			BWN_DMA_WRITE(dr, BWN_DMA32_RXRING, 0);
4307203945Sweongyo	}
4308203945Sweongyo}
4309203945Sweongyo
4310203945Sweongyostatic void
4311203945Sweongyobwn_dma_free_descbufs(struct bwn_dma_ring *dr)
4312203945Sweongyo{
4313203945Sweongyo	struct bwn_dmadesc_generic *desc;
4314203945Sweongyo	struct bwn_dmadesc_meta *meta;
4315203945Sweongyo	struct bwn_mac *mac = dr->dr_mac;
4316203945Sweongyo	struct bwn_dma *dma = &mac->mac_method.dma;
4317203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
4318203945Sweongyo	int i;
4319203945Sweongyo
4320203945Sweongyo	if (!dr->dr_usedslot)
4321203945Sweongyo		return;
4322203945Sweongyo	for (i = 0; i < dr->dr_numslots; i++) {
4323203945Sweongyo		dr->getdesc(dr, i, &desc, &meta);
4324203945Sweongyo
4325203945Sweongyo		if (meta->mt_m == NULL) {
4326203945Sweongyo			if (!dr->dr_tx)
4327203945Sweongyo				device_printf(sc->sc_dev, "%s: not TX?\n",
4328203945Sweongyo				    __func__);
4329203945Sweongyo			continue;
4330203945Sweongyo		}
4331203945Sweongyo		if (dr->dr_tx) {
4332203945Sweongyo			if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
4333203945Sweongyo				bus_dmamap_unload(dr->dr_txring_dtag,
4334203945Sweongyo				    meta->mt_dmap);
4335203945Sweongyo			else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
4336203945Sweongyo				bus_dmamap_unload(dma->txbuf_dtag,
4337203945Sweongyo				    meta->mt_dmap);
4338203945Sweongyo		} else
4339203945Sweongyo			bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
4340203945Sweongyo		bwn_dma_free_descbuf(dr, meta);
4341203945Sweongyo	}
4342203945Sweongyo}
4343203945Sweongyo
4344203945Sweongyostatic int
4345203945Sweongyobwn_dma_tx_reset(struct bwn_mac *mac, uint16_t base,
4346203945Sweongyo    int type)
4347203945Sweongyo{
4348203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
4349203945Sweongyo	uint32_t value;
4350203945Sweongyo	int i;
4351203945Sweongyo	uint16_t offset;
4352203945Sweongyo
4353203945Sweongyo	for (i = 0; i < 10; i++) {
4354203945Sweongyo		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4355203945Sweongyo		    BWN_DMA32_TXSTATUS;
4356203945Sweongyo		value = BWN_READ_4(mac, base + offset);
4357203945Sweongyo		if (type == BWN_DMA_64BIT) {
4358203945Sweongyo			value &= BWN_DMA64_TXSTAT;
4359203945Sweongyo			if (value == BWN_DMA64_TXSTAT_DISABLED ||
4360203945Sweongyo			    value == BWN_DMA64_TXSTAT_IDLEWAIT ||
4361203945Sweongyo			    value == BWN_DMA64_TXSTAT_STOPPED)
4362203945Sweongyo				break;
4363203945Sweongyo		} else {
4364203945Sweongyo			value &= BWN_DMA32_TXSTATE;
4365203945Sweongyo			if (value == BWN_DMA32_TXSTAT_DISABLED ||
4366203945Sweongyo			    value == BWN_DMA32_TXSTAT_IDLEWAIT ||
4367203945Sweongyo			    value == BWN_DMA32_TXSTAT_STOPPED)
4368203945Sweongyo				break;
4369203945Sweongyo		}
4370203945Sweongyo		DELAY(1000);
4371203945Sweongyo	}
4372203945Sweongyo	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXCTL : BWN_DMA32_TXCTL;
4373203945Sweongyo	BWN_WRITE_4(mac, base + offset, 0);
4374203945Sweongyo	for (i = 0; i < 10; i++) {
4375203945Sweongyo		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4376203945Sweongyo						   BWN_DMA32_TXSTATUS;
4377203945Sweongyo		value = BWN_READ_4(mac, base + offset);
4378203945Sweongyo		if (type == BWN_DMA_64BIT) {
4379203945Sweongyo			value &= BWN_DMA64_TXSTAT;
4380203945Sweongyo			if (value == BWN_DMA64_TXSTAT_DISABLED) {
4381203945Sweongyo				i = -1;
4382203945Sweongyo				break;
4383203945Sweongyo			}
4384203945Sweongyo		} else {
4385203945Sweongyo			value &= BWN_DMA32_TXSTATE;
4386203945Sweongyo			if (value == BWN_DMA32_TXSTAT_DISABLED) {
4387203945Sweongyo				i = -1;
4388203945Sweongyo				break;
4389203945Sweongyo			}
4390203945Sweongyo		}
4391203945Sweongyo		DELAY(1000);
4392203945Sweongyo	}
4393203945Sweongyo	if (i != -1) {
4394203945Sweongyo		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4395203945Sweongyo		return (ENODEV);
4396203945Sweongyo	}
4397203945Sweongyo	DELAY(1000);
4398203945Sweongyo
4399203945Sweongyo	return (0);
4400203945Sweongyo}
4401203945Sweongyo
4402203945Sweongyostatic int
4403203945Sweongyobwn_dma_rx_reset(struct bwn_mac *mac, uint16_t base,
4404203945Sweongyo    int type)
4405203945Sweongyo{
4406203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
4407203945Sweongyo	uint32_t value;
4408203945Sweongyo	int i;
4409203945Sweongyo	uint16_t offset;
4410203945Sweongyo
4411203945Sweongyo	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXCTL : BWN_DMA32_RXCTL;
4412203945Sweongyo	BWN_WRITE_4(mac, base + offset, 0);
4413203945Sweongyo	for (i = 0; i < 10; i++) {
4414203945Sweongyo		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXSTATUS :
4415203945Sweongyo		    BWN_DMA32_RXSTATUS;
4416203945Sweongyo		value = BWN_READ_4(mac, base + offset);
4417203945Sweongyo		if (type == BWN_DMA_64BIT) {
4418203945Sweongyo			value &= BWN_DMA64_RXSTAT;
4419203945Sweongyo			if (value == BWN_DMA64_RXSTAT_DISABLED) {
4420203945Sweongyo				i = -1;
4421203945Sweongyo				break;
4422203945Sweongyo			}
4423203945Sweongyo		} else {
4424203945Sweongyo			value &= BWN_DMA32_RXSTATE;
4425203945Sweongyo			if (value == BWN_DMA32_RXSTAT_DISABLED) {
4426203945Sweongyo				i = -1;
4427203945Sweongyo				break;
4428203945Sweongyo			}
4429203945Sweongyo		}
4430203945Sweongyo		DELAY(1000);
4431203945Sweongyo	}
4432203945Sweongyo	if (i != -1) {
4433203945Sweongyo		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4434203945Sweongyo		return (ENODEV);
4435203945Sweongyo	}
4436203945Sweongyo
4437203945Sweongyo	return (0);
4438203945Sweongyo}
4439203945Sweongyo
4440203945Sweongyostatic void
4441203945Sweongyobwn_dma_free_descbuf(struct bwn_dma_ring *dr,
4442203945Sweongyo    struct bwn_dmadesc_meta *meta)
4443203945Sweongyo{
4444203945Sweongyo
4445203945Sweongyo	if (meta->mt_m != NULL) {
4446203945Sweongyo		m_freem(meta->mt_m);
4447203945Sweongyo		meta->mt_m = NULL;
4448203945Sweongyo	}
4449203945Sweongyo	if (meta->mt_ni != NULL) {
4450203945Sweongyo		ieee80211_free_node(meta->mt_ni);
4451203945Sweongyo		meta->mt_ni = NULL;
4452203945Sweongyo	}
4453203945Sweongyo}
4454203945Sweongyo
4455203945Sweongyostatic void
4456203945Sweongyobwn_dma_set_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4457203945Sweongyo{
4458203945Sweongyo	struct bwn_rxhdr4 *rxhdr;
4459203945Sweongyo	unsigned char *frame;
4460203945Sweongyo
4461203945Sweongyo	rxhdr = mtod(m, struct bwn_rxhdr4 *);
4462203945Sweongyo	rxhdr->frame_len = 0;
4463203945Sweongyo
4464203945Sweongyo	KASSERT(dr->dr_rx_bufsize >= dr->dr_frameoffset +
4465203945Sweongyo	    sizeof(struct bwn_plcp6) + 2,
4466203945Sweongyo	    ("%s:%d: fail", __func__, __LINE__));
4467203945Sweongyo	frame = mtod(m, char *) + dr->dr_frameoffset;
4468203945Sweongyo	memset(frame, 0xff, sizeof(struct bwn_plcp6) + 2 /* padding */);
4469203945Sweongyo}
4470203945Sweongyo
4471203945Sweongyostatic uint8_t
4472203945Sweongyobwn_dma_check_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4473203945Sweongyo{
4474203945Sweongyo	unsigned char *f = mtod(m, char *) + dr->dr_frameoffset;
4475203945Sweongyo
4476203945Sweongyo	return ((f[0] & f[1] & f[2] & f[3] & f[4] & f[5] & f[6] & f[7])
4477203945Sweongyo	    == 0xff);
4478203945Sweongyo}
4479203945Sweongyo
4480203945Sweongyostatic void
4481203945Sweongyobwn_wme_init(struct bwn_mac *mac)
4482203945Sweongyo{
4483203945Sweongyo
4484203945Sweongyo	bwn_wme_load(mac);
4485203945Sweongyo
4486203945Sweongyo	/* enable WME support. */
4487203945Sweongyo	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_EDCF);
4488203945Sweongyo	BWN_WRITE_2(mac, BWN_IFSCTL, BWN_READ_2(mac, BWN_IFSCTL) |
4489203945Sweongyo	    BWN_IFSCTL_USE_EDCF);
4490203945Sweongyo}
4491203945Sweongyo
4492203945Sweongyostatic void
4493203945Sweongyobwn_spu_setdelay(struct bwn_mac *mac, int idle)
4494203945Sweongyo{
4495203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
4496203945Sweongyo	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
4497203945Sweongyo	uint16_t delay;	/* microsec */
4498203945Sweongyo
4499203945Sweongyo	delay = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 3700 : 1050;
4500203945Sweongyo	if (ic->ic_opmode == IEEE80211_M_IBSS || idle)
4501203945Sweongyo		delay = 500;
4502203945Sweongyo	if ((mac->mac_phy.rf_ver == 0x2050) && (mac->mac_phy.rf_rev == 8))
4503203945Sweongyo		delay = max(delay, (uint16_t)2400);
4504203945Sweongyo
4505203945Sweongyo	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SPU_WAKEUP, delay);
4506203945Sweongyo}
4507203945Sweongyo
4508203945Sweongyostatic void
4509203945Sweongyobwn_bt_enable(struct bwn_mac *mac)
4510203945Sweongyo{
4511204922Sweongyo	struct bwn_softc *sc = mac->mac_sc;
4512203945Sweongyo	uint64_t hf;
4513203945Sweongyo
4514203945Sweongyo	if (bwn_bluetooth == 0)
4515203945Sweongyo		return;
4516204922Sweongyo	if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCOEXIST) == 0)
4517203945Sweongyo		return;
4518203945Sweongyo	if (mac->mac_phy.type != BWN_PHYTYPE_B && !mac->mac_phy.gmode)
4519203945Sweongyo		return;
4520203945Sweongyo
4521203945Sweongyo	hf = bwn_hf_read(mac);
4522204922Sweongyo	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCMOD)
4523203945Sweongyo		hf |= BWN_HF_BT_COEXISTALT;
4524203945Sweongyo	else
4525203945Sweongyo		hf |= BWN_HF_BT_COEXIST;
4526203945Sweongyo	bwn_hf_write(mac, hf);
4527203945Sweongyo}
4528203945Sweongyo
4529203945Sweongyostatic void
4530203945Sweongyobwn_set_macaddr(struct bwn_mac *mac)
4531203945Sweongyo{
4532203945Sweongyo
4533203945Sweongyo	bwn_mac_write_bssid(mac);
4534203945Sweongyo	bwn_mac_setfilter(mac, BWN_MACFILTER_SELF, mac->mac_sc->sc_macaddr);
4535203945Sweongyo}
4536203945Sweongyo
4537203945Sweongyostatic void
4538203945Sweongyobwn_clear_keys(struct bwn_mac *mac)
4539203945Sweongyo{
4540203945Sweongyo	int i;
4541203945Sweongyo
4542203945Sweongyo	for (i = 0; i < mac->mac_max_nr_keys; i++) {
4543203945Sweongyo		KASSERT(i >= 0 && i < mac->mac_max_nr_keys,
4544203945Sweongyo		    ("%s:%d: fail", __func__, __LINE__));
4545203945Sweongyo
4546203945Sweongyo		bwn_key_dowrite(mac, i, BWN_SEC_ALGO_NONE,
4547203945Sweongyo		    NULL, BWN_SEC_KEYSIZE, NULL);
4548203945Sweongyo		if ((i <= 3) && !BWN_SEC_NEWAPI(mac)) {
4549203945Sweongyo			bwn_key_dowrite(mac, i + 4, BWN_SEC_ALGO_NONE,
4550203945Sweongyo			    NULL, BWN_SEC_KEYSIZE, NULL);
4551203945Sweongyo		}
4552203945Sweongyo		mac->mac_key[i].keyconf = NULL;
4553203945Sweongyo	}
4554203945Sweongyo}
4555203945Sweongyo
4556203945Sweongyostatic void
4557203945Sweongyobwn_crypt_init(struct bwn_mac *mac)
4558203945Sweongyo{
4559204922Sweongyo	struct bwn_softc *sc = mac->mac_sc;
4560203945Sweongyo
4561204922Sweongyo	mac->mac_max_nr_keys = (siba_get_revid(sc->sc_dev) >= 5) ? 58 : 20;
4562203945Sweongyo	KASSERT(mac->mac_max_nr_keys <= N(mac->mac_key),
4563203945Sweongyo	    ("%s:%d: fail", __func__, __LINE__));
4564203945Sweongyo	mac->mac_ktp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_KEY_TABLEP);
4565203945Sweongyo	mac->mac_ktp *= 2;
4566204922Sweongyo	if (siba_get_revid(sc->sc_dev) >= 5)
4567204922Sweongyo		BWN_WRITE_2(mac, BWN_RCMTA_COUNT, mac->mac_max_nr_keys - 8);
4568203945Sweongyo	bwn_clear_keys(mac);
4569203945Sweongyo}
4570203945Sweongyo
4571203945Sweongyostatic void
4572203945Sweongyobwn_chip_exit(struct bwn_mac *mac)
4573203945Sweongyo{
4574204922Sweongyo	struct bwn_softc *sc = mac->mac_sc;
4575203945Sweongyo
4576203945Sweongyo	bwn_phy_exit(mac);
4577204922Sweongyo	siba_gpio_set(sc->sc_dev, 0);
4578203945Sweongyo}
4579203945Sweongyo
4580203945Sweongyostatic int
4581203945Sweongyobwn_fw_fillinfo(struct bwn_mac *mac)
4582203945Sweongyo{
4583203945Sweongyo	int error;
4584203945Sweongyo
4585203945Sweongyo	error = bwn_fw_gets(mac, BWN_FWTYPE_DEFAULT);
4586203945Sweongyo	if (error == 0)
4587203945Sweongyo		return (0);
4588203945Sweongyo	error = bwn_fw_gets(mac, BWN_FWTYPE_OPENSOURCE);
4589203945Sweongyo	if (error == 0)
4590203945Sweongyo		return (0);
4591203945Sweongyo	return (error);
4592203945Sweongyo}
4593203945Sweongyo
4594203945Sweongyostatic int
4595203945Sweongyobwn_gpio_init(struct bwn_mac *mac)
4596203945Sweongyo{
4597204922Sweongyo	struct bwn_softc *sc = mac->mac_sc;
4598204922Sweongyo	uint32_t mask = 0x1f, set = 0xf, value;
4599203945Sweongyo
4600203945Sweongyo	BWN_WRITE_4(mac, BWN_MACCTL,
4601203945Sweongyo	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GPOUT_MASK);
4602203945Sweongyo	BWN_WRITE_2(mac, BWN_GPIO_MASK,
4603203945Sweongyo	    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x000f);
4604203945Sweongyo
4605204922Sweongyo	if (siba_get_chipid(sc->sc_dev) == 0x4301) {
4606203945Sweongyo		mask |= 0x0060;
4607203945Sweongyo		set |= 0x0060;
4608203945Sweongyo	}
4609204922Sweongyo	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL) {
4610203945Sweongyo		BWN_WRITE_2(mac, BWN_GPIO_MASK,
4611203945Sweongyo		    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x0200);
4612203945Sweongyo		mask |= 0x0200;
4613203945Sweongyo		set |= 0x0200;
4614203945Sweongyo	}
4615204922Sweongyo	if (siba_get_revid(sc->sc_dev) >= 2)
4616203945Sweongyo		mask |= 0x0010;
4617204922Sweongyo
4618204922Sweongyo	value = siba_gpio_get(sc->sc_dev);
4619204922Sweongyo	if (value == -1)
4620203945Sweongyo		return (0);
4621204922Sweongyo	siba_gpio_set(sc->sc_dev, (value & mask) | set);
4622203945Sweongyo
4623203945Sweongyo	return (0);
4624203945Sweongyo}
4625203945Sweongyo
4626203945Sweongyostatic int
4627203945Sweongyobwn_fw_loadinitvals(struct bwn_mac *mac)
4628203945Sweongyo{
4629203945Sweongyo#define	GETFWOFFSET(fwp, offset)				\
4630203945Sweongyo	((const struct bwn_fwinitvals *)((const char *)fwp.fw->data + offset))
4631203945Sweongyo	const size_t hdr_len = sizeof(struct bwn_fwhdr);
4632203945Sweongyo	const struct bwn_fwhdr *hdr;
4633203945Sweongyo	struct bwn_fw *fw = &mac->mac_fw;
4634203945Sweongyo	int error;
4635203945Sweongyo
4636203945Sweongyo	hdr = (const struct bwn_fwhdr *)(fw->initvals.fw->data);
4637203945Sweongyo	error = bwn_fwinitvals_write(mac, GETFWOFFSET(fw->initvals, hdr_len),
4638203945Sweongyo	    be32toh(hdr->size), fw->initvals.fw->datasize - hdr_len);
4639203945Sweongyo	if (error)
4640203945Sweongyo		return (error);
4641203945Sweongyo	if (fw->initvals_band.fw) {
4642203945Sweongyo		hdr = (const struct bwn_fwhdr *)(fw->initvals_band.fw->data);
4643203945Sweongyo		error = bwn_fwinitvals_write(mac,
4644203945Sweongyo		    GETFWOFFSET(fw->initvals_band, hdr_len),
4645203945Sweongyo		    be32toh(hdr->size),
4646203945Sweongyo		    fw->initvals_band.fw->datasize - hdr_len);
4647203945Sweongyo	}
4648203945Sweongyo	return (error);
4649203945Sweongyo#undef GETFWOFFSET
4650203945Sweongyo}
4651203945Sweongyo
4652203945Sweongyostatic int
4653203945Sweongyobwn_phy_init(struct bwn_mac *mac)
4654203945Sweongyo{
4655203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
4656203945Sweongyo	int error;
4657203945Sweongyo
4658203945Sweongyo	mac->mac_phy.chan = mac->mac_phy.get_default_chan(mac);
4659203945Sweongyo	mac->mac_phy.rf_onoff(mac, 1);
4660203945Sweongyo	error = mac->mac_phy.init(mac);
4661203945Sweongyo	if (error) {
4662203945Sweongyo		device_printf(sc->sc_dev, "PHY init failed\n");
4663203945Sweongyo		goto fail0;
4664203945Sweongyo	}
4665203945Sweongyo	error = bwn_switch_channel(mac,
4666203945Sweongyo	    mac->mac_phy.get_default_chan(mac));
4667203945Sweongyo	if (error) {
4668203945Sweongyo		device_printf(sc->sc_dev,
4669203945Sweongyo		    "failed to switch default channel\n");
4670203945Sweongyo		goto fail1;
4671203945Sweongyo	}
4672203945Sweongyo	return (0);
4673203945Sweongyofail1:
4674203945Sweongyo	if (mac->mac_phy.exit)
4675203945Sweongyo		mac->mac_phy.exit(mac);
4676203945Sweongyofail0:
4677203945Sweongyo	mac->mac_phy.rf_onoff(mac, 0);
4678203945Sweongyo
4679203945Sweongyo	return (error);
4680203945Sweongyo}
4681203945Sweongyo
4682203945Sweongyostatic void
4683203945Sweongyobwn_set_txantenna(struct bwn_mac *mac, int antenna)
4684203945Sweongyo{
4685203945Sweongyo	uint16_t ant;
4686203945Sweongyo	uint16_t tmp;
4687203945Sweongyo
4688203945Sweongyo	ant = bwn_ant2phy(antenna);
4689203945Sweongyo
4690203945Sweongyo	/* For ACK/CTS */
4691203945Sweongyo	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL);
4692203945Sweongyo	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4693203945Sweongyo	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, tmp);
4694203945Sweongyo	/* For Probe Resposes */
4695203945Sweongyo	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL);
4696203945Sweongyo	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4697203945Sweongyo	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, tmp);
4698203945Sweongyo}
4699203945Sweongyo
4700203945Sweongyostatic void
4701203945Sweongyobwn_set_opmode(struct bwn_mac *mac)
4702203945Sweongyo{
4703203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
4704203945Sweongyo	struct ifnet *ifp = sc->sc_ifp;
4705203945Sweongyo	struct ieee80211com *ic = ifp->if_l2com;
4706203945Sweongyo	uint32_t ctl;
4707203945Sweongyo	uint16_t cfp_pretbtt;
4708203945Sweongyo
4709203945Sweongyo	ctl = BWN_READ_4(mac, BWN_MACCTL);
4710203945Sweongyo	ctl &= ~(BWN_MACCTL_HOSTAP | BWN_MACCTL_PASS_CTL |
4711203945Sweongyo	    BWN_MACCTL_PASS_BADPLCP | BWN_MACCTL_PASS_BADFCS |
4712203945Sweongyo	    BWN_MACCTL_PROMISC | BWN_MACCTL_BEACON_PROMISC);
4713203945Sweongyo	ctl |= BWN_MACCTL_STA;
4714203945Sweongyo
4715203945Sweongyo	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
4716203945Sweongyo	    ic->ic_opmode == IEEE80211_M_MBSS)
4717203945Sweongyo		ctl |= BWN_MACCTL_HOSTAP;
4718203945Sweongyo	else if (ic->ic_opmode == IEEE80211_M_IBSS)
4719203945Sweongyo		ctl &= ~BWN_MACCTL_STA;
4720203945Sweongyo	ctl |= sc->sc_filters;
4721203945Sweongyo
4722204922Sweongyo	if (siba_get_revid(sc->sc_dev) <= 4)
4723203945Sweongyo		ctl |= BWN_MACCTL_PROMISC;
4724203945Sweongyo
4725203945Sweongyo	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
4726203945Sweongyo
4727203945Sweongyo	cfp_pretbtt = 2;
4728203945Sweongyo	if ((ctl & BWN_MACCTL_STA) && !(ctl & BWN_MACCTL_HOSTAP)) {
4729204922Sweongyo		if (siba_get_chipid(sc->sc_dev) == 0x4306 &&
4730204922Sweongyo		    siba_get_chiprev(sc->sc_dev) == 3)
4731203945Sweongyo			cfp_pretbtt = 100;
4732203945Sweongyo		else
4733203945Sweongyo			cfp_pretbtt = 50;
4734203945Sweongyo	}
4735203945Sweongyo	BWN_WRITE_2(mac, 0x612, cfp_pretbtt);
4736203945Sweongyo}
4737203945Sweongyo
4738203945Sweongyostatic int
4739203945Sweongyobwn_dma_gettype(struct bwn_mac *mac)
4740203945Sweongyo{
4741203945Sweongyo	uint32_t tmp;
4742203945Sweongyo	uint16_t base;
4743203945Sweongyo
4744203945Sweongyo	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
4745203945Sweongyo	if (tmp & SIBA_TGSHIGH_DMA64)
4746203945Sweongyo		return (BWN_DMA_64BIT);
4747203945Sweongyo	base = bwn_dma_base(0, 0);
4748203945Sweongyo	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
4749203945Sweongyo	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
4750203945Sweongyo	if (tmp & BWN_DMA32_TXADDREXT_MASK)
4751203945Sweongyo		return (BWN_DMA_32BIT);
4752203945Sweongyo
4753203945Sweongyo	return (BWN_DMA_30BIT);
4754203945Sweongyo}
4755203945Sweongyo
4756203945Sweongyostatic void
4757203945Sweongyobwn_dma_ring_addr(void *arg, bus_dma_segment_t *seg, int nseg, int error)
4758203945Sweongyo{
4759203945Sweongyo	if (!error) {
4760203945Sweongyo		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
4761203945Sweongyo		*((bus_addr_t *)arg) = seg->ds_addr;
4762203945Sweongyo	}
4763203945Sweongyo}
4764203945Sweongyo
4765203945Sweongyostatic void
4766203945Sweongyobwn_phy_g_init_sub(struct bwn_mac *mac)
4767203945Sweongyo{
4768203945Sweongyo	struct bwn_phy *phy = &mac->mac_phy;
4769203945Sweongyo	struct bwn_phy_g *pg = &phy->phy_g;
4770204922Sweongyo	struct bwn_softc *sc = mac->mac_sc;
4771203945Sweongyo	uint16_t i, tmp;
4772203945Sweongyo
4773203945Sweongyo	if (phy->rev == 1)
4774203945Sweongyo		bwn_phy_init_b5(mac);
4775203945Sweongyo	else
4776203945Sweongyo		bwn_phy_init_b6(mac);
4777203945Sweongyo
4778203945Sweongyo	if (phy->rev >= 2 || phy->gmode)
4779203945Sweongyo		bwn_phy_init_a(mac);
4780203945Sweongyo
4781203945Sweongyo	if (phy->rev >= 2) {
4782203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, 0);
4783203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, 0);
4784203945Sweongyo	}
4785203945Sweongyo	if (phy->rev == 2) {
4786203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
4787203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4788203945Sweongyo	}
4789203945Sweongyo	if (phy->rev > 5) {
4790203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x400);
4791203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4792203945Sweongyo	}
4793203945Sweongyo	if (phy->gmode || phy->rev >= 2) {
4794203945Sweongyo		tmp = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
4795203945Sweongyo		tmp &= BWN_PHYVER_VERSION;
4796203945Sweongyo		if (tmp == 3 || tmp == 5) {
4797203945Sweongyo			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc2), 0x1816);
4798203945Sweongyo			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc3), 0x8006);
4799203945Sweongyo		}
4800203945Sweongyo		if (tmp == 5) {
4801203945Sweongyo			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xcc), 0x00ff,
4802203945Sweongyo			    0x1f00);
4803203945Sweongyo		}
4804203945Sweongyo	}
4805203945Sweongyo	if ((phy->rev <= 2 && phy->gmode) || phy->rev >= 2)
4806203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x7e), 0x78);
4807203945Sweongyo	if (phy->rf_rev == 8) {
4808203945Sweongyo		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x80);
4809203945Sweongyo		BWN_PHY_SET(mac, BWN_PHY_OFDM(0x3e), 0x4);
4810203945Sweongyo	}
4811203945Sweongyo	if (BWN_HAS_LOOPBACK(phy))
4812203945Sweongyo		bwn_loopback_calcgain(mac);
4813203945Sweongyo
4814203945Sweongyo	if (phy->rf_rev != 8) {
4815203945Sweongyo		if (pg->pg_initval == 0xffff)
4816203945Sweongyo			pg->pg_initval = bwn_rf_init_bcm2050(mac);
4817203945Sweongyo		else
4818203945Sweongyo			BWN_RF_WRITE(mac, 0x0078, pg->pg_initval);
4819203945Sweongyo	}
4820203945Sweongyo	bwn_lo_g_init(mac);
4821203945Sweongyo	if (BWN_HAS_TXMAG(phy)) {
4822203945Sweongyo		BWN_RF_WRITE(mac, 0x52,
4823203945Sweongyo		    (BWN_RF_READ(mac, 0x52) & 0xff00)
4824203945Sweongyo		    | pg->pg_loctl.tx_bias |
4825203945Sweongyo		    pg->pg_loctl.tx_magn);
4826203945Sweongyo	} else {
4827203945Sweongyo		BWN_RF_SETMASK(mac, 0x52, 0xfff0, pg->pg_loctl.tx_bias);
4828203945Sweongyo	}
4829203945Sweongyo	if (phy->rev >= 6) {
4830203945Sweongyo		BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x36), 0x0fff,
4831203945Sweongyo		    (pg->pg_loctl.tx_bias << 12));
4832203945Sweongyo	}
4833204922Sweongyo	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
4834203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8075);
4835203945Sweongyo	else
4836203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x807f);
4837203945Sweongyo	if (phy->rev < 2)
4838203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x101);
4839203945Sweongyo	else
4840203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x202);
4841203945Sweongyo	if (phy->gmode || phy->rev >= 2) {
4842203945Sweongyo		bwn_lo_g_adjust(mac);
4843203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
4844203945Sweongyo	}
4845203945Sweongyo
4846204922Sweongyo	if (!(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI)) {
4847203945Sweongyo		for (i = 0; i < 64; i++) {
4848203945Sweongyo			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, i);
4849203945Sweongyo			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_DATA,
4850203945Sweongyo			    (uint16_t)MIN(MAX(bwn_nrssi_read(mac, i) - 0xffff,
4851203945Sweongyo			    -32), 31));
4852203945Sweongyo		}
4853203945Sweongyo		bwn_nrssi_threshold(mac);
4854203945Sweongyo	} else if (phy->gmode || phy->rev >= 2) {
4855203945Sweongyo		if (pg->pg_nrssi[0] == -1000) {
4856203945Sweongyo			KASSERT(pg->pg_nrssi[1] == -1000,
4857203945Sweongyo			    ("%s:%d: fail", __func__, __LINE__));
4858203945Sweongyo			bwn_nrssi_slope_11g(mac);
4859203945Sweongyo		} else
4860203945Sweongyo			bwn_nrssi_threshold(mac);
4861203945Sweongyo	}
4862203945Sweongyo	if (phy->rf_rev == 8)
4863203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x05), 0x3230);
4864203945Sweongyo	bwn_phy_hwpctl_init(mac);
4865204922Sweongyo	if ((siba_get_chipid(sc->sc_dev) == 0x4306
4866204922Sweongyo	     && siba_get_chippkg(sc->sc_dev) == 2) || 0) {
4867203945Sweongyo		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0xbfff);
4868203945Sweongyo		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xc3), 0x7fff);
4869203945Sweongyo	}
4870203945Sweongyo}
4871203945Sweongyo
4872203945Sweongyostatic uint8_t
4873203945Sweongyobwn_has_hwpctl(struct bwn_mac *mac)
4874203945Sweongyo{
4875203945Sweongyo
4876203945Sweongyo	if (mac->mac_phy.hwpctl == 0 || mac->mac_phy.use_hwpctl == NULL)
4877203945Sweongyo		return (0);
4878203945Sweongyo	return (mac->mac_phy.use_hwpctl(mac));
4879203945Sweongyo}
4880203945Sweongyo
4881203945Sweongyostatic void
4882203945Sweongyobwn_phy_init_b5(struct bwn_mac *mac)
4883203945Sweongyo{
4884203945Sweongyo	struct bwn_phy *phy = &mac->mac_phy;
4885203945Sweongyo	struct bwn_phy_g *pg = &phy->phy_g;
4886204922Sweongyo	struct bwn_softc *sc = mac->mac_sc;
4887203945Sweongyo	uint16_t offset, value;
4888203945Sweongyo	uint8_t old_channel;
4889203945Sweongyo
4890203945Sweongyo	if (phy->analog == 1)
4891203945Sweongyo		BWN_RF_SET(mac, 0x007a, 0x0050);
4892204922Sweongyo	if ((siba_get_pci_subvendor(sc->sc_dev) != SIBA_BOARDVENDOR_BCM) &&
4893204922Sweongyo	    (siba_get_pci_subdevice(sc->sc_dev) != SIBA_BOARD_BU4306)) {
4894203945Sweongyo		value = 0x2120;
4895203945Sweongyo		for (offset = 0x00a8; offset < 0x00c7; offset++) {
4896203945Sweongyo			BWN_PHY_WRITE(mac, offset, value);
4897203945Sweongyo			value += 0x202;
4898203945Sweongyo		}
4899203945Sweongyo	}
4900203945Sweongyo	BWN_PHY_SETMASK(mac, 0x0035, 0xf0ff, 0x0700);
4901203945Sweongyo	if (phy->rf_ver == 0x2050)
4902203945Sweongyo		BWN_PHY_WRITE(mac, 0x0038, 0x0667);
4903203945Sweongyo
4904203945Sweongyo	if (phy->gmode || phy->rev >= 2) {
4905203945Sweongyo		if (phy->rf_ver == 0x2050) {
4906203945Sweongyo			BWN_RF_SET(mac, 0x007a, 0x0020);
4907203945Sweongyo			BWN_RF_SET(mac, 0x0051, 0x0004);
4908203945Sweongyo		}
4909203945Sweongyo		BWN_WRITE_2(mac, BWN_PHY_RADIO, 0x0000);
4910203945Sweongyo
4911203945Sweongyo		BWN_PHY_SET(mac, 0x0802, 0x0100);
4912203945Sweongyo		BWN_PHY_SET(mac, 0x042b, 0x2000);
4913203945Sweongyo
4914203945Sweongyo		BWN_PHY_WRITE(mac, 0x001c, 0x186a);
4915203945Sweongyo
4916203945Sweongyo		BWN_PHY_SETMASK(mac, 0x0013, 0x00ff, 0x1900);
4917203945Sweongyo		BWN_PHY_SETMASK(mac, 0x0035, 0xffc0, 0x0064);
4918203945Sweongyo		BWN_PHY_SETMASK(mac, 0x005d, 0xff80, 0x000a);
4919203945Sweongyo	}
4920203945Sweongyo
4921203945Sweongyo	if (mac->mac_flags & BWN_MAC_FLAG_BADFRAME_PREEMP)
4922203945Sweongyo		BWN_PHY_SET(mac, BWN_PHY_RADIO_BITFIELD, (1 << 11));
4923203945Sweongyo
4924203945Sweongyo	if (phy->analog == 1) {
4925203945Sweongyo		BWN_PHY_WRITE(mac, 0x0026, 0xce00);
4926203945Sweongyo		BWN_PHY_WRITE(mac, 0x0021, 0x3763);
4927203945Sweongyo		BWN_PHY_WRITE(mac, 0x0022, 0x1bc3);
4928203945Sweongyo		BWN_PHY_WRITE(mac, 0x0023, 0x06f9);
4929203945Sweongyo		BWN_PHY_WRITE(mac, 0x0024, 0x037e);
4930203945Sweongyo	} else
4931203945Sweongyo		BWN_PHY_WRITE(mac, 0x0026, 0xcc00);
4932203945Sweongyo	BWN_PHY_WRITE(mac, 0x0030, 0x00c6);
4933203945Sweongyo	BWN_WRITE_2(mac, 0x03ec, 0x3f22);
4934203945Sweongyo
4935203945Sweongyo	if (phy->analog == 1)
4936203945Sweongyo		BWN_PHY_WRITE(mac, 0x0020, 0x3e1c);
4937203945Sweongyo	else
4938203945Sweongyo		BWN_PHY_WRITE(mac, 0x0020, 0x301c);
4939203945Sweongyo
4940203945Sweongyo	if (phy->analog == 0)
4941203945Sweongyo		BWN_WRITE_2(mac, 0x03e4, 0x3000);
4942203945Sweongyo
4943203945Sweongyo	old_channel = phy->chan;
4944203945Sweongyo	bwn_phy_g_switch_chan(mac, 7, 0);
4945203945Sweongyo
4946203945Sweongyo	if (phy->rf_ver != 0x2050) {
4947203945Sweongyo		BWN_RF_WRITE(mac, 0x0075, 0x0080);
4948203945Sweongyo		BWN_RF_WRITE(mac, 0x0079, 0x0081);
4949203945Sweongyo	}
4950203945Sweongyo
4951203945Sweongyo	BWN_RF_WRITE(mac, 0x0050, 0x0020);
4952203945Sweongyo	BWN_RF_WRITE(mac, 0x0050, 0x0023);
4953203945Sweongyo
4954203945Sweongyo	if (phy->rf_ver == 0x2050) {
4955203945Sweongyo		BWN_RF_WRITE(mac, 0x0050, 0x0020);
4956203945Sweongyo		BWN_RF_WRITE(mac, 0x005a, 0x0070);
4957203945Sweongyo	}
4958203945Sweongyo
4959203945Sweongyo	BWN_RF_WRITE(mac, 0x005b, 0x007b);
4960203945Sweongyo	BWN_RF_WRITE(mac, 0x005c, 0x00b0);
4961203945Sweongyo	BWN_RF_SET(mac, 0x007a, 0x0007);
4962203945Sweongyo
4963203945Sweongyo	bwn_phy_g_switch_chan(mac, old_channel, 0);
4964203945Sweongyo	BWN_PHY_WRITE(mac, 0x0014, 0x0080);
4965203945Sweongyo	BWN_PHY_WRITE(mac, 0x0032, 0x00ca);
4966203945Sweongyo	BWN_PHY_WRITE(mac, 0x002a, 0x88a3);
4967203945Sweongyo
4968203945Sweongyo	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
4969203945Sweongyo	    pg->pg_txctl);
4970203945Sweongyo
4971203945Sweongyo	if (phy->rf_ver == 0x2050)
4972203945Sweongyo		BWN_RF_WRITE(mac, 0x005d, 0x000d);
4973203945Sweongyo
4974203945Sweongyo	BWN_WRITE_2(mac, 0x03e4, (BWN_READ_2(mac, 0x03e4) & 0xffc0) | 0x0004);
4975203945Sweongyo}
4976203945Sweongyo
4977203945Sweongyostatic void
4978203945Sweongyobwn_loopback_calcgain(struct bwn_mac *mac)
4979203945Sweongyo{
4980203945Sweongyo	struct bwn_phy *phy = &mac->mac_phy;
4981203945Sweongyo	struct bwn_phy_g *pg = &phy->phy_g;
4982204922Sweongyo	struct bwn_softc *sc = mac->mac_sc;
4983203945Sweongyo	uint16_t backup_phy[16] = { 0 };
4984203945Sweongyo	uint16_t backup_radio[3];
4985203945Sweongyo	uint16_t backup_bband;
4986203945Sweongyo	uint16_t i, j, loop_i_max;
4987203945Sweongyo	uint16_t trsw_rx;
4988203945Sweongyo	uint16_t loop1_outer_done, loop1_inner_done;
4989203945Sweongyo
4990203945Sweongyo	backup_phy[0] = BWN_PHY_READ(mac, BWN_PHY_CRS0);
4991203945Sweongyo	backup_phy[1] = BWN_PHY_READ(mac, BWN_PHY_CCKBBANDCFG);
4992203945Sweongyo	backup_phy[2] = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
4993203945Sweongyo	backup_phy[3] = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
4994203945Sweongyo	if (phy->rev != 1) {
4995203945Sweongyo		backup_phy[4] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
4996203945Sweongyo		backup_phy[5] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
4997203945Sweongyo	}
4998203945Sweongyo	backup_phy[6] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
4999203945Sweongyo	backup_phy[7] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
5000203945Sweongyo	backup_phy[8] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
5001203945Sweongyo	backup_phy[9] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x0a));
5002203945Sweongyo	backup_phy[10] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x03));
5003203945Sweongyo	backup_phy[11] = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
5004203945Sweongyo	backup_phy[12] = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
5005203945Sweongyo	backup_phy[13] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2b));
5006203945Sweongyo	backup_phy[14] = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
5007203945Sweongyo	backup_phy[15] = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5008203945Sweongyo	backup_bband = pg->pg_bbatt.att;
5009203945Sweongyo	backup_radio[0] = BWN_RF_READ(mac, 0x52);
5010203945Sweongyo	backup_radio[1] = BWN_RF_READ(mac, 0x43);
5011203945Sweongyo	backup_radio[2] = BWN_RF_READ(mac, 0x7a);
5012203945Sweongyo
5013203945Sweongyo	BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x3fff);
5014203945Sweongyo	BWN_PHY_SET(mac, BWN_PHY_CCKBBANDCFG, 0x8000);
5015203945Sweongyo	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0002);
5016203945Sweongyo	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffd);
5017203945Sweongyo	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0001);
5018203945Sweongyo	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffe);
5019203945Sweongyo	if (phy->rev != 1) {
5020203945Sweongyo		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0001);
5021203945Sweongyo		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffe);
5022203945Sweongyo		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0002);
5023203945Sweongyo		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffd);
5024203945Sweongyo	}
5025203945Sweongyo	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x000c);
5026203945Sweongyo	BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x000c);
5027203945Sweongyo	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0030);
5028203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xffcf, 0x10);
5029203945Sweongyo
5030203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0780);
5031203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5032203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5033203945Sweongyo
5034203945Sweongyo	BWN_PHY_SET(mac, BWN_PHY_CCK(0x0a), 0x2000);
5035203945Sweongyo	if (phy->rev != 1) {
5036203945Sweongyo		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0004);
5037203945Sweongyo		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffb);
5038203945Sweongyo	}
5039203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xff9f, 0x40);
5040203945Sweongyo
5041203945Sweongyo	if (phy->rf_rev == 8)
5042203945Sweongyo		BWN_RF_WRITE(mac, 0x43, 0x000f);
5043203945Sweongyo	else {
5044203945Sweongyo		BWN_RF_WRITE(mac, 0x52, 0);
5045203945Sweongyo		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x9);
5046203945Sweongyo	}
5047203945Sweongyo	bwn_phy_g_set_bbatt(mac, 11);
5048203945Sweongyo
5049203945Sweongyo	if (phy->rev >= 3)
5050203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
5051203945Sweongyo	else
5052203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
5053203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
5054203945Sweongyo
5055203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xffc0, 0x01);
5056203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xc0ff, 0x800);
5057203945Sweongyo
5058203945Sweongyo	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0100);
5059203945Sweongyo	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xcfff);
5060203945Sweongyo
5061204922Sweongyo	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA) {
5062203945Sweongyo		if (phy->rev >= 7) {
5063203945Sweongyo			BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0800);
5064203945Sweongyo			BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x8000);
5065203945Sweongyo		}
5066203945Sweongyo	}
5067203945Sweongyo	BWN_RF_MASK(mac, 0x7a, 0x00f7);
5068203945Sweongyo
5069203945Sweongyo	j = 0;
5070203945Sweongyo	loop_i_max = (phy->rf_rev == 8) ? 15 : 9;
5071203945Sweongyo	for (i = 0; i < loop_i_max; i++) {
5072203945Sweongyo		for (j = 0; j < 16; j++) {
5073203945Sweongyo			BWN_RF_WRITE(mac, 0x43, i);
5074203945Sweongyo			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff,
5075203945Sweongyo			    (j << 8));
5076203945Sweongyo			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
5077203945Sweongyo			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
5078203945Sweongyo			DELAY(20);
5079203945Sweongyo			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
5080203945Sweongyo				goto done0;
5081203945Sweongyo		}
5082203945Sweongyo	}
5083203945Sweongyodone0:
5084203945Sweongyo	loop1_outer_done = i;
5085203945Sweongyo	loop1_inner_done = j;
5086203945Sweongyo	if (j >= 8) {
5087203945Sweongyo		BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x30);
5088203945Sweongyo		trsw_rx = 0x1b;
5089203945Sweongyo		for (j = j - 8; j < 16; j++) {
5090203945Sweongyo			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff, j << 8);
5091203945Sweongyo			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
5092203945Sweongyo			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
5093203945Sweongyo			DELAY(20);
5094203945Sweongyo			trsw_rx -= 3;
5095203945Sweongyo			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
5096203945Sweongyo				goto done1;
5097203945Sweongyo		}
5098203945Sweongyo	} else
5099203945Sweongyo		trsw_rx = 0x18;
5100203945Sweongyodone1:
5101203945Sweongyo
5102203945Sweongyo	if (phy->rev != 1) {
5103203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, backup_phy[4]);
5104203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, backup_phy[5]);
5105203945Sweongyo	}
5106203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), backup_phy[6]);
5107203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), backup_phy[7]);
5108203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), backup_phy[8]);
5109203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x0a), backup_phy[9]);
5110203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x03), backup_phy[10]);
5111203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, backup_phy[11]);
5112203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, backup_phy[12]);
5113203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), backup_phy[13]);
5114203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, backup_phy[14]);
5115203945Sweongyo
5116203945Sweongyo	bwn_phy_g_set_bbatt(mac, backup_bband);
5117203945Sweongyo
5118203945Sweongyo	BWN_RF_WRITE(mac, 0x52, backup_radio[0]);
5119203945Sweongyo	BWN_RF_WRITE(mac, 0x43, backup_radio[1]);
5120203945Sweongyo	BWN_RF_WRITE(mac, 0x7a, backup_radio[2]);
5121203945Sweongyo
5122203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2] | 0x0003);
5123203945Sweongyo	DELAY(10);
5124203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2]);
5125203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, backup_phy[3]);
5126203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_CRS0, backup_phy[0]);
5127203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_CCKBBANDCFG, backup_phy[1]);
5128203945Sweongyo
5129203945Sweongyo	pg->pg_max_lb_gain =
5130203945Sweongyo	    ((loop1_inner_done * 6) - (loop1_outer_done * 4)) - 11;
5131203945Sweongyo	pg->pg_trsw_rx_gain = trsw_rx * 2;
5132203945Sweongyo}
5133203945Sweongyo
5134203945Sweongyostatic uint16_t
5135203945Sweongyobwn_rf_init_bcm2050(struct bwn_mac *mac)
5136203945Sweongyo{
5137203945Sweongyo	struct bwn_phy *phy = &mac->mac_phy;
5138203945Sweongyo	uint32_t tmp1 = 0, tmp2 = 0;
5139203945Sweongyo	uint16_t rcc, i, j, pgactl, cck0, cck1, cck2, cck3, rfover, rfoverval,
5140203945Sweongyo	    analogover, analogoverval, crs0, classctl, lomask, loctl, syncctl,
5141203945Sweongyo	    radio0, radio1, radio2, reg0, reg1, reg2, radio78, reg, index;
5142203945Sweongyo	static const uint8_t rcc_table[] = {
5143203945Sweongyo		0x02, 0x03, 0x01, 0x0f,
5144203945Sweongyo		0x06, 0x07, 0x05, 0x0f,
5145203945Sweongyo		0x0a, 0x0b, 0x09, 0x0f,
5146203945Sweongyo		0x0e, 0x0f, 0x0d, 0x0f,
5147203945Sweongyo	};
5148203945Sweongyo
5149204242Simp	loctl = lomask = reg0 = classctl = crs0 = analogoverval = analogover =
5150204242Simp	    rfoverval = rfover = cck3 = 0;
5151203945Sweongyo	radio0 = BWN_RF_READ(mac, 0x43);
5152203945Sweongyo	radio1 = BWN_RF_READ(mac, 0x51);
5153203945Sweongyo	radio2 = BWN_RF_READ(mac, 0x52);
5154203945Sweongyo	pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
5155203945Sweongyo	cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
5156203945Sweongyo	cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
5157203945Sweongyo	cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
5158203945Sweongyo
5159203945Sweongyo	if (phy->type == BWN_PHYTYPE_B) {
5160203945Sweongyo		cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
5161203945Sweongyo		reg0 = BWN_READ_2(mac, 0x3ec);
5162203945Sweongyo
5163203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0xff);
5164203945Sweongyo		BWN_WRITE_2(mac, 0x3ec, 0x3f3f);
5165203945Sweongyo	} else if (phy->gmode || phy->rev >= 2) {
5166203945Sweongyo		rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
5167203945Sweongyo		rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
5168203945Sweongyo		analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
5169203945Sweongyo		analogoverval = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
5170203945Sweongyo		crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
5171203945Sweongyo		classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
5172203945Sweongyo
5173203945Sweongyo		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
5174203945Sweongyo		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
5175203945Sweongyo		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
5176203945Sweongyo		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
5177203945Sweongyo		if (BWN_HAS_LOOPBACK(phy)) {
5178203945Sweongyo			lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
5179203945Sweongyo			loctl = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
5180203945Sweongyo			if (phy->rev >= 3)
5181203945Sweongyo				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
5182203945Sweongyo			else
5183203945Sweongyo				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
5184203945Sweongyo			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
5185203945Sweongyo		}
5186203945Sweongyo
5187203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5188203945Sweongyo		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5189203945Sweongyo			BWN_LPD(0, 1, 1)));
5190203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
5191203945Sweongyo		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVER, 0));
5192203945Sweongyo	}
5193203945Sweongyo	BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2) | 0x8000);
5194203945Sweongyo
5195203945Sweongyo	syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
5196203945Sweongyo	BWN_PHY_MASK(mac, BWN_PHY_SYNCCTL, 0xff7f);
5197203945Sweongyo	reg1 = BWN_READ_2(mac, 0x3e6);
5198203945Sweongyo	reg2 = BWN_READ_2(mac, 0x3f4);
5199203945Sweongyo
5200203945Sweongyo	if (phy->analog == 0)
5201203945Sweongyo		BWN_WRITE_2(mac, 0x03e6, 0x0122);
5202203945Sweongyo	else {
5203203945Sweongyo		if (phy->analog >= 2)
5204203945Sweongyo			BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xffbf, 0x40);
5205203945Sweongyo		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
5206203945Sweongyo		    (BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000));
5207203945Sweongyo	}
5208203945Sweongyo
5209203945Sweongyo	reg = BWN_RF_READ(mac, 0x60);
5210203945Sweongyo	index = (reg & 0x001e) >> 1;
5211203945Sweongyo	rcc = (((rcc_table[index] << 1) | (reg & 0x0001)) | 0x0020);
5212203945Sweongyo
5213203945Sweongyo	if (phy->type == BWN_PHYTYPE_B)
5214203945Sweongyo		BWN_RF_WRITE(mac, 0x78, 0x26);
5215203945Sweongyo	if (phy->gmode || phy->rev >= 2) {
5216203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5217203945Sweongyo		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5218203945Sweongyo			BWN_LPD(0, 1, 1)));
5219203945Sweongyo	}
5220203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfaf);
5221203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1403);
5222203945Sweongyo	if (phy->gmode || phy->rev >= 2) {
5223203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5224203945Sweongyo		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5225203945Sweongyo			BWN_LPD(0, 0, 1)));
5226203945Sweongyo	}
5227203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfa0);
5228203945Sweongyo	BWN_RF_SET(mac, 0x51, 0x0004);
5229203945Sweongyo	if (phy->rf_rev == 8)
5230203945Sweongyo		BWN_RF_WRITE(mac, 0x43, 0x1f);
5231203945Sweongyo	else {
5232203945Sweongyo		BWN_RF_WRITE(mac, 0x52, 0);
5233203945Sweongyo		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x0009);
5234203945Sweongyo	}
5235203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5236203945Sweongyo
5237203945Sweongyo	for (i = 0; i < 16; i++) {
5238203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0480);
5239203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5240203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5241203945Sweongyo		if (phy->gmode || phy->rev >= 2) {
5242203945Sweongyo			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5243203945Sweongyo			    bwn_rf_2050_rfoverval(mac,
5244203945Sweongyo				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5245203945Sweongyo		}
5246203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5247203945Sweongyo		DELAY(10);
5248203945Sweongyo		if (phy->gmode || phy->rev >= 2) {
5249203945Sweongyo			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5250203945Sweongyo			    bwn_rf_2050_rfoverval(mac,
5251203945Sweongyo				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5252203945Sweongyo		}
5253203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5254203945Sweongyo		DELAY(10);
5255203945Sweongyo		if (phy->gmode || phy->rev >= 2) {
5256203945Sweongyo			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5257203945Sweongyo			    bwn_rf_2050_rfoverval(mac,
5258203945Sweongyo				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5259203945Sweongyo		}
5260203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5261203945Sweongyo		DELAY(20);
5262203945Sweongyo		tmp1 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5263203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5264203945Sweongyo		if (phy->gmode || phy->rev >= 2) {
5265203945Sweongyo			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5266203945Sweongyo			    bwn_rf_2050_rfoverval(mac,
5267203945Sweongyo				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5268203945Sweongyo		}
5269203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5270203945Sweongyo	}
5271203945Sweongyo	DELAY(10);
5272203945Sweongyo
5273203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5274203945Sweongyo	tmp1++;
5275203945Sweongyo	tmp1 >>= 9;
5276203945Sweongyo
5277203945Sweongyo	for (i = 0; i < 16; i++) {
5278203945Sweongyo		radio78 = (BWN_BITREV4(i) << 1) | 0x0020;
5279203945Sweongyo		BWN_RF_WRITE(mac, 0x78, radio78);
5280203945Sweongyo		DELAY(10);
5281203945Sweongyo		for (j = 0; j < 16; j++) {
5282203945Sweongyo			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0d80);
5283203945Sweongyo			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5284203945Sweongyo			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5285203945Sweongyo			if (phy->gmode || phy->rev >= 2) {
5286203945Sweongyo				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5287203945Sweongyo				    bwn_rf_2050_rfoverval(mac,
5288203945Sweongyo					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5289203945Sweongyo			}
5290203945Sweongyo			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5291203945Sweongyo			DELAY(10);
5292203945Sweongyo			if (phy->gmode || phy->rev >= 2) {
5293203945Sweongyo				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5294203945Sweongyo				    bwn_rf_2050_rfoverval(mac,
5295203945Sweongyo					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5296203945Sweongyo			}
5297203945Sweongyo			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5298203945Sweongyo			DELAY(10);
5299203945Sweongyo			if (phy->gmode || phy->rev >= 2) {
5300203945Sweongyo				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5301203945Sweongyo				    bwn_rf_2050_rfoverval(mac,
5302203945Sweongyo					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5303203945Sweongyo			}
5304203945Sweongyo			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5305203945Sweongyo			DELAY(10);
5306203945Sweongyo			tmp2 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5307203945Sweongyo			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5308203945Sweongyo			if (phy->gmode || phy->rev >= 2) {
5309203945Sweongyo				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5310203945Sweongyo				    bwn_rf_2050_rfoverval(mac,
5311203945Sweongyo					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5312203945Sweongyo			}
5313203945Sweongyo			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5314203945Sweongyo		}
5315203945Sweongyo		tmp2++;
5316203945Sweongyo		tmp2 >>= 8;
5317203945Sweongyo		if (tmp1 < tmp2)
5318203945Sweongyo			break;
5319203945Sweongyo	}
5320203945Sweongyo
5321203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pgactl);
5322203945Sweongyo	BWN_RF_WRITE(mac, 0x51, radio1);
5323203945Sweongyo	BWN_RF_WRITE(mac, 0x52, radio2);
5324203945Sweongyo	BWN_RF_WRITE(mac, 0x43, radio0);
5325203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), cck0);
5326203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), cck1);
5327203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), cck2);
5328203945Sweongyo	BWN_WRITE_2(mac, 0x3e6, reg1);
5329203945Sweongyo	if (phy->analog != 0)
5330203945Sweongyo		BWN_WRITE_2(mac, 0x3f4, reg2);
5331203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, syncctl);
5332203945Sweongyo	bwn_spu_workaround(mac, phy->chan);
5333203945Sweongyo	if (phy->type == BWN_PHYTYPE_B) {
5334203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), cck3);
5335203945Sweongyo		BWN_WRITE_2(mac, 0x3ec, reg0);
5336203945Sweongyo	} else if (phy->gmode) {
5337203945Sweongyo		BWN_WRITE_2(mac, BWN_PHY_RADIO,
5338203945Sweongyo			    BWN_READ_2(mac, BWN_PHY_RADIO)
5339203945Sweongyo			    & 0x7fff);
5340203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover);
5341203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval);
5342203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, analogover);
5343203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
5344203945Sweongyo			      analogoverval);
5345203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, crs0);
5346203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, classctl);
5347203945Sweongyo		if (BWN_HAS_LOOPBACK(phy)) {
5348203945Sweongyo			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, lomask);
5349203945Sweongyo			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, loctl);
5350203945Sweongyo		}
5351203945Sweongyo	}
5352203945Sweongyo
5353203945Sweongyo	return ((i > 15) ? radio78 : rcc);
5354203945Sweongyo}
5355203945Sweongyo
5356203945Sweongyostatic void
5357203945Sweongyobwn_phy_init_b6(struct bwn_mac *mac)
5358203945Sweongyo{
5359203945Sweongyo	struct bwn_phy *phy = &mac->mac_phy;
5360203945Sweongyo	struct bwn_phy_g *pg = &phy->phy_g;
5361204922Sweongyo	struct bwn_softc *sc = mac->mac_sc;
5362203945Sweongyo	uint16_t offset, val;
5363203945Sweongyo	uint8_t old_channel;
5364203945Sweongyo
5365203945Sweongyo	KASSERT(!(phy->rf_rev == 6 || phy->rf_rev == 7),
5366203945Sweongyo	    ("%s:%d: fail", __func__, __LINE__));
5367203945Sweongyo
5368203945Sweongyo	BWN_PHY_WRITE(mac, 0x003e, 0x817a);
5369203945Sweongyo	BWN_RF_WRITE(mac, 0x007a, BWN_RF_READ(mac, 0x007a) | 0x0058);
5370203945Sweongyo	if (phy->rf_rev == 4 || phy->rf_rev == 5) {
5371203945Sweongyo		BWN_RF_WRITE(mac, 0x51, 0x37);
5372203945Sweongyo		BWN_RF_WRITE(mac, 0x52, 0x70);
5373203945Sweongyo		BWN_RF_WRITE(mac, 0x53, 0xb3);
5374203945Sweongyo		BWN_RF_WRITE(mac, 0x54, 0x9b);
5375203945Sweongyo		BWN_RF_WRITE(mac, 0x5a, 0x88);
5376203945Sweongyo		BWN_RF_WRITE(mac, 0x5b, 0x88);
5377203945Sweongyo		BWN_RF_WRITE(mac, 0x5d, 0x88);
5378203945Sweongyo		BWN_RF_WRITE(mac, 0x5e, 0x88);
5379203945Sweongyo		BWN_RF_WRITE(mac, 0x7d, 0x88);
5380203945Sweongyo		bwn_hf_write(mac,
5381203945Sweongyo		    bwn_hf_read(mac) | BWN_HF_TSSI_RESET_PSM_WORKAROUN);
5382203945Sweongyo	}
5383203945Sweongyo	if (phy->rf_rev == 8) {
5384203945Sweongyo		BWN_RF_WRITE(mac, 0x51, 0);
5385203945Sweongyo		BWN_RF_WRITE(mac, 0x52, 0x40);
5386203945Sweongyo		BWN_RF_WRITE(mac, 0x53, 0xb7);
5387203945Sweongyo		BWN_RF_WRITE(mac, 0x54, 0x98);
5388203945Sweongyo		BWN_RF_WRITE(mac, 0x5a, 0x88);
5389203945Sweongyo		BWN_RF_WRITE(mac, 0x5b, 0x6b);
5390203945Sweongyo		BWN_RF_WRITE(mac, 0x5c, 0x0f);
5391204922Sweongyo		if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_ALTIQ) {
5392203945Sweongyo			BWN_RF_WRITE(mac, 0x5d, 0xfa);
5393203945Sweongyo			BWN_RF_WRITE(mac, 0x5e, 0xd8);
5394203945Sweongyo		} else {
5395203945Sweongyo			BWN_RF_WRITE(mac, 0x5d, 0xf5);
5396203945Sweongyo			BWN_RF_WRITE(mac, 0x5e, 0xb8);
5397203945Sweongyo		}
5398203945Sweongyo		BWN_RF_WRITE(mac, 0x0073, 0x0003);
5399203945Sweongyo		BWN_RF_WRITE(mac, 0x007d, 0x00a8);
5400203945Sweongyo		BWN_RF_WRITE(mac, 0x007c, 0x0001);
5401203945Sweongyo		BWN_RF_WRITE(mac, 0x007e, 0x0008);
5402203945Sweongyo	}
5403203945Sweongyo	for (val = 0x1e1f, offset = 0x0088; offset < 0x0098; offset++) {
5404203945Sweongyo		BWN_PHY_WRITE(mac, offset, val);
5405203945Sweongyo		val -= 0x0202;
5406203945Sweongyo	}
5407203945Sweongyo	for (val = 0x3e3f, offset = 0x0098; offset < 0x00a8; offset++) {
5408203945Sweongyo		BWN_PHY_WRITE(mac, offset, val);
5409203945Sweongyo		val -= 0x0202;
5410203945Sweongyo	}
5411203945Sweongyo	for (val = 0x2120, offset = 0x00a8; offset < 0x00c8; offset++) {
5412203945Sweongyo		BWN_PHY_WRITE(mac, offset, (val & 0x3f3f));
5413203945Sweongyo		val += 0x0202;
5414203945Sweongyo	}
5415203945Sweongyo	if (phy->type == BWN_PHYTYPE_G) {
5416203945Sweongyo		BWN_RF_SET(mac, 0x007a, 0x0020);
5417203945Sweongyo		BWN_RF_SET(mac, 0x0051, 0x0004);
5418203945Sweongyo		BWN_PHY_SET(mac, 0x0802, 0x0100);
5419203945Sweongyo		BWN_PHY_SET(mac, 0x042b, 0x2000);
5420203945Sweongyo		BWN_PHY_WRITE(mac, 0x5b, 0);
5421203945Sweongyo		BWN_PHY_WRITE(mac, 0x5c, 0);
5422203945Sweongyo	}
5423203945Sweongyo
5424203945Sweongyo	old_channel = phy->chan;
5425203945Sweongyo	bwn_phy_g_switch_chan(mac, (old_channel >= 8) ? 1 : 13, 0);
5426203945Sweongyo
5427203945Sweongyo	BWN_RF_WRITE(mac, 0x0050, 0x0020);
5428203945Sweongyo	BWN_RF_WRITE(mac, 0x0050, 0x0023);
5429203945Sweongyo	DELAY(40);
5430203945Sweongyo	if (phy->rf_rev < 6 || phy->rf_rev == 8) {
5431203945Sweongyo		BWN_RF_WRITE(mac, 0x7c, BWN_RF_READ(mac, 0x7c) | 0x0002);
5432203945Sweongyo		BWN_RF_WRITE(mac, 0x50, 0x20);
5433203945Sweongyo	}
5434203945Sweongyo	if (phy->rf_rev <= 2) {
5435203945Sweongyo		BWN_RF_WRITE(mac, 0x7c, 0x20);
5436203945Sweongyo		BWN_RF_WRITE(mac, 0x5a, 0x70);
5437203945Sweongyo		BWN_RF_WRITE(mac, 0x5b, 0x7b);
5438203945Sweongyo		BWN_RF_WRITE(mac, 0x5c, 0xb0);
5439203945Sweongyo	}
5440203945Sweongyo	BWN_RF_SETMASK(mac, 0x007a, 0x00f8, 0x0007);
5441203945Sweongyo
5442203945Sweongyo	bwn_phy_g_switch_chan(mac, old_channel, 0);
5443203945Sweongyo
5444203945Sweongyo	BWN_PHY_WRITE(mac, 0x0014, 0x0200);
5445203945Sweongyo	if (phy->rf_rev >= 6)
5446203945Sweongyo		BWN_PHY_WRITE(mac, 0x2a, 0x88c2);
5447203945Sweongyo	else
5448203945Sweongyo		BWN_PHY_WRITE(mac, 0x2a, 0x8ac0);
5449203945Sweongyo	BWN_PHY_WRITE(mac, 0x0038, 0x0668);
5450203945Sweongyo	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
5451203945Sweongyo	    pg->pg_txctl);
5452203945Sweongyo	if (phy->rf_rev <= 5)
5453203945Sweongyo		BWN_PHY_SETMASK(mac, 0x5d, 0xff80, 0x0003);
5454203945Sweongyo	if (phy->rf_rev <= 2)
5455203945Sweongyo		BWN_RF_WRITE(mac, 0x005d, 0x000d);
5456203945Sweongyo
5457203945Sweongyo	if (phy->analog == 4) {
5458203945Sweongyo		BWN_WRITE_2(mac, 0x3e4, 9);
5459203945Sweongyo		BWN_PHY_MASK(mac, 0x61, 0x0fff);
5460203945Sweongyo	} else
5461203945Sweongyo		BWN_PHY_SETMASK(mac, 0x0002, 0xffc0, 0x0004);
5462203945Sweongyo	if (phy->type == BWN_PHYTYPE_B)
5463203945Sweongyo		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5464203945Sweongyo	else if (phy->type == BWN_PHYTYPE_G)
5465203945Sweongyo		BWN_WRITE_2(mac, 0x03e6, 0x0);
5466203945Sweongyo}
5467203945Sweongyo
5468203945Sweongyostatic void
5469203945Sweongyobwn_phy_init_a(struct bwn_mac *mac)
5470203945Sweongyo{
5471203945Sweongyo	struct bwn_phy *phy = &mac->mac_phy;
5472204922Sweongyo	struct bwn_softc *sc = mac->mac_sc;
5473203945Sweongyo
5474203945Sweongyo	KASSERT(phy->type == BWN_PHYTYPE_A || phy->type == BWN_PHYTYPE_G,
5475203945Sweongyo	    ("%s:%d: fail", __func__, __LINE__));
5476203945Sweongyo
5477203945Sweongyo	if (phy->rev >= 6) {
5478203945Sweongyo		if (phy->type == BWN_PHYTYPE_A)
5479203945Sweongyo			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x1000);
5480203945Sweongyo		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) & BWN_PHY_ENCORE_EN)
5481203945Sweongyo			BWN_PHY_SET(mac, BWN_PHY_ENCORE, 0x0010);
5482203945Sweongyo		else
5483203945Sweongyo			BWN_PHY_MASK(mac, BWN_PHY_ENCORE, ~0x1010);
5484203945Sweongyo	}
5485203945Sweongyo
5486203945Sweongyo	bwn_wa_init(mac);
5487203945Sweongyo
5488203945Sweongyo	if (phy->type == BWN_PHYTYPE_G &&
5489204922Sweongyo	    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL))
5490203945Sweongyo		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x6e), 0xe000, 0x3cf);
5491203945Sweongyo}
5492203945Sweongyo
5493203945Sweongyostatic void
5494203945Sweongyobwn_wa_write_noisescale(struct bwn_mac *mac, const uint16_t *nst)
5495203945Sweongyo{
5496203945Sweongyo	int i;
5497203945Sweongyo
5498203945Sweongyo	for (i = 0; i < BWN_TAB_NOISESCALE_SIZE; i++)
5499203945Sweongyo		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_NOISESCALE, i, nst[i]);
5500203945Sweongyo}
5501203945Sweongyo
5502203945Sweongyostatic void
5503203945Sweongyobwn_wa_agc(struct bwn_mac *mac)
5504203945Sweongyo{
5505203945Sweongyo	struct bwn_phy *phy = &mac->mac_phy;
5506203945Sweongyo
5507203945Sweongyo	if (phy->rev == 1) {
5508203945Sweongyo		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 0, 254);
5509203945Sweongyo		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 1, 13);
5510203945Sweongyo		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 2, 19);
5511203945Sweongyo		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 3, 25);
5512203945Sweongyo		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 0, 0x2710);
5513203945Sweongyo		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 1, 0x9b83);
5514203945Sweongyo		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 2, 0x9b83);
5515203945Sweongyo		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 3, 0x0f8d);
5516203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_LMS, 4);
5517203945Sweongyo	} else {
5518203945Sweongyo		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 0, 254);
5519203945Sweongyo		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 1, 13);
5520203945Sweongyo		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 2, 19);
5521203945Sweongyo		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 3, 25);
5522203945Sweongyo	}
5523203945Sweongyo
5524203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_CCKSHIFTBITS_WA, (uint16_t)~0xff00,
5525203945Sweongyo	    0x5700);
5526203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x007f, 0x000f);
5527203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x3f80, 0x2b80);
5528203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, 0xf0ff, 0x0300);
5529203945Sweongyo	BWN_RF_SET(mac, 0x7a, 0x0008);
5530203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x000f, 0x0008);
5531203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_P1P2GAIN, ~0x0f00, 0x0600);
5532203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x0f00, 0x0700);
5533203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x0f00, 0x0100);
5534203945Sweongyo	if (phy->rev == 1)
5535203945Sweongyo		BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x000f, 0x0007);
5536203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x00ff, 0x001c);
5537203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x3f00, 0x0200);
5538203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), ~0x00ff, 0x001c);
5539203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x00ff, 0x0020);
5540203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x3f00, 0x0200);
5541203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x82), ~0x00ff, 0x002e);
5542203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), (uint16_t)~0xff00, 0x1a00);
5543203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), ~0x00ff, 0x0028);
5544203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), (uint16_t)~0xff00, 0x2c00);
5545203945Sweongyo	if (phy->rev == 1) {
5546203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_PEAK_COUNT, 0x092b);
5547203945Sweongyo		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e, 0x0002);
5548203945Sweongyo	} else {
5549203945Sweongyo		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e);
5550203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x1f), 0x287a);
5551203945Sweongyo		BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL, ~0x000f, 0x0004);
5552203945Sweongyo		if (phy->rev >= 6) {
5553203945Sweongyo			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x22), 0x287a);
5554203945Sweongyo			BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL,
5555203945Sweongyo			    (uint16_t)~0xf000, 0x3000);
5556203945Sweongyo		}
5557203945Sweongyo	}
5558203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_DIVSRCHIDX, 0x8080, 0x7874);
5559203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8e), 0x1c00);
5560203945Sweongyo	if (phy->rev == 1) {
5561203945Sweongyo		BWN_PHY_SETMASK(mac, BWN_PHY_DIVP1P2GAIN, ~0x0f00, 0x0600);
5562203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8b), 0x005e);
5563203945Sweongyo		BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, ~0x00ff, 0x001e);
5564203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8d), 0x0002);
5565203945Sweongyo		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 0, 0);
5566203945Sweongyo		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 1, 7);
5567203945Sweongyo		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 2, 16);
5568203945Sweongyo		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 3, 28);
5569203945Sweongyo	} else {
5570203945Sweongyo		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 0, 0);
5571203945Sweongyo		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 1, 7);
5572203945Sweongyo		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 2, 16);
5573203945Sweongyo		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 3, 28);
5574203945Sweongyo	}
5575203945Sweongyo	if (phy->rev >= 6) {
5576203945Sweongyo		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x0003);
5577203945Sweongyo		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x1000);
5578203945Sweongyo	}
5579203945Sweongyo	BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
5580203945Sweongyo}
5581203945Sweongyo
5582203945Sweongyostatic void
5583203945Sweongyobwn_wa_grev1(struct bwn_mac *mac)
5584203945Sweongyo{
5585203945Sweongyo	struct bwn_phy *phy = &mac->mac_phy;
5586203945Sweongyo	int i;
5587203945Sweongyo	static const uint16_t bwn_tab_finefreqg[] = BWN_TAB_FINEFREQ_G;
5588203945Sweongyo	static const uint32_t bwn_tab_retard[] = BWN_TAB_RETARD;
5589203945Sweongyo	static const uint32_t bwn_tab_rotor[] = BWN_TAB_ROTOR;
5590203945Sweongyo
5591203945Sweongyo	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5592203945Sweongyo
5593203945Sweongyo	/* init CRSTHRES and ANTDWELL */
5594203945Sweongyo	if (phy->rev == 1) {
5595203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5596203945Sweongyo	} else if (phy->rev == 2) {
5597203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5598203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5599203945Sweongyo		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5600203945Sweongyo	} else {
5601203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5602203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5603203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5604203945Sweongyo		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5605203945Sweongyo	}
5606203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_CRS0, ~0x03c0, 0xd000);
5607203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x2c), 0x005a);
5608203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_CCKSHIFTBITS, 0x0026);
5609203945Sweongyo
5610203945Sweongyo	/* XXX support PHY-A??? */
5611203945Sweongyo	for (i = 0; i < N(bwn_tab_finefreqg); i++)
5612203945Sweongyo		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DACRFPABB, i,
5613203945Sweongyo		    bwn_tab_finefreqg[i]);
5614203945Sweongyo
5615203945Sweongyo	/* XXX support PHY-A??? */
5616203945Sweongyo	if (phy->rev == 1)
5617203945Sweongyo		for (i = 0; i < N(bwn_tab_noise_g1); i++)
5618203945Sweongyo			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5619203945Sweongyo			    bwn_tab_noise_g1[i]);
5620203945Sweongyo	else
5621203945Sweongyo		for (i = 0; i < N(bwn_tab_noise_g2); i++)
5622203945Sweongyo			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5623203945Sweongyo			    bwn_tab_noise_g2[i]);
5624203945Sweongyo
5625203945Sweongyo
5626203945Sweongyo	for (i = 0; i < N(bwn_tab_rotor); i++)
5627203945Sweongyo		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ROTOR, i,
5628203945Sweongyo		    bwn_tab_rotor[i]);
5629203945Sweongyo
5630203945Sweongyo	/* XXX support PHY-A??? */
5631203945Sweongyo	if (phy->rev >= 6) {
5632203945Sweongyo		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5633203945Sweongyo		    BWN_PHY_ENCORE_EN)
5634203945Sweongyo			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5635203945Sweongyo		else
5636203945Sweongyo			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5637203945Sweongyo	} else
5638203945Sweongyo		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5639203945Sweongyo
5640203945Sweongyo	for (i = 0; i < N(bwn_tab_retard); i++)
5641203945Sweongyo		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ADVRETARD, i,
5642203945Sweongyo		    bwn_tab_retard[i]);
5643203945Sweongyo
5644203945Sweongyo	if (phy->rev == 1) {
5645203945Sweongyo		for (i = 0; i < 16; i++)
5646203945Sweongyo			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1,
5647203945Sweongyo			    i, 0x0020);
5648203945Sweongyo	} else {
5649203945Sweongyo		for (i = 0; i < 32; i++)
5650203945Sweongyo			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5651203945Sweongyo	}
5652203945Sweongyo
5653203945Sweongyo	bwn_wa_agc(mac);
5654203945Sweongyo}
5655203945Sweongyo
5656203945Sweongyostatic void
5657203945Sweongyobwn_wa_grev26789(struct bwn_mac *mac)
5658203945Sweongyo{
5659203945Sweongyo	struct bwn_phy *phy = &mac->mac_phy;
5660203945Sweongyo	int i;
5661203945Sweongyo	static const uint16_t bwn_tab_sigmasqr2[] = BWN_TAB_SIGMASQR2;
5662203945Sweongyo	uint16_t ofdmrev;
5663203945Sweongyo
5664203945Sweongyo	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5665203945Sweongyo
5666203945Sweongyo	bwn_gtab_write(mac, BWN_GTAB_ORIGTR, 0, 0xc480);
5667203945Sweongyo
5668203945Sweongyo	/* init CRSTHRES and ANTDWELL */
5669203945Sweongyo	if (phy->rev == 1)
5670203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5671203945Sweongyo	else if (phy->rev == 2) {
5672203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5673203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5674203945Sweongyo		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5675203945Sweongyo	} else {
5676203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5677203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5678203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5679203945Sweongyo		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5680203945Sweongyo	}
5681203945Sweongyo
5682203945Sweongyo	for (i = 0; i < 64; i++)
5683203945Sweongyo		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_RSSI, i, i);
5684203945Sweongyo
5685203945Sweongyo	/* XXX support PHY-A??? */
5686203945Sweongyo	if (phy->rev == 1)
5687203945Sweongyo		for (i = 0; i < N(bwn_tab_noise_g1); i++)
5688203945Sweongyo			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5689203945Sweongyo			    bwn_tab_noise_g1[i]);
5690203945Sweongyo	else
5691203945Sweongyo		for (i = 0; i < N(bwn_tab_noise_g2); i++)
5692203945Sweongyo			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5693203945Sweongyo			    bwn_tab_noise_g2[i]);
5694203945Sweongyo
5695203945Sweongyo	/* XXX support PHY-A??? */
5696203945Sweongyo	if (phy->rev >= 6) {
5697203945Sweongyo		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5698203945Sweongyo		    BWN_PHY_ENCORE_EN)
5699203945Sweongyo			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5700203945Sweongyo		else
5701203945Sweongyo			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5702203945Sweongyo	} else
5703203945Sweongyo		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5704203945Sweongyo
5705203945Sweongyo	for (i = 0; i < N(bwn_tab_sigmasqr2); i++)
5706203945Sweongyo		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_MINSIGSQ, i,
5707203945Sweongyo		    bwn_tab_sigmasqr2[i]);
5708203945Sweongyo
5709203945Sweongyo	if (phy->rev == 1) {
5710203945Sweongyo		for (i = 0; i < 16; i++)
5711203945Sweongyo			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1, i,
5712203945Sweongyo			    0x0020);
5713203945Sweongyo	} else {
5714203945Sweongyo		for (i = 0; i < 32; i++)
5715203945Sweongyo			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5716203945Sweongyo	}
5717203945Sweongyo
5718203945Sweongyo	bwn_wa_agc(mac);
5719203945Sweongyo
5720203945Sweongyo	ofdmrev = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM) & BWN_PHYVER_VERSION;
5721203945Sweongyo	if (ofdmrev > 2) {
5722203945Sweongyo		if (phy->type == BWN_PHYTYPE_A)
5723203945Sweongyo			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1808);
5724203945Sweongyo		else
5725203945Sweongyo			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1000);
5726203945Sweongyo	} else {
5727203945Sweongyo		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 3, 0x1044);
5728203945Sweongyo		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 4, 0x7201);
5729203945Sweongyo		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 6, 0x0040);
5730203945Sweongyo	}
5731203945Sweongyo
5732203945Sweongyo	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 2, 15);
5733203945Sweongyo	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 3, 20);
5734203945Sweongyo}
5735203945Sweongyo
5736203945Sweongyostatic void
5737203945Sweongyobwn_wa_init(struct bwn_mac *mac)
5738203945Sweongyo{
5739203945Sweongyo	struct bwn_phy *phy = &mac->mac_phy;
5740204922Sweongyo	struct bwn_softc *sc = mac->mac_sc;
5741203945Sweongyo
5742203945Sweongyo	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5743203945Sweongyo
5744203945Sweongyo	switch (phy->rev) {
5745203945Sweongyo	case 1:
5746203945Sweongyo		bwn_wa_grev1(mac);
5747203945Sweongyo		break;
5748203945Sweongyo	case 2:
5749203945Sweongyo	case 6:
5750203945Sweongyo	case 7:
5751203945Sweongyo	case 8:
5752203945Sweongyo	case 9:
5753203945Sweongyo		bwn_wa_grev26789(mac);
5754203945Sweongyo		break;
5755203945Sweongyo	default:
5756203945Sweongyo		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5757203945Sweongyo	}
5758203945Sweongyo
5759204922Sweongyo	if (siba_get_pci_subvendor(sc->sc_dev) != SIBA_BOARDVENDOR_BCM ||
5760204922Sweongyo	    siba_get_pci_subdevice(sc->sc_dev) != SIBA_BOARD_BU4306 ||
5761204922Sweongyo	    siba_get_pci_revid(sc->sc_dev) != 0x17) {
5762203945Sweongyo		if (phy->rev < 2) {
5763203945Sweongyo			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 1,
5764203945Sweongyo			    0x0002);
5765203945Sweongyo			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 2,
5766203945Sweongyo			    0x0001);
5767203945Sweongyo		} else {
5768203945Sweongyo			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 1, 0x0002);
5769203945Sweongyo			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 2, 0x0001);
5770204922Sweongyo			if ((siba_sprom_get_bf_lo(sc->sc_dev) &
5771204922Sweongyo			     BWN_BFL_EXTLNA) &&
5772203945Sweongyo			    (phy->rev >= 7)) {
5773203945Sweongyo				BWN_PHY_MASK(mac, BWN_PHY_EXTG(0x11), 0xf7ff);
5774203945Sweongyo				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5775203945Sweongyo				    0x0020, 0x0001);
5776203945Sweongyo				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5777203945Sweongyo				    0x0021, 0x0001);
5778203945Sweongyo				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5779203945Sweongyo				    0x0022, 0x0001);
5780203945Sweongyo				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5781203945Sweongyo				    0x0023, 0x0000);
5782203945Sweongyo				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5783203945Sweongyo				    0x0000, 0x0000);
5784203945Sweongyo				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5785203945Sweongyo				    0x0003, 0x0002);
5786203945Sweongyo			}
5787203945Sweongyo		}
5788203945Sweongyo	}
5789204922Sweongyo	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM) {
5790203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, 0x3120);
5791203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, 0xc480);
5792203945Sweongyo	}
5793203945Sweongyo
5794203945Sweongyo	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 0, 0);
5795203945Sweongyo	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 1, 0);
5796203945Sweongyo}
5797203945Sweongyo
5798203945Sweongyostatic void
5799203945Sweongyobwn_ofdmtab_write_2(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5800203945Sweongyo    uint16_t value)
5801203945Sweongyo{
5802203945Sweongyo	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5803203945Sweongyo	uint16_t addr;
5804203945Sweongyo
5805203945Sweongyo	addr = table + offset;
5806203945Sweongyo	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5807203945Sweongyo	    (addr - 1 != pg->pg_ofdmtab_addr)) {
5808203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5809203945Sweongyo		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5810203945Sweongyo	}
5811203945Sweongyo	pg->pg_ofdmtab_addr = addr;
5812203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5813203945Sweongyo}
5814203945Sweongyo
5815203945Sweongyostatic void
5816203945Sweongyobwn_ofdmtab_write_4(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5817203945Sweongyo    uint32_t value)
5818203945Sweongyo{
5819203945Sweongyo	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5820203945Sweongyo	uint16_t addr;
5821203945Sweongyo
5822203945Sweongyo	addr = table + offset;
5823203945Sweongyo	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5824203945Sweongyo	    (addr - 1 != pg->pg_ofdmtab_addr)) {
5825203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5826203945Sweongyo		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5827203945Sweongyo	}
5828203945Sweongyo	pg->pg_ofdmtab_addr = addr;
5829203945Sweongyo
5830203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5831203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEQ, (value >> 16));
5832203945Sweongyo}
5833203945Sweongyo
5834203945Sweongyostatic void
5835203945Sweongyobwn_gtab_write(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5836203945Sweongyo    uint16_t value)
5837203945Sweongyo{
5838203945Sweongyo
5839203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, table + offset);
5840203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, value);
5841203945Sweongyo}
5842203945Sweongyo
5843203945Sweongyostatic void
5844203945Sweongyobwn_dummy_transmission(struct bwn_mac *mac, int ofdm, int paon)
5845203945Sweongyo{
5846203945Sweongyo	struct bwn_phy *phy = &mac->mac_phy;
5847204922Sweongyo	struct bwn_softc *sc = mac->mac_sc;
5848203945Sweongyo	unsigned int i, max_loop;
5849203945Sweongyo	uint16_t value;
5850203945Sweongyo	uint32_t buffer[5] = {
5851203945Sweongyo		0x00000000, 0x00d40000, 0x00000000, 0x01000000, 0x00000000
5852203945Sweongyo	};
5853203945Sweongyo
5854203945Sweongyo	if (ofdm) {
5855203945Sweongyo		max_loop = 0x1e;
5856203945Sweongyo		buffer[0] = 0x000201cc;
5857203945Sweongyo	} else {
5858203945Sweongyo		max_loop = 0xfa;
5859203945Sweongyo		buffer[0] = 0x000b846e;
5860203945Sweongyo	}
5861203945Sweongyo
5862204242Simp	BWN_ASSERT_LOCKED(mac->mac_sc);
5863203945Sweongyo
5864203945Sweongyo	for (i = 0; i < 5; i++)
5865203945Sweongyo		bwn_ram_write(mac, i * 4, buffer[i]);
5866203945Sweongyo
5867203945Sweongyo	BWN_WRITE_2(mac, 0x0568, 0x0000);
5868203945Sweongyo	BWN_WRITE_2(mac, 0x07c0,
5869204922Sweongyo	    (siba_get_revid(sc->sc_dev) < 11) ? 0x0000 : 0x0100);
5870203945Sweongyo	value = ((phy->type == BWN_PHYTYPE_A) ? 0x41 : 0x40);
5871203945Sweongyo	BWN_WRITE_2(mac, 0x050c, value);
5872203945Sweongyo	if (phy->type == BWN_PHYTYPE_LP)
5873203945Sweongyo		BWN_WRITE_2(mac, 0x0514, 0x1a02);
5874203945Sweongyo	BWN_WRITE_2(mac, 0x0508, 0x0000);
5875203945Sweongyo	BWN_WRITE_2(mac, 0x050a, 0x0000);
5876203945Sweongyo	BWN_WRITE_2(mac, 0x054c, 0x0000);
5877203945Sweongyo	BWN_WRITE_2(mac, 0x056a, 0x0014);
5878203945Sweongyo	BWN_WRITE_2(mac, 0x0568, 0x0826);
5879203945Sweongyo	BWN_WRITE_2(mac, 0x0500, 0x0000);
5880203945Sweongyo	if (phy->type == BWN_PHYTYPE_LP)
5881203945Sweongyo		BWN_WRITE_2(mac, 0x0502, 0x0050);
5882203945Sweongyo	else
5883203945Sweongyo		BWN_WRITE_2(mac, 0x0502, 0x0030);
5884203945Sweongyo
5885203945Sweongyo	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5886203945Sweongyo		BWN_RF_WRITE(mac, 0x0051, 0x0017);
5887203945Sweongyo	for (i = 0x00; i < max_loop; i++) {
5888203945Sweongyo		value = BWN_READ_2(mac, 0x050e);
5889203945Sweongyo		if (value & 0x0080)
5890203945Sweongyo			break;
5891203945Sweongyo		DELAY(10);
5892203945Sweongyo	}
5893203945Sweongyo	for (i = 0x00; i < 0x0a; i++) {
5894203945Sweongyo		value = BWN_READ_2(mac, 0x050e);
5895203945Sweongyo		if (value & 0x0400)
5896203945Sweongyo			break;
5897203945Sweongyo		DELAY(10);
5898203945Sweongyo	}
5899203945Sweongyo	for (i = 0x00; i < 0x19; i++) {
5900203945Sweongyo		value = BWN_READ_2(mac, 0x0690);
5901203945Sweongyo		if (!(value & 0x0100))
5902203945Sweongyo			break;
5903203945Sweongyo		DELAY(10);
5904203945Sweongyo	}
5905203945Sweongyo	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5906203945Sweongyo		BWN_RF_WRITE(mac, 0x0051, 0x0037);
5907203945Sweongyo}
5908203945Sweongyo
5909203945Sweongyostatic void
5910203945Sweongyobwn_ram_write(struct bwn_mac *mac, uint16_t offset, uint32_t val)
5911203945Sweongyo{
5912203945Sweongyo	uint32_t macctl;
5913203945Sweongyo
5914203945Sweongyo	KASSERT(offset % 4 == 0, ("%s:%d: fail", __func__, __LINE__));
5915203945Sweongyo
5916203945Sweongyo	macctl = BWN_READ_4(mac, BWN_MACCTL);
5917203945Sweongyo	if (macctl & BWN_MACCTL_BIGENDIAN)
5918203945Sweongyo		printf("TODO: need swap\n");
5919203945Sweongyo
5920203945Sweongyo	BWN_WRITE_4(mac, BWN_RAM_CONTROL, offset);
5921203945Sweongyo	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
5922203945Sweongyo	BWN_WRITE_4(mac, BWN_RAM_DATA, val);
5923203945Sweongyo}
5924203945Sweongyo
5925203945Sweongyostatic void
5926203945Sweongyobwn_lo_write(struct bwn_mac *mac, struct bwn_loctl *ctl)
5927203945Sweongyo{
5928203945Sweongyo	uint16_t value;
5929203945Sweongyo
5930204256Sweongyo	KASSERT(mac->mac_phy.type == BWN_PHYTYPE_G,
5931203945Sweongyo	    ("%s:%d: fail", __func__, __LINE__));
5932203945Sweongyo
5933203945Sweongyo	value = (uint8_t) (ctl->q);
5934203945Sweongyo	value |= ((uint8_t) (ctl->i)) << 8;
5935203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, value);
5936203945Sweongyo}
5937203945Sweongyo
5938203945Sweongyostatic uint16_t
5939203945Sweongyobwn_lo_calcfeed(struct bwn_mac *mac,
5940203945Sweongyo    uint16_t lna, uint16_t pga, uint16_t trsw_rx)
5941203945Sweongyo{
5942203945Sweongyo	struct bwn_phy *phy = &mac->mac_phy;
5943204922Sweongyo	struct bwn_softc *sc = mac->mac_sc;
5944203945Sweongyo	uint16_t rfover;
5945203945Sweongyo	uint16_t feedthrough;
5946203945Sweongyo
5947203945Sweongyo	if (phy->gmode) {
5948203945Sweongyo		lna <<= BWN_PHY_RFOVERVAL_LNA_SHIFT;
5949203945Sweongyo		pga <<= BWN_PHY_RFOVERVAL_PGA_SHIFT;
5950203945Sweongyo
5951203945Sweongyo		KASSERT((lna & ~BWN_PHY_RFOVERVAL_LNA) == 0,
5952203945Sweongyo		    ("%s:%d: fail", __func__, __LINE__));
5953203945Sweongyo		KASSERT((pga & ~BWN_PHY_RFOVERVAL_PGA) == 0,
5954203945Sweongyo		    ("%s:%d: fail", __func__, __LINE__));
5955203945Sweongyo
5956203945Sweongyo		trsw_rx &= (BWN_PHY_RFOVERVAL_TRSWRX | BWN_PHY_RFOVERVAL_BW);
5957203945Sweongyo
5958203945Sweongyo		rfover = BWN_PHY_RFOVERVAL_UNK | pga | lna | trsw_rx;
5959204922Sweongyo		if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA) &&
5960204922Sweongyo		    phy->rev > 6)
5961203945Sweongyo			rfover |= BWN_PHY_RFOVERVAL_EXTLNA;
5962203945Sweongyo
5963203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
5964203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5965203945Sweongyo		DELAY(10);
5966203945Sweongyo		rfover |= BWN_PHY_RFOVERVAL_BW_LBW;
5967203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5968203945Sweongyo		DELAY(10);
5969203945Sweongyo		rfover |= BWN_PHY_RFOVERVAL_BW_LPF;
5970203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5971203945Sweongyo		DELAY(10);
5972203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xf300);
5973203945Sweongyo	} else {
5974203945Sweongyo		pga |= BWN_PHY_PGACTL_UNKNOWN;
5975203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5976203945Sweongyo		DELAY(10);
5977203945Sweongyo		pga |= BWN_PHY_PGACTL_LOWBANDW;
5978203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5979203945Sweongyo		DELAY(10);
5980203945Sweongyo		pga |= BWN_PHY_PGACTL_LPF;
5981203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5982203945Sweongyo	}
5983203945Sweongyo	DELAY(21);
5984203945Sweongyo	feedthrough = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5985203945Sweongyo
5986203945Sweongyo	return (feedthrough);
5987203945Sweongyo}
5988203945Sweongyo
5989203945Sweongyostatic uint16_t
5990203945Sweongyobwn_lo_txctl_regtable(struct bwn_mac *mac,
5991203945Sweongyo    uint16_t *value, uint16_t *pad_mix_gain)
5992203945Sweongyo{
5993203945Sweongyo	struct bwn_phy *phy = &mac->mac_phy;
5994203945Sweongyo	uint16_t reg, v, padmix;
5995203945Sweongyo
5996203945Sweongyo	if (phy->type == BWN_PHYTYPE_B) {
5997203945Sweongyo		v = 0x30;
5998203945Sweongyo		if (phy->rf_rev <= 5) {
5999203945Sweongyo			reg = 0x43;
6000203945Sweongyo			padmix = 0;
6001203945Sweongyo		} else {
6002203945Sweongyo			reg = 0x52;
6003203945Sweongyo			padmix = 5;
6004203945Sweongyo		}
6005203945Sweongyo	} else {
6006203945Sweongyo		if (phy->rev >= 2 && phy->rf_rev == 8) {
6007203945Sweongyo			reg = 0x43;
6008203945Sweongyo			v = 0x10;
6009203945Sweongyo			padmix = 2;
6010203945Sweongyo		} else {
6011203945Sweongyo			reg = 0x52;
6012203945Sweongyo			v = 0x30;
6013203945Sweongyo			padmix = 5;
6014203945Sweongyo		}
6015203945Sweongyo	}
6016203945Sweongyo	if (value)
6017203945Sweongyo		*value = v;
6018203945Sweongyo	if (pad_mix_gain)
6019203945Sweongyo		*pad_mix_gain = padmix;
6020203945Sweongyo
6021203945Sweongyo	return (reg);
6022203945Sweongyo}
6023203945Sweongyo
6024203945Sweongyostatic void
6025203945Sweongyobwn_lo_measure_txctl_values(struct bwn_mac *mac)
6026203945Sweongyo{
6027203945Sweongyo	struct bwn_phy *phy = &mac->mac_phy;
6028203945Sweongyo	struct bwn_phy_g *pg = &phy->phy_g;
6029203945Sweongyo	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6030203945Sweongyo	uint16_t reg, mask;
6031203945Sweongyo	uint16_t trsw_rx, pga;
6032203945Sweongyo	uint16_t rf_pctl_reg;
6033203945Sweongyo
6034203945Sweongyo	static const uint8_t tx_bias_values[] = {
6035203945Sweongyo		0x09, 0x08, 0x0a, 0x01, 0x00,
6036203945Sweongyo		0x02, 0x05, 0x04, 0x06,
6037203945Sweongyo	};
6038203945Sweongyo	static const uint8_t tx_magn_values[] = {
6039203945Sweongyo		0x70, 0x40,
6040203945Sweongyo	};
6041203945Sweongyo
6042203945Sweongyo	if (!BWN_HAS_LOOPBACK(phy)) {
6043203945Sweongyo		rf_pctl_reg = 6;
6044203945Sweongyo		trsw_rx = 2;
6045203945Sweongyo		pga = 0;
6046203945Sweongyo	} else {
6047203945Sweongyo		int lb_gain;
6048203945Sweongyo
6049203945Sweongyo		trsw_rx = 0;
6050203945Sweongyo		lb_gain = pg->pg_max_lb_gain / 2;
6051203945Sweongyo		if (lb_gain > 10) {
6052203945Sweongyo			rf_pctl_reg = 0;
6053203945Sweongyo			pga = abs(10 - lb_gain) / 6;
6054203945Sweongyo			pga = MIN(MAX(pga, 0), 15);
6055203945Sweongyo		} else {
6056203945Sweongyo			int cmp_val;
6057203945Sweongyo			int tmp;
6058203945Sweongyo
6059203945Sweongyo			pga = 0;
6060203945Sweongyo			cmp_val = 0x24;
6061203945Sweongyo			if ((phy->rev >= 2) &&
6062203945Sweongyo			    (phy->rf_ver == 0x2050) && (phy->rf_rev == 8))
6063203945Sweongyo				cmp_val = 0x3c;
6064203945Sweongyo			tmp = lb_gain;
6065203945Sweongyo			if ((10 - lb_gain) < cmp_val)
6066203945Sweongyo				tmp = (10 - lb_gain);
6067203945Sweongyo			if (tmp < 0)
6068203945Sweongyo				tmp += 6;
6069203945Sweongyo			else
6070203945Sweongyo				tmp += 3;
6071203945Sweongyo			cmp_val /= 4;
6072203945Sweongyo			tmp /= 4;
6073203945Sweongyo			if (tmp >= cmp_val)
6074203945Sweongyo				rf_pctl_reg = cmp_val;
6075203945Sweongyo			else
6076203945Sweongyo				rf_pctl_reg = tmp;
6077203945Sweongyo		}
6078203945Sweongyo	}
6079203945Sweongyo	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rf_pctl_reg);
6080203945Sweongyo	bwn_phy_g_set_bbatt(mac, 2);
6081203945Sweongyo
6082203945Sweongyo	reg = bwn_lo_txctl_regtable(mac, &mask, NULL);
6083203945Sweongyo	mask = ~mask;
6084203945Sweongyo	BWN_RF_MASK(mac, reg, mask);
6085203945Sweongyo
6086203945Sweongyo	if (BWN_HAS_TXMAG(phy)) {
6087203945Sweongyo		int i, j;
6088203945Sweongyo		int feedthrough;
6089203945Sweongyo		int min_feedth = 0xffff;
6090203945Sweongyo		uint8_t tx_magn, tx_bias;
6091203945Sweongyo
6092203945Sweongyo		for (i = 0; i < N(tx_magn_values); i++) {
6093203945Sweongyo			tx_magn = tx_magn_values[i];
6094203945Sweongyo			BWN_RF_SETMASK(mac, 0x52, 0xff0f, tx_magn);
6095203945Sweongyo			for (j = 0; j < N(tx_bias_values); j++) {
6096203945Sweongyo				tx_bias = tx_bias_values[j];
6097203945Sweongyo				BWN_RF_SETMASK(mac, 0x52, 0xfff0, tx_bias);
6098203945Sweongyo				feedthrough = bwn_lo_calcfeed(mac, 0, pga,
6099203945Sweongyo				    trsw_rx);
6100203945Sweongyo				if (feedthrough < min_feedth) {
6101203945Sweongyo					lo->tx_bias = tx_bias;
6102203945Sweongyo					lo->tx_magn = tx_magn;
6103203945Sweongyo					min_feedth = feedthrough;
6104203945Sweongyo				}
6105203945Sweongyo				if (lo->tx_bias == 0)
6106203945Sweongyo					break;
6107203945Sweongyo			}
6108203945Sweongyo			BWN_RF_WRITE(mac, 0x52,
6109203945Sweongyo					  (BWN_RF_READ(mac, 0x52)
6110203945Sweongyo					   & 0xff00) | lo->tx_bias | lo->
6111203945Sweongyo					  tx_magn);
6112203945Sweongyo		}
6113203945Sweongyo	} else {
6114203945Sweongyo		lo->tx_magn = 0;
6115203945Sweongyo		lo->tx_bias = 0;
6116203945Sweongyo		BWN_RF_MASK(mac, 0x52, 0xfff0);
6117203945Sweongyo	}
6118203945Sweongyo
6119203945Sweongyo	BWN_GETTIME(lo->txctl_measured_time);
6120203945Sweongyo}
6121203945Sweongyo
6122203945Sweongyostatic void
6123203945Sweongyobwn_lo_get_powervector(struct bwn_mac *mac)
6124203945Sweongyo{
6125203945Sweongyo	struct bwn_phy *phy = &mac->mac_phy;
6126203945Sweongyo	struct bwn_phy_g *pg = &phy->phy_g;
6127203945Sweongyo	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6128203945Sweongyo	int i;
6129203945Sweongyo	uint64_t tmp;
6130203945Sweongyo	uint64_t power_vector = 0;
6131203945Sweongyo
6132203945Sweongyo	for (i = 0; i < 8; i += 2) {
6133203945Sweongyo		tmp = bwn_shm_read_2(mac, BWN_SHARED, 0x310 + i);
6134203945Sweongyo		power_vector |= (tmp << (i * 8));
6135203945Sweongyo		bwn_shm_write_2(mac, BWN_SHARED, 0x310 + i, 0);
6136203945Sweongyo	}
6137203945Sweongyo	if (power_vector)
6138203945Sweongyo		lo->power_vector = power_vector;
6139203945Sweongyo
6140203945Sweongyo	BWN_GETTIME(lo->pwr_vec_read_time);
6141203945Sweongyo}
6142203945Sweongyo
6143203945Sweongyostatic void
6144203945Sweongyobwn_lo_measure_gain_values(struct bwn_mac *mac, int16_t max_rx_gain,
6145203945Sweongyo    int use_trsw_rx)
6146203945Sweongyo{
6147203945Sweongyo	struct bwn_phy *phy = &mac->mac_phy;
6148203945Sweongyo	struct bwn_phy_g *pg = &phy->phy_g;
6149203945Sweongyo	uint16_t tmp;
6150203945Sweongyo
6151203945Sweongyo	if (max_rx_gain < 0)
6152203945Sweongyo		max_rx_gain = 0;
6153203945Sweongyo
6154203945Sweongyo	if (BWN_HAS_LOOPBACK(phy)) {
6155203945Sweongyo		int trsw_rx = 0;
6156203945Sweongyo		int trsw_rx_gain;
6157203945Sweongyo
6158203945Sweongyo		if (use_trsw_rx) {
6159203945Sweongyo			trsw_rx_gain = pg->pg_trsw_rx_gain / 2;
6160203945Sweongyo			if (max_rx_gain >= trsw_rx_gain) {
6161203945Sweongyo				trsw_rx_gain = max_rx_gain - trsw_rx_gain;
6162203945Sweongyo				trsw_rx = 0x20;
6163203945Sweongyo			}
6164203945Sweongyo		} else
6165203945Sweongyo			trsw_rx_gain = max_rx_gain;
6166203945Sweongyo		if (trsw_rx_gain < 9) {
6167203945Sweongyo			pg->pg_lna_lod_gain = 0;
6168203945Sweongyo		} else {
6169203945Sweongyo			pg->pg_lna_lod_gain = 1;
6170203945Sweongyo			trsw_rx_gain -= 8;
6171203945Sweongyo		}
6172203945Sweongyo		trsw_rx_gain = MIN(MAX(trsw_rx_gain, 0), 0x2d);
6173203945Sweongyo		pg->pg_pga_gain = trsw_rx_gain / 3;
6174203945Sweongyo		if (pg->pg_pga_gain >= 5) {
6175203945Sweongyo			pg->pg_pga_gain -= 5;
6176203945Sweongyo			pg->pg_lna_gain = 2;
6177203945Sweongyo		} else
6178203945Sweongyo			pg->pg_lna_gain = 0;
6179203945Sweongyo	} else {
6180203945Sweongyo		pg->pg_lna_gain = 0;
6181203945Sweongyo		pg->pg_trsw_rx_gain = 0x20;
6182203945Sweongyo		if (max_rx_gain >= 0x14) {
6183203945Sweongyo			pg->pg_lna_lod_gain = 1;
6184203945Sweongyo			pg->pg_pga_gain = 2;
6185203945Sweongyo		} else if (max_rx_gain >= 0x12) {
6186203945Sweongyo			pg->pg_lna_lod_gain = 1;
6187203945Sweongyo			pg->pg_pga_gain = 1;
6188203945Sweongyo		} else if (max_rx_gain >= 0xf) {
6189203945Sweongyo			pg->pg_lna_lod_gain = 1;
6190203945Sweongyo			pg->pg_pga_gain = 0;
6191203945Sweongyo		} else {
6192203945Sweongyo			pg->pg_lna_lod_gain = 0;
6193203945Sweongyo			pg->pg_pga_gain = 0;
6194203945Sweongyo		}
6195203945Sweongyo	}
6196203945Sweongyo
6197203945Sweongyo	tmp = BWN_RF_READ(mac, 0x7a);
6198203945Sweongyo	if (pg->pg_lna_lod_gain == 0)
6199203945Sweongyo		tmp &= ~0x0008;
6200203945Sweongyo	else
6201203945Sweongyo		tmp |= 0x0008;
6202203945Sweongyo	BWN_RF_WRITE(mac, 0x7a, tmp);
6203203945Sweongyo}
6204203945Sweongyo
6205203945Sweongyostatic void
6206203945Sweongyobwn_lo_save(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6207203945Sweongyo{
6208203945Sweongyo	struct bwn_phy *phy = &mac->mac_phy;
6209203945Sweongyo	struct bwn_phy_g *pg = &phy->phy_g;
6210204922Sweongyo	struct bwn_softc *sc = mac->mac_sc;
6211203945Sweongyo	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6212203945Sweongyo	struct timespec ts;
6213203945Sweongyo	uint16_t tmp;
6214203945Sweongyo
6215203945Sweongyo	if (bwn_has_hwpctl(mac)) {
6216203945Sweongyo		sav->phy_lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
6217203945Sweongyo		sav->phy_extg = BWN_PHY_READ(mac, BWN_PHY_EXTG(0x01));
6218203945Sweongyo		sav->phy_dacctl_hwpctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6219203945Sweongyo		sav->phy_cck4 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x14));
6220203945Sweongyo		sav->phy_hpwr_tssictl = BWN_PHY_READ(mac, BWN_PHY_HPWR_TSSICTL);
6221203945Sweongyo
6222203945Sweongyo		BWN_PHY_SET(mac, BWN_PHY_HPWR_TSSICTL, 0x100);
6223203945Sweongyo		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x40);
6224203945Sweongyo		BWN_PHY_SET(mac, BWN_PHY_DACCTL, 0x40);
6225203945Sweongyo		BWN_PHY_SET(mac, BWN_PHY_CCK(0x14), 0x200);
6226203945Sweongyo	}
6227203945Sweongyo	if (phy->type == BWN_PHYTYPE_B &&
6228203945Sweongyo	    phy->rf_ver == 0x2050 && phy->rf_rev < 6) {
6229203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x16), 0x410);
6230203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x17), 0x820);
6231203945Sweongyo	}
6232203945Sweongyo	if (phy->rev >= 2) {
6233203945Sweongyo		sav->phy_analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
6234203945Sweongyo		sav->phy_analogoverval =
6235203945Sweongyo		    BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
6236203945Sweongyo		sav->phy_rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
6237203945Sweongyo		sav->phy_rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
6238203945Sweongyo		sav->phy_classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
6239203945Sweongyo		sav->phy_cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x3e));
6240203945Sweongyo		sav->phy_crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
6241203945Sweongyo
6242203945Sweongyo		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
6243203945Sweongyo		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
6244203945Sweongyo		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
6245203945Sweongyo		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
6246203945Sweongyo		if (phy->type == BWN_PHYTYPE_G) {
6247203945Sweongyo			if ((phy->rev >= 7) &&
6248204922Sweongyo			    (siba_sprom_get_bf_lo(sc->sc_dev) &
6249204922Sweongyo			     BWN_BFL_EXTLNA)) {
6250203945Sweongyo				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x933);
6251203945Sweongyo			} else {
6252203945Sweongyo				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x133);
6253203945Sweongyo			}
6254203945Sweongyo		} else {
6255203945Sweongyo			BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
6256203945Sweongyo		}
6257203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), 0);
6258203945Sweongyo	}
6259203945Sweongyo	sav->reg0 = BWN_READ_2(mac, 0x3f4);
6260203945Sweongyo	sav->reg1 = BWN_READ_2(mac, 0x3e2);
6261203945Sweongyo	sav->rf0 = BWN_RF_READ(mac, 0x43);
6262203945Sweongyo	sav->rf1 = BWN_RF_READ(mac, 0x7a);
6263203945Sweongyo	sav->phy_pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
6264203945Sweongyo	sav->phy_cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2a));
6265203945Sweongyo	sav->phy_syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
6266203945Sweongyo	sav->phy_dacctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6267203945Sweongyo
6268203945Sweongyo	if (!BWN_HAS_TXMAG(phy)) {
6269203945Sweongyo		sav->rf2 = BWN_RF_READ(mac, 0x52);
6270203945Sweongyo		sav->rf2 &= 0x00f0;
6271203945Sweongyo	}
6272203945Sweongyo	if (phy->type == BWN_PHYTYPE_B) {
6273203945Sweongyo		sav->phy_cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
6274203945Sweongyo		sav->phy_cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x06));
6275203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0x00ff);
6276203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), 0x3f3f);
6277203945Sweongyo	} else {
6278203945Sweongyo		BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2)
6279203945Sweongyo			    | 0x8000);
6280203945Sweongyo	}
6281203945Sweongyo	BWN_WRITE_2(mac, 0x3f4, BWN_READ_2(mac, 0x3f4)
6282203945Sweongyo		    & 0xf000);
6283203945Sweongyo
6284203945Sweongyo	tmp =
6285203945Sweongyo	    (phy->type == BWN_PHYTYPE_G) ? BWN_PHY_LO_MASK : BWN_PHY_CCK(0x2e);
6286203945Sweongyo	BWN_PHY_WRITE(mac, tmp, 0x007f);
6287203945Sweongyo
6288203945Sweongyo	tmp = sav->phy_syncctl;
6289203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, tmp & 0xff7f);
6290203945Sweongyo	tmp = sav->rf1;
6291203945Sweongyo	BWN_RF_WRITE(mac, 0x007a, tmp & 0xfff0);
6292203945Sweongyo
6293203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), 0x8a3);
6294203945Sweongyo	if (phy->type == BWN_PHYTYPE_G ||
6295203945Sweongyo	    (phy->type == BWN_PHYTYPE_B &&
6296203945Sweongyo	     phy->rf_ver == 0x2050 && phy->rf_rev >= 6)) {
6297203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1003);
6298203945Sweongyo	} else
6299203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x0802);
6300203945Sweongyo	if (phy->rev >= 2)
6301203945Sweongyo		bwn_dummy_transmission(mac, 0, 1);
6302203945Sweongyo	bwn_phy_g_switch_chan(mac, 6, 0);
6303203945Sweongyo	BWN_RF_READ(mac, 0x51);
6304203945Sweongyo	if (phy->type == BWN_PHYTYPE_G)
6305203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0);
6306203945Sweongyo
6307203945Sweongyo	nanouptime(&ts);
6308203945Sweongyo	if (time_before(lo->txctl_measured_time,
6309203945Sweongyo	    (ts.tv_nsec / 1000000 + ts.tv_sec * 1000) - BWN_LO_TXCTL_EXPIRE))
6310203945Sweongyo		bwn_lo_measure_txctl_values(mac);
6311203945Sweongyo
6312203945Sweongyo	if (phy->type == BWN_PHYTYPE_G && phy->rev >= 3)
6313203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc078);
6314203945Sweongyo	else {
6315203945Sweongyo		if (phy->type == BWN_PHYTYPE_B)
6316203945Sweongyo			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6317203945Sweongyo		else
6318203945Sweongyo			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
6319203945Sweongyo	}
6320203945Sweongyo}
6321203945Sweongyo
6322203945Sweongyostatic void
6323203945Sweongyobwn_lo_restore(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6324203945Sweongyo{
6325203945Sweongyo	struct bwn_phy *phy = &mac->mac_phy;
6326203945Sweongyo	struct bwn_phy_g *pg = &phy->phy_g;
6327203945Sweongyo	uint16_t tmp;
6328203945Sweongyo
6329203945Sweongyo	if (phy->rev >= 2) {
6330203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
6331203945Sweongyo		tmp = (pg->pg_pga_gain << 8);
6332203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa0);
6333203945Sweongyo		DELAY(5);
6334203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa2);
6335203945Sweongyo		DELAY(2);
6336203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa3);
6337203945Sweongyo	} else {
6338203945Sweongyo		tmp = (pg->pg_pga_gain | 0xefa0);
6339203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, tmp);
6340203945Sweongyo	}
6341203945Sweongyo	if (phy->type == BWN_PHYTYPE_G) {
6342203945Sweongyo		if (phy->rev >= 3)
6343203945Sweongyo			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0xc078);
6344203945Sweongyo		else
6345203945Sweongyo			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6346203945Sweongyo		if (phy->rev >= 2)
6347203945Sweongyo			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0202);
6348203945Sweongyo		else
6349203945Sweongyo			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0101);
6350203945Sweongyo	}
6351203945Sweongyo	BWN_WRITE_2(mac, 0x3f4, sav->reg0);
6352203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, sav->phy_pgactl);
6353203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), sav->phy_cck2);
6354203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, sav->phy_syncctl);
6355203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl);
6356203945Sweongyo	BWN_RF_WRITE(mac, 0x43, sav->rf0);
6357203945Sweongyo	BWN_RF_WRITE(mac, 0x7a, sav->rf1);
6358203945Sweongyo	if (!BWN_HAS_TXMAG(phy)) {
6359203945Sweongyo		tmp = sav->rf2;
6360203945Sweongyo		BWN_RF_SETMASK(mac, 0x52, 0xff0f, tmp);
6361203945Sweongyo	}
6362203945Sweongyo	BWN_WRITE_2(mac, 0x3e2, sav->reg1);
6363203945Sweongyo	if (phy->type == BWN_PHYTYPE_B &&
6364203945Sweongyo	    phy->rf_ver == 0x2050 && phy->rf_rev <= 5) {
6365203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), sav->phy_cck0);
6366203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), sav->phy_cck1);
6367203945Sweongyo	}
6368203945Sweongyo	if (phy->rev >= 2) {
6369203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, sav->phy_analogover);
6370203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
6371203945Sweongyo			      sav->phy_analogoverval);
6372203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, sav->phy_classctl);
6373203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, sav->phy_rfover);
6374203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, sav->phy_rfoverval);
6375203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), sav->phy_cck3);
6376203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, sav->phy_crs0);
6377203945Sweongyo	}
6378203945Sweongyo	if (bwn_has_hwpctl(mac)) {
6379203945Sweongyo		tmp = (sav->phy_lomask & 0xbfff);
6380203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, tmp);
6381203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x01), sav->phy_extg);
6382203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl_hwpctl);
6383203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x14), sav->phy_cck4);
6384203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_HPWR_TSSICTL, sav->phy_hpwr_tssictl);
6385203945Sweongyo	}
6386203945Sweongyo	bwn_phy_g_switch_chan(mac, sav->old_channel, 1);
6387203945Sweongyo}
6388203945Sweongyo
6389203945Sweongyostatic int
6390203945Sweongyobwn_lo_probe_loctl(struct bwn_mac *mac,
6391203945Sweongyo    struct bwn_loctl *probe, struct bwn_lo_g_sm *d)
6392203945Sweongyo{
6393203945Sweongyo	struct bwn_phy *phy = &mac->mac_phy;
6394203945Sweongyo	struct bwn_phy_g *pg = &phy->phy_g;
6395203945Sweongyo	struct bwn_loctl orig, test;
6396203945Sweongyo	struct bwn_loctl prev = { -100, -100 };
6397203945Sweongyo	static const struct bwn_loctl modifiers[] = {
6398203945Sweongyo		{  1,  1,}, {  1,  0,}, {  1, -1,}, {  0, -1,},
6399203945Sweongyo		{ -1, -1,}, { -1,  0,}, { -1,  1,}, {  0,  1,}
6400203945Sweongyo	};
6401203945Sweongyo	int begin, end, lower = 0, i;
6402203945Sweongyo	uint16_t feedth;
6403203945Sweongyo
6404203945Sweongyo	if (d->curstate == 0) {
6405203945Sweongyo		begin = 1;
6406203945Sweongyo		end = 8;
6407203945Sweongyo	} else if (d->curstate % 2 == 0) {
6408203945Sweongyo		begin = d->curstate - 1;
6409203945Sweongyo		end = d->curstate + 1;
6410203945Sweongyo	} else {
6411203945Sweongyo		begin = d->curstate - 2;
6412203945Sweongyo		end = d->curstate + 2;
6413203945Sweongyo	}
6414203945Sweongyo	if (begin < 1)
6415203945Sweongyo		begin += 8;
6416203945Sweongyo	if (end > 8)
6417203945Sweongyo		end -= 8;
6418203945Sweongyo
6419203945Sweongyo	memcpy(&orig, probe, sizeof(struct bwn_loctl));
6420203945Sweongyo	i = begin;
6421203945Sweongyo	d->curstate = i;
6422203945Sweongyo	while (1) {
6423203945Sweongyo		KASSERT(i >= 1 && i <= 8, ("%s:%d: fail", __func__, __LINE__));
6424203945Sweongyo		memcpy(&test, &orig, sizeof(struct bwn_loctl));
6425203945Sweongyo		test.i += modifiers[i - 1].i * d->multipler;
6426203945Sweongyo		test.q += modifiers[i - 1].q * d->multipler;
6427203945Sweongyo		if ((test.i != prev.i || test.q != prev.q) &&
6428203945Sweongyo		    (abs(test.i) <= 16 && abs(test.q) <= 16)) {
6429203945Sweongyo			bwn_lo_write(mac, &test);
6430203945Sweongyo			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6431203945Sweongyo			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6432203945Sweongyo			if (feedth < d->feedth) {
6433203945Sweongyo				memcpy(probe, &test,
6434203945Sweongyo				    sizeof(struct bwn_loctl));
6435203945Sweongyo				lower = 1;
6436203945Sweongyo				d->feedth = feedth;
6437203945Sweongyo				if (d->nmeasure < 2 && !BWN_HAS_LOOPBACK(phy))
6438203945Sweongyo					break;
6439203945Sweongyo			}
6440203945Sweongyo		}
6441203945Sweongyo		memcpy(&prev, &test, sizeof(prev));
6442203945Sweongyo		if (i == end)
6443203945Sweongyo			break;
6444203945Sweongyo		if (i == 8)
6445203945Sweongyo			i = 1;
6446203945Sweongyo		else
6447203945Sweongyo			i++;
6448203945Sweongyo		d->curstate = i;
6449203945Sweongyo	}
6450203945Sweongyo
6451203945Sweongyo	return (lower);
6452203945Sweongyo}
6453203945Sweongyo
6454203945Sweongyostatic void
6455203945Sweongyobwn_lo_probe_sm(struct bwn_mac *mac, struct bwn_loctl *loctl, int *rxgain)
6456203945Sweongyo{
6457203945Sweongyo	struct bwn_phy *phy = &mac->mac_phy;
6458203945Sweongyo	struct bwn_phy_g *pg = &phy->phy_g;
6459203945Sweongyo	struct bwn_lo_g_sm d;
6460203945Sweongyo	struct bwn_loctl probe;
6461203945Sweongyo	int lower, repeat, cnt = 0;
6462203945Sweongyo	uint16_t feedth;
6463203945Sweongyo
6464203945Sweongyo	d.nmeasure = 0;
6465203945Sweongyo	d.multipler = 1;
6466203945Sweongyo	if (BWN_HAS_LOOPBACK(phy))
6467203945Sweongyo		d.multipler = 3;
6468203945Sweongyo
6469203945Sweongyo	memcpy(&d.loctl, loctl, sizeof(struct bwn_loctl));
6470203945Sweongyo	repeat = (BWN_HAS_LOOPBACK(phy)) ? 4 : 1;
6471203945Sweongyo
6472203945Sweongyo	do {
6473203945Sweongyo		bwn_lo_write(mac, &d.loctl);
6474203945Sweongyo		feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6475203945Sweongyo		    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6476203945Sweongyo		if (feedth < 0x258) {
6477203945Sweongyo			if (feedth >= 0x12c)
6478203945Sweongyo				*rxgain += 6;
6479203945Sweongyo			else
6480203945Sweongyo				*rxgain += 3;
6481203945Sweongyo			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6482203945Sweongyo			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6483203945Sweongyo		}
6484203945Sweongyo		d.feedth = feedth;
6485203945Sweongyo		d.curstate = 0;
6486203945Sweongyo		do {
6487203945Sweongyo			KASSERT(d.curstate >= 0 && d.curstate <= 8,
6488203945Sweongyo			    ("%s:%d: fail", __func__, __LINE__));
6489203945Sweongyo			memcpy(&probe, &d.loctl,
6490203945Sweongyo			       sizeof(struct bwn_loctl));
6491203945Sweongyo			lower = bwn_lo_probe_loctl(mac, &probe, &d);
6492203945Sweongyo			if (!lower)
6493203945Sweongyo				break;
6494203945Sweongyo			if ((probe.i == d.loctl.i) && (probe.q == d.loctl.q))
6495203945Sweongyo				break;
6496203945Sweongyo			memcpy(&d.loctl, &probe, sizeof(struct bwn_loctl));
6497203945Sweongyo			d.nmeasure++;
6498203945Sweongyo		} while (d.nmeasure < 24);
6499203945Sweongyo		memcpy(loctl, &d.loctl, sizeof(struct bwn_loctl));
6500203945Sweongyo
6501203945Sweongyo		if (BWN_HAS_LOOPBACK(phy)) {
6502203945Sweongyo			if (d.feedth > 0x1194)
6503203945Sweongyo				*rxgain -= 6;
6504203945Sweongyo			else if (d.feedth < 0x5dc)
6505203945Sweongyo				*rxgain += 3;
6506203945Sweongyo			if (cnt == 0) {
6507203945Sweongyo				if (d.feedth <= 0x5dc) {
6508203945Sweongyo					d.multipler = 1;
6509203945Sweongyo					cnt++;
6510203945Sweongyo				} else
6511203945Sweongyo					d.multipler = 2;
6512203945Sweongyo			} else if (cnt == 2)
6513203945Sweongyo				d.multipler = 1;
6514203945Sweongyo		}
6515203945Sweongyo		bwn_lo_measure_gain_values(mac, *rxgain, BWN_HAS_LOOPBACK(phy));
6516203945Sweongyo	} while (++cnt < repeat);
6517203945Sweongyo}
6518203945Sweongyo
6519203945Sweongyostatic struct bwn_lo_calib *
6520203945Sweongyobwn_lo_calibset(struct bwn_mac *mac,
6521203945Sweongyo    const struct bwn_bbatt *bbatt, const struct bwn_rfatt *rfatt)
6522203945Sweongyo{
6523203945Sweongyo	struct bwn_phy *phy = &mac->mac_phy;
6524203945Sweongyo	struct bwn_phy_g *pg = &phy->phy_g;
6525203945Sweongyo	struct bwn_loctl loctl = { 0, 0 };
6526203945Sweongyo	struct bwn_lo_calib *cal;
6527204242Simp	struct bwn_lo_g_value sval = { 0 };
6528203945Sweongyo	int rxgain;
6529203945Sweongyo	uint16_t pad, reg, value;
6530203945Sweongyo
6531203945Sweongyo	sval.old_channel = phy->chan;
6532203945Sweongyo	bwn_mac_suspend(mac);
6533203945Sweongyo	bwn_lo_save(mac, &sval);
6534203945Sweongyo
6535203945Sweongyo	reg = bwn_lo_txctl_regtable(mac, &value, &pad);
6536203945Sweongyo	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rfatt->att);
6537203945Sweongyo	BWN_RF_SETMASK(mac, reg, ~value, (rfatt->padmix ? value :0));
6538203945Sweongyo
6539203945Sweongyo	rxgain = (rfatt->att * 2) + (bbatt->att / 2);
6540203945Sweongyo	if (rfatt->padmix)
6541203945Sweongyo		rxgain -= pad;
6542203945Sweongyo	if (BWN_HAS_LOOPBACK(phy))
6543203945Sweongyo		rxgain += pg->pg_max_lb_gain;
6544203945Sweongyo	bwn_lo_measure_gain_values(mac, rxgain, BWN_HAS_LOOPBACK(phy));
6545203945Sweongyo	bwn_phy_g_set_bbatt(mac, bbatt->att);
6546203945Sweongyo	bwn_lo_probe_sm(mac, &loctl, &rxgain);
6547203945Sweongyo
6548203945Sweongyo	bwn_lo_restore(mac, &sval);
6549203945Sweongyo	bwn_mac_enable(mac);
6550203945Sweongyo
6551203945Sweongyo	cal = malloc(sizeof(*cal), M_DEVBUF, M_NOWAIT | M_ZERO);
6552203945Sweongyo	if (!cal) {
6553203945Sweongyo		device_printf(mac->mac_sc->sc_dev, "out of memory\n");
6554203945Sweongyo		return (NULL);
6555203945Sweongyo	}
6556203945Sweongyo	memcpy(&cal->bbatt, bbatt, sizeof(*bbatt));
6557203945Sweongyo	memcpy(&cal->rfatt, rfatt, sizeof(*rfatt));
6558203945Sweongyo	memcpy(&cal->ctl, &loctl, sizeof(loctl));
6559203945Sweongyo
6560203945Sweongyo	BWN_GETTIME(cal->calib_time);
6561203945Sweongyo
6562203945Sweongyo	return (cal);
6563203945Sweongyo}
6564203945Sweongyo
6565203945Sweongyostatic struct bwn_lo_calib *
6566203945Sweongyobwn_lo_get_calib(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
6567203945Sweongyo    const struct bwn_rfatt *rfatt)
6568203945Sweongyo{
6569203945Sweongyo	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
6570203945Sweongyo	struct bwn_lo_calib *c;
6571203945Sweongyo
6572203945Sweongyo	TAILQ_FOREACH(c, &lo->calib_list, list) {
6573203945Sweongyo		if (!BWN_BBATTCMP(&c->bbatt, bbatt))
6574203945Sweongyo			continue;
6575203945Sweongyo		if (!BWN_RFATTCMP(&c->rfatt, rfatt))
6576203945Sweongyo			continue;
6577203945Sweongyo		return (c);
6578203945Sweongyo	}
6579203945Sweongyo
6580203945Sweongyo	c = bwn_lo_calibset(mac, bbatt, rfatt);
6581203945Sweongyo	if (!c)
6582203945Sweongyo		return (NULL);
6583203945Sweongyo	TAILQ_INSERT_TAIL(&lo->calib_list, c, list);
6584203945Sweongyo
6585203945Sweongyo	return (c);
6586203945Sweongyo}
6587203945Sweongyo
6588203945Sweongyostatic void
6589203945Sweongyobwn_phy_g_dc_lookup_init(struct bwn_mac *mac, uint8_t update)
6590203945Sweongyo{
6591203945Sweongyo	struct bwn_phy *phy = &mac->mac_phy;
6592203945Sweongyo	struct bwn_phy_g *pg = &phy->phy_g;
6593203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
6594203945Sweongyo	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6595203945Sweongyo	const struct bwn_rfatt *rfatt;
6596203945Sweongyo	const struct bwn_bbatt *bbatt;
6597203945Sweongyo	uint64_t pvector;
6598203945Sweongyo	int i;
6599203945Sweongyo	int rf_offset, bb_offset;
6600203945Sweongyo	uint8_t changed = 0;
6601203945Sweongyo
6602203945Sweongyo	KASSERT(BWN_DC_LT_SIZE == 32, ("%s:%d: fail", __func__, __LINE__));
6603203945Sweongyo	KASSERT(lo->rfatt.len * lo->bbatt.len <= 64,
6604203945Sweongyo	    ("%s:%d: fail", __func__, __LINE__));
6605203945Sweongyo
6606203945Sweongyo	pvector = lo->power_vector;
6607203945Sweongyo	if (!update && !pvector)
6608203945Sweongyo		return;
6609203945Sweongyo
6610203945Sweongyo	bwn_mac_suspend(mac);
6611203945Sweongyo
6612203945Sweongyo	for (i = 0; i < BWN_DC_LT_SIZE * 2; i++) {
6613203945Sweongyo		struct bwn_lo_calib *cal;
6614203945Sweongyo		int idx;
6615203945Sweongyo		uint16_t val;
6616203945Sweongyo
6617203945Sweongyo		if (!update && !(pvector & (((uint64_t)1ULL) << i)))
6618203945Sweongyo			continue;
6619203945Sweongyo		bb_offset = i / lo->rfatt.len;
6620203945Sweongyo		rf_offset = i % lo->rfatt.len;
6621203945Sweongyo		bbatt = &(lo->bbatt.array[bb_offset]);
6622203945Sweongyo		rfatt = &(lo->rfatt.array[rf_offset]);
6623203945Sweongyo
6624203945Sweongyo		cal = bwn_lo_calibset(mac, bbatt, rfatt);
6625203945Sweongyo		if (!cal) {
6626203945Sweongyo			device_printf(sc->sc_dev, "LO: Could not "
6627203945Sweongyo			    "calibrate DC table entry\n");
6628203945Sweongyo			continue;
6629203945Sweongyo		}
6630203945Sweongyo		val = (uint8_t)(cal->ctl.q);
6631203945Sweongyo		val |= ((uint8_t)(cal->ctl.i)) << 4;
6632203945Sweongyo		free(cal, M_DEVBUF);
6633203945Sweongyo
6634203945Sweongyo		idx = i / 2;
6635203945Sweongyo		if (i % 2)
6636203945Sweongyo			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0x00ff)
6637203945Sweongyo			    | ((val & 0x00ff) << 8);
6638203945Sweongyo		else
6639203945Sweongyo			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0xff00)
6640203945Sweongyo			    | (val & 0x00ff);
6641203945Sweongyo		changed = 1;
6642203945Sweongyo	}
6643203945Sweongyo	if (changed) {
6644203945Sweongyo		for (i = 0; i < BWN_DC_LT_SIZE; i++)
6645203945Sweongyo			BWN_PHY_WRITE(mac, 0x3a0 + i, lo->dc_lt[i]);
6646203945Sweongyo	}
6647203945Sweongyo	bwn_mac_enable(mac);
6648203945Sweongyo}
6649203945Sweongyo
6650203945Sweongyostatic void
6651203945Sweongyobwn_lo_fixup_rfatt(struct bwn_rfatt *rf)
6652203945Sweongyo{
6653203945Sweongyo
6654203945Sweongyo	if (!rf->padmix)
6655203945Sweongyo		return;
6656203945Sweongyo	if ((rf->att != 1) && (rf->att != 2) && (rf->att != 3))
6657203945Sweongyo		rf->att = 4;
6658203945Sweongyo}
6659203945Sweongyo
6660203945Sweongyostatic void
6661203945Sweongyobwn_lo_g_adjust(struct bwn_mac *mac)
6662203945Sweongyo{
6663203945Sweongyo	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
6664203945Sweongyo	struct bwn_lo_calib *cal;
6665203945Sweongyo	struct bwn_rfatt rf;
6666203945Sweongyo
6667203945Sweongyo	memcpy(&rf, &pg->pg_rfatt, sizeof(rf));
6668203945Sweongyo	bwn_lo_fixup_rfatt(&rf);
6669203945Sweongyo
6670203945Sweongyo	cal = bwn_lo_get_calib(mac, &pg->pg_bbatt, &rf);
6671203945Sweongyo	if (!cal)
6672203945Sweongyo		return;
6673203945Sweongyo	bwn_lo_write(mac, &cal->ctl);
6674203945Sweongyo}
6675203945Sweongyo
6676203945Sweongyostatic void
6677203945Sweongyobwn_lo_g_init(struct bwn_mac *mac)
6678203945Sweongyo{
6679203945Sweongyo
6680203945Sweongyo	if (!bwn_has_hwpctl(mac))
6681203945Sweongyo		return;
6682203945Sweongyo
6683203945Sweongyo	bwn_lo_get_powervector(mac);
6684203945Sweongyo	bwn_phy_g_dc_lookup_init(mac, 1);
6685203945Sweongyo}
6686203945Sweongyo
6687203945Sweongyostatic void
6688203945Sweongyobwn_mac_suspend(struct bwn_mac *mac)
6689203945Sweongyo{
6690203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
6691203945Sweongyo	int i;
6692203945Sweongyo	uint32_t tmp;
6693203945Sweongyo
6694203945Sweongyo	KASSERT(mac->mac_suspended >= 0,
6695203945Sweongyo	    ("%s:%d: fail", __func__, __LINE__));
6696203945Sweongyo
6697203945Sweongyo	if (mac->mac_suspended == 0) {
6698203945Sweongyo		bwn_psctl(mac, BWN_PS_AWAKE);
6699203945Sweongyo		BWN_WRITE_4(mac, BWN_MACCTL,
6700203945Sweongyo			    BWN_READ_4(mac, BWN_MACCTL)
6701203945Sweongyo			    & ~BWN_MACCTL_ON);
6702203945Sweongyo		BWN_READ_4(mac, BWN_MACCTL);
6703203945Sweongyo		for (i = 35; i; i--) {
6704203945Sweongyo			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6705203945Sweongyo			if (tmp & BWN_INTR_MAC_SUSPENDED)
6706203945Sweongyo				goto out;
6707203945Sweongyo			DELAY(10);
6708203945Sweongyo		}
6709203945Sweongyo		for (i = 40; i; i--) {
6710203945Sweongyo			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6711203945Sweongyo			if (tmp & BWN_INTR_MAC_SUSPENDED)
6712203945Sweongyo				goto out;
6713203945Sweongyo			DELAY(1000);
6714203945Sweongyo		}
6715203945Sweongyo		device_printf(sc->sc_dev, "MAC suspend failed\n");
6716203945Sweongyo	}
6717203945Sweongyoout:
6718203945Sweongyo	mac->mac_suspended++;
6719203945Sweongyo}
6720203945Sweongyo
6721203945Sweongyostatic void
6722203945Sweongyobwn_mac_enable(struct bwn_mac *mac)
6723203945Sweongyo{
6724203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
6725203945Sweongyo	uint16_t state;
6726203945Sweongyo
6727203945Sweongyo	state = bwn_shm_read_2(mac, BWN_SHARED,
6728203945Sweongyo	    BWN_SHARED_UCODESTAT);
6729203945Sweongyo	if (state != BWN_SHARED_UCODESTAT_SUSPEND &&
6730203945Sweongyo	    state != BWN_SHARED_UCODESTAT_SLEEP)
6731203945Sweongyo		device_printf(sc->sc_dev, "warn: firmware state (%d)\n", state);
6732203945Sweongyo
6733203945Sweongyo	mac->mac_suspended--;
6734203945Sweongyo	KASSERT(mac->mac_suspended >= 0,
6735203945Sweongyo	    ("%s:%d: fail", __func__, __LINE__));
6736203945Sweongyo	if (mac->mac_suspended == 0) {
6737203945Sweongyo		BWN_WRITE_4(mac, BWN_MACCTL,
6738203945Sweongyo		    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_ON);
6739203945Sweongyo		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_MAC_SUSPENDED);
6740203945Sweongyo		BWN_READ_4(mac, BWN_MACCTL);
6741203945Sweongyo		BWN_READ_4(mac, BWN_INTR_REASON);
6742203945Sweongyo		bwn_psctl(mac, 0);
6743203945Sweongyo	}
6744203945Sweongyo}
6745203945Sweongyo
6746203945Sweongyostatic void
6747203945Sweongyobwn_psctl(struct bwn_mac *mac, uint32_t flags)
6748203945Sweongyo{
6749204922Sweongyo	struct bwn_softc *sc = mac->mac_sc;
6750203945Sweongyo	int i;
6751203945Sweongyo	uint16_t ucstat;
6752203945Sweongyo
6753203945Sweongyo	KASSERT(!((flags & BWN_PS_ON) && (flags & BWN_PS_OFF)),
6754203945Sweongyo	    ("%s:%d: fail", __func__, __LINE__));
6755203945Sweongyo	KASSERT(!((flags & BWN_PS_AWAKE) && (flags & BWN_PS_ASLEEP)),
6756203945Sweongyo	    ("%s:%d: fail", __func__, __LINE__));
6757203945Sweongyo
6758203945Sweongyo	/* XXX forcibly awake and hwps-off */
6759203945Sweongyo
6760203945Sweongyo	BWN_WRITE_4(mac, BWN_MACCTL,
6761203945Sweongyo	    (BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_AWAKE) &
6762203945Sweongyo	    ~BWN_MACCTL_HWPS);
6763203945Sweongyo	BWN_READ_4(mac, BWN_MACCTL);
6764204922Sweongyo	if (siba_get_revid(sc->sc_dev) >= 5) {
6765203945Sweongyo		for (i = 0; i < 100; i++) {
6766203945Sweongyo			ucstat = bwn_shm_read_2(mac, BWN_SHARED,
6767203945Sweongyo			    BWN_SHARED_UCODESTAT);
6768203945Sweongyo			if (ucstat != BWN_SHARED_UCODESTAT_SLEEP)
6769203945Sweongyo				break;
6770203945Sweongyo			DELAY(10);
6771203945Sweongyo		}
6772203945Sweongyo	}
6773203945Sweongyo}
6774203945Sweongyo
6775203945Sweongyostatic int16_t
6776203945Sweongyobwn_nrssi_read(struct bwn_mac *mac, uint16_t offset)
6777203945Sweongyo{
6778203945Sweongyo
6779203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, offset);
6780203945Sweongyo	return ((int16_t)BWN_PHY_READ(mac, BWN_PHY_NRSSI_DATA));
6781203945Sweongyo}
6782203945Sweongyo
6783203945Sweongyostatic void
6784203945Sweongyobwn_nrssi_threshold(struct bwn_mac *mac)
6785203945Sweongyo{
6786203945Sweongyo	struct bwn_phy *phy = &mac->mac_phy;
6787203945Sweongyo	struct bwn_phy_g *pg = &phy->phy_g;
6788204922Sweongyo	struct bwn_softc *sc = mac->mac_sc;
6789203945Sweongyo	int32_t a, b;
6790203945Sweongyo	int16_t tmp16;
6791203945Sweongyo	uint16_t tmpu16;
6792203945Sweongyo
6793203945Sweongyo	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
6794203945Sweongyo
6795204922Sweongyo	if (phy->gmode && (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI)) {
6796203945Sweongyo		if (!pg->pg_aci_wlan_automatic && pg->pg_aci_enable) {
6797203945Sweongyo			a = 0x13;
6798203945Sweongyo			b = 0x12;
6799203945Sweongyo		} else {
6800203945Sweongyo			a = 0xe;
6801203945Sweongyo			b = 0x11;
6802203945Sweongyo		}
6803203945Sweongyo
6804203945Sweongyo		a = a * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6805203945Sweongyo		a += (pg->pg_nrssi[0] << 6);
6806203945Sweongyo		a += (a < 32) ? 31 : 32;
6807203945Sweongyo		a = a >> 6;
6808203945Sweongyo		a = MIN(MAX(a, -31), 31);
6809203945Sweongyo
6810203945Sweongyo		b = b * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6811203945Sweongyo		b += (pg->pg_nrssi[0] << 6);
6812203945Sweongyo		if (b < 32)
6813203945Sweongyo			b += 31;
6814203945Sweongyo		else
6815203945Sweongyo			b += 32;
6816203945Sweongyo		b = b >> 6;
6817203945Sweongyo		b = MIN(MAX(b, -31), 31);
6818203945Sweongyo
6819203945Sweongyo		tmpu16 = BWN_PHY_READ(mac, 0x048a) & 0xf000;
6820203945Sweongyo		tmpu16 |= ((uint32_t)b & 0x0000003f);
6821203945Sweongyo		tmpu16 |= (((uint32_t)a & 0x0000003f) << 6);
6822203945Sweongyo		BWN_PHY_WRITE(mac, 0x048a, tmpu16);
6823203945Sweongyo		return;
6824203945Sweongyo	}
6825203945Sweongyo
6826203945Sweongyo	tmp16 = bwn_nrssi_read(mac, 0x20);
6827203945Sweongyo	if (tmp16 >= 0x20)
6828203945Sweongyo		tmp16 -= 0x40;
6829203945Sweongyo	BWN_PHY_SETMASK(mac, 0x048a, 0xf000, (tmp16 < 3) ? 0x09eb : 0x0aed);
6830203945Sweongyo}
6831203945Sweongyo
6832203945Sweongyostatic void
6833203945Sweongyobwn_nrssi_slope_11g(struct bwn_mac *mac)
6834203945Sweongyo{
6835203945Sweongyo#define	SAVE_RF_MAX		3
6836203945Sweongyo#define	SAVE_PHY_COMM_MAX	4
6837203945Sweongyo#define	SAVE_PHY3_MAX		8
6838203945Sweongyo	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
6839203945Sweongyo		{ 0x7a, 0x52, 0x43 };
6840203945Sweongyo	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] =
6841203945Sweongyo		{ 0x15, 0x5a, 0x59, 0x58 };
6842203945Sweongyo	static const uint16_t save_phy3_regs[SAVE_PHY3_MAX] = {
6843203945Sweongyo		0x002e, 0x002f, 0x080f, BWN_PHY_G_LOCTL,
6844203945Sweongyo		0x0801, 0x0060, 0x0014, 0x0478
6845203945Sweongyo	};
6846203945Sweongyo	struct bwn_phy *phy = &mac->mac_phy;
6847203945Sweongyo	struct bwn_phy_g *pg = &phy->phy_g;
6848203945Sweongyo	int32_t i, tmp32, phy3_idx = 0;
6849203945Sweongyo	uint16_t delta, tmp;
6850203945Sweongyo	uint16_t save_rf[SAVE_RF_MAX];
6851203945Sweongyo	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
6852203945Sweongyo	uint16_t save_phy3[SAVE_PHY3_MAX];
6853203945Sweongyo	uint16_t ant_div, phy0, chan_ex;
6854203945Sweongyo	int16_t nrssi0, nrssi1;
6855203945Sweongyo
6856203945Sweongyo	KASSERT(phy->type == BWN_PHYTYPE_G,
6857203945Sweongyo	    ("%s:%d: fail", __func__, __LINE__));
6858203945Sweongyo
6859203945Sweongyo	if (phy->rf_rev >= 9)
6860203945Sweongyo		return;
6861203945Sweongyo	if (phy->rf_rev == 8)
6862203945Sweongyo		bwn_nrssi_offset(mac);
6863203945Sweongyo
6864203945Sweongyo	BWN_PHY_MASK(mac, BWN_PHY_G_CRS, 0x7fff);
6865203945Sweongyo	BWN_PHY_MASK(mac, 0x0802, 0xfffc);
6866203945Sweongyo
6867203945Sweongyo	/*
6868203945Sweongyo	 * Save RF/PHY registers for later restoration
6869203945Sweongyo	 */
6870203945Sweongyo	ant_div = BWN_READ_2(mac, 0x03e2);
6871203945Sweongyo	BWN_WRITE_2(mac, 0x03e2, BWN_READ_2(mac, 0x03e2) | 0x8000);
6872203945Sweongyo	for (i = 0; i < SAVE_RF_MAX; ++i)
6873203945Sweongyo		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
6874203945Sweongyo	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6875203945Sweongyo		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
6876203945Sweongyo
6877203945Sweongyo	phy0 = BWN_READ_2(mac, BWN_PHY0);
6878203945Sweongyo	chan_ex = BWN_READ_2(mac, BWN_CHANNEL_EXT);
6879203945Sweongyo	if (phy->rev >= 3) {
6880203945Sweongyo		for (i = 0; i < SAVE_PHY3_MAX; ++i)
6881203945Sweongyo			save_phy3[i] = BWN_PHY_READ(mac, save_phy3_regs[i]);
6882203945Sweongyo		BWN_PHY_WRITE(mac, 0x002e, 0);
6883203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_G_LOCTL, 0);
6884203945Sweongyo		switch (phy->rev) {
6885203945Sweongyo		case 4:
6886203945Sweongyo		case 6:
6887203945Sweongyo		case 7:
6888203945Sweongyo			BWN_PHY_SET(mac, 0x0478, 0x0100);
6889203945Sweongyo			BWN_PHY_SET(mac, 0x0801, 0x0040);
6890203945Sweongyo			break;
6891203945Sweongyo		case 3:
6892203945Sweongyo		case 5:
6893203945Sweongyo			BWN_PHY_MASK(mac, 0x0801, 0xffbf);
6894203945Sweongyo			break;
6895203945Sweongyo		}
6896203945Sweongyo		BWN_PHY_SET(mac, 0x0060, 0x0040);
6897203945Sweongyo		BWN_PHY_SET(mac, 0x0014, 0x0200);
6898203945Sweongyo	}
6899203945Sweongyo	/*
6900203945Sweongyo	 * Calculate nrssi0
6901203945Sweongyo	 */
6902203945Sweongyo	BWN_RF_SET(mac, 0x007a, 0x0070);
6903203945Sweongyo	bwn_set_all_gains(mac, 0, 8, 0);
6904203945Sweongyo	BWN_RF_MASK(mac, 0x007a, 0x00f7);
6905203945Sweongyo	if (phy->rev >= 2) {
6906203945Sweongyo		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0030);
6907203945Sweongyo		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0010);
6908203945Sweongyo	}
6909203945Sweongyo	BWN_RF_SET(mac, 0x007a, 0x0080);
6910203945Sweongyo	DELAY(20);
6911203945Sweongyo
6912203945Sweongyo	nrssi0 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6913203945Sweongyo	if (nrssi0 >= 0x0020)
6914203945Sweongyo		nrssi0 -= 0x0040;
6915203945Sweongyo
6916203945Sweongyo	/*
6917203945Sweongyo	 * Calculate nrssi1
6918203945Sweongyo	 */
6919203945Sweongyo	BWN_RF_MASK(mac, 0x007a, 0x007f);
6920203945Sweongyo	if (phy->rev >= 2)
6921203945Sweongyo		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
6922203945Sweongyo
6923203945Sweongyo	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
6924203945Sweongyo	    BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000);
6925203945Sweongyo	BWN_RF_SET(mac, 0x007a, 0x000f);
6926203945Sweongyo	BWN_PHY_WRITE(mac, 0x0015, 0xf330);
6927203945Sweongyo	if (phy->rev >= 2) {
6928203945Sweongyo		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0020);
6929203945Sweongyo		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0020);
6930203945Sweongyo	}
6931203945Sweongyo
6932203945Sweongyo	bwn_set_all_gains(mac, 3, 0, 1);
6933203945Sweongyo	if (phy->rf_rev == 8) {
6934203945Sweongyo		BWN_RF_WRITE(mac, 0x0043, 0x001f);
6935203945Sweongyo	} else {
6936203945Sweongyo		tmp = BWN_RF_READ(mac, 0x0052) & 0xff0f;
6937203945Sweongyo		BWN_RF_WRITE(mac, 0x0052, tmp | 0x0060);
6938203945Sweongyo		tmp = BWN_RF_READ(mac, 0x0043) & 0xfff0;
6939203945Sweongyo		BWN_RF_WRITE(mac, 0x0043, tmp | 0x0009);
6940203945Sweongyo	}
6941203945Sweongyo	BWN_PHY_WRITE(mac, 0x005a, 0x0480);
6942203945Sweongyo	BWN_PHY_WRITE(mac, 0x0059, 0x0810);
6943203945Sweongyo	BWN_PHY_WRITE(mac, 0x0058, 0x000d);
6944203945Sweongyo	DELAY(20);
6945203945Sweongyo	nrssi1 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6946203945Sweongyo
6947203945Sweongyo	/*
6948203945Sweongyo	 * Install calculated narrow RSSI values
6949203945Sweongyo	 */
6950203945Sweongyo	if (nrssi1 >= 0x0020)
6951203945Sweongyo		nrssi1 -= 0x0040;
6952203945Sweongyo	if (nrssi0 == nrssi1)
6953203945Sweongyo		pg->pg_nrssi_slope = 0x00010000;
6954203945Sweongyo	else
6955203945Sweongyo		pg->pg_nrssi_slope = 0x00400000 / (nrssi0 - nrssi1);
6956203945Sweongyo	if (nrssi0 >= -4) {
6957203945Sweongyo		pg->pg_nrssi[0] = nrssi1;
6958203945Sweongyo		pg->pg_nrssi[1] = nrssi0;
6959203945Sweongyo	}
6960203945Sweongyo
6961203945Sweongyo	/*
6962203945Sweongyo	 * Restore saved RF/PHY registers
6963203945Sweongyo	 */
6964203945Sweongyo	if (phy->rev >= 3) {
6965203945Sweongyo		for (phy3_idx = 0; phy3_idx < 4; ++phy3_idx) {
6966203945Sweongyo			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
6967203945Sweongyo			    save_phy3[phy3_idx]);
6968203945Sweongyo		}
6969203945Sweongyo	}
6970203945Sweongyo	if (phy->rev >= 2) {
6971203945Sweongyo		BWN_PHY_MASK(mac, 0x0812, 0xffcf);
6972203945Sweongyo		BWN_PHY_MASK(mac, 0x0811, 0xffcf);
6973203945Sweongyo	}
6974203945Sweongyo
6975203945Sweongyo	for (i = 0; i < SAVE_RF_MAX; ++i)
6976203945Sweongyo		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
6977203945Sweongyo
6978203945Sweongyo	BWN_WRITE_2(mac, 0x03e2, ant_div);
6979203945Sweongyo	BWN_WRITE_2(mac, 0x03e6, phy0);
6980203945Sweongyo	BWN_WRITE_2(mac, BWN_CHANNEL_EXT, chan_ex);
6981203945Sweongyo
6982203945Sweongyo	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6983203945Sweongyo		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
6984203945Sweongyo
6985203945Sweongyo	bwn_spu_workaround(mac, phy->chan);
6986203945Sweongyo	BWN_PHY_SET(mac, 0x0802, (0x0001 | 0x0002));
6987203945Sweongyo	bwn_set_original_gains(mac);
6988203945Sweongyo	BWN_PHY_SET(mac, BWN_PHY_G_CRS, 0x8000);
6989203945Sweongyo	if (phy->rev >= 3) {
6990203945Sweongyo		for (; phy3_idx < SAVE_PHY3_MAX; ++phy3_idx) {
6991203945Sweongyo			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
6992203945Sweongyo			    save_phy3[phy3_idx]);
6993203945Sweongyo		}
6994203945Sweongyo	}
6995203945Sweongyo
6996203945Sweongyo	delta = 0x1f - pg->pg_nrssi[0];
6997203945Sweongyo	for (i = 0; i < 64; i++) {
6998203945Sweongyo		tmp32 = (((i - delta) * pg->pg_nrssi_slope) / 0x10000) + 0x3a;
6999203945Sweongyo		tmp32 = MIN(MAX(tmp32, 0), 0x3f);
7000203945Sweongyo		pg->pg_nrssi_lt[i] = tmp32;
7001203945Sweongyo	}
7002203945Sweongyo
7003203945Sweongyo	bwn_nrssi_threshold(mac);
7004203945Sweongyo#undef SAVE_RF_MAX
7005203945Sweongyo#undef SAVE_PHY_COMM_MAX
7006203945Sweongyo#undef SAVE_PHY3_MAX
7007203945Sweongyo}
7008203945Sweongyo
7009203945Sweongyostatic void
7010203945Sweongyobwn_nrssi_offset(struct bwn_mac *mac)
7011203945Sweongyo{
7012203945Sweongyo#define	SAVE_RF_MAX		2
7013203945Sweongyo#define	SAVE_PHY_COMM_MAX	10
7014203945Sweongyo#define	SAVE_PHY6_MAX		8
7015203945Sweongyo	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
7016203945Sweongyo		{ 0x7a, 0x43 };
7017203945Sweongyo	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] = {
7018203945Sweongyo		0x0001, 0x0811, 0x0812, 0x0814,
7019203945Sweongyo		0x0815, 0x005a, 0x0059, 0x0058,
7020203945Sweongyo		0x000a, 0x0003
7021203945Sweongyo	};
7022203945Sweongyo	static const uint16_t save_phy6_regs[SAVE_PHY6_MAX] = {
7023203945Sweongyo		0x002e, 0x002f, 0x080f, 0x0810,
7024203945Sweongyo		0x0801, 0x0060, 0x0014, 0x0478
7025203945Sweongyo	};
7026203945Sweongyo	struct bwn_phy *phy = &mac->mac_phy;
7027203945Sweongyo	int i, phy6_idx = 0;
7028203945Sweongyo	uint16_t save_rf[SAVE_RF_MAX];
7029203945Sweongyo	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
7030203945Sweongyo	uint16_t save_phy6[SAVE_PHY6_MAX];
7031203945Sweongyo	int16_t nrssi;
7032203945Sweongyo	uint16_t saved = 0xffff;
7033203945Sweongyo
7034203945Sweongyo	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
7035203945Sweongyo		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
7036203945Sweongyo	for (i = 0; i < SAVE_RF_MAX; ++i)
7037203945Sweongyo		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
7038203945Sweongyo
7039203945Sweongyo	BWN_PHY_MASK(mac, 0x0429, 0x7fff);
7040203945Sweongyo	BWN_PHY_SETMASK(mac, 0x0001, 0x3fff, 0x4000);
7041203945Sweongyo	BWN_PHY_SET(mac, 0x0811, 0x000c);
7042203945Sweongyo	BWN_PHY_SETMASK(mac, 0x0812, 0xfff3, 0x0004);
7043203945Sweongyo	BWN_PHY_MASK(mac, 0x0802, ~(0x1 | 0x2));
7044203945Sweongyo	if (phy->rev >= 6) {
7045203945Sweongyo		for (i = 0; i < SAVE_PHY6_MAX; ++i)
7046203945Sweongyo			save_phy6[i] = BWN_PHY_READ(mac, save_phy6_regs[i]);
7047203945Sweongyo
7048203945Sweongyo		BWN_PHY_WRITE(mac, 0x002e, 0);
7049203945Sweongyo		BWN_PHY_WRITE(mac, 0x002f, 0);
7050203945Sweongyo		BWN_PHY_WRITE(mac, 0x080f, 0);
7051203945Sweongyo		BWN_PHY_WRITE(mac, 0x0810, 0);
7052203945Sweongyo		BWN_PHY_SET(mac, 0x0478, 0x0100);
7053203945Sweongyo		BWN_PHY_SET(mac, 0x0801, 0x0040);
7054203945Sweongyo		BWN_PHY_SET(mac, 0x0060, 0x0040);
7055203945Sweongyo		BWN_PHY_SET(mac, 0x0014, 0x0200);
7056203945Sweongyo	}
7057203945Sweongyo	BWN_RF_SET(mac, 0x007a, 0x0070);
7058203945Sweongyo	BWN_RF_SET(mac, 0x007a, 0x0080);
7059203945Sweongyo	DELAY(30);
7060203945Sweongyo
7061203945Sweongyo	nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
7062203945Sweongyo	if (nrssi >= 0x20)
7063203945Sweongyo		nrssi -= 0x40;
7064203945Sweongyo	if (nrssi == 31) {
7065203945Sweongyo		for (i = 7; i >= 4; i--) {
7066203945Sweongyo			BWN_RF_WRITE(mac, 0x007b, i);
7067203945Sweongyo			DELAY(20);
7068203945Sweongyo			nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) &
7069203945Sweongyo			    0x003f);
7070203945Sweongyo			if (nrssi >= 0x20)
7071203945Sweongyo				nrssi -= 0x40;
7072203945Sweongyo			if (nrssi < 31 && saved == 0xffff)
7073203945Sweongyo				saved = i;
7074203945Sweongyo		}
7075203945Sweongyo		if (saved == 0xffff)
7076203945Sweongyo			saved = 4;
7077203945Sweongyo	} else {
7078203945Sweongyo		BWN_RF_MASK(mac, 0x007a, 0x007f);
7079203945Sweongyo		if (phy->rev != 1) {
7080203945Sweongyo			BWN_PHY_SET(mac, 0x0814, 0x0001);
7081203945Sweongyo			BWN_PHY_MASK(mac, 0x0815, 0xfffe);
7082203945Sweongyo		}
7083203945Sweongyo		BWN_PHY_SET(mac, 0x0811, 0x000c);
7084203945Sweongyo		BWN_PHY_SET(mac, 0x0812, 0x000c);
7085203945Sweongyo		BWN_PHY_SET(mac, 0x0811, 0x0030);
7086203945Sweongyo		BWN_PHY_SET(mac, 0x0812, 0x0030);
7087203945Sweongyo		BWN_PHY_WRITE(mac, 0x005a, 0x0480);
7088203945Sweongyo		BWN_PHY_WRITE(mac, 0x0059, 0x0810);
7089203945Sweongyo		BWN_PHY_WRITE(mac, 0x0058, 0x000d);
7090203945Sweongyo		if (phy->rev == 0)
7091203945Sweongyo			BWN_PHY_WRITE(mac, 0x0003, 0x0122);
7092203945Sweongyo		else
7093203945Sweongyo			BWN_PHY_SET(mac, 0x000a, 0x2000);
7094203945Sweongyo		if (phy->rev != 1) {
7095203945Sweongyo			BWN_PHY_SET(mac, 0x0814, 0x0004);
7096203945Sweongyo			BWN_PHY_MASK(mac, 0x0815, 0xfffb);
7097203945Sweongyo		}
7098203945Sweongyo		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
7099203945Sweongyo		BWN_RF_SET(mac, 0x007a, 0x000f);
7100203945Sweongyo		bwn_set_all_gains(mac, 3, 0, 1);
7101203945Sweongyo		BWN_RF_SETMASK(mac, 0x0043, 0x00f0, 0x000f);
7102203945Sweongyo		DELAY(30);
7103203945Sweongyo		nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
7104203945Sweongyo		if (nrssi >= 0x20)
7105203945Sweongyo			nrssi -= 0x40;
7106203945Sweongyo		if (nrssi == -32) {
7107203945Sweongyo			for (i = 0; i < 4; i++) {
7108203945Sweongyo				BWN_RF_WRITE(mac, 0x007b, i);
7109203945Sweongyo				DELAY(20);
7110203945Sweongyo				nrssi = (int16_t)((BWN_PHY_READ(mac,
7111203945Sweongyo				    0x047f) >> 8) & 0x003f);
7112203945Sweongyo				if (nrssi >= 0x20)
7113203945Sweongyo					nrssi -= 0x40;
7114203945Sweongyo				if (nrssi > -31 && saved == 0xffff)
7115203945Sweongyo					saved = i;
7116203945Sweongyo			}
7117203945Sweongyo			if (saved == 0xffff)
7118203945Sweongyo				saved = 3;
7119203945Sweongyo		} else
7120203945Sweongyo			saved = 0;
7121203945Sweongyo	}
7122203945Sweongyo	BWN_RF_WRITE(mac, 0x007b, saved);
7123203945Sweongyo
7124203945Sweongyo	/*
7125203945Sweongyo	 * Restore saved RF/PHY registers
7126203945Sweongyo	 */
7127203945Sweongyo	if (phy->rev >= 6) {
7128203945Sweongyo		for (phy6_idx = 0; phy6_idx < 4; ++phy6_idx) {
7129203945Sweongyo			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
7130203945Sweongyo			    save_phy6[phy6_idx]);
7131203945Sweongyo		}
7132203945Sweongyo	}
7133203945Sweongyo	if (phy->rev != 1) {
7134203945Sweongyo		for (i = 3; i < 5; i++)
7135203945Sweongyo			BWN_PHY_WRITE(mac, save_phy_comm_regs[i],
7136203945Sweongyo			    save_phy_comm[i]);
7137203945Sweongyo	}
7138203945Sweongyo	for (i = 5; i < SAVE_PHY_COMM_MAX; i++)
7139203945Sweongyo		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
7140203945Sweongyo
7141203945Sweongyo	for (i = SAVE_RF_MAX - 1; i >= 0; --i)
7142203945Sweongyo		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
7143203945Sweongyo
7144203945Sweongyo	BWN_PHY_WRITE(mac, 0x0802, BWN_PHY_READ(mac, 0x0802) | 0x1 | 0x2);
7145203945Sweongyo	BWN_PHY_SET(mac, 0x0429, 0x8000);
7146203945Sweongyo	bwn_set_original_gains(mac);
7147203945Sweongyo	if (phy->rev >= 6) {
7148203945Sweongyo		for (; phy6_idx < SAVE_PHY6_MAX; ++phy6_idx) {
7149203945Sweongyo			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
7150203945Sweongyo			    save_phy6[phy6_idx]);
7151203945Sweongyo		}
7152203945Sweongyo	}
7153203945Sweongyo
7154203945Sweongyo	BWN_PHY_WRITE(mac, save_phy_comm_regs[0], save_phy_comm[0]);
7155203945Sweongyo	BWN_PHY_WRITE(mac, save_phy_comm_regs[2], save_phy_comm[2]);
7156203945Sweongyo	BWN_PHY_WRITE(mac, save_phy_comm_regs[1], save_phy_comm[1]);
7157203945Sweongyo}
7158203945Sweongyo
7159203945Sweongyostatic void
7160203945Sweongyobwn_set_all_gains(struct bwn_mac *mac, int16_t first, int16_t second,
7161203945Sweongyo    int16_t third)
7162203945Sweongyo{
7163203945Sweongyo	struct bwn_phy *phy = &mac->mac_phy;
7164203945Sweongyo	uint16_t i;
7165203945Sweongyo	uint16_t start = 0x08, end = 0x18;
7166203945Sweongyo	uint16_t tmp;
7167203945Sweongyo	uint16_t table;
7168203945Sweongyo
7169203945Sweongyo	if (phy->rev <= 1) {
7170203945Sweongyo		start = 0x10;
7171203945Sweongyo		end = 0x20;
7172203945Sweongyo	}
7173203945Sweongyo
7174203945Sweongyo	table = BWN_OFDMTAB_GAINX;
7175203945Sweongyo	if (phy->rev <= 1)
7176203945Sweongyo		table = BWN_OFDMTAB_GAINX_R1;
7177203945Sweongyo	for (i = 0; i < 4; i++)
7178203945Sweongyo		bwn_ofdmtab_write_2(mac, table, i, first);
7179203945Sweongyo
7180203945Sweongyo	for (i = start; i < end; i++)
7181203945Sweongyo		bwn_ofdmtab_write_2(mac, table, i, second);
7182203945Sweongyo
7183203945Sweongyo	if (third != -1) {
7184203945Sweongyo		tmp = ((uint16_t) third << 14) | ((uint16_t) third << 6);
7185203945Sweongyo		BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, tmp);
7186203945Sweongyo		BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, tmp);
7187203945Sweongyo		BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, tmp);
7188203945Sweongyo	}
7189203945Sweongyo	bwn_dummy_transmission(mac, 0, 1);
7190203945Sweongyo}
7191203945Sweongyo
7192203945Sweongyostatic void
7193203945Sweongyobwn_set_original_gains(struct bwn_mac *mac)
7194203945Sweongyo{
7195203945Sweongyo	struct bwn_phy *phy = &mac->mac_phy;
7196203945Sweongyo	uint16_t i, tmp;
7197203945Sweongyo	uint16_t table;
7198203945Sweongyo	uint16_t start = 0x0008, end = 0x0018;
7199203945Sweongyo
7200203945Sweongyo	if (phy->rev <= 1) {
7201203945Sweongyo		start = 0x0010;
7202203945Sweongyo		end = 0x0020;
7203203945Sweongyo	}
7204203945Sweongyo
7205203945Sweongyo	table = BWN_OFDMTAB_GAINX;
7206203945Sweongyo	if (phy->rev <= 1)
7207203945Sweongyo		table = BWN_OFDMTAB_GAINX_R1;
7208203945Sweongyo	for (i = 0; i < 4; i++) {
7209203945Sweongyo		tmp = (i & 0xfffc);
7210203945Sweongyo		tmp |= (i & 0x0001) << 1;
7211203945Sweongyo		tmp |= (i & 0x0002) >> 1;
7212203945Sweongyo
7213203945Sweongyo		bwn_ofdmtab_write_2(mac, table, i, tmp);
7214203945Sweongyo	}
7215203945Sweongyo
7216203945Sweongyo	for (i = start; i < end; i++)
7217203945Sweongyo		bwn_ofdmtab_write_2(mac, table, i, i - start);
7218203945Sweongyo
7219203945Sweongyo	BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, 0x4040);
7220203945Sweongyo	BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, 0x4040);
7221203945Sweongyo	BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, 0x4000);
7222203945Sweongyo	bwn_dummy_transmission(mac, 0, 1);
7223203945Sweongyo}
7224203945Sweongyo
7225203945Sweongyostatic void
7226203945Sweongyobwn_phy_hwpctl_init(struct bwn_mac *mac)
7227203945Sweongyo{
7228203945Sweongyo	struct bwn_phy *phy = &mac->mac_phy;
7229203945Sweongyo	struct bwn_phy_g *pg = &phy->phy_g;
7230203945Sweongyo	struct bwn_rfatt old_rfatt, rfatt;
7231203945Sweongyo	struct bwn_bbatt old_bbatt, bbatt;
7232204922Sweongyo	struct bwn_softc *sc = mac->mac_sc;
7233203945Sweongyo	uint8_t old_txctl = 0;
7234203945Sweongyo
7235203945Sweongyo	KASSERT(phy->type == BWN_PHYTYPE_G,
7236203945Sweongyo	    ("%s:%d: fail", __func__, __LINE__));
7237203945Sweongyo
7238204922Sweongyo	if ((siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM) &&
7239204922Sweongyo	    (siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306))
7240203945Sweongyo		return;
7241203945Sweongyo
7242203945Sweongyo	BWN_PHY_WRITE(mac, 0x0028, 0x8018);
7243203945Sweongyo
7244203945Sweongyo	BWN_WRITE_2(mac, BWN_PHY0, BWN_READ_2(mac, BWN_PHY0) & 0xffdf);
7245203945Sweongyo
7246203945Sweongyo	if (!phy->gmode)
7247203945Sweongyo		return;
7248203945Sweongyo	bwn_hwpctl_early_init(mac);
7249203945Sweongyo	if (pg->pg_curtssi == 0) {
7250203945Sweongyo		if (phy->rf_ver == 0x2050 && phy->analog == 0) {
7251203945Sweongyo			BWN_RF_SETMASK(mac, 0x0076, 0x00f7, 0x0084);
7252203945Sweongyo		} else {
7253203945Sweongyo			memcpy(&old_rfatt, &pg->pg_rfatt, sizeof(old_rfatt));
7254203945Sweongyo			memcpy(&old_bbatt, &pg->pg_bbatt, sizeof(old_bbatt));
7255203945Sweongyo			old_txctl = pg->pg_txctl;
7256203945Sweongyo
7257203945Sweongyo			bbatt.att = 11;
7258203945Sweongyo			if (phy->rf_rev == 8) {
7259203945Sweongyo				rfatt.att = 15;
7260203945Sweongyo				rfatt.padmix = 1;
7261203945Sweongyo			} else {
7262203945Sweongyo				rfatt.att = 9;
7263203945Sweongyo				rfatt.padmix = 0;
7264203945Sweongyo			}
7265203945Sweongyo			bwn_phy_g_set_txpwr_sub(mac, &bbatt, &rfatt, 0);
7266203945Sweongyo		}
7267203945Sweongyo		bwn_dummy_transmission(mac, 0, 1);
7268203945Sweongyo		pg->pg_curtssi = BWN_PHY_READ(mac, BWN_PHY_TSSI);
7269203945Sweongyo		if (phy->rf_ver == 0x2050 && phy->analog == 0)
7270203945Sweongyo			BWN_RF_MASK(mac, 0x0076, 0xff7b);
7271203945Sweongyo		else
7272203945Sweongyo			bwn_phy_g_set_txpwr_sub(mac, &old_bbatt,
7273203945Sweongyo			    &old_rfatt, old_txctl);
7274203945Sweongyo	}
7275203945Sweongyo	bwn_hwpctl_init_gphy(mac);
7276203945Sweongyo
7277203945Sweongyo	/* clear TSSI */
7278203945Sweongyo	bwn_shm_write_2(mac, BWN_SHARED, 0x0058, 0x7f7f);
7279203945Sweongyo	bwn_shm_write_2(mac, BWN_SHARED, 0x005a, 0x7f7f);
7280203945Sweongyo	bwn_shm_write_2(mac, BWN_SHARED, 0x0070, 0x7f7f);
7281203945Sweongyo	bwn_shm_write_2(mac, BWN_SHARED, 0x0072, 0x7f7f);
7282203945Sweongyo}
7283203945Sweongyo
7284203945Sweongyostatic void
7285203945Sweongyobwn_hwpctl_early_init(struct bwn_mac *mac)
7286203945Sweongyo{
7287203945Sweongyo	struct bwn_phy *phy = &mac->mac_phy;
7288203945Sweongyo
7289203945Sweongyo	if (!bwn_has_hwpctl(mac)) {
7290203945Sweongyo		BWN_PHY_WRITE(mac, 0x047a, 0xc111);
7291203945Sweongyo		return;
7292203945Sweongyo	}
7293203945Sweongyo
7294203945Sweongyo	BWN_PHY_MASK(mac, 0x0036, 0xfeff);
7295203945Sweongyo	BWN_PHY_WRITE(mac, 0x002f, 0x0202);
7296203945Sweongyo	BWN_PHY_SET(mac, 0x047c, 0x0002);
7297203945Sweongyo	BWN_PHY_SET(mac, 0x047a, 0xf000);
7298203945Sweongyo	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
7299203945Sweongyo		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7300203945Sweongyo		BWN_PHY_SET(mac, 0x005d, 0x8000);
7301203945Sweongyo		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7302203945Sweongyo		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7303203945Sweongyo		BWN_PHY_SET(mac, 0x0036, 0x0400);
7304203945Sweongyo	} else {
7305203945Sweongyo		BWN_PHY_SET(mac, 0x0036, 0x0200);
7306203945Sweongyo		BWN_PHY_SET(mac, 0x0036, 0x0400);
7307203945Sweongyo		BWN_PHY_MASK(mac, 0x005d, 0x7fff);
7308203945Sweongyo		BWN_PHY_MASK(mac, 0x004f, 0xfffe);
7309203945Sweongyo		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7310203945Sweongyo		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7311203945Sweongyo		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7312203945Sweongyo	}
7313203945Sweongyo}
7314203945Sweongyo
7315203945Sweongyostatic void
7316203945Sweongyobwn_hwpctl_init_gphy(struct bwn_mac *mac)
7317203945Sweongyo{
7318203945Sweongyo	struct bwn_phy *phy = &mac->mac_phy;
7319203945Sweongyo	struct bwn_phy_g *pg = &phy->phy_g;
7320203945Sweongyo	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7321203945Sweongyo	int i;
7322203945Sweongyo	uint16_t nr_written = 0, tmp, value;
7323203945Sweongyo	uint8_t rf, bb;
7324203945Sweongyo
7325203945Sweongyo	if (!bwn_has_hwpctl(mac)) {
7326203945Sweongyo		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_HW_POWERCTL);
7327203945Sweongyo		return;
7328203945Sweongyo	}
7329203945Sweongyo
7330203945Sweongyo	BWN_PHY_SETMASK(mac, 0x0036, 0xffc0,
7331203945Sweongyo	    (pg->pg_idletssi - pg->pg_curtssi));
7332203945Sweongyo	BWN_PHY_SETMASK(mac, 0x0478, 0xff00,
7333203945Sweongyo	    (pg->pg_idletssi - pg->pg_curtssi));
7334203945Sweongyo
7335203945Sweongyo	for (i = 0; i < 32; i++)
7336203945Sweongyo		bwn_ofdmtab_write_2(mac, 0x3c20, i, pg->pg_tssi2dbm[i]);
7337203945Sweongyo	for (i = 32; i < 64; i++)
7338203945Sweongyo		bwn_ofdmtab_write_2(mac, 0x3c00, i - 32, pg->pg_tssi2dbm[i]);
7339203945Sweongyo	for (i = 0; i < 64; i += 2) {
7340203945Sweongyo		value = (uint16_t) pg->pg_tssi2dbm[i];
7341203945Sweongyo		value |= ((uint16_t) pg->pg_tssi2dbm[i + 1]) << 8;
7342203945Sweongyo		BWN_PHY_WRITE(mac, 0x380 + (i / 2), value);
7343203945Sweongyo	}
7344203945Sweongyo
7345203945Sweongyo	for (rf = 0; rf < lo->rfatt.len; rf++) {
7346203945Sweongyo		for (bb = 0; bb < lo->bbatt.len; bb++) {
7347203945Sweongyo			if (nr_written >= 0x40)
7348203945Sweongyo				return;
7349203945Sweongyo			tmp = lo->bbatt.array[bb].att;
7350203945Sweongyo			tmp <<= 8;
7351203945Sweongyo			if (phy->rf_rev == 8)
7352203945Sweongyo				tmp |= 0x50;
7353203945Sweongyo			else
7354203945Sweongyo				tmp |= 0x40;
7355203945Sweongyo			tmp |= lo->rfatt.array[rf].att;
7356203945Sweongyo			BWN_PHY_WRITE(mac, 0x3c0 + nr_written, tmp);
7357203945Sweongyo			nr_written++;
7358203945Sweongyo		}
7359203945Sweongyo	}
7360203945Sweongyo
7361203945Sweongyo	BWN_PHY_MASK(mac, 0x0060, 0xffbf);
7362203945Sweongyo	BWN_PHY_WRITE(mac, 0x0014, 0x0000);
7363203945Sweongyo
7364203945Sweongyo	KASSERT(phy->rev >= 6, ("%s:%d: fail", __func__, __LINE__));
7365203945Sweongyo	BWN_PHY_SET(mac, 0x0478, 0x0800);
7366203945Sweongyo	BWN_PHY_MASK(mac, 0x0478, 0xfeff);
7367203945Sweongyo	BWN_PHY_MASK(mac, 0x0801, 0xffbf);
7368203945Sweongyo
7369203945Sweongyo	bwn_phy_g_dc_lookup_init(mac, 1);
7370203945Sweongyo	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_HW_POWERCTL);
7371203945Sweongyo}
7372203945Sweongyo
7373203945Sweongyostatic void
7374203945Sweongyobwn_phy_g_switch_chan(struct bwn_mac *mac, int channel, uint8_t spu)
7375203945Sweongyo{
7376204922Sweongyo	struct bwn_softc *sc = mac->mac_sc;
7377203945Sweongyo
7378203945Sweongyo	if (spu != 0)
7379203945Sweongyo		bwn_spu_workaround(mac, channel);
7380203945Sweongyo
7381203945Sweongyo	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7382203945Sweongyo
7383203945Sweongyo	if (channel == 14) {
7384204922Sweongyo		if (siba_sprom_get_ccode(sc->sc_dev) == SIBA_CCODE_JAPAN)
7385203945Sweongyo			bwn_hf_write(mac,
7386203945Sweongyo			    bwn_hf_read(mac) & ~BWN_HF_JAPAN_CHAN14_OFF);
7387203945Sweongyo		else
7388203945Sweongyo			bwn_hf_write(mac,
7389203945Sweongyo			    bwn_hf_read(mac) | BWN_HF_JAPAN_CHAN14_OFF);
7390203945Sweongyo		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7391203945Sweongyo		    BWN_READ_2(mac, BWN_CHANNEL_EXT) | (1 << 11));
7392203945Sweongyo		return;
7393203945Sweongyo	}
7394203945Sweongyo
7395203945Sweongyo	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7396203945Sweongyo	    BWN_READ_2(mac, BWN_CHANNEL_EXT) & 0xf7bf);
7397203945Sweongyo}
7398203945Sweongyo
7399203945Sweongyostatic uint16_t
7400203945Sweongyobwn_phy_g_chan2freq(uint8_t channel)
7401203945Sweongyo{
7402203945Sweongyo	static const uint8_t bwn_phy_g_rf_channels[] = BWN_PHY_G_RF_CHANNELS;
7403203945Sweongyo
7404203945Sweongyo	KASSERT(channel >= 1 && channel <= 14,
7405203945Sweongyo	    ("%s:%d: fail", __func__, __LINE__));
7406203945Sweongyo
7407203945Sweongyo	return (bwn_phy_g_rf_channels[channel - 1]);
7408203945Sweongyo}
7409203945Sweongyo
7410203945Sweongyostatic void
7411203945Sweongyobwn_phy_g_set_txpwr_sub(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
7412203945Sweongyo    const struct bwn_rfatt *rfatt, uint8_t txctl)
7413203945Sweongyo{
7414203945Sweongyo	struct bwn_phy *phy = &mac->mac_phy;
7415203945Sweongyo	struct bwn_phy_g *pg = &phy->phy_g;
7416203945Sweongyo	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7417203945Sweongyo	uint16_t bb, rf;
7418203945Sweongyo	uint16_t tx_bias, tx_magn;
7419203945Sweongyo
7420203945Sweongyo	bb = bbatt->att;
7421203945Sweongyo	rf = rfatt->att;
7422203945Sweongyo	tx_bias = lo->tx_bias;
7423203945Sweongyo	tx_magn = lo->tx_magn;
7424203945Sweongyo	if (tx_bias == 0xff)
7425203945Sweongyo		tx_bias = 0;
7426203945Sweongyo
7427203945Sweongyo	pg->pg_txctl = txctl;
7428203945Sweongyo	memmove(&pg->pg_rfatt, rfatt, sizeof(*rfatt));
7429203945Sweongyo	pg->pg_rfatt.padmix = (txctl & BWN_TXCTL_TXMIX) ? 1 : 0;
7430203945Sweongyo	memmove(&pg->pg_bbatt, bbatt, sizeof(*bbatt));
7431203945Sweongyo	bwn_phy_g_set_bbatt(mac, bb);
7432203945Sweongyo	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RADIO_ATT, rf);
7433203945Sweongyo	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8)
7434203945Sweongyo		BWN_RF_WRITE(mac, 0x43, (rf & 0x000f) | (txctl & 0x0070));
7435203945Sweongyo	else {
7436203945Sweongyo		BWN_RF_SETMASK(mac, 0x43, 0xfff0, (rf & 0x000f));
7437203945Sweongyo		BWN_RF_SETMASK(mac, 0x52, ~0x0070, (txctl & 0x0070));
7438203945Sweongyo	}
7439203945Sweongyo	if (BWN_HAS_TXMAG(phy))
7440203945Sweongyo		BWN_RF_WRITE(mac, 0x52, tx_magn | tx_bias);
7441203945Sweongyo	else
7442203945Sweongyo		BWN_RF_SETMASK(mac, 0x52, 0xfff0, (tx_bias & 0x000f));
7443203945Sweongyo	bwn_lo_g_adjust(mac);
7444203945Sweongyo}
7445203945Sweongyo
7446203945Sweongyostatic void
7447203945Sweongyobwn_phy_g_set_bbatt(struct bwn_mac *mac,
7448203945Sweongyo    uint16_t bbatt)
7449203945Sweongyo{
7450203945Sweongyo	struct bwn_phy *phy = &mac->mac_phy;
7451203945Sweongyo
7452203945Sweongyo	if (phy->analog == 0) {
7453203945Sweongyo		BWN_WRITE_2(mac, BWN_PHY0,
7454203945Sweongyo		    (BWN_READ_2(mac, BWN_PHY0) & 0xfff0) | bbatt);
7455203945Sweongyo		return;
7456203945Sweongyo	}
7457203945Sweongyo	if (phy->analog > 1) {
7458203945Sweongyo		BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xffc3, bbatt << 2);
7459203945Sweongyo		return;
7460203945Sweongyo	}
7461203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xff87, bbatt << 3);
7462203945Sweongyo}
7463203945Sweongyo
7464203945Sweongyostatic uint16_t
7465203945Sweongyobwn_rf_2050_rfoverval(struct bwn_mac *mac, uint16_t reg, uint32_t lpd)
7466203945Sweongyo{
7467203945Sweongyo	struct bwn_phy *phy = &mac->mac_phy;
7468203945Sweongyo	struct bwn_phy_g *pg = &phy->phy_g;
7469204922Sweongyo	struct bwn_softc *sc = mac->mac_sc;
7470203945Sweongyo	int max_lb_gain;
7471203945Sweongyo	uint16_t extlna;
7472203945Sweongyo	uint16_t i;
7473203945Sweongyo
7474203945Sweongyo	if (phy->gmode == 0)
7475203945Sweongyo		return (0);
7476203945Sweongyo
7477203945Sweongyo	if (BWN_HAS_LOOPBACK(phy)) {
7478203945Sweongyo		max_lb_gain = pg->pg_max_lb_gain;
7479203945Sweongyo		max_lb_gain += (phy->rf_rev == 8) ? 0x3e : 0x26;
7480203945Sweongyo		if (max_lb_gain >= 0x46) {
7481203945Sweongyo			extlna = 0x3000;
7482203945Sweongyo			max_lb_gain -= 0x46;
7483203945Sweongyo		} else if (max_lb_gain >= 0x3a) {
7484203945Sweongyo			extlna = 0x1000;
7485203945Sweongyo			max_lb_gain -= 0x3a;
7486203945Sweongyo		} else if (max_lb_gain >= 0x2e) {
7487203945Sweongyo			extlna = 0x2000;
7488203945Sweongyo			max_lb_gain -= 0x2e;
7489203945Sweongyo		} else {
7490203945Sweongyo			extlna = 0;
7491203945Sweongyo			max_lb_gain -= 0x10;
7492203945Sweongyo		}
7493203945Sweongyo
7494203945Sweongyo		for (i = 0; i < 16; i++) {
7495203945Sweongyo			max_lb_gain -= (i * 6);
7496203945Sweongyo			if (max_lb_gain < 6)
7497203945Sweongyo				break;
7498203945Sweongyo		}
7499203945Sweongyo
7500204922Sweongyo		if ((phy->rev < 7) ||
7501204922Sweongyo		    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA)) {
7502203945Sweongyo			if (reg == BWN_PHY_RFOVER) {
7503203945Sweongyo				return (0x1b3);
7504203945Sweongyo			} else if (reg == BWN_PHY_RFOVERVAL) {
7505203945Sweongyo				extlna |= (i << 8);
7506203945Sweongyo				switch (lpd) {
7507203945Sweongyo				case BWN_LPD(0, 1, 1):
7508203945Sweongyo					return (0x0f92);
7509203945Sweongyo				case BWN_LPD(0, 0, 1):
7510203945Sweongyo				case BWN_LPD(1, 0, 1):
7511203945Sweongyo					return (0x0092 | extlna);
7512203945Sweongyo				case BWN_LPD(1, 0, 0):
7513203945Sweongyo					return (0x0093 | extlna);
7514203945Sweongyo				}
7515203945Sweongyo				KASSERT(0 == 1,
7516203945Sweongyo				    ("%s:%d: fail", __func__, __LINE__));
7517203945Sweongyo			}
7518203945Sweongyo			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7519203945Sweongyo		} else {
7520203945Sweongyo			if (reg == BWN_PHY_RFOVER)
7521203945Sweongyo				return (0x9b3);
7522203945Sweongyo			if (reg == BWN_PHY_RFOVERVAL) {
7523203945Sweongyo				if (extlna)
7524203945Sweongyo					extlna |= 0x8000;
7525203945Sweongyo				extlna |= (i << 8);
7526203945Sweongyo				switch (lpd) {
7527203945Sweongyo				case BWN_LPD(0, 1, 1):
7528203945Sweongyo					return (0x8f92);
7529203945Sweongyo				case BWN_LPD(0, 0, 1):
7530203945Sweongyo					return (0x8092 | extlna);
7531203945Sweongyo				case BWN_LPD(1, 0, 1):
7532203945Sweongyo					return (0x2092 | extlna);
7533203945Sweongyo				case BWN_LPD(1, 0, 0):
7534203945Sweongyo					return (0x2093 | extlna);
7535203945Sweongyo				}
7536203945Sweongyo				KASSERT(0 == 1,
7537203945Sweongyo				    ("%s:%d: fail", __func__, __LINE__));
7538203945Sweongyo			}
7539203945Sweongyo			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7540203945Sweongyo		}
7541203945Sweongyo		return (0);
7542203945Sweongyo	}
7543203945Sweongyo
7544203945Sweongyo	if ((phy->rev < 7) ||
7545204922Sweongyo	    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA)) {
7546203945Sweongyo		if (reg == BWN_PHY_RFOVER) {
7547203945Sweongyo			return (0x1b3);
7548203945Sweongyo		} else if (reg == BWN_PHY_RFOVERVAL) {
7549203945Sweongyo			switch (lpd) {
7550203945Sweongyo			case BWN_LPD(0, 1, 1):
7551203945Sweongyo				return (0x0fb2);
7552203945Sweongyo			case BWN_LPD(0, 0, 1):
7553203945Sweongyo				return (0x00b2);
7554203945Sweongyo			case BWN_LPD(1, 0, 1):
7555203945Sweongyo				return (0x30b2);
7556203945Sweongyo			case BWN_LPD(1, 0, 0):
7557203945Sweongyo				return (0x30b3);
7558203945Sweongyo			}
7559203945Sweongyo			KASSERT(0 == 1,
7560203945Sweongyo			    ("%s:%d: fail", __func__, __LINE__));
7561203945Sweongyo		}
7562203945Sweongyo		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7563203945Sweongyo	} else {
7564203945Sweongyo		if (reg == BWN_PHY_RFOVER) {
7565203945Sweongyo			return (0x9b3);
7566203945Sweongyo		} else if (reg == BWN_PHY_RFOVERVAL) {
7567203945Sweongyo			switch (lpd) {
7568203945Sweongyo			case BWN_LPD(0, 1, 1):
7569203945Sweongyo				return (0x8fb2);
7570203945Sweongyo			case BWN_LPD(0, 0, 1):
7571203945Sweongyo				return (0x80b2);
7572203945Sweongyo			case BWN_LPD(1, 0, 1):
7573203945Sweongyo				return (0x20b2);
7574203945Sweongyo			case BWN_LPD(1, 0, 0):
7575203945Sweongyo				return (0x20b3);
7576203945Sweongyo			}
7577203945Sweongyo			KASSERT(0 == 1,
7578203945Sweongyo			    ("%s:%d: fail", __func__, __LINE__));
7579203945Sweongyo		}
7580203945Sweongyo		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7581203945Sweongyo	}
7582203945Sweongyo	return (0);
7583203945Sweongyo}
7584203945Sweongyo
7585203945Sweongyostatic void
7586203945Sweongyobwn_spu_workaround(struct bwn_mac *mac, uint8_t channel)
7587203945Sweongyo{
7588203945Sweongyo
7589203945Sweongyo	if (mac->mac_phy.rf_ver != 0x2050 || mac->mac_phy.rf_rev >= 6)
7590203945Sweongyo		return;
7591203945Sweongyo	BWN_WRITE_2(mac, BWN_CHANNEL, (channel <= 10) ?
7592203945Sweongyo	    bwn_phy_g_chan2freq(channel + 4) : bwn_phy_g_chan2freq(1));
7593203945Sweongyo	DELAY(1000);
7594203945Sweongyo	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7595203945Sweongyo}
7596203945Sweongyo
7597203945Sweongyostatic int
7598203945Sweongyobwn_fw_gets(struct bwn_mac *mac, enum bwn_fwtype type)
7599203945Sweongyo{
7600203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
7601203945Sweongyo	struct bwn_fw *fw = &mac->mac_fw;
7602204922Sweongyo	const uint8_t rev = siba_get_revid(sc->sc_dev);
7603203945Sweongyo	const char *filename;
7604203945Sweongyo	uint32_t high;
7605203945Sweongyo	int error;
7606203945Sweongyo
7607203945Sweongyo	/* microcode */
7608203945Sweongyo	if (rev >= 5 && rev <= 10)
7609203945Sweongyo		filename = "ucode5";
7610203945Sweongyo	else if (rev >= 11 && rev <= 12)
7611203945Sweongyo		filename = "ucode11";
7612203945Sweongyo	else if (rev == 13)
7613203945Sweongyo		filename = "ucode13";
7614203945Sweongyo	else if (rev == 14)
7615203945Sweongyo		filename = "ucode14";
7616203945Sweongyo	else if (rev >= 15)
7617203945Sweongyo		filename = "ucode15";
7618203945Sweongyo	else {
7619203945Sweongyo		device_printf(sc->sc_dev, "no ucode for rev %d\n", rev);
7620203945Sweongyo		bwn_release_firmware(mac);
7621203945Sweongyo		return (EOPNOTSUPP);
7622203945Sweongyo	}
7623203945Sweongyo	error = bwn_fw_get(mac, type, filename, &fw->ucode);
7624203945Sweongyo	if (error) {
7625203945Sweongyo		bwn_release_firmware(mac);
7626203945Sweongyo		return (error);
7627203945Sweongyo	}
7628203945Sweongyo
7629203945Sweongyo	/* PCM */
7630203945Sweongyo	KASSERT(fw->no_pcmfile == 0, ("%s:%d fail", __func__, __LINE__));
7631203945Sweongyo	if (rev >= 5 && rev <= 10) {
7632203945Sweongyo		error = bwn_fw_get(mac, type, "pcm5", &fw->pcm);
7633203945Sweongyo		if (error == ENOENT)
7634203945Sweongyo			fw->no_pcmfile = 1;
7635203945Sweongyo		else if (error) {
7636203945Sweongyo			bwn_release_firmware(mac);
7637203945Sweongyo			return (error);
7638203945Sweongyo		}
7639203945Sweongyo	} else if (rev < 11) {
7640203945Sweongyo		device_printf(sc->sc_dev, "no PCM for rev %d\n", rev);
7641203945Sweongyo		return (EOPNOTSUPP);
7642203945Sweongyo	}
7643203945Sweongyo
7644203945Sweongyo	/* initvals */
7645204922Sweongyo	high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH);
7646203945Sweongyo	switch (mac->mac_phy.type) {
7647203945Sweongyo	case BWN_PHYTYPE_A:
7648203945Sweongyo		if (rev < 5 || rev > 10)
7649203945Sweongyo			goto fail1;
7650203945Sweongyo		if (high & BWN_TGSHIGH_HAVE_2GHZ)
7651203945Sweongyo			filename = "a0g1initvals5";
7652203945Sweongyo		else
7653203945Sweongyo			filename = "a0g0initvals5";
7654203945Sweongyo		break;
7655203945Sweongyo	case BWN_PHYTYPE_G:
7656203945Sweongyo		if (rev >= 5 && rev <= 10)
7657203945Sweongyo			filename = "b0g0initvals5";
7658203945Sweongyo		else if (rev >= 13)
7659203945Sweongyo			filename = "b0g0initvals13";
7660203945Sweongyo		else
7661203945Sweongyo			goto fail1;
7662203945Sweongyo		break;
7663203945Sweongyo	case BWN_PHYTYPE_LP:
7664203945Sweongyo		if (rev == 13)
7665203945Sweongyo			filename = "lp0initvals13";
7666203945Sweongyo		else if (rev == 14)
7667203945Sweongyo			filename = "lp0initvals14";
7668203945Sweongyo		else if (rev >= 15)
7669203945Sweongyo			filename = "lp0initvals15";
7670203945Sweongyo		else
7671203945Sweongyo			goto fail1;
7672203945Sweongyo		break;
7673203945Sweongyo	case BWN_PHYTYPE_N:
7674203945Sweongyo		if (rev >= 11 && rev <= 12)
7675203945Sweongyo			filename = "n0initvals11";
7676203945Sweongyo		else
7677203945Sweongyo			goto fail1;
7678203945Sweongyo		break;
7679203945Sweongyo	default:
7680203945Sweongyo		goto fail1;
7681203945Sweongyo	}
7682203945Sweongyo	error = bwn_fw_get(mac, type, filename, &fw->initvals);
7683203945Sweongyo	if (error) {
7684203945Sweongyo		bwn_release_firmware(mac);
7685203945Sweongyo		return (error);
7686203945Sweongyo	}
7687203945Sweongyo
7688203945Sweongyo	/* bandswitch initvals */
7689203945Sweongyo	switch (mac->mac_phy.type) {
7690203945Sweongyo	case BWN_PHYTYPE_A:
7691203945Sweongyo		if (rev >= 5 && rev <= 10) {
7692203945Sweongyo			if (high & BWN_TGSHIGH_HAVE_2GHZ)
7693203945Sweongyo				filename = "a0g1bsinitvals5";
7694203945Sweongyo			else
7695203945Sweongyo				filename = "a0g0bsinitvals5";
7696203945Sweongyo		} else if (rev >= 11)
7697203945Sweongyo			filename = NULL;
7698203945Sweongyo		else
7699203945Sweongyo			goto fail1;
7700203945Sweongyo		break;
7701203945Sweongyo	case BWN_PHYTYPE_G:
7702203945Sweongyo		if (rev >= 5 && rev <= 10)
7703203945Sweongyo			filename = "b0g0bsinitvals5";
7704203945Sweongyo		else if (rev >= 11)
7705203945Sweongyo			filename = NULL;
7706203945Sweongyo		else
7707203945Sweongyo			goto fail1;
7708203945Sweongyo		break;
7709203945Sweongyo	case BWN_PHYTYPE_LP:
7710203945Sweongyo		if (rev == 13)
7711203945Sweongyo			filename = "lp0bsinitvals13";
7712203945Sweongyo		else if (rev == 14)
7713203945Sweongyo			filename = "lp0bsinitvals14";
7714203945Sweongyo		else if (rev >= 15)
7715203945Sweongyo			filename = "lp0bsinitvals15";
7716203945Sweongyo		else
7717203945Sweongyo			goto fail1;
7718203945Sweongyo		break;
7719203945Sweongyo	case BWN_PHYTYPE_N:
7720203945Sweongyo		if (rev >= 11 && rev <= 12)
7721203945Sweongyo			filename = "n0bsinitvals11";
7722203945Sweongyo		else
7723203945Sweongyo			goto fail1;
7724203945Sweongyo		break;
7725203945Sweongyo	default:
7726203945Sweongyo		goto fail1;
7727203945Sweongyo	}
7728203945Sweongyo	error = bwn_fw_get(mac, type, filename, &fw->initvals_band);
7729203945Sweongyo	if (error) {
7730203945Sweongyo		bwn_release_firmware(mac);
7731203945Sweongyo		return (error);
7732203945Sweongyo	}
7733203945Sweongyo	return (0);
7734203945Sweongyofail1:
7735203945Sweongyo	device_printf(sc->sc_dev, "no INITVALS for rev %d\n", rev);
7736203945Sweongyo	bwn_release_firmware(mac);
7737203945Sweongyo	return (EOPNOTSUPP);
7738203945Sweongyo}
7739203945Sweongyo
7740203945Sweongyostatic int
7741203945Sweongyobwn_fw_get(struct bwn_mac *mac, enum bwn_fwtype type,
7742203945Sweongyo    const char *name, struct bwn_fwfile *bfw)
7743203945Sweongyo{
7744203945Sweongyo	const struct bwn_fwhdr *hdr;
7745203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
7746203945Sweongyo	const struct firmware *fw;
7747203945Sweongyo	char namebuf[64];
7748203945Sweongyo
7749203945Sweongyo	if (name == NULL) {
7750203945Sweongyo		bwn_do_release_fw(bfw);
7751203945Sweongyo		return (0);
7752203945Sweongyo	}
7753203945Sweongyo	if (bfw->filename != NULL) {
7754203945Sweongyo		if (bfw->type == type && (strcmp(bfw->filename, name) == 0))
7755203945Sweongyo			return (0);
7756203945Sweongyo		bwn_do_release_fw(bfw);
7757203945Sweongyo	}
7758203945Sweongyo
7759204437Sweongyo	snprintf(namebuf, sizeof(namebuf), "bwn%s_v4_%s%s",
7760204437Sweongyo	    (type == BWN_FWTYPE_OPENSOURCE) ? "-open" : "",
7761204437Sweongyo	    (mac->mac_phy.type == BWN_PHYTYPE_LP) ? "lp_" : "", name);
7762203945Sweongyo	/* XXX Sleeping on "fwload" with the non-sleepable locks held */
7763203945Sweongyo	fw = firmware_get(namebuf);
7764203945Sweongyo	if (fw == NULL) {
7765203945Sweongyo		device_printf(sc->sc_dev, "the fw file(%s) not found\n",
7766203945Sweongyo		    namebuf);
7767203945Sweongyo		return (ENOENT);
7768203945Sweongyo	}
7769203945Sweongyo	if (fw->datasize < sizeof(struct bwn_fwhdr))
7770203945Sweongyo		goto fail;
7771203945Sweongyo	hdr = (const struct bwn_fwhdr *)(fw->data);
7772203945Sweongyo	switch (hdr->type) {
7773203945Sweongyo	case BWN_FWTYPE_UCODE:
7774203945Sweongyo	case BWN_FWTYPE_PCM:
7775203945Sweongyo		if (be32toh(hdr->size) !=
7776203945Sweongyo		    (fw->datasize - sizeof(struct bwn_fwhdr)))
7777203945Sweongyo			goto fail;
7778203945Sweongyo		/* FALLTHROUGH */
7779203945Sweongyo	case BWN_FWTYPE_IV:
7780203945Sweongyo		if (hdr->ver != 1)
7781203945Sweongyo			goto fail;
7782203945Sweongyo		break;
7783203945Sweongyo	default:
7784203945Sweongyo		goto fail;
7785203945Sweongyo	}
7786203945Sweongyo	bfw->filename = name;
7787203945Sweongyo	bfw->fw = fw;
7788203945Sweongyo	bfw->type = type;
7789203945Sweongyo	return (0);
7790203945Sweongyofail:
7791203945Sweongyo	device_printf(sc->sc_dev, "the fw file(%s) format error\n", namebuf);
7792203945Sweongyo	if (fw != NULL)
7793203945Sweongyo		firmware_put(fw, FIRMWARE_UNLOAD);
7794203945Sweongyo	return (EPROTO);
7795203945Sweongyo}
7796203945Sweongyo
7797203945Sweongyostatic void
7798203945Sweongyobwn_release_firmware(struct bwn_mac *mac)
7799203945Sweongyo{
7800203945Sweongyo
7801203945Sweongyo	bwn_do_release_fw(&mac->mac_fw.ucode);
7802203945Sweongyo	bwn_do_release_fw(&mac->mac_fw.pcm);
7803203945Sweongyo	bwn_do_release_fw(&mac->mac_fw.initvals);
7804203945Sweongyo	bwn_do_release_fw(&mac->mac_fw.initvals_band);
7805203945Sweongyo}
7806203945Sweongyo
7807203945Sweongyostatic void
7808203945Sweongyobwn_do_release_fw(struct bwn_fwfile *bfw)
7809203945Sweongyo{
7810203945Sweongyo
7811203945Sweongyo	if (bfw->fw != NULL)
7812203945Sweongyo		firmware_put(bfw->fw, FIRMWARE_UNLOAD);
7813203945Sweongyo	bfw->fw = NULL;
7814203945Sweongyo	bfw->filename = NULL;
7815203945Sweongyo}
7816203945Sweongyo
7817203945Sweongyostatic int
7818203945Sweongyobwn_fw_loaducode(struct bwn_mac *mac)
7819203945Sweongyo{
7820203945Sweongyo#define	GETFWOFFSET(fwp, offset)	\
7821203945Sweongyo	((const uint32_t *)((const char *)fwp.fw->data + offset))
7822203945Sweongyo#define	GETFWSIZE(fwp, offset)	\
7823203945Sweongyo	((fwp.fw->datasize - offset) / sizeof(uint32_t))
7824203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
7825203945Sweongyo	const uint32_t *data;
7826203945Sweongyo	unsigned int i;
7827203945Sweongyo	uint32_t ctl;
7828203945Sweongyo	uint16_t date, fwcaps, time;
7829203945Sweongyo	int error = 0;
7830203945Sweongyo
7831203945Sweongyo	ctl = BWN_READ_4(mac, BWN_MACCTL);
7832203945Sweongyo	ctl |= BWN_MACCTL_MCODE_JMP0;
7833203945Sweongyo	KASSERT(!(ctl & BWN_MACCTL_MCODE_RUN), ("%s:%d: fail", __func__,
7834203945Sweongyo	    __LINE__));
7835203945Sweongyo	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
7836203945Sweongyo	for (i = 0; i < 64; i++)
7837203945Sweongyo		bwn_shm_write_2(mac, BWN_SCRATCH, i, 0);
7838203945Sweongyo	for (i = 0; i < 4096; i += 2)
7839203945Sweongyo		bwn_shm_write_2(mac, BWN_SHARED, i, 0);
7840203945Sweongyo
7841203945Sweongyo	data = GETFWOFFSET(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7842203945Sweongyo	bwn_shm_ctlword(mac, BWN_UCODE | BWN_SHARED_AUTOINC, 0x0000);
7843203945Sweongyo	for (i = 0; i < GETFWSIZE(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7844203945Sweongyo	     i++) {
7845203945Sweongyo		BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7846203945Sweongyo		DELAY(10);
7847203945Sweongyo	}
7848203945Sweongyo
7849203945Sweongyo	if (mac->mac_fw.pcm.fw) {
7850203945Sweongyo		data = GETFWOFFSET(mac->mac_fw.pcm, sizeof(struct bwn_fwhdr));
7851203945Sweongyo		bwn_shm_ctlword(mac, BWN_HW, 0x01ea);
7852203945Sweongyo		BWN_WRITE_4(mac, BWN_SHM_DATA, 0x00004000);
7853203945Sweongyo		bwn_shm_ctlword(mac, BWN_HW, 0x01eb);
7854203945Sweongyo		for (i = 0; i < GETFWSIZE(mac->mac_fw.pcm,
7855203945Sweongyo		    sizeof(struct bwn_fwhdr)); i++) {
7856203945Sweongyo			BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7857203945Sweongyo			DELAY(10);
7858203945Sweongyo		}
7859203945Sweongyo	}
7860203945Sweongyo
7861203945Sweongyo	BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_ALL);
7862203945Sweongyo	BWN_WRITE_4(mac, BWN_MACCTL,
7863203945Sweongyo	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_JMP0) |
7864203945Sweongyo	    BWN_MACCTL_MCODE_RUN);
7865203945Sweongyo
7866203945Sweongyo	for (i = 0; i < 21; i++) {
7867203945Sweongyo		if (BWN_READ_4(mac, BWN_INTR_REASON) == BWN_INTR_MAC_SUSPENDED)
7868203945Sweongyo			break;
7869203945Sweongyo		if (i >= 20) {
7870203945Sweongyo			device_printf(sc->sc_dev, "ucode timeout\n");
7871203945Sweongyo			error = ENXIO;
7872203945Sweongyo			goto error;
7873203945Sweongyo		}
7874203945Sweongyo		DELAY(50000);
7875203945Sweongyo	}
7876203945Sweongyo	BWN_READ_4(mac, BWN_INTR_REASON);
7877203945Sweongyo
7878203945Sweongyo	mac->mac_fw.rev = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_REV);
7879203945Sweongyo	if (mac->mac_fw.rev <= 0x128) {
7880203945Sweongyo		device_printf(sc->sc_dev, "the firmware is too old\n");
7881203945Sweongyo		error = EOPNOTSUPP;
7882203945Sweongyo		goto error;
7883203945Sweongyo	}
7884203945Sweongyo	mac->mac_fw.patch = bwn_shm_read_2(mac, BWN_SHARED,
7885203945Sweongyo	    BWN_SHARED_UCODE_PATCH);
7886203945Sweongyo	date = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_DATE);
7887203945Sweongyo	mac->mac_fw.opensource = (date == 0xffff);
7888203945Sweongyo	if (bwn_wme != 0)
7889203945Sweongyo		mac->mac_flags |= BWN_MAC_FLAG_WME;
7890203945Sweongyo	mac->mac_flags |= BWN_MAC_FLAG_HWCRYPTO;
7891203945Sweongyo
7892203945Sweongyo	time = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_TIME);
7893203945Sweongyo	if (mac->mac_fw.opensource == 0) {
7894203945Sweongyo		device_printf(sc->sc_dev,
7895203945Sweongyo		    "firmware version (rev %u patch %u date %#x time %#x)\n",
7896203945Sweongyo		    mac->mac_fw.rev, mac->mac_fw.patch, date, time);
7897203945Sweongyo		if (mac->mac_fw.no_pcmfile)
7898203945Sweongyo			device_printf(sc->sc_dev,
7899203945Sweongyo			    "no HW crypto acceleration due to pcm5\n");
7900203945Sweongyo	} else {
7901203945Sweongyo		mac->mac_fw.patch = time;
7902203945Sweongyo		fwcaps = bwn_fwcaps_read(mac);
7903203945Sweongyo		if (!(fwcaps & BWN_FWCAPS_HWCRYPTO) || mac->mac_fw.no_pcmfile) {
7904203945Sweongyo			device_printf(sc->sc_dev,
7905203945Sweongyo			    "disabling HW crypto acceleration\n");
7906203945Sweongyo			mac->mac_flags &= ~BWN_MAC_FLAG_HWCRYPTO;
7907203945Sweongyo		}
7908203945Sweongyo		if (!(fwcaps & BWN_FWCAPS_WME)) {
7909203945Sweongyo			device_printf(sc->sc_dev, "disabling WME support\n");
7910203945Sweongyo			mac->mac_flags &= ~BWN_MAC_FLAG_WME;
7911203945Sweongyo		}
7912203945Sweongyo	}
7913203945Sweongyo
7914203945Sweongyo	if (BWN_ISOLDFMT(mac))
7915203945Sweongyo		device_printf(sc->sc_dev, "using old firmware image\n");
7916203945Sweongyo
7917203945Sweongyo	return (0);
7918203945Sweongyo
7919203945Sweongyoerror:
7920203945Sweongyo	BWN_WRITE_4(mac, BWN_MACCTL,
7921203945Sweongyo	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_RUN) |
7922203945Sweongyo	    BWN_MACCTL_MCODE_JMP0);
7923203945Sweongyo
7924203945Sweongyo	return (error);
7925203945Sweongyo#undef GETFWSIZE
7926203945Sweongyo#undef GETFWOFFSET
7927203945Sweongyo}
7928203945Sweongyo
7929203945Sweongyo/* OpenFirmware only */
7930203945Sweongyostatic uint16_t
7931203945Sweongyobwn_fwcaps_read(struct bwn_mac *mac)
7932203945Sweongyo{
7933203945Sweongyo
7934203945Sweongyo	KASSERT(mac->mac_fw.opensource == 1,
7935203945Sweongyo	    ("%s:%d: fail", __func__, __LINE__));
7936203945Sweongyo	return (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_FWCAPS));
7937203945Sweongyo}
7938203945Sweongyo
7939203945Sweongyostatic int
7940203945Sweongyobwn_fwinitvals_write(struct bwn_mac *mac, const struct bwn_fwinitvals *ivals,
7941203945Sweongyo    size_t count, size_t array_size)
7942203945Sweongyo{
7943203945Sweongyo#define	GET_NEXTIV16(iv)						\
7944203945Sweongyo	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
7945203945Sweongyo	    sizeof(uint16_t) + sizeof(uint16_t)))
7946203945Sweongyo#define	GET_NEXTIV32(iv)						\
7947203945Sweongyo	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
7948203945Sweongyo	    sizeof(uint16_t) + sizeof(uint32_t)))
7949203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
7950203945Sweongyo	const struct bwn_fwinitvals *iv;
7951203945Sweongyo	uint16_t offset;
7952203945Sweongyo	size_t i;
7953203945Sweongyo	uint8_t bit32;
7954203945Sweongyo
7955203945Sweongyo	KASSERT(sizeof(struct bwn_fwinitvals) == 6,
7956203945Sweongyo	    ("%s:%d: fail", __func__, __LINE__));
7957203945Sweongyo	iv = ivals;
7958203945Sweongyo	for (i = 0; i < count; i++) {
7959203945Sweongyo		if (array_size < sizeof(iv->offset_size))
7960203945Sweongyo			goto fail;
7961203945Sweongyo		array_size -= sizeof(iv->offset_size);
7962203945Sweongyo		offset = be16toh(iv->offset_size);
7963203945Sweongyo		bit32 = (offset & BWN_FWINITVALS_32BIT) ? 1 : 0;
7964203945Sweongyo		offset &= BWN_FWINITVALS_OFFSET_MASK;
7965203945Sweongyo		if (offset >= 0x1000)
7966203945Sweongyo			goto fail;
7967203945Sweongyo		if (bit32) {
7968203945Sweongyo			if (array_size < sizeof(iv->data.d32))
7969203945Sweongyo				goto fail;
7970203945Sweongyo			array_size -= sizeof(iv->data.d32);
7971203945Sweongyo			BWN_WRITE_4(mac, offset, be32toh(iv->data.d32));
7972203945Sweongyo			iv = GET_NEXTIV32(iv);
7973203945Sweongyo		} else {
7974203945Sweongyo
7975203945Sweongyo			if (array_size < sizeof(iv->data.d16))
7976203945Sweongyo				goto fail;
7977203945Sweongyo			array_size -= sizeof(iv->data.d16);
7978203945Sweongyo			BWN_WRITE_2(mac, offset, be16toh(iv->data.d16));
7979203945Sweongyo
7980203945Sweongyo			iv = GET_NEXTIV16(iv);
7981203945Sweongyo		}
7982203945Sweongyo	}
7983203945Sweongyo	if (array_size != 0)
7984203945Sweongyo		goto fail;
7985203945Sweongyo	return (0);
7986203945Sweongyofail:
7987203945Sweongyo	device_printf(sc->sc_dev, "initvals: invalid format\n");
7988203945Sweongyo	return (EPROTO);
7989203945Sweongyo#undef GET_NEXTIV16
7990203945Sweongyo#undef GET_NEXTIV32
7991203945Sweongyo}
7992203945Sweongyo
7993203945Sweongyostatic int
7994203945Sweongyobwn_switch_channel(struct bwn_mac *mac, int chan)
7995203945Sweongyo{
7996203945Sweongyo	struct bwn_phy *phy = &(mac->mac_phy);
7997203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
7998203945Sweongyo	struct ifnet *ifp = sc->sc_ifp;
7999203945Sweongyo	struct ieee80211com *ic = ifp->if_l2com;
8000203945Sweongyo	uint16_t channelcookie, savedcookie;
8001203945Sweongyo	int error;
8002203945Sweongyo
8003203945Sweongyo	if (chan == 0xffff)
8004203945Sweongyo		chan = phy->get_default_chan(mac);
8005203945Sweongyo
8006203945Sweongyo	channelcookie = chan;
8007203945Sweongyo	if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan))
8008203945Sweongyo		channelcookie |= 0x100;
8009203945Sweongyo	savedcookie = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_CHAN);
8010203945Sweongyo	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, channelcookie);
8011203945Sweongyo	error = phy->switch_channel(mac, chan);
8012203945Sweongyo	if (error)
8013203945Sweongyo		goto fail;
8014203945Sweongyo
8015203945Sweongyo	mac->mac_phy.chan = chan;
8016203945Sweongyo	DELAY(8000);
8017203945Sweongyo	return (0);
8018203945Sweongyofail:
8019203945Sweongyo	device_printf(sc->sc_dev, "failed to switch channel\n");
8020203945Sweongyo	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, savedcookie);
8021203945Sweongyo	return (error);
8022203945Sweongyo}
8023203945Sweongyo
8024203945Sweongyostatic uint16_t
8025203945Sweongyobwn_ant2phy(int antenna)
8026203945Sweongyo{
8027203945Sweongyo
8028203945Sweongyo	switch (antenna) {
8029203945Sweongyo	case BWN_ANT0:
8030203945Sweongyo		return (BWN_TX_PHY_ANT0);
8031203945Sweongyo	case BWN_ANT1:
8032203945Sweongyo		return (BWN_TX_PHY_ANT1);
8033203945Sweongyo	case BWN_ANT2:
8034203945Sweongyo		return (BWN_TX_PHY_ANT2);
8035203945Sweongyo	case BWN_ANT3:
8036203945Sweongyo		return (BWN_TX_PHY_ANT3);
8037203945Sweongyo	case BWN_ANTAUTO:
8038203945Sweongyo		return (BWN_TX_PHY_ANT01AUTO);
8039203945Sweongyo	}
8040203945Sweongyo	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8041203945Sweongyo	return (0);
8042203945Sweongyo}
8043203945Sweongyo
8044203945Sweongyostatic void
8045203945Sweongyobwn_wme_load(struct bwn_mac *mac)
8046203945Sweongyo{
8047203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
8048203945Sweongyo	int i;
8049203945Sweongyo
8050203945Sweongyo	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
8051203945Sweongyo	    ("%s:%d: fail", __func__, __LINE__));
8052203945Sweongyo
8053203945Sweongyo	bwn_mac_suspend(mac);
8054203945Sweongyo	for (i = 0; i < N(sc->sc_wmeParams); i++)
8055203945Sweongyo		bwn_wme_loadparams(mac, &(sc->sc_wmeParams[i]),
8056203945Sweongyo		    bwn_wme_shm_offsets[i]);
8057203945Sweongyo	bwn_mac_enable(mac);
8058203945Sweongyo}
8059203945Sweongyo
8060203945Sweongyostatic void
8061203945Sweongyobwn_wme_loadparams(struct bwn_mac *mac,
8062203945Sweongyo    const struct wmeParams *p, uint16_t shm_offset)
8063203945Sweongyo{
8064203945Sweongyo#define	SM(_v, _f)      (((_v) << _f##_S) & _f)
8065203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
8066203945Sweongyo	uint16_t params[BWN_NR_WMEPARAMS];
8067203945Sweongyo	int slot, tmp;
8068203945Sweongyo	unsigned int i;
8069203945Sweongyo
8070203945Sweongyo	slot = BWN_READ_2(mac, BWN_RNG) &
8071203945Sweongyo	    SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8072203945Sweongyo
8073203945Sweongyo	memset(&params, 0, sizeof(params));
8074203945Sweongyo
8075203945Sweongyo	DPRINTF(sc, BWN_DEBUG_WME, "wmep_txopLimit %d wmep_logcwmin %d "
8076203945Sweongyo	    "wmep_logcwmax %d wmep_aifsn %d\n", p->wmep_txopLimit,
8077203945Sweongyo	    p->wmep_logcwmin, p->wmep_logcwmax, p->wmep_aifsn);
8078203945Sweongyo
8079203945Sweongyo	params[BWN_WMEPARAM_TXOP] = p->wmep_txopLimit * 32;
8080203945Sweongyo	params[BWN_WMEPARAM_CWMIN] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8081203945Sweongyo	params[BWN_WMEPARAM_CWMAX] = SM(p->wmep_logcwmax, WME_PARAM_LOGCWMAX);
8082203945Sweongyo	params[BWN_WMEPARAM_CWCUR] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8083203945Sweongyo	params[BWN_WMEPARAM_AIFS] = p->wmep_aifsn;
8084203945Sweongyo	params[BWN_WMEPARAM_BSLOTS] = slot;
8085203945Sweongyo	params[BWN_WMEPARAM_REGGAP] = slot + p->wmep_aifsn;
8086203945Sweongyo
8087203945Sweongyo	for (i = 0; i < N(params); i++) {
8088203945Sweongyo		if (i == BWN_WMEPARAM_STATUS) {
8089203945Sweongyo			tmp = bwn_shm_read_2(mac, BWN_SHARED,
8090203945Sweongyo			    shm_offset + (i * 2));
8091203945Sweongyo			tmp |= 0x100;
8092203945Sweongyo			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
8093203945Sweongyo			    tmp);
8094203945Sweongyo		} else {
8095203945Sweongyo			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
8096203945Sweongyo			    params[i]);
8097203945Sweongyo		}
8098203945Sweongyo	}
8099203945Sweongyo}
8100203945Sweongyo
8101203945Sweongyostatic void
8102203945Sweongyobwn_mac_write_bssid(struct bwn_mac *mac)
8103203945Sweongyo{
8104203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
8105203945Sweongyo	uint32_t tmp;
8106203945Sweongyo	int i;
8107203945Sweongyo	uint8_t mac_bssid[IEEE80211_ADDR_LEN * 2];
8108203945Sweongyo
8109203945Sweongyo	bwn_mac_setfilter(mac, BWN_MACFILTER_BSSID, sc->sc_bssid);
8110203945Sweongyo	memcpy(mac_bssid, sc->sc_macaddr, IEEE80211_ADDR_LEN);
8111203945Sweongyo	memcpy(mac_bssid + IEEE80211_ADDR_LEN, sc->sc_bssid,
8112203945Sweongyo	    IEEE80211_ADDR_LEN);
8113203945Sweongyo
8114203945Sweongyo	for (i = 0; i < N(mac_bssid); i += sizeof(uint32_t)) {
8115203945Sweongyo		tmp = (uint32_t) (mac_bssid[i + 0]);
8116203945Sweongyo		tmp |= (uint32_t) (mac_bssid[i + 1]) << 8;
8117203945Sweongyo		tmp |= (uint32_t) (mac_bssid[i + 2]) << 16;
8118203945Sweongyo		tmp |= (uint32_t) (mac_bssid[i + 3]) << 24;
8119203945Sweongyo		bwn_ram_write(mac, 0x20 + i, tmp);
8120203945Sweongyo	}
8121203945Sweongyo}
8122203945Sweongyo
8123203945Sweongyostatic void
8124203945Sweongyobwn_mac_setfilter(struct bwn_mac *mac, uint16_t offset,
8125203945Sweongyo    const uint8_t *macaddr)
8126203945Sweongyo{
8127203945Sweongyo	static const uint8_t zero[IEEE80211_ADDR_LEN] = { 0 };
8128203945Sweongyo	uint16_t data;
8129203945Sweongyo
8130203945Sweongyo	if (!mac)
8131203945Sweongyo		macaddr = zero;
8132203945Sweongyo
8133203945Sweongyo	offset |= 0x0020;
8134203945Sweongyo	BWN_WRITE_2(mac, BWN_MACFILTER_CONTROL, offset);
8135203945Sweongyo
8136203945Sweongyo	data = macaddr[0];
8137203945Sweongyo	data |= macaddr[1] << 8;
8138203945Sweongyo	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8139203945Sweongyo	data = macaddr[2];
8140203945Sweongyo	data |= macaddr[3] << 8;
8141203945Sweongyo	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8142203945Sweongyo	data = macaddr[4];
8143203945Sweongyo	data |= macaddr[5] << 8;
8144203945Sweongyo	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8145203945Sweongyo}
8146203945Sweongyo
8147203945Sweongyostatic void
8148203945Sweongyobwn_key_dowrite(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8149203945Sweongyo    const uint8_t *key, size_t key_len, const uint8_t *mac_addr)
8150203945Sweongyo{
8151203945Sweongyo	uint8_t buf[BWN_SEC_KEYSIZE] = { 0, };
8152203945Sweongyo	uint8_t per_sta_keys_start = 8;
8153203945Sweongyo
8154203945Sweongyo	if (BWN_SEC_NEWAPI(mac))
8155203945Sweongyo		per_sta_keys_start = 4;
8156203945Sweongyo
8157203945Sweongyo	KASSERT(index < mac->mac_max_nr_keys,
8158203945Sweongyo	    ("%s:%d: fail", __func__, __LINE__));
8159203945Sweongyo	KASSERT(key_len <= BWN_SEC_KEYSIZE,
8160203945Sweongyo	    ("%s:%d: fail", __func__, __LINE__));
8161203945Sweongyo
8162203945Sweongyo	if (index >= per_sta_keys_start)
8163203945Sweongyo		bwn_key_macwrite(mac, index, NULL);
8164203945Sweongyo	if (key)
8165203945Sweongyo		memcpy(buf, key, key_len);
8166203945Sweongyo	bwn_key_write(mac, index, algorithm, buf);
8167203945Sweongyo	if (index >= per_sta_keys_start)
8168203945Sweongyo		bwn_key_macwrite(mac, index, mac_addr);
8169203945Sweongyo
8170203945Sweongyo	mac->mac_key[index].algorithm = algorithm;
8171203945Sweongyo}
8172203945Sweongyo
8173203945Sweongyostatic void
8174203945Sweongyobwn_key_macwrite(struct bwn_mac *mac, uint8_t index, const uint8_t *addr)
8175203945Sweongyo{
8176204922Sweongyo	struct bwn_softc *sc = mac->mac_sc;
8177203945Sweongyo	uint32_t addrtmp[2] = { 0, 0 };
8178203945Sweongyo	uint8_t start = 8;
8179203945Sweongyo
8180203945Sweongyo	if (BWN_SEC_NEWAPI(mac))
8181203945Sweongyo		start = 4;
8182203945Sweongyo
8183203945Sweongyo	KASSERT(index >= start,
8184203945Sweongyo	    ("%s:%d: fail", __func__, __LINE__));
8185203945Sweongyo	index -= start;
8186203945Sweongyo
8187203945Sweongyo	if (addr) {
8188203945Sweongyo		addrtmp[0] = addr[0];
8189203945Sweongyo		addrtmp[0] |= ((uint32_t) (addr[1]) << 8);
8190203945Sweongyo		addrtmp[0] |= ((uint32_t) (addr[2]) << 16);
8191203945Sweongyo		addrtmp[0] |= ((uint32_t) (addr[3]) << 24);
8192203945Sweongyo		addrtmp[1] = addr[4];
8193203945Sweongyo		addrtmp[1] |= ((uint32_t) (addr[5]) << 8);
8194203945Sweongyo	}
8195203945Sweongyo
8196204922Sweongyo	if (siba_get_revid(sc->sc_dev) >= 5) {
8197203945Sweongyo		bwn_shm_write_4(mac, BWN_RCMTA, (index * 2) + 0, addrtmp[0]);
8198203945Sweongyo		bwn_shm_write_2(mac, BWN_RCMTA, (index * 2) + 1, addrtmp[1]);
8199203945Sweongyo	} else {
8200203945Sweongyo		if (index >= 8) {
8201203945Sweongyo			bwn_shm_write_4(mac, BWN_SHARED,
8202203945Sweongyo			    BWN_SHARED_PSM + (index * 6) + 0, addrtmp[0]);
8203203945Sweongyo			bwn_shm_write_2(mac, BWN_SHARED,
8204203945Sweongyo			    BWN_SHARED_PSM + (index * 6) + 4, addrtmp[1]);
8205203945Sweongyo		}
8206203945Sweongyo	}
8207203945Sweongyo}
8208203945Sweongyo
8209203945Sweongyostatic void
8210203945Sweongyobwn_key_write(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8211203945Sweongyo    const uint8_t *key)
8212203945Sweongyo{
8213203945Sweongyo	unsigned int i;
8214203945Sweongyo	uint32_t offset;
8215203945Sweongyo	uint16_t kidx, value;
8216203945Sweongyo
8217203945Sweongyo	kidx = BWN_SEC_KEY2FW(mac, index);
8218203945Sweongyo	bwn_shm_write_2(mac, BWN_SHARED,
8219203945Sweongyo	    BWN_SHARED_KEYIDX_BLOCK + (kidx * 2), (kidx << 4) | algorithm);
8220203945Sweongyo
8221203945Sweongyo	offset = mac->mac_ktp + (index * BWN_SEC_KEYSIZE);
8222203945Sweongyo	for (i = 0; i < BWN_SEC_KEYSIZE; i += 2) {
8223203945Sweongyo		value = key[i];
8224203945Sweongyo		value |= (uint16_t)(key[i + 1]) << 8;
8225203945Sweongyo		bwn_shm_write_2(mac, BWN_SHARED, offset + i, value);
8226203945Sweongyo	}
8227203945Sweongyo}
8228203945Sweongyo
8229203945Sweongyostatic void
8230203945Sweongyobwn_phy_exit(struct bwn_mac *mac)
8231203945Sweongyo{
8232203945Sweongyo
8233203945Sweongyo	mac->mac_phy.rf_onoff(mac, 0);
8234203945Sweongyo	if (mac->mac_phy.exit != NULL)
8235203945Sweongyo		mac->mac_phy.exit(mac);
8236203945Sweongyo}
8237203945Sweongyo
8238203945Sweongyostatic void
8239203945Sweongyobwn_dma_free(struct bwn_mac *mac)
8240203945Sweongyo{
8241203945Sweongyo	struct bwn_dma *dma;
8242203945Sweongyo
8243203945Sweongyo	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
8244203945Sweongyo		return;
8245203945Sweongyo	dma = &mac->mac_method.dma;
8246203945Sweongyo
8247203945Sweongyo	bwn_dma_ringfree(&dma->rx);
8248203945Sweongyo	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
8249203945Sweongyo	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
8250203945Sweongyo	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
8251203945Sweongyo	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
8252203945Sweongyo	bwn_dma_ringfree(&dma->mcast);
8253203945Sweongyo}
8254203945Sweongyo
8255203945Sweongyostatic void
8256203945Sweongyobwn_core_stop(struct bwn_mac *mac)
8257203945Sweongyo{
8258203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
8259203945Sweongyo
8260203945Sweongyo	BWN_ASSERT_LOCKED(sc);
8261203945Sweongyo
8262203945Sweongyo	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8263203945Sweongyo		return;
8264203945Sweongyo
8265203945Sweongyo	callout_stop(&sc->sc_rfswitch_ch);
8266203945Sweongyo	callout_stop(&sc->sc_task_ch);
8267203945Sweongyo	callout_stop(&sc->sc_watchdog_ch);
8268203945Sweongyo	sc->sc_watchdog_timer = 0;
8269203945Sweongyo	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8270203945Sweongyo	BWN_READ_4(mac, BWN_INTR_MASK);
8271203945Sweongyo	bwn_mac_suspend(mac);
8272203945Sweongyo
8273203945Sweongyo	mac->mac_status = BWN_MAC_STATUS_INITED;
8274203945Sweongyo}
8275203945Sweongyo
8276203945Sweongyostatic int
8277203945Sweongyobwn_switch_band(struct bwn_softc *sc, struct ieee80211_channel *chan)
8278203945Sweongyo{
8279203945Sweongyo	struct bwn_mac *up_dev = NULL;
8280203945Sweongyo	struct bwn_mac *down_dev;
8281203945Sweongyo	struct bwn_mac *mac;
8282203945Sweongyo	int err, status;
8283203945Sweongyo	uint8_t gmode;
8284203945Sweongyo
8285203945Sweongyo	BWN_ASSERT_LOCKED(sc);
8286203945Sweongyo
8287203945Sweongyo	TAILQ_FOREACH(mac, &sc->sc_maclist, mac_list) {
8288203945Sweongyo		if (IEEE80211_IS_CHAN_2GHZ(chan) &&
8289203945Sweongyo		    mac->mac_phy.supports_2ghz) {
8290203945Sweongyo			up_dev = mac;
8291203945Sweongyo			gmode = 1;
8292203945Sweongyo		} else if (IEEE80211_IS_CHAN_5GHZ(chan) &&
8293203945Sweongyo		    mac->mac_phy.supports_5ghz) {
8294203945Sweongyo			up_dev = mac;
8295203945Sweongyo			gmode = 0;
8296203945Sweongyo		} else {
8297203945Sweongyo			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8298203945Sweongyo			return (EINVAL);
8299203945Sweongyo		}
8300203945Sweongyo		if (up_dev != NULL)
8301203945Sweongyo			break;
8302203945Sweongyo	}
8303203945Sweongyo	if (up_dev == NULL) {
8304203945Sweongyo		device_printf(sc->sc_dev, "Could not find a device\n");
8305203945Sweongyo		return (ENODEV);
8306203945Sweongyo	}
8307203945Sweongyo	if (up_dev == sc->sc_curmac && sc->sc_curmac->mac_phy.gmode == gmode)
8308203945Sweongyo		return (0);
8309203945Sweongyo
8310203945Sweongyo	device_printf(sc->sc_dev, "switching to %s-GHz band\n",
8311203945Sweongyo	    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8312203945Sweongyo
8313203945Sweongyo	down_dev = sc->sc_curmac;;
8314203945Sweongyo	status = down_dev->mac_status;
8315203945Sweongyo	if (status >= BWN_MAC_STATUS_STARTED)
8316203945Sweongyo		bwn_core_stop(down_dev);
8317203945Sweongyo	if (status >= BWN_MAC_STATUS_INITED)
8318203945Sweongyo		bwn_core_exit(down_dev);
8319203945Sweongyo
8320203945Sweongyo	if (down_dev != up_dev)
8321203945Sweongyo		bwn_phy_reset(down_dev);
8322203945Sweongyo
8323203945Sweongyo	up_dev->mac_phy.gmode = gmode;
8324203945Sweongyo	if (status >= BWN_MAC_STATUS_INITED) {
8325203945Sweongyo		err = bwn_core_init(up_dev);
8326203945Sweongyo		if (err) {
8327203945Sweongyo			device_printf(sc->sc_dev,
8328203945Sweongyo			    "fatal: failed to initialize for %s-GHz\n",
8329203945Sweongyo			    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8330203945Sweongyo			goto fail;
8331203945Sweongyo		}
8332203945Sweongyo	}
8333203945Sweongyo	if (status >= BWN_MAC_STATUS_STARTED)
8334203945Sweongyo		bwn_core_start(up_dev);
8335203945Sweongyo	KASSERT(up_dev->mac_status == status, ("%s: fail", __func__));
8336203945Sweongyo	sc->sc_curmac = up_dev;
8337203945Sweongyo
8338203945Sweongyo	return (0);
8339203945Sweongyofail:
8340203945Sweongyo	sc->sc_curmac = NULL;
8341203945Sweongyo	return (err);
8342203945Sweongyo}
8343203945Sweongyo
8344203945Sweongyostatic void
8345203945Sweongyobwn_rf_turnon(struct bwn_mac *mac)
8346203945Sweongyo{
8347203945Sweongyo
8348203945Sweongyo	bwn_mac_suspend(mac);
8349203945Sweongyo	mac->mac_phy.rf_onoff(mac, 1);
8350203945Sweongyo	mac->mac_phy.rf_on = 1;
8351203945Sweongyo	bwn_mac_enable(mac);
8352203945Sweongyo}
8353203945Sweongyo
8354203945Sweongyostatic void
8355203945Sweongyobwn_rf_turnoff(struct bwn_mac *mac)
8356203945Sweongyo{
8357203945Sweongyo
8358203945Sweongyo	bwn_mac_suspend(mac);
8359203945Sweongyo	mac->mac_phy.rf_onoff(mac, 0);
8360203945Sweongyo	mac->mac_phy.rf_on = 0;
8361203945Sweongyo	bwn_mac_enable(mac);
8362203945Sweongyo}
8363203945Sweongyo
8364203945Sweongyostatic void
8365203945Sweongyobwn_phy_reset(struct bwn_mac *mac)
8366203945Sweongyo{
8367204922Sweongyo	struct bwn_softc *sc = mac->mac_sc;
8368203945Sweongyo
8369204922Sweongyo	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
8370204922Sweongyo	    ((siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~BWN_TGSLOW_SUPPORT_G) |
8371203945Sweongyo	     BWN_TGSLOW_PHYRESET) | SIBA_TGSLOW_FGC);
8372203945Sweongyo	DELAY(1000);
8373204922Sweongyo	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
8374204922Sweongyo	    (siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~SIBA_TGSLOW_FGC) |
8375203945Sweongyo	    BWN_TGSLOW_PHYRESET);
8376203945Sweongyo	DELAY(1000);
8377203945Sweongyo}
8378203945Sweongyo
8379203945Sweongyostatic int
8380203945Sweongyobwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
8381203945Sweongyo{
8382203945Sweongyo	struct bwn_vap *bvp = BWN_VAP(vap);
8383203945Sweongyo	struct ieee80211com *ic= vap->iv_ic;
8384203945Sweongyo	struct ifnet *ifp = ic->ic_ifp;
8385203945Sweongyo	enum ieee80211_state ostate = vap->iv_state;
8386203945Sweongyo	struct bwn_softc *sc = ifp->if_softc;
8387203945Sweongyo	struct bwn_mac *mac = sc->sc_curmac;
8388203945Sweongyo	int error;
8389203945Sweongyo
8390203945Sweongyo	DPRINTF(sc, BWN_DEBUG_STATE, "%s: %s -> %s\n", __func__,
8391203945Sweongyo	    ieee80211_state_name[vap->iv_state],
8392203945Sweongyo	    ieee80211_state_name[nstate]);
8393203945Sweongyo
8394203945Sweongyo	error = bvp->bv_newstate(vap, nstate, arg);
8395203945Sweongyo	if (error != 0)
8396203945Sweongyo		return (error);
8397203945Sweongyo
8398203945Sweongyo	BWN_LOCK(sc);
8399203945Sweongyo
8400203945Sweongyo	bwn_led_newstate(mac, nstate);
8401203945Sweongyo
8402203945Sweongyo	/*
8403203945Sweongyo	 * Clear the BSSID when we stop a STA
8404203945Sweongyo	 */
8405203945Sweongyo	if (vap->iv_opmode == IEEE80211_M_STA) {
8406203945Sweongyo		if (ostate == IEEE80211_S_RUN && nstate != IEEE80211_S_RUN) {
8407203945Sweongyo			/*
8408203945Sweongyo			 * Clear out the BSSID.  If we reassociate to
8409203945Sweongyo			 * the same AP, this will reinialize things
8410203945Sweongyo			 * correctly...
8411203945Sweongyo			 */
8412203945Sweongyo			if (ic->ic_opmode == IEEE80211_M_STA &&
8413203945Sweongyo			    (sc->sc_flags & BWN_FLAG_INVALID) == 0) {
8414203945Sweongyo				memset(sc->sc_bssid, 0, IEEE80211_ADDR_LEN);
8415203945Sweongyo				bwn_set_macaddr(mac);
8416203945Sweongyo			}
8417203945Sweongyo		}
8418203945Sweongyo	}
8419203945Sweongyo
8420204436Sweongyo	if (vap->iv_opmode == IEEE80211_M_MONITOR ||
8421204436Sweongyo	    vap->iv_opmode == IEEE80211_M_AHDEMO) {
8422203945Sweongyo		/* XXX nothing to do? */
8423203945Sweongyo	} else if (nstate == IEEE80211_S_RUN) {
8424203945Sweongyo		memcpy(sc->sc_bssid, vap->iv_bss->ni_bssid, IEEE80211_ADDR_LEN);
8425203945Sweongyo		memcpy(sc->sc_macaddr, IF_LLADDR(ifp), IEEE80211_ADDR_LEN);
8426203945Sweongyo		bwn_set_opmode(mac);
8427203945Sweongyo		bwn_set_pretbtt(mac);
8428203945Sweongyo		bwn_spu_setdelay(mac, 0);
8429203945Sweongyo		bwn_set_macaddr(mac);
8430203945Sweongyo	}
8431203945Sweongyo
8432203945Sweongyo	BWN_UNLOCK(sc);
8433203945Sweongyo
8434203945Sweongyo	return (error);
8435203945Sweongyo}
8436203945Sweongyo
8437203945Sweongyostatic void
8438203945Sweongyobwn_set_pretbtt(struct bwn_mac *mac)
8439203945Sweongyo{
8440203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
8441203945Sweongyo	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8442203945Sweongyo	uint16_t pretbtt;
8443203945Sweongyo
8444203945Sweongyo	if (ic->ic_opmode == IEEE80211_M_IBSS)
8445203945Sweongyo		pretbtt = 2;
8446203945Sweongyo	else
8447203945Sweongyo		pretbtt = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 120 : 250;
8448203945Sweongyo	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PRETBTT, pretbtt);
8449203945Sweongyo	BWN_WRITE_2(mac, BWN_TSF_CFP_PRETBTT, pretbtt);
8450203945Sweongyo}
8451203945Sweongyo
8452203945Sweongyostatic int
8453203945Sweongyobwn_intr(void *arg)
8454203945Sweongyo{
8455203945Sweongyo	struct bwn_mac *mac = arg;
8456203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
8457203945Sweongyo	uint32_t reason;
8458203945Sweongyo
8459204922Sweongyo	if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
8460204922Sweongyo	    (sc->sc_flags & BWN_FLAG_INVALID))
8461203945Sweongyo		return (FILTER_STRAY);
8462203945Sweongyo
8463203945Sweongyo	reason = BWN_READ_4(mac, BWN_INTR_REASON);
8464203945Sweongyo	if (reason == 0xffffffff)	/* shared IRQ */
8465203945Sweongyo		return (FILTER_STRAY);
8466203945Sweongyo	reason &= mac->mac_intr_mask;
8467203945Sweongyo	if (reason == 0)
8468203945Sweongyo		return (FILTER_HANDLED);
8469203945Sweongyo
8470203945Sweongyo	mac->mac_reason[0] = BWN_READ_4(mac, BWN_DMA0_REASON) & 0x0001dc00;
8471203945Sweongyo	mac->mac_reason[1] = BWN_READ_4(mac, BWN_DMA1_REASON) & 0x0000dc00;
8472203945Sweongyo	mac->mac_reason[2] = BWN_READ_4(mac, BWN_DMA2_REASON) & 0x0000dc00;
8473203945Sweongyo	mac->mac_reason[3] = BWN_READ_4(mac, BWN_DMA3_REASON) & 0x0001dc00;
8474203945Sweongyo	mac->mac_reason[4] = BWN_READ_4(mac, BWN_DMA4_REASON) & 0x0000dc00;
8475203945Sweongyo	BWN_WRITE_4(mac, BWN_INTR_REASON, reason);
8476203945Sweongyo	BWN_WRITE_4(mac, BWN_DMA0_REASON, mac->mac_reason[0]);
8477203945Sweongyo	BWN_WRITE_4(mac, BWN_DMA1_REASON, mac->mac_reason[1]);
8478203945Sweongyo	BWN_WRITE_4(mac, BWN_DMA2_REASON, mac->mac_reason[2]);
8479203945Sweongyo	BWN_WRITE_4(mac, BWN_DMA3_REASON, mac->mac_reason[3]);
8480203945Sweongyo	BWN_WRITE_4(mac, BWN_DMA4_REASON, mac->mac_reason[4]);
8481203945Sweongyo
8482203945Sweongyo	/* Disable interrupts. */
8483203945Sweongyo	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8484203945Sweongyo
8485203945Sweongyo	mac->mac_reason_intr = reason;
8486203945Sweongyo
8487203945Sweongyo	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8488203945Sweongyo	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8489203945Sweongyo
8490203945Sweongyo	taskqueue_enqueue_fast(sc->sc_tq, &mac->mac_intrtask);
8491203945Sweongyo	return (FILTER_HANDLED);
8492203945Sweongyo}
8493203945Sweongyo
8494203945Sweongyostatic void
8495203945Sweongyobwn_intrtask(void *arg, int npending)
8496203945Sweongyo{
8497203945Sweongyo	struct bwn_mac *mac = arg;
8498203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
8499203945Sweongyo	struct ifnet *ifp = sc->sc_ifp;
8500203945Sweongyo	uint32_t merged = 0;
8501203945Sweongyo	int i, tx = 0, rx = 0;
8502203945Sweongyo
8503203945Sweongyo	BWN_LOCK(sc);
8504204922Sweongyo	if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
8505204922Sweongyo	    (sc->sc_flags & BWN_FLAG_INVALID)) {
8506203945Sweongyo		BWN_UNLOCK(sc);
8507203945Sweongyo		return;
8508203945Sweongyo	}
8509203945Sweongyo
8510203945Sweongyo	for (i = 0; i < N(mac->mac_reason); i++)
8511203945Sweongyo		merged |= mac->mac_reason[i];
8512203945Sweongyo
8513203945Sweongyo	if (mac->mac_reason_intr & BWN_INTR_MAC_TXERR)
8514203945Sweongyo		device_printf(sc->sc_dev, "MAC trans error\n");
8515203945Sweongyo
8516203945Sweongyo	if (mac->mac_reason_intr & BWN_INTR_PHY_TXERR) {
8517203945Sweongyo		DPRINTF(sc, BWN_DEBUG_INTR, "%s: PHY trans error\n", __func__);
8518203945Sweongyo		mac->mac_phy.txerrors--;
8519203945Sweongyo		if (mac->mac_phy.txerrors == 0) {
8520203945Sweongyo			mac->mac_phy.txerrors = BWN_TXERROR_MAX;
8521203945Sweongyo			bwn_restart(mac, "PHY TX errors");
8522203945Sweongyo		}
8523203945Sweongyo	}
8524203945Sweongyo
8525203945Sweongyo	if (merged & (BWN_DMAINTR_FATALMASK | BWN_DMAINTR_NONFATALMASK)) {
8526203945Sweongyo		if (merged & BWN_DMAINTR_FATALMASK) {
8527203945Sweongyo			device_printf(sc->sc_dev,
8528203945Sweongyo			    "Fatal DMA error: %#x %#x %#x %#x %#x %#x\n",
8529203945Sweongyo			    mac->mac_reason[0], mac->mac_reason[1],
8530203945Sweongyo			    mac->mac_reason[2], mac->mac_reason[3],
8531203945Sweongyo			    mac->mac_reason[4], mac->mac_reason[5]);
8532203945Sweongyo			bwn_restart(mac, "DMA error");
8533203945Sweongyo			BWN_UNLOCK(sc);
8534203945Sweongyo			return;
8535203945Sweongyo		}
8536203945Sweongyo		if (merged & BWN_DMAINTR_NONFATALMASK) {
8537203945Sweongyo			device_printf(sc->sc_dev,
8538203945Sweongyo			    "DMA error: %#x %#x %#x %#x %#x %#x\n",
8539203945Sweongyo			    mac->mac_reason[0], mac->mac_reason[1],
8540203945Sweongyo			    mac->mac_reason[2], mac->mac_reason[3],
8541203945Sweongyo			    mac->mac_reason[4], mac->mac_reason[5]);
8542203945Sweongyo		}
8543203945Sweongyo	}
8544203945Sweongyo
8545203945Sweongyo	if (mac->mac_reason_intr & BWN_INTR_UCODE_DEBUG)
8546203945Sweongyo		bwn_intr_ucode_debug(mac);
8547203945Sweongyo	if (mac->mac_reason_intr & BWN_INTR_TBTT_INDI)
8548203945Sweongyo		bwn_intr_tbtt_indication(mac);
8549203945Sweongyo	if (mac->mac_reason_intr & BWN_INTR_ATIM_END)
8550203945Sweongyo		bwn_intr_atim_end(mac);
8551203945Sweongyo	if (mac->mac_reason_intr & BWN_INTR_BEACON)
8552203945Sweongyo		bwn_intr_beacon(mac);
8553203945Sweongyo	if (mac->mac_reason_intr & BWN_INTR_PMQ)
8554203945Sweongyo		bwn_intr_pmq(mac);
8555203945Sweongyo	if (mac->mac_reason_intr & BWN_INTR_NOISESAMPLE_OK)
8556203945Sweongyo		bwn_intr_noise(mac);
8557203945Sweongyo
8558203945Sweongyo	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
8559203945Sweongyo		if (mac->mac_reason[0] & BWN_DMAINTR_RX_DONE) {
8560203945Sweongyo			bwn_dma_rx(mac->mac_method.dma.rx);
8561203945Sweongyo			rx = 1;
8562203945Sweongyo		}
8563203945Sweongyo	} else
8564203945Sweongyo		rx = bwn_pio_rx(&mac->mac_method.pio.rx);
8565203945Sweongyo
8566203945Sweongyo	KASSERT(!(mac->mac_reason[1] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8567203945Sweongyo	KASSERT(!(mac->mac_reason[2] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8568203945Sweongyo	KASSERT(!(mac->mac_reason[3] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8569203945Sweongyo	KASSERT(!(mac->mac_reason[4] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8570203945Sweongyo	KASSERT(!(mac->mac_reason[5] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8571203945Sweongyo
8572203945Sweongyo	if (mac->mac_reason_intr & BWN_INTR_TX_OK) {
8573203945Sweongyo		bwn_intr_txeof(mac);
8574203945Sweongyo		tx = 1;
8575203945Sweongyo	}
8576203945Sweongyo
8577203945Sweongyo	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
8578203945Sweongyo
8579203945Sweongyo	if (sc->sc_blink_led != NULL && sc->sc_led_blink) {
8580203945Sweongyo		int evt = BWN_LED_EVENT_NONE;
8581203945Sweongyo
8582203945Sweongyo		if (tx && rx) {
8583203945Sweongyo			if (sc->sc_rx_rate > sc->sc_tx_rate)
8584203945Sweongyo				evt = BWN_LED_EVENT_RX;
8585203945Sweongyo			else
8586203945Sweongyo				evt = BWN_LED_EVENT_TX;
8587203945Sweongyo		} else if (tx) {
8588203945Sweongyo			evt = BWN_LED_EVENT_TX;
8589203945Sweongyo		} else if (rx) {
8590203945Sweongyo			evt = BWN_LED_EVENT_RX;
8591203945Sweongyo		} else if (rx == 0) {
8592203945Sweongyo			evt = BWN_LED_EVENT_POLL;
8593203945Sweongyo		}
8594203945Sweongyo
8595203945Sweongyo		if (evt != BWN_LED_EVENT_NONE)
8596203945Sweongyo			bwn_led_event(mac, evt);
8597203945Sweongyo       }
8598203945Sweongyo
8599203945Sweongyo	if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0) {
8600203945Sweongyo		if (!IFQ_IS_EMPTY(&ifp->if_snd))
8601203945Sweongyo			bwn_start_locked(ifp);
8602203945Sweongyo	}
8603203945Sweongyo
8604203945Sweongyo	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8605203945Sweongyo	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8606203945Sweongyo
8607203945Sweongyo	BWN_UNLOCK(sc);
8608203945Sweongyo}
8609203945Sweongyo
8610203945Sweongyostatic void
8611203945Sweongyobwn_restart(struct bwn_mac *mac, const char *msg)
8612203945Sweongyo{
8613203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
8614203945Sweongyo	struct ifnet *ifp = sc->sc_ifp;
8615203945Sweongyo	struct ieee80211com *ic = ifp->if_l2com;
8616203945Sweongyo
8617203945Sweongyo	if (mac->mac_status < BWN_MAC_STATUS_INITED)
8618203945Sweongyo		return;
8619203945Sweongyo
8620203945Sweongyo	device_printf(sc->sc_dev, "HW reset: %s\n", msg);
8621203945Sweongyo	ieee80211_runtask(ic, &mac->mac_hwreset);
8622203945Sweongyo}
8623203945Sweongyo
8624203945Sweongyostatic void
8625203945Sweongyobwn_intr_ucode_debug(struct bwn_mac *mac)
8626203945Sweongyo{
8627203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
8628203945Sweongyo	uint16_t reason;
8629203945Sweongyo
8630203945Sweongyo	if (mac->mac_fw.opensource == 0)
8631203945Sweongyo		return;
8632203945Sweongyo
8633203945Sweongyo	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG);
8634203945Sweongyo	switch (reason) {
8635203945Sweongyo	case BWN_DEBUGINTR_PANIC:
8636203945Sweongyo		bwn_handle_fwpanic(mac);
8637203945Sweongyo		break;
8638203945Sweongyo	case BWN_DEBUGINTR_DUMP_SHM:
8639203945Sweongyo		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_SHM\n");
8640203945Sweongyo		break;
8641203945Sweongyo	case BWN_DEBUGINTR_DUMP_REGS:
8642203945Sweongyo		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_REGS\n");
8643203945Sweongyo		break;
8644203945Sweongyo	case BWN_DEBUGINTR_MARKER:
8645203945Sweongyo		device_printf(sc->sc_dev, "BWN_DEBUGINTR_MARKER\n");
8646203945Sweongyo		break;
8647203945Sweongyo	default:
8648203945Sweongyo		device_printf(sc->sc_dev,
8649203945Sweongyo		    "ucode debug unknown reason: %#x\n", reason);
8650203945Sweongyo	}
8651203945Sweongyo
8652203945Sweongyo	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG,
8653203945Sweongyo	    BWN_DEBUGINTR_ACK);
8654203945Sweongyo}
8655203945Sweongyo
8656203945Sweongyostatic void
8657203945Sweongyobwn_intr_tbtt_indication(struct bwn_mac *mac)
8658203945Sweongyo{
8659203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
8660203945Sweongyo	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8661203945Sweongyo
8662203945Sweongyo	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
8663203945Sweongyo		bwn_psctl(mac, 0);
8664203945Sweongyo	if (ic->ic_opmode == IEEE80211_M_IBSS)
8665203945Sweongyo		mac->mac_flags |= BWN_MAC_FLAG_DFQVALID;
8666203945Sweongyo}
8667203945Sweongyo
8668203945Sweongyostatic void
8669203945Sweongyobwn_intr_atim_end(struct bwn_mac *mac)
8670203945Sweongyo{
8671203945Sweongyo
8672203945Sweongyo	if (mac->mac_flags & BWN_MAC_FLAG_DFQVALID) {
8673203945Sweongyo		BWN_WRITE_4(mac, BWN_MACCMD,
8674203945Sweongyo		    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_DFQ_VALID);
8675203945Sweongyo		mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
8676203945Sweongyo	}
8677203945Sweongyo}
8678203945Sweongyo
8679203945Sweongyostatic void
8680203945Sweongyobwn_intr_beacon(struct bwn_mac *mac)
8681203945Sweongyo{
8682203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
8683203945Sweongyo	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8684203945Sweongyo	uint32_t cmd, beacon0, beacon1;
8685203945Sweongyo
8686203945Sweongyo	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
8687203945Sweongyo	    ic->ic_opmode == IEEE80211_M_MBSS)
8688203945Sweongyo		return;
8689203945Sweongyo
8690203945Sweongyo	mac->mac_intr_mask &= ~BWN_INTR_BEACON;
8691203945Sweongyo
8692203945Sweongyo	cmd = BWN_READ_4(mac, BWN_MACCMD);
8693203945Sweongyo	beacon0 = (cmd & BWN_MACCMD_BEACON0_VALID);
8694203945Sweongyo	beacon1 = (cmd & BWN_MACCMD_BEACON1_VALID);
8695203945Sweongyo
8696203945Sweongyo	if (beacon0 && beacon1) {
8697203945Sweongyo		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_BEACON);
8698203945Sweongyo		mac->mac_intr_mask |= BWN_INTR_BEACON;
8699203945Sweongyo		return;
8700203945Sweongyo	}
8701203945Sweongyo
8702203945Sweongyo	if (sc->sc_flags & BWN_FLAG_NEED_BEACON_TP) {
8703203945Sweongyo		sc->sc_flags &= ~BWN_FLAG_NEED_BEACON_TP;
8704203945Sweongyo		bwn_load_beacon0(mac);
8705203945Sweongyo		bwn_load_beacon1(mac);
8706203945Sweongyo		cmd = BWN_READ_4(mac, BWN_MACCMD);
8707203945Sweongyo		cmd |= BWN_MACCMD_BEACON0_VALID;
8708203945Sweongyo		BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8709203945Sweongyo	} else {
8710203945Sweongyo		if (!beacon0) {
8711203945Sweongyo			bwn_load_beacon0(mac);
8712203945Sweongyo			cmd = BWN_READ_4(mac, BWN_MACCMD);
8713203945Sweongyo			cmd |= BWN_MACCMD_BEACON0_VALID;
8714203945Sweongyo			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8715203945Sweongyo		} else if (!beacon1) {
8716203945Sweongyo			bwn_load_beacon1(mac);
8717203945Sweongyo			cmd = BWN_READ_4(mac, BWN_MACCMD);
8718203945Sweongyo			cmd |= BWN_MACCMD_BEACON1_VALID;
8719203945Sweongyo			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8720203945Sweongyo		}
8721203945Sweongyo	}
8722203945Sweongyo}
8723203945Sweongyo
8724203945Sweongyostatic void
8725203945Sweongyobwn_intr_pmq(struct bwn_mac *mac)
8726203945Sweongyo{
8727203945Sweongyo	uint32_t tmp;
8728203945Sweongyo
8729203945Sweongyo	while (1) {
8730203945Sweongyo		tmp = BWN_READ_4(mac, BWN_PS_STATUS);
8731203945Sweongyo		if (!(tmp & 0x00000008))
8732203945Sweongyo			break;
8733203945Sweongyo	}
8734203945Sweongyo	BWN_WRITE_2(mac, BWN_PS_STATUS, 0x0002);
8735203945Sweongyo}
8736203945Sweongyo
8737203945Sweongyostatic void
8738203945Sweongyobwn_intr_noise(struct bwn_mac *mac)
8739203945Sweongyo{
8740203945Sweongyo	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
8741203945Sweongyo	uint16_t tmp;
8742203945Sweongyo	uint8_t noise[4];
8743203945Sweongyo	uint8_t i, j;
8744203945Sweongyo	int32_t average;
8745203945Sweongyo
8746203945Sweongyo	if (mac->mac_phy.type != BWN_PHYTYPE_G)
8747203945Sweongyo		return;
8748203945Sweongyo
8749203945Sweongyo	KASSERT(mac->mac_noise.noi_running, ("%s: fail", __func__));
8750203945Sweongyo	*((uint32_t *)noise) = htole32(bwn_jssi_read(mac));
8751203945Sweongyo	if (noise[0] == 0x7f || noise[1] == 0x7f || noise[2] == 0x7f ||
8752203945Sweongyo	    noise[3] == 0x7f)
8753203945Sweongyo		goto new;
8754203945Sweongyo
8755203945Sweongyo	KASSERT(mac->mac_noise.noi_nsamples < 8,
8756203945Sweongyo	    ("%s:%d: fail", __func__, __LINE__));
8757203945Sweongyo	i = mac->mac_noise.noi_nsamples;
8758203945Sweongyo	noise[0] = MIN(MAX(noise[0], 0), N(pg->pg_nrssi_lt) - 1);
8759203945Sweongyo	noise[1] = MIN(MAX(noise[1], 0), N(pg->pg_nrssi_lt) - 1);
8760203945Sweongyo	noise[2] = MIN(MAX(noise[2], 0), N(pg->pg_nrssi_lt) - 1);
8761203945Sweongyo	noise[3] = MIN(MAX(noise[3], 0), N(pg->pg_nrssi_lt) - 1);
8762203945Sweongyo	mac->mac_noise.noi_samples[i][0] = pg->pg_nrssi_lt[noise[0]];
8763203945Sweongyo	mac->mac_noise.noi_samples[i][1] = pg->pg_nrssi_lt[noise[1]];
8764203945Sweongyo	mac->mac_noise.noi_samples[i][2] = pg->pg_nrssi_lt[noise[2]];
8765203945Sweongyo	mac->mac_noise.noi_samples[i][3] = pg->pg_nrssi_lt[noise[3]];
8766203945Sweongyo	mac->mac_noise.noi_nsamples++;
8767203945Sweongyo	if (mac->mac_noise.noi_nsamples == 8) {
8768203945Sweongyo		average = 0;
8769203945Sweongyo		for (i = 0; i < 8; i++) {
8770203945Sweongyo			for (j = 0; j < 4; j++)
8771203945Sweongyo				average += mac->mac_noise.noi_samples[i][j];
8772203945Sweongyo		}
8773203945Sweongyo		average = (((average / 32) * 125) + 64) / 128;
8774203945Sweongyo		tmp = (bwn_shm_read_2(mac, BWN_SHARED, 0x40c) / 128) & 0x1f;
8775203945Sweongyo		if (tmp >= 8)
8776203945Sweongyo			average += 2;
8777203945Sweongyo		else
8778203945Sweongyo			average -= 25;
8779203945Sweongyo		average -= (tmp == 8) ? 72 : 48;
8780203945Sweongyo
8781203945Sweongyo		mac->mac_stats.link_noise = average;
8782203945Sweongyo		mac->mac_noise.noi_running = 0;
8783203945Sweongyo		return;
8784203945Sweongyo	}
8785203945Sweongyonew:
8786203945Sweongyo	bwn_noise_gensample(mac);
8787203945Sweongyo}
8788203945Sweongyo
8789203945Sweongyostatic int
8790203945Sweongyobwn_pio_rx(struct bwn_pio_rxqueue *prq)
8791203945Sweongyo{
8792203945Sweongyo	struct bwn_mac *mac = prq->prq_mac;
8793203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
8794203945Sweongyo	unsigned int i;
8795203945Sweongyo
8796203945Sweongyo	BWN_ASSERT_LOCKED(sc);
8797203945Sweongyo
8798203945Sweongyo	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8799203945Sweongyo		return (0);
8800203945Sweongyo
8801203945Sweongyo	for (i = 0; i < 5000; i++) {
8802203945Sweongyo		if (bwn_pio_rxeof(prq) == 0)
8803203945Sweongyo			break;
8804203945Sweongyo	}
8805203945Sweongyo	if (i >= 5000)
8806203945Sweongyo		device_printf(sc->sc_dev, "too many RX frames in PIO mode\n");
8807203945Sweongyo	return ((i > 0) ? 1 : 0);
8808203945Sweongyo}
8809203945Sweongyo
8810203945Sweongyostatic void
8811203945Sweongyobwn_dma_rx(struct bwn_dma_ring *dr)
8812203945Sweongyo{
8813203945Sweongyo	int slot, curslot;
8814203945Sweongyo
8815203945Sweongyo	KASSERT(!dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
8816203945Sweongyo	curslot = dr->get_curslot(dr);
8817203945Sweongyo	KASSERT(curslot >= 0 && curslot < dr->dr_numslots,
8818203945Sweongyo	    ("%s:%d: fail", __func__, __LINE__));
8819203945Sweongyo
8820203945Sweongyo	slot = dr->dr_curslot;
8821203945Sweongyo	for (; slot != curslot; slot = bwn_dma_nextslot(dr, slot))
8822203945Sweongyo		bwn_dma_rxeof(dr, &slot);
8823203945Sweongyo
8824203945Sweongyo	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
8825203945Sweongyo	    BUS_DMASYNC_PREWRITE);
8826203945Sweongyo
8827203945Sweongyo	dr->set_curslot(dr, slot);
8828203945Sweongyo	dr->dr_curslot = slot;
8829203945Sweongyo}
8830203945Sweongyo
8831203945Sweongyostatic void
8832203945Sweongyobwn_intr_txeof(struct bwn_mac *mac)
8833203945Sweongyo{
8834203945Sweongyo	struct bwn_txstatus stat;
8835203945Sweongyo	uint32_t stat0, stat1;
8836203945Sweongyo	uint16_t tmp;
8837203945Sweongyo
8838203945Sweongyo	BWN_ASSERT_LOCKED(mac->mac_sc);
8839203945Sweongyo
8840203945Sweongyo	while (1) {
8841203945Sweongyo		stat0 = BWN_READ_4(mac, BWN_XMITSTAT_0);
8842203945Sweongyo		if (!(stat0 & 0x00000001))
8843203945Sweongyo			break;
8844203945Sweongyo		stat1 = BWN_READ_4(mac, BWN_XMITSTAT_1);
8845203945Sweongyo
8846203945Sweongyo		stat.cookie = (stat0 >> 16);
8847203945Sweongyo		stat.seq = (stat1 & 0x0000ffff);
8848203945Sweongyo		stat.phy_stat = ((stat1 & 0x00ff0000) >> 16);
8849203945Sweongyo		tmp = (stat0 & 0x0000ffff);
8850203945Sweongyo		stat.framecnt = ((tmp & 0xf000) >> 12);
8851203945Sweongyo		stat.rtscnt = ((tmp & 0x0f00) >> 8);
8852203945Sweongyo		stat.sreason = ((tmp & 0x001c) >> 2);
8853203945Sweongyo		stat.pm = (tmp & 0x0080) ? 1 : 0;
8854203945Sweongyo		stat.im = (tmp & 0x0040) ? 1 : 0;
8855203945Sweongyo		stat.ampdu = (tmp & 0x0020) ? 1 : 0;
8856203945Sweongyo		stat.ack = (tmp & 0x0002) ? 1 : 0;
8857203945Sweongyo
8858203945Sweongyo		bwn_handle_txeof(mac, &stat);
8859203945Sweongyo	}
8860203945Sweongyo}
8861203945Sweongyo
8862203945Sweongyostatic void
8863203945Sweongyobwn_hwreset(void *arg, int npending)
8864203945Sweongyo{
8865203945Sweongyo	struct bwn_mac *mac = arg;
8866203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
8867203945Sweongyo	int error = 0;
8868203945Sweongyo	int prev_status;
8869203945Sweongyo
8870203945Sweongyo	BWN_LOCK(sc);
8871203945Sweongyo
8872203945Sweongyo	prev_status = mac->mac_status;
8873203945Sweongyo	if (prev_status >= BWN_MAC_STATUS_STARTED)
8874203945Sweongyo		bwn_core_stop(mac);
8875203945Sweongyo	if (prev_status >= BWN_MAC_STATUS_INITED)
8876203945Sweongyo		bwn_core_exit(mac);
8877203945Sweongyo
8878203945Sweongyo	if (prev_status >= BWN_MAC_STATUS_INITED) {
8879203945Sweongyo		error = bwn_core_init(mac);
8880203945Sweongyo		if (error)
8881203945Sweongyo			goto out;
8882203945Sweongyo	}
8883203945Sweongyo	if (prev_status >= BWN_MAC_STATUS_STARTED)
8884203945Sweongyo		bwn_core_start(mac);
8885203945Sweongyoout:
8886203945Sweongyo	if (error) {
8887203945Sweongyo		device_printf(sc->sc_dev, "%s: failed (%d)\n", __func__, error);
8888203945Sweongyo		sc->sc_curmac = NULL;
8889203945Sweongyo	}
8890203945Sweongyo	BWN_UNLOCK(sc);
8891203945Sweongyo}
8892203945Sweongyo
8893203945Sweongyostatic void
8894203945Sweongyobwn_handle_fwpanic(struct bwn_mac *mac)
8895203945Sweongyo{
8896203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
8897203945Sweongyo	uint16_t reason;
8898203945Sweongyo
8899203945Sweongyo	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_FWPANIC_REASON_REG);
8900203945Sweongyo	device_printf(sc->sc_dev,"fw panic (%u)\n", reason);
8901203945Sweongyo
8902203945Sweongyo	if (reason == BWN_FWPANIC_RESTART)
8903203945Sweongyo		bwn_restart(mac, "ucode panic");
8904203945Sweongyo}
8905203945Sweongyo
8906203945Sweongyostatic void
8907203945Sweongyobwn_load_beacon0(struct bwn_mac *mac)
8908203945Sweongyo{
8909203945Sweongyo
8910203945Sweongyo	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8911203945Sweongyo}
8912203945Sweongyo
8913203945Sweongyostatic void
8914203945Sweongyobwn_load_beacon1(struct bwn_mac *mac)
8915203945Sweongyo{
8916203945Sweongyo
8917203945Sweongyo	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8918203945Sweongyo}
8919203945Sweongyo
8920203945Sweongyostatic uint32_t
8921203945Sweongyobwn_jssi_read(struct bwn_mac *mac)
8922203945Sweongyo{
8923203945Sweongyo	uint32_t val = 0;
8924203945Sweongyo
8925203945Sweongyo	val = bwn_shm_read_2(mac, BWN_SHARED, 0x08a);
8926203945Sweongyo	val <<= 16;
8927203945Sweongyo	val |= bwn_shm_read_2(mac, BWN_SHARED, 0x088);
8928203945Sweongyo
8929203945Sweongyo	return (val);
8930203945Sweongyo}
8931203945Sweongyo
8932203945Sweongyostatic void
8933203945Sweongyobwn_noise_gensample(struct bwn_mac *mac)
8934203945Sweongyo{
8935203945Sweongyo	uint32_t jssi = 0x7f7f7f7f;
8936203945Sweongyo
8937203945Sweongyo	bwn_shm_write_2(mac, BWN_SHARED, 0x088, (jssi & 0x0000ffff));
8938203945Sweongyo	bwn_shm_write_2(mac, BWN_SHARED, 0x08a, (jssi & 0xffff0000) >> 16);
8939203945Sweongyo	BWN_WRITE_4(mac, BWN_MACCMD,
8940203945Sweongyo	    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_BGNOISE);
8941203945Sweongyo}
8942203945Sweongyo
8943203945Sweongyostatic int
8944203945Sweongyobwn_dma_freeslot(struct bwn_dma_ring *dr)
8945203945Sweongyo{
8946204242Simp	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8947203945Sweongyo
8948203945Sweongyo	return (dr->dr_numslots - dr->dr_usedslot);
8949203945Sweongyo}
8950203945Sweongyo
8951203945Sweongyostatic int
8952203945Sweongyobwn_dma_nextslot(struct bwn_dma_ring *dr, int slot)
8953203945Sweongyo{
8954204242Simp	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8955203945Sweongyo
8956203945Sweongyo	KASSERT(slot >= -1 && slot <= dr->dr_numslots - 1,
8957203945Sweongyo	    ("%s:%d: fail", __func__, __LINE__));
8958203945Sweongyo	if (slot == dr->dr_numslots - 1)
8959203945Sweongyo		return (0);
8960203945Sweongyo	return (slot + 1);
8961203945Sweongyo}
8962203945Sweongyo
8963203945Sweongyostatic void
8964203945Sweongyobwn_dma_rxeof(struct bwn_dma_ring *dr, int *slot)
8965203945Sweongyo{
8966203945Sweongyo	struct bwn_mac *mac = dr->dr_mac;
8967203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
8968203945Sweongyo	struct bwn_dma *dma = &mac->mac_method.dma;
8969203945Sweongyo	struct bwn_dmadesc_generic *desc;
8970203945Sweongyo	struct bwn_dmadesc_meta *meta;
8971203945Sweongyo	struct bwn_rxhdr4 *rxhdr;
8972203945Sweongyo	struct ifnet *ifp = sc->sc_ifp;
8973203945Sweongyo	struct mbuf *m;
8974203945Sweongyo	uint32_t macstat;
8975203945Sweongyo	int32_t tmp;
8976203945Sweongyo	int cnt = 0;
8977203945Sweongyo	uint16_t len;
8978203945Sweongyo
8979203945Sweongyo	dr->getdesc(dr, *slot, &desc, &meta);
8980203945Sweongyo
8981203945Sweongyo	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap, BUS_DMASYNC_POSTREAD);
8982203945Sweongyo	m = meta->mt_m;
8983203945Sweongyo
8984203945Sweongyo	if (bwn_dma_newbuf(dr, desc, meta, 0)) {
8985203945Sweongyo		ifp->if_ierrors++;
8986203945Sweongyo		return;
8987203945Sweongyo	}
8988203945Sweongyo
8989203945Sweongyo	rxhdr = mtod(m, struct bwn_rxhdr4 *);
8990203945Sweongyo	len = le16toh(rxhdr->frame_len);
8991203945Sweongyo	if (len <= 0) {
8992203945Sweongyo		ifp->if_ierrors++;
8993203945Sweongyo		return;
8994203945Sweongyo	}
8995203945Sweongyo	if (bwn_dma_check_redzone(dr, m)) {
8996203945Sweongyo		device_printf(sc->sc_dev, "redzone error.\n");
8997203945Sweongyo		bwn_dma_set_redzone(dr, m);
8998203945Sweongyo		bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
8999203945Sweongyo		    BUS_DMASYNC_PREWRITE);
9000203945Sweongyo		return;
9001203945Sweongyo	}
9002203945Sweongyo	if (len > dr->dr_rx_bufsize) {
9003203945Sweongyo		tmp = len;
9004203945Sweongyo		while (1) {
9005203945Sweongyo			dr->getdesc(dr, *slot, &desc, &meta);
9006203945Sweongyo			bwn_dma_set_redzone(dr, meta->mt_m);
9007203945Sweongyo			bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
9008203945Sweongyo			    BUS_DMASYNC_PREWRITE);
9009203945Sweongyo			*slot = bwn_dma_nextslot(dr, *slot);
9010203945Sweongyo			cnt++;
9011203945Sweongyo			tmp -= dr->dr_rx_bufsize;
9012203945Sweongyo			if (tmp <= 0)
9013203945Sweongyo				break;
9014203945Sweongyo		}
9015203945Sweongyo		device_printf(sc->sc_dev, "too small buffer "
9016203945Sweongyo		       "(len %u buffer %u dropped %d)\n",
9017203945Sweongyo		       len, dr->dr_rx_bufsize, cnt);
9018203945Sweongyo		return;
9019203945Sweongyo	}
9020203945Sweongyo	macstat = le32toh(rxhdr->mac_status);
9021203945Sweongyo	if (macstat & BWN_RX_MAC_FCSERR) {
9022203945Sweongyo		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
9023203945Sweongyo			device_printf(sc->sc_dev, "RX drop\n");
9024203945Sweongyo			return;
9025203945Sweongyo		}
9026203945Sweongyo	}
9027203945Sweongyo
9028203945Sweongyo	m->m_pkthdr.rcvif = ifp;
9029203945Sweongyo	m->m_len = m->m_pkthdr.len = len + dr->dr_frameoffset;
9030203945Sweongyo	m_adj(m, dr->dr_frameoffset);
9031203945Sweongyo
9032203945Sweongyo	bwn_rxeof(dr->dr_mac, m, rxhdr);
9033203945Sweongyo}
9034203945Sweongyo
9035203945Sweongyostatic void
9036203945Sweongyobwn_handle_txeof(struct bwn_mac *mac, const struct bwn_txstatus *status)
9037203945Sweongyo{
9038203945Sweongyo	struct bwn_dma_ring *dr;
9039203945Sweongyo	struct bwn_dmadesc_generic *desc;
9040203945Sweongyo	struct bwn_dmadesc_meta *meta;
9041203945Sweongyo	struct bwn_node *bn;
9042203945Sweongyo	struct bwn_pio_txqueue *tq;
9043203945Sweongyo	struct bwn_pio_txpkt *tp = NULL;
9044203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
9045204257Sweongyo	struct bwn_stats *stats = &mac->mac_stats;
9046203945Sweongyo	struct ieee80211_node *ni;
9047203945Sweongyo	int slot;
9048203945Sweongyo
9049203945Sweongyo	BWN_ASSERT_LOCKED(mac->mac_sc);
9050203945Sweongyo
9051203945Sweongyo	if (status->im)
9052203945Sweongyo		device_printf(sc->sc_dev, "TODO: STATUS IM\n");
9053203945Sweongyo	if (status->ampdu)
9054203945Sweongyo		device_printf(sc->sc_dev, "TODO: STATUS AMPDU\n");
9055203945Sweongyo	if (status->rtscnt) {
9056203945Sweongyo		if (status->rtscnt == 0xf)
9057204257Sweongyo			stats->rtsfail++;
9058203945Sweongyo		else
9059204257Sweongyo			stats->rts++;
9060203945Sweongyo	}
9061203945Sweongyo
9062203945Sweongyo	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
9063203945Sweongyo		if (status->ack) {
9064203945Sweongyo			dr = bwn_dma_parse_cookie(mac, status,
9065203945Sweongyo			    status->cookie, &slot);
9066203945Sweongyo			if (dr == NULL) {
9067203945Sweongyo				device_printf(sc->sc_dev,
9068203945Sweongyo				    "failed to parse cookie\n");
9069203945Sweongyo				return;
9070203945Sweongyo			}
9071203945Sweongyo			while (1) {
9072203945Sweongyo				dr->getdesc(dr, slot, &desc, &meta);
9073203945Sweongyo				if (meta->mt_islast) {
9074203945Sweongyo					ni = meta->mt_ni;
9075203945Sweongyo					bn = (struct bwn_node *)ni;
9076203945Sweongyo					ieee80211_amrr_tx_complete(&bn->bn_amn,
9077203945Sweongyo					    status->ack, 0);
9078203945Sweongyo					break;
9079203945Sweongyo				}
9080203945Sweongyo				slot = bwn_dma_nextslot(dr, slot);
9081203945Sweongyo			}
9082203945Sweongyo		}
9083203945Sweongyo		bwn_dma_handle_txeof(mac, status);
9084203945Sweongyo	} else {
9085203945Sweongyo		if (status->ack) {
9086203945Sweongyo			tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9087203945Sweongyo			if (tq == NULL) {
9088203945Sweongyo				device_printf(sc->sc_dev,
9089203945Sweongyo				    "failed to parse cookie\n");
9090203945Sweongyo				return;
9091203945Sweongyo			}
9092203945Sweongyo			ni = tp->tp_ni;
9093203945Sweongyo			bn = (struct bwn_node *)ni;
9094203945Sweongyo			ieee80211_amrr_tx_complete(&bn->bn_amn, status->ack, 0);
9095203945Sweongyo		}
9096203945Sweongyo		bwn_pio_handle_txeof(mac, status);
9097203945Sweongyo	}
9098203945Sweongyo
9099203945Sweongyo	bwn_phy_txpower_check(mac, 0);
9100203945Sweongyo}
9101203945Sweongyo
9102203945Sweongyostatic uint8_t
9103203945Sweongyobwn_pio_rxeof(struct bwn_pio_rxqueue *prq)
9104203945Sweongyo{
9105203945Sweongyo	struct bwn_mac *mac = prq->prq_mac;
9106203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
9107203945Sweongyo	struct bwn_rxhdr4 rxhdr;
9108203945Sweongyo	struct ifnet *ifp = sc->sc_ifp;
9109203945Sweongyo	struct mbuf *m;
9110203945Sweongyo	uint32_t ctl32, macstat, v32;
9111203945Sweongyo	unsigned int i, padding;
9112203945Sweongyo	uint16_t ctl16, len, v16;
9113203945Sweongyo	unsigned char *mp;
9114203945Sweongyo	char *data;
9115203945Sweongyo
9116203945Sweongyo	memset(&rxhdr, 0, sizeof(rxhdr));
9117203945Sweongyo
9118203945Sweongyo	if (prq->prq_rev >= 8) {
9119203945Sweongyo		ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
9120203945Sweongyo		if (!(ctl32 & BWN_PIO8_RXCTL_FRAMEREADY))
9121203945Sweongyo			return (0);
9122203945Sweongyo		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9123203945Sweongyo		    BWN_PIO8_RXCTL_FRAMEREADY);
9124203945Sweongyo		for (i = 0; i < 10; i++) {
9125203945Sweongyo			ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
9126203945Sweongyo			if (ctl32 & BWN_PIO8_RXCTL_DATAREADY)
9127203945Sweongyo				goto ready;
9128203945Sweongyo			DELAY(10);
9129203945Sweongyo		}
9130203945Sweongyo	} else {
9131203945Sweongyo		ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
9132203945Sweongyo		if (!(ctl16 & BWN_PIO_RXCTL_FRAMEREADY))
9133203945Sweongyo			return (0);
9134203945Sweongyo		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL,
9135203945Sweongyo		    BWN_PIO_RXCTL_FRAMEREADY);
9136203945Sweongyo		for (i = 0; i < 10; i++) {
9137203945Sweongyo			ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
9138203945Sweongyo			if (ctl16 & BWN_PIO_RXCTL_DATAREADY)
9139203945Sweongyo				goto ready;
9140203945Sweongyo			DELAY(10);
9141203945Sweongyo		}
9142203945Sweongyo	}
9143203945Sweongyo	device_printf(sc->sc_dev, "%s: timed out\n", __func__);
9144203945Sweongyo	return (1);
9145203945Sweongyoready:
9146203945Sweongyo	if (prq->prq_rev >= 8)
9147204922Sweongyo		siba_read_multi_4(sc->sc_dev, &rxhdr, sizeof(rxhdr),
9148203945Sweongyo		    prq->prq_base + BWN_PIO8_RXDATA);
9149203945Sweongyo	else
9150204922Sweongyo		siba_read_multi_2(sc->sc_dev, &rxhdr, sizeof(rxhdr),
9151203945Sweongyo		    prq->prq_base + BWN_PIO_RXDATA);
9152203945Sweongyo	len = le16toh(rxhdr.frame_len);
9153203945Sweongyo	if (len > 0x700) {
9154203945Sweongyo		device_printf(sc->sc_dev, "%s: len is too big\n", __func__);
9155203945Sweongyo		goto error;
9156203945Sweongyo	}
9157203945Sweongyo	if (len == 0) {
9158203945Sweongyo		device_printf(sc->sc_dev, "%s: len is 0\n", __func__);
9159203945Sweongyo		goto error;
9160203945Sweongyo	}
9161203945Sweongyo
9162203945Sweongyo	macstat = le32toh(rxhdr.mac_status);
9163203945Sweongyo	if (macstat & BWN_RX_MAC_FCSERR) {
9164203945Sweongyo		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
9165203945Sweongyo			device_printf(sc->sc_dev, "%s: FCS error", __func__);
9166203945Sweongyo			goto error;
9167203945Sweongyo		}
9168203945Sweongyo	}
9169203945Sweongyo
9170203945Sweongyo	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9171203945Sweongyo	KASSERT(len + padding <= MCLBYTES, ("too big..\n"));
9172203945Sweongyo	m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
9173203945Sweongyo	if (m == NULL) {
9174203945Sweongyo		device_printf(sc->sc_dev, "%s: out of memory", __func__);
9175203945Sweongyo		goto error;
9176203945Sweongyo	}
9177203945Sweongyo	mp = mtod(m, unsigned char *);
9178203945Sweongyo	if (prq->prq_rev >= 8) {
9179204922Sweongyo		siba_read_multi_4(sc->sc_dev, mp + padding, (len & ~3),
9180203945Sweongyo		    prq->prq_base + BWN_PIO8_RXDATA);
9181203945Sweongyo		if (len & 3) {
9182203945Sweongyo			v32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXDATA);
9183203945Sweongyo			data = &(mp[len + padding - 1]);
9184203945Sweongyo			switch (len & 3) {
9185203945Sweongyo			case 3:
9186203945Sweongyo				*data = (v32 >> 16);
9187203945Sweongyo				data--;
9188203945Sweongyo			case 2:
9189203945Sweongyo				*data = (v32 >> 8);
9190203945Sweongyo				data--;
9191203945Sweongyo			case 1:
9192203945Sweongyo				*data = v32;
9193203945Sweongyo			}
9194203945Sweongyo		}
9195203945Sweongyo	} else {
9196204922Sweongyo		siba_read_multi_2(sc->sc_dev, mp + padding, (len & ~1),
9197203945Sweongyo		    prq->prq_base + BWN_PIO_RXDATA);
9198203945Sweongyo		if (len & 1) {
9199203945Sweongyo			v16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXDATA);
9200203945Sweongyo			mp[len + padding - 1] = v16;
9201203945Sweongyo		}
9202203945Sweongyo	}
9203203945Sweongyo
9204203945Sweongyo	m->m_pkthdr.rcvif = ifp;
9205203945Sweongyo	m->m_len = m->m_pkthdr.len = len + padding;
9206203945Sweongyo
9207203945Sweongyo	bwn_rxeof(prq->prq_mac, m, &rxhdr);
9208203945Sweongyo
9209203945Sweongyo	return (1);
9210203945Sweongyoerror:
9211203945Sweongyo	if (prq->prq_rev >= 8)
9212203945Sweongyo		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9213203945Sweongyo		    BWN_PIO8_RXCTL_DATAREADY);
9214203945Sweongyo	else
9215203945Sweongyo		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL, BWN_PIO_RXCTL_DATAREADY);
9216203945Sweongyo	return (1);
9217203945Sweongyo}
9218203945Sweongyo
9219203945Sweongyostatic int
9220203945Sweongyobwn_dma_newbuf(struct bwn_dma_ring *dr, struct bwn_dmadesc_generic *desc,
9221203945Sweongyo    struct bwn_dmadesc_meta *meta, int init)
9222203945Sweongyo{
9223203945Sweongyo	struct bwn_mac *mac = dr->dr_mac;
9224203945Sweongyo	struct bwn_dma *dma = &mac->mac_method.dma;
9225203945Sweongyo	struct bwn_rxhdr4 *hdr;
9226203945Sweongyo	bus_dmamap_t map;
9227203945Sweongyo	bus_addr_t paddr;
9228203945Sweongyo	struct mbuf *m;
9229203945Sweongyo	int error;
9230203945Sweongyo
9231203945Sweongyo	m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
9232203945Sweongyo	if (m == NULL) {
9233203945Sweongyo		error = ENOBUFS;
9234203945Sweongyo
9235203945Sweongyo		/*
9236203945Sweongyo		 * If the NIC is up and running, we need to:
9237203945Sweongyo		 * - Clear RX buffer's header.
9238203945Sweongyo		 * - Restore RX descriptor settings.
9239203945Sweongyo		 */
9240203945Sweongyo		if (init)
9241203945Sweongyo			return (error);
9242203945Sweongyo		else
9243203945Sweongyo			goto back;
9244203945Sweongyo	}
9245203945Sweongyo	m->m_len = m->m_pkthdr.len = MCLBYTES;
9246203945Sweongyo
9247203945Sweongyo	bwn_dma_set_redzone(dr, m);
9248203945Sweongyo
9249203945Sweongyo	/*
9250203945Sweongyo	 * Try to load RX buf into temporary DMA map
9251203945Sweongyo	 */
9252203945Sweongyo	error = bus_dmamap_load_mbuf(dma->rxbuf_dtag, dr->dr_spare_dmap, m,
9253203945Sweongyo	    bwn_dma_buf_addr, &paddr, BUS_DMA_NOWAIT);
9254203945Sweongyo	if (error) {
9255203945Sweongyo		m_freem(m);
9256203945Sweongyo
9257203945Sweongyo		/*
9258203945Sweongyo		 * See the comment above
9259203945Sweongyo		 */
9260203945Sweongyo		if (init)
9261203945Sweongyo			return (error);
9262203945Sweongyo		else
9263203945Sweongyo			goto back;
9264203945Sweongyo	}
9265203945Sweongyo
9266203945Sweongyo	if (!init)
9267203945Sweongyo		bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
9268203945Sweongyo	meta->mt_m = m;
9269203945Sweongyo	meta->mt_paddr = paddr;
9270203945Sweongyo
9271203945Sweongyo	/*
9272203945Sweongyo	 * Swap RX buf's DMA map with the loaded temporary one
9273203945Sweongyo	 */
9274203945Sweongyo	map = meta->mt_dmap;
9275203945Sweongyo	meta->mt_dmap = dr->dr_spare_dmap;
9276203945Sweongyo	dr->dr_spare_dmap = map;
9277203945Sweongyo
9278203945Sweongyoback:
9279203945Sweongyo	/*
9280203945Sweongyo	 * Clear RX buf header
9281203945Sweongyo	 */
9282203945Sweongyo	hdr = mtod(meta->mt_m, struct bwn_rxhdr4 *);
9283203945Sweongyo	bzero(hdr, sizeof(*hdr));
9284203945Sweongyo	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
9285203945Sweongyo	    BUS_DMASYNC_PREWRITE);
9286203945Sweongyo
9287203945Sweongyo	/*
9288203945Sweongyo	 * Setup RX buf descriptor
9289203945Sweongyo	 */
9290203945Sweongyo	dr->setdesc(dr, desc, paddr, meta->mt_m->m_len -
9291203945Sweongyo	    sizeof(*hdr), 0, 0, 0);
9292203945Sweongyo	return (error);
9293203945Sweongyo}
9294203945Sweongyo
9295203945Sweongyostatic void
9296203945Sweongyobwn_dma_buf_addr(void *arg, bus_dma_segment_t *seg, int nseg,
9297203945Sweongyo		 bus_size_t mapsz __unused, int error)
9298203945Sweongyo{
9299203945Sweongyo
9300203945Sweongyo	if (!error) {
9301203945Sweongyo		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
9302203945Sweongyo		*((bus_addr_t *)arg) = seg->ds_addr;
9303203945Sweongyo	}
9304203945Sweongyo}
9305203945Sweongyo
9306203945Sweongyostatic int
9307203945Sweongyobwn_hwrate2ieeerate(int rate)
9308203945Sweongyo{
9309203945Sweongyo
9310203945Sweongyo	switch (rate) {
9311203945Sweongyo	case BWN_CCK_RATE_1MB:
9312203945Sweongyo		return (2);
9313203945Sweongyo	case BWN_CCK_RATE_2MB:
9314203945Sweongyo		return (4);
9315203945Sweongyo	case BWN_CCK_RATE_5MB:
9316203945Sweongyo		return (11);
9317203945Sweongyo	case BWN_CCK_RATE_11MB:
9318203945Sweongyo		return (22);
9319203945Sweongyo	case BWN_OFDM_RATE_6MB:
9320203945Sweongyo		return (12);
9321203945Sweongyo	case BWN_OFDM_RATE_9MB:
9322203945Sweongyo		return (18);
9323203945Sweongyo	case BWN_OFDM_RATE_12MB:
9324203945Sweongyo		return (24);
9325203945Sweongyo	case BWN_OFDM_RATE_18MB:
9326203945Sweongyo		return (36);
9327203945Sweongyo	case BWN_OFDM_RATE_24MB:
9328203945Sweongyo		return (48);
9329203945Sweongyo	case BWN_OFDM_RATE_36MB:
9330203945Sweongyo		return (72);
9331203945Sweongyo	case BWN_OFDM_RATE_48MB:
9332203945Sweongyo		return (96);
9333203945Sweongyo	case BWN_OFDM_RATE_54MB:
9334203945Sweongyo		return (108);
9335203945Sweongyo	default:
9336203945Sweongyo		printf("Ooops\n");
9337203945Sweongyo		return (0);
9338203945Sweongyo	}
9339203945Sweongyo}
9340203945Sweongyo
9341203945Sweongyostatic void
9342203945Sweongyobwn_rxeof(struct bwn_mac *mac, struct mbuf *m, const void *_rxhdr)
9343203945Sweongyo{
9344203945Sweongyo	const struct bwn_rxhdr4 *rxhdr = _rxhdr;
9345203945Sweongyo	struct bwn_plcp6 *plcp;
9346203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
9347203945Sweongyo	struct ieee80211_frame_min *wh;
9348203945Sweongyo	struct ieee80211_node *ni;
9349203945Sweongyo	struct ifnet *ifp = sc->sc_ifp;
9350203945Sweongyo	struct ieee80211com *ic = ifp->if_l2com;
9351203945Sweongyo	uint32_t macstat;
9352204242Simp	int padding, rate, rssi = 0, noise = 0, type;
9353203945Sweongyo	uint16_t phytype, phystat0, phystat3, chanstat;
9354203945Sweongyo	unsigned char *mp = mtod(m, unsigned char *);
9355204242Simp	static int rx_mac_dec_rpt = 0;
9356203945Sweongyo
9357203945Sweongyo	BWN_ASSERT_LOCKED(sc);
9358203945Sweongyo
9359203945Sweongyo	phystat0 = le16toh(rxhdr->phy_status0);
9360203945Sweongyo	phystat3 = le16toh(rxhdr->phy_status3);
9361203945Sweongyo	macstat = le32toh(rxhdr->mac_status);
9362203945Sweongyo	chanstat = le16toh(rxhdr->channel);
9363203945Sweongyo	phytype = chanstat & BWN_RX_CHAN_PHYTYPE;
9364203945Sweongyo
9365203945Sweongyo	if (macstat & BWN_RX_MAC_FCSERR)
9366203945Sweongyo		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_FCS_CRC\n");
9367203945Sweongyo	if (phystat0 & (BWN_RX_PHYST0_PLCPHCF | BWN_RX_PHYST0_PLCPFV))
9368203945Sweongyo		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_PLCP_CRC\n");
9369203945Sweongyo	if (macstat & BWN_RX_MAC_DECERR)
9370203945Sweongyo		goto drop;
9371203945Sweongyo
9372203945Sweongyo	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9373203945Sweongyo	if (m->m_pkthdr.len < (sizeof(struct bwn_plcp6) + padding)) {
9374204081Sweongyo		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9375204081Sweongyo		    m->m_pkthdr.len);
9376203945Sweongyo		goto drop;
9377203945Sweongyo	}
9378203945Sweongyo	plcp = (struct bwn_plcp6 *)(mp + padding);
9379203945Sweongyo	m_adj(m, sizeof(struct bwn_plcp6) + padding);
9380203945Sweongyo	if (m->m_pkthdr.len < IEEE80211_MIN_LEN) {
9381204081Sweongyo		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9382204081Sweongyo		    m->m_pkthdr.len);
9383203945Sweongyo		goto drop;
9384203945Sweongyo	}
9385203945Sweongyo	wh = mtod(m, struct ieee80211_frame_min *);
9386203945Sweongyo
9387204242Simp	if (macstat & BWN_RX_MAC_DEC && rx_mac_dec_rpt++ < 50)
9388204081Sweongyo		device_printf(sc->sc_dev,
9389204081Sweongyo		    "RX decryption attempted (old %d keyidx %#x)\n",
9390204081Sweongyo		    BWN_ISOLDFMT(mac),
9391204081Sweongyo		    (macstat & BWN_RX_MAC_KEYIDX) >> BWN_RX_MAC_KEYIDX_SHIFT);
9392203945Sweongyo
9393203945Sweongyo	/* XXX calculating RSSI & noise & antenna */
9394203945Sweongyo
9395203945Sweongyo	if (phystat0 & BWN_RX_PHYST0_OFDM)
9396203945Sweongyo		rate = bwn_plcp_get_ofdmrate(mac, plcp,
9397203945Sweongyo		    phytype == BWN_PHYTYPE_A);
9398203945Sweongyo	else
9399203945Sweongyo		rate = bwn_plcp_get_cckrate(mac, plcp);
9400203945Sweongyo	if (rate == -1) {
9401203945Sweongyo		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADPLCP))
9402203945Sweongyo			goto drop;
9403203945Sweongyo	}
9404203945Sweongyo	sc->sc_rx_rate = bwn_hwrate2ieeerate(rate);
9405203945Sweongyo
9406203945Sweongyo	/* RX radio tap */
9407203945Sweongyo	if (ieee80211_radiotap_active(ic))
9408203945Sweongyo		bwn_rx_radiotap(mac, m, rxhdr, plcp, rate, rssi, noise);
9409203945Sweongyo	m_adj(m, -IEEE80211_CRC_LEN);
9410203945Sweongyo
9411203945Sweongyo	rssi = rxhdr->phy.abg.rssi;	/* XXX incorrect RSSI calculation? */
9412203945Sweongyo	noise = mac->mac_stats.link_noise;
9413203945Sweongyo
9414203945Sweongyo	BWN_UNLOCK(sc);
9415203945Sweongyo
9416203945Sweongyo	ni = ieee80211_find_rxnode(ic, wh);
9417203945Sweongyo	if (ni != NULL) {
9418203945Sweongyo		type = ieee80211_input(ni, m, rssi, noise);
9419203945Sweongyo		ieee80211_free_node(ni);
9420203945Sweongyo	} else
9421203945Sweongyo		type = ieee80211_input_all(ic, m, rssi, noise);
9422203945Sweongyo
9423203945Sweongyo	BWN_LOCK(sc);
9424203945Sweongyo	return;
9425203945Sweongyodrop:
9426203945Sweongyo	device_printf(sc->sc_dev, "%s: dropped\n", __func__);
9427203945Sweongyo}
9428203945Sweongyo
9429203945Sweongyostatic void
9430203945Sweongyobwn_dma_handle_txeof(struct bwn_mac *mac,
9431203945Sweongyo    const struct bwn_txstatus *status)
9432203945Sweongyo{
9433203945Sweongyo	struct bwn_dma *dma = &mac->mac_method.dma;
9434203945Sweongyo	struct bwn_dma_ring *dr;
9435203945Sweongyo	struct bwn_dmadesc_generic *desc;
9436203945Sweongyo	struct bwn_dmadesc_meta *meta;
9437203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
9438203945Sweongyo	struct ieee80211_node *ni;
9439203945Sweongyo	struct ifnet *ifp = sc->sc_ifp;
9440203945Sweongyo	struct mbuf *m;
9441203945Sweongyo	int slot;
9442203945Sweongyo
9443203945Sweongyo	BWN_ASSERT_LOCKED(sc);
9444203945Sweongyo
9445203945Sweongyo	dr = bwn_dma_parse_cookie(mac, status, status->cookie, &slot);
9446203945Sweongyo	if (dr == NULL) {
9447203945Sweongyo		device_printf(sc->sc_dev, "failed to parse cookie\n");
9448203945Sweongyo		return;
9449203945Sweongyo	}
9450203945Sweongyo	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
9451203945Sweongyo
9452203945Sweongyo	while (1) {
9453203945Sweongyo		KASSERT(slot >= 0 && slot < dr->dr_numslots,
9454203945Sweongyo		    ("%s:%d: fail", __func__, __LINE__));
9455203945Sweongyo		dr->getdesc(dr, slot, &desc, &meta);
9456203945Sweongyo
9457203945Sweongyo		if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
9458203945Sweongyo			bus_dmamap_unload(dr->dr_txring_dtag, meta->mt_dmap);
9459203945Sweongyo		else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
9460203945Sweongyo			bus_dmamap_unload(dma->txbuf_dtag, meta->mt_dmap);
9461203945Sweongyo
9462203945Sweongyo		if (meta->mt_islast) {
9463203945Sweongyo			KASSERT(meta->mt_m != NULL,
9464203945Sweongyo			    ("%s:%d: fail", __func__, __LINE__));
9465203945Sweongyo
9466203945Sweongyo			ni = meta->mt_ni;
9467203945Sweongyo			m = meta->mt_m;
9468203945Sweongyo			if (ni != NULL) {
9469203945Sweongyo				/*
9470203945Sweongyo				 * Do any tx complete callback. Note this must
9471203945Sweongyo				 * be done before releasing the node reference.
9472203945Sweongyo				 */
9473203945Sweongyo				if (m->m_flags & M_TXCB)
9474203945Sweongyo					ieee80211_process_callback(ni, m, 0);
9475203945Sweongyo				ieee80211_free_node(ni);
9476203945Sweongyo				meta->mt_ni = NULL;
9477203945Sweongyo			}
9478203945Sweongyo			m_freem(m);
9479203945Sweongyo			meta->mt_m = NULL;
9480203945Sweongyo		} else {
9481203945Sweongyo			KASSERT(meta->mt_m == NULL,
9482203945Sweongyo			    ("%s:%d: fail", __func__, __LINE__));
9483203945Sweongyo		}
9484203945Sweongyo
9485203945Sweongyo		dr->dr_usedslot--;
9486203945Sweongyo		if (meta->mt_islast) {
9487203945Sweongyo			ifp->if_opackets++;
9488203945Sweongyo			break;
9489203945Sweongyo		}
9490203945Sweongyo		slot = bwn_dma_nextslot(dr, slot);
9491203945Sweongyo	}
9492203945Sweongyo	sc->sc_watchdog_timer = 0;
9493203945Sweongyo	if (dr->dr_stop) {
9494203945Sweongyo		KASSERT(bwn_dma_freeslot(dr) >= BWN_TX_SLOTS_PER_FRAME,
9495203945Sweongyo		    ("%s:%d: fail", __func__, __LINE__));
9496203945Sweongyo		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
9497203945Sweongyo		dr->dr_stop = 0;
9498203945Sweongyo	}
9499203945Sweongyo}
9500203945Sweongyo
9501203945Sweongyostatic void
9502203945Sweongyobwn_pio_handle_txeof(struct bwn_mac *mac,
9503203945Sweongyo    const struct bwn_txstatus *status)
9504203945Sweongyo{
9505203945Sweongyo	struct bwn_pio_txqueue *tq;
9506203945Sweongyo	struct bwn_pio_txpkt *tp = NULL;
9507203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
9508203945Sweongyo	struct ifnet *ifp = sc->sc_ifp;
9509203945Sweongyo
9510203945Sweongyo	BWN_ASSERT_LOCKED(sc);
9511203945Sweongyo
9512203945Sweongyo	tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9513203945Sweongyo	if (tq == NULL)
9514203945Sweongyo		return;
9515203945Sweongyo
9516203945Sweongyo	tq->tq_used -= roundup(tp->tp_m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
9517203945Sweongyo	tq->tq_free++;
9518203945Sweongyo
9519203945Sweongyo	if (tp->tp_ni != NULL) {
9520203945Sweongyo		/*
9521203945Sweongyo		 * Do any tx complete callback.  Note this must
9522203945Sweongyo		 * be done before releasing the node reference.
9523203945Sweongyo		 */
9524203945Sweongyo		if (tp->tp_m->m_flags & M_TXCB)
9525203945Sweongyo			ieee80211_process_callback(tp->tp_ni, tp->tp_m, 0);
9526203945Sweongyo		ieee80211_free_node(tp->tp_ni);
9527203945Sweongyo		tp->tp_ni = NULL;
9528203945Sweongyo	}
9529203945Sweongyo	m_freem(tp->tp_m);
9530203945Sweongyo	tp->tp_m = NULL;
9531203945Sweongyo	TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
9532203945Sweongyo
9533203945Sweongyo	ifp->if_opackets++;
9534203945Sweongyo
9535203945Sweongyo	sc->sc_watchdog_timer = 0;
9536203945Sweongyo	if (tq->tq_stop) {
9537203945Sweongyo		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
9538203945Sweongyo		tq->tq_stop = 0;
9539203945Sweongyo	}
9540203945Sweongyo}
9541203945Sweongyo
9542203945Sweongyostatic void
9543203945Sweongyobwn_phy_txpower_check(struct bwn_mac *mac, uint32_t flags)
9544203945Sweongyo{
9545203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
9546203945Sweongyo	struct bwn_phy *phy = &mac->mac_phy;
9547203945Sweongyo	struct ifnet *ifp = sc->sc_ifp;
9548203945Sweongyo	struct ieee80211com *ic = ifp->if_l2com;
9549203945Sweongyo	unsigned long now;
9550203945Sweongyo	int result;
9551203945Sweongyo
9552203945Sweongyo	BWN_GETTIME(now);
9553203945Sweongyo
9554203945Sweongyo	if (!(flags & BWN_TXPWR_IGNORE_TIME) && time_before(now, phy->nexttime))
9555203945Sweongyo		return;
9556203945Sweongyo	phy->nexttime = now + 2 * 1000;
9557203945Sweongyo
9558204922Sweongyo	if (siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM &&
9559204922Sweongyo	    siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306)
9560203945Sweongyo		return;
9561203945Sweongyo
9562203945Sweongyo	if (phy->recalc_txpwr != NULL) {
9563203945Sweongyo		result = phy->recalc_txpwr(mac,
9564203945Sweongyo		    (flags & BWN_TXPWR_IGNORE_TSSI) ? 1 : 0);
9565203945Sweongyo		if (result == BWN_TXPWR_RES_DONE)
9566203945Sweongyo			return;
9567203945Sweongyo		KASSERT(result == BWN_TXPWR_RES_NEED_ADJUST,
9568203945Sweongyo		    ("%s: fail", __func__));
9569203945Sweongyo		KASSERT(phy->set_txpwr != NULL, ("%s: fail", __func__));
9570203945Sweongyo
9571203945Sweongyo		ieee80211_runtask(ic, &mac->mac_txpower);
9572203945Sweongyo	}
9573203945Sweongyo}
9574203945Sweongyo
9575203945Sweongyostatic uint16_t
9576203945Sweongyobwn_pio_rx_read_2(struct bwn_pio_rxqueue *prq, uint16_t offset)
9577203945Sweongyo{
9578203945Sweongyo
9579203945Sweongyo	return (BWN_READ_2(prq->prq_mac, prq->prq_base + offset));
9580203945Sweongyo}
9581203945Sweongyo
9582203945Sweongyostatic uint32_t
9583203945Sweongyobwn_pio_rx_read_4(struct bwn_pio_rxqueue *prq, uint16_t offset)
9584203945Sweongyo{
9585203945Sweongyo
9586203945Sweongyo	return (BWN_READ_4(prq->prq_mac, prq->prq_base + offset));
9587203945Sweongyo}
9588203945Sweongyo
9589203945Sweongyostatic void
9590203945Sweongyobwn_pio_rx_write_2(struct bwn_pio_rxqueue *prq, uint16_t offset, uint16_t value)
9591203945Sweongyo{
9592203945Sweongyo
9593203945Sweongyo	BWN_WRITE_2(prq->prq_mac, prq->prq_base + offset, value);
9594203945Sweongyo}
9595203945Sweongyo
9596203945Sweongyostatic void
9597203945Sweongyobwn_pio_rx_write_4(struct bwn_pio_rxqueue *prq, uint16_t offset, uint32_t value)
9598203945Sweongyo{
9599203945Sweongyo
9600203945Sweongyo	BWN_WRITE_4(prq->prq_mac, prq->prq_base + offset, value);
9601203945Sweongyo}
9602203945Sweongyo
9603203945Sweongyostatic int
9604203945Sweongyobwn_ieeerate2hwrate(struct bwn_softc *sc, int rate)
9605203945Sweongyo{
9606203945Sweongyo
9607203945Sweongyo	switch (rate) {
9608203945Sweongyo	/* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
9609203945Sweongyo	case 12:
9610203945Sweongyo		return (BWN_OFDM_RATE_6MB);
9611203945Sweongyo	case 18:
9612203945Sweongyo		return (BWN_OFDM_RATE_9MB);
9613203945Sweongyo	case 24:
9614203945Sweongyo		return (BWN_OFDM_RATE_12MB);
9615203945Sweongyo	case 36:
9616203945Sweongyo		return (BWN_OFDM_RATE_18MB);
9617203945Sweongyo	case 48:
9618203945Sweongyo		return (BWN_OFDM_RATE_24MB);
9619203945Sweongyo	case 72:
9620203945Sweongyo		return (BWN_OFDM_RATE_36MB);
9621203945Sweongyo	case 96:
9622203945Sweongyo		return (BWN_OFDM_RATE_48MB);
9623203945Sweongyo	case 108:
9624203945Sweongyo		return (BWN_OFDM_RATE_54MB);
9625203945Sweongyo	/* CCK rates (NB: not IEEE std, device-specific) */
9626203945Sweongyo	case 2:
9627203945Sweongyo		return (BWN_CCK_RATE_1MB);
9628203945Sweongyo	case 4:
9629203945Sweongyo		return (BWN_CCK_RATE_2MB);
9630203945Sweongyo	case 11:
9631203945Sweongyo		return (BWN_CCK_RATE_5MB);
9632203945Sweongyo	case 22:
9633203945Sweongyo		return (BWN_CCK_RATE_11MB);
9634203945Sweongyo	}
9635203945Sweongyo
9636203945Sweongyo	device_printf(sc->sc_dev, "unsupported rate %d\n", rate);
9637203945Sweongyo	return (BWN_CCK_RATE_1MB);
9638203945Sweongyo}
9639203945Sweongyo
9640203945Sweongyostatic int
9641203945Sweongyobwn_set_txhdr(struct bwn_mac *mac, struct ieee80211_node *ni,
9642203945Sweongyo    struct mbuf *m, struct bwn_txhdr *txhdr, uint16_t cookie)
9643203945Sweongyo{
9644203945Sweongyo	const struct bwn_phy *phy = &mac->mac_phy;
9645203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
9646203945Sweongyo	struct ieee80211_frame *wh;
9647203945Sweongyo	struct ieee80211_frame *protwh;
9648203945Sweongyo	struct ieee80211_frame_cts *cts;
9649203945Sweongyo	struct ieee80211_frame_rts *rts;
9650203945Sweongyo	const struct ieee80211_txparam *tp;
9651203945Sweongyo	struct ieee80211vap *vap = ni->ni_vap;
9652203945Sweongyo	struct ifnet *ifp = sc->sc_ifp;
9653203945Sweongyo	struct ieee80211com *ic = ifp->if_l2com;
9654203945Sweongyo	struct mbuf *mprot;
9655203945Sweongyo	unsigned int len;
9656203945Sweongyo	uint32_t macctl = 0;
9657203945Sweongyo	int protdur, rts_rate, rts_rate_fb, ismcast, isshort, rix, type;
9658203945Sweongyo	uint16_t phyctl = 0;
9659203945Sweongyo	uint8_t rate, rate_fb;
9660203945Sweongyo
9661203945Sweongyo	wh = mtod(m, struct ieee80211_frame *);
9662203945Sweongyo	memset(txhdr, 0, sizeof(*txhdr));
9663203945Sweongyo
9664203945Sweongyo	type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
9665203945Sweongyo	ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
9666203945Sweongyo	isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0;
9667203945Sweongyo
9668203945Sweongyo	/*
9669203945Sweongyo	 * Find TX rate
9670203945Sweongyo	 */
9671203945Sweongyo	tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)];
9672203945Sweongyo	if (type != IEEE80211_FC0_TYPE_DATA || (m->m_flags & M_EAPOL))
9673203945Sweongyo		rate = rate_fb = tp->mgmtrate;
9674203945Sweongyo	else if (ismcast)
9675203945Sweongyo		rate = rate_fb = tp->mcastrate;
9676203945Sweongyo	else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
9677203945Sweongyo		rate = rate_fb = tp->ucastrate;
9678203945Sweongyo	else {
9679203945Sweongyo		rix = ieee80211_amrr_choose(ni, &BWN_NODE(ni)->bn_amn);
9680203945Sweongyo		rate = ni->ni_txrate;
9681203945Sweongyo
9682203945Sweongyo		if (rix > 0)
9683203945Sweongyo			rate_fb = ni->ni_rates.rs_rates[rix - 1] &
9684203945Sweongyo			    IEEE80211_RATE_VAL;
9685203945Sweongyo		else
9686203945Sweongyo			rate_fb = rate;
9687203945Sweongyo	}
9688203945Sweongyo
9689203945Sweongyo	sc->sc_tx_rate = rate;
9690203945Sweongyo
9691203945Sweongyo	rate = bwn_ieeerate2hwrate(sc, rate);
9692203945Sweongyo	rate_fb = bwn_ieeerate2hwrate(sc, rate_fb);
9693203945Sweongyo
9694203945Sweongyo	txhdr->phyrate = (BWN_ISOFDMRATE(rate)) ? bwn_plcp_getofdm(rate) :
9695203945Sweongyo	    bwn_plcp_getcck(rate);
9696203945Sweongyo	bcopy(wh->i_fc, txhdr->macfc, sizeof(txhdr->macfc));
9697203945Sweongyo	bcopy(wh->i_addr1, txhdr->addr1, IEEE80211_ADDR_LEN);
9698203945Sweongyo
9699203945Sweongyo	if ((rate_fb == rate) ||
9700203945Sweongyo	    (*(u_int16_t *)wh->i_dur & htole16(0x8000)) ||
9701203945Sweongyo	    (*(u_int16_t *)wh->i_dur == htole16(0)))
9702203945Sweongyo		txhdr->dur_fb = *(u_int16_t *)wh->i_dur;
9703203945Sweongyo	else
9704203945Sweongyo		txhdr->dur_fb = ieee80211_compute_duration(ic->ic_rt,
9705203945Sweongyo		    m->m_pkthdr.len, rate, isshort);
9706203945Sweongyo
9707203945Sweongyo	/* XXX TX encryption */
9708203945Sweongyo	bwn_plcp_genhdr(BWN_ISOLDFMT(mac) ?
9709203945Sweongyo	    (struct bwn_plcp4 *)(&txhdr->body.old.plcp) :
9710203945Sweongyo	    (struct bwn_plcp4 *)(&txhdr->body.new.plcp),
9711203945Sweongyo	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate);
9712203945Sweongyo	bwn_plcp_genhdr((struct bwn_plcp4 *)(&txhdr->plcp_fb),
9713203945Sweongyo	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate_fb);
9714203945Sweongyo
9715203945Sweongyo	txhdr->eftypes |= (BWN_ISOFDMRATE(rate_fb)) ? BWN_TX_EFT_FB_OFDM :
9716203945Sweongyo	    BWN_TX_EFT_FB_CCK;
9717203945Sweongyo	txhdr->chan = phy->chan;
9718203945Sweongyo	phyctl |= (BWN_ISOFDMRATE(rate)) ? BWN_TX_PHY_ENC_OFDM :
9719203945Sweongyo	    BWN_TX_PHY_ENC_CCK;
9720203945Sweongyo	if (isshort && (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9721203945Sweongyo	     rate == BWN_CCK_RATE_11MB))
9722203945Sweongyo		phyctl |= BWN_TX_PHY_SHORTPRMBL;
9723203945Sweongyo
9724203945Sweongyo	/* XXX TX antenna selection */
9725203945Sweongyo
9726203945Sweongyo	switch (bwn_antenna_sanitize(mac, 0)) {
9727203945Sweongyo	case 0:
9728203945Sweongyo		phyctl |= BWN_TX_PHY_ANT01AUTO;
9729203945Sweongyo		break;
9730203945Sweongyo	case 1:
9731203945Sweongyo		phyctl |= BWN_TX_PHY_ANT0;
9732203945Sweongyo		break;
9733203945Sweongyo	case 2:
9734203945Sweongyo		phyctl |= BWN_TX_PHY_ANT1;
9735203945Sweongyo		break;
9736203945Sweongyo	case 3:
9737203945Sweongyo		phyctl |= BWN_TX_PHY_ANT2;
9738203945Sweongyo		break;
9739203945Sweongyo	case 4:
9740203945Sweongyo		phyctl |= BWN_TX_PHY_ANT3;
9741203945Sweongyo		break;
9742203945Sweongyo	default:
9743203945Sweongyo		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9744203945Sweongyo	}
9745203945Sweongyo
9746203945Sweongyo	if (!ismcast)
9747203945Sweongyo		macctl |= BWN_TX_MAC_ACK;
9748203945Sweongyo
9749203945Sweongyo	macctl |= (BWN_TX_MAC_HWSEQ | BWN_TX_MAC_START_MSDU);
9750203945Sweongyo	if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
9751203945Sweongyo	    m->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold)
9752203945Sweongyo		macctl |= BWN_TX_MAC_LONGFRAME;
9753203945Sweongyo
9754203945Sweongyo	if (ic->ic_flags & IEEE80211_F_USEPROT) {
9755203945Sweongyo		/* XXX RTS rate is always 1MB??? */
9756203945Sweongyo		rts_rate = BWN_CCK_RATE_1MB;
9757203945Sweongyo		rts_rate_fb = bwn_get_fbrate(rts_rate);
9758203945Sweongyo
9759203945Sweongyo		protdur = ieee80211_compute_duration(ic->ic_rt,
9760203945Sweongyo		    m->m_pkthdr.len, rate, isshort) +
9761203945Sweongyo		    + ieee80211_ack_duration(ic->ic_rt, rate, isshort);
9762203945Sweongyo
9763203945Sweongyo		if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) {
9764203945Sweongyo			cts = (struct ieee80211_frame_cts *)(BWN_ISOLDFMT(mac) ?
9765203945Sweongyo			    (txhdr->body.old.rts_frame) :
9766203945Sweongyo			    (txhdr->body.new.rts_frame));
9767203945Sweongyo			mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr,
9768203945Sweongyo			    protdur);
9769203945Sweongyo			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9770203945Sweongyo			bcopy(mtod(mprot, uint8_t *), (uint8_t *)cts,
9771203945Sweongyo			    mprot->m_pkthdr.len);
9772203945Sweongyo			m_freem(mprot);
9773203945Sweongyo			macctl |= BWN_TX_MAC_SEND_CTSTOSELF;
9774203945Sweongyo			len = sizeof(struct ieee80211_frame_cts);
9775203945Sweongyo		} else {
9776203945Sweongyo			rts = (struct ieee80211_frame_rts *)(BWN_ISOLDFMT(mac) ?
9777203945Sweongyo			    (txhdr->body.old.rts_frame) :
9778203945Sweongyo			    (txhdr->body.new.rts_frame));
9779203945Sweongyo			protdur += ieee80211_ack_duration(ic->ic_rt, rate,
9780203945Sweongyo			    isshort);
9781203945Sweongyo			mprot = ieee80211_alloc_rts(ic, wh->i_addr1,
9782203945Sweongyo			    wh->i_addr2, protdur);
9783203945Sweongyo			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9784203945Sweongyo			bcopy(mtod(mprot, uint8_t *), (uint8_t *)rts,
9785203945Sweongyo			    mprot->m_pkthdr.len);
9786203945Sweongyo			m_freem(mprot);
9787203945Sweongyo			macctl |= BWN_TX_MAC_SEND_RTSCTS;
9788203945Sweongyo			len = sizeof(struct ieee80211_frame_rts);
9789203945Sweongyo		}
9790203945Sweongyo		len += IEEE80211_CRC_LEN;
9791203945Sweongyo		bwn_plcp_genhdr((struct bwn_plcp4 *)((BWN_ISOLDFMT(mac)) ?
9792203945Sweongyo		    &txhdr->body.old.rts_plcp :
9793203945Sweongyo		    &txhdr->body.new.rts_plcp), len, rts_rate);
9794203945Sweongyo		bwn_plcp_genhdr((struct bwn_plcp4 *)&txhdr->rts_plcp_fb, len,
9795203945Sweongyo		    rts_rate_fb);
9796203945Sweongyo
9797203945Sweongyo		protwh = (struct ieee80211_frame *)(BWN_ISOLDFMT(mac) ?
9798203945Sweongyo		    (&txhdr->body.old.rts_frame) :
9799203945Sweongyo		    (&txhdr->body.new.rts_frame));
9800203945Sweongyo		txhdr->rts_dur_fb = *(u_int16_t *)protwh->i_dur;
9801203945Sweongyo
9802203945Sweongyo		if (BWN_ISOFDMRATE(rts_rate)) {
9803203945Sweongyo			txhdr->eftypes |= BWN_TX_EFT_RTS_OFDM;
9804203945Sweongyo			txhdr->phyrate_rts = bwn_plcp_getofdm(rts_rate);
9805203945Sweongyo		} else {
9806203945Sweongyo			txhdr->eftypes |= BWN_TX_EFT_RTS_CCK;
9807203945Sweongyo			txhdr->phyrate_rts = bwn_plcp_getcck(rts_rate);
9808203945Sweongyo		}
9809203945Sweongyo		txhdr->eftypes |= (BWN_ISOFDMRATE(rts_rate_fb)) ?
9810203945Sweongyo		    BWN_TX_EFT_RTS_FBOFDM : BWN_TX_EFT_RTS_FBCCK;
9811203945Sweongyo	}
9812203945Sweongyo
9813203945Sweongyo	if (BWN_ISOLDFMT(mac))
9814203945Sweongyo		txhdr->body.old.cookie = htole16(cookie);
9815203945Sweongyo	else
9816203945Sweongyo		txhdr->body.new.cookie = htole16(cookie);
9817203945Sweongyo
9818203945Sweongyo	txhdr->macctl = htole32(macctl);
9819203945Sweongyo	txhdr->phyctl = htole16(phyctl);
9820203945Sweongyo
9821203945Sweongyo	/*
9822203945Sweongyo	 * TX radio tap
9823203945Sweongyo	 */
9824203945Sweongyo	if (ieee80211_radiotap_active_vap(vap)) {
9825203945Sweongyo		sc->sc_tx_th.wt_flags = 0;
9826203945Sweongyo		if (wh->i_fc[1] & IEEE80211_FC1_WEP)
9827203945Sweongyo			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP;
9828203945Sweongyo		if (isshort &&
9829203945Sweongyo		    (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9830203945Sweongyo		     rate == BWN_CCK_RATE_11MB))
9831203945Sweongyo			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
9832203945Sweongyo		sc->sc_tx_th.wt_rate = rate;
9833203945Sweongyo
9834203945Sweongyo		ieee80211_radiotap_tx(vap, m);
9835203945Sweongyo	}
9836203945Sweongyo
9837203945Sweongyo	return (0);
9838203945Sweongyo}
9839203945Sweongyo
9840203945Sweongyostatic void
9841203945Sweongyobwn_plcp_genhdr(struct bwn_plcp4 *plcp, const uint16_t octets,
9842203945Sweongyo    const uint8_t rate)
9843203945Sweongyo{
9844203945Sweongyo	uint32_t d, plen;
9845203945Sweongyo	uint8_t *raw = plcp->o.raw;
9846203945Sweongyo
9847203945Sweongyo	if (BWN_ISOFDMRATE(rate)) {
9848203945Sweongyo		d = bwn_plcp_getofdm(rate);
9849203945Sweongyo		KASSERT(!(octets & 0xf000),
9850203945Sweongyo		    ("%s:%d: fail", __func__, __LINE__));
9851203945Sweongyo		d |= (octets << 5);
9852203945Sweongyo		plcp->o.data = htole32(d);
9853203945Sweongyo	} else {
9854203945Sweongyo		plen = octets * 16 / rate;
9855203945Sweongyo		if ((octets * 16 % rate) > 0) {
9856203945Sweongyo			plen++;
9857203945Sweongyo			if ((rate == BWN_CCK_RATE_11MB)
9858203945Sweongyo			    && ((octets * 8 % 11) < 4)) {
9859203945Sweongyo				raw[1] = 0x84;
9860203945Sweongyo			} else
9861203945Sweongyo				raw[1] = 0x04;
9862203945Sweongyo		} else
9863203945Sweongyo			raw[1] = 0x04;
9864203945Sweongyo		plcp->o.data |= htole32(plen << 16);
9865203945Sweongyo		raw[0] = bwn_plcp_getcck(rate);
9866203945Sweongyo	}
9867203945Sweongyo}
9868203945Sweongyo
9869203945Sweongyostatic uint8_t
9870203945Sweongyobwn_antenna_sanitize(struct bwn_mac *mac, uint8_t n)
9871203945Sweongyo{
9872204922Sweongyo	struct bwn_softc *sc = mac->mac_sc;
9873203945Sweongyo	uint8_t mask;
9874203945Sweongyo
9875203945Sweongyo	if (n == 0)
9876203945Sweongyo		return (0);
9877203945Sweongyo	if (mac->mac_phy.gmode)
9878204922Sweongyo		mask = siba_sprom_get_ant_bg(sc->sc_dev);
9879203945Sweongyo	else
9880204922Sweongyo		mask = siba_sprom_get_ant_a(sc->sc_dev);
9881203945Sweongyo	if (!(mask & (1 << (n - 1))))
9882203945Sweongyo		return (0);
9883203945Sweongyo	return (n);
9884203945Sweongyo}
9885203945Sweongyo
9886203945Sweongyostatic uint8_t
9887203945Sweongyobwn_get_fbrate(uint8_t bitrate)
9888203945Sweongyo{
9889203945Sweongyo	switch (bitrate) {
9890203945Sweongyo	case BWN_CCK_RATE_1MB:
9891203945Sweongyo		return (BWN_CCK_RATE_1MB);
9892203945Sweongyo	case BWN_CCK_RATE_2MB:
9893203945Sweongyo		return (BWN_CCK_RATE_1MB);
9894203945Sweongyo	case BWN_CCK_RATE_5MB:
9895203945Sweongyo		return (BWN_CCK_RATE_2MB);
9896203945Sweongyo	case BWN_CCK_RATE_11MB:
9897203945Sweongyo		return (BWN_CCK_RATE_5MB);
9898203945Sweongyo	case BWN_OFDM_RATE_6MB:
9899203945Sweongyo		return (BWN_CCK_RATE_5MB);
9900203945Sweongyo	case BWN_OFDM_RATE_9MB:
9901203945Sweongyo		return (BWN_OFDM_RATE_6MB);
9902203945Sweongyo	case BWN_OFDM_RATE_12MB:
9903203945Sweongyo		return (BWN_OFDM_RATE_9MB);
9904203945Sweongyo	case BWN_OFDM_RATE_18MB:
9905203945Sweongyo		return (BWN_OFDM_RATE_12MB);
9906203945Sweongyo	case BWN_OFDM_RATE_24MB:
9907203945Sweongyo		return (BWN_OFDM_RATE_18MB);
9908203945Sweongyo	case BWN_OFDM_RATE_36MB:
9909203945Sweongyo		return (BWN_OFDM_RATE_24MB);
9910203945Sweongyo	case BWN_OFDM_RATE_48MB:
9911203945Sweongyo		return (BWN_OFDM_RATE_36MB);
9912203945Sweongyo	case BWN_OFDM_RATE_54MB:
9913203945Sweongyo		return (BWN_OFDM_RATE_48MB);
9914203945Sweongyo	}
9915203945Sweongyo	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9916203945Sweongyo	return (0);
9917203945Sweongyo}
9918203945Sweongyo
9919203945Sweongyostatic uint32_t
9920203945Sweongyobwn_pio_write_multi_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9921203945Sweongyo    uint32_t ctl, const void *_data, int len)
9922203945Sweongyo{
9923204922Sweongyo	struct bwn_softc *sc = mac->mac_sc;
9924203945Sweongyo	uint32_t value = 0;
9925203945Sweongyo	const uint8_t *data = _data;
9926203945Sweongyo
9927203945Sweongyo	ctl |= BWN_PIO8_TXCTL_0_7 | BWN_PIO8_TXCTL_8_15 |
9928203945Sweongyo	    BWN_PIO8_TXCTL_16_23 | BWN_PIO8_TXCTL_24_31;
9929203945Sweongyo	bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9930203945Sweongyo
9931204922Sweongyo	siba_write_multi_4(sc->sc_dev, data, (len & ~3),
9932203945Sweongyo	    tq->tq_base + BWN_PIO8_TXDATA);
9933203945Sweongyo	if (len & 3) {
9934203945Sweongyo		ctl &= ~(BWN_PIO8_TXCTL_8_15 | BWN_PIO8_TXCTL_16_23 |
9935203945Sweongyo		    BWN_PIO8_TXCTL_24_31);
9936203945Sweongyo		data = &(data[len - 1]);
9937203945Sweongyo		switch (len & 3) {
9938203945Sweongyo		case 3:
9939203945Sweongyo			ctl |= BWN_PIO8_TXCTL_16_23;
9940203945Sweongyo			value |= (uint32_t)(*data) << 16;
9941203945Sweongyo			data--;
9942203945Sweongyo		case 2:
9943203945Sweongyo			ctl |= BWN_PIO8_TXCTL_8_15;
9944203945Sweongyo			value |= (uint32_t)(*data) << 8;
9945203945Sweongyo			data--;
9946203945Sweongyo		case 1:
9947203945Sweongyo			value |= (uint32_t)(*data);
9948203945Sweongyo		}
9949203945Sweongyo		bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9950203945Sweongyo		bwn_pio_write_4(mac, tq, BWN_PIO8_TXDATA, value);
9951203945Sweongyo	}
9952203945Sweongyo
9953203945Sweongyo	return (ctl);
9954203945Sweongyo}
9955203945Sweongyo
9956203945Sweongyostatic void
9957203945Sweongyobwn_pio_write_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9958203945Sweongyo    uint16_t offset, uint32_t value)
9959203945Sweongyo{
9960203945Sweongyo
9961203945Sweongyo	BWN_WRITE_4(mac, tq->tq_base + offset, value);
9962203945Sweongyo}
9963203945Sweongyo
9964203945Sweongyostatic uint16_t
9965203945Sweongyobwn_pio_write_multi_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9966203945Sweongyo    uint16_t ctl, const void *_data, int len)
9967203945Sweongyo{
9968204922Sweongyo	struct bwn_softc *sc = mac->mac_sc;
9969203945Sweongyo	const uint8_t *data = _data;
9970203945Sweongyo
9971203945Sweongyo	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
9972203945Sweongyo	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9973203945Sweongyo
9974204922Sweongyo	siba_write_multi_2(sc->sc_dev, data, (len & ~1),
9975203945Sweongyo	    tq->tq_base + BWN_PIO_TXDATA);
9976203945Sweongyo	if (len & 1) {
9977203945Sweongyo		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
9978203945Sweongyo		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9979203945Sweongyo		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data[len - 1]);
9980203945Sweongyo	}
9981203945Sweongyo
9982203945Sweongyo	return (ctl);
9983203945Sweongyo}
9984203945Sweongyo
9985203945Sweongyostatic uint16_t
9986203945Sweongyobwn_pio_write_mbuf_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9987203945Sweongyo    uint16_t ctl, struct mbuf *m0)
9988203945Sweongyo{
9989203945Sweongyo	int i, j = 0;
9990203945Sweongyo	uint16_t data = 0;
9991203945Sweongyo	const uint8_t *buf;
9992203945Sweongyo	struct mbuf *m = m0;
9993203945Sweongyo
9994203945Sweongyo	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
9995203945Sweongyo	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9996203945Sweongyo
9997203945Sweongyo	for (; m != NULL; m = m->m_next) {
9998203945Sweongyo		buf = mtod(m, const uint8_t *);
9999203945Sweongyo		for (i = 0; i < m->m_len; i++) {
10000203945Sweongyo			if (!((j++) % 2))
10001203945Sweongyo				data |= buf[i];
10002203945Sweongyo			else {
10003203945Sweongyo				data |= (buf[i] << 8);
10004203945Sweongyo				BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
10005203945Sweongyo				data = 0;
10006203945Sweongyo			}
10007203945Sweongyo		}
10008203945Sweongyo	}
10009203945Sweongyo	if (m0->m_pkthdr.len % 2) {
10010203945Sweongyo		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
10011203945Sweongyo		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
10012203945Sweongyo		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
10013203945Sweongyo	}
10014203945Sweongyo
10015203945Sweongyo	return (ctl);
10016203945Sweongyo}
10017203945Sweongyo
10018203945Sweongyostatic void
10019203945Sweongyobwn_set_slot_time(struct bwn_mac *mac, uint16_t time)
10020203945Sweongyo{
10021203945Sweongyo
10022203945Sweongyo	if (mac->mac_phy.type != BWN_PHYTYPE_G)
10023203945Sweongyo		return;
10024203945Sweongyo	BWN_WRITE_2(mac, 0x684, 510 + time);
10025203945Sweongyo	bwn_shm_write_2(mac, BWN_SHARED, 0x0010, time);
10026203945Sweongyo}
10027203945Sweongyo
10028203945Sweongyostatic struct bwn_dma_ring *
10029203945Sweongyobwn_dma_select(struct bwn_mac *mac, uint8_t prio)
10030203945Sweongyo{
10031203945Sweongyo
10032203945Sweongyo	if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
10033203945Sweongyo		return (mac->mac_method.dma.wme[WME_AC_BE]);
10034203945Sweongyo
10035203945Sweongyo	switch (prio) {
10036203945Sweongyo	case 3:
10037203945Sweongyo		return (mac->mac_method.dma.wme[WME_AC_VO]);
10038203945Sweongyo	case 2:
10039203945Sweongyo		return (mac->mac_method.dma.wme[WME_AC_VI]);
10040203945Sweongyo	case 0:
10041203945Sweongyo		return (mac->mac_method.dma.wme[WME_AC_BE]);
10042203945Sweongyo	case 1:
10043203945Sweongyo		return (mac->mac_method.dma.wme[WME_AC_BK]);
10044203945Sweongyo	}
10045203945Sweongyo	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
10046204242Simp	return (NULL);
10047203945Sweongyo}
10048203945Sweongyo
10049203945Sweongyostatic int
10050203945Sweongyobwn_dma_getslot(struct bwn_dma_ring *dr)
10051203945Sweongyo{
10052203945Sweongyo	int slot;
10053203945Sweongyo
10054204242Simp	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
10055203945Sweongyo
10056203945Sweongyo	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
10057203945Sweongyo	KASSERT(!(dr->dr_stop), ("%s:%d: fail", __func__, __LINE__));
10058203945Sweongyo	KASSERT(bwn_dma_freeslot(dr) != 0, ("%s:%d: fail", __func__, __LINE__));
10059203945Sweongyo
10060203945Sweongyo	slot = bwn_dma_nextslot(dr, dr->dr_curslot);
10061203945Sweongyo	KASSERT(!(slot & ~0x0fff), ("%s:%d: fail", __func__, __LINE__));
10062203945Sweongyo	dr->dr_curslot = slot;
10063203945Sweongyo	dr->dr_usedslot++;
10064203945Sweongyo
10065203945Sweongyo	return (slot);
10066203945Sweongyo}
10067203945Sweongyo
10068203945Sweongyostatic int
10069203945Sweongyobwn_phy_shm_tssi_read(struct bwn_mac *mac, uint16_t shm_offset)
10070203945Sweongyo{
10071203945Sweongyo	const uint8_t ofdm = (shm_offset != BWN_SHARED_TSSI_CCK);
10072203945Sweongyo	unsigned int a, b, c, d;
10073203945Sweongyo	unsigned int avg;
10074203945Sweongyo	uint32_t tmp;
10075203945Sweongyo
10076203945Sweongyo	tmp = bwn_shm_read_4(mac, BWN_SHARED, shm_offset);
10077203945Sweongyo	a = tmp & 0xff;
10078203945Sweongyo	b = (tmp >> 8) & 0xff;
10079203945Sweongyo	c = (tmp >> 16) & 0xff;
10080203945Sweongyo	d = (tmp >> 24) & 0xff;
10081203945Sweongyo	if (a == 0 || a == BWN_TSSI_MAX || b == 0 || b == BWN_TSSI_MAX ||
10082203945Sweongyo	    c == 0 || c == BWN_TSSI_MAX || d == 0 || d == BWN_TSSI_MAX)
10083203945Sweongyo		return (ENOENT);
10084203945Sweongyo	bwn_shm_write_4(mac, BWN_SHARED, shm_offset,
10085203945Sweongyo	    BWN_TSSI_MAX | (BWN_TSSI_MAX << 8) |
10086203945Sweongyo	    (BWN_TSSI_MAX << 16) | (BWN_TSSI_MAX << 24));
10087203945Sweongyo
10088203945Sweongyo	if (ofdm) {
10089203945Sweongyo		a = (a + 32) & 0x3f;
10090203945Sweongyo		b = (b + 32) & 0x3f;
10091203945Sweongyo		c = (c + 32) & 0x3f;
10092203945Sweongyo		d = (d + 32) & 0x3f;
10093203945Sweongyo	}
10094203945Sweongyo
10095203945Sweongyo	avg = (a + b + c + d + 2) / 4;
10096203945Sweongyo	if (ofdm) {
10097203945Sweongyo		if (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO)
10098203945Sweongyo		    & BWN_HF_4DB_CCK_POWERBOOST)
10099203945Sweongyo			avg = (avg >= 13) ? (avg - 13) : 0;
10100203945Sweongyo	}
10101203945Sweongyo	return (avg);
10102203945Sweongyo}
10103203945Sweongyo
10104203945Sweongyostatic void
10105203945Sweongyobwn_phy_g_setatt(struct bwn_mac *mac, int *bbattp, int *rfattp)
10106203945Sweongyo{
10107203945Sweongyo	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
10108203945Sweongyo	int rfatt = *rfattp;
10109203945Sweongyo	int bbatt = *bbattp;
10110203945Sweongyo
10111203945Sweongyo	while (1) {
10112203945Sweongyo		if (rfatt > lo->rfatt.max && bbatt > lo->bbatt.max - 4)
10113203945Sweongyo			break;
10114203945Sweongyo		if (rfatt < lo->rfatt.min && bbatt < lo->bbatt.min + 4)
10115203945Sweongyo			break;
10116203945Sweongyo		if (bbatt > lo->bbatt.max && rfatt > lo->rfatt.max - 1)
10117203945Sweongyo			break;
10118203945Sweongyo		if (bbatt < lo->bbatt.min && rfatt < lo->rfatt.min + 1)
10119203945Sweongyo			break;
10120203945Sweongyo		if (bbatt > lo->bbatt.max) {
10121203945Sweongyo			bbatt -= 4;
10122203945Sweongyo			rfatt += 1;
10123203945Sweongyo			continue;
10124203945Sweongyo		}
10125203945Sweongyo		if (bbatt < lo->bbatt.min) {
10126203945Sweongyo			bbatt += 4;
10127203945Sweongyo			rfatt -= 1;
10128203945Sweongyo			continue;
10129203945Sweongyo		}
10130203945Sweongyo		if (rfatt > lo->rfatt.max) {
10131203945Sweongyo			rfatt -= 1;
10132203945Sweongyo			bbatt += 4;
10133203945Sweongyo			continue;
10134203945Sweongyo		}
10135203945Sweongyo		if (rfatt < lo->rfatt.min) {
10136203945Sweongyo			rfatt += 1;
10137203945Sweongyo			bbatt -= 4;
10138203945Sweongyo			continue;
10139203945Sweongyo		}
10140203945Sweongyo		break;
10141203945Sweongyo	}
10142203945Sweongyo
10143203945Sweongyo	*rfattp = MIN(MAX(rfatt, lo->rfatt.min), lo->rfatt.max);
10144203945Sweongyo	*bbattp = MIN(MAX(bbatt, lo->bbatt.min), lo->bbatt.max);
10145203945Sweongyo}
10146203945Sweongyo
10147203945Sweongyostatic void
10148203945Sweongyobwn_phy_lock(struct bwn_mac *mac)
10149203945Sweongyo{
10150203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
10151203945Sweongyo	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
10152203945Sweongyo
10153204922Sweongyo	KASSERT(siba_get_revid(sc->sc_dev) >= 3,
10154204922Sweongyo	    ("%s: unsupported rev %d", __func__, siba_get_revid(sc->sc_dev)));
10155203945Sweongyo
10156203945Sweongyo	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
10157203945Sweongyo		bwn_psctl(mac, BWN_PS_AWAKE);
10158203945Sweongyo}
10159203945Sweongyo
10160203945Sweongyostatic void
10161203945Sweongyobwn_phy_unlock(struct bwn_mac *mac)
10162203945Sweongyo{
10163203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
10164203945Sweongyo	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
10165203945Sweongyo
10166204922Sweongyo	KASSERT(siba_get_revid(sc->sc_dev) >= 3,
10167204922Sweongyo	    ("%s: unsupported rev %d", __func__, siba_get_revid(sc->sc_dev)));
10168203945Sweongyo
10169203945Sweongyo	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
10170203945Sweongyo		bwn_psctl(mac, 0);
10171203945Sweongyo}
10172203945Sweongyo
10173203945Sweongyostatic void
10174203945Sweongyobwn_rf_lock(struct bwn_mac *mac)
10175203945Sweongyo{
10176203945Sweongyo
10177203945Sweongyo	BWN_WRITE_4(mac, BWN_MACCTL,
10178203945Sweongyo	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_RADIO_LOCK);
10179203945Sweongyo	BWN_READ_4(mac, BWN_MACCTL);
10180203945Sweongyo	DELAY(10);
10181203945Sweongyo}
10182203945Sweongyo
10183203945Sweongyostatic void
10184203945Sweongyobwn_rf_unlock(struct bwn_mac *mac)
10185203945Sweongyo{
10186203945Sweongyo
10187203945Sweongyo	BWN_READ_2(mac, BWN_PHYVER);
10188203945Sweongyo	BWN_WRITE_4(mac, BWN_MACCTL,
10189203945Sweongyo	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_RADIO_LOCK);
10190203945Sweongyo}
10191203945Sweongyo
10192203945Sweongyostatic struct bwn_pio_txqueue *
10193203945Sweongyobwn_pio_parse_cookie(struct bwn_mac *mac, uint16_t cookie,
10194203945Sweongyo    struct bwn_pio_txpkt **pack)
10195203945Sweongyo{
10196203945Sweongyo	struct bwn_pio *pio = &mac->mac_method.pio;
10197203945Sweongyo	struct bwn_pio_txqueue *tq = NULL;
10198203945Sweongyo	unsigned int index;
10199203945Sweongyo
10200203945Sweongyo	switch (cookie & 0xf000) {
10201203945Sweongyo	case 0x1000:
10202203945Sweongyo		tq = &pio->wme[WME_AC_BK];
10203203945Sweongyo		break;
10204203945Sweongyo	case 0x2000:
10205203945Sweongyo		tq = &pio->wme[WME_AC_BE];
10206203945Sweongyo		break;
10207203945Sweongyo	case 0x3000:
10208203945Sweongyo		tq = &pio->wme[WME_AC_VI];
10209203945Sweongyo		break;
10210203945Sweongyo	case 0x4000:
10211203945Sweongyo		tq = &pio->wme[WME_AC_VO];
10212203945Sweongyo		break;
10213203945Sweongyo	case 0x5000:
10214203945Sweongyo		tq = &pio->mcast;
10215203945Sweongyo		break;
10216203945Sweongyo	}
10217203945Sweongyo	KASSERT(tq != NULL, ("%s:%d: fail", __func__, __LINE__));
10218203945Sweongyo	if (tq == NULL)
10219203945Sweongyo		return (NULL);
10220203945Sweongyo	index = (cookie & 0x0fff);
10221203945Sweongyo	KASSERT(index < N(tq->tq_pkts), ("%s:%d: fail", __func__, __LINE__));
10222203945Sweongyo	if (index >= N(tq->tq_pkts))
10223203945Sweongyo		return (NULL);
10224203945Sweongyo	*pack = &tq->tq_pkts[index];
10225203945Sweongyo	KASSERT(*pack != NULL, ("%s:%d: fail", __func__, __LINE__));
10226203945Sweongyo	return (tq);
10227203945Sweongyo}
10228203945Sweongyo
10229203945Sweongyostatic void
10230203945Sweongyobwn_txpwr(void *arg, int npending)
10231203945Sweongyo{
10232203945Sweongyo	struct bwn_mac *mac = arg;
10233203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
10234203945Sweongyo
10235203945Sweongyo	BWN_LOCK(sc);
10236203945Sweongyo	if (mac && mac->mac_status >= BWN_MAC_STATUS_STARTED &&
10237203945Sweongyo	    mac->mac_phy.set_txpwr != NULL)
10238203945Sweongyo		mac->mac_phy.set_txpwr(mac);
10239203945Sweongyo	BWN_UNLOCK(sc);
10240203945Sweongyo}
10241203945Sweongyo
10242203945Sweongyostatic void
10243203945Sweongyobwn_task_15s(struct bwn_mac *mac)
10244203945Sweongyo{
10245203945Sweongyo	uint16_t reg;
10246203945Sweongyo
10247203945Sweongyo	if (mac->mac_fw.opensource) {
10248203945Sweongyo		reg = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG);
10249203945Sweongyo		if (reg) {
10250203945Sweongyo			bwn_restart(mac, "fw watchdog");
10251203945Sweongyo			return;
10252203945Sweongyo		}
10253203945Sweongyo		bwn_shm_write_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG, 1);
10254203945Sweongyo	}
10255203945Sweongyo	if (mac->mac_phy.task_15s)
10256203945Sweongyo		mac->mac_phy.task_15s(mac);
10257203945Sweongyo
10258203945Sweongyo	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
10259203945Sweongyo}
10260203945Sweongyo
10261203945Sweongyostatic void
10262203945Sweongyobwn_task_30s(struct bwn_mac *mac)
10263203945Sweongyo{
10264203945Sweongyo
10265203945Sweongyo	if (mac->mac_phy.type != BWN_PHYTYPE_G || mac->mac_noise.noi_running)
10266203945Sweongyo		return;
10267203945Sweongyo	mac->mac_noise.noi_running = 1;
10268203945Sweongyo	mac->mac_noise.noi_nsamples = 0;
10269203945Sweongyo
10270203945Sweongyo	bwn_noise_gensample(mac);
10271203945Sweongyo}
10272203945Sweongyo
10273203945Sweongyostatic void
10274203945Sweongyobwn_task_60s(struct bwn_mac *mac)
10275203945Sweongyo{
10276203945Sweongyo
10277203945Sweongyo	if (mac->mac_phy.task_60s)
10278203945Sweongyo		mac->mac_phy.task_60s(mac);
10279203945Sweongyo	bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME);
10280203945Sweongyo}
10281203945Sweongyo
10282203945Sweongyostatic void
10283203945Sweongyobwn_tasks(void *arg)
10284203945Sweongyo{
10285203945Sweongyo	struct bwn_mac *mac = arg;
10286203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
10287203945Sweongyo
10288203945Sweongyo	BWN_ASSERT_LOCKED(sc);
10289203945Sweongyo	if (mac->mac_status != BWN_MAC_STATUS_STARTED)
10290203945Sweongyo		return;
10291203945Sweongyo
10292203945Sweongyo	if (mac->mac_task_state % 4 == 0)
10293203945Sweongyo		bwn_task_60s(mac);
10294203945Sweongyo	if (mac->mac_task_state % 2 == 0)
10295203945Sweongyo		bwn_task_30s(mac);
10296203945Sweongyo	bwn_task_15s(mac);
10297203945Sweongyo
10298203945Sweongyo	mac->mac_task_state++;
10299203945Sweongyo	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
10300203945Sweongyo}
10301203945Sweongyo
10302203945Sweongyostatic int
10303203945Sweongyobwn_plcp_get_ofdmrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp, uint8_t a)
10304203945Sweongyo{
10305203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
10306203945Sweongyo
10307203945Sweongyo	KASSERT(a == 0, ("not support APHY\n"));
10308203945Sweongyo
10309203945Sweongyo	switch (plcp->o.raw[0] & 0xf) {
10310203945Sweongyo	case 0xb:
10311203945Sweongyo		return (BWN_OFDM_RATE_6MB);
10312203945Sweongyo	case 0xf:
10313203945Sweongyo		return (BWN_OFDM_RATE_9MB);
10314203945Sweongyo	case 0xa:
10315203945Sweongyo		return (BWN_OFDM_RATE_12MB);
10316203945Sweongyo	case 0xe:
10317203945Sweongyo		return (BWN_OFDM_RATE_18MB);
10318203945Sweongyo	case 0x9:
10319203945Sweongyo		return (BWN_OFDM_RATE_24MB);
10320203945Sweongyo	case 0xd:
10321203945Sweongyo		return (BWN_OFDM_RATE_36MB);
10322203945Sweongyo	case 0x8:
10323203945Sweongyo		return (BWN_OFDM_RATE_48MB);
10324203945Sweongyo	case 0xc:
10325203945Sweongyo		return (BWN_OFDM_RATE_54MB);
10326203945Sweongyo	}
10327203945Sweongyo	device_printf(sc->sc_dev, "incorrect OFDM rate %d\n",
10328203945Sweongyo	    plcp->o.raw[0] & 0xf);
10329203945Sweongyo	return (-1);
10330203945Sweongyo}
10331203945Sweongyo
10332203945Sweongyostatic int
10333203945Sweongyobwn_plcp_get_cckrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp)
10334203945Sweongyo{
10335203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
10336203945Sweongyo
10337203945Sweongyo	switch (plcp->o.raw[0]) {
10338203945Sweongyo	case 0x0a:
10339203945Sweongyo		return (BWN_CCK_RATE_1MB);
10340203945Sweongyo	case 0x14:
10341203945Sweongyo		return (BWN_CCK_RATE_2MB);
10342203945Sweongyo	case 0x37:
10343203945Sweongyo		return (BWN_CCK_RATE_5MB);
10344203945Sweongyo	case 0x6e:
10345203945Sweongyo		return (BWN_CCK_RATE_11MB);
10346203945Sweongyo	}
10347203945Sweongyo	device_printf(sc->sc_dev, "incorrect CCK rate %d\n", plcp->o.raw[0]);
10348203945Sweongyo	return (-1);
10349203945Sweongyo}
10350203945Sweongyo
10351203945Sweongyostatic void
10352203945Sweongyobwn_rx_radiotap(struct bwn_mac *mac, struct mbuf *m,
10353203945Sweongyo    const struct bwn_rxhdr4 *rxhdr, struct bwn_plcp6 *plcp, int rate,
10354203945Sweongyo    int rssi, int noise)
10355203945Sweongyo{
10356203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
10357203945Sweongyo	const struct ieee80211_frame_min *wh;
10358203945Sweongyo	uint64_t tsf;
10359203945Sweongyo	uint16_t low_mactime_now;
10360203945Sweongyo
10361203945Sweongyo	if (htole16(rxhdr->phy_status0) & BWN_RX_PHYST0_SHORTPRMBL)
10362203945Sweongyo		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
10363203945Sweongyo
10364203945Sweongyo	wh = mtod(m, const struct ieee80211_frame_min *);
10365203945Sweongyo	if (wh->i_fc[1] & IEEE80211_FC1_WEP)
10366203945Sweongyo		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_WEP;
10367203945Sweongyo
10368203945Sweongyo	bwn_tsf_read(mac, &tsf);
10369203945Sweongyo	low_mactime_now = tsf;
10370203945Sweongyo	tsf = tsf & ~0xffffULL;
10371203945Sweongyo	tsf += le16toh(rxhdr->mac_time);
10372203945Sweongyo	if (low_mactime_now < le16toh(rxhdr->mac_time))
10373203945Sweongyo		tsf -= 0x10000;
10374203945Sweongyo
10375203945Sweongyo	sc->sc_rx_th.wr_tsf = tsf;
10376203945Sweongyo	sc->sc_rx_th.wr_rate = rate;
10377203945Sweongyo	sc->sc_rx_th.wr_antsignal = rssi;
10378203945Sweongyo	sc->sc_rx_th.wr_antnoise = noise;
10379203945Sweongyo}
10380203945Sweongyo
10381203945Sweongyostatic void
10382203945Sweongyobwn_tsf_read(struct bwn_mac *mac, uint64_t *tsf)
10383203945Sweongyo{
10384203945Sweongyo	uint32_t low, high;
10385203945Sweongyo
10386204983Syongari	KASSERT(siba_get_revid(mac->mac_sc->sc_dev) >= 3,
10387203945Sweongyo	    ("%s:%d: fail", __func__, __LINE__));
10388203945Sweongyo
10389203945Sweongyo	low = BWN_READ_4(mac, BWN_REV3PLUS_TSF_LOW);
10390203945Sweongyo	high = BWN_READ_4(mac, BWN_REV3PLUS_TSF_HIGH);
10391203945Sweongyo	*tsf = high;
10392203945Sweongyo	*tsf <<= 32;
10393203945Sweongyo	*tsf |= low;
10394203945Sweongyo}
10395203945Sweongyo
10396203945Sweongyostatic int
10397203945Sweongyobwn_dma_attach(struct bwn_mac *mac)
10398203945Sweongyo{
10399203945Sweongyo	struct bwn_dma *dma = &mac->mac_method.dma;
10400203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
10401203945Sweongyo	bus_addr_t lowaddr = 0;
10402203945Sweongyo	int error;
10403203945Sweongyo
10404204922Sweongyo	if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
10405203945Sweongyo		return (0);
10406203945Sweongyo
10407204922Sweongyo	KASSERT(siba_get_revid(sc->sc_dev) >= 5, ("%s: fail", __func__));
10408203945Sweongyo
10409203945Sweongyo	mac->mac_flags |= BWN_MAC_FLAG_DMA;
10410203945Sweongyo
10411203945Sweongyo	dma->dmatype = bwn_dma_gettype(mac);
10412203945Sweongyo	if (dma->dmatype == BWN_DMA_30BIT)
10413203945Sweongyo		lowaddr = BWN_BUS_SPACE_MAXADDR_30BIT;
10414203945Sweongyo	else if (dma->dmatype == BWN_DMA_32BIT)
10415203945Sweongyo		lowaddr = BUS_SPACE_MAXADDR_32BIT;
10416203945Sweongyo	else
10417203945Sweongyo		lowaddr = BUS_SPACE_MAXADDR;
10418203945Sweongyo
10419203945Sweongyo	/*
10420203945Sweongyo	 * Create top level DMA tag
10421203945Sweongyo	 */
10422203945Sweongyo	error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev),	/* parent */
10423203945Sweongyo			       BWN_ALIGN, 0,		/* alignment, bounds */
10424203945Sweongyo			       lowaddr,			/* lowaddr */
10425203945Sweongyo			       BUS_SPACE_MAXADDR,	/* highaddr */
10426203945Sweongyo			       NULL, NULL,		/* filter, filterarg */
10427203945Sweongyo			       MAXBSIZE,		/* maxsize */
10428203945Sweongyo			       BUS_SPACE_UNRESTRICTED,	/* nsegments */
10429203945Sweongyo			       BUS_SPACE_MAXSIZE,	/* maxsegsize */
10430203945Sweongyo			       0,			/* flags */
10431203945Sweongyo			       NULL, NULL,		/* lockfunc, lockarg */
10432203945Sweongyo			       &dma->parent_dtag);
10433203945Sweongyo	if (error) {
10434203945Sweongyo		device_printf(sc->sc_dev, "can't create parent DMA tag\n");
10435203945Sweongyo		return (error);
10436203945Sweongyo	}
10437203945Sweongyo
10438203945Sweongyo	/*
10439203945Sweongyo	 * Create TX/RX mbuf DMA tag
10440203945Sweongyo	 */
10441203945Sweongyo	error = bus_dma_tag_create(dma->parent_dtag,
10442203945Sweongyo				1,
10443203945Sweongyo				0,
10444203945Sweongyo				BUS_SPACE_MAXADDR,
10445203945Sweongyo				BUS_SPACE_MAXADDR,
10446203945Sweongyo				NULL, NULL,
10447203945Sweongyo				MCLBYTES,
10448203945Sweongyo				1,
10449203945Sweongyo				BUS_SPACE_MAXSIZE_32BIT,
10450203945Sweongyo				0,
10451203945Sweongyo				NULL, NULL,
10452203945Sweongyo				&dma->rxbuf_dtag);
10453203945Sweongyo	if (error) {
10454203945Sweongyo		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10455203945Sweongyo		goto fail0;
10456203945Sweongyo	}
10457203945Sweongyo	error = bus_dma_tag_create(dma->parent_dtag,
10458203945Sweongyo				1,
10459203945Sweongyo				0,
10460203945Sweongyo				BUS_SPACE_MAXADDR,
10461203945Sweongyo				BUS_SPACE_MAXADDR,
10462203945Sweongyo				NULL, NULL,
10463203945Sweongyo				MCLBYTES,
10464203945Sweongyo				1,
10465203945Sweongyo				BUS_SPACE_MAXSIZE_32BIT,
10466203945Sweongyo				0,
10467203945Sweongyo				NULL, NULL,
10468203945Sweongyo				&dma->txbuf_dtag);
10469203945Sweongyo	if (error) {
10470203945Sweongyo		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10471203945Sweongyo		goto fail1;
10472203945Sweongyo	}
10473203945Sweongyo
10474203945Sweongyo	dma->wme[WME_AC_BK] = bwn_dma_ringsetup(mac, 0, 1, dma->dmatype);
10475203945Sweongyo	if (!dma->wme[WME_AC_BK])
10476203945Sweongyo		goto fail2;
10477203945Sweongyo
10478203945Sweongyo	dma->wme[WME_AC_BE] = bwn_dma_ringsetup(mac, 1, 1, dma->dmatype);
10479203945Sweongyo	if (!dma->wme[WME_AC_BE])
10480203945Sweongyo		goto fail3;
10481203945Sweongyo
10482203945Sweongyo	dma->wme[WME_AC_VI] = bwn_dma_ringsetup(mac, 2, 1, dma->dmatype);
10483203945Sweongyo	if (!dma->wme[WME_AC_VI])
10484203945Sweongyo		goto fail4;
10485203945Sweongyo
10486203945Sweongyo	dma->wme[WME_AC_VO] = bwn_dma_ringsetup(mac, 3, 1, dma->dmatype);
10487203945Sweongyo	if (!dma->wme[WME_AC_VO])
10488203945Sweongyo		goto fail5;
10489203945Sweongyo
10490203945Sweongyo	dma->mcast = bwn_dma_ringsetup(mac, 4, 1, dma->dmatype);
10491203945Sweongyo	if (!dma->mcast)
10492203945Sweongyo		goto fail6;
10493203945Sweongyo	dma->rx = bwn_dma_ringsetup(mac, 0, 0, dma->dmatype);
10494203945Sweongyo	if (!dma->rx)
10495203945Sweongyo		goto fail7;
10496203945Sweongyo
10497203945Sweongyo	return (error);
10498203945Sweongyo
10499203945Sweongyofail7:	bwn_dma_ringfree(&dma->mcast);
10500203945Sweongyofail6:	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
10501203945Sweongyofail5:	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
10502203945Sweongyofail4:	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
10503203945Sweongyofail3:	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
10504203945Sweongyofail2:	bus_dma_tag_destroy(dma->txbuf_dtag);
10505203945Sweongyofail1:	bus_dma_tag_destroy(dma->rxbuf_dtag);
10506203945Sweongyofail0:	bus_dma_tag_destroy(dma->parent_dtag);
10507203945Sweongyo	return (error);
10508203945Sweongyo}
10509203945Sweongyo
10510203945Sweongyostatic struct bwn_dma_ring *
10511203945Sweongyobwn_dma_parse_cookie(struct bwn_mac *mac, const struct bwn_txstatus *status,
10512203945Sweongyo    uint16_t cookie, int *slot)
10513203945Sweongyo{
10514203945Sweongyo	struct bwn_dma *dma = &mac->mac_method.dma;
10515203945Sweongyo	struct bwn_dma_ring *dr;
10516203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
10517203945Sweongyo
10518203945Sweongyo	BWN_ASSERT_LOCKED(mac->mac_sc);
10519203945Sweongyo
10520203945Sweongyo	switch (cookie & 0xf000) {
10521203945Sweongyo	case 0x1000:
10522203945Sweongyo		dr = dma->wme[WME_AC_BK];
10523203945Sweongyo		break;
10524203945Sweongyo	case 0x2000:
10525203945Sweongyo		dr = dma->wme[WME_AC_BE];
10526203945Sweongyo		break;
10527203945Sweongyo	case 0x3000:
10528203945Sweongyo		dr = dma->wme[WME_AC_VI];
10529203945Sweongyo		break;
10530203945Sweongyo	case 0x4000:
10531203945Sweongyo		dr = dma->wme[WME_AC_VO];
10532203945Sweongyo		break;
10533203945Sweongyo	case 0x5000:
10534203945Sweongyo		dr = dma->mcast;
10535203945Sweongyo		break;
10536203945Sweongyo	default:
10537204242Simp		dr = NULL;
10538203945Sweongyo		KASSERT(0 == 1,
10539203945Sweongyo		    ("invalid cookie value %d", cookie & 0xf000));
10540203945Sweongyo	}
10541203945Sweongyo	*slot = (cookie & 0x0fff);
10542203945Sweongyo	if (*slot < 0 || *slot >= dr->dr_numslots) {
10543203945Sweongyo		/*
10544203945Sweongyo		 * XXX FIXME: sometimes H/W returns TX DONE events duplicately
10545203945Sweongyo		 * that it occurs events which have same H/W sequence numbers.
10546203945Sweongyo		 * When it's occurred just prints a WARNING msgs and ignores.
10547203945Sweongyo		 */
10548203945Sweongyo		KASSERT(status->seq == dma->lastseq,
10549203945Sweongyo		    ("%s:%d: fail", __func__, __LINE__));
10550203945Sweongyo		device_printf(sc->sc_dev,
10551203945Sweongyo		    "out of slot ranges (0 < %d < %d)\n", *slot,
10552203945Sweongyo		    dr->dr_numslots);
10553203945Sweongyo		return (NULL);
10554203945Sweongyo	}
10555203945Sweongyo	dma->lastseq = status->seq;
10556203945Sweongyo	return (dr);
10557203945Sweongyo}
10558203945Sweongyo
10559203945Sweongyostatic void
10560203945Sweongyobwn_dma_stop(struct bwn_mac *mac)
10561203945Sweongyo{
10562203945Sweongyo	struct bwn_dma *dma;
10563203945Sweongyo
10564203945Sweongyo	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
10565203945Sweongyo		return;
10566203945Sweongyo	dma = &mac->mac_method.dma;
10567203945Sweongyo
10568203945Sweongyo	bwn_dma_ringstop(&dma->rx);
10569203945Sweongyo	bwn_dma_ringstop(&dma->wme[WME_AC_BK]);
10570203945Sweongyo	bwn_dma_ringstop(&dma->wme[WME_AC_BE]);
10571203945Sweongyo	bwn_dma_ringstop(&dma->wme[WME_AC_VI]);
10572203945Sweongyo	bwn_dma_ringstop(&dma->wme[WME_AC_VO]);
10573203945Sweongyo	bwn_dma_ringstop(&dma->mcast);
10574203945Sweongyo}
10575203945Sweongyo
10576203945Sweongyostatic void
10577203945Sweongyobwn_dma_ringstop(struct bwn_dma_ring **dr)
10578203945Sweongyo{
10579203945Sweongyo
10580203945Sweongyo	if (dr == NULL)
10581203945Sweongyo		return;
10582203945Sweongyo
10583203945Sweongyo	bwn_dma_cleanup(*dr);
10584203945Sweongyo}
10585203945Sweongyo
10586203945Sweongyostatic void
10587203945Sweongyobwn_pio_stop(struct bwn_mac *mac)
10588203945Sweongyo{
10589203945Sweongyo	struct bwn_pio *pio;
10590203945Sweongyo
10591203945Sweongyo	if (mac->mac_flags & BWN_MAC_FLAG_DMA)
10592203945Sweongyo		return;
10593203945Sweongyo	pio = &mac->mac_method.pio;
10594203945Sweongyo
10595203945Sweongyo	bwn_destroy_queue_tx(&pio->mcast);
10596203945Sweongyo	bwn_destroy_queue_tx(&pio->wme[WME_AC_VO]);
10597203945Sweongyo	bwn_destroy_queue_tx(&pio->wme[WME_AC_VI]);
10598203945Sweongyo	bwn_destroy_queue_tx(&pio->wme[WME_AC_BE]);
10599203945Sweongyo	bwn_destroy_queue_tx(&pio->wme[WME_AC_BK]);
10600203945Sweongyo}
10601203945Sweongyo
10602203945Sweongyostatic void
10603203945Sweongyobwn_led_attach(struct bwn_mac *mac)
10604203945Sweongyo{
10605203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
10606203945Sweongyo	const uint8_t *led_act = NULL;
10607203945Sweongyo	uint16_t val[BWN_LED_MAX];
10608203945Sweongyo	int i;
10609203945Sweongyo
10610203945Sweongyo	sc->sc_led_idle = (2350 * hz) / 1000;
10611203945Sweongyo	sc->sc_led_blink = 1;
10612203945Sweongyo
10613203945Sweongyo	for (i = 0; i < N(bwn_vendor_led_act); ++i) {
10614204922Sweongyo		if (siba_get_pci_subvendor(sc->sc_dev) ==
10615204922Sweongyo		    bwn_vendor_led_act[i].vid) {
10616203945Sweongyo			led_act = bwn_vendor_led_act[i].led_act;
10617203945Sweongyo			break;
10618203945Sweongyo		}
10619203945Sweongyo	}
10620203945Sweongyo	if (led_act == NULL)
10621203945Sweongyo		led_act = bwn_default_led_act;
10622203945Sweongyo
10623204922Sweongyo	val[0] = siba_sprom_get_gpio0(sc->sc_dev);
10624204922Sweongyo	val[1] = siba_sprom_get_gpio1(sc->sc_dev);
10625204922Sweongyo	val[2] = siba_sprom_get_gpio2(sc->sc_dev);
10626204922Sweongyo	val[3] = siba_sprom_get_gpio3(sc->sc_dev);
10627203945Sweongyo
10628203945Sweongyo	for (i = 0; i < BWN_LED_MAX; ++i) {
10629203945Sweongyo		struct bwn_led *led = &sc->sc_leds[i];
10630203945Sweongyo
10631203945Sweongyo		if (val[i] == 0xff) {
10632203945Sweongyo			led->led_act = led_act[i];
10633203945Sweongyo		} else {
10634203945Sweongyo			if (val[i] & BWN_LED_ACT_LOW)
10635203945Sweongyo				led->led_flags |= BWN_LED_F_ACTLOW;
10636203945Sweongyo			led->led_act = val[i] & BWN_LED_ACT_MASK;
10637203945Sweongyo		}
10638203945Sweongyo		led->led_mask = (1 << i);
10639203945Sweongyo
10640203945Sweongyo		if (led->led_act == BWN_LED_ACT_BLINK_SLOW ||
10641203945Sweongyo		    led->led_act == BWN_LED_ACT_BLINK_POLL ||
10642203945Sweongyo		    led->led_act == BWN_LED_ACT_BLINK) {
10643203945Sweongyo			led->led_flags |= BWN_LED_F_BLINK;
10644203945Sweongyo			if (led->led_act == BWN_LED_ACT_BLINK_POLL)
10645203945Sweongyo				led->led_flags |= BWN_LED_F_POLLABLE;
10646203945Sweongyo			else if (led->led_act == BWN_LED_ACT_BLINK_SLOW)
10647203945Sweongyo				led->led_flags |= BWN_LED_F_SLOW;
10648203945Sweongyo
10649203945Sweongyo			if (sc->sc_blink_led == NULL) {
10650203945Sweongyo				sc->sc_blink_led = led;
10651203945Sweongyo				if (led->led_flags & BWN_LED_F_SLOW)
10652203945Sweongyo					BWN_LED_SLOWDOWN(sc->sc_led_idle);
10653203945Sweongyo			}
10654203945Sweongyo		}
10655203945Sweongyo
10656203945Sweongyo		DPRINTF(sc, BWN_DEBUG_LED,
10657203945Sweongyo		    "%dth led, act %d, lowact %d\n", i,
10658203945Sweongyo		    led->led_act, led->led_flags & BWN_LED_F_ACTLOW);
10659203945Sweongyo	}
10660203945Sweongyo	callout_init_mtx(&sc->sc_led_blink_ch, &sc->sc_mtx, 0);
10661203945Sweongyo}
10662203945Sweongyo
10663203945Sweongyostatic __inline uint16_t
10664203945Sweongyobwn_led_onoff(const struct bwn_led *led, uint16_t val, int on)
10665203945Sweongyo{
10666203945Sweongyo
10667203945Sweongyo	if (led->led_flags & BWN_LED_F_ACTLOW)
10668203945Sweongyo		on = !on;
10669203945Sweongyo	if (on)
10670203945Sweongyo		val |= led->led_mask;
10671203945Sweongyo	else
10672203945Sweongyo		val &= ~led->led_mask;
10673203945Sweongyo	return val;
10674203945Sweongyo}
10675203945Sweongyo
10676203945Sweongyostatic void
10677203945Sweongyobwn_led_newstate(struct bwn_mac *mac, enum ieee80211_state nstate)
10678203945Sweongyo{
10679203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
10680203945Sweongyo	struct ifnet *ifp = sc->sc_ifp;
10681203945Sweongyo	struct ieee80211com *ic = ifp->if_l2com;
10682203945Sweongyo	uint16_t val;
10683203945Sweongyo	int i;
10684203945Sweongyo
10685203945Sweongyo	if (nstate == IEEE80211_S_INIT) {
10686203945Sweongyo		callout_stop(&sc->sc_led_blink_ch);
10687203945Sweongyo		sc->sc_led_blinking = 0;
10688203945Sweongyo	}
10689203945Sweongyo
10690203945Sweongyo	if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
10691203945Sweongyo		return;
10692203945Sweongyo
10693203945Sweongyo	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10694203945Sweongyo	for (i = 0; i < BWN_LED_MAX; ++i) {
10695203945Sweongyo		struct bwn_led *led = &sc->sc_leds[i];
10696203945Sweongyo		int on;
10697203945Sweongyo
10698203945Sweongyo		if (led->led_act == BWN_LED_ACT_UNKN ||
10699203945Sweongyo		    led->led_act == BWN_LED_ACT_NULL)
10700203945Sweongyo			continue;
10701203945Sweongyo
10702203945Sweongyo		if ((led->led_flags & BWN_LED_F_BLINK) &&
10703203945Sweongyo		    nstate != IEEE80211_S_INIT)
10704203945Sweongyo			continue;
10705203945Sweongyo
10706203945Sweongyo		switch (led->led_act) {
10707203945Sweongyo		case BWN_LED_ACT_ON:    /* Always on */
10708203945Sweongyo			on = 1;
10709203945Sweongyo			break;
10710203945Sweongyo		case BWN_LED_ACT_OFF:   /* Always off */
10711203945Sweongyo		case BWN_LED_ACT_5GHZ:  /* TODO: 11A */
10712203945Sweongyo			on = 0;
10713203945Sweongyo			break;
10714203945Sweongyo		default:
10715203945Sweongyo			on = 1;
10716203945Sweongyo			switch (nstate) {
10717203945Sweongyo			case IEEE80211_S_INIT:
10718203945Sweongyo				on = 0;
10719203945Sweongyo				break;
10720203945Sweongyo			case IEEE80211_S_RUN:
10721203945Sweongyo				if (led->led_act == BWN_LED_ACT_11G &&
10722203945Sweongyo				    ic->ic_curmode != IEEE80211_MODE_11G)
10723203945Sweongyo					on = 0;
10724203945Sweongyo				break;
10725203945Sweongyo			default:
10726203945Sweongyo				if (led->led_act == BWN_LED_ACT_ASSOC)
10727203945Sweongyo					on = 0;
10728203945Sweongyo				break;
10729203945Sweongyo			}
10730203945Sweongyo			break;
10731203945Sweongyo		}
10732203945Sweongyo
10733203945Sweongyo		val = bwn_led_onoff(led, val, on);
10734203945Sweongyo	}
10735203945Sweongyo	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10736203945Sweongyo}
10737203945Sweongyo
10738203945Sweongyostatic void
10739203945Sweongyobwn_led_event(struct bwn_mac *mac, int event)
10740203945Sweongyo{
10741203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
10742204922Sweongyo	struct bwn_led *led = sc->sc_blink_led;
10743204922Sweongyo	int rate;
10744203945Sweongyo
10745204922Sweongyo	if (event == BWN_LED_EVENT_POLL) {
10746204922Sweongyo		if ((led->led_flags & BWN_LED_F_POLLABLE) == 0)
10747204922Sweongyo			return;
10748204922Sweongyo		if (ticks - sc->sc_led_ticks < sc->sc_led_idle)
10749204922Sweongyo			return;
10750204922Sweongyo	}
10751203945Sweongyo
10752204922Sweongyo	sc->sc_led_ticks = ticks;
10753204922Sweongyo	if (sc->sc_led_blinking)
10754204922Sweongyo		return;
10755203945Sweongyo
10756204922Sweongyo	switch (event) {
10757204922Sweongyo	case BWN_LED_EVENT_RX:
10758204922Sweongyo		rate = sc->sc_rx_rate;
10759204922Sweongyo		break;
10760204922Sweongyo	case BWN_LED_EVENT_TX:
10761204922Sweongyo		rate = sc->sc_tx_rate;
10762204922Sweongyo		break;
10763204922Sweongyo	case BWN_LED_EVENT_POLL:
10764204922Sweongyo		rate = 0;
10765204922Sweongyo		break;
10766204922Sweongyo	default:
10767204922Sweongyo		panic("unknown LED event %d\n", event);
10768204922Sweongyo		break;
10769204922Sweongyo	}
10770204922Sweongyo	bwn_led_blink_start(mac, bwn_led_duration[rate].on_dur,
10771204922Sweongyo	    bwn_led_duration[rate].off_dur);
10772203945Sweongyo}
10773203945Sweongyo
10774203945Sweongyostatic void
10775203945Sweongyobwn_led_blink_start(struct bwn_mac *mac, int on_dur, int off_dur)
10776203945Sweongyo{
10777203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
10778204922Sweongyo	struct bwn_led *led = sc->sc_blink_led;
10779204922Sweongyo	uint16_t val;
10780203945Sweongyo
10781204922Sweongyo	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10782204922Sweongyo	val = bwn_led_onoff(led, val, 1);
10783204922Sweongyo	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10784203945Sweongyo
10785204922Sweongyo	if (led->led_flags & BWN_LED_F_SLOW) {
10786204922Sweongyo		BWN_LED_SLOWDOWN(on_dur);
10787204922Sweongyo		BWN_LED_SLOWDOWN(off_dur);
10788204922Sweongyo	}
10789203945Sweongyo
10790204922Sweongyo	sc->sc_led_blinking = 1;
10791204922Sweongyo	sc->sc_led_blink_offdur = off_dur;
10792203945Sweongyo
10793204922Sweongyo	callout_reset(&sc->sc_led_blink_ch, on_dur, bwn_led_blink_next, mac);
10794203945Sweongyo}
10795203945Sweongyo
10796203945Sweongyostatic void
10797203945Sweongyobwn_led_blink_next(void *arg)
10798203945Sweongyo{
10799203945Sweongyo	struct bwn_mac *mac = arg;
10800204922Sweongyo	struct bwn_softc *sc = mac->mac_sc;
10801204922Sweongyo	uint16_t val;
10802203945Sweongyo
10803204922Sweongyo	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10804204922Sweongyo	val = bwn_led_onoff(sc->sc_blink_led, val, 0);
10805204922Sweongyo	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10806203945Sweongyo
10807204922Sweongyo	callout_reset(&sc->sc_led_blink_ch, sc->sc_led_blink_offdur,
10808204922Sweongyo	    bwn_led_blink_end, mac);
10809203945Sweongyo}
10810203945Sweongyo
10811203945Sweongyostatic void
10812203945Sweongyobwn_led_blink_end(void *arg)
10813203945Sweongyo{
10814203945Sweongyo	struct bwn_mac *mac = arg;
10815204922Sweongyo	struct bwn_softc *sc = mac->mac_sc;
10816203945Sweongyo
10817204922Sweongyo	sc->sc_led_blinking = 0;
10818203945Sweongyo}
10819203945Sweongyo
10820203945Sweongyostatic int
10821203945Sweongyobwn_suspend(device_t dev)
10822203945Sweongyo{
10823203945Sweongyo	struct bwn_softc *sc = device_get_softc(dev);
10824203945Sweongyo
10825203945Sweongyo	bwn_stop(sc, 1);
10826203945Sweongyo	return (0);
10827203945Sweongyo}
10828203945Sweongyo
10829203945Sweongyostatic int
10830203945Sweongyobwn_resume(device_t dev)
10831203945Sweongyo{
10832203945Sweongyo	struct bwn_softc *sc = device_get_softc(dev);
10833203945Sweongyo	struct ifnet *ifp = sc->sc_ifp;
10834203945Sweongyo
10835203945Sweongyo	if (ifp->if_flags & IFF_UP)
10836203945Sweongyo		bwn_init(sc);
10837203945Sweongyo	return (0);
10838203945Sweongyo}
10839203945Sweongyo
10840203945Sweongyostatic void
10841203945Sweongyobwn_rfswitch(void *arg)
10842203945Sweongyo{
10843203945Sweongyo	struct bwn_softc *sc = arg;
10844203945Sweongyo	struct bwn_mac *mac = sc->sc_curmac;
10845203945Sweongyo	int cur = 0, prev = 0;
10846203945Sweongyo
10847203945Sweongyo	KASSERT(mac->mac_status >= BWN_MAC_STATUS_STARTED,
10848203945Sweongyo	    ("%s: invalid MAC status %d", __func__, mac->mac_status));
10849203945Sweongyo
10850203945Sweongyo	if (mac->mac_phy.rf_rev >= 3 || mac->mac_phy.type == BWN_PHYTYPE_LP) {
10851203945Sweongyo		if (!(BWN_READ_4(mac, BWN_RF_HWENABLED_HI)
10852203945Sweongyo			& BWN_RF_HWENABLED_HI_MASK))
10853203945Sweongyo			cur = 1;
10854203945Sweongyo	} else {
10855203945Sweongyo		if (BWN_READ_2(mac, BWN_RF_HWENABLED_LO)
10856203945Sweongyo		    & BWN_RF_HWENABLED_LO_MASK)
10857203945Sweongyo			cur = 1;
10858203945Sweongyo	}
10859203945Sweongyo
10860203945Sweongyo	if (mac->mac_flags & BWN_MAC_FLAG_RADIO_ON)
10861203945Sweongyo		prev = 1;
10862203945Sweongyo
10863203945Sweongyo	if (cur != prev) {
10864203945Sweongyo		if (cur)
10865203945Sweongyo			mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
10866203945Sweongyo		else
10867203945Sweongyo			mac->mac_flags &= ~BWN_MAC_FLAG_RADIO_ON;
10868203945Sweongyo
10869203945Sweongyo		device_printf(sc->sc_dev,
10870203945Sweongyo		    "status of RF switch is changed to %s\n",
10871203945Sweongyo		    cur ? "ON" : "OFF");
10872203945Sweongyo		if (cur != mac->mac_phy.rf_on) {
10873203945Sweongyo			if (cur)
10874203945Sweongyo				bwn_rf_turnon(mac);
10875203945Sweongyo			else
10876203945Sweongyo				bwn_rf_turnoff(mac);
10877203945Sweongyo		}
10878203945Sweongyo	}
10879203945Sweongyo
10880203945Sweongyo	callout_schedule(&sc->sc_rfswitch_ch, hz);
10881203945Sweongyo}
10882203945Sweongyo
10883203945Sweongyostatic void
10884203945Sweongyobwn_phy_lp_init_pre(struct bwn_mac *mac)
10885203945Sweongyo{
10886203945Sweongyo	struct bwn_phy *phy = &mac->mac_phy;
10887203945Sweongyo	struct bwn_phy_lp *plp = &phy->phy_lp;
10888203945Sweongyo
10889203945Sweongyo	plp->plp_antenna = BWN_ANT_DEFAULT;
10890203945Sweongyo}
10891203945Sweongyo
10892203945Sweongyostatic int
10893203945Sweongyobwn_phy_lp_init(struct bwn_mac *mac)
10894203945Sweongyo{
10895203945Sweongyo	static const struct bwn_stxtable tables[] = {
10896203945Sweongyo		{ 2,  6, 0x3d, 3, 0x01 }, { 1, 12, 0x4c, 1, 0x01 },
10897203945Sweongyo		{ 1,  8, 0x50, 0, 0x7f }, { 0,  8, 0x44, 0, 0xff },
10898203945Sweongyo		{ 1,  0, 0x4a, 0, 0xff }, { 0,  4, 0x4d, 0, 0xff },
10899203945Sweongyo		{ 1,  4, 0x4e, 0, 0xff }, { 0, 12, 0x4f, 0, 0x0f },
10900203945Sweongyo		{ 1,  0, 0x4f, 4, 0x0f }, { 3,  0, 0x49, 0, 0x0f },
10901203945Sweongyo		{ 4,  3, 0x46, 4, 0x07 }, { 3, 15, 0x46, 0, 0x01 },
10902203945Sweongyo		{ 4,  0, 0x46, 1, 0x07 }, { 3,  8, 0x48, 4, 0x07 },
10903203945Sweongyo		{ 3, 11, 0x48, 0, 0x0f }, { 3,  4, 0x49, 4, 0x0f },
10904203945Sweongyo		{ 2, 15, 0x45, 0, 0x01 }, { 5, 13, 0x52, 4, 0x07 },
10905203945Sweongyo		{ 6,  0, 0x52, 7, 0x01 }, { 5,  3, 0x41, 5, 0x07 },
10906203945Sweongyo		{ 5,  6, 0x41, 0, 0x0f }, { 5, 10, 0x42, 5, 0x07 },
10907203945Sweongyo		{ 4, 15, 0x42, 0, 0x01 }, { 5,  0, 0x42, 1, 0x07 },
10908203945Sweongyo		{ 4, 11, 0x43, 4, 0x0f }, { 4,  7, 0x43, 0, 0x0f },
10909203945Sweongyo		{ 4,  6, 0x45, 1, 0x01 }, { 2,  7, 0x40, 4, 0x0f },
10910203945Sweongyo		{ 2, 11, 0x40, 0, 0x0f }
10911203945Sweongyo	};
10912203945Sweongyo	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
10913203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
10914203945Sweongyo	const struct bwn_stxtable *st;
10915203945Sweongyo	struct ifnet *ifp = sc->sc_ifp;
10916203945Sweongyo	struct ieee80211com *ic = ifp->if_l2com;
10917203945Sweongyo	int i, error;
10918203945Sweongyo	uint16_t tmp;
10919203945Sweongyo
10920203945Sweongyo	bwn_phy_lp_readsprom(mac);	/* XXX bad place */
10921203945Sweongyo	bwn_phy_lp_bbinit(mac);
10922203945Sweongyo
10923203945Sweongyo	/* initialize RF */
10924203945Sweongyo	BWN_PHY_SET(mac, BWN_PHY_4WIRECTL, 0x2);
10925203945Sweongyo	DELAY(1);
10926203945Sweongyo	BWN_PHY_MASK(mac, BWN_PHY_4WIRECTL, 0xfffd);
10927203945Sweongyo	DELAY(1);
10928203945Sweongyo
10929203945Sweongyo	if (mac->mac_phy.rf_ver == 0x2062)
10930203945Sweongyo		bwn_phy_lp_b2062_init(mac);
10931203945Sweongyo	else {
10932203945Sweongyo		bwn_phy_lp_b2063_init(mac);
10933203945Sweongyo
10934203945Sweongyo		/* synchronize stx table. */
10935203945Sweongyo		for (i = 0; i < N(tables); i++) {
10936203945Sweongyo			st = &tables[i];
10937203945Sweongyo			tmp = BWN_RF_READ(mac, st->st_rfaddr);
10938203945Sweongyo			tmp >>= st->st_rfshift;
10939203945Sweongyo			tmp <<= st->st_physhift;
10940203945Sweongyo			BWN_PHY_SETMASK(mac,
10941203945Sweongyo			    BWN_PHY_OFDM(0xf2 + st->st_phyoffset),
10942203945Sweongyo			    ~(st->st_mask << st->st_physhift), tmp);
10943203945Sweongyo		}
10944203945Sweongyo
10945203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf0), 0x5f80);
10946203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf1), 0);
10947203945Sweongyo	}
10948203945Sweongyo
10949203945Sweongyo	/* calibrate RC */
10950203945Sweongyo	if (mac->mac_phy.rev >= 2)
10951203945Sweongyo		bwn_phy_lp_rxcal_r2(mac);
10952203945Sweongyo	else if (!plp->plp_rccap) {
10953203945Sweongyo		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
10954203945Sweongyo			bwn_phy_lp_rccal_r12(mac);
10955203945Sweongyo	} else
10956203945Sweongyo		bwn_phy_lp_set_rccap(mac);
10957203945Sweongyo
10958203945Sweongyo	error = bwn_phy_lp_switch_channel(mac, 7);
10959203945Sweongyo	if (error)
10960203945Sweongyo		device_printf(sc->sc_dev,
10961203945Sweongyo		    "failed to change channel 7 (%d)\n", error);
10962203945Sweongyo	bwn_phy_lp_txpctl_init(mac);
10963203945Sweongyo	bwn_phy_lp_calib(mac);
10964203945Sweongyo	return (0);
10965203945Sweongyo}
10966203945Sweongyo
10967203945Sweongyostatic uint16_t
10968203945Sweongyobwn_phy_lp_read(struct bwn_mac *mac, uint16_t reg)
10969203945Sweongyo{
10970203945Sweongyo
10971203945Sweongyo	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10972203945Sweongyo	return (BWN_READ_2(mac, BWN_PHYDATA));
10973203945Sweongyo}
10974203945Sweongyo
10975203945Sweongyostatic void
10976203945Sweongyobwn_phy_lp_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
10977203945Sweongyo{
10978203945Sweongyo
10979203945Sweongyo	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10980203945Sweongyo	BWN_WRITE_2(mac, BWN_PHYDATA, value);
10981203945Sweongyo}
10982203945Sweongyo
10983203945Sweongyostatic void
10984203945Sweongyobwn_phy_lp_maskset(struct bwn_mac *mac, uint16_t reg, uint16_t mask,
10985203945Sweongyo    uint16_t set)
10986203945Sweongyo{
10987203945Sweongyo
10988203945Sweongyo	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10989203945Sweongyo	BWN_WRITE_2(mac, BWN_PHYDATA,
10990203945Sweongyo	    (BWN_READ_2(mac, BWN_PHYDATA) & mask) | set);
10991203945Sweongyo}
10992203945Sweongyo
10993203945Sweongyostatic uint16_t
10994203945Sweongyobwn_phy_lp_rf_read(struct bwn_mac *mac, uint16_t reg)
10995203945Sweongyo{
10996203945Sweongyo
10997203945Sweongyo	KASSERT(reg != 1, ("unaccessible register %d", reg));
10998203945Sweongyo	if (mac->mac_phy.rev < 2 && reg != 0x4001)
10999203945Sweongyo		reg |= 0x100;
11000203945Sweongyo	if (mac->mac_phy.rev >= 2)
11001203945Sweongyo		reg |= 0x200;
11002203945Sweongyo	BWN_WRITE_2(mac, BWN_RFCTL, reg);
11003203945Sweongyo	return BWN_READ_2(mac, BWN_RFDATALO);
11004203945Sweongyo}
11005203945Sweongyo
11006203945Sweongyostatic void
11007203945Sweongyobwn_phy_lp_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
11008203945Sweongyo{
11009203945Sweongyo
11010203945Sweongyo	KASSERT(reg != 1, ("unaccessible register %d", reg));
11011203945Sweongyo	BWN_WRITE_2(mac, BWN_RFCTL, reg);
11012203945Sweongyo	BWN_WRITE_2(mac, BWN_RFDATALO, value);
11013203945Sweongyo}
11014203945Sweongyo
11015203945Sweongyostatic void
11016203945Sweongyobwn_phy_lp_rf_onoff(struct bwn_mac *mac, int on)
11017203945Sweongyo{
11018203945Sweongyo
11019203945Sweongyo	if (on) {
11020203945Sweongyo		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xe0ff);
11021203945Sweongyo		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2,
11022203945Sweongyo		    (mac->mac_phy.rev >= 2) ? 0xf7f7 : 0xffe7);
11023203945Sweongyo		return;
11024203945Sweongyo	}
11025203945Sweongyo
11026203945Sweongyo	if (mac->mac_phy.rev >= 2) {
11027203945Sweongyo		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x83ff);
11028203945Sweongyo		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
11029203945Sweongyo		BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0x80ff);
11030203945Sweongyo		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xdfff);
11031203945Sweongyo		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0808);
11032203945Sweongyo		return;
11033203945Sweongyo	}
11034203945Sweongyo
11035203945Sweongyo	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xe0ff);
11036203945Sweongyo	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
11037203945Sweongyo	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfcff);
11038203945Sweongyo	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0018);
11039203945Sweongyo}
11040203945Sweongyo
11041203945Sweongyostatic int
11042203945Sweongyobwn_phy_lp_switch_channel(struct bwn_mac *mac, uint32_t chan)
11043203945Sweongyo{
11044203945Sweongyo	struct bwn_phy *phy = &mac->mac_phy;
11045203945Sweongyo	struct bwn_phy_lp *plp = &phy->phy_lp;
11046203945Sweongyo	int error;
11047203945Sweongyo
11048203945Sweongyo	if (phy->rf_ver == 0x2063) {
11049203945Sweongyo		error = bwn_phy_lp_b2063_switch_channel(mac, chan);
11050203945Sweongyo		if (error)
11051203945Sweongyo			return (error);
11052203945Sweongyo	} else {
11053203945Sweongyo		error = bwn_phy_lp_b2062_switch_channel(mac, chan);
11054203945Sweongyo		if (error)
11055203945Sweongyo			return (error);
11056203945Sweongyo		bwn_phy_lp_set_anafilter(mac, chan);
11057203945Sweongyo		bwn_phy_lp_set_gaintbl(mac, ieee80211_ieee2mhz(chan, 0));
11058203945Sweongyo	}
11059203945Sweongyo
11060203945Sweongyo	plp->plp_chan = chan;
11061203945Sweongyo	BWN_WRITE_2(mac, BWN_CHANNEL, chan);
11062203945Sweongyo	return (0);
11063203945Sweongyo}
11064203945Sweongyo
11065203945Sweongyostatic uint32_t
11066203945Sweongyobwn_phy_lp_get_default_chan(struct bwn_mac *mac)
11067203945Sweongyo{
11068203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
11069203945Sweongyo	struct ifnet *ifp = sc->sc_ifp;
11070203945Sweongyo	struct ieee80211com *ic = ifp->if_l2com;
11071203945Sweongyo
11072203945Sweongyo	return (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? 1 : 36);
11073203945Sweongyo}
11074203945Sweongyo
11075203945Sweongyostatic void
11076203945Sweongyobwn_phy_lp_set_antenna(struct bwn_mac *mac, int antenna)
11077203945Sweongyo{
11078203945Sweongyo	struct bwn_phy *phy = &mac->mac_phy;
11079203945Sweongyo	struct bwn_phy_lp *plp = &phy->phy_lp;
11080203945Sweongyo
11081203945Sweongyo	if (phy->rev >= 2 || antenna > BWN_ANTAUTO1)
11082203945Sweongyo		return;
11083203945Sweongyo
11084203945Sweongyo	bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER);
11085203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffd, antenna & 0x2);
11086203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffe, antenna & 0x1);
11087203945Sweongyo	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_UCODE_ANTDIV_HELPER);
11088203945Sweongyo	plp->plp_antenna = antenna;
11089203945Sweongyo}
11090203945Sweongyo
11091203945Sweongyostatic void
11092203945Sweongyobwn_phy_lp_task_60s(struct bwn_mac *mac)
11093203945Sweongyo{
11094203945Sweongyo
11095203945Sweongyo	bwn_phy_lp_calib(mac);
11096203945Sweongyo}
11097203945Sweongyo
11098203945Sweongyostatic void
11099203945Sweongyobwn_phy_lp_readsprom(struct bwn_mac *mac)
11100203945Sweongyo{
11101203945Sweongyo	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11102203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
11103203945Sweongyo	struct ifnet *ifp = sc->sc_ifp;
11104203945Sweongyo	struct ieee80211com *ic = ifp->if_l2com;
11105203945Sweongyo
11106203945Sweongyo	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11107204922Sweongyo		plp->plp_txisoband_m = siba_sprom_get_tri2g(sc->sc_dev);
11108204922Sweongyo		plp->plp_bxarch = siba_sprom_get_bxa2g(sc->sc_dev);
11109204922Sweongyo		plp->plp_rxpwroffset = siba_sprom_get_rxpo2g(sc->sc_dev);
11110204922Sweongyo		plp->plp_rssivf = siba_sprom_get_rssismf2g(sc->sc_dev);
11111204922Sweongyo		plp->plp_rssivc = siba_sprom_get_rssismc2g(sc->sc_dev);
11112204922Sweongyo		plp->plp_rssigs = siba_sprom_get_rssisav2g(sc->sc_dev);
11113203945Sweongyo		return;
11114203945Sweongyo	}
11115203945Sweongyo
11116204922Sweongyo	plp->plp_txisoband_l = siba_sprom_get_tri5gl(sc->sc_dev);
11117204922Sweongyo	plp->plp_txisoband_m = siba_sprom_get_tri5g(sc->sc_dev);
11118204922Sweongyo	plp->plp_txisoband_h = siba_sprom_get_tri5gh(sc->sc_dev);
11119204922Sweongyo	plp->plp_bxarch = siba_sprom_get_bxa5g(sc->sc_dev);
11120204922Sweongyo	plp->plp_rxpwroffset = siba_sprom_get_rxpo5g(sc->sc_dev);
11121204922Sweongyo	plp->plp_rssivf = siba_sprom_get_rssismf5g(sc->sc_dev);
11122204922Sweongyo	plp->plp_rssivc = siba_sprom_get_rssismc5g(sc->sc_dev);
11123204922Sweongyo	plp->plp_rssigs = siba_sprom_get_rssisav5g(sc->sc_dev);
11124203945Sweongyo}
11125203945Sweongyo
11126203945Sweongyostatic void
11127203945Sweongyobwn_phy_lp_bbinit(struct bwn_mac *mac)
11128203945Sweongyo{
11129203945Sweongyo
11130203945Sweongyo	bwn_phy_lp_tblinit(mac);
11131203945Sweongyo	if (mac->mac_phy.rev >= 2)
11132203945Sweongyo		bwn_phy_lp_bbinit_r2(mac);
11133203945Sweongyo	else
11134203945Sweongyo		bwn_phy_lp_bbinit_r01(mac);
11135203945Sweongyo}
11136203945Sweongyo
11137203945Sweongyostatic void
11138203945Sweongyobwn_phy_lp_txpctl_init(struct bwn_mac *mac)
11139203945Sweongyo{
11140203945Sweongyo	struct bwn_txgain gain_2ghz = { 4, 12, 12, 0 };
11141203945Sweongyo	struct bwn_txgain gain_5ghz = { 7, 15, 14, 0 };
11142203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
11143203945Sweongyo	struct ifnet *ifp = sc->sc_ifp;
11144203945Sweongyo	struct ieee80211com *ic = ifp->if_l2com;
11145203945Sweongyo
11146203945Sweongyo	bwn_phy_lp_set_txgain(mac,
11147203945Sweongyo	    IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? &gain_2ghz : &gain_5ghz);
11148203945Sweongyo	bwn_phy_lp_set_bbmult(mac, 150);
11149203945Sweongyo}
11150203945Sweongyo
11151203945Sweongyostatic void
11152203945Sweongyobwn_phy_lp_calib(struct bwn_mac *mac)
11153203945Sweongyo{
11154203945Sweongyo	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11155203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
11156203945Sweongyo	struct ifnet *ifp = sc->sc_ifp;
11157203945Sweongyo	struct ieee80211com *ic = ifp->if_l2com;
11158203945Sweongyo	const struct bwn_rxcompco *rc = NULL;
11159203945Sweongyo	struct bwn_txgain ogain;
11160203945Sweongyo	int i, omode, oafeovr, orf, obbmult;
11161203945Sweongyo	uint8_t mode, fc = 0;
11162203945Sweongyo
11163203945Sweongyo	if (plp->plp_chanfullcal != plp->plp_chan) {
11164203945Sweongyo		plp->plp_chanfullcal = plp->plp_chan;
11165203945Sweongyo		fc = 1;
11166203945Sweongyo	}
11167203945Sweongyo
11168203945Sweongyo	bwn_mac_suspend(mac);
11169203945Sweongyo
11170203945Sweongyo	/* BlueTooth Coexistance Override */
11171203945Sweongyo	BWN_WRITE_2(mac, BWN_BTCOEX_CTL, 0x3);
11172203945Sweongyo	BWN_WRITE_2(mac, BWN_BTCOEX_TXCTL, 0xff);
11173203945Sweongyo
11174203945Sweongyo	if (mac->mac_phy.rev >= 2)
11175203945Sweongyo		bwn_phy_lp_digflt_save(mac);
11176203945Sweongyo	bwn_phy_lp_get_txpctlmode(mac);
11177203945Sweongyo	mode = plp->plp_txpctlmode;
11178203945Sweongyo	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11179203945Sweongyo	if (mac->mac_phy.rev == 0 && mode != BWN_PHYLP_TXPCTL_OFF)
11180203945Sweongyo		bwn_phy_lp_bugfix(mac);
11181203945Sweongyo	if (mac->mac_phy.rev >= 2 && fc == 1) {
11182203945Sweongyo		bwn_phy_lp_get_txpctlmode(mac);
11183203945Sweongyo		omode = plp->plp_txpctlmode;
11184203945Sweongyo		oafeovr = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40;
11185203945Sweongyo		if (oafeovr)
11186203945Sweongyo			ogain = bwn_phy_lp_get_txgain(mac);
11187203945Sweongyo		orf = BWN_PHY_READ(mac, BWN_PHY_RF_PWR_OVERRIDE) & 0xff;
11188203945Sweongyo		obbmult = bwn_phy_lp_get_bbmult(mac);
11189203945Sweongyo		bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11190203945Sweongyo		if (oafeovr)
11191203945Sweongyo			bwn_phy_lp_set_txgain(mac, &ogain);
11192203945Sweongyo		bwn_phy_lp_set_bbmult(mac, obbmult);
11193203945Sweongyo		bwn_phy_lp_set_txpctlmode(mac, omode);
11194203945Sweongyo		BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00, orf);
11195203945Sweongyo	}
11196203945Sweongyo	bwn_phy_lp_set_txpctlmode(mac, mode);
11197203945Sweongyo	if (mac->mac_phy.rev >= 2)
11198203945Sweongyo		bwn_phy_lp_digflt_restore(mac);
11199203945Sweongyo
11200203945Sweongyo	/* do RX IQ Calculation; assumes that noise is true. */
11201204922Sweongyo	if (siba_get_chipid(sc->sc_dev) == 0x5354) {
11202203945Sweongyo		for (i = 0; i < N(bwn_rxcompco_5354); i++) {
11203203945Sweongyo			if (bwn_rxcompco_5354[i].rc_chan == plp->plp_chan)
11204203945Sweongyo				rc = &bwn_rxcompco_5354[i];
11205203945Sweongyo		}
11206203945Sweongyo	} else if (mac->mac_phy.rev >= 2)
11207203945Sweongyo		rc = &bwn_rxcompco_r2;
11208203945Sweongyo	else {
11209203945Sweongyo		for (i = 0; i < N(bwn_rxcompco_r12); i++) {
11210203945Sweongyo			if (bwn_rxcompco_r12[i].rc_chan == plp->plp_chan)
11211203945Sweongyo				rc = &bwn_rxcompco_r12[i];
11212203945Sweongyo		}
11213203945Sweongyo	}
11214203945Sweongyo	if (rc == NULL)
11215203945Sweongyo		goto fail;
11216203945Sweongyo
11217203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, rc->rc_c1);
11218203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, rc->rc_c0 << 8);
11219203945Sweongyo
11220203945Sweongyo	bwn_phy_lp_set_trsw_over(mac, 1 /* TX */, 0 /* RX */);
11221203945Sweongyo
11222203945Sweongyo	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11223203945Sweongyo		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
11224203945Sweongyo		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7, 0);
11225203945Sweongyo	} else {
11226203945Sweongyo		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
11227203945Sweongyo		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf, 0);
11228203945Sweongyo	}
11229203945Sweongyo
11230203945Sweongyo	bwn_phy_lp_set_rxgain(mac, 0x2d5d);
11231203945Sweongyo	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11232203945Sweongyo	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
11233203945Sweongyo	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
11234203945Sweongyo	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
11235203945Sweongyo	bwn_phy_lp_set_deaf(mac, 0);
11236203945Sweongyo	/* XXX no checking return value? */
11237203945Sweongyo	(void)bwn_phy_lp_calc_rx_iq_comp(mac, 0xfff0);
11238203945Sweongyo	bwn_phy_lp_clear_deaf(mac, 0);
11239203945Sweongyo	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffc);
11240203945Sweongyo	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfff7);
11241203945Sweongyo	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffdf);
11242203945Sweongyo
11243203945Sweongyo	/* disable RX GAIN override. */
11244203945Sweongyo	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffe);
11245203945Sweongyo	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffef);
11246203945Sweongyo	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffbf);
11247203945Sweongyo	if (mac->mac_phy.rev >= 2) {
11248203945Sweongyo		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11249203945Sweongyo		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11250203945Sweongyo			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfbff);
11251203945Sweongyo			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xe5), 0xfff7);
11252203945Sweongyo		}
11253203945Sweongyo	} else {
11254203945Sweongyo		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfdff);
11255203945Sweongyo	}
11256203945Sweongyo
11257203945Sweongyo	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11258203945Sweongyo	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xf7ff);
11259203945Sweongyofail:
11260203945Sweongyo	bwn_mac_enable(mac);
11261203945Sweongyo}
11262203945Sweongyo
11263203945Sweongyostatic void
11264203945Sweongyobwn_phy_lp_switch_analog(struct bwn_mac *mac, int on)
11265203945Sweongyo{
11266203945Sweongyo
11267204922Sweongyo	if (on) {
11268204922Sweongyo		BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfff8);
11269204922Sweongyo		return;
11270204922Sweongyo	}
11271203945Sweongyo
11272204922Sweongyo	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVRVAL, 0x0007);
11273204922Sweongyo	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x0007);
11274203945Sweongyo}
11275203945Sweongyo
11276203945Sweongyostatic int
11277203945Sweongyobwn_phy_lp_b2063_switch_channel(struct bwn_mac *mac, uint8_t chan)
11278203945Sweongyo{
11279203945Sweongyo	static const struct bwn_b206x_chan *bc = NULL;
11280204922Sweongyo	struct bwn_softc *sc = mac->mac_sc;
11281203945Sweongyo	uint32_t count, freqref, freqvco, freqxtal, val[3], timeout, timeoutref,
11282203945Sweongyo	    tmp[6];
11283203945Sweongyo	uint16_t old, scale, tmp16;
11284203945Sweongyo	int i, div;
11285203945Sweongyo
11286203945Sweongyo	for (i = 0; i < N(bwn_b2063_chantable); i++) {
11287203945Sweongyo		if (bwn_b2063_chantable[i].bc_chan == chan) {
11288203945Sweongyo			bc = &bwn_b2063_chantable[i];
11289203945Sweongyo			break;
11290203945Sweongyo		}
11291203945Sweongyo	}
11292203945Sweongyo	if (bc == NULL)
11293203945Sweongyo		return (EINVAL);
11294203945Sweongyo
11295203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_VCOBUF1, bc->bc_data[0]);
11296203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_MIXER2, bc->bc_data[1]);
11297203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_BUF2, bc->bc_data[2]);
11298203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_RCCR1, bc->bc_data[3]);
11299203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2063_A_RX_1ST3, bc->bc_data[4]);
11300203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND1, bc->bc_data[5]);
11301203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND4, bc->bc_data[6]);
11302203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND7, bc->bc_data[7]);
11303203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2063_A_RX_PS6, bc->bc_data[8]);
11304203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL2, bc->bc_data[9]);
11305203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL5, bc->bc_data[10]);
11306203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2063_PA_CTL11, bc->bc_data[11]);
11307203945Sweongyo
11308203945Sweongyo	old = BWN_RF_READ(mac, BWN_B2063_COM15);
11309203945Sweongyo	BWN_RF_SET(mac, BWN_B2063_COM15, 0x1e);
11310203945Sweongyo
11311204922Sweongyo	freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
11312203945Sweongyo	freqvco = bc->bc_freq << ((bc->bc_freq > 4000) ? 1 : 2);
11313203945Sweongyo	freqref = freqxtal * 3;
11314203945Sweongyo	div = (freqxtal <= 26000000 ? 1 : 2);
11315203945Sweongyo	timeout = ((((8 * freqxtal) / (div * 5000000)) + 1) >> 1) - 1;
11316203945Sweongyo	timeoutref = ((((8 * freqxtal) / (div * (timeout + 1))) +
11317203945Sweongyo		999999) / 1000000) + 1;
11318203945Sweongyo
11319203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB3, 0x2);
11320203945Sweongyo	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB6,
11321203945Sweongyo	    0xfff8, timeout >> 2);
11322203945Sweongyo	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11323203945Sweongyo	    0xff9f,timeout << 5);
11324203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB5, timeoutref);
11325203945Sweongyo
11326203945Sweongyo	val[0] = bwn_phy_lp_roundup(freqxtal, 1000000, 16);
11327203945Sweongyo	val[1] = bwn_phy_lp_roundup(freqxtal, 1000000 * div, 16);
11328203945Sweongyo	val[2] = bwn_phy_lp_roundup(freqvco, 3, 16);
11329203945Sweongyo
11330203945Sweongyo	count = (bwn_phy_lp_roundup(val[2], val[1] + 16, 16) * (timeout + 1) *
11331203945Sweongyo	    (timeoutref + 1)) - 1;
11332203945Sweongyo	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11333203945Sweongyo	    0xf0, count >> 8);
11334203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB8, count & 0xff);
11335203945Sweongyo
11336203945Sweongyo	tmp[0] = ((val[2] * 62500) / freqref) << 4;
11337203945Sweongyo	tmp[1] = ((val[2] * 62500) % freqref) << 4;
11338203945Sweongyo	while (tmp[1] >= freqref) {
11339203945Sweongyo		tmp[0]++;
11340203945Sweongyo		tmp[1] -= freqref;
11341203945Sweongyo	}
11342203945Sweongyo	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG1, 0xffe0, tmp[0] >> 4);
11343203945Sweongyo	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfe0f, tmp[0] << 4);
11344203945Sweongyo	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfff0, tmp[0] >> 16);
11345203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG3, (tmp[1] >> 8) & 0xff);
11346203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG4, tmp[1] & 0xff);
11347203945Sweongyo
11348203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF1, 0xb9);
11349203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF2, 0x88);
11350203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF3, 0x28);
11351203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF4, 0x63);
11352203945Sweongyo
11353203945Sweongyo	tmp[2] = ((41 * (val[2] - 3000)) /1200) + 27;
11354203945Sweongyo	tmp[3] = bwn_phy_lp_roundup(132000 * tmp[0], 8451, 16);
11355203945Sweongyo
11356203945Sweongyo	if ((tmp[3] + tmp[2] - 1) / tmp[2] > 60) {
11357203945Sweongyo		scale = 1;
11358203945Sweongyo		tmp[4] = ((tmp[3] + tmp[2]) / (tmp[2] << 1)) - 8;
11359203945Sweongyo	} else {
11360203945Sweongyo		scale = 0;
11361203945Sweongyo		tmp[4] = ((tmp[3] + (tmp[2] >> 1)) / tmp[2]) - 8;
11362203945Sweongyo	}
11363203945Sweongyo	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffc0, tmp[4]);
11364203945Sweongyo	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffbf, scale << 6);
11365203945Sweongyo
11366203945Sweongyo	tmp[5] = bwn_phy_lp_roundup(100 * val[0], val[2], 16) * (tmp[4] * 8) *
11367203945Sweongyo	    (scale + 1);
11368203945Sweongyo	if (tmp[5] > 150)
11369203945Sweongyo		tmp[5] = 0;
11370203945Sweongyo
11371203945Sweongyo	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffe0, tmp[5]);
11372203945Sweongyo	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffdf, scale << 5);
11373203945Sweongyo
11374203945Sweongyo	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfffb, 0x4);
11375203945Sweongyo	if (freqxtal > 26000000)
11376203945Sweongyo		BWN_RF_SET(mac, BWN_B2063_JTAG_XTAL_12, 0x2);
11377203945Sweongyo	else
11378203945Sweongyo		BWN_RF_MASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfd);
11379203945Sweongyo
11380203945Sweongyo	if (val[0] == 45)
11381203945Sweongyo		BWN_RF_SET(mac, BWN_B2063_JTAG_VCO1, 0x2);
11382203945Sweongyo	else
11383203945Sweongyo		BWN_RF_MASK(mac, BWN_B2063_JTAG_VCO1, 0xfd);
11384203945Sweongyo
11385203945Sweongyo	BWN_RF_SET(mac, BWN_B2063_PLL_SP2, 0x3);
11386203945Sweongyo	DELAY(1);
11387203945Sweongyo	BWN_RF_MASK(mac, BWN_B2063_PLL_SP2, 0xfffc);
11388203945Sweongyo
11389203945Sweongyo	/* VCO Calibration */
11390203945Sweongyo	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, ~0x40);
11391203945Sweongyo	tmp16 = BWN_RF_READ(mac, BWN_B2063_JTAG_CALNRST) & 0xf8;
11392203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16);
11393203945Sweongyo	DELAY(1);
11394203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x4);
11395203945Sweongyo	DELAY(1);
11396203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x6);
11397203945Sweongyo	DELAY(1);
11398203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x7);
11399203945Sweongyo	DELAY(300);
11400203945Sweongyo	BWN_RF_SET(mac, BWN_B2063_PLL_SP1, 0x40);
11401203945Sweongyo
11402203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2063_COM15, old);
11403203945Sweongyo	return (0);
11404203945Sweongyo}
11405203945Sweongyo
11406203945Sweongyostatic int
11407203945Sweongyobwn_phy_lp_b2062_switch_channel(struct bwn_mac *mac, uint8_t chan)
11408203945Sweongyo{
11409204922Sweongyo	struct bwn_softc *sc = mac->mac_sc;
11410203945Sweongyo	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11411203945Sweongyo	const struct bwn_b206x_chan *bc = NULL;
11412204922Sweongyo	uint32_t freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
11413203945Sweongyo	uint32_t tmp[9];
11414203945Sweongyo	int i;
11415203945Sweongyo
11416203945Sweongyo	for (i = 0; i < N(bwn_b2062_chantable); i++) {
11417203945Sweongyo		if (bwn_b2062_chantable[i].bc_chan == chan) {
11418203945Sweongyo			bc = &bwn_b2062_chantable[i];
11419203945Sweongyo			break;
11420203945Sweongyo		}
11421203945Sweongyo	}
11422203945Sweongyo
11423203945Sweongyo	if (bc == NULL)
11424203945Sweongyo		return (EINVAL);
11425203945Sweongyo
11426203945Sweongyo	BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL14, 0x04);
11427203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE0, bc->bc_data[0]);
11428203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE2, bc->bc_data[1]);
11429203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE3, bc->bc_data[2]);
11430203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2062_N_TX_TUNE, bc->bc_data[3]);
11431203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2062_S_LGENG_CTL1, bc->bc_data[4]);
11432203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL5, bc->bc_data[5]);
11433203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL6, bc->bc_data[6]);
11434203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PGA, bc->bc_data[7]);
11435203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PAD, bc->bc_data[8]);
11436203945Sweongyo
11437203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xcc);
11438203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0x07);
11439203945Sweongyo	bwn_phy_lp_b2062_reset_pllbias(mac);
11440203945Sweongyo	tmp[0] = freqxtal / 1000;
11441203945Sweongyo	tmp[1] = plp->plp_div * 1000;
11442203945Sweongyo	tmp[2] = tmp[1] * ieee80211_ieee2mhz(chan, 0);
11443203945Sweongyo	if (ieee80211_ieee2mhz(chan, 0) < 4000)
11444203945Sweongyo		tmp[2] *= 2;
11445203945Sweongyo	tmp[3] = 48 * tmp[0];
11446203945Sweongyo	tmp[5] = tmp[2] / tmp[3];
11447203945Sweongyo	tmp[6] = tmp[2] % tmp[3];
11448203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL26, tmp[5]);
11449203945Sweongyo	tmp[4] = tmp[6] * 0x100;
11450203945Sweongyo	tmp[5] = tmp[4] / tmp[3];
11451203945Sweongyo	tmp[6] = tmp[4] % tmp[3];
11452203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL27, tmp[5]);
11453203945Sweongyo	tmp[4] = tmp[6] * 0x100;
11454203945Sweongyo	tmp[5] = tmp[4] / tmp[3];
11455203945Sweongyo	tmp[6] = tmp[4] % tmp[3];
11456203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL28, tmp[5]);
11457203945Sweongyo	tmp[4] = tmp[6] * 0x100;
11458203945Sweongyo	tmp[5] = tmp[4] / tmp[3];
11459203945Sweongyo	tmp[6] = tmp[4] % tmp[3];
11460203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL29,
11461203945Sweongyo	    tmp[5] + ((2 * tmp[6]) / tmp[3]));
11462203945Sweongyo	tmp[7] = BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL19);
11463203945Sweongyo	tmp[8] = ((2 * tmp[2] * (tmp[7] + 1)) + (3 * tmp[0])) / (6 * tmp[0]);
11464203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL23, (tmp[8] >> 8) + 16);
11465203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL24, tmp[8] & 0xff);
11466203945Sweongyo
11467203945Sweongyo	bwn_phy_lp_b2062_vco_calib(mac);
11468203945Sweongyo	if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11469203945Sweongyo		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xfc);
11470203945Sweongyo		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0);
11471203945Sweongyo		bwn_phy_lp_b2062_reset_pllbias(mac);
11472203945Sweongyo		bwn_phy_lp_b2062_vco_calib(mac);
11473203945Sweongyo		if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11474203945Sweongyo			BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11475203945Sweongyo			return (EIO);
11476203945Sweongyo		}
11477203945Sweongyo	}
11478203945Sweongyo	BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11479203945Sweongyo	return (0);
11480203945Sweongyo}
11481203945Sweongyo
11482203945Sweongyostatic void
11483203945Sweongyobwn_phy_lp_set_anafilter(struct bwn_mac *mac, uint8_t channel)
11484203945Sweongyo{
11485203945Sweongyo	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11486203945Sweongyo	uint16_t tmp = (channel == 14);
11487203945Sweongyo
11488203945Sweongyo	if (mac->mac_phy.rev < 2) {
11489203945Sweongyo		BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xfcff, tmp << 9);
11490203945Sweongyo		if ((mac->mac_phy.rev == 1) && (plp->plp_rccap))
11491203945Sweongyo			bwn_phy_lp_set_rccap(mac);
11492203945Sweongyo		return;
11493203945Sweongyo	}
11494203945Sweongyo
11495203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, 0x3f);
11496203945Sweongyo}
11497203945Sweongyo
11498203945Sweongyostatic void
11499203945Sweongyobwn_phy_lp_set_gaintbl(struct bwn_mac *mac, uint32_t freq)
11500203945Sweongyo{
11501203945Sweongyo	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11502203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
11503203945Sweongyo	struct ifnet *ifp = sc->sc_ifp;
11504203945Sweongyo	struct ieee80211com *ic = ifp->if_l2com;
11505203945Sweongyo	uint16_t iso, tmp[3];
11506203945Sweongyo
11507203945Sweongyo	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
11508203945Sweongyo
11509203945Sweongyo	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
11510203945Sweongyo		iso = plp->plp_txisoband_m;
11511203945Sweongyo	else if (freq <= 5320)
11512203945Sweongyo		iso = plp->plp_txisoband_l;
11513203945Sweongyo	else if (freq <= 5700)
11514203945Sweongyo		iso = plp->plp_txisoband_m;
11515203945Sweongyo	else
11516203945Sweongyo		iso = plp->plp_txisoband_h;
11517203945Sweongyo
11518203945Sweongyo	tmp[0] = ((iso - 26) / 12) << 12;
11519203945Sweongyo	tmp[1] = tmp[0] + 0x1000;
11520203945Sweongyo	tmp[2] = tmp[0] + 0x2000;
11521203945Sweongyo
11522203945Sweongyo	bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), 3, tmp);
11523203945Sweongyo	bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), 3, tmp);
11524203945Sweongyo}
11525203945Sweongyo
11526203945Sweongyostatic void
11527203945Sweongyobwn_phy_lp_digflt_save(struct bwn_mac *mac)
11528203945Sweongyo{
11529203945Sweongyo	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11530203945Sweongyo	int i;
11531203945Sweongyo	static const uint16_t addr[] = {
11532203945Sweongyo		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11533203945Sweongyo		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11534203945Sweongyo		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11535203945Sweongyo		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11536203945Sweongyo		BWN_PHY_OFDM(0xcf),
11537203945Sweongyo	};
11538203945Sweongyo	static const uint16_t val[] = {
11539203945Sweongyo		0xde5e, 0xe832, 0xe331, 0x4d26,
11540203945Sweongyo		0x0026, 0x1420, 0x0020, 0xfe08,
11541203945Sweongyo		0x0008,
11542203945Sweongyo	};
11543203945Sweongyo
11544203945Sweongyo	for (i = 0; i < N(addr); i++) {
11545203945Sweongyo		plp->plp_digfilt[i] = BWN_PHY_READ(mac, addr[i]);
11546203945Sweongyo		BWN_PHY_WRITE(mac, addr[i], val[i]);
11547203945Sweongyo	}
11548203945Sweongyo}
11549203945Sweongyo
11550203945Sweongyostatic void
11551203945Sweongyobwn_phy_lp_get_txpctlmode(struct bwn_mac *mac)
11552203945Sweongyo{
11553203945Sweongyo	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11554203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
11555203945Sweongyo	uint16_t ctl;
11556203945Sweongyo
11557203945Sweongyo	ctl = BWN_PHY_READ(mac, BWN_PHY_TX_PWR_CTL_CMD);
11558203945Sweongyo	switch (ctl & BWN_PHY_TX_PWR_CTL_CMD_MODE) {
11559203945Sweongyo	case BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF:
11560203945Sweongyo		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_OFF;
11561203945Sweongyo		break;
11562203945Sweongyo	case BWN_PHY_TX_PWR_CTL_CMD_MODE_SW:
11563203945Sweongyo		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_SW;
11564203945Sweongyo		break;
11565203945Sweongyo	case BWN_PHY_TX_PWR_CTL_CMD_MODE_HW:
11566203945Sweongyo		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_HW;
11567203945Sweongyo		break;
11568203945Sweongyo	default:
11569203945Sweongyo		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_UNKNOWN;
11570203945Sweongyo		device_printf(sc->sc_dev, "unknown command mode\n");
11571203945Sweongyo		break;
11572203945Sweongyo	}
11573203945Sweongyo}
11574203945Sweongyo
11575203945Sweongyostatic void
11576203945Sweongyobwn_phy_lp_set_txpctlmode(struct bwn_mac *mac, uint8_t mode)
11577203945Sweongyo{
11578203945Sweongyo	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11579203945Sweongyo	uint16_t ctl;
11580203945Sweongyo	uint8_t old;
11581203945Sweongyo
11582203945Sweongyo	bwn_phy_lp_get_txpctlmode(mac);
11583203945Sweongyo	old = plp->plp_txpctlmode;
11584203945Sweongyo	if (old == mode)
11585203945Sweongyo		return;
11586203945Sweongyo	plp->plp_txpctlmode = mode;
11587203945Sweongyo
11588203945Sweongyo	if (old != BWN_PHYLP_TXPCTL_ON_HW && mode == BWN_PHYLP_TXPCTL_ON_HW) {
11589203945Sweongyo		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD, 0xff80,
11590203945Sweongyo		    plp->plp_tssiidx);
11591203945Sweongyo		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_NNUM,
11592203945Sweongyo		    0x8fff, ((uint16_t)plp->plp_tssinpt << 16));
11593203945Sweongyo
11594203945Sweongyo		/* disable TX GAIN override */
11595203945Sweongyo		if (mac->mac_phy.rev < 2)
11596203945Sweongyo			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11597203945Sweongyo		else {
11598203945Sweongyo			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xff7f);
11599203945Sweongyo			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xbfff);
11600203945Sweongyo		}
11601203945Sweongyo		BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xffbf);
11602203945Sweongyo
11603203945Sweongyo		plp->plp_txpwridx = -1;
11604203945Sweongyo	}
11605203945Sweongyo	if (mac->mac_phy.rev >= 2) {
11606203945Sweongyo		if (mode == BWN_PHYLP_TXPCTL_ON_HW)
11607203945Sweongyo			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xd0), 0x2);
11608203945Sweongyo		else
11609203945Sweongyo			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xd0), 0xfffd);
11610203945Sweongyo	}
11611203945Sweongyo
11612203945Sweongyo	/* writes TX Power Control mode */
11613203945Sweongyo	switch (plp->plp_txpctlmode) {
11614203945Sweongyo	case BWN_PHYLP_TXPCTL_OFF:
11615203945Sweongyo		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF;
11616203945Sweongyo		break;
11617203945Sweongyo	case BWN_PHYLP_TXPCTL_ON_HW:
11618203945Sweongyo		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_HW;
11619203945Sweongyo		break;
11620203945Sweongyo	case BWN_PHYLP_TXPCTL_ON_SW:
11621203945Sweongyo		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_SW;
11622203945Sweongyo		break;
11623203945Sweongyo	default:
11624204242Simp		ctl = 0;
11625203945Sweongyo		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
11626203945Sweongyo	}
11627203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD,
11628203945Sweongyo	    (uint16_t)~BWN_PHY_TX_PWR_CTL_CMD_MODE, ctl);
11629203945Sweongyo}
11630203945Sweongyo
11631203945Sweongyostatic void
11632203945Sweongyobwn_phy_lp_bugfix(struct bwn_mac *mac)
11633203945Sweongyo{
11634203945Sweongyo	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11635203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
11636203945Sweongyo	const unsigned int size = 256;
11637203945Sweongyo	struct bwn_txgain tg;
11638203945Sweongyo	uint32_t rxcomp, txgain, coeff, rfpwr, *tabs;
11639203945Sweongyo	uint16_t tssinpt, tssiidx, value[2];
11640203945Sweongyo	uint8_t mode;
11641203945Sweongyo	int8_t txpwridx;
11642203945Sweongyo
11643203945Sweongyo	tabs = (uint32_t *)malloc(sizeof(uint32_t) * size, M_DEVBUF,
11644203945Sweongyo	    M_NOWAIT | M_ZERO);
11645203945Sweongyo	if (tabs == NULL) {
11646203945Sweongyo		device_printf(sc->sc_dev, "failed to allocate buffer.\n");
11647203945Sweongyo		return;
11648203945Sweongyo	}
11649203945Sweongyo
11650203945Sweongyo	bwn_phy_lp_get_txpctlmode(mac);
11651203945Sweongyo	mode = plp->plp_txpctlmode;
11652203945Sweongyo	txpwridx = plp->plp_txpwridx;
11653203945Sweongyo	tssinpt = plp->plp_tssinpt;
11654203945Sweongyo	tssiidx = plp->plp_tssiidx;
11655203945Sweongyo
11656203945Sweongyo	bwn_tab_read_multi(mac,
11657203945Sweongyo	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11658203945Sweongyo	    BWN_TAB_4(7, 0x140), size, tabs);
11659203945Sweongyo
11660203945Sweongyo	bwn_phy_lp_tblinit(mac);
11661203945Sweongyo	bwn_phy_lp_bbinit(mac);
11662203945Sweongyo	bwn_phy_lp_txpctl_init(mac);
11663203945Sweongyo	bwn_phy_lp_rf_onoff(mac, 1);
11664203945Sweongyo	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11665203945Sweongyo
11666203945Sweongyo	bwn_tab_write_multi(mac,
11667203945Sweongyo	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11668203945Sweongyo	    BWN_TAB_4(7, 0x140), size, tabs);
11669203945Sweongyo
11670203945Sweongyo	BWN_WRITE_2(mac, BWN_CHANNEL, plp->plp_chan);
11671203945Sweongyo	plp->plp_tssinpt = tssinpt;
11672203945Sweongyo	plp->plp_tssiidx = tssiidx;
11673203945Sweongyo	bwn_phy_lp_set_anafilter(mac, plp->plp_chan);
11674203945Sweongyo	if (txpwridx != -1) {
11675203945Sweongyo		/* set TX power by index */
11676203945Sweongyo		plp->plp_txpwridx = txpwridx;
11677203945Sweongyo		bwn_phy_lp_get_txpctlmode(mac);
11678203945Sweongyo		if (plp->plp_txpctlmode != BWN_PHYLP_TXPCTL_OFF)
11679203945Sweongyo			bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_ON_SW);
11680203945Sweongyo		if (mac->mac_phy.rev >= 2) {
11681203945Sweongyo			rxcomp = bwn_tab_read(mac,
11682203945Sweongyo			    BWN_TAB_4(7, txpwridx + 320));
11683203945Sweongyo			txgain = bwn_tab_read(mac,
11684203945Sweongyo			    BWN_TAB_4(7, txpwridx + 192));
11685203945Sweongyo			tg.tg_pad = (txgain >> 16) & 0xff;
11686203945Sweongyo			tg.tg_gm = txgain & 0xff;
11687203945Sweongyo			tg.tg_pga = (txgain >> 8) & 0xff;
11688203945Sweongyo			tg.tg_dac = (rxcomp >> 28) & 0xff;
11689203945Sweongyo			bwn_phy_lp_set_txgain(mac, &tg);
11690203945Sweongyo		} else {
11691203945Sweongyo			rxcomp = bwn_tab_read(mac,
11692203945Sweongyo			    BWN_TAB_4(10, txpwridx + 320));
11693203945Sweongyo			txgain = bwn_tab_read(mac,
11694203945Sweongyo			    BWN_TAB_4(10, txpwridx + 192));
11695203945Sweongyo			BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
11696203945Sweongyo			    0xf800, (txgain >> 4) & 0x7fff);
11697203945Sweongyo			bwn_phy_lp_set_txgain_dac(mac, txgain & 0x7);
11698203945Sweongyo			bwn_phy_lp_set_txgain_pa(mac, (txgain >> 24) & 0x7f);
11699203945Sweongyo		}
11700203945Sweongyo		bwn_phy_lp_set_bbmult(mac, (rxcomp >> 20) & 0xff);
11701203945Sweongyo
11702203945Sweongyo		/* set TX IQCC */
11703203945Sweongyo		value[0] = (rxcomp >> 10) & 0x3ff;
11704203945Sweongyo		value[1] = rxcomp & 0x3ff;
11705203945Sweongyo		bwn_tab_write_multi(mac, BWN_TAB_2(0, 80), 2, value);
11706203945Sweongyo
11707203945Sweongyo		coeff = bwn_tab_read(mac,
11708203945Sweongyo		    (mac->mac_phy.rev >= 2) ? BWN_TAB_4(7, txpwridx + 448) :
11709203945Sweongyo		    BWN_TAB_4(10, txpwridx + 448));
11710203945Sweongyo		bwn_tab_write(mac, BWN_TAB_2(0, 85), coeff & 0xffff);
11711203945Sweongyo		if (mac->mac_phy.rev >= 2) {
11712203945Sweongyo			rfpwr = bwn_tab_read(mac,
11713203945Sweongyo			    BWN_TAB_4(7, txpwridx + 576));
11714203945Sweongyo			BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00,
11715203945Sweongyo			    rfpwr & 0xffff);
11716203945Sweongyo		}
11717203945Sweongyo		bwn_phy_lp_set_txgain_override(mac);
11718203945Sweongyo	}
11719203945Sweongyo	if (plp->plp_rccap)
11720203945Sweongyo		bwn_phy_lp_set_rccap(mac);
11721203945Sweongyo	bwn_phy_lp_set_antenna(mac, plp->plp_antenna);
11722203945Sweongyo	bwn_phy_lp_set_txpctlmode(mac, mode);
11723203945Sweongyo	free(tabs, M_DEVBUF);
11724203945Sweongyo}
11725203945Sweongyo
11726203945Sweongyostatic void
11727203945Sweongyobwn_phy_lp_digflt_restore(struct bwn_mac *mac)
11728203945Sweongyo{
11729203945Sweongyo	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11730203945Sweongyo	int i;
11731203945Sweongyo	static const uint16_t addr[] = {
11732203945Sweongyo		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11733203945Sweongyo		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11734203945Sweongyo		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11735203945Sweongyo		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11736203945Sweongyo		BWN_PHY_OFDM(0xcf),
11737203945Sweongyo	};
11738203945Sweongyo
11739203945Sweongyo	for (i = 0; i < N(addr); i++)
11740203945Sweongyo		BWN_PHY_WRITE(mac, addr[i], plp->plp_digfilt[i]);
11741203945Sweongyo}
11742203945Sweongyo
11743203945Sweongyostatic void
11744203945Sweongyobwn_phy_lp_tblinit(struct bwn_mac *mac)
11745203945Sweongyo{
11746203945Sweongyo	uint32_t freq = ieee80211_ieee2mhz(bwn_phy_lp_get_default_chan(mac), 0);
11747203945Sweongyo
11748203945Sweongyo	if (mac->mac_phy.rev < 2) {
11749203945Sweongyo		bwn_phy_lp_tblinit_r01(mac);
11750203945Sweongyo		bwn_phy_lp_tblinit_txgain(mac);
11751203945Sweongyo		bwn_phy_lp_set_gaintbl(mac, freq);
11752203945Sweongyo		return;
11753203945Sweongyo	}
11754203945Sweongyo
11755203945Sweongyo	bwn_phy_lp_tblinit_r2(mac);
11756203945Sweongyo	bwn_phy_lp_tblinit_txgain(mac);
11757203945Sweongyo}
11758203945Sweongyo
11759203945Sweongyostruct bwn_wpair {
11760203945Sweongyo	uint16_t		reg;
11761203945Sweongyo	uint16_t		value;
11762203945Sweongyo};
11763203945Sweongyo
11764203945Sweongyostruct bwn_smpair {
11765203945Sweongyo	uint16_t		offset;
11766203945Sweongyo	uint16_t		mask;
11767203945Sweongyo	uint16_t		set;
11768203945Sweongyo};
11769203945Sweongyo
11770203945Sweongyostatic void
11771203945Sweongyobwn_phy_lp_bbinit_r2(struct bwn_mac *mac)
11772203945Sweongyo{
11773203945Sweongyo	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11774203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
11775203945Sweongyo	struct ifnet *ifp = sc->sc_ifp;
11776203945Sweongyo	struct ieee80211com *ic = ifp->if_l2com;
11777203945Sweongyo	static const struct bwn_wpair v1[] = {
11778203945Sweongyo		{ BWN_PHY_AFE_DAC_CTL, 0x50 },
11779203945Sweongyo		{ BWN_PHY_AFE_CTL, 0x8800 },
11780203945Sweongyo		{ BWN_PHY_AFE_CTL_OVR, 0 },
11781203945Sweongyo		{ BWN_PHY_AFE_CTL_OVRVAL, 0 },
11782203945Sweongyo		{ BWN_PHY_RF_OVERRIDE_0, 0 },
11783203945Sweongyo		{ BWN_PHY_RF_OVERRIDE_2, 0 },
11784203945Sweongyo		{ BWN_PHY_OFDM(0xf9), 0 },
11785203945Sweongyo		{ BWN_PHY_TR_LOOKUP_1, 0 }
11786203945Sweongyo	};
11787203945Sweongyo	static const struct bwn_smpair v2[] = {
11788203945Sweongyo		{ BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0xb4 },
11789203945Sweongyo		{ BWN_PHY_DCOFFSETTRANSIENT, 0xf8ff, 0x200 },
11790203945Sweongyo		{ BWN_PHY_DCOFFSETTRANSIENT, 0xff00, 0x7f },
11791203945Sweongyo		{ BWN_PHY_GAINDIRECTMISMATCH, 0xff0f, 0x40 },
11792203945Sweongyo		{ BWN_PHY_PREAMBLECONFIRMTO, 0xff00, 0x2 }
11793203945Sweongyo	};
11794203945Sweongyo	static const struct bwn_smpair v3[] = {
11795203945Sweongyo		{ BWN_PHY_OFDM(0xfe), 0xffe0, 0x1f },
11796203945Sweongyo		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11797203945Sweongyo		{ BWN_PHY_OFDM(0x100), 0xff00, 0x19 },
11798203945Sweongyo		{ BWN_PHY_OFDM(0xff), 0x03ff, 0x3c00 },
11799203945Sweongyo		{ BWN_PHY_OFDM(0xfe), 0xfc1f, 0x3e0 },
11800203945Sweongyo		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11801203945Sweongyo		{ BWN_PHY_OFDM(0x100), 0x00ff, 0x1900 },
11802203945Sweongyo		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800 },
11803203945Sweongyo		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x12 },
11804203945Sweongyo		{ BWN_PHY_GAINMISMATCH, 0x0fff, 0x9000 },
11805204922Sweongyo
11806203945Sweongyo	};
11807203945Sweongyo	int i;
11808203945Sweongyo
11809203945Sweongyo	for (i = 0; i < N(v1); i++)
11810203945Sweongyo		BWN_PHY_WRITE(mac, v1[i].reg, v1[i].value);
11811203945Sweongyo	BWN_PHY_SET(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x10);
11812203945Sweongyo	for (i = 0; i < N(v2); i++)
11813203945Sweongyo		BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask, v2[i].set);
11814203945Sweongyo
11815203945Sweongyo	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x4000);
11816203945Sweongyo	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x2000);
11817203945Sweongyo	BWN_PHY_SET(mac, BWN_PHY_OFDM(0x10a), 0x1);
11818204922Sweongyo	if (siba_get_pci_revid(sc->sc_dev) >= 0x18) {
11819203945Sweongyo		bwn_tab_write(mac, BWN_TAB_4(17, 65), 0xec);
11820203945Sweongyo		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x14);
11821203945Sweongyo	} else {
11822203945Sweongyo		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x10);
11823203945Sweongyo	}
11824203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0xff00, 0xf4);
11825203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0x00ff, 0xf100);
11826203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_CLIPTHRESH, 0x48);
11827203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0xff00, 0x46);
11828203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe4), 0xff00, 0x10);
11829203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_PWR_THRESH1, 0xfff0, 0x9);
11830203945Sweongyo	BWN_PHY_MASK(mac, BWN_PHY_GAINDIRECTMISMATCH, ~0xf);
11831203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5500);
11832203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0xa0);
11833203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_GAINDIRECTMISMATCH, 0xe0ff, 0x300);
11834203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2a00);
11835204922Sweongyo	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11836204922Sweongyo	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11837203945Sweongyo		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11838203945Sweongyo		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xa);
11839203945Sweongyo	} else {
11840203945Sweongyo		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x1e00);
11841203945Sweongyo		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xd);
11842203945Sweongyo	}
11843203945Sweongyo	for (i = 0; i < N(v3); i++)
11844203945Sweongyo		BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask, v3[i].set);
11845204922Sweongyo	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11846204922Sweongyo	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11847203945Sweongyo		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x14), 0);
11848203945Sweongyo		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x12), 0x40);
11849203945Sweongyo	}
11850203945Sweongyo
11851203945Sweongyo	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11852203945Sweongyo		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x40);
11853203945Sweongyo		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0xb00);
11854203945Sweongyo		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x6);
11855203945Sweongyo		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0x9d00);
11856203945Sweongyo		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0xff00, 0xa1);
11857203945Sweongyo		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
11858203945Sweongyo	} else
11859203945Sweongyo		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x40);
11860203945Sweongyo
11861203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0xff00, 0xb3);
11862203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00);
11863203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB, 0xff00, plp->plp_rxpwroffset);
11864203945Sweongyo	BWN_PHY_SET(mac, BWN_PHY_RESET_CTL, 0x44);
11865203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_RESET_CTL, 0x80);
11866203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, 0xa954);
11867203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_1,
11868203945Sweongyo	    0x2000 | ((uint16_t)plp->plp_rssigs << 10) |
11869203945Sweongyo	    ((uint16_t)plp->plp_rssivc << 4) | plp->plp_rssivf);
11870203945Sweongyo
11871204922Sweongyo	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11872204922Sweongyo	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11873203945Sweongyo		BWN_PHY_SET(mac, BWN_PHY_AFE_ADC_CTL_0, 0x1c);
11874203945Sweongyo		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_CTL, 0x00ff, 0x8800);
11875203945Sweongyo		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_1, 0xfc3c, 0x0400);
11876203945Sweongyo	}
11877203945Sweongyo
11878203945Sweongyo	bwn_phy_lp_digflt_save(mac);
11879203945Sweongyo}
11880203945Sweongyo
11881203945Sweongyostatic void
11882203945Sweongyobwn_phy_lp_bbinit_r01(struct bwn_mac *mac)
11883203945Sweongyo{
11884203945Sweongyo	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11885203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
11886203945Sweongyo	struct ifnet *ifp = sc->sc_ifp;
11887203945Sweongyo	struct ieee80211com *ic = ifp->if_l2com;
11888203945Sweongyo	static const struct bwn_smpair v1[] = {
11889203945Sweongyo		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x0005 },
11890203945Sweongyo		{ BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0x0180 },
11891203945Sweongyo		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x3c00 },
11892203945Sweongyo		{ BWN_PHY_GAINDIRECTMISMATCH, 0xfff0, 0x0005 },
11893203945Sweongyo		{ BWN_PHY_GAIN_MISMATCH_LIMIT, 0xffc0, 0x001a },
11894203945Sweongyo		{ BWN_PHY_CRS_ED_THRESH, 0xff00, 0x00b3 },
11895203945Sweongyo		{ BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00 }
11896203945Sweongyo	};
11897203945Sweongyo	static const struct bwn_smpair v2[] = {
11898203945Sweongyo		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11899203945Sweongyo		{ BWN_PHY_TR_LOOKUP_1, 0x3f00, 0x0900 },
11900203945Sweongyo		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11901203945Sweongyo		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11902203945Sweongyo		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x000a },
11903203945Sweongyo		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0400 },
11904203945Sweongyo		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x000a },
11905203945Sweongyo		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0b00 },
11906203945Sweongyo		{ BWN_PHY_TR_LOOKUP_5, 0xffc0, 0x000a },
11907203945Sweongyo		{ BWN_PHY_TR_LOOKUP_5, 0xc0ff, 0x0900 },
11908203945Sweongyo		{ BWN_PHY_TR_LOOKUP_6, 0xffc0, 0x000a },
11909203945Sweongyo		{ BWN_PHY_TR_LOOKUP_6, 0xc0ff, 0x0b00 },
11910203945Sweongyo		{ BWN_PHY_TR_LOOKUP_7, 0xffc0, 0x000a },
11911203945Sweongyo		{ BWN_PHY_TR_LOOKUP_7, 0xc0ff, 0x0900 },
11912203945Sweongyo		{ BWN_PHY_TR_LOOKUP_8, 0xffc0, 0x000a },
11913203945Sweongyo		{ BWN_PHY_TR_LOOKUP_8, 0xc0ff, 0x0b00 }
11914203945Sweongyo	};
11915203945Sweongyo	static const struct bwn_smpair v3[] = {
11916203945Sweongyo		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0001 },
11917203945Sweongyo		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0400 },
11918203945Sweongyo		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0001 },
11919203945Sweongyo		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0500 },
11920203945Sweongyo		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11921203945Sweongyo		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0800 },
11922203945Sweongyo		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11923203945Sweongyo		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0a00 }
11924203945Sweongyo	};
11925203945Sweongyo	static const struct bwn_smpair v4[] = {
11926203945Sweongyo		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0004 },
11927203945Sweongyo		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0800 },
11928203945Sweongyo		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0004 },
11929203945Sweongyo		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0c00 },
11930203945Sweongyo		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11931203945Sweongyo		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0100 },
11932203945Sweongyo		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11933203945Sweongyo		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0300 }
11934203945Sweongyo	};
11935203945Sweongyo	static const struct bwn_smpair v5[] = {
11936203945Sweongyo		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11937203945Sweongyo		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0900 },
11938203945Sweongyo		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11939203945Sweongyo		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11940203945Sweongyo		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0006 },
11941203945Sweongyo		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0500 },
11942203945Sweongyo		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0006 },
11943203945Sweongyo		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0700 }
11944203945Sweongyo	};
11945203945Sweongyo	int i;
11946203945Sweongyo	uint16_t tmp, tmp2;
11947203945Sweongyo
11948203945Sweongyo	BWN_PHY_MASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf7ff);
11949203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL, 0);
11950203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, 0);
11951203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, 0);
11952203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0);
11953203945Sweongyo	BWN_PHY_SET(mac, BWN_PHY_AFE_DAC_CTL, 0x0004);
11954203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0x0078);
11955203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800);
11956203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x0016);
11957203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_0, 0xfff8, 0x0004);
11958203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5400);
11959203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2400);
11960203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11961203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0x0006);
11962203945Sweongyo	BWN_PHY_MASK(mac, BWN_PHY_RX_RADIO_CTL, 0xfffe);
11963203945Sweongyo	for (i = 0; i < N(v1); i++)
11964203945Sweongyo		BWN_PHY_SETMASK(mac, v1[i].offset, v1[i].mask, v1[i].set);
11965203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB,
11966203945Sweongyo	    0xff00, plp->plp_rxpwroffset);
11967204922Sweongyo	if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM) &&
11968203945Sweongyo	    ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ||
11969204922Sweongyo	   (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_LDO_PAREF))) {
11970204922Sweongyo		siba_cc_pmu_set_ldovolt(sc->sc_dev, SIBA_LDO_PAREF, 0x28);
11971204922Sweongyo		siba_cc_pmu_set_ldoparef(sc->sc_dev, 1);
11972203945Sweongyo		if (mac->mac_phy.rev == 0)
11973203945Sweongyo			BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT,
11974203945Sweongyo			    0xffcf, 0x0010);
11975203945Sweongyo		bwn_tab_write(mac, BWN_TAB_2(11, 7), 60);
11976203945Sweongyo	} else {
11977204922Sweongyo		siba_cc_pmu_set_ldoparef(sc->sc_dev, 0);
11978203945Sweongyo		BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT, 0xffcf, 0x0020);
11979203945Sweongyo		bwn_tab_write(mac, BWN_TAB_2(11, 7), 100);
11980203945Sweongyo	}
11981203945Sweongyo	tmp = plp->plp_rssivf | plp->plp_rssivc << 4 | 0xa000;
11982203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, tmp);
11983204922Sweongyo	if (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_RSSIINV)
11984203945Sweongyo		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x0aaa);
11985203945Sweongyo	else
11986203945Sweongyo		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x02aa);
11987203945Sweongyo	bwn_tab_write(mac, BWN_TAB_2(11, 1), 24);
11988203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_RX_RADIO_CTL,
11989203945Sweongyo	    0xfff9, (plp->plp_bxarch << 1));
11990203945Sweongyo	if (mac->mac_phy.rev == 1 &&
11991204922Sweongyo	    (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_FEM_BT)) {
11992203945Sweongyo		for (i = 0; i < N(v2); i++)
11993203945Sweongyo			BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask,
11994203945Sweongyo			    v2[i].set);
11995203945Sweongyo	} else if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ||
11996204922Sweongyo	    (siba_get_pci_subdevice(sc->sc_dev) == 0x048a) ||
11997204922Sweongyo	    ((mac->mac_phy.rev == 0) &&
11998204922Sweongyo	     (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM))) {
11999203945Sweongyo		for (i = 0; i < N(v3); i++)
12000203945Sweongyo			BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask,
12001203945Sweongyo			    v3[i].set);
12002203945Sweongyo	} else if (mac->mac_phy.rev == 1 ||
12003204922Sweongyo		  (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM)) {
12004203945Sweongyo		for (i = 0; i < N(v4); i++)
12005203945Sweongyo			BWN_PHY_SETMASK(mac, v4[i].offset, v4[i].mask,
12006203945Sweongyo			    v4[i].set);
12007203945Sweongyo	} else {
12008203945Sweongyo		for (i = 0; i < N(v5); i++)
12009203945Sweongyo			BWN_PHY_SETMASK(mac, v5[i].offset, v5[i].mask,
12010203945Sweongyo			    v5[i].set);
12011203945Sweongyo	}
12012203945Sweongyo	if (mac->mac_phy.rev == 1 &&
12013204922Sweongyo	    (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_LDO_PAREF)) {
12014203945Sweongyo		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_5, BWN_PHY_TR_LOOKUP_1);
12015203945Sweongyo		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_6, BWN_PHY_TR_LOOKUP_2);
12016203945Sweongyo		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_7, BWN_PHY_TR_LOOKUP_3);
12017203945Sweongyo		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_8, BWN_PHY_TR_LOOKUP_4);
12018203945Sweongyo	}
12019204922Sweongyo	if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_FEM_BT) &&
12020204922Sweongyo	    (siba_get_chipid(sc->sc_dev) == 0x5354) &&
12021204922Sweongyo	    (siba_get_chippkg(sc->sc_dev) == SIBA_CHIPPACK_BCM4712S)) {
12022203945Sweongyo		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0006);
12023203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_SELECT, 0x0005);
12024203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_OUTEN, 0xffff);
12025203945Sweongyo		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_PR45960W);
12026203945Sweongyo	}
12027203945Sweongyo	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12028203945Sweongyo		BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x8000);
12029203945Sweongyo		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0040);
12030203945Sweongyo		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0xa400);
12031203945Sweongyo		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0x0b00);
12032203945Sweongyo		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x0007);
12033203945Sweongyo		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xfff8, 0x0003);
12034203945Sweongyo		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xffc7, 0x0020);
12035203945Sweongyo		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
12036203945Sweongyo	} else {
12037203945Sweongyo		BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0x7fff);
12038203945Sweongyo		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xffbf);
12039203945Sweongyo	}
12040203945Sweongyo	if (mac->mac_phy.rev == 1) {
12041203945Sweongyo		tmp = BWN_PHY_READ(mac, BWN_PHY_CLIPCTRTHRESH);
12042203945Sweongyo		tmp2 = (tmp & 0x03e0) >> 5;
12043203945Sweongyo		tmp2 |= tmp2 << 5;
12044203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_4C3, tmp2);
12045203945Sweongyo		tmp = BWN_PHY_READ(mac, BWN_PHY_GAINDIRECTMISMATCH);
12046203945Sweongyo		tmp2 = (tmp & 0x1f00) >> 8;
12047203945Sweongyo		tmp2 |= tmp2 << 5;
12048203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_4C4, tmp2);
12049203945Sweongyo		tmp = BWN_PHY_READ(mac, BWN_PHY_VERYLOWGAINDB);
12050203945Sweongyo		tmp2 = tmp & 0x00ff;
12051203945Sweongyo		tmp2 |= tmp << 8;
12052203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_4C5, tmp2);
12053203945Sweongyo	}
12054203945Sweongyo}
12055203945Sweongyo
12056203945Sweongyostruct bwn_b2062_freq {
12057203945Sweongyo	uint16_t		freq;
12058203945Sweongyo	uint8_t			value[6];
12059203945Sweongyo};
12060203945Sweongyo
12061203945Sweongyostatic void
12062203945Sweongyobwn_phy_lp_b2062_init(struct bwn_mac *mac)
12063203945Sweongyo{
12064203945Sweongyo#define	CALC_CTL7(freq, div)						\
12065203945Sweongyo	(((800000000 * (div) + (freq)) / (2 * (freq)) - 8) & 0xff)
12066203945Sweongyo#define	CALC_CTL18(freq, div)						\
12067203945Sweongyo	((((100 * (freq) + 16000000 * (div)) / (32000000 * (div))) - 1) & 0xff)
12068203945Sweongyo#define	CALC_CTL19(freq, div)						\
12069203945Sweongyo	((((2 * (freq) + 1000000 * (div)) / (2000000 * (div))) - 1) & 0xff)
12070203945Sweongyo	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12071203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
12072203945Sweongyo	struct ifnet *ifp = sc->sc_ifp;
12073203945Sweongyo	struct ieee80211com *ic = ifp->if_l2com;
12074203945Sweongyo	static const struct bwn_b2062_freq freqdata_tab[] = {
12075203945Sweongyo		{ 12000, { 6, 6, 6, 6, 10, 6 } },
12076203945Sweongyo		{ 13000, { 4, 4, 4, 4, 11, 7 } },
12077203945Sweongyo		{ 14400, { 3, 3, 3, 3, 12, 7 } },
12078203945Sweongyo		{ 16200, { 3, 3, 3, 3, 13, 8 } },
12079203945Sweongyo		{ 18000, { 2, 2, 2, 2, 14, 8 } },
12080203945Sweongyo		{ 19200, { 1, 1, 1, 1, 14, 9 } }
12081203945Sweongyo	};
12082203945Sweongyo	static const struct bwn_wpair v1[] = {
12083203945Sweongyo		{ BWN_B2062_N_TXCTL3, 0 },
12084203945Sweongyo		{ BWN_B2062_N_TXCTL4, 0 },
12085203945Sweongyo		{ BWN_B2062_N_TXCTL5, 0 },
12086203945Sweongyo		{ BWN_B2062_N_TXCTL6, 0 },
12087203945Sweongyo		{ BWN_B2062_N_PDNCTL0, 0x40 },
12088203945Sweongyo		{ BWN_B2062_N_PDNCTL0, 0 },
12089203945Sweongyo		{ BWN_B2062_N_CALIB_TS, 0x10 },
12090203945Sweongyo		{ BWN_B2062_N_CALIB_TS, 0 }
12091203945Sweongyo	};
12092203945Sweongyo	const struct bwn_b2062_freq *f = NULL;
12093203945Sweongyo	uint32_t xtalfreq, ref;
12094203945Sweongyo	unsigned int i;
12095203945Sweongyo
12096203945Sweongyo	bwn_phy_lp_b2062_tblinit(mac);
12097203945Sweongyo
12098203945Sweongyo	for (i = 0; i < N(v1); i++)
12099203945Sweongyo		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12100203945Sweongyo	if (mac->mac_phy.rev > 0)
12101203945Sweongyo		BWN_RF_WRITE(mac, BWN_B2062_S_BG_CTL1,
12102203945Sweongyo		    (BWN_RF_READ(mac, BWN_B2062_N_COM2) >> 1) | 0x80);
12103203945Sweongyo	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12104203945Sweongyo		BWN_RF_SET(mac, BWN_B2062_N_TSSI_CTL0, 0x1);
12105203945Sweongyo	else
12106203945Sweongyo		BWN_RF_MASK(mac, BWN_B2062_N_TSSI_CTL0, ~0x1);
12107203945Sweongyo
12108204922Sweongyo	KASSERT(siba_get_cc_caps(sc->sc_dev) & SIBA_CC_CAPS_PMU,
12109203945Sweongyo	    ("%s:%d: fail", __func__, __LINE__));
12110204922Sweongyo	xtalfreq = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
12111203945Sweongyo	KASSERT(xtalfreq != 0, ("%s:%d: fail", __func__, __LINE__));
12112203945Sweongyo
12113203945Sweongyo	if (xtalfreq <= 30000000) {
12114203945Sweongyo		plp->plp_div = 1;
12115203945Sweongyo		BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL1, 0xfffb);
12116203945Sweongyo	} else {
12117203945Sweongyo		plp->plp_div = 2;
12118203945Sweongyo		BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL1, 0x4);
12119203945Sweongyo	}
12120203945Sweongyo
12121203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL7,
12122203945Sweongyo	    CALC_CTL7(xtalfreq, plp->plp_div));
12123203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL18,
12124203945Sweongyo	    CALC_CTL18(xtalfreq, plp->plp_div));
12125203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL19,
12126203945Sweongyo	    CALC_CTL19(xtalfreq, plp->plp_div));
12127203945Sweongyo
12128203945Sweongyo	ref = (1000 * plp->plp_div + 2 * xtalfreq) / (2000 * plp->plp_div);
12129203945Sweongyo	ref &= 0xffff;
12130203945Sweongyo	for (i = 0; i < N(freqdata_tab); i++) {
12131203945Sweongyo		if (ref < freqdata_tab[i].freq) {
12132203945Sweongyo			f = &freqdata_tab[i];
12133203945Sweongyo			break;
12134203945Sweongyo		}
12135203945Sweongyo	}
12136203945Sweongyo	if (f == NULL)
12137203945Sweongyo		f = &freqdata_tab[N(freqdata_tab) - 1];
12138203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL8,
12139203945Sweongyo	    ((uint16_t)(f->value[1]) << 4) | f->value[0]);
12140203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL9,
12141203945Sweongyo	    ((uint16_t)(f->value[3]) << 4) | f->value[2]);
12142203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL10, f->value[4]);
12143203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL11, f->value[5]);
12144203945Sweongyo#undef CALC_CTL7
12145203945Sweongyo#undef CALC_CTL18
12146203945Sweongyo#undef CALC_CTL19
12147203945Sweongyo}
12148203945Sweongyo
12149203945Sweongyostatic void
12150203945Sweongyobwn_phy_lp_b2063_init(struct bwn_mac *mac)
12151203945Sweongyo{
12152203945Sweongyo
12153203945Sweongyo	bwn_phy_lp_b2063_tblinit(mac);
12154203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_SP5, 0);
12155203945Sweongyo	BWN_RF_SET(mac, BWN_B2063_COM8, 0x38);
12156203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2063_REG_SP1, 0x56);
12157203945Sweongyo	BWN_RF_MASK(mac, BWN_B2063_RX_BB_CTL2, ~0x2);
12158203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0);
12159203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP6, 0x20);
12160203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP9, 0x40);
12161203945Sweongyo	if (mac->mac_phy.rev == 2) {
12162203945Sweongyo		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0xa0);
12163203945Sweongyo		BWN_RF_WRITE(mac, BWN_B2063_PA_SP4, 0xa0);
12164203945Sweongyo		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x18);
12165203945Sweongyo	} else {
12166203945Sweongyo		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0x20);
12167203945Sweongyo		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x20);
12168203945Sweongyo	}
12169203945Sweongyo}
12170203945Sweongyo
12171203945Sweongyostatic void
12172203945Sweongyobwn_phy_lp_rxcal_r2(struct bwn_mac *mac)
12173203945Sweongyo{
12174204922Sweongyo	struct bwn_softc *sc = mac->mac_sc;
12175203945Sweongyo	static const struct bwn_wpair v1[] = {
12176203945Sweongyo		{ BWN_B2063_RX_BB_SP8, 0x0 },
12177203945Sweongyo		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
12178203945Sweongyo		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
12179203945Sweongyo		{ BWN_B2063_RC_CALIB_CTL2, 0x15 },
12180203945Sweongyo		{ BWN_B2063_RC_CALIB_CTL3, 0x70 },
12181203945Sweongyo		{ BWN_B2063_RC_CALIB_CTL4, 0x52 },
12182203945Sweongyo		{ BWN_B2063_RC_CALIB_CTL5, 0x1 },
12183203945Sweongyo		{ BWN_B2063_RC_CALIB_CTL1, 0x7d }
12184203945Sweongyo	};
12185203945Sweongyo	static const struct bwn_wpair v2[] = {
12186203945Sweongyo		{ BWN_B2063_TX_BB_SP3, 0x0 },
12187203945Sweongyo		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
12188203945Sweongyo		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
12189203945Sweongyo		{ BWN_B2063_RC_CALIB_CTL2, 0x55 },
12190203945Sweongyo		{ BWN_B2063_RC_CALIB_CTL3, 0x76 }
12191203945Sweongyo	};
12192204922Sweongyo	uint32_t freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
12193203945Sweongyo	int i;
12194203945Sweongyo	uint8_t tmp;
12195203945Sweongyo
12196203945Sweongyo	tmp = BWN_RF_READ(mac, BWN_B2063_RX_BB_SP8) & 0xff;
12197203945Sweongyo
12198203945Sweongyo	for (i = 0; i < 2; i++)
12199203945Sweongyo		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12200203945Sweongyo	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, 0xf7);
12201203945Sweongyo	for (i = 2; i < N(v1); i++)
12202203945Sweongyo		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12203203945Sweongyo	for (i = 0; i < 10000; i++) {
12204203945Sweongyo		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12205203945Sweongyo			break;
12206203945Sweongyo		DELAY(1000);
12207203945Sweongyo	}
12208203945Sweongyo
12209203945Sweongyo	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12210203945Sweongyo		BWN_RF_WRITE(mac, BWN_B2063_RX_BB_SP8, tmp);
12211203945Sweongyo
12212203945Sweongyo	tmp = BWN_RF_READ(mac, BWN_B2063_TX_BB_SP3) & 0xff;
12213203945Sweongyo
12214203945Sweongyo	for (i = 0; i < N(v2); i++)
12215203945Sweongyo		BWN_RF_WRITE(mac, v2[i].reg, v2[i].value);
12216203945Sweongyo	if (freqxtal == 24000000) {
12217203945Sweongyo		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0xfc);
12218203945Sweongyo		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x0);
12219203945Sweongyo	} else {
12220203945Sweongyo		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0x13);
12221203945Sweongyo		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x1);
12222203945Sweongyo	}
12223203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0x7d);
12224203945Sweongyo	for (i = 0; i < 10000; i++) {
12225203945Sweongyo		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12226203945Sweongyo			break;
12227203945Sweongyo		DELAY(1000);
12228203945Sweongyo	}
12229203945Sweongyo	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12230203945Sweongyo		BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, tmp);
12231203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL1, 0x7e);
12232203945Sweongyo}
12233203945Sweongyo
12234203945Sweongyostatic void
12235203945Sweongyobwn_phy_lp_rccal_r12(struct bwn_mac *mac)
12236203945Sweongyo{
12237203945Sweongyo	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12238203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
12239203945Sweongyo	struct bwn_phy_lp_iq_est ie;
12240203945Sweongyo	struct bwn_txgain tx_gains;
12241203945Sweongyo	static const uint32_t pwrtbl[21] = {
12242203945Sweongyo		0x10000, 0x10557, 0x10e2d, 0x113e0, 0x10f22, 0x0ff64,
12243203945Sweongyo		0x0eda2, 0x0e5d4, 0x0efd1, 0x0fbe8, 0x0b7b8, 0x04b35,
12244203945Sweongyo		0x01a5e, 0x00a0b, 0x00444, 0x001fd, 0x000ff, 0x00088,
12245203945Sweongyo		0x0004c, 0x0002c, 0x0001a,
12246203945Sweongyo	};
12247203945Sweongyo	uint32_t npwr, ipwr, sqpwr, tmp;
12248203945Sweongyo	int loopback, i, j, sum, error;
12249203945Sweongyo	uint16_t save[7];
12250203945Sweongyo	uint8_t txo, bbmult, txpctlmode;
12251203945Sweongyo
12252203945Sweongyo	error = bwn_phy_lp_switch_channel(mac, 7);
12253203945Sweongyo	if (error)
12254203945Sweongyo		device_printf(sc->sc_dev,
12255203945Sweongyo		    "failed to change channel to 7 (%d)\n", error);
12256203945Sweongyo	txo = (BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40) ? 1 : 0;
12257203945Sweongyo	bbmult = bwn_phy_lp_get_bbmult(mac);
12258203945Sweongyo	if (txo)
12259203945Sweongyo		tx_gains = bwn_phy_lp_get_txgain(mac);
12260203945Sweongyo
12261203945Sweongyo	save[0] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_0);
12262203945Sweongyo	save[1] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_VAL_0);
12263203945Sweongyo	save[2] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR);
12264203945Sweongyo	save[3] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVRVAL);
12265203945Sweongyo	save[4] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2);
12266203945Sweongyo	save[5] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2_VAL);
12267203945Sweongyo	save[6] = BWN_PHY_READ(mac, BWN_PHY_LP_PHY_CTL);
12268203945Sweongyo
12269203945Sweongyo	bwn_phy_lp_get_txpctlmode(mac);
12270203945Sweongyo	txpctlmode = plp->plp_txpctlmode;
12271203945Sweongyo	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
12272203945Sweongyo
12273203945Sweongyo	/* disable CRS */
12274203945Sweongyo	bwn_phy_lp_set_deaf(mac, 1);
12275203945Sweongyo	bwn_phy_lp_set_trsw_over(mac, 0, 1);
12276203945Sweongyo	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffb);
12277203945Sweongyo	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x4);
12278203945Sweongyo	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7);
12279203945Sweongyo	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
12280203945Sweongyo	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x10);
12281203945Sweongyo	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12282203945Sweongyo	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf);
12283203945Sweongyo	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
12284203945Sweongyo	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffbf);
12285203945Sweongyo	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12286203945Sweongyo	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x7);
12287203945Sweongyo	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x38);
12288203945Sweongyo	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f);
12289203945Sweongyo	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x100);
12290203945Sweongyo	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfdff);
12291203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL0, 0);
12292203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL1, 1);
12293203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL2, 0x20);
12294203945Sweongyo	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfbff);
12295203945Sweongyo	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xf7ff);
12296203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0);
12297203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, 0x45af);
12298203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0x3ff);
12299203945Sweongyo
12300203945Sweongyo	loopback = bwn_phy_lp_loopback(mac);
12301203945Sweongyo	if (loopback == -1)
12302203945Sweongyo		goto done;
12303203945Sweongyo	bwn_phy_lp_set_rxgain_idx(mac, loopback);
12304203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xffbf, 0x40);
12305203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfff8, 0x1);
12306203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xffc7, 0x8);
12307203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f, 0xc0);
12308203945Sweongyo
12309203945Sweongyo	tmp = 0;
12310203945Sweongyo	memset(&ie, 0, sizeof(ie));
12311203945Sweongyo	for (i = 128; i <= 159; i++) {
12312203945Sweongyo		BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2, i);
12313203945Sweongyo		sum = 0;
12314203945Sweongyo		for (j = 5; j <= 25; j++) {
12315203945Sweongyo			bwn_phy_lp_ddfs_turnon(mac, 1, 1, j, j, 0);
12316203945Sweongyo			if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
12317203945Sweongyo				goto done;
12318203945Sweongyo			sqpwr = ie.ie_ipwr + ie.ie_qpwr;
12319203945Sweongyo			ipwr = ((pwrtbl[j - 5] >> 3) + 1) >> 1;
12320203945Sweongyo			npwr = bwn_phy_lp_roundup(sqpwr, (j == 5) ? sqpwr : 0,
12321203945Sweongyo			    12);
12322203945Sweongyo			sum += ((ipwr - npwr) * (ipwr - npwr));
12323203945Sweongyo			if ((i == 128) || (sum < tmp)) {
12324203945Sweongyo				plp->plp_rccap = i;
12325203945Sweongyo				tmp = sum;
12326203945Sweongyo			}
12327203945Sweongyo		}
12328203945Sweongyo	}
12329203945Sweongyo	bwn_phy_lp_ddfs_turnoff(mac);
12330203945Sweongyodone:
12331203945Sweongyo	/* restore CRS */
12332203945Sweongyo	bwn_phy_lp_clear_deaf(mac, 1);
12333203945Sweongyo	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xff80);
12334203945Sweongyo	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfc00);
12335203945Sweongyo
12336203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_VAL_0, save[1]);
12337203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, save[0]);
12338203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVRVAL, save[3]);
12339203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, save[2]);
12340203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2_VAL, save[5]);
12341203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, save[4]);
12342203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_LP_PHY_CTL, save[6]);
12343203945Sweongyo
12344203945Sweongyo	bwn_phy_lp_set_bbmult(mac, bbmult);
12345203945Sweongyo	if (txo)
12346203945Sweongyo		bwn_phy_lp_set_txgain(mac, &tx_gains);
12347203945Sweongyo	bwn_phy_lp_set_txpctlmode(mac, txpctlmode);
12348203945Sweongyo	if (plp->plp_rccap)
12349203945Sweongyo		bwn_phy_lp_set_rccap(mac);
12350203945Sweongyo}
12351203945Sweongyo
12352203945Sweongyostatic void
12353203945Sweongyobwn_phy_lp_set_rccap(struct bwn_mac *mac)
12354203945Sweongyo{
12355203945Sweongyo	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12356203945Sweongyo	uint8_t rc_cap = (plp->plp_rccap & 0x1f) >> 1;
12357203945Sweongyo
12358203945Sweongyo	if (mac->mac_phy.rev == 1)
12359203945Sweongyo		rc_cap = MIN(rc_cap + 5, 15);
12360203945Sweongyo
12361203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2,
12362203945Sweongyo	    MAX(plp->plp_rccap - 4, 0x80));
12363203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, rc_cap | 0x80);
12364203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2062_S_RXG_CNT16,
12365203945Sweongyo	    ((plp->plp_rccap & 0x1f) >> 2) | 0x80);
12366203945Sweongyo}
12367203945Sweongyo
12368203945Sweongyostatic uint32_t
12369203945Sweongyobwn_phy_lp_roundup(uint32_t value, uint32_t div, uint8_t pre)
12370203945Sweongyo{
12371203945Sweongyo	uint32_t i, q, r;
12372203945Sweongyo
12373203945Sweongyo	if (div == 0)
12374203945Sweongyo		return (0);
12375203945Sweongyo
12376203945Sweongyo	for (i = 0, q = value / div, r = value % div; i < pre; i++) {
12377203945Sweongyo		q <<= 1;
12378203945Sweongyo		if (r << 1 >= div) {
12379203945Sweongyo			q++;
12380203945Sweongyo			r = (r << 1) - div;
12381203945Sweongyo		}
12382203945Sweongyo	}
12383203945Sweongyo	if (r << 1 >= div)
12384203945Sweongyo		q++;
12385203945Sweongyo	return (q);
12386203945Sweongyo}
12387203945Sweongyo
12388203945Sweongyostatic void
12389203945Sweongyobwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *mac)
12390203945Sweongyo{
12391204922Sweongyo	struct bwn_softc *sc = mac->mac_sc;
12392203945Sweongyo
12393203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0xff);
12394203945Sweongyo	DELAY(20);
12395204922Sweongyo	if (siba_get_chipid(sc->sc_dev) == 0x5354) {
12396203945Sweongyo		BWN_RF_WRITE(mac, BWN_B2062_N_COM1, 4);
12397203945Sweongyo		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 4);
12398203945Sweongyo	} else {
12399203945Sweongyo		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0);
12400203945Sweongyo	}
12401203945Sweongyo	DELAY(5);
12402203945Sweongyo}
12403203945Sweongyo
12404203945Sweongyostatic void
12405203945Sweongyobwn_phy_lp_b2062_vco_calib(struct bwn_mac *mac)
12406203945Sweongyo{
12407203945Sweongyo
12408203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x42);
12409203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x62);
12410203945Sweongyo	DELAY(200);
12411203945Sweongyo}
12412203945Sweongyo
12413203945Sweongyostatic void
12414203945Sweongyobwn_phy_lp_b2062_tblinit(struct bwn_mac *mac)
12415203945Sweongyo{
12416203945Sweongyo#define	FLAG_A	0x01
12417203945Sweongyo#define	FLAG_G	0x02
12418203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
12419203945Sweongyo	struct ifnet *ifp = sc->sc_ifp;
12420203945Sweongyo	struct ieee80211com *ic = ifp->if_l2com;
12421203945Sweongyo	static const struct bwn_b206x_rfinit_entry bwn_b2062_init_tab[] = {
12422203945Sweongyo		{ BWN_B2062_N_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12423203945Sweongyo		{ BWN_B2062_N_PDNCTL1, 0x0, 0xca, FLAG_G, },
12424203945Sweongyo		{ BWN_B2062_N_PDNCTL3, 0x0, 0x0, FLAG_A | FLAG_G, },
12425203945Sweongyo		{ BWN_B2062_N_PDNCTL4, 0x15, 0x2a, FLAG_A | FLAG_G, },
12426203945Sweongyo		{ BWN_B2062_N_LGENC, 0xDB, 0xff, FLAG_A, },
12427203945Sweongyo		{ BWN_B2062_N_LGENATUNE0, 0xdd, 0x0, FLAG_A | FLAG_G, },
12428203945Sweongyo		{ BWN_B2062_N_LGENATUNE2, 0xdd, 0x0, FLAG_A | FLAG_G, },
12429203945Sweongyo		{ BWN_B2062_N_LGENATUNE3, 0x77, 0xB5, FLAG_A | FLAG_G, },
12430203945Sweongyo		{ BWN_B2062_N_LGENACTL3, 0x0, 0xff, FLAG_A | FLAG_G, },
12431203945Sweongyo		{ BWN_B2062_N_LGENACTL7, 0x33, 0x33, FLAG_A | FLAG_G, },
12432203945Sweongyo		{ BWN_B2062_N_RXA_CTL1, 0x0, 0x0, FLAG_G, },
12433203945Sweongyo		{ BWN_B2062_N_RXBB_CTL0, 0x82, 0x80, FLAG_A | FLAG_G, },
12434203945Sweongyo		{ BWN_B2062_N_RXBB_GAIN1, 0x4, 0x4, FLAG_A | FLAG_G, },
12435203945Sweongyo		{ BWN_B2062_N_RXBB_GAIN2, 0x0, 0x0, FLAG_A | FLAG_G, },
12436203945Sweongyo		{ BWN_B2062_N_TXCTL4, 0x3, 0x3, FLAG_A | FLAG_G, },
12437203945Sweongyo		{ BWN_B2062_N_TXCTL5, 0x2, 0x2, FLAG_A | FLAG_G, },
12438203945Sweongyo		{ BWN_B2062_N_TX_TUNE, 0x88, 0x1b, FLAG_A | FLAG_G, },
12439203945Sweongyo		{ BWN_B2062_S_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12440203945Sweongyo		{ BWN_B2062_S_PDS_CTL0, 0xff, 0xff, FLAG_A | FLAG_G, },
12441203945Sweongyo		{ BWN_B2062_S_LGENG_CTL0, 0xf8, 0xd8, FLAG_A | FLAG_G, },
12442203945Sweongyo		{ BWN_B2062_S_LGENG_CTL1, 0x3c, 0x24, FLAG_A | FLAG_G, },
12443203945Sweongyo		{ BWN_B2062_S_LGENG_CTL8, 0x88, 0x80, FLAG_A | FLAG_G, },
12444203945Sweongyo		{ BWN_B2062_S_LGENG_CTL10, 0x88, 0x80, FLAG_A | FLAG_G, },
12445203945Sweongyo		{ BWN_B2062_S_RFPLLCTL0, 0x98, 0x98, FLAG_A | FLAG_G, },
12446203945Sweongyo		{ BWN_B2062_S_RFPLLCTL1, 0x10, 0x10, FLAG_A | FLAG_G, },
12447203945Sweongyo		{ BWN_B2062_S_RFPLLCTL5, 0x43, 0x43, FLAG_A | FLAG_G, },
12448203945Sweongyo		{ BWN_B2062_S_RFPLLCTL6, 0x47, 0x47, FLAG_A | FLAG_G, },
12449203945Sweongyo		{ BWN_B2062_S_RFPLLCTL7, 0xc, 0xc, FLAG_A | FLAG_G, },
12450203945Sweongyo		{ BWN_B2062_S_RFPLLCTL8, 0x11, 0x11, FLAG_A | FLAG_G, },
12451203945Sweongyo		{ BWN_B2062_S_RFPLLCTL9, 0x11, 0x11, FLAG_A | FLAG_G, },
12452203945Sweongyo		{ BWN_B2062_S_RFPLLCTL10, 0xe, 0xe, FLAG_A | FLAG_G, },
12453203945Sweongyo		{ BWN_B2062_S_RFPLLCTL11, 0x8, 0x8, FLAG_A | FLAG_G, },
12454203945Sweongyo		{ BWN_B2062_S_RFPLLCTL12, 0x33, 0x33, FLAG_A | FLAG_G, },
12455203945Sweongyo		{ BWN_B2062_S_RFPLLCTL13, 0xa, 0xa, FLAG_A | FLAG_G, },
12456203945Sweongyo		{ BWN_B2062_S_RFPLLCTL14, 0x6, 0x6, FLAG_A | FLAG_G, },
12457203945Sweongyo		{ BWN_B2062_S_RFPLLCTL18, 0x3e, 0x3e, FLAG_A | FLAG_G, },
12458203945Sweongyo		{ BWN_B2062_S_RFPLLCTL19, 0x13, 0x13, FLAG_A | FLAG_G, },
12459203945Sweongyo		{ BWN_B2062_S_RFPLLCTL21, 0x62, 0x62, FLAG_A | FLAG_G, },
12460203945Sweongyo		{ BWN_B2062_S_RFPLLCTL22, 0x7, 0x7, FLAG_A | FLAG_G, },
12461203945Sweongyo		{ BWN_B2062_S_RFPLLCTL23, 0x16, 0x16, FLAG_A | FLAG_G, },
12462203945Sweongyo		{ BWN_B2062_S_RFPLLCTL24, 0x5c, 0x5c, FLAG_A | FLAG_G, },
12463203945Sweongyo		{ BWN_B2062_S_RFPLLCTL25, 0x95, 0x95, FLAG_A | FLAG_G, },
12464203945Sweongyo		{ BWN_B2062_S_RFPLLCTL30, 0xa0, 0xa0, FLAG_A | FLAG_G, },
12465203945Sweongyo		{ BWN_B2062_S_RFPLLCTL31, 0x4, 0x4, FLAG_A | FLAG_G, },
12466203945Sweongyo		{ BWN_B2062_S_RFPLLCTL33, 0xcc, 0xcc, FLAG_A | FLAG_G, },
12467203945Sweongyo		{ BWN_B2062_S_RFPLLCTL34, 0x7, 0x7, FLAG_A | FLAG_G, },
12468203945Sweongyo		{ BWN_B2062_S_RXG_CNT8, 0xf, 0xf, FLAG_A, },
12469203945Sweongyo	};
12470203945Sweongyo	const struct bwn_b206x_rfinit_entry *br;
12471203945Sweongyo	unsigned int i;
12472203945Sweongyo
12473203945Sweongyo	for (i = 0; i < N(bwn_b2062_init_tab); i++) {
12474203945Sweongyo		br = &bwn_b2062_init_tab[i];
12475203945Sweongyo		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12476203945Sweongyo			if (br->br_flags & FLAG_G)
12477203945Sweongyo				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12478203945Sweongyo		} else {
12479203945Sweongyo			if (br->br_flags & FLAG_A)
12480203945Sweongyo				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12481203945Sweongyo		}
12482203945Sweongyo	}
12483203945Sweongyo#undef FLAG_A
12484203945Sweongyo#undef FLAG_B
12485203945Sweongyo}
12486203945Sweongyo
12487203945Sweongyostatic void
12488203945Sweongyobwn_phy_lp_b2063_tblinit(struct bwn_mac *mac)
12489203945Sweongyo{
12490203945Sweongyo#define	FLAG_A	0x01
12491203945Sweongyo#define	FLAG_G	0x02
12492203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
12493203945Sweongyo	struct ifnet *ifp = sc->sc_ifp;
12494203945Sweongyo	struct ieee80211com *ic = ifp->if_l2com;
12495203945Sweongyo	static const struct bwn_b206x_rfinit_entry bwn_b2063_init_tab[] = {
12496203945Sweongyo		{ BWN_B2063_COM1, 0x0, 0x0, FLAG_G, },
12497203945Sweongyo		{ BWN_B2063_COM10, 0x1, 0x0, FLAG_A, },
12498203945Sweongyo		{ BWN_B2063_COM16, 0x0, 0x0, FLAG_G, },
12499203945Sweongyo		{ BWN_B2063_COM17, 0x0, 0x0, FLAG_G, },
12500203945Sweongyo		{ BWN_B2063_COM18, 0x0, 0x0, FLAG_G, },
12501203945Sweongyo		{ BWN_B2063_COM19, 0x0, 0x0, FLAG_G, },
12502203945Sweongyo		{ BWN_B2063_COM20, 0x0, 0x0, FLAG_G, },
12503203945Sweongyo		{ BWN_B2063_COM21, 0x0, 0x0, FLAG_G, },
12504203945Sweongyo		{ BWN_B2063_COM22, 0x0, 0x0, FLAG_G, },
12505203945Sweongyo		{ BWN_B2063_COM23, 0x0, 0x0, FLAG_G, },
12506203945Sweongyo		{ BWN_B2063_COM24, 0x0, 0x0, FLAG_G, },
12507203945Sweongyo		{ BWN_B2063_LOGEN_SP1, 0xe8, 0xd4, FLAG_A | FLAG_G, },
12508203945Sweongyo		{ BWN_B2063_LOGEN_SP2, 0xa7, 0x53, FLAG_A | FLAG_G, },
12509203945Sweongyo		{ BWN_B2063_LOGEN_SP4, 0xf0, 0xf, FLAG_A | FLAG_G, },
12510203945Sweongyo		{ BWN_B2063_G_RX_SP1, 0x1f, 0x5e, FLAG_G, },
12511203945Sweongyo		{ BWN_B2063_G_RX_SP2, 0x7f, 0x7e, FLAG_G, },
12512203945Sweongyo		{ BWN_B2063_G_RX_SP3, 0x30, 0xf0, FLAG_G, },
12513203945Sweongyo		{ BWN_B2063_G_RX_SP7, 0x7f, 0x7f, FLAG_A | FLAG_G, },
12514203945Sweongyo		{ BWN_B2063_G_RX_SP10, 0xc, 0xc, FLAG_A | FLAG_G, },
12515203945Sweongyo		{ BWN_B2063_A_RX_SP1, 0x3c, 0x3f, FLAG_A, },
12516203945Sweongyo		{ BWN_B2063_A_RX_SP2, 0xfc, 0xfe, FLAG_A, },
12517203945Sweongyo		{ BWN_B2063_A_RX_SP7, 0x8, 0x8, FLAG_A | FLAG_G, },
12518203945Sweongyo		{ BWN_B2063_RX_BB_SP4, 0x60, 0x60, FLAG_A | FLAG_G, },
12519203945Sweongyo		{ BWN_B2063_RX_BB_SP8, 0x30, 0x30, FLAG_A | FLAG_G, },
12520203945Sweongyo		{ BWN_B2063_TX_RF_SP3, 0xc, 0xb, FLAG_A | FLAG_G, },
12521203945Sweongyo		{ BWN_B2063_TX_RF_SP4, 0x10, 0xf, FLAG_A | FLAG_G, },
12522203945Sweongyo		{ BWN_B2063_PA_SP1, 0x3d, 0xfd, FLAG_A | FLAG_G, },
12523203945Sweongyo		{ BWN_B2063_TX_BB_SP1, 0x2, 0x2, FLAG_A | FLAG_G, },
12524203945Sweongyo		{ BWN_B2063_BANDGAP_CTL1, 0x56, 0x56, FLAG_A | FLAG_G, },
12525203945Sweongyo		{ BWN_B2063_JTAG_VCO2, 0xF7, 0xF7, FLAG_A | FLAG_G, },
12526203945Sweongyo		{ BWN_B2063_G_RX_MIX3, 0x71, 0x71, FLAG_A | FLAG_G, },
12527203945Sweongyo		{ BWN_B2063_G_RX_MIX4, 0x71, 0x71, FLAG_A | FLAG_G, },
12528203945Sweongyo		{ BWN_B2063_A_RX_1ST2, 0xf0, 0x30, FLAG_A, },
12529203945Sweongyo		{ BWN_B2063_A_RX_PS6, 0x77, 0x77, FLAG_A | FLAG_G, },
12530203945Sweongyo		{ BWN_B2063_A_RX_MIX4, 0x3, 0x3, FLAG_A | FLAG_G, },
12531203945Sweongyo		{ BWN_B2063_A_RX_MIX5, 0xf, 0xf, FLAG_A | FLAG_G, },
12532203945Sweongyo		{ BWN_B2063_A_RX_MIX6, 0xf, 0xf, FLAG_A | FLAG_G, },
12533203945Sweongyo		{ BWN_B2063_RX_TIA_CTL1, 0x77, 0x77, FLAG_A | FLAG_G, },
12534203945Sweongyo		{ BWN_B2063_RX_TIA_CTL3, 0x77, 0x77, FLAG_A | FLAG_G, },
12535203945Sweongyo		{ BWN_B2063_RX_BB_CTL2, 0x4, 0x4, FLAG_A | FLAG_G, },
12536203945Sweongyo		{ BWN_B2063_PA_CTL1, 0x0, 0x4, FLAG_A, },
12537203945Sweongyo		{ BWN_B2063_VREG_CTL1, 0x3, 0x3, FLAG_A | FLAG_G, },
12538203945Sweongyo	};
12539203945Sweongyo	const struct bwn_b206x_rfinit_entry *br;
12540203945Sweongyo	unsigned int i;
12541203945Sweongyo
12542203945Sweongyo	for (i = 0; i < N(bwn_b2063_init_tab); i++) {
12543203945Sweongyo		br = &bwn_b2063_init_tab[i];
12544203945Sweongyo		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12545203945Sweongyo			if (br->br_flags & FLAG_G)
12546203945Sweongyo				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12547203945Sweongyo		} else {
12548203945Sweongyo			if (br->br_flags & FLAG_A)
12549203945Sweongyo				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12550203945Sweongyo		}
12551203945Sweongyo	}
12552203945Sweongyo#undef FLAG_A
12553203945Sweongyo#undef FLAG_B
12554203945Sweongyo}
12555203945Sweongyo
12556203945Sweongyostatic void
12557203945Sweongyobwn_tab_read_multi(struct bwn_mac *mac, uint32_t typenoffset,
12558203945Sweongyo    int count, void *_data)
12559203945Sweongyo{
12560203945Sweongyo	unsigned int i;
12561203945Sweongyo	uint32_t offset, type;
12562203945Sweongyo	uint8_t *data = _data;
12563203945Sweongyo
12564203945Sweongyo	type = BWN_TAB_GETTYPE(typenoffset);
12565203945Sweongyo	offset = BWN_TAB_GETOFFSET(typenoffset);
12566203945Sweongyo	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12567203945Sweongyo
12568203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12569203945Sweongyo
12570203945Sweongyo	for (i = 0; i < count; i++) {
12571203945Sweongyo		switch (type) {
12572203945Sweongyo		case BWN_TAB_8BIT:
12573203945Sweongyo			*data = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
12574203945Sweongyo			data++;
12575203945Sweongyo			break;
12576203945Sweongyo		case BWN_TAB_16BIT:
12577203945Sweongyo			*((uint16_t *)data) = BWN_PHY_READ(mac,
12578203945Sweongyo			    BWN_PHY_TABLEDATALO);
12579203945Sweongyo			data += 2;
12580203945Sweongyo			break;
12581203945Sweongyo		case BWN_TAB_32BIT:
12582203945Sweongyo			*((uint32_t *)data) = BWN_PHY_READ(mac,
12583203945Sweongyo			    BWN_PHY_TABLEDATAHI);
12584203945Sweongyo			*((uint32_t *)data) <<= 16;
12585203945Sweongyo			*((uint32_t *)data) |= BWN_PHY_READ(mac,
12586203945Sweongyo			    BWN_PHY_TABLEDATALO);
12587203945Sweongyo			data += 4;
12588203945Sweongyo			break;
12589203945Sweongyo		default:
12590203945Sweongyo			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12591203945Sweongyo		}
12592203945Sweongyo	}
12593203945Sweongyo}
12594203945Sweongyo
12595203945Sweongyostatic void
12596203945Sweongyobwn_tab_write_multi(struct bwn_mac *mac, uint32_t typenoffset,
12597203945Sweongyo    int count, const void *_data)
12598203945Sweongyo{
12599203945Sweongyo	uint32_t offset, type, value;
12600203945Sweongyo	const uint8_t *data = _data;
12601203945Sweongyo	unsigned int i;
12602203945Sweongyo
12603203945Sweongyo	type = BWN_TAB_GETTYPE(typenoffset);
12604203945Sweongyo	offset = BWN_TAB_GETOFFSET(typenoffset);
12605203945Sweongyo	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12606203945Sweongyo
12607203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12608203945Sweongyo
12609203945Sweongyo	for (i = 0; i < count; i++) {
12610203945Sweongyo		switch (type) {
12611203945Sweongyo		case BWN_TAB_8BIT:
12612203945Sweongyo			value = *data;
12613203945Sweongyo			data++;
12614203945Sweongyo			KASSERT(!(value & ~0xff),
12615203945Sweongyo			    ("%s:%d: fail", __func__, __LINE__));
12616203945Sweongyo			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12617203945Sweongyo			break;
12618203945Sweongyo		case BWN_TAB_16BIT:
12619203945Sweongyo			value = *((const uint16_t *)data);
12620203945Sweongyo			data += 2;
12621203945Sweongyo			KASSERT(!(value & ~0xffff),
12622203945Sweongyo			    ("%s:%d: fail", __func__, __LINE__));
12623203945Sweongyo			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12624203945Sweongyo			break;
12625203945Sweongyo		case BWN_TAB_32BIT:
12626203945Sweongyo			value = *((const uint32_t *)data);
12627203945Sweongyo			data += 4;
12628203945Sweongyo			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
12629203945Sweongyo			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12630203945Sweongyo			break;
12631203945Sweongyo		default:
12632203945Sweongyo			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12633203945Sweongyo		}
12634203945Sweongyo	}
12635203945Sweongyo}
12636203945Sweongyo
12637203945Sweongyostatic struct bwn_txgain
12638203945Sweongyobwn_phy_lp_get_txgain(struct bwn_mac *mac)
12639203945Sweongyo{
12640203945Sweongyo	struct bwn_txgain tg;
12641203945Sweongyo	uint16_t tmp;
12642203945Sweongyo
12643203945Sweongyo	tg.tg_dac = (BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0x380) >> 7;
12644203945Sweongyo	if (mac->mac_phy.rev < 2) {
12645203945Sweongyo		tmp = BWN_PHY_READ(mac,
12646203945Sweongyo		    BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL) & 0x7ff;
12647203945Sweongyo		tg.tg_gm = tmp & 0x0007;
12648203945Sweongyo		tg.tg_pga = (tmp & 0x0078) >> 3;
12649203945Sweongyo		tg.tg_pad = (tmp & 0x780) >> 7;
12650203945Sweongyo		return (tg);
12651203945Sweongyo	}
12652203945Sweongyo
12653203945Sweongyo	tmp = BWN_PHY_READ(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL);
12654203945Sweongyo	tg.tg_pad = BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0xff;
12655203945Sweongyo	tg.tg_gm = tmp & 0xff;
12656203945Sweongyo	tg.tg_pga = (tmp >> 8) & 0xff;
12657203945Sweongyo	return (tg);
12658203945Sweongyo}
12659203945Sweongyo
12660203945Sweongyostatic uint8_t
12661203945Sweongyobwn_phy_lp_get_bbmult(struct bwn_mac *mac)
12662203945Sweongyo{
12663203945Sweongyo
12664203945Sweongyo	return (bwn_tab_read(mac, BWN_TAB_2(0, 87)) & 0xff00) >> 8;
12665203945Sweongyo}
12666203945Sweongyo
12667203945Sweongyostatic void
12668203945Sweongyobwn_phy_lp_set_txgain(struct bwn_mac *mac, struct bwn_txgain *tg)
12669203945Sweongyo{
12670203945Sweongyo	uint16_t pa;
12671203945Sweongyo
12672203945Sweongyo	if (mac->mac_phy.rev < 2) {
12673203945Sweongyo		BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0xf800,
12674203945Sweongyo		    (tg->tg_pad << 7) | (tg->tg_pga << 3) | tg->tg_gm);
12675203945Sweongyo		bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12676203945Sweongyo		bwn_phy_lp_set_txgain_override(mac);
12677203945Sweongyo		return;
12678203945Sweongyo	}
12679203945Sweongyo
12680203945Sweongyo	pa = bwn_phy_lp_get_pa_gain(mac);
12681203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
12682203945Sweongyo	    (tg->tg_pga << 8) | tg->tg_gm);
12683203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0x8000,
12684203945Sweongyo	    tg->tg_pad | (pa << 6));
12685203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xfc), (tg->tg_pga << 8) | tg->tg_gm);
12686203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x8000,
12687203945Sweongyo	    tg->tg_pad | (pa << 8));
12688203945Sweongyo	bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12689203945Sweongyo	bwn_phy_lp_set_txgain_override(mac);
12690203945Sweongyo}
12691203945Sweongyo
12692203945Sweongyostatic void
12693203945Sweongyobwn_phy_lp_set_bbmult(struct bwn_mac *mac, uint8_t bbmult)
12694203945Sweongyo{
12695203945Sweongyo
12696203945Sweongyo	bwn_tab_write(mac, BWN_TAB_2(0, 87), (uint16_t)bbmult << 8);
12697203945Sweongyo}
12698203945Sweongyo
12699203945Sweongyostatic void
12700203945Sweongyobwn_phy_lp_set_trsw_over(struct bwn_mac *mac, uint8_t tx, uint8_t rx)
12701203945Sweongyo{
12702203945Sweongyo	uint16_t trsw = (tx << 1) | rx;
12703203945Sweongyo
12704203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffc, trsw);
12705203945Sweongyo	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x3);
12706203945Sweongyo}
12707203945Sweongyo
12708203945Sweongyostatic void
12709203945Sweongyobwn_phy_lp_set_rxgain(struct bwn_mac *mac, uint32_t gain)
12710203945Sweongyo{
12711203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
12712203945Sweongyo	struct ifnet *ifp = sc->sc_ifp;
12713203945Sweongyo	struct ieee80211com *ic = ifp->if_l2com;
12714203945Sweongyo	uint16_t ext_lna, high_gain, lna, low_gain, trsw, tmp;
12715203945Sweongyo
12716203945Sweongyo	if (mac->mac_phy.rev < 2) {
12717203945Sweongyo		trsw = gain & 0x1;
12718203945Sweongyo		lna = (gain & 0xfffc) | ((gain & 0xc) >> 2);
12719203945Sweongyo		ext_lna = (gain & 2) >> 1;
12720203945Sweongyo
12721203945Sweongyo		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12722203945Sweongyo		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12723203945Sweongyo		    0xfbff, ext_lna << 10);
12724203945Sweongyo		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12725203945Sweongyo		    0xf7ff, ext_lna << 11);
12726203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, lna);
12727203945Sweongyo	} else {
12728203945Sweongyo		low_gain = gain & 0xffff;
12729203945Sweongyo		high_gain = (gain >> 16) & 0xf;
12730203945Sweongyo		ext_lna = (gain >> 21) & 0x1;
12731203945Sweongyo		trsw = ~(gain >> 20) & 0x1;
12732203945Sweongyo
12733203945Sweongyo		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12734203945Sweongyo		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12735203945Sweongyo		    0xfdff, ext_lna << 9);
12736203945Sweongyo		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12737203945Sweongyo		    0xfbff, ext_lna << 10);
12738203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, low_gain);
12739203945Sweongyo		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff0, high_gain);
12740203945Sweongyo		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12741203945Sweongyo			tmp = (gain >> 2) & 0x3;
12742203945Sweongyo			BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12743203945Sweongyo			    0xe7ff, tmp<<11);
12744203945Sweongyo			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe6), 0xffe7,
12745203945Sweongyo			    tmp << 3);
12746203945Sweongyo		}
12747203945Sweongyo	}
12748203945Sweongyo
12749203945Sweongyo	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1);
12750203945Sweongyo	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12751203945Sweongyo	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12752203945Sweongyo	if (mac->mac_phy.rev >= 2) {
12753203945Sweongyo		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
12754203945Sweongyo		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12755203945Sweongyo			BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x400);
12756203945Sweongyo			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xe5), 0x8);
12757203945Sweongyo		}
12758203945Sweongyo		return;
12759203945Sweongyo	}
12760203945Sweongyo	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x200);
12761203945Sweongyo}
12762203945Sweongyo
12763203945Sweongyostatic void
12764203945Sweongyobwn_phy_lp_set_deaf(struct bwn_mac *mac, uint8_t user)
12765203945Sweongyo{
12766203945Sweongyo	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12767203945Sweongyo
12768203945Sweongyo	if (user)
12769203945Sweongyo		plp->plp_crsusr_off = 1;
12770203945Sweongyo	else
12771203945Sweongyo		plp->plp_crssys_off = 1;
12772203945Sweongyo
12773203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x80);
12774203945Sweongyo}
12775203945Sweongyo
12776203945Sweongyostatic void
12777203945Sweongyobwn_phy_lp_clear_deaf(struct bwn_mac *mac, uint8_t user)
12778203945Sweongyo{
12779203945Sweongyo	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12780203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
12781203945Sweongyo	struct ifnet *ifp = sc->sc_ifp;
12782203945Sweongyo	struct ieee80211com *ic = ifp->if_l2com;
12783203945Sweongyo
12784203945Sweongyo	if (user)
12785203945Sweongyo		plp->plp_crsusr_off = 0;
12786203945Sweongyo	else
12787203945Sweongyo		plp->plp_crssys_off = 0;
12788203945Sweongyo
12789203945Sweongyo	if (plp->plp_crsusr_off || plp->plp_crssys_off)
12790203945Sweongyo		return;
12791203945Sweongyo
12792203945Sweongyo	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12793203945Sweongyo		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x60);
12794203945Sweongyo	else
12795203945Sweongyo		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x20);
12796203945Sweongyo}
12797203945Sweongyo
12798203945Sweongyostatic unsigned int
12799203945Sweongyobwn_sqrt(struct bwn_mac *mac, unsigned int x)
12800203945Sweongyo{
12801203945Sweongyo	/* Table holding (10 * sqrt(x)) for x between 1 and 256. */
12802203945Sweongyo	static uint8_t sqrt_table[256] = {
12803203945Sweongyo		10, 14, 17, 20, 22, 24, 26, 28,
12804203945Sweongyo		30, 31, 33, 34, 36, 37, 38, 40,
12805203945Sweongyo		41, 42, 43, 44, 45, 46, 47, 48,
12806203945Sweongyo		50, 50, 51, 52, 53, 54, 55, 56,
12807203945Sweongyo		57, 58, 59, 60, 60, 61, 62, 63,
12808203945Sweongyo		64, 64, 65, 66, 67, 67, 68, 69,
12809203945Sweongyo		70, 70, 71, 72, 72, 73, 74, 74,
12810203945Sweongyo		75, 76, 76, 77, 78, 78, 79, 80,
12811203945Sweongyo		80, 81, 81, 82, 83, 83, 84, 84,
12812203945Sweongyo		85, 86, 86, 87, 87, 88, 88, 89,
12813203945Sweongyo		90, 90, 91, 91, 92, 92, 93, 93,
12814203945Sweongyo		94, 94, 95, 95, 96, 96, 97, 97,
12815203945Sweongyo		98, 98, 99, 100, 100, 100, 101, 101,
12816203945Sweongyo		102, 102, 103, 103, 104, 104, 105, 105,
12817203945Sweongyo		106, 106, 107, 107, 108, 108, 109, 109,
12818203945Sweongyo		110, 110, 110, 111, 111, 112, 112, 113,
12819203945Sweongyo		113, 114, 114, 114, 115, 115, 116, 116,
12820203945Sweongyo		117, 117, 117, 118, 118, 119, 119, 120,
12821203945Sweongyo		120, 120, 121, 121, 122, 122, 122, 123,
12822203945Sweongyo		123, 124, 124, 124, 125, 125, 126, 126,
12823203945Sweongyo		126, 127, 127, 128, 128, 128, 129, 129,
12824203945Sweongyo		130, 130, 130, 131, 131, 131, 132, 132,
12825203945Sweongyo		133, 133, 133, 134, 134, 134, 135, 135,
12826203945Sweongyo		136, 136, 136, 137, 137, 137, 138, 138,
12827203945Sweongyo		138, 139, 139, 140, 140, 140, 141, 141,
12828203945Sweongyo		141, 142, 142, 142, 143, 143, 143, 144,
12829203945Sweongyo		144, 144, 145, 145, 145, 146, 146, 146,
12830203945Sweongyo		147, 147, 147, 148, 148, 148, 149, 149,
12831203945Sweongyo		150, 150, 150, 150, 151, 151, 151, 152,
12832203945Sweongyo		152, 152, 153, 153, 153, 154, 154, 154,
12833203945Sweongyo		155, 155, 155, 156, 156, 156, 157, 157,
12834203945Sweongyo		157, 158, 158, 158, 159, 159, 159, 160
12835203945Sweongyo	};
12836203945Sweongyo
12837203945Sweongyo	if (x == 0)
12838203945Sweongyo		return (0);
12839203945Sweongyo	if (x >= 256) {
12840204542Sweongyo		unsigned int tmp;
12841204542Sweongyo
12842204542Sweongyo		for (tmp = 0; x >= (2 * tmp) + 1; x -= (2 * tmp++) + 1)
12843204542Sweongyo			/* do nothing */ ;
12844204542Sweongyo		return (tmp);
12845203945Sweongyo	}
12846203945Sweongyo	return (sqrt_table[x - 1] / 10);
12847203945Sweongyo}
12848203945Sweongyo
12849203945Sweongyostatic int
12850203945Sweongyobwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *mac, uint16_t sample)
12851203945Sweongyo{
12852203945Sweongyo#define	CALC_COEFF(_v, _x, _y, _z)	do {				\
12853203945Sweongyo	int _t;								\
12854203945Sweongyo	_t = _x - 20;							\
12855203945Sweongyo	if (_t >= 0) {							\
12856203945Sweongyo		_v = ((_y << (30 - _x)) + (_z >> (1 + _t))) / (_z >> _t); \
12857203945Sweongyo	} else {							\
12858203945Sweongyo		_v = ((_y << (30 - _x)) + (_z << (-1 - _t))) / (_z << -_t); \
12859203945Sweongyo	}								\
12860203945Sweongyo} while (0)
12861203945Sweongyo#define	CALC_COEFF2(_v, _x, _y, _z)	do {				\
12862203945Sweongyo	int _t;								\
12863203945Sweongyo	_t = _x - 11;							\
12864203945Sweongyo	if (_t >= 0)							\
12865203945Sweongyo		tmp[3] = (_y << (31 - _x)) / (_z >> _t);		\
12866203945Sweongyo	else								\
12867203945Sweongyo		tmp[3] = (_y << (31 - _x)) / (_z << -_t);		\
12868203945Sweongyo} while (0)
12869203945Sweongyo	struct bwn_phy_lp_iq_est ie;
12870203945Sweongyo	uint16_t v0, v1;
12871203945Sweongyo	int tmp[2], ret;
12872203945Sweongyo
12873203945Sweongyo	v1 = BWN_PHY_READ(mac, BWN_PHY_RX_COMP_COEFF_S);
12874203945Sweongyo	v0 = v1 >> 8;
12875203945Sweongyo	v1 |= 0xff;
12876203945Sweongyo
12877203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, 0x00c0);
12878203945Sweongyo	BWN_PHY_MASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff);
12879203945Sweongyo
12880203945Sweongyo	ret = bwn_phy_lp_rx_iq_est(mac, sample, 32, &ie);
12881203945Sweongyo	if (ret == 0)
12882203945Sweongyo		goto done;
12883203945Sweongyo
12884203945Sweongyo	if (ie.ie_ipwr + ie.ie_qpwr < 2) {
12885203945Sweongyo		ret = 0;
12886203945Sweongyo		goto done;
12887203945Sweongyo	}
12888203945Sweongyo
12889203945Sweongyo	CALC_COEFF(tmp[0], bwn_nbits(ie.ie_iqprod), ie.ie_iqprod, ie.ie_ipwr);
12890203945Sweongyo	CALC_COEFF2(tmp[1], bwn_nbits(ie.ie_qpwr), ie.ie_qpwr, ie.ie_ipwr);
12891203945Sweongyo
12892203945Sweongyo	tmp[1] = -bwn_sqrt(mac, tmp[1] - (tmp[0] * tmp[0]));
12893203945Sweongyo	v0 = tmp[0] >> 3;
12894203945Sweongyo	v1 = tmp[1] >> 4;
12895203945Sweongyodone:
12896203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, v1);
12897203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, v0 << 8);
12898203945Sweongyo	return ret;
12899203945Sweongyo#undef CALC_COEFF
12900203945Sweongyo#undef CALC_COEFF2
12901203945Sweongyo}
12902203945Sweongyo
12903203945Sweongyostatic void
12904203945Sweongyobwn_phy_lp_tblinit_r01(struct bwn_mac *mac)
12905203945Sweongyo{
12906203945Sweongyo	static const uint16_t noisescale[] = {
12907203945Sweongyo		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12908203945Sweongyo		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa400, 0xa4a4, 0xa4a4,
12909203945Sweongyo		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12910203945Sweongyo		0xa4a4, 0xa4a4, 0x00a4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12911203945Sweongyo		0x0000, 0x0000, 0x4c00, 0x2d36, 0x0000, 0x0000, 0x4c00, 0x2d36,
12912203945Sweongyo	};
12913203945Sweongyo	static const uint16_t crsgainnft[] = {
12914203945Sweongyo		0x0366, 0x036a, 0x036f, 0x0364, 0x0367, 0x036d, 0x0374, 0x037f,
12915203945Sweongyo		0x036f, 0x037b, 0x038a, 0x0378, 0x0367, 0x036d, 0x0375, 0x0381,
12916203945Sweongyo		0x0374, 0x0381, 0x0392, 0x03a9, 0x03c4, 0x03e1, 0x0001, 0x001f,
12917203945Sweongyo		0x0040, 0x005e, 0x007f, 0x009e, 0x00bd, 0x00dd, 0x00fd, 0x011d,
12918203945Sweongyo		0x013d,
12919203945Sweongyo	};
12920203945Sweongyo	static const uint16_t filterctl[] = {
12921203945Sweongyo		0xa0fc, 0x10fc, 0x10db, 0x20b7, 0xff93, 0x10bf, 0x109b, 0x2077,
12922203945Sweongyo		0xff53, 0x0127,
12923203945Sweongyo	};
12924203945Sweongyo	static const uint32_t psctl[] = {
12925203945Sweongyo		0x00010000, 0x000000a0, 0x00040000, 0x00000048, 0x08080101,
12926203945Sweongyo		0x00000080, 0x08080101, 0x00000040, 0x08080101, 0x000000c0,
12927203945Sweongyo		0x08a81501, 0x000000c0, 0x0fe8fd01, 0x000000c0, 0x08300105,
12928203945Sweongyo		0x000000c0, 0x08080201, 0x000000c0, 0x08280205, 0x000000c0,
12929203945Sweongyo		0xe80802fe, 0x000000c7, 0x28080206, 0x000000c0, 0x08080202,
12930203945Sweongyo		0x000000c0, 0x0ba87602, 0x000000c0, 0x1068013d, 0x000000c0,
12931203945Sweongyo		0x10280105, 0x000000c0, 0x08880102, 0x000000c0, 0x08280106,
12932203945Sweongyo		0x000000c0, 0xe80801fd, 0x000000c7, 0xa8080115, 0x000000c0,
12933203945Sweongyo	};
12934203945Sweongyo	static const uint16_t ofdmcckgain_r0[] = {
12935203945Sweongyo		0x0001, 0x0001, 0x0001, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12936203945Sweongyo		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12937203945Sweongyo		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12938203945Sweongyo		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12939203945Sweongyo		0x755d,
12940203945Sweongyo	};
12941203945Sweongyo	static const uint16_t ofdmcckgain_r1[] = {
12942203945Sweongyo		0x5000, 0x6000, 0x7000, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12943203945Sweongyo		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12944203945Sweongyo		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12945203945Sweongyo		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12946203945Sweongyo		0x755d,
12947203945Sweongyo	};
12948203945Sweongyo	static const uint16_t gaindelta[] = {
12949203945Sweongyo		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12950203945Sweongyo		0x0000,
12951203945Sweongyo	};
12952203945Sweongyo	static const uint32_t txpwrctl[] = {
12953203945Sweongyo		0x00000050, 0x0000004f, 0x0000004e, 0x0000004d, 0x0000004c,
12954203945Sweongyo		0x0000004b, 0x0000004a, 0x00000049, 0x00000048, 0x00000047,
12955203945Sweongyo		0x00000046, 0x00000045, 0x00000044, 0x00000043, 0x00000042,
12956203945Sweongyo		0x00000041, 0x00000040, 0x0000003f, 0x0000003e, 0x0000003d,
12957203945Sweongyo		0x0000003c, 0x0000003b, 0x0000003a, 0x00000039, 0x00000038,
12958203945Sweongyo		0x00000037, 0x00000036, 0x00000035, 0x00000034, 0x00000033,
12959203945Sweongyo		0x00000032, 0x00000031, 0x00000030, 0x0000002f, 0x0000002e,
12960203945Sweongyo		0x0000002d, 0x0000002c, 0x0000002b, 0x0000002a, 0x00000029,
12961203945Sweongyo		0x00000028, 0x00000027, 0x00000026, 0x00000025, 0x00000024,
12962203945Sweongyo		0x00000023, 0x00000022, 0x00000021, 0x00000020, 0x0000001f,
12963203945Sweongyo		0x0000001e, 0x0000001d, 0x0000001c, 0x0000001b, 0x0000001a,
12964203945Sweongyo		0x00000019, 0x00000018, 0x00000017, 0x00000016, 0x00000015,
12965203945Sweongyo		0x00000014, 0x00000013, 0x00000012, 0x00000011, 0x00000000,
12966203945Sweongyo		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12967203945Sweongyo		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12968203945Sweongyo		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12969203945Sweongyo		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12970203945Sweongyo		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12971203945Sweongyo		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12972203945Sweongyo		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12973203945Sweongyo		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12974203945Sweongyo		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12975203945Sweongyo		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12976203945Sweongyo		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12977203945Sweongyo		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12978203945Sweongyo		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12979203945Sweongyo		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12980203945Sweongyo		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12981203945Sweongyo		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12982203945Sweongyo		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12983203945Sweongyo		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12984203945Sweongyo		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12985203945Sweongyo		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12986203945Sweongyo		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12987203945Sweongyo		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12988203945Sweongyo		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12989203945Sweongyo		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12990203945Sweongyo		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12991203945Sweongyo		0x00000000, 0x00000000, 0x000075a0, 0x000075a0, 0x000075a1,
12992203945Sweongyo		0x000075a1, 0x000075a2, 0x000075a2, 0x000075a3, 0x000075a3,
12993203945Sweongyo		0x000074b0, 0x000074b0, 0x000074b1, 0x000074b1, 0x000074b2,
12994203945Sweongyo		0x000074b2, 0x000074b3, 0x000074b3, 0x00006d20, 0x00006d20,
12995203945Sweongyo		0x00006d21, 0x00006d21, 0x00006d22, 0x00006d22, 0x00006d23,
12996203945Sweongyo		0x00006d23, 0x00004660, 0x00004660, 0x00004661, 0x00004661,
12997203945Sweongyo		0x00004662, 0x00004662, 0x00004663, 0x00004663, 0x00003e60,
12998203945Sweongyo		0x00003e60, 0x00003e61, 0x00003e61, 0x00003e62, 0x00003e62,
12999203945Sweongyo		0x00003e63, 0x00003e63, 0x00003660, 0x00003660, 0x00003661,
13000203945Sweongyo		0x00003661, 0x00003662, 0x00003662, 0x00003663, 0x00003663,
13001203945Sweongyo		0x00002e60, 0x00002e60, 0x00002e61, 0x00002e61, 0x00002e62,
13002203945Sweongyo		0x00002e62, 0x00002e63, 0x00002e63, 0x00002660, 0x00002660,
13003203945Sweongyo		0x00002661, 0x00002661, 0x00002662, 0x00002662, 0x00002663,
13004203945Sweongyo		0x00002663, 0x000025e0, 0x000025e0, 0x000025e1, 0x000025e1,
13005203945Sweongyo		0x000025e2, 0x000025e2, 0x000025e3, 0x000025e3, 0x00001de0,
13006203945Sweongyo		0x00001de0, 0x00001de1, 0x00001de1, 0x00001de2, 0x00001de2,
13007203945Sweongyo		0x00001de3, 0x00001de3, 0x00001d60, 0x00001d60, 0x00001d61,
13008203945Sweongyo		0x00001d61, 0x00001d62, 0x00001d62, 0x00001d63, 0x00001d63,
13009203945Sweongyo		0x00001560, 0x00001560, 0x00001561, 0x00001561, 0x00001562,
13010203945Sweongyo		0x00001562, 0x00001563, 0x00001563, 0x00000d60, 0x00000d60,
13011203945Sweongyo		0x00000d61, 0x00000d61, 0x00000d62, 0x00000d62, 0x00000d63,
13012203945Sweongyo		0x00000d63, 0x00000ce0, 0x00000ce0, 0x00000ce1, 0x00000ce1,
13013203945Sweongyo		0x00000ce2, 0x00000ce2, 0x00000ce3, 0x00000ce3, 0x00000e10,
13014203945Sweongyo		0x00000e10, 0x00000e11, 0x00000e11, 0x00000e12, 0x00000e12,
13015203945Sweongyo		0x00000e13, 0x00000e13, 0x00000bf0, 0x00000bf0, 0x00000bf1,
13016203945Sweongyo		0x00000bf1, 0x00000bf2, 0x00000bf2, 0x00000bf3, 0x00000bf3,
13017203945Sweongyo		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13018203945Sweongyo		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13019203945Sweongyo		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13020203945Sweongyo		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13021203945Sweongyo		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13022203945Sweongyo		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13023203945Sweongyo		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13024203945Sweongyo		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13025203945Sweongyo		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13026203945Sweongyo		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13027203945Sweongyo		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13028203945Sweongyo		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13029203945Sweongyo		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13030203945Sweongyo		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13031203945Sweongyo		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13032203945Sweongyo		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13033203945Sweongyo		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13034203945Sweongyo		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13035203945Sweongyo		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13036203945Sweongyo		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13037203945Sweongyo		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13038203945Sweongyo		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13039203945Sweongyo		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13040203945Sweongyo		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13041203945Sweongyo		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13042203945Sweongyo		0x04000000, 0x04200000, 0x04000000, 0x000000ff, 0x000002fc,
13043203945Sweongyo		0x0000fa08, 0x00000305, 0x00000206, 0x00000304, 0x0000fb04,
13044203945Sweongyo		0x0000fcff, 0x000005fb, 0x0000fd01, 0x00000401, 0x00000006,
13045203945Sweongyo		0x0000ff03, 0x000007fc, 0x0000fc08, 0x00000203, 0x0000fffb,
13046203945Sweongyo		0x00000600, 0x0000fa01, 0x0000fc03, 0x0000fe06, 0x0000fe00,
13047203945Sweongyo		0x00000102, 0x000007fd, 0x000004fb, 0x000006ff, 0x000004fd,
13048203945Sweongyo		0x0000fdfa, 0x000007fb, 0x0000fdfa, 0x0000fa06, 0x00000500,
13049203945Sweongyo		0x0000f902, 0x000007fa, 0x0000fafa, 0x00000500, 0x000007fa,
13050203945Sweongyo		0x00000700, 0x00000305, 0x000004ff, 0x00000801, 0x00000503,
13051203945Sweongyo		0x000005f9, 0x00000404, 0x0000fb08, 0x000005fd, 0x00000501,
13052203945Sweongyo		0x00000405, 0x0000fb03, 0x000007fc, 0x00000403, 0x00000303,
13053203945Sweongyo		0x00000402, 0x0000faff, 0x0000fe05, 0x000005fd, 0x0000fe01,
13054203945Sweongyo		0x000007fa, 0x00000202, 0x00000504, 0x00000102, 0x000008fe,
13055203945Sweongyo		0x0000fa04, 0x0000fafc, 0x0000fe08, 0x000000f9, 0x000002fa,
13056203945Sweongyo		0x000003fe, 0x00000304, 0x000004f9, 0x00000100, 0x0000fd06,
13057203945Sweongyo		0x000008fc, 0x00000701, 0x00000504, 0x0000fdfe, 0x0000fdfc,
13058203945Sweongyo		0x000003fe, 0x00000704, 0x000002fc, 0x000004f9, 0x0000fdfd,
13059203945Sweongyo		0x0000fa07, 0x00000205, 0x000003fd, 0x000005fb, 0x000004f9,
13060203945Sweongyo		0x00000804, 0x0000fc06, 0x0000fcf9, 0x00000100, 0x0000fe05,
13061203945Sweongyo		0x00000408, 0x0000fb02, 0x00000304, 0x000006fe, 0x000004fa,
13062203945Sweongyo		0x00000305, 0x000008fc, 0x00000102, 0x000001fd, 0x000004fc,
13063203945Sweongyo		0x0000fe03, 0x00000701, 0x000001fb, 0x000001f9, 0x00000206,
13064203945Sweongyo		0x000006fd, 0x00000508, 0x00000700, 0x00000304, 0x000005fe,
13065203945Sweongyo		0x000005ff, 0x0000fa04, 0x00000303, 0x0000fefb, 0x000007f9,
13066203945Sweongyo		0x0000fefc, 0x000004fd, 0x000005fc, 0x0000fffd, 0x0000fc08,
13067203945Sweongyo		0x0000fbf9, 0x0000fd07, 0x000008fb, 0x0000fe02, 0x000006fb,
13068203945Sweongyo		0x00000702,
13069203945Sweongyo	};
13070203945Sweongyo
13071203945Sweongyo	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13072203945Sweongyo
13073203945Sweongyo	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13074203945Sweongyo	    bwn_tab_sigsq_tbl);
13075203945Sweongyo	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13076203945Sweongyo	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(crsgainnft), crsgainnft);
13077203945Sweongyo	bwn_tab_write_multi(mac, BWN_TAB_2(8, 0), N(filterctl), filterctl);
13078203945Sweongyo	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(psctl), psctl);
13079203945Sweongyo	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13080203945Sweongyo	    bwn_tab_pllfrac_tbl);
13081203945Sweongyo	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13082203945Sweongyo	    bwn_tabl_iqlocal_tbl);
13083203945Sweongyo	if (mac->mac_phy.rev == 0) {
13084203945Sweongyo		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r0),
13085203945Sweongyo		    ofdmcckgain_r0);
13086203945Sweongyo		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r0),
13087203945Sweongyo		    ofdmcckgain_r0);
13088203945Sweongyo	} else {
13089203945Sweongyo		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r1),
13090203945Sweongyo		    ofdmcckgain_r1);
13091203945Sweongyo		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r1),
13092203945Sweongyo		    ofdmcckgain_r1);
13093203945Sweongyo	}
13094203945Sweongyo	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(gaindelta), gaindelta);
13095203945Sweongyo	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(txpwrctl), txpwrctl);
13096203945Sweongyo}
13097203945Sweongyo
13098203945Sweongyostatic void
13099203945Sweongyobwn_phy_lp_tblinit_r2(struct bwn_mac *mac)
13100203945Sweongyo{
13101204922Sweongyo	struct bwn_softc *sc = mac->mac_sc;
13102203945Sweongyo	int i;
13103203945Sweongyo	static const uint16_t noisescale[] = {
13104203945Sweongyo		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13105203945Sweongyo		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13106203945Sweongyo		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13107203945Sweongyo		0x00a4, 0x00a4, 0x0000, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13108203945Sweongyo		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13109203945Sweongyo		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13110203945Sweongyo		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4
13111203945Sweongyo	};
13112203945Sweongyo	static const uint32_t filterctl[] = {
13113203945Sweongyo		0x000141fc, 0x000021fc, 0x000021b7, 0x0000416f, 0x0001ff27,
13114203945Sweongyo		0x0000217f, 0x00002137, 0x000040ef, 0x0001fea7, 0x0000024f
13115203945Sweongyo	};
13116203945Sweongyo	static const uint32_t psctl[] = {
13117203945Sweongyo		0x00e38e08, 0x00e08e38, 0x00000000, 0x00000000, 0x00000000,
13118203945Sweongyo		0x00002080, 0x00006180, 0x00003002, 0x00000040, 0x00002042,
13119203945Sweongyo		0x00180047, 0x00080043, 0x00000041, 0x000020c1, 0x00046006,
13120203945Sweongyo		0x00042002, 0x00040000, 0x00002003, 0x00180006, 0x00080002
13121203945Sweongyo	};
13122203945Sweongyo	static const uint32_t gainidx[] = {
13123203945Sweongyo		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13124203945Sweongyo		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13125203945Sweongyo		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13126203945Sweongyo		0x00000000, 0x00000000, 0x00000000, 0x10000001, 0x00000000,
13127203945Sweongyo		0x20000082, 0x00000000, 0x40000104, 0x00000000, 0x60004207,
13128203945Sweongyo		0x00000001, 0x7000838a, 0x00000001, 0xd021050d, 0x00000001,
13129203945Sweongyo		0xe041c683, 0x00000001, 0x50828805, 0x00000000, 0x80e34288,
13130203945Sweongyo		0x00000000, 0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000,
13131203945Sweongyo		0x12064711, 0x00000001, 0xb0a18612, 0x00000010, 0xe1024794,
13132203945Sweongyo		0x00000010, 0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011,
13133203945Sweongyo		0xc1848a9c, 0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21,
13134203945Sweongyo		0x00000019, 0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019,
13135203945Sweongyo		0xb36811a6, 0x00000019, 0xf3e89227, 0x00000019, 0x0408d329,
13136203945Sweongyo		0x0000001a, 0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a,
13137203945Sweongyo		0x54aa152c, 0x0000001a, 0x64ca55ad, 0x0000001a, 0x00000000,
13138203945Sweongyo		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13139203945Sweongyo		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13140203945Sweongyo		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13141203945Sweongyo		0x00000000, 0x00000000, 0x10000001, 0x00000000, 0x20000082,
13142203945Sweongyo		0x00000000, 0x40000104, 0x00000000, 0x60004207, 0x00000001,
13143203945Sweongyo		0x7000838a, 0x00000001, 0xd021050d, 0x00000001, 0xe041c683,
13144203945Sweongyo		0x00000001, 0x50828805, 0x00000000, 0x80e34288, 0x00000000,
13145203945Sweongyo		0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000, 0x12064711,
13146203945Sweongyo		0x00000001, 0xb0a18612, 0x00000010, 0xe1024794, 0x00000010,
13147203945Sweongyo		0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011, 0xc1848a9c,
13148203945Sweongyo		0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21, 0x00000019,
13149203945Sweongyo		0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019, 0xb36811a6,
13150203945Sweongyo		0x00000019, 0xf3e89227, 0x00000019, 0x0408d329, 0x0000001a,
13151203945Sweongyo		0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a, 0x54aa152c,
13152203945Sweongyo		0x0000001a, 0x64ca55ad, 0x0000001a
13153203945Sweongyo	};
13154203945Sweongyo	static const uint16_t auxgainidx[] = {
13155203945Sweongyo		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13156203945Sweongyo		0x0000, 0x0001, 0x0002, 0x0004, 0x0016, 0x0000, 0x0000, 0x0000,
13157203945Sweongyo		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002,
13158203945Sweongyo		0x0004, 0x0016
13159203945Sweongyo	};
13160203945Sweongyo	static const uint16_t swctl[] = {
13161203945Sweongyo		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13162203945Sweongyo		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13163203945Sweongyo		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
13164203945Sweongyo		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018,
13165203945Sweongyo		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13166203945Sweongyo		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13167203945Sweongyo		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
13168203945Sweongyo		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018
13169203945Sweongyo	};
13170203945Sweongyo	static const uint8_t hf[] = {
13171203945Sweongyo		0x4b, 0x36, 0x24, 0x18, 0x49, 0x34, 0x23, 0x17, 0x48,
13172203945Sweongyo		0x33, 0x23, 0x17, 0x48, 0x33, 0x23, 0x17
13173203945Sweongyo	};
13174203945Sweongyo	static const uint32_t gainval[] = {
13175203945Sweongyo		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13176203945Sweongyo		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13177203945Sweongyo		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13178203945Sweongyo		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13179203945Sweongyo		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13180203945Sweongyo		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13181203945Sweongyo		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13182203945Sweongyo		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13183203945Sweongyo		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13184203945Sweongyo		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13185203945Sweongyo		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13186203945Sweongyo		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13187203945Sweongyo		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000009,
13188203945Sweongyo		0x000000f1, 0x00000000, 0x00000000
13189203945Sweongyo	};
13190203945Sweongyo	static const uint16_t gain[] = {
13191203945Sweongyo		0x0000, 0x0400, 0x0800, 0x0802, 0x0804, 0x0806, 0x0807, 0x0808,
13192203945Sweongyo		0x080a, 0x080b, 0x080c, 0x080e, 0x080f, 0x0810, 0x0812, 0x0813,
13193203945Sweongyo		0x0814, 0x0816, 0x0817, 0x081a, 0x081b, 0x081f, 0x0820, 0x0824,
13194203945Sweongyo		0x0830, 0x0834, 0x0837, 0x083b, 0x083f, 0x0840, 0x0844, 0x0857,
13195203945Sweongyo		0x085b, 0x085f, 0x08d7, 0x08db, 0x08df, 0x0957, 0x095b, 0x095f,
13196203945Sweongyo		0x0b57, 0x0b5b, 0x0b5f, 0x0f5f, 0x135f, 0x175f, 0x0000, 0x0000,
13197203945Sweongyo		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13198203945Sweongyo		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13199203945Sweongyo		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13200203945Sweongyo		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13201203945Sweongyo		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13202203945Sweongyo		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13203203945Sweongyo	};
13204203945Sweongyo	static const uint32_t papdeps[] = {
13205203945Sweongyo		0x00000000, 0x00013ffc, 0x0001dff3, 0x0001bff0, 0x00023fe9,
13206203945Sweongyo		0x00021fdf, 0x00028fdf, 0x00033fd2, 0x00039fcb, 0x00043fc7,
13207203945Sweongyo		0x0004efc2, 0x00055fb5, 0x0005cfb0, 0x00063fa8, 0x00068fa3,
13208203945Sweongyo		0x00071f98, 0x0007ef92, 0x00084f8b, 0x0008df82, 0x00097f77,
13209203945Sweongyo		0x0009df69, 0x000a3f62, 0x000adf57, 0x000b6f4c, 0x000bff41,
13210203945Sweongyo		0x000c9f39, 0x000cff30, 0x000dbf27, 0x000e4f1e, 0x000edf16,
13211203945Sweongyo		0x000f7f13, 0x00102f11, 0x00110f10, 0x0011df11, 0x0012ef15,
13212203945Sweongyo		0x00143f1c, 0x00158f27, 0x00172f35, 0x00193f47, 0x001baf5f,
13213203945Sweongyo		0x001e6f7e, 0x0021cfa4, 0x0025bfd2, 0x002a2008, 0x002fb047,
13214203945Sweongyo		0x00360090, 0x003d40e0, 0x0045c135, 0x004fb189, 0x005ae1d7,
13215203945Sweongyo		0x0067221d, 0x0075025a, 0x007ff291, 0x007ff2bf, 0x007ff2e3,
13216203945Sweongyo		0x007ff2ff, 0x007ff315, 0x007ff329, 0x007ff33f, 0x007ff356,
13217203945Sweongyo		0x007ff36e, 0x007ff39c, 0x007ff441, 0x007ff506
13218203945Sweongyo	};
13219203945Sweongyo	static const uint32_t papdmult[] = {
13220203945Sweongyo		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13221203945Sweongyo		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13222203945Sweongyo		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13223203945Sweongyo		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13224203945Sweongyo		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13225203945Sweongyo		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13226203945Sweongyo		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13227203945Sweongyo		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13228203945Sweongyo		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13229203945Sweongyo		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13230203945Sweongyo		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13231203945Sweongyo		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13232203945Sweongyo		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13233203945Sweongyo	};
13234203945Sweongyo	static const uint32_t gainidx_a0[] = {
13235203945Sweongyo		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13236203945Sweongyo		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13237203945Sweongyo		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13238203945Sweongyo		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13239203945Sweongyo		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13240203945Sweongyo		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13241203945Sweongyo		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13242203945Sweongyo		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13243203945Sweongyo		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13244203945Sweongyo		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13245203945Sweongyo		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13246203945Sweongyo		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13247203945Sweongyo		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13248203945Sweongyo	};
13249203945Sweongyo	static const uint16_t auxgainidx_a0[] = {
13250203945Sweongyo		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13251203945Sweongyo		0x0000, 0x0000, 0x0000, 0x0002, 0x0014, 0x0000, 0x0000, 0x0000,
13252203945Sweongyo		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13253203945Sweongyo		0x0002, 0x0014
13254203945Sweongyo	};
13255203945Sweongyo	static const uint32_t gainval_a0[] = {
13256203945Sweongyo		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13257203945Sweongyo		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13258203945Sweongyo		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13259203945Sweongyo		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13260203945Sweongyo		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13261203945Sweongyo		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13262203945Sweongyo		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13263203945Sweongyo		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13264203945Sweongyo		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13265203945Sweongyo		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13266203945Sweongyo		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13267203945Sweongyo		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13268203945Sweongyo		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000f,
13269203945Sweongyo		0x000000f7, 0x00000000, 0x00000000
13270203945Sweongyo	};
13271203945Sweongyo	static const uint16_t gain_a0[] = {
13272203945Sweongyo		0x0000, 0x0002, 0x0004, 0x0006, 0x0007, 0x0008, 0x000a, 0x000b,
13273203945Sweongyo		0x000c, 0x000e, 0x000f, 0x0010, 0x0012, 0x0013, 0x0014, 0x0016,
13274203945Sweongyo		0x0017, 0x001a, 0x001b, 0x001f, 0x0020, 0x0024, 0x0030, 0x0034,
13275203945Sweongyo		0x0037, 0x003b, 0x003f, 0x0040, 0x0044, 0x0057, 0x005b, 0x005f,
13276203945Sweongyo		0x00d7, 0x00db, 0x00df, 0x0157, 0x015b, 0x015f, 0x0357, 0x035b,
13277203945Sweongyo		0x035f, 0x075f, 0x0b5f, 0x0f5f, 0x0000, 0x0000, 0x0000, 0x0000,
13278203945Sweongyo		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13279203945Sweongyo		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13280203945Sweongyo		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13281203945Sweongyo		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13282203945Sweongyo		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13283203945Sweongyo		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13284203945Sweongyo	};
13285203945Sweongyo
13286203945Sweongyo	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13287203945Sweongyo
13288203945Sweongyo	for (i = 0; i < 704; i++)
13289203945Sweongyo		bwn_tab_write(mac, BWN_TAB_4(7, i), 0);
13290203945Sweongyo
13291203945Sweongyo	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13292203945Sweongyo	    bwn_tab_sigsq_tbl);
13293203945Sweongyo	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13294203945Sweongyo	bwn_tab_write_multi(mac, BWN_TAB_4(11, 0), N(filterctl), filterctl);
13295203945Sweongyo	bwn_tab_write_multi(mac, BWN_TAB_4(12, 0), N(psctl), psctl);
13296203945Sweongyo	bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx), gainidx);
13297203945Sweongyo	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx), auxgainidx);
13298203945Sweongyo	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(swctl), swctl);
13299203945Sweongyo	bwn_tab_write_multi(mac, BWN_TAB_1(16, 0), N(hf), hf);
13300203945Sweongyo	bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval), gainval);
13301203945Sweongyo	bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain), gain);
13302203945Sweongyo	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13303203945Sweongyo	    bwn_tab_pllfrac_tbl);
13304203945Sweongyo	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13305203945Sweongyo	    bwn_tabl_iqlocal_tbl);
13306203945Sweongyo	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(papdeps), papdeps);
13307203945Sweongyo	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(papdmult), papdmult);
13308203945Sweongyo
13309204922Sweongyo	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
13310204922Sweongyo	    (siba_get_chiprev(sc->sc_dev) == 0)) {
13311203945Sweongyo		bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx_a0),
13312203945Sweongyo		    gainidx_a0);
13313203945Sweongyo		bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx_a0),
13314203945Sweongyo		    auxgainidx_a0);
13315203945Sweongyo		bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval_a0),
13316203945Sweongyo		    gainval_a0);
13317203945Sweongyo		bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain_a0), gain_a0);
13318203945Sweongyo	}
13319203945Sweongyo}
13320203945Sweongyo
13321203945Sweongyostatic void
13322203945Sweongyobwn_phy_lp_tblinit_txgain(struct bwn_mac *mac)
13323203945Sweongyo{
13324203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
13325203945Sweongyo	struct ifnet *ifp = sc->sc_ifp;
13326203945Sweongyo	struct ieee80211com *ic = ifp->if_l2com;
13327203945Sweongyo	static struct bwn_txgain_entry txgain_r2[] = {
13328203945Sweongyo		{ 255, 255, 203, 0, 152 }, { 255, 255, 203, 0, 147 },
13329203945Sweongyo		{ 255, 255, 203, 0, 143 }, { 255, 255, 203, 0, 139 },
13330203945Sweongyo		{ 255, 255, 203, 0, 135 }, { 255, 255, 203, 0, 131 },
13331203945Sweongyo		{ 255, 255, 203, 0, 128 }, { 255, 255, 203, 0, 124 },
13332203945Sweongyo		{ 255, 255, 203, 0, 121 }, { 255, 255, 203, 0, 117 },
13333203945Sweongyo		{ 255, 255, 203, 0, 114 }, { 255, 255, 203, 0, 111 },
13334203945Sweongyo		{ 255, 255, 203, 0, 107 }, { 255, 255, 203, 0, 104 },
13335203945Sweongyo		{ 255, 255, 203, 0, 101 }, { 255, 255, 203, 0, 99 },
13336203945Sweongyo		{ 255, 255, 203, 0, 96 }, { 255, 255, 203, 0, 93 },
13337203945Sweongyo		{ 255, 255, 203, 0, 90 }, { 255, 255, 203, 0, 88 },
13338203945Sweongyo		{ 255, 255, 203, 0, 85 }, { 255, 255, 203, 0, 83 },
13339203945Sweongyo		{ 255, 255, 203, 0, 81 }, { 255, 255, 203, 0, 78 },
13340203945Sweongyo		{ 255, 255, 203, 0, 76 }, { 255, 255, 203, 0, 74 },
13341203945Sweongyo		{ 255, 255, 203, 0, 72 }, { 255, 255, 203, 0, 70 },
13342203945Sweongyo		{ 255, 255, 203, 0, 68 }, { 255, 255, 203, 0, 66 },
13343203945Sweongyo		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13344203945Sweongyo		{ 255, 255, 192, 0, 64 }, { 255, 255, 186, 0, 64 },
13345203945Sweongyo		{ 255, 255, 181, 0, 64 }, { 255, 255, 176, 0, 64 },
13346203945Sweongyo		{ 255, 255, 171, 0, 64 }, { 255, 255, 166, 0, 64 },
13347203945Sweongyo		{ 255, 255, 161, 0, 64 }, { 255, 255, 157, 0, 64 },
13348203945Sweongyo		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13349203945Sweongyo		{ 255, 255, 144, 0, 64 }, { 255, 255, 140, 0, 64 },
13350203945Sweongyo		{ 255, 255, 136, 0, 64 }, { 255, 255, 132, 0, 64 },
13351203945Sweongyo		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13352203945Sweongyo		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13353203945Sweongyo		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13354203945Sweongyo		{ 255, 255, 108, 0, 64 }, { 255, 255, 105, 0, 64 },
13355203945Sweongyo		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13356203945Sweongyo		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13357203945Sweongyo		{ 255, 255, 91, 0, 64 }, { 255, 255, 88, 0, 64 },
13358203945Sweongyo		{ 255, 255, 86, 0, 64 }, { 255, 255, 83, 0, 64 },
13359203945Sweongyo		{ 255, 255, 81, 0, 64 }, { 255, 255, 79, 0, 64 },
13360203945Sweongyo		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13361203945Sweongyo		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13362203945Sweongyo		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13363203945Sweongyo		{ 255, 255, 64, 0, 64 }, { 255, 248, 64, 0, 64 },
13364203945Sweongyo		{ 255, 248, 62, 0, 64 }, { 255, 241, 62, 0, 64 },
13365203945Sweongyo		{ 255, 241, 60, 0, 64 }, { 255, 234, 60, 0, 64 },
13366203945Sweongyo		{ 255, 234, 59, 0, 64 }, { 255, 227, 59, 0, 64 },
13367203945Sweongyo		{ 255, 227, 57, 0, 64 }, { 255, 221, 57, 0, 64 },
13368203945Sweongyo		{ 255, 221, 55, 0, 64 }, { 255, 215, 55, 0, 64 },
13369203945Sweongyo		{ 255, 215, 54, 0, 64 }, { 255, 208, 54, 0, 64 },
13370203945Sweongyo		{ 255, 208, 52, 0, 64 }, { 255, 203, 52, 0, 64 },
13371203945Sweongyo		{ 255, 203, 51, 0, 64 }, { 255, 197, 51, 0, 64 },
13372203945Sweongyo		{ 255, 197, 49, 0, 64 }, { 255, 191, 49, 0, 64 },
13373203945Sweongyo		{ 255, 191, 48, 0, 64 }, { 255, 186, 48, 0, 64 },
13374203945Sweongyo		{ 255, 186, 47, 0, 64 }, { 255, 181, 47, 0, 64 },
13375203945Sweongyo		{ 255, 181, 45, 0, 64 }, { 255, 175, 45, 0, 64 },
13376203945Sweongyo		{ 255, 175, 44, 0, 64 }, { 255, 170, 44, 0, 64 },
13377203945Sweongyo		{ 255, 170, 43, 0, 64 }, { 255, 166, 43, 0, 64 },
13378203945Sweongyo		{ 255, 166, 42, 0, 64 }, { 255, 161, 42, 0, 64 },
13379203945Sweongyo		{ 255, 161, 40, 0, 64 }, { 255, 156, 40, 0, 64 },
13380203945Sweongyo		{ 255, 156, 39, 0, 64 }, { 255, 152, 39, 0, 64 },
13381203945Sweongyo		{ 255, 152, 38, 0, 64 }, { 255, 148, 38, 0, 64 },
13382203945Sweongyo		{ 255, 148, 37, 0, 64 }, { 255, 143, 37, 0, 64 },
13383203945Sweongyo		{ 255, 143, 36, 0, 64 }, { 255, 139, 36, 0, 64 },
13384203945Sweongyo		{ 255, 139, 35, 0, 64 }, { 255, 135, 35, 0, 64 },
13385203945Sweongyo		{ 255, 135, 34, 0, 64 }, { 255, 132, 34, 0, 64 },
13386203945Sweongyo		{ 255, 132, 33, 0, 64 }, { 255, 128, 33, 0, 64 },
13387203945Sweongyo		{ 255, 128, 32, 0, 64 }, { 255, 124, 32, 0, 64 },
13388203945Sweongyo		{ 255, 124, 31, 0, 64 }, { 255, 121, 31, 0, 64 },
13389203945Sweongyo		{ 255, 121, 30, 0, 64 }, { 255, 117, 30, 0, 64 },
13390203945Sweongyo		{ 255, 117, 29, 0, 64 }, { 255, 114, 29, 0, 64 },
13391203945Sweongyo		{ 255, 114, 29, 0, 64 }, { 255, 111, 29, 0, 64 },
13392203945Sweongyo	};
13393203945Sweongyo	static struct bwn_txgain_entry txgain_2ghz_r2[] = {
13394203945Sweongyo		{ 7, 99, 255, 0, 64 }, { 7, 96, 255, 0, 64 },
13395203945Sweongyo		{ 7, 93, 255, 0, 64 }, { 7, 90, 255, 0, 64 },
13396203945Sweongyo		{ 7, 88, 255, 0, 64 }, { 7, 85, 255, 0, 64 },
13397203945Sweongyo		{ 7, 83, 255, 0, 64 }, { 7, 81, 255, 0, 64 },
13398203945Sweongyo		{ 7, 78, 255, 0, 64 }, { 7, 76, 255, 0, 64 },
13399203945Sweongyo		{ 7, 74, 255, 0, 64 }, { 7, 72, 255, 0, 64 },
13400203945Sweongyo		{ 7, 70, 255, 0, 64 }, { 7, 68, 255, 0, 64 },
13401203945Sweongyo		{ 7, 66, 255, 0, 64 }, { 7, 64, 255, 0, 64 },
13402203945Sweongyo		{ 7, 64, 255, 0, 64 }, { 7, 62, 255, 0, 64 },
13403203945Sweongyo		{ 7, 62, 248, 0, 64 }, { 7, 60, 248, 0, 64 },
13404203945Sweongyo		{ 7, 60, 241, 0, 64 }, { 7, 59, 241, 0, 64 },
13405203945Sweongyo		{ 7, 59, 234, 0, 64 }, { 7, 57, 234, 0, 64 },
13406203945Sweongyo		{ 7, 57, 227, 0, 64 }, { 7, 55, 227, 0, 64 },
13407203945Sweongyo		{ 7, 55, 221, 0, 64 }, { 7, 54, 221, 0, 64 },
13408203945Sweongyo		{ 7, 54, 215, 0, 64 }, { 7, 52, 215, 0, 64 },
13409203945Sweongyo		{ 7, 52, 208, 0, 64 }, { 7, 51, 208, 0, 64 },
13410203945Sweongyo		{ 7, 51, 203, 0, 64 }, { 7, 49, 203, 0, 64 },
13411203945Sweongyo		{ 7, 49, 197, 0, 64 }, { 7, 48, 197, 0, 64 },
13412203945Sweongyo		{ 7, 48, 191, 0, 64 }, { 7, 47, 191, 0, 64 },
13413203945Sweongyo		{ 7, 47, 186, 0, 64 }, { 7, 45, 186, 0, 64 },
13414203945Sweongyo		{ 7, 45, 181, 0, 64 }, { 7, 44, 181, 0, 64 },
13415203945Sweongyo		{ 7, 44, 175, 0, 64 }, { 7, 43, 175, 0, 64 },
13416203945Sweongyo		{ 7, 43, 170, 0, 64 }, { 7, 42, 170, 0, 64 },
13417203945Sweongyo		{ 7, 42, 166, 0, 64 }, { 7, 40, 166, 0, 64 },
13418203945Sweongyo		{ 7, 40, 161, 0, 64 }, { 7, 39, 161, 0, 64 },
13419203945Sweongyo		{ 7, 39, 156, 0, 64 }, { 7, 38, 156, 0, 64 },
13420203945Sweongyo		{ 7, 38, 152, 0, 64 }, { 7, 37, 152, 0, 64 },
13421203945Sweongyo		{ 7, 37, 148, 0, 64 }, { 7, 36, 148, 0, 64 },
13422203945Sweongyo		{ 7, 36, 143, 0, 64 }, { 7, 35, 143, 0, 64 },
13423203945Sweongyo		{ 7, 35, 139, 0, 64 }, { 7, 34, 139, 0, 64 },
13424203945Sweongyo		{ 7, 34, 135, 0, 64 }, { 7, 33, 135, 0, 64 },
13425203945Sweongyo		{ 7, 33, 132, 0, 64 }, { 7, 32, 132, 0, 64 },
13426203945Sweongyo		{ 7, 32, 128, 0, 64 }, { 7, 31, 128, 0, 64 },
13427203945Sweongyo		{ 7, 31, 124, 0, 64 }, { 7, 30, 124, 0, 64 },
13428203945Sweongyo		{ 7, 30, 121, 0, 64 }, { 7, 29, 121, 0, 64 },
13429203945Sweongyo		{ 7, 29, 117, 0, 64 }, { 7, 29, 117, 0, 64 },
13430203945Sweongyo		{ 7, 29, 114, 0, 64 }, { 7, 28, 114, 0, 64 },
13431203945Sweongyo		{ 7, 28, 111, 0, 64 }, { 7, 27, 111, 0, 64 },
13432203945Sweongyo		{ 7, 27, 108, 0, 64 }, { 7, 26, 108, 0, 64 },
13433203945Sweongyo		{ 7, 26, 104, 0, 64 }, { 7, 25, 104, 0, 64 },
13434203945Sweongyo		{ 7, 25, 102, 0, 64 }, { 7, 25, 102, 0, 64 },
13435203945Sweongyo		{ 7, 25, 99, 0, 64 }, { 7, 24, 99, 0, 64 },
13436203945Sweongyo		{ 7, 24, 96, 0, 64 }, { 7, 23, 96, 0, 64 },
13437203945Sweongyo		{ 7, 23, 93, 0, 64 }, { 7, 23, 93, 0, 64 },
13438203945Sweongyo		{ 7, 23, 90, 0, 64 }, { 7, 22, 90, 0, 64 },
13439203945Sweongyo		{ 7, 22, 88, 0, 64 }, { 7, 21, 88, 0, 64 },
13440203945Sweongyo		{ 7, 21, 85, 0, 64 }, { 7, 21, 85, 0, 64 },
13441203945Sweongyo		{ 7, 21, 83, 0, 64 }, { 7, 20, 83, 0, 64 },
13442203945Sweongyo		{ 7, 20, 81, 0, 64 }, { 7, 20, 81, 0, 64 },
13443203945Sweongyo		{ 7, 20, 78, 0, 64 }, { 7, 19, 78, 0, 64 },
13444203945Sweongyo		{ 7, 19, 76, 0, 64 }, { 7, 19, 76, 0, 64 },
13445203945Sweongyo		{ 7, 19, 74, 0, 64 }, { 7, 18, 74, 0, 64 },
13446203945Sweongyo		{ 7, 18, 72, 0, 64 }, { 7, 18, 72, 0, 64 },
13447203945Sweongyo		{ 7, 18, 70, 0, 64 }, { 7, 17, 70, 0, 64 },
13448203945Sweongyo		{ 7, 17, 68, 0, 64 }, { 7, 17, 68, 0, 64 },
13449203945Sweongyo		{ 7, 17, 66, 0, 64 }, { 7, 16, 66, 0, 64 },
13450203945Sweongyo		{ 7, 16, 64, 0, 64 }, { 7, 16, 64, 0, 64 },
13451203945Sweongyo		{ 7, 16, 62, 0, 64 }, { 7, 15, 62, 0, 64 },
13452203945Sweongyo		{ 7, 15, 60, 0, 64 }, { 7, 15, 60, 0, 64 },
13453203945Sweongyo		{ 7, 15, 59, 0, 64 }, { 7, 14, 59, 0, 64 },
13454203945Sweongyo		{ 7, 14, 57, 0, 64 }, { 7, 14, 57, 0, 64 },
13455203945Sweongyo		{ 7, 14, 55, 0, 64 }, { 7, 14, 55, 0, 64 },
13456203945Sweongyo		{ 7, 14, 54, 0, 64 }, { 7, 13, 54, 0, 64 },
13457203945Sweongyo		{ 7, 13, 52, 0, 64 }, { 7, 13, 52, 0, 64 },
13458203945Sweongyo	};
13459203945Sweongyo	static struct bwn_txgain_entry txgain_5ghz_r2[] = {
13460203945Sweongyo		{ 255, 255, 255, 0, 152 }, { 255, 255, 255, 0, 147 },
13461203945Sweongyo		{ 255, 255, 255, 0, 143 }, { 255, 255, 255, 0, 139 },
13462203945Sweongyo		{ 255, 255, 255, 0, 135 }, { 255, 255, 255, 0, 131 },
13463203945Sweongyo		{ 255, 255, 255, 0, 128 }, { 255, 255, 255, 0, 124 },
13464203945Sweongyo		{ 255, 255, 255, 0, 121 }, { 255, 255, 255, 0, 117 },
13465203945Sweongyo		{ 255, 255, 255, 0, 114 }, { 255, 255, 255, 0, 111 },
13466203945Sweongyo		{ 255, 255, 255, 0, 107 }, { 255, 255, 255, 0, 104 },
13467203945Sweongyo		{ 255, 255, 255, 0, 101 }, { 255, 255, 255, 0, 99 },
13468203945Sweongyo		{ 255, 255, 255, 0, 96 }, { 255, 255, 255, 0, 93 },
13469203945Sweongyo		{ 255, 255, 255, 0, 90 }, { 255, 255, 255, 0, 88 },
13470203945Sweongyo		{ 255, 255, 255, 0, 85 }, { 255, 255, 255, 0, 83 },
13471203945Sweongyo		{ 255, 255, 255, 0, 81 }, { 255, 255, 255, 0, 78 },
13472203945Sweongyo		{ 255, 255, 255, 0, 76 }, { 255, 255, 255, 0, 74 },
13473203945Sweongyo		{ 255, 255, 255, 0, 72 }, { 255, 255, 255, 0, 70 },
13474203945Sweongyo		{ 255, 255, 255, 0, 68 }, { 255, 255, 255, 0, 66 },
13475203945Sweongyo		{ 255, 255, 255, 0, 64 }, { 255, 255, 248, 0, 64 },
13476203945Sweongyo		{ 255, 255, 241, 0, 64 }, { 255, 255, 234, 0, 64 },
13477203945Sweongyo		{ 255, 255, 227, 0, 64 }, { 255, 255, 221, 0, 64 },
13478203945Sweongyo		{ 255, 255, 215, 0, 64 }, { 255, 255, 208, 0, 64 },
13479203945Sweongyo		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13480203945Sweongyo		{ 255, 255, 191, 0, 64 }, { 255, 255, 186, 0, 64 },
13481203945Sweongyo		{ 255, 255, 181, 0, 64 }, { 255, 255, 175, 0, 64 },
13482203945Sweongyo		{ 255, 255, 170, 0, 64 }, { 255, 255, 166, 0, 64 },
13483203945Sweongyo		{ 255, 255, 161, 0, 64 }, { 255, 255, 156, 0, 64 },
13484203945Sweongyo		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13485203945Sweongyo		{ 255, 255, 143, 0, 64 }, { 255, 255, 139, 0, 64 },
13486203945Sweongyo		{ 255, 255, 135, 0, 64 }, { 255, 255, 132, 0, 64 },
13487203945Sweongyo		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13488203945Sweongyo		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13489203945Sweongyo		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13490203945Sweongyo		{ 255, 255, 108, 0, 64 }, { 255, 255, 104, 0, 64 },
13491203945Sweongyo		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13492203945Sweongyo		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13493203945Sweongyo		{ 255, 255, 90, 0, 64 }, { 255, 255, 88, 0, 64 },
13494203945Sweongyo		{ 255, 255, 85, 0, 64 }, { 255, 255, 83, 0, 64 },
13495203945Sweongyo		{ 255, 255, 81, 0, 64 }, { 255, 255, 78, 0, 64 },
13496203945Sweongyo		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13497203945Sweongyo		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13498203945Sweongyo		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13499203945Sweongyo		{ 255, 255, 64, 0, 64 }, { 255, 255, 64, 0, 64 },
13500203945Sweongyo		{ 255, 255, 62, 0, 64 }, { 255, 248, 62, 0, 64 },
13501203945Sweongyo		{ 255, 248, 60, 0, 64 }, { 255, 241, 60, 0, 64 },
13502203945Sweongyo		{ 255, 241, 59, 0, 64 }, { 255, 234, 59, 0, 64 },
13503203945Sweongyo		{ 255, 234, 57, 0, 64 }, { 255, 227, 57, 0, 64 },
13504203945Sweongyo		{ 255, 227, 55, 0, 64 }, { 255, 221, 55, 0, 64 },
13505203945Sweongyo		{ 255, 221, 54, 0, 64 }, { 255, 215, 54, 0, 64 },
13506203945Sweongyo		{ 255, 215, 52, 0, 64 }, { 255, 208, 52, 0, 64 },
13507203945Sweongyo		{ 255, 208, 51, 0, 64 }, { 255, 203, 51, 0, 64 },
13508203945Sweongyo		{ 255, 203, 49, 0, 64 }, { 255, 197, 49, 0, 64 },
13509203945Sweongyo		{ 255, 197, 48, 0, 64 }, { 255, 191, 48, 0, 64 },
13510203945Sweongyo		{ 255, 191, 47, 0, 64 }, { 255, 186, 47, 0, 64 },
13511203945Sweongyo		{ 255, 186, 45, 0, 64 }, { 255, 181, 45, 0, 64 },
13512203945Sweongyo		{ 255, 181, 44, 0, 64 }, { 255, 175, 44, 0, 64 },
13513203945Sweongyo		{ 255, 175, 43, 0, 64 }, { 255, 170, 43, 0, 64 },
13514203945Sweongyo		{ 255, 170, 42, 0, 64 }, { 255, 166, 42, 0, 64 },
13515203945Sweongyo		{ 255, 166, 40, 0, 64 }, { 255, 161, 40, 0, 64 },
13516203945Sweongyo		{ 255, 161, 39, 0, 64 }, { 255, 156, 39, 0, 64 },
13517203945Sweongyo		{ 255, 156, 38, 0, 64 }, { 255, 152, 38, 0, 64 },
13518203945Sweongyo		{ 255, 152, 37, 0, 64 }, { 255, 148, 37, 0, 64 },
13519203945Sweongyo		{ 255, 148, 36, 0, 64 }, { 255, 143, 36, 0, 64 },
13520203945Sweongyo		{ 255, 143, 35, 0, 64 }, { 255, 139, 35, 0, 64 },
13521203945Sweongyo		{ 255, 139, 34, 0, 64 }, { 255, 135, 34, 0, 64 },
13522203945Sweongyo		{ 255, 135, 33, 0, 64 }, { 255, 132, 33, 0, 64 },
13523203945Sweongyo		{ 255, 132, 32, 0, 64 }, { 255, 128, 32, 0, 64 }
13524203945Sweongyo	};
13525203945Sweongyo	static struct bwn_txgain_entry txgain_r0[] = {
13526203945Sweongyo		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13527203945Sweongyo		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13528203945Sweongyo		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13529203945Sweongyo		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13530203945Sweongyo		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13531203945Sweongyo		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13532203945Sweongyo		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13533203945Sweongyo		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13534203945Sweongyo		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13535203945Sweongyo		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13536203945Sweongyo		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13537203945Sweongyo		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13538203945Sweongyo		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13539203945Sweongyo		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13540203945Sweongyo		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13541203945Sweongyo		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13542203945Sweongyo		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13543203945Sweongyo		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13544203945Sweongyo		{ 7, 15, 13, 0, 70 }, { 7, 15, 13, 0, 68 },
13545203945Sweongyo		{ 7, 15, 13, 0, 66 }, { 7, 15, 13, 0, 64 },
13546203945Sweongyo		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13547203945Sweongyo		{ 7, 15, 13, 0, 59 }, { 7, 15, 13, 0, 57 },
13548203945Sweongyo		{ 7, 15, 12, 0, 71 }, { 7, 15, 12, 0, 69 },
13549203945Sweongyo		{ 7, 15, 12, 0, 67 }, { 7, 15, 12, 0, 65 },
13550203945Sweongyo		{ 7, 15, 12, 0, 63 }, { 7, 15, 12, 0, 62 },
13551203945Sweongyo		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 58 },
13552203945Sweongyo		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 70 },
13553203945Sweongyo		{ 7, 15, 11, 0, 68 }, { 7, 15, 11, 0, 66 },
13554203945Sweongyo		{ 7, 15, 11, 0, 65 }, { 7, 15, 11, 0, 63 },
13555203945Sweongyo		{ 7, 15, 11, 0, 61 }, { 7, 15, 11, 0, 59 },
13556203945Sweongyo		{ 7, 15, 11, 0, 58 }, { 7, 15, 10, 0, 71 },
13557203945Sweongyo		{ 7, 15, 10, 0, 69 }, { 7, 15, 10, 0, 67 },
13558203945Sweongyo		{ 7, 15, 10, 0, 65 }, { 7, 15, 10, 0, 63 },
13559203945Sweongyo		{ 7, 15, 10, 0, 61 }, { 7, 15, 10, 0, 60 },
13560203945Sweongyo		{ 7, 15, 10, 0, 58 }, { 7, 15, 10, 0, 56 },
13561203945Sweongyo		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13562203945Sweongyo		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13563203945Sweongyo		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 60 },
13564203945Sweongyo		{ 7, 15, 9, 0, 59 }, { 7, 14, 9, 0, 72 },
13565203945Sweongyo		{ 7, 14, 9, 0, 70 }, { 7, 14, 9, 0, 68 },
13566203945Sweongyo		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 64 },
13567203945Sweongyo		{ 7, 14, 9, 0, 62 }, { 7, 14, 9, 0, 60 },
13568203945Sweongyo		{ 7, 14, 9, 0, 59 }, { 7, 13, 9, 0, 72 },
13569203945Sweongyo		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13570203945Sweongyo		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13571203945Sweongyo		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13572203945Sweongyo		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13573203945Sweongyo		{ 7, 13, 8, 0, 72 }, { 7, 13, 8, 0, 70 },
13574203945Sweongyo		{ 7, 13, 8, 0, 68 }, { 7, 13, 8, 0, 66 },
13575203945Sweongyo		{ 7, 13, 8, 0, 64 }, { 7, 13, 8, 0, 62 },
13576203945Sweongyo		{ 7, 13, 8, 0, 60 }, { 7, 13, 8, 0, 59 },
13577203945Sweongyo		{ 7, 12, 8, 0, 72 }, { 7, 12, 8, 0, 70 },
13578203945Sweongyo		{ 7, 12, 8, 0, 68 }, { 7, 12, 8, 0, 66 },
13579203945Sweongyo		{ 7, 12, 8, 0, 64 }, { 7, 12, 8, 0, 62 },
13580203945Sweongyo		{ 7, 12, 8, 0, 61 }, { 7, 12, 8, 0, 59 },
13581203945Sweongyo		{ 7, 12, 7, 0, 73 }, { 7, 12, 7, 0, 71 },
13582203945Sweongyo		{ 7, 12, 7, 0, 69 }, { 7, 12, 7, 0, 67 },
13583203945Sweongyo		{ 7, 12, 7, 0, 65 }, { 7, 12, 7, 0, 63 },
13584203945Sweongyo		{ 7, 12, 7, 0, 61 }, { 7, 12, 7, 0, 59 },
13585203945Sweongyo		{ 7, 11, 7, 0, 72 }, { 7, 11, 7, 0, 70 },
13586203945Sweongyo		{ 7, 11, 7, 0, 68 }, { 7, 11, 7, 0, 66 },
13587203945Sweongyo		{ 7, 11, 7, 0, 65 }, { 7, 11, 7, 0, 63 },
13588203945Sweongyo		{ 7, 11, 7, 0, 61 }, { 7, 11, 7, 0, 59 },
13589203945Sweongyo		{ 7, 11, 6, 0, 73 }, { 7, 11, 6, 0, 71 }
13590203945Sweongyo	};
13591203945Sweongyo	static struct bwn_txgain_entry txgain_2ghz_r0[] = {
13592203945Sweongyo		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13593203945Sweongyo		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13594203945Sweongyo		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13595203945Sweongyo		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13596203945Sweongyo		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13597203945Sweongyo		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13598203945Sweongyo		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13599203945Sweongyo		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13600203945Sweongyo		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13601203945Sweongyo		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13602203945Sweongyo		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13603203945Sweongyo		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13604203945Sweongyo		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13605203945Sweongyo		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13606203945Sweongyo		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13607203945Sweongyo		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13608203945Sweongyo		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13609203945Sweongyo		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13610203945Sweongyo		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13611203945Sweongyo		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13612203945Sweongyo		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13613203945Sweongyo		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13614203945Sweongyo		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13615203945Sweongyo		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13616203945Sweongyo		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13617203945Sweongyo		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13618203945Sweongyo		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13619203945Sweongyo		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13620203945Sweongyo		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13621203945Sweongyo		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13622203945Sweongyo		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13623203945Sweongyo		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13624203945Sweongyo		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13625203945Sweongyo		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 },
13626203945Sweongyo		{ 4, 10, 6, 0, 59 }, { 4, 10, 5, 0, 72 },
13627203945Sweongyo		{ 4, 10, 5, 0, 70 }, { 4, 10, 5, 0, 68 },
13628203945Sweongyo		{ 4, 10, 5, 0, 66 }, { 4, 10, 5, 0, 64 },
13629203945Sweongyo		{ 4, 10, 5, 0, 62 }, { 4, 10, 5, 0, 60 },
13630203945Sweongyo		{ 4, 10, 5, 0, 59 }, { 4, 9, 5, 0, 70 },
13631203945Sweongyo		{ 4, 9, 5, 0, 68 }, { 4, 9, 5, 0, 66 },
13632203945Sweongyo		{ 4, 9, 5, 0, 64 }, { 4, 9, 5, 0, 63 },
13633203945Sweongyo		{ 4, 9, 5, 0, 61 }, { 4, 9, 5, 0, 59 },
13634203945Sweongyo		{ 4, 9, 4, 0, 71 }, { 4, 9, 4, 0, 69 },
13635203945Sweongyo		{ 4, 9, 4, 0, 67 }, { 4, 9, 4, 0, 65 },
13636203945Sweongyo		{ 4, 9, 4, 0, 63 }, { 4, 9, 4, 0, 62 },
13637203945Sweongyo		{ 4, 9, 4, 0, 60 }, { 4, 9, 4, 0, 58 },
13638203945Sweongyo		{ 4, 8, 4, 0, 70 }, { 4, 8, 4, 0, 68 },
13639203945Sweongyo		{ 4, 8, 4, 0, 66 }, { 4, 8, 4, 0, 65 },
13640203945Sweongyo		{ 4, 8, 4, 0, 63 }, { 4, 8, 4, 0, 61 },
13641203945Sweongyo		{ 4, 8, 4, 0, 59 }, { 4, 7, 4, 0, 68 },
13642203945Sweongyo		{ 4, 7, 4, 0, 66 }, { 4, 7, 4, 0, 64 },
13643203945Sweongyo		{ 4, 7, 4, 0, 62 }, { 4, 7, 4, 0, 61 },
13644203945Sweongyo		{ 4, 7, 4, 0, 59 }, { 4, 7, 3, 0, 67 },
13645203945Sweongyo		{ 4, 7, 3, 0, 65 }, { 4, 7, 3, 0, 63 },
13646203945Sweongyo		{ 4, 7, 3, 0, 62 }, { 4, 7, 3, 0, 60 },
13647203945Sweongyo		{ 4, 6, 3, 0, 65 }, { 4, 6, 3, 0, 63 },
13648203945Sweongyo		{ 4, 6, 3, 0, 61 }, { 4, 6, 3, 0, 60 },
13649203945Sweongyo		{ 4, 6, 3, 0, 58 }, { 4, 5, 3, 0, 68 },
13650203945Sweongyo		{ 4, 5, 3, 0, 66 }, { 4, 5, 3, 0, 64 },
13651203945Sweongyo		{ 4, 5, 3, 0, 62 }, { 4, 5, 3, 0, 60 },
13652203945Sweongyo		{ 4, 5, 3, 0, 59 }, { 4, 5, 3, 0, 57 },
13653203945Sweongyo		{ 4, 4, 2, 0, 83 }, { 4, 4, 2, 0, 81 },
13654203945Sweongyo		{ 4, 4, 2, 0, 78 }, { 4, 4, 2, 0, 76 },
13655203945Sweongyo		{ 4, 4, 2, 0, 74 }, { 4, 4, 2, 0, 72 }
13656203945Sweongyo	};
13657203945Sweongyo	static struct bwn_txgain_entry txgain_5ghz_r0[] = {
13658203945Sweongyo		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13659203945Sweongyo		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13660203945Sweongyo		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13661203945Sweongyo		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13662203945Sweongyo		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13663203945Sweongyo		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13664203945Sweongyo		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13665203945Sweongyo		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13666203945Sweongyo		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13667203945Sweongyo		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13668203945Sweongyo		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13669203945Sweongyo		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13670203945Sweongyo		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13671203945Sweongyo		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13672203945Sweongyo		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13673203945Sweongyo		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13674203945Sweongyo		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13675203945Sweongyo		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13676203945Sweongyo		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13677203945Sweongyo		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13678203945Sweongyo		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13679203945Sweongyo		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13680203945Sweongyo		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13681203945Sweongyo		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13682203945Sweongyo		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13683203945Sweongyo		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13684203945Sweongyo		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13685203945Sweongyo		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13686203945Sweongyo		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13687203945Sweongyo		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13688203945Sweongyo		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13689203945Sweongyo		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13690203945Sweongyo		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13691203945Sweongyo		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13692203945Sweongyo		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13693203945Sweongyo		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13694203945Sweongyo		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13695203945Sweongyo		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13696203945Sweongyo		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13697203945Sweongyo		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13698203945Sweongyo		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13699203945Sweongyo		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13700203945Sweongyo		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13701203945Sweongyo		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13702203945Sweongyo		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13703203945Sweongyo		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13704203945Sweongyo		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13705203945Sweongyo		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13706203945Sweongyo		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13707203945Sweongyo		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13708203945Sweongyo		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13709203945Sweongyo		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13710203945Sweongyo		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13711203945Sweongyo		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13712203945Sweongyo		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13713203945Sweongyo		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13714203945Sweongyo		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13715203945Sweongyo		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13716203945Sweongyo		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13717203945Sweongyo		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13718203945Sweongyo		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13719203945Sweongyo		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13720203945Sweongyo		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13721203945Sweongyo		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13722203945Sweongyo	};
13723203945Sweongyo	static struct bwn_txgain_entry txgain_r1[] = {
13724203945Sweongyo		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13725203945Sweongyo		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13726203945Sweongyo		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13727203945Sweongyo		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13728203945Sweongyo		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13729203945Sweongyo		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13730203945Sweongyo		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13731203945Sweongyo		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13732203945Sweongyo		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13733203945Sweongyo		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13734203945Sweongyo		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13735203945Sweongyo		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13736203945Sweongyo		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13737203945Sweongyo		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13738203945Sweongyo		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13739203945Sweongyo		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13740203945Sweongyo		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13741203945Sweongyo		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13742203945Sweongyo		{ 7, 15, 13, 0, 70 }, { 7, 15, 14, 0, 68 },
13743203945Sweongyo		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13744203945Sweongyo		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13745203945Sweongyo		{ 7, 15, 14, 0, 59 }, { 7, 15, 14, 0, 57 },
13746203945Sweongyo		{ 7, 15, 13, 0, 72 }, { 7, 15, 13, 0, 70 },
13747203945Sweongyo		{ 7, 15, 13, 0, 68 }, { 7, 15, 13, 0, 66 },
13748203945Sweongyo		{ 7, 15, 13, 0, 64 }, { 7, 15, 13, 0, 62 },
13749203945Sweongyo		{ 7, 15, 13, 0, 60 }, { 7, 15, 13, 0, 59 },
13750203945Sweongyo		{ 7, 15, 13, 0, 57 }, { 7, 15, 12, 0, 71 },
13751203945Sweongyo		{ 7, 15, 12, 0, 69 }, { 7, 15, 12, 0, 67 },
13752203945Sweongyo		{ 7, 15, 12, 0, 65 }, { 7, 15, 12, 0, 63 },
13753203945Sweongyo		{ 7, 15, 12, 0, 62 }, { 7, 15, 12, 0, 60 },
13754203945Sweongyo		{ 7, 15, 12, 0, 58 }, { 7, 15, 12, 0, 57 },
13755203945Sweongyo		{ 7, 15, 11, 0, 70 }, { 7, 15, 11, 0, 68 },
13756203945Sweongyo		{ 7, 15, 11, 0, 66 }, { 7, 15, 11, 0, 65 },
13757203945Sweongyo		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13758203945Sweongyo		{ 7, 15, 11, 0, 59 }, { 7, 15, 11, 0, 58 },
13759203945Sweongyo		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13760203945Sweongyo		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13761203945Sweongyo		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13762203945Sweongyo		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13763203945Sweongyo		{ 7, 15, 10, 0, 56 }, { 7, 15, 9, 0, 70 },
13764203945Sweongyo		{ 7, 15, 9, 0, 68 }, { 7, 15, 9, 0, 66 },
13765203945Sweongyo		{ 7, 15, 9, 0, 64 }, { 7, 15, 9, 0, 62 },
13766203945Sweongyo		{ 7, 15, 9, 0, 60 }, { 7, 15, 9, 0, 59 },
13767203945Sweongyo		{ 7, 14, 9, 0, 72 }, { 7, 14, 9, 0, 70 },
13768203945Sweongyo		{ 7, 14, 9, 0, 68 }, { 7, 14, 9, 0, 66 },
13769203945Sweongyo		{ 7, 14, 9, 0, 64 }, { 7, 14, 9, 0, 62 },
13770203945Sweongyo		{ 7, 14, 9, 0, 60 }, { 7, 14, 9, 0, 59 },
13771203945Sweongyo		{ 7, 13, 9, 0, 72 }, { 7, 13, 9, 0, 70 },
13772203945Sweongyo		{ 7, 13, 9, 0, 68 }, { 7, 13, 9, 0, 66 },
13773203945Sweongyo		{ 7, 13, 9, 0, 64 }, { 7, 13, 9, 0, 63 },
13774203945Sweongyo		{ 7, 13, 9, 0, 61 }, { 7, 13, 9, 0, 59 },
13775203945Sweongyo		{ 7, 13, 9, 0, 57 }, { 7, 13, 8, 0, 72 },
13776203945Sweongyo		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13777203945Sweongyo		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13778203945Sweongyo		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13779203945Sweongyo		{ 7, 13, 8, 0, 59 }, { 7, 12, 8, 0, 72 },
13780203945Sweongyo		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13781203945Sweongyo		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13782203945Sweongyo		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13783203945Sweongyo		{ 7, 12, 8, 0, 59 }, { 7, 12, 7, 0, 73 },
13784203945Sweongyo		{ 7, 12, 7, 0, 71 }, { 7, 12, 7, 0, 69 },
13785203945Sweongyo		{ 7, 12, 7, 0, 67 }, { 7, 12, 7, 0, 65 },
13786203945Sweongyo		{ 7, 12, 7, 0, 63 }, { 7, 12, 7, 0, 61 },
13787203945Sweongyo		{ 7, 12, 7, 0, 59 }, { 7, 11, 7, 0, 72 },
13788203945Sweongyo		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13789203945Sweongyo		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 65 },
13790203945Sweongyo		{ 7, 11, 7, 0, 63 }, { 7, 11, 7, 0, 61 },
13791203945Sweongyo		{ 7, 11, 7, 0, 59 }, { 7, 11, 6, 0, 73 },
13792203945Sweongyo		{ 7, 11, 6, 0, 71 }
13793203945Sweongyo	};
13794203945Sweongyo	static struct bwn_txgain_entry txgain_2ghz_r1[] = {
13795203945Sweongyo		{ 4, 15, 15, 0, 90 }, { 4, 15, 15, 0, 88 },
13796203945Sweongyo		{ 4, 15, 15, 0, 85 }, { 4, 15, 15, 0, 83 },
13797203945Sweongyo		{ 4, 15, 15, 0, 81 }, { 4, 15, 15, 0, 78 },
13798203945Sweongyo		{ 4, 15, 15, 0, 76 }, { 4, 15, 15, 0, 74 },
13799203945Sweongyo		{ 4, 15, 15, 0, 72 }, { 4, 15, 15, 0, 70 },
13800203945Sweongyo		{ 4, 15, 15, 0, 68 }, { 4, 15, 15, 0, 66 },
13801203945Sweongyo		{ 4, 15, 15, 0, 64 }, { 4, 15, 15, 0, 62 },
13802203945Sweongyo		{ 4, 15, 15, 0, 60 }, { 4, 15, 15, 0, 59 },
13803203945Sweongyo		{ 4, 15, 14, 0, 72 }, { 4, 15, 14, 0, 70 },
13804203945Sweongyo		{ 4, 15, 14, 0, 68 }, { 4, 15, 14, 0, 66 },
13805203945Sweongyo		{ 4, 15, 14, 0, 64 }, { 4, 15, 14, 0, 62 },
13806203945Sweongyo		{ 4, 15, 14, 0, 60 }, { 4, 15, 14, 0, 59 },
13807203945Sweongyo		{ 4, 15, 13, 0, 72 }, { 4, 15, 13, 0, 70 },
13808203945Sweongyo		{ 4, 15, 13, 0, 68 }, { 4, 15, 13, 0, 66 },
13809203945Sweongyo		{ 4, 15, 13, 0, 64 }, { 4, 15, 13, 0, 62 },
13810203945Sweongyo		{ 4, 15, 13, 0, 60 }, { 4, 15, 13, 0, 59 },
13811203945Sweongyo		{ 4, 15, 12, 0, 72 }, { 4, 15, 12, 0, 70 },
13812203945Sweongyo		{ 4, 15, 12, 0, 68 }, { 4, 15, 12, 0, 66 },
13813203945Sweongyo		{ 4, 15, 12, 0, 64 }, { 4, 15, 12, 0, 62 },
13814203945Sweongyo		{ 4, 15, 12, 0, 60 }, { 4, 15, 12, 0, 59 },
13815203945Sweongyo		{ 4, 15, 11, 0, 72 }, { 4, 15, 11, 0, 70 },
13816203945Sweongyo		{ 4, 15, 11, 0, 68 }, { 4, 15, 11, 0, 66 },
13817203945Sweongyo		{ 4, 15, 11, 0, 64 }, { 4, 15, 11, 0, 62 },
13818203945Sweongyo		{ 4, 15, 11, 0, 60 }, { 4, 15, 11, 0, 59 },
13819203945Sweongyo		{ 4, 15, 10, 0, 72 }, { 4, 15, 10, 0, 70 },
13820203945Sweongyo		{ 4, 15, 10, 0, 68 }, { 4, 15, 10, 0, 66 },
13821203945Sweongyo		{ 4, 15, 10, 0, 64 }, { 4, 15, 10, 0, 62 },
13822203945Sweongyo		{ 4, 15, 10, 0, 60 }, { 4, 15, 10, 0, 59 },
13823203945Sweongyo		{ 4, 15, 9, 0, 72 }, { 4, 15, 9, 0, 70 },
13824203945Sweongyo		{ 4, 15, 9, 0, 68 }, { 4, 15, 9, 0, 66 },
13825203945Sweongyo		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13826203945Sweongyo		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13827203945Sweongyo		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13828203945Sweongyo		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13829203945Sweongyo		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13830203945Sweongyo		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13831203945Sweongyo		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13832203945Sweongyo		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13833203945Sweongyo		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13834203945Sweongyo		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13835203945Sweongyo		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13836203945Sweongyo		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13837203945Sweongyo		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13838203945Sweongyo		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13839203945Sweongyo		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13840203945Sweongyo		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13841203945Sweongyo		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13842203945Sweongyo		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13843203945Sweongyo		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13844203945Sweongyo		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13845203945Sweongyo		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13846203945Sweongyo		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13847203945Sweongyo		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13848203945Sweongyo		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13849203945Sweongyo		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13850203945Sweongyo		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13851203945Sweongyo		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13852203945Sweongyo		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13853203945Sweongyo		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13854203945Sweongyo		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13855203945Sweongyo		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13856203945Sweongyo		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13857203945Sweongyo		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13858203945Sweongyo		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 }
13859203945Sweongyo	};
13860203945Sweongyo	static struct bwn_txgain_entry txgain_5ghz_r1[] = {
13861203945Sweongyo		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13862203945Sweongyo		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13863203945Sweongyo		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13864203945Sweongyo		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13865203945Sweongyo		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13866203945Sweongyo		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13867203945Sweongyo		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13868203945Sweongyo		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13869203945Sweongyo		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13870203945Sweongyo		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13871203945Sweongyo		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13872203945Sweongyo		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13873203945Sweongyo		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13874203945Sweongyo		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13875203945Sweongyo		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13876203945Sweongyo		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13877203945Sweongyo		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13878203945Sweongyo		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13879203945Sweongyo		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13880203945Sweongyo		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13881203945Sweongyo		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13882203945Sweongyo		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13883203945Sweongyo		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13884203945Sweongyo		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13885203945Sweongyo		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13886203945Sweongyo		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13887203945Sweongyo		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13888203945Sweongyo		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13889203945Sweongyo		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13890203945Sweongyo		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13891203945Sweongyo		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13892203945Sweongyo		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13893203945Sweongyo		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13894203945Sweongyo		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13895203945Sweongyo		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13896203945Sweongyo		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13897203945Sweongyo		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13898203945Sweongyo		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13899203945Sweongyo		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13900203945Sweongyo		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13901203945Sweongyo		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13902203945Sweongyo		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13903203945Sweongyo		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13904203945Sweongyo		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13905203945Sweongyo		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13906203945Sweongyo		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13907203945Sweongyo		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13908203945Sweongyo		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13909203945Sweongyo		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13910203945Sweongyo		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13911203945Sweongyo		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13912203945Sweongyo		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13913203945Sweongyo		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13914203945Sweongyo		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13915203945Sweongyo		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13916203945Sweongyo		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13917203945Sweongyo		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13918203945Sweongyo		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13919203945Sweongyo		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13920203945Sweongyo		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13921203945Sweongyo		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13922203945Sweongyo		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13923203945Sweongyo		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13924203945Sweongyo		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13925203945Sweongyo	};
13926203945Sweongyo
13927203945Sweongyo	if (mac->mac_phy.rev != 0 && mac->mac_phy.rev != 1) {
13928204922Sweongyo		if (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA)
13929203945Sweongyo			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r2);
13930203945Sweongyo		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13931203945Sweongyo			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13932203945Sweongyo			    txgain_2ghz_r2);
13933203945Sweongyo		else
13934203945Sweongyo			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13935203945Sweongyo			    txgain_5ghz_r2);
13936203945Sweongyo		return;
13937203945Sweongyo	}
13938203945Sweongyo
13939203945Sweongyo	if (mac->mac_phy.rev == 0) {
13940204922Sweongyo		if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA) ||
13941204922Sweongyo		    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_HGPA))
13942203945Sweongyo			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r0);
13943203945Sweongyo		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13944203945Sweongyo			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13945203945Sweongyo			    txgain_2ghz_r0);
13946203945Sweongyo		else
13947203945Sweongyo			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13948203945Sweongyo			    txgain_5ghz_r0);
13949203945Sweongyo		return;
13950203945Sweongyo	}
13951203945Sweongyo
13952204922Sweongyo	if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA) ||
13953204922Sweongyo	    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_HGPA))
13954203945Sweongyo		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r1);
13955203945Sweongyo	else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13956203945Sweongyo		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_2ghz_r1);
13957203945Sweongyo	else
13958203945Sweongyo		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_5ghz_r1);
13959203945Sweongyo}
13960203945Sweongyo
13961203945Sweongyostatic void
13962203945Sweongyobwn_tab_write(struct bwn_mac *mac, uint32_t typeoffset, uint32_t value)
13963203945Sweongyo{
13964203945Sweongyo	uint32_t offset, type;
13965203945Sweongyo
13966203945Sweongyo	type = BWN_TAB_GETTYPE(typeoffset);
13967203945Sweongyo	offset = BWN_TAB_GETOFFSET(typeoffset);
13968203945Sweongyo	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
13969203945Sweongyo
13970203945Sweongyo	switch (type) {
13971203945Sweongyo	case BWN_TAB_8BIT:
13972203945Sweongyo		KASSERT(!(value & ~0xff), ("%s:%d: fail", __func__, __LINE__));
13973203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13974203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13975203945Sweongyo		break;
13976203945Sweongyo	case BWN_TAB_16BIT:
13977203945Sweongyo		KASSERT(!(value & ~0xffff),
13978203945Sweongyo		    ("%s:%d: fail", __func__, __LINE__));
13979203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13980203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13981203945Sweongyo		break;
13982203945Sweongyo	case BWN_TAB_32BIT:
13983203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13984203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
13985203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13986203945Sweongyo		break;
13987203945Sweongyo	default:
13988203945Sweongyo		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
13989203945Sweongyo	}
13990203945Sweongyo}
13991203945Sweongyo
13992203945Sweongyostatic int
13993203945Sweongyobwn_phy_lp_loopback(struct bwn_mac *mac)
13994203945Sweongyo{
13995203945Sweongyo	struct bwn_phy_lp_iq_est ie;
13996203945Sweongyo	int i, index = -1;
13997203945Sweongyo	uint32_t tmp;
13998203945Sweongyo
13999203945Sweongyo	memset(&ie, 0, sizeof(ie));
14000203945Sweongyo
14001203945Sweongyo	bwn_phy_lp_set_trsw_over(mac, 1, 1);
14002203945Sweongyo	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 1);
14003203945Sweongyo	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
14004203945Sweongyo	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
14005203945Sweongyo	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
14006203945Sweongyo	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
14007203945Sweongyo	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x8);
14008203945Sweongyo	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, 0x80);
14009203945Sweongyo	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x80);
14010203945Sweongyo	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x80);
14011203945Sweongyo	for (i = 0; i < 32; i++) {
14012203945Sweongyo		bwn_phy_lp_set_rxgain_idx(mac, i);
14013203945Sweongyo		bwn_phy_lp_ddfs_turnon(mac, 1, 1, 5, 5, 0);
14014203945Sweongyo		if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
14015203945Sweongyo			continue;
14016203945Sweongyo		tmp = (ie.ie_ipwr + ie.ie_qpwr) / 1000;
14017203945Sweongyo		if ((tmp > 4000) && (tmp < 10000)) {
14018203945Sweongyo			index = i;
14019203945Sweongyo			break;
14020203945Sweongyo		}
14021203945Sweongyo	}
14022203945Sweongyo	bwn_phy_lp_ddfs_turnoff(mac);
14023203945Sweongyo	return (index);
14024203945Sweongyo}
14025203945Sweongyo
14026203945Sweongyostatic void
14027203945Sweongyobwn_phy_lp_set_rxgain_idx(struct bwn_mac *mac, uint16_t idx)
14028203945Sweongyo{
14029203945Sweongyo
14030203945Sweongyo	bwn_phy_lp_set_rxgain(mac, bwn_tab_read(mac, BWN_TAB_2(12, idx)));
14031203945Sweongyo}
14032203945Sweongyo
14033203945Sweongyostatic void
14034203945Sweongyobwn_phy_lp_ddfs_turnon(struct bwn_mac *mac, int i_on, int q_on,
14035203945Sweongyo    int incr1, int incr2, int scale_idx)
14036203945Sweongyo{
14037203945Sweongyo
14038203945Sweongyo	bwn_phy_lp_ddfs_turnoff(mac);
14039203945Sweongyo	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0xff80);
14040203945Sweongyo	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0x80ff);
14041203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0xff80, incr1);
14042203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0x80ff, incr2 << 8);
14043203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff7, i_on << 3);
14044203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xffef, q_on << 4);
14045203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xff9f, scale_idx << 5);
14046203945Sweongyo	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffb);
14047203945Sweongyo	BWN_PHY_SET(mac, BWN_PHY_AFE_DDFS, 0x2);
14048203945Sweongyo	BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x20);
14049203945Sweongyo}
14050203945Sweongyo
14051203945Sweongyostatic uint8_t
14052203945Sweongyobwn_phy_lp_rx_iq_est(struct bwn_mac *mac, uint16_t sample, uint8_t time,
14053203945Sweongyo    struct bwn_phy_lp_iq_est *ie)
14054203945Sweongyo{
14055203945Sweongyo	int i;
14056203945Sweongyo
14057203945Sweongyo	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfff7);
14058203945Sweongyo	BWN_PHY_WRITE(mac, BWN_PHY_IQ_NUM_SMPLS_ADDR, sample);
14059203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xff00, time);
14060203945Sweongyo	BWN_PHY_MASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xfeff);
14061203945Sweongyo	BWN_PHY_SET(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0x200);
14062203945Sweongyo
14063203945Sweongyo	for (i = 0; i < 500; i++) {
14064203945Sweongyo		if (!(BWN_PHY_READ(mac,
14065203945Sweongyo		    BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200))
14066203945Sweongyo			break;
14067203945Sweongyo		DELAY(1000);
14068203945Sweongyo	}
14069203945Sweongyo	if ((BWN_PHY_READ(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200)) {
14070203945Sweongyo		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
14071203945Sweongyo		return 0;
14072203945Sweongyo	}
14073203945Sweongyo
14074203945Sweongyo	ie->ie_iqprod = BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_HI_ADDR);
14075203945Sweongyo	ie->ie_iqprod <<= 16;
14076203945Sweongyo	ie->ie_iqprod |= BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_LO_ADDR);
14077203945Sweongyo	ie->ie_ipwr = BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_HI_ADDR);
14078203945Sweongyo	ie->ie_ipwr <<= 16;
14079203945Sweongyo	ie->ie_ipwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_LO_ADDR);
14080203945Sweongyo	ie->ie_qpwr = BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_HI_ADDR);
14081203945Sweongyo	ie->ie_qpwr <<= 16;
14082203945Sweongyo	ie->ie_qpwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_LO_ADDR);
14083203945Sweongyo
14084203945Sweongyo	BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
14085203945Sweongyo	return 1;
14086203945Sweongyo}
14087203945Sweongyo
14088203945Sweongyostatic uint32_t
14089203945Sweongyobwn_tab_read(struct bwn_mac *mac, uint32_t typeoffset)
14090203945Sweongyo{
14091203945Sweongyo	uint32_t offset, type, value;
14092203945Sweongyo
14093203945Sweongyo	type = BWN_TAB_GETTYPE(typeoffset);
14094203945Sweongyo	offset = BWN_TAB_GETOFFSET(typeoffset);
14095203945Sweongyo	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
14096203945Sweongyo
14097203945Sweongyo	switch (type) {
14098203945Sweongyo	case BWN_TAB_8BIT:
14099203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14100203945Sweongyo		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
14101203945Sweongyo		break;
14102203945Sweongyo	case BWN_TAB_16BIT:
14103203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14104203945Sweongyo		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
14105203945Sweongyo		break;
14106203945Sweongyo	case BWN_TAB_32BIT:
14107203945Sweongyo		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14108203945Sweongyo		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATAHI);
14109203945Sweongyo		value <<= 16;
14110203945Sweongyo		value |= BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
14111203945Sweongyo		break;
14112203945Sweongyo	default:
14113203945Sweongyo		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
14114203945Sweongyo		value = 0;
14115203945Sweongyo	}
14116203945Sweongyo
14117203945Sweongyo	return (value);
14118203945Sweongyo}
14119203945Sweongyo
14120203945Sweongyostatic void
14121203945Sweongyobwn_phy_lp_ddfs_turnoff(struct bwn_mac *mac)
14122203945Sweongyo{
14123203945Sweongyo
14124203945Sweongyo	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffd);
14125203945Sweongyo	BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0xffdf);
14126203945Sweongyo}
14127203945Sweongyo
14128203945Sweongyostatic void
14129203945Sweongyobwn_phy_lp_set_txgain_dac(struct bwn_mac *mac, uint16_t dac)
14130203945Sweongyo{
14131203945Sweongyo	uint16_t ctl;
14132203945Sweongyo
14133203945Sweongyo	ctl = BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0xc7f;
14134203945Sweongyo	ctl |= dac << 7;
14135203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf000, ctl);
14136203945Sweongyo}
14137203945Sweongyo
14138203945Sweongyostatic void
14139203945Sweongyobwn_phy_lp_set_txgain_pa(struct bwn_mac *mac, uint16_t gain)
14140203945Sweongyo{
14141203945Sweongyo
14142203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0xe03f, gain << 6);
14143203945Sweongyo	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x80ff, gain << 8);
14144203945Sweongyo}
14145203945Sweongyo
14146203945Sweongyostatic void
14147203945Sweongyobwn_phy_lp_set_txgain_override(struct bwn_mac *mac)
14148203945Sweongyo{
14149203945Sweongyo
14150203945Sweongyo	if (mac->mac_phy.rev < 2)
14151203945Sweongyo		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
14152203945Sweongyo	else {
14153203945Sweongyo		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x80);
14154203945Sweongyo		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x4000);
14155203945Sweongyo	}
14156203945Sweongyo	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x40);
14157203945Sweongyo}
14158203945Sweongyo
14159203945Sweongyostatic uint16_t
14160203945Sweongyobwn_phy_lp_get_pa_gain(struct bwn_mac *mac)
14161203945Sweongyo{
14162203945Sweongyo
14163203945Sweongyo	return BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0x7f;
14164203945Sweongyo}
14165203945Sweongyo
14166203945Sweongyostatic uint8_t
14167203945Sweongyobwn_nbits(int32_t val)
14168203945Sweongyo{
14169203945Sweongyo	uint32_t tmp;
14170203945Sweongyo	uint8_t nbits = 0;
14171203945Sweongyo
14172203945Sweongyo	for (tmp = abs(val); tmp != 0; tmp >>= 1)
14173203945Sweongyo		nbits++;
14174203945Sweongyo	return (nbits);
14175203945Sweongyo}
14176203945Sweongyo
14177203945Sweongyostatic void
14178203945Sweongyobwn_phy_lp_gaintbl_write_multi(struct bwn_mac *mac, int offset, int count,
14179203945Sweongyo    struct bwn_txgain_entry *table)
14180203945Sweongyo{
14181203945Sweongyo	int i;
14182203945Sweongyo
14183203945Sweongyo	for (i = offset; i < count; i++)
14184203945Sweongyo		bwn_phy_lp_gaintbl_write(mac, i, table[i]);
14185203945Sweongyo}
14186203945Sweongyo
14187203945Sweongyostatic void
14188203945Sweongyobwn_phy_lp_gaintbl_write(struct bwn_mac *mac, int offset,
14189203945Sweongyo    struct bwn_txgain_entry data)
14190203945Sweongyo{
14191203945Sweongyo
14192203945Sweongyo	if (mac->mac_phy.rev >= 2)
14193203945Sweongyo		bwn_phy_lp_gaintbl_write_r2(mac, offset, data);
14194203945Sweongyo	else
14195203945Sweongyo		bwn_phy_lp_gaintbl_write_r01(mac, offset, data);
14196203945Sweongyo}
14197203945Sweongyo
14198203945Sweongyostatic void
14199203945Sweongyobwn_phy_lp_gaintbl_write_r2(struct bwn_mac *mac, int offset,
14200203945Sweongyo    struct bwn_txgain_entry te)
14201203945Sweongyo{
14202203945Sweongyo	struct bwn_softc *sc = mac->mac_sc;
14203203945Sweongyo	struct ifnet *ifp = sc->sc_ifp;
14204203945Sweongyo	struct ieee80211com *ic = ifp->if_l2com;
14205203945Sweongyo	uint32_t tmp;
14206203945Sweongyo
14207203945Sweongyo	KASSERT(mac->mac_phy.rev >= 2, ("%s:%d: fail", __func__, __LINE__));
14208203945Sweongyo
14209203945Sweongyo	tmp = (te.te_pad << 16) | (te.te_pga << 8) | te.te_gm;
14210203945Sweongyo	if (mac->mac_phy.rev >= 3) {
14211203945Sweongyo		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14212203945Sweongyo		    (0x10 << 24) : (0x70 << 24));
14213203945Sweongyo	} else {
14214203945Sweongyo		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14215203945Sweongyo		    (0x14 << 24) : (0x7f << 24));
14216203945Sweongyo	}
14217203945Sweongyo	bwn_tab_write(mac, BWN_TAB_4(7, 0xc0 + offset), tmp);
14218203945Sweongyo	bwn_tab_write(mac, BWN_TAB_4(7, 0x140 + offset),
14219203945Sweongyo	    te.te_bbmult << 20 | te.te_dac << 28);
14220203945Sweongyo}
14221203945Sweongyo
14222203945Sweongyostatic void
14223203945Sweongyobwn_phy_lp_gaintbl_write_r01(struct bwn_mac *mac, int offset,
14224203945Sweongyo    struct bwn_txgain_entry te)
14225203945Sweongyo{
14226203945Sweongyo
14227203945Sweongyo	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
14228203945Sweongyo
14229203945Sweongyo	bwn_tab_write(mac, BWN_TAB_4(10, 0xc0 + offset),
14230203945Sweongyo	    (te.te_pad << 11) | (te.te_pga << 7) | (te.te_gm  << 4) |
14231203945Sweongyo	    te.te_dac);
14232203945Sweongyo	bwn_tab_write(mac, BWN_TAB_4(10, 0x140 + offset), te.te_bbmult << 20);
14233203945Sweongyo}
14234203945Sweongyo
14235203945Sweongyostatic void
14236204257Sweongyobwn_sysctl_node(struct bwn_softc *sc)
14237204257Sweongyo{
14238204257Sweongyo	device_t dev = sc->sc_dev;
14239204257Sweongyo	struct bwn_mac *mac;
14240204257Sweongyo	struct bwn_stats *stats;
14241204257Sweongyo
14242204257Sweongyo	/* XXX assume that count of MAC is only 1. */
14243204257Sweongyo
14244204257Sweongyo	if ((mac = sc->sc_curmac) == NULL)
14245204257Sweongyo		return;
14246204257Sweongyo	stats = &mac->mac_stats;
14247204257Sweongyo
14248204257Sweongyo	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14249204257Sweongyo	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14250204257Sweongyo	    "linknoise", CTLFLAG_RW, &stats->rts, 0, "Noise level");
14251204257Sweongyo	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14252204257Sweongyo	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14253204257Sweongyo	    "rts", CTLFLAG_RW, &stats->rts, 0, "RTS");
14254204257Sweongyo	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14255204257Sweongyo	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14256204257Sweongyo	    "rtsfail", CTLFLAG_RW, &stats->rtsfail, 0, "RTS failed to send");
14257204257Sweongyo
14258204257Sweongyo#ifdef BWN_DEBUG
14259204257Sweongyo	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14260204257Sweongyo	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14261204257Sweongyo	    "debug", CTLFLAG_RW, &sc->sc_debug, 0, "Debug flags");
14262204257Sweongyo#endif
14263204257Sweongyo}
14264204257Sweongyo
14265203945Sweongyostatic device_method_t bwn_methods[] = {
14266203945Sweongyo	/* Device interface */
14267203945Sweongyo	DEVMETHOD(device_probe,		bwn_probe),
14268203945Sweongyo	DEVMETHOD(device_attach,	bwn_attach),
14269203945Sweongyo	DEVMETHOD(device_detach,	bwn_detach),
14270203945Sweongyo	DEVMETHOD(device_suspend,	bwn_suspend),
14271203945Sweongyo	DEVMETHOD(device_resume,	bwn_resume),
14272204923Sweongyo	KOBJMETHOD_END
14273203945Sweongyo};
14274203945Sweongyostatic driver_t bwn_driver = {
14275203945Sweongyo	"bwn",
14276203945Sweongyo	bwn_methods,
14277203945Sweongyo	sizeof(struct bwn_softc)
14278203945Sweongyo};
14279203945Sweongyostatic devclass_t bwn_devclass;
14280203945SweongyoDRIVER_MODULE(bwn, siba_bwn, bwn_driver, bwn_devclass, 0, 0);
14281203945SweongyoMODULE_DEPEND(bwn, siba_bwn, 1, 1, 1);
14282203945SweongyoMODULE_DEPEND(bwn, wlan, 1, 1, 1);		/* 802.11 media layer */
14283203945SweongyoMODULE_DEPEND(bwn, firmware, 1, 1, 1);		/* firmware support */
14284203945SweongyoMODULE_DEPEND(bwn, wlan_amrr, 1, 1, 1);
14285