1/*	$NetBSD: bwi.c,v 1.38 2021/06/16 00:21:18 riastradh Exp $	*/
2/*	$OpenBSD: bwi.c,v 1.74 2008/02/25 21:13:30 mglocker Exp $	*/
3
4/*
5 * Copyright (c) 2007 The DragonFly Project.  All rights reserved.
6 *
7 * This code is derived from software contributed to The DragonFly Project
8 * by Sepherosa Ziehau <sepherosa@gmail.com>
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 *
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 *    notice, this list of conditions and the following disclaimer in
18 *    the documentation and/or other materials provided with the
19 *    distribution.
20 * 3. Neither the name of The DragonFly Project nor the names of its
21 *    contributors may be used to endorse or promote products derived
22 *    from this software without specific, prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
28 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
30 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
32 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
33 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
34 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 *
37 * $DragonFly: src/sys/dev/netif/bwi/bwimac.c,v 1.1 2007/09/08 06:15:54 sephe Exp $
38 */
39
40/*
41 * Broadcom AirForce BCM43xx IEEE 802.11b/g wireless network driver
42 * Generic back end
43 */
44
45/* [TRC: XXX Names beginning with `bwi_ieee80211_*' are those that I
46   think should be in NetBSD's generic 802.11 code, not in this
47   driver.] */
48
49
50#include <sys/cdefs.h>
51__KERNEL_RCSID(0, "$NetBSD: bwi.c,v 1.38 2021/06/16 00:21:18 riastradh Exp $");
52
53#include <sys/param.h>
54#include <sys/callout.h>
55#include <sys/device.h>
56#include <sys/kernel.h>
57#include <sys/malloc.h>
58#include <sys/mbuf.h>
59#include <sys/socket.h>
60#include <sys/sockio.h>
61#include <sys/sysctl.h>
62#include <sys/systm.h>
63#include <sys/bus.h>
64#include <sys/intr.h>
65
66#include <machine/endian.h>
67
68#include <dev/firmload.h>
69
70#include <net/if.h>
71#include <net/if_dl.h>
72#include <net/if_ether.h>
73#include <net/if_media.h>
74
75#include <net/bpf.h>
76
77#include <net80211/ieee80211_var.h>
78/* [TRC: XXX amrr] */
79#include <net80211/ieee80211_amrr.h>
80#include <net80211/ieee80211_radiotap.h>
81
82#include <dev/ic/bwireg.h>
83#include <dev/ic/bwivar.h>
84
85#ifdef BWI_DEBUG
86int bwi_debug = 0;
87
88#define DPRINTF(sc, dbg, fmt, ...)					\
89do {									\
90	if ((sc)->sc_debug & (dbg))					\
91		aprint_debug_dev((sc)->sc_dev, fmt, ##__VA_ARGS__);	\
92} while (0)
93
94#else	/* !BWI_DEBUG */
95
96#define DPRINTF(sc, dbg, fmt, ...)	((void)0)
97
98#endif	/* BWI_DEBUG */
99
100/* XXX temporary porting goop */
101#include <dev/pci/pcireg.h>
102#include <dev/pci/pcivar.h>
103#include <dev/pci/pcidevs.h>
104
105/* XXX does not belong here */
106#define IEEE80211_OFDM_PLCP_RATE_MASK	0x0000000f
107#define IEEE80211_OFDM_PLCP_LEN_MASK	0x0001ffe0
108
109/*
110 * Contention window (slots).  [TRC: dfly/net80211/80211.h]
111 */
112#define IEEE80211_CW_MAX	1023	/* aCWmax */
113#define IEEE80211_CW_MIN_0	31	/* DS/CCK aCWmin, ERP aCWmin(0) */
114#define IEEE80211_CW_MIN_1	15	/* OFDM aCWmin, ERP aCWmin(1) */
115
116/*
117 * Slot time (microseconds).  [TRC: dfly/net80211/80211.h]
118 */
119#define IEEE80211_DUR_SLOT      20      /* DS/CCK slottime, ERP long slottime */
120#define IEEE80211_DUR_SHSLOT    9       /* ERP short slottime */
121#define IEEE80211_DUR_OFDM_SLOT 9       /* OFDM slottime */
122
123/* XXX end porting goop */
124
125/* MAC */
126struct bwi_retry_lim {
127	uint16_t	shretry;
128	uint16_t	shretry_fb;
129	uint16_t	lgretry;
130	uint16_t	lgretry_fb;
131};
132
133struct bwi_clock_freq {
134	uint		clkfreq_min;
135	uint		clkfreq_max;
136};
137
138/* XXX does not belong here */
139struct ieee80211_ds_plcp_hdr {
140	uint8_t		i_signal;
141	uint8_t		i_service;
142	uint16_t	i_length;
143	uint16_t	i_crc;
144} __packed;
145
146static void	 bwi_sysctlattach(struct bwi_softc *);
147
148/* MAC */
149static void	 bwi_tmplt_write_4(struct bwi_mac *, uint32_t, uint32_t);
150static void	 bwi_hostflags_write(struct bwi_mac *, uint64_t);
151static uint64_t	 bwi_hostflags_read(struct bwi_mac *);
152static uint16_t	 bwi_memobj_read_2(struct bwi_mac *, uint16_t, uint16_t);
153static uint32_t	 bwi_memobj_read_4(struct bwi_mac *, uint16_t, uint16_t);
154static void	 bwi_memobj_write_2(struct bwi_mac *, uint16_t, uint16_t,
155		     uint16_t);
156static void	 bwi_memobj_write_4(struct bwi_mac *, uint16_t, uint16_t,
157		     uint32_t);
158static int	 bwi_mac_lateattach(struct bwi_mac *);
159static int	 bwi_mac_init(struct bwi_mac *);
160static void	 bwi_mac_reset(struct bwi_mac *, int);
161static void	 bwi_mac_set_tpctl_11bg(struct bwi_mac *,
162		     const struct bwi_tpctl *);
163static int	 bwi_mac_test(struct bwi_mac *);
164static void	 bwi_mac_setup_tpctl(struct bwi_mac *);
165static void	 bwi_mac_dummy_xmit(struct bwi_mac *);
166static void	 bwi_mac_init_tpctl_11bg(struct bwi_mac *);
167static void	 bwi_mac_detach(struct bwi_mac *);
168static int	 bwi_mac_fw_alloc(struct bwi_mac *);
169static void	 bwi_mac_fw_free(struct bwi_mac *);
170static int	 bwi_mac_fw_image_alloc(struct bwi_mac *, const char *,
171    		     int idx, struct bwi_fw_image *, uint8_t);
172static void	 bwi_mac_fw_image_free(struct bwi_mac *, struct bwi_fw_image *);
173static int	 bwi_mac_fw_load(struct bwi_mac *);
174static int	 bwi_mac_gpio_init(struct bwi_mac *);
175static int	 bwi_mac_gpio_fini(struct bwi_mac *);
176static int	 bwi_mac_fw_load_iv(struct bwi_mac *,
177		     const struct bwi_fw_image *);
178static int	 bwi_mac_fw_init(struct bwi_mac *);
179static void	 bwi_mac_opmode_init(struct bwi_mac *);
180static void	 bwi_mac_hostflags_init(struct bwi_mac *);
181static void	 bwi_mac_bss_param_init(struct bwi_mac *);
182static void	 bwi_mac_set_retry_lim(struct bwi_mac *,
183		     const struct bwi_retry_lim *);
184static void	 bwi_mac_set_ackrates(struct bwi_mac *,
185		     const struct ieee80211_rateset *);
186static int	 bwi_mac_start(struct bwi_mac *);
187static int	 bwi_mac_stop(struct bwi_mac *);
188static int	 bwi_mac_config_ps(struct bwi_mac *);
189static void	 bwi_mac_reset_hwkeys(struct bwi_mac *);
190static void	 bwi_mac_shutdown(struct bwi_mac *);
191static int	 bwi_mac_get_property(struct bwi_mac *);
192static void	 bwi_mac_updateslot(struct bwi_mac *, int);
193static int	 bwi_mac_attach(struct bwi_softc *, int, uint8_t);
194static void	 bwi_mac_balance_atten(int *, int *);
195static void	 bwi_mac_adjust_tpctl(struct bwi_mac *, int, int);
196static void	 bwi_mac_calibrate_txpower(struct bwi_mac *,
197		     enum bwi_txpwrcb_type);
198static void	 bwi_mac_lock(struct bwi_mac *);
199static void	 bwi_mac_unlock(struct bwi_mac *);
200static void	 bwi_mac_set_promisc(struct bwi_mac *, int);
201
202/* PHY */
203static void	 bwi_phy_write(struct bwi_mac *, uint16_t, uint16_t);
204static uint16_t	 bwi_phy_read(struct bwi_mac *, uint16_t);
205static int	 bwi_phy_attach(struct bwi_mac *);
206static void	 bwi_phy_set_bbp_atten(struct bwi_mac *, uint16_t);
207static int	 bwi_phy_calibrate(struct bwi_mac *);
208static void	 bwi_tbl_write_2(struct bwi_mac *mac, uint16_t, uint16_t);
209static void	 bwi_tbl_write_4(struct bwi_mac *mac, uint16_t, uint32_t);
210static void	 bwi_nrssi_write(struct bwi_mac *, uint16_t, int16_t);
211static int16_t	 bwi_nrssi_read(struct bwi_mac *, uint16_t);
212static void	 bwi_phy_init_11a(struct bwi_mac *);
213static void	 bwi_phy_init_11g(struct bwi_mac *);
214static void	 bwi_phy_init_11b_rev2(struct bwi_mac *);
215static void	 bwi_phy_init_11b_rev4(struct bwi_mac *);
216static void	 bwi_phy_init_11b_rev5(struct bwi_mac *);
217static void	 bwi_phy_init_11b_rev6(struct bwi_mac *);
218static void	 bwi_phy_config_11g(struct bwi_mac *);
219static void	 bwi_phy_config_agc(struct bwi_mac *);
220static void	 bwi_set_gains(struct bwi_mac *, const struct bwi_gains *);
221static void	 bwi_phy_clear_state(struct bwi_phy *);
222
223/* RF */
224static int16_t	 bwi_nrssi_11g(struct bwi_mac *);
225static struct bwi_rf_lo
226		*bwi_get_rf_lo(struct bwi_mac *, uint16_t, uint16_t);
227static int	 bwi_rf_lo_isused(struct bwi_mac *, const struct bwi_rf_lo *);
228static void	 bwi_rf_write(struct bwi_mac *, uint16_t, uint16_t);
229static uint16_t	 bwi_rf_read(struct bwi_mac *, uint16_t);
230static int	 bwi_rf_attach(struct bwi_mac *);
231static void	 bwi_rf_set_chan(struct bwi_mac *, uint, int);
232static void	 bwi_rf_get_gains(struct bwi_mac *);
233static void	 bwi_rf_init(struct bwi_mac *);
234static void	 bwi_rf_off_11a(struct bwi_mac *);
235static void	 bwi_rf_off_11bg(struct bwi_mac *);
236static void	 bwi_rf_off_11g_rev5(struct bwi_mac *);
237static void	 bwi_rf_workaround(struct bwi_mac *, uint);
238static struct bwi_rf_lo
239		*bwi_rf_lo_find(struct bwi_mac *, const struct bwi_tpctl *);
240static void	 bwi_rf_lo_adjust(struct bwi_mac *, const struct bwi_tpctl *);
241static void	 bwi_rf_lo_write(struct bwi_mac *, const struct bwi_rf_lo *);
242static int	 bwi_rf_gain_max_reached(struct bwi_mac *, int);
243static uint16_t	 bwi_bitswap4(uint16_t);
244static uint16_t	 bwi_phy812_value(struct bwi_mac *, uint16_t);
245static void	 bwi_rf_init_bcm2050(struct bwi_mac *);
246static uint16_t	 bwi_rf_calibval(struct bwi_mac *);
247static int32_t	 _bwi_adjust_devide(int32_t, int32_t);
248static int	 bwi_rf_calc_txpower(int8_t *, uint8_t, const int16_t[]);
249static int	 bwi_rf_map_txpower(struct bwi_mac *);
250static void	 bwi_rf_lo_update_11g(struct bwi_mac *);
251static uint32_t	 bwi_rf_lo_devi_measure(struct bwi_mac *, uint16_t);
252static uint16_t	 bwi_rf_get_tp_ctrl2(struct bwi_mac *);
253static uint8_t	 _bwi_rf_lo_update_11g(struct bwi_mac *, uint16_t);
254static void	 bwi_rf_lo_measure_11g(struct bwi_mac *,
255		     const struct bwi_rf_lo *, struct bwi_rf_lo *, uint8_t);
256static void	 bwi_rf_calc_nrssi_slope_11b(struct bwi_mac *);
257static void	 bwi_rf_set_nrssi_ofs_11g(struct bwi_mac *);
258static void	 bwi_rf_calc_nrssi_slope_11g(struct bwi_mac *);
259static void	 bwi_rf_init_sw_nrssi_table(struct bwi_mac *);
260static void	 bwi_rf_init_hw_nrssi_table(struct bwi_mac *, uint16_t);
261static void	 bwi_rf_set_nrssi_thr_11b(struct bwi_mac *);
262static int32_t	 _nrssi_threshold(const struct bwi_rf *, int32_t);
263static void	 bwi_rf_set_nrssi_thr_11g(struct bwi_mac *);
264static void	 bwi_rf_clear_tssi(struct bwi_mac *);
265static void	 bwi_rf_clear_state(struct bwi_rf *);
266static void	 bwi_rf_on_11a(struct bwi_mac *);
267static void	 bwi_rf_on_11bg(struct bwi_mac *);
268static void	 bwi_rf_set_ant_mode(struct bwi_mac *, int);
269static int	 bwi_rf_get_latest_tssi(struct bwi_mac *, int8_t[], uint16_t);
270static int	 bwi_rf_tssi2dbm(struct bwi_mac *, int8_t, int8_t *);
271static int	 bwi_rf_calc_rssi_bcm2050(struct bwi_mac *,
272		     const struct bwi_rxbuf_hdr *);
273static int	 bwi_rf_calc_rssi_bcm2053(struct bwi_mac *,
274		     const struct bwi_rxbuf_hdr *);
275static int	 bwi_rf_calc_rssi_bcm2060(struct bwi_mac *,
276		     const struct bwi_rxbuf_hdr *);
277static uint16_t	 bwi_rf_lo_measure_11b(struct bwi_mac *);
278static void	 bwi_rf_lo_update_11b(struct bwi_mac *);
279
280/* INTERFACE */
281static uint16_t	 bwi_read_sprom(struct bwi_softc *, uint16_t);
282static void	 bwi_setup_desc32(struct bwi_softc *, struct bwi_desc32 *, int,
283		     int, bus_addr_t, int, int);
284static void	 bwi_power_on(struct bwi_softc *, int);
285static int	 bwi_power_off(struct bwi_softc *, int);
286static int	 bwi_regwin_switch(struct bwi_softc *, struct bwi_regwin *,
287		     struct bwi_regwin **);
288static int	 bwi_regwin_select(struct bwi_softc *, int);
289static void	 bwi_regwin_info(struct bwi_softc *, uint16_t *, uint8_t *);
290static void	 bwi_led_attach(struct bwi_softc *);
291static void	 bwi_led_newstate(struct bwi_softc *, enum ieee80211_state);
292static uint16_t	 bwi_led_onoff(const struct bwi_led *, uint16_t, int);
293static void	 bwi_led_event(struct bwi_softc *, int);
294static void	 bwi_led_blink_start(struct bwi_softc *, int, int);
295static void	 bwi_led_blink_next(void *);
296static void	 bwi_led_blink_end(void *);
297static int	 bwi_bbp_attach(struct bwi_softc *);
298static int	 bwi_bus_init(struct bwi_softc *, struct bwi_mac *);
299static void	 bwi_get_card_flags(struct bwi_softc *);
300static void	 bwi_get_eaddr(struct bwi_softc *, uint16_t, uint8_t *);
301static void	 bwi_get_clock_freq(struct bwi_softc *,
302		     struct bwi_clock_freq *);
303static int	 bwi_set_clock_mode(struct bwi_softc *, enum bwi_clock_mode);
304static int	 bwi_set_clock_delay(struct bwi_softc *);
305static int	 bwi_init(struct ifnet *);
306static void	 bwi_init_statechg(struct bwi_softc *, int);
307static int	 bwi_ioctl(struct ifnet *, u_long, void *);
308static void	 bwi_start(struct ifnet *);
309static void	 bwi_watchdog(struct ifnet *);
310static void	 bwi_stop(struct ifnet *, int);
311static void	 bwi_newstate_begin(struct bwi_softc *, enum ieee80211_state);
312static int	 bwi_newstate(struct ieee80211com *, enum ieee80211_state, int);
313static int	 bwi_media_change(struct ifnet *);
314/* [TRC: XXX amrr] */
315static void	 bwi_iter_func(void *, struct ieee80211_node *);
316static void	 bwi_amrr_timeout(void *);
317static void	 bwi_newassoc(struct ieee80211_node *, int);
318static struct ieee80211_node *
319		 bwi_node_alloc(struct ieee80211_node_table *);
320static int	 bwi_dma_alloc(struct bwi_softc *);
321static void	 bwi_dma_free(struct bwi_softc *);
322static void	 bwi_ring_data_free(struct bwi_ring_data *, struct bwi_softc *);
323static int	 bwi_dma_ring_alloc(struct bwi_softc *,
324		     struct bwi_ring_data *, bus_size_t, uint32_t);
325static int	 bwi_dma_txstats_alloc(struct bwi_softc *, uint32_t,
326		     bus_size_t);
327static void	 bwi_dma_txstats_free(struct bwi_softc *);
328static int	 bwi_dma_mbuf_create(struct bwi_softc *);
329static void	 bwi_dma_mbuf_destroy(struct bwi_softc *, int, int);
330static void	 bwi_enable_intrs(struct bwi_softc *, uint32_t);
331static void	 bwi_disable_intrs(struct bwi_softc *, uint32_t);
332static int	 bwi_init_tx_ring32(struct bwi_softc *, int);
333static void	 bwi_init_rxdesc_ring32(struct bwi_softc *, uint32_t,
334		     bus_addr_t, int, int);
335static int	 bwi_init_rx_ring32(struct bwi_softc *);
336static int	 bwi_init_txstats32(struct bwi_softc *);
337static void	 bwi_setup_rx_desc32(struct bwi_softc *, int, bus_addr_t, int);
338static void	 bwi_setup_tx_desc32(struct bwi_softc *, struct bwi_ring_data *,
339		     int, bus_addr_t, int);
340static int	 bwi_init_tx_ring64(struct bwi_softc *, int);
341static int	 bwi_init_rx_ring64(struct bwi_softc *);
342static int	 bwi_init_txstats64(struct bwi_softc *);
343static void	 bwi_setup_rx_desc64(struct bwi_softc *, int, bus_addr_t, int);
344static void	 bwi_setup_tx_desc64(struct bwi_softc *, struct bwi_ring_data *,
345		     int, bus_addr_t, int);
346static int	 bwi_newbuf(struct bwi_softc *, int, int);
347static void	 bwi_set_addr_filter(struct bwi_softc *, uint16_t,
348		     const uint8_t *);
349static int	 bwi_set_chan(struct bwi_softc *, struct ieee80211_channel *);
350static void	 bwi_next_scan(void *);
351static int	 bwi_rxeof(struct bwi_softc *, int);
352static int	 bwi_rxeof32(struct bwi_softc *);
353static int	 bwi_rxeof64(struct bwi_softc *);
354static void	 bwi_reset_rx_ring32(struct bwi_softc *, uint32_t);
355static void	 bwi_free_txstats32(struct bwi_softc *);
356static void	 bwi_free_rx_ring32(struct bwi_softc *);
357static void	 bwi_free_tx_ring32(struct bwi_softc *, int);
358static void	 bwi_free_txstats64(struct bwi_softc *);
359static void	 bwi_free_rx_ring64(struct bwi_softc *);
360static void	 bwi_free_tx_ring64(struct bwi_softc *, int);
361static uint8_t	 bwi_ieee80211_rate2plcp(uint8_t rate, enum ieee80211_phymode);
362static uint8_t	 bwi_ieee80211_plcp2rate(uint8_t rate, enum ieee80211_phymode);
363static enum bwi_ieee80211_modtype
364		 bwi_ieee80211_rate2modtype(uint8_t rate);
365static uint8_t	 bwi_ofdm_plcp2rate(const void *);
366static uint8_t	 bwi_ds_plcp2rate(const struct ieee80211_ds_plcp_hdr *);
367static void	 bwi_ofdm_plcp_header(uint32_t *, int, uint8_t);
368static void	 bwi_ds_plcp_header(struct ieee80211_ds_plcp_hdr *, int,
369		     uint8_t);
370static void	 bwi_plcp_header(void *, int, uint8_t);
371static int	 bwi_encap(struct bwi_softc *, int, struct mbuf *,
372		     struct ieee80211_node **, int);
373static void	 bwi_start_tx32(struct bwi_softc *, uint32_t, int);
374static void	 bwi_start_tx64(struct bwi_softc *, uint32_t, int);
375static void	 bwi_txeof_status32(struct bwi_softc *);
376static void	 bwi_txeof_status64(struct bwi_softc *);
377static void	 _bwi_txeof(struct bwi_softc *, uint16_t);
378static void	 bwi_txeof_status(struct bwi_softc *, int);
379static void	 bwi_txeof(struct bwi_softc *);
380static int	 bwi_bbp_power_on(struct bwi_softc *, enum bwi_clock_mode);
381static void	 bwi_bbp_power_off(struct bwi_softc *);
382static int	 bwi_get_pwron_delay(struct bwi_softc *sc);
383static int	 bwi_bus_attach(struct bwi_softc *);
384static const char
385		*bwi_regwin_name(const struct bwi_regwin *);
386static int	 bwi_regwin_is_enabled(struct bwi_softc *, struct bwi_regwin *);
387static uint32_t	 bwi_regwin_disable_bits(struct bwi_softc *);
388static void	 bwi_regwin_enable(struct bwi_softc *, struct bwi_regwin *,
389		     uint32_t);
390static void	 bwi_regwin_disable(struct bwi_softc *, struct bwi_regwin *,
391		     uint32_t);
392static void	 bwi_set_bssid(struct bwi_softc *, const uint8_t *);
393static void	 bwi_updateslot(struct ifnet *);
394static void	 bwi_calibrate(void *);
395static int	 bwi_calc_rssi(struct bwi_softc *,
396		     const struct bwi_rxbuf_hdr *);
397static uint8_t	 bwi_ieee80211_ack_rate(struct ieee80211_node *, uint8_t);
398static uint16_t	 bwi_ieee80211_txtime(struct ieee80211com *,
399		     struct ieee80211_node *, uint, uint8_t, uint32_t);
400
401/* MAC */
402static const uint8_t bwi_sup_macrev[] = { 2, 4, 5, 6, 7, 9, 10, 12 };
403
404/* PHY */
405#define SUP_BPHY(num)	{ .rev = num, .init = bwi_phy_init_11b_rev##num }
406
407static const struct {
408	uint8_t	rev;
409	void	(*init)(struct bwi_mac *);
410} bwi_sup_bphy[] = {
411	SUP_BPHY(2),
412	SUP_BPHY(4),
413	SUP_BPHY(5),
414	SUP_BPHY(6)
415};
416
417#undef SUP_BPHY
418
419#define BWI_PHYTBL_WRSSI	0x1000
420#define BWI_PHYTBL_NOISE_SCALE	0x1400
421#define BWI_PHYTBL_NOISE	0x1800
422#define BWI_PHYTBL_ROTOR	0x2000
423#define BWI_PHYTBL_DELAY	0x2400
424#define BWI_PHYTBL_RSSI		0x4000
425#define BWI_PHYTBL_SIGMA_SQ	0x5000
426#define BWI_PHYTBL_WRSSI_REV1	0x5400
427#define BWI_PHYTBL_FREQ		0x5800
428
429static const uint16_t	bwi_phy_freq_11g_rev1[] =
430	{ BWI_PHY_FREQ_11G_REV1 };
431static const uint16_t	bwi_phy_noise_11g_rev1[] =
432	{ BWI_PHY_NOISE_11G_REV1 };
433static const uint16_t	bwi_phy_noise_11g[] =
434	{ BWI_PHY_NOISE_11G };
435static const uint32_t	bwi_phy_rotor_11g_rev1[] =
436	{ BWI_PHY_ROTOR_11G_REV1 };
437static const uint16_t	bwi_phy_noise_scale_11g_rev2[] =
438	{ BWI_PHY_NOISE_SCALE_11G_REV2 };
439static const uint16_t	bwi_phy_noise_scale_11g_rev7[] =
440	{ BWI_PHY_NOISE_SCALE_11G_REV7 };
441static const uint16_t	bwi_phy_noise_scale_11g[] =
442	{ BWI_PHY_NOISE_SCALE_11G };
443static const uint16_t	bwi_phy_sigma_sq_11g_rev2[] =
444	{ BWI_PHY_SIGMA_SQ_11G_REV2 };
445static const uint16_t	bwi_phy_sigma_sq_11g_rev7[] =
446	{ BWI_PHY_SIGMA_SQ_11G_REV7 };
447static const uint32_t	bwi_phy_delay_11g_rev1[] =
448	{ BWI_PHY_DELAY_11G_REV1 };
449
450/* RF */
451#define RF_LO_WRITE(mac, lo)	bwi_rf_lo_write((mac), (lo))
452
453#define BWI_RF_2GHZ_CHAN(chan) \
454	(ieee80211_ieee2mhz((chan), IEEE80211_CHAN_2GHZ) - 2400)
455
456#define BWI_DEFAULT_IDLE_TSSI	52
457
458struct rf_saveregs {
459	uint16_t	phy_01;
460	uint16_t	phy_03;
461	uint16_t	phy_0a;
462	uint16_t	phy_15;
463	uint16_t	phy_2a;
464	uint16_t	phy_30;
465	uint16_t	phy_35;
466	uint16_t	phy_60;
467	uint16_t	phy_429;
468	uint16_t	phy_802;
469	uint16_t	phy_811;
470	uint16_t	phy_812;
471	uint16_t	phy_814;
472	uint16_t	phy_815;
473
474	uint16_t	rf_43;
475	uint16_t	rf_52;
476	uint16_t	rf_7a;
477};
478
479#define SAVE_RF_REG(mac, regs, n)	(regs)->rf_##n = RF_READ((mac), 0x##n)
480#define RESTORE_RF_REG(mac, regs, n)	RF_WRITE((mac), 0x##n, (regs)->rf_##n)
481
482#define SAVE_PHY_REG(mac, regs, n)	(regs)->phy_##n = PHY_READ((mac), 0x##n)
483#define RESTORE_PHY_REG(mac, regs, n)	PHY_WRITE((mac), 0x##n, (regs)->phy_##n)
484
485static const int8_t	bwi_txpower_map_11b[BWI_TSSI_MAX] =
486	{ BWI_TXPOWER_MAP_11B };
487static const int8_t	bwi_txpower_map_11g[BWI_TSSI_MAX] =
488	{ BWI_TXPOWER_MAP_11G };
489
490/* INTERFACE */
491
492struct bwi_myaddr_bssid {
493	uint8_t		myaddr[IEEE80211_ADDR_LEN];
494	uint8_t		bssid[IEEE80211_ADDR_LEN];
495} __packed;
496
497/* [TRC: XXX What are these about?] */
498
499#define IEEE80211_DS_PLCP_SERVICE_LOCKED	0x04
500#define IEEE80211_DS_PLCL_SERVICE_PBCC		0x08
501#define IEEE80211_DS_PLCP_SERVICE_LENEXT5	0x20
502#define IEEE80211_DS_PLCP_SERVICE_LENEXT6	0x40
503#define IEEE80211_DS_PLCP_SERVICE_LENEXT7	0x80
504
505static const struct {
506	uint16_t	did_min;
507	uint16_t	did_max;
508	uint16_t	bbp_id;
509} bwi_bbpid_map[] = {
510	{ 0x4301, 0x4301, 0x4301 },
511	{ 0x4305, 0x4307, 0x4307 },
512	{ 0x4403, 0x4403, 0x4402 },
513	{ 0x4610, 0x4615, 0x4610 },
514	{ 0x4710, 0x4715, 0x4710 },
515	{ 0x4720, 0x4725, 0x4309 }
516};
517
518static const struct {
519	uint16_t	bbp_id;
520	int		nregwin;
521} bwi_regwin_count[] = {
522	{ 0x4301, 5 },
523	{ 0x4306, 6 },
524	{ 0x4307, 5 },
525	{ 0x4310, 8 },
526	{ 0x4401, 3 },
527	{ 0x4402, 3 },
528	{ 0x4610, 9 },
529	{ 0x4704, 9 },
530	{ 0x4710, 9 },
531	{ 0x5365, 7 }
532};
533
534#define CLKSRC(src) 				\
535[BWI_CLKSRC_ ## src] = {			\
536	.freq_min = BWI_CLKSRC_ ##src## _FMIN,	\
537	.freq_max = BWI_CLKSRC_ ##src## _FMAX	\
538}
539
540static const struct {
541	uint	freq_min;
542	uint	freq_max;
543} bwi_clkfreq[BWI_CLKSRC_MAX] = {
544	CLKSRC(LP_OSC),
545	CLKSRC(CS_OSC),
546	CLKSRC(PCI)
547};
548
549#undef CLKSRC
550
551#define VENDOR_LED_ACT(vendor)				\
552{							\
553	.vid = PCI_VENDOR_##vendor,			\
554	.led_act = { BWI_VENDOR_LED_ACT_##vendor }	\
555}
556
557static const struct {
558	uint16_t	vid;
559	uint8_t		led_act[BWI_LED_MAX];
560} bwi_vendor_led_act[] = {
561	VENDOR_LED_ACT(COMPAQ),
562	VENDOR_LED_ACT(LINKSYS)
563};
564
565static const uint8_t bwi_default_led_act[BWI_LED_MAX] =
566	{ BWI_VENDOR_LED_ACT_DEFAULT };
567
568#undef VENDOR_LED_ACT
569
570static const struct {
571	int	on_dur;
572	int	off_dur;
573} bwi_led_duration[109] = {
574	[0]	= { 400, 100 },
575	[2]	= { 150, 75 },
576	[4]	= { 90, 45 },
577	[11]	= { 66, 34 },
578	[12]	= { 53, 26 },
579	[18]	= { 42, 21 },
580	[22]	= { 35, 17 },
581	[24]	= { 32, 16 },
582	[36]	= { 21, 10 },
583	[48]	= { 16, 8 },
584	[72]	= { 11, 5 },
585	[96]	= { 9, 4 },
586	[108]	= { 7, 3 }
587};
588
589/* [TRC: XXX Should this be zeroed?] */
590
591static const uint8_t bwi_zero_addr[IEEE80211_ADDR_LEN];
592
593/* [TRC: Derived from DragonFly's src/sys/netproto/802_11/_ieee80211.h */
594
595enum bwi_ieee80211_modtype {
596	IEEE80211_MODTYPE_DS	= 0,	/* DS/CCK modulation */
597	IEEE80211_MODTYPE_PBCC	= 1,	/* PBCC modulation */
598	IEEE80211_MODTYPE_OFDM	= 2	/* OFDM modulation */
599};
600#define IEEE80211_MODTYPE_CCK   IEEE80211_MODTYPE_DS
601
602/*
603 * Setup sysctl(3) MIB, hw.bwi.* and hw.bwiN.*
604 */
605
606#ifdef BWI_DEBUG
607SYSCTL_SETUP(sysctl_bwi, "sysctl bwi(4) subtree setup")
608{
609	int rc;
610	const struct sysctlnode *rnode;
611	const struct sysctlnode *cnode;
612
613	if ((rc = sysctl_createv(clog, 0, NULL, &rnode,
614	    CTLFLAG_PERMANENT, CTLTYPE_NODE, "bwi",
615	    SYSCTL_DESCR("bwi global controls"),
616	    NULL, 0, NULL, 0, CTL_HW, CTL_CREATE, CTL_EOL)) != 0)
617		goto err;
618
619	if ((rc = sysctl_createv(clog, 0, &rnode, &cnode,
620	    CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT,
621	    "debug", SYSCTL_DESCR("default debug flags"),
622	    NULL, 0, &bwi_debug, 0, CTL_CREATE, CTL_EOL)) != 0)
623		goto err;
624
625	return;
626
627err:
628	aprint_error("%s: sysctl_createv failed (rc = %d)\n", __func__, rc);
629}
630#endif	/* BWI_DEBUG */
631
632static void
633bwi_sysctlattach(struct bwi_softc *sc)
634{
635	int rc;
636	const struct sysctlnode *rnode;
637	const struct sysctlnode *cnode;
638
639	struct sysctllog **clog = &sc->sc_sysctllog;
640
641	if ((rc = sysctl_createv(clog, 0, NULL, &rnode,
642	    CTLFLAG_PERMANENT, CTLTYPE_NODE, device_xname(sc->sc_dev),
643	    SYSCTL_DESCR("bwi controls and statistics"),
644	    NULL, 0, NULL, 0, CTL_HW, CTL_CREATE, CTL_EOL)) != 0)
645		goto err;
646
647	if ((rc = sysctl_createv(clog, 0, &rnode, &cnode,
648	    CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT,
649	    "fw_version", SYSCTL_DESCR("firmware version"),
650	    NULL, 0, &sc->sc_fw_version, 0, CTL_CREATE, CTL_EOL)) != 0)
651		goto err;
652
653	if ((rc = sysctl_createv(clog, 0, &rnode, &cnode,
654	    CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT,
655	    "dwell_time", SYSCTL_DESCR("channel dwell time during scan (msec)"),
656	    NULL, 0, &sc->sc_dwell_time, 0, CTL_CREATE, CTL_EOL)) != 0)
657		goto err;
658
659	if ((rc = sysctl_createv(clog, 0, &rnode, &cnode,
660	    CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT,
661	    "led_idle", SYSCTL_DESCR("# ticks before LED enters idle state"),
662	    NULL, 0, &sc->sc_led_idle, 0, CTL_CREATE, CTL_EOL)) != 0)
663		goto err;
664
665	if ((rc = sysctl_createv(clog, 0, &rnode, &cnode,
666	    CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT,
667	    "led_blink", SYSCTL_DESCR("allow LED to blink"),
668	    NULL, 0, &sc->sc_led_blink, 0, CTL_CREATE, CTL_EOL)) != 0)
669		goto err;
670
671	if ((rc = sysctl_createv(clog, 0, &rnode, &cnode,
672	    CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT,
673	    "txpwr_calib", SYSCTL_DESCR("enable software TX power calibration"),
674	    NULL, 0, &sc->sc_txpwr_calib, 0, CTL_CREATE, CTL_EOL)) != 0)
675		goto err;
676
677#ifdef BWI_DEBUG
678	if ((rc = sysctl_createv(clog, 0, &rnode, &cnode,
679	    CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT,
680	    "debug", SYSCTL_DESCR("debug flags"),
681	    NULL, 0, &sc->sc_debug, 0, CTL_CREATE, CTL_EOL)) != 0)
682		goto err;
683#endif
684
685	return;
686
687err:
688	aprint_error("%s: sysctl_createv failed (rc = %d)\n", __func__, rc);
689}
690
691/* CODE */
692
693int
694bwi_intr(void *arg)
695{
696	struct bwi_softc *sc = arg;
697	struct ifnet *ifp = &sc->sc_if;
698
699	if (!device_is_active(sc->sc_dev) ||
700	    (ifp->if_flags & IFF_RUNNING) == 0)
701		return (0);
702
703	/* Disable all interrupts */
704	bwi_disable_intrs(sc, BWI_ALL_INTRS);
705
706	softint_schedule(sc->sc_soft_ih);
707	return (1);
708}
709
710static void
711bwi_softintr(void *arg)
712{
713	struct bwi_softc *sc = arg;
714	struct bwi_mac *mac;
715	struct ifnet *ifp = &sc->sc_if;
716	uint32_t intr_status;
717	uint32_t txrx_intr_status[BWI_TXRX_NRING];
718	int i, s, txrx_error, tx = 0, rx_data = -1;
719
720	if (!device_is_active(sc->sc_dev) ||
721	    (ifp->if_flags & IFF_RUNNING) == 0)
722		return;
723
724	for (;;) {
725		/*
726		 * Get interrupt status
727		 */
728		intr_status = CSR_READ_4(sc, BWI_MAC_INTR_STATUS);
729		if (intr_status == 0xffffffff)	/* Not for us */
730			goto out;
731
732		intr_status &= CSR_READ_4(sc, BWI_MAC_INTR_MASK);
733		if (intr_status == 0)		/* Nothing is interesting */
734			goto out;
735
736		DPRINTF(sc, BWI_DBG_INTR, "intr status 0x%08x\n", intr_status);
737
738		KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC);
739		mac = (struct bwi_mac *)sc->sc_cur_regwin;
740
741		txrx_error = 0;
742
743		for (i = 0; i < BWI_TXRX_NRING; ++i) {
744			uint32_t mask;
745
746			if (BWI_TXRX_IS_RX(i))
747				mask = BWI_TXRX_RX_INTRS;
748			else
749				mask = BWI_TXRX_TX_INTRS;
750
751			txrx_intr_status[i] =
752			    CSR_READ_4(sc, BWI_TXRX_INTR_STATUS(i)) & mask;
753
754			if (txrx_intr_status[i] & BWI_TXRX_INTR_ERROR) {
755				aprint_error_dev(sc->sc_dev,
756				    "intr fatal TX/RX (%d) error 0x%08x\n",
757				    i, txrx_intr_status[i]);
758				txrx_error = 1;
759			}
760		}
761
762		/*
763		 * Acknowledge interrupt
764		 */
765		CSR_WRITE_4(sc, BWI_MAC_INTR_STATUS, intr_status);
766
767		for (i = 0; i < BWI_TXRX_NRING; ++i)
768			CSR_WRITE_4(sc, BWI_TXRX_INTR_STATUS(i),
769			    txrx_intr_status[i]);
770
771		if (intr_status & BWI_INTR_PHY_TXERR) {
772			if (mac->mac_flags & BWI_MAC_F_PHYE_RESET) {
773				aprint_error_dev(sc->sc_dev,
774				    "intr PHY TX error\n");
775				/* XXX to netisr0? */
776				s = splnet();
777				bwi_init_statechg(sc, 0);
778				splx(s);
779				goto out;
780			}
781		}
782
783		if (txrx_error) {
784			/* TODO: reset device */
785		}
786
787		if (intr_status & BWI_INTR_TBTT)
788			bwi_mac_config_ps(mac);
789
790		if (intr_status & BWI_INTR_EO_ATIM)
791			aprint_normal_dev(sc->sc_dev, "EO_ATIM\n");
792
793		if (intr_status & BWI_INTR_PMQ) {
794			for (;;) {
795				if ((CSR_READ_4(sc, BWI_MAC_PS_STATUS) & 0x8)
796				    == 0)
797					break;
798			}
799			CSR_WRITE_2(sc, BWI_MAC_PS_STATUS, 0x2);
800		}
801
802		if (intr_status & BWI_INTR_NOISE)
803			aprint_normal_dev(sc->sc_dev, "intr noise\n");
804
805		if (txrx_intr_status[0] & BWI_TXRX_INTR_RX)
806			rx_data = (sc->sc_rxeof)(sc);
807
808		if (txrx_intr_status[3] & BWI_TXRX_INTR_RX) {
809			(sc->sc_txeof_status)(sc);
810			tx = 1;
811		}
812
813		if (intr_status & BWI_INTR_TX_DONE) {
814			bwi_txeof(sc);
815			tx = 1;
816		}
817
818		if (sc->sc_blink_led != NULL && sc->sc_led_blink) {
819			int evt = BWI_LED_EVENT_NONE;
820
821			if (tx && rx_data > 0) {
822				if (sc->sc_rx_rate > sc->sc_tx_rate)
823					evt = BWI_LED_EVENT_RX;
824				else
825					evt = BWI_LED_EVENT_TX;
826			} else if (tx) {
827				evt = BWI_LED_EVENT_TX;
828			} else if (rx_data > 0) {
829				evt = BWI_LED_EVENT_RX;
830			} else if (rx_data == 0) {
831				evt = BWI_LED_EVENT_POLL;
832			}
833
834			if (evt != BWI_LED_EVENT_NONE)
835				bwi_led_event(sc, evt);
836		}
837	}
838
839out:
840	/* Re-enable interrupts */
841	bwi_enable_intrs(sc, BWI_INIT_INTRS);
842}
843
844int
845bwi_attach(struct bwi_softc *sc)
846{
847	struct ieee80211com *ic = &sc->sc_ic;
848	struct ifnet *ifp = &sc->sc_if;
849	struct bwi_mac *mac;
850	struct bwi_phy *phy;
851	int s, i, error;
852
853	/* [TRC: XXX Is this necessary?] */
854	s = splnet();
855
856	sc->sc_soft_ih = softint_establish(SOFTINT_NET, bwi_softintr, sc);
857	if (sc->sc_soft_ih == NULL) {
858		error = ENXIO;
859		goto fail;
860	}
861
862	/*
863	 * Initialize sysctl variables
864	 */
865	sc->sc_fw_version = BWI_FW_VERSION3;
866	sc->sc_dwell_time = 200;
867	sc->sc_led_idle = (2350 * hz) / 1000;
868	sc->sc_led_blink = 1;
869	sc->sc_txpwr_calib = 1;
870#ifdef BWI_DEBUG
871	sc->sc_debug = bwi_debug;
872#endif
873
874	DPRINTF(sc, BWI_DBG_ATTACH, "%s\n", __func__);
875
876	/* [TRC: XXX amrr] */
877	/* AMRR rate control */
878	sc->sc_amrr.amrr_min_success_threshold = 1;
879	sc->sc_amrr.amrr_max_success_threshold = 15;
880	callout_init(&sc->sc_amrr_ch, 0);
881	callout_setfunc(&sc->sc_amrr_ch, bwi_amrr_timeout, sc);
882
883	callout_init(&sc->sc_scan_ch, 0);
884	callout_setfunc(&sc->sc_scan_ch, bwi_next_scan, sc);
885	callout_init(&sc->sc_calib_ch, 0);
886	callout_setfunc(&sc->sc_calib_ch, bwi_calibrate, sc);
887
888	bwi_sysctlattach(sc);
889
890	bwi_power_on(sc, 1);
891
892	error = bwi_bbp_attach(sc);
893	if (error)
894		goto fail;
895
896	error = bwi_bbp_power_on(sc, BWI_CLOCK_MODE_FAST);
897	if (error)
898		goto fail;
899
900	if (BWI_REGWIN_EXIST(&sc->sc_com_regwin)) {
901		error = bwi_set_clock_delay(sc);
902		if (error)
903			goto fail;
904
905		error = bwi_set_clock_mode(sc, BWI_CLOCK_MODE_FAST);
906		if (error)
907			goto fail;
908
909		error = bwi_get_pwron_delay(sc);
910		if (error)
911			goto fail;
912	}
913
914	error = bwi_bus_attach(sc);
915	if (error)
916		goto fail;
917
918	bwi_get_card_flags(sc);
919
920	bwi_led_attach(sc);
921
922	for (i = 0; i < sc->sc_nmac; ++i) {
923		struct bwi_regwin *old;
924
925		mac = &sc->sc_mac[i];
926		error = bwi_regwin_switch(sc, &mac->mac_regwin, &old);
927		if (error)
928			goto fail;
929
930		error = bwi_mac_lateattach(mac);
931		if (error)
932			goto fail;
933
934		error = bwi_regwin_switch(sc, old, NULL);
935		if (error)
936			goto fail;
937	}
938
939	/*
940	 * XXX First MAC is known to exist
941	 * TODO2
942	 */
943	mac = &sc->sc_mac[0];
944	phy = &mac->mac_phy;
945
946	bwi_bbp_power_off(sc);
947
948	error = bwi_dma_alloc(sc);
949	if (error)
950		goto fail;
951
952	/* setup interface */
953	ifp->if_softc = sc;
954	ifp->if_init = bwi_init;
955	ifp->if_ioctl = bwi_ioctl;
956	ifp->if_start = bwi_start;
957	ifp->if_watchdog = bwi_watchdog;
958	ifp->if_stop = bwi_stop;
959	ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST;
960	memcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ);
961	IFQ_SET_READY(&ifp->if_snd);
962
963	/* Get locale */
964	sc->sc_locale = __SHIFTOUT(bwi_read_sprom(sc, BWI_SPROM_CARD_INFO),
965	    BWI_SPROM_CARD_INFO_LOCALE);
966	DPRINTF(sc, BWI_DBG_ATTACH, "locale: %d\n", sc->sc_locale);
967
968	/*
969	 * Setup ratesets, phytype, channels and get MAC address
970	 */
971	if (phy->phy_mode == IEEE80211_MODE_11B ||
972	    phy->phy_mode == IEEE80211_MODE_11G) {
973		uint16_t chan_flags;
974
975		ic->ic_sup_rates[IEEE80211_MODE_11B] =
976		    ieee80211_std_rateset_11b;
977
978		if (phy->phy_mode == IEEE80211_MODE_11B) {
979			chan_flags = IEEE80211_CHAN_B;
980			ic->ic_phytype = IEEE80211_T_DS;
981		} else {
982			chan_flags = IEEE80211_CHAN_CCK |
983			    IEEE80211_CHAN_OFDM |
984			    IEEE80211_CHAN_DYN |
985			    IEEE80211_CHAN_2GHZ;
986			ic->ic_phytype = IEEE80211_T_OFDM;
987			ic->ic_sup_rates[IEEE80211_MODE_11G] =
988			    ieee80211_std_rateset_11g;
989		}
990
991		/* XXX depend on locale */
992		for (i = 1; i <= 14; ++i) {
993			ic->ic_channels[i].ic_freq =
994			    ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ);
995			ic->ic_channels[i].ic_flags = chan_flags;
996		}
997
998		bwi_get_eaddr(sc, BWI_SPROM_11BG_EADDR, ic->ic_myaddr);
999		if (IEEE80211_IS_MULTICAST(ic->ic_myaddr)) {
1000			bwi_get_eaddr(sc, BWI_SPROM_11A_EADDR, ic->ic_myaddr);
1001			if (IEEE80211_IS_MULTICAST(ic->ic_myaddr))
1002				aprint_error_dev(sc->sc_dev,
1003				    "invalid MAC address: %s\n",
1004				    ether_sprintf(ic->ic_myaddr));
1005		}
1006	} else if (phy->phy_mode == IEEE80211_MODE_11A) {
1007		/* TODO: 11A */
1008		error = ENXIO;
1009		goto fail;
1010	} else
1011		panic("unknown phymode %d\n", phy->phy_mode);
1012
1013	ic->ic_ifp = ifp;
1014	ic->ic_caps = IEEE80211_C_SHSLOT |
1015	    IEEE80211_C_SHPREAMBLE |
1016	    IEEE80211_C_IBSS |
1017	    IEEE80211_C_HOSTAP |
1018	    IEEE80211_C_MONITOR;
1019	ic->ic_state = IEEE80211_S_INIT;
1020	ic->ic_opmode = IEEE80211_M_STA;
1021
1022	ic->ic_updateslot = bwi_updateslot;
1023
1024	if_initialize(ifp);
1025	ieee80211_ifattach(ic);
1026	ifp->if_percpuq = if_percpuq_create(ifp);
1027	if_register(ifp);
1028
1029	/* [TRC: XXX Not supported on NetBSD?] */
1030	/* ic->ic_flags_ext |= IEEE80211_FEXT_SWBMISS; */
1031
1032	sc->sc_newstate = ic->ic_newstate;
1033	ic->ic_newstate = bwi_newstate;
1034	/* [TRC: XXX amrr] */
1035	ic->ic_newassoc = bwi_newassoc;
1036	ic->ic_node_alloc = bwi_node_alloc;
1037
1038	ieee80211_media_init(ic, bwi_media_change, ieee80211_media_status);
1039
1040	bpf_attach2(ifp, DLT_IEEE802_11_RADIO,
1041	    sizeof(struct ieee80211_frame) + IEEE80211_RADIOTAP_HDRLEN,
1042	    &sc->sc_drvbpf);
1043
1044	/* [TRC: XXX DragonFlyBSD rounds this up to a multiple of
1045	   sizeof(uint32_t).  Should we?] */
1046	sc->sc_rxtap_len = sizeof(sc->sc_rxtapu);
1047	sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len);
1048	sc->sc_rxtap.wr_ihdr.it_present = htole32(BWI_RX_RADIOTAP_PRESENT);
1049
1050	sc->sc_txtap_len = sizeof(sc->sc_txtapu);
1051	sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len);
1052	sc->sc_txtap.wt_ihdr.it_present = htole32(BWI_TX_RADIOTAP_PRESENT);
1053
1054	splx(s);
1055	ieee80211_announce(ic);
1056	return (0);
1057fail:
1058	/* [TRC: XXX DragonFlyBSD detaches the device here.  Should we?] */
1059	splx(s);
1060	return (error);
1061}
1062
1063void
1064bwi_detach(struct bwi_softc *sc)
1065{
1066	struct ifnet *ifp = &sc->sc_if;
1067	int i, s;
1068
1069	s = splnet();
1070
1071	bwi_stop(ifp, 1);
1072
1073	bpf_detach(ifp);
1074
1075	ieee80211_ifdetach(&sc->sc_ic);
1076	if_detach(ifp);
1077
1078	for (i = 0; i < sc->sc_nmac; ++i)
1079		bwi_mac_detach(&sc->sc_mac[i]);
1080
1081	sysctl_teardown(&sc->sc_sysctllog);
1082
1083	if (sc->sc_soft_ih != NULL)
1084		softint_disestablish(sc->sc_soft_ih);
1085
1086	splx(s);
1087
1088	bwi_dma_free(sc);
1089}
1090
1091/* MAC */
1092
1093static void
1094bwi_tmplt_write_4(struct bwi_mac *mac, uint32_t ofs, uint32_t val)
1095{
1096	struct bwi_softc *sc = mac->mac_sc;
1097
1098	if (mac->mac_flags & BWI_MAC_F_BSWAP)
1099		val = bswap32(val);
1100
1101	CSR_WRITE_4(sc, BWI_MAC_TMPLT_CTRL, ofs);
1102	CSR_WRITE_4(sc, BWI_MAC_TMPLT_DATA, val);
1103}
1104
1105static void
1106bwi_hostflags_write(struct bwi_mac *mac, uint64_t flags)
1107{
1108	uint64_t val;
1109
1110	val = flags & 0xffff;
1111	MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_HFLAGS_LO, val);
1112
1113	val = (flags >> 16) & 0xffff;
1114	MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_HFLAGS_MI, val);
1115
1116	/* HI has unclear meaning, so leave it as it is */
1117}
1118
1119static uint64_t
1120bwi_hostflags_read(struct bwi_mac *mac)
1121{
1122	uint64_t flags, val;
1123
1124	/* HI has unclear meaning, so don't touch it */
1125	flags = 0;
1126
1127	val = MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_HFLAGS_MI);
1128	flags |= val << 16;
1129
1130	val = MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_HFLAGS_LO);
1131	flags |= val;
1132
1133	return (flags);
1134}
1135
1136static uint16_t
1137bwi_memobj_read_2(struct bwi_mac *mac, uint16_t obj_id, uint16_t ofs0)
1138{
1139	struct bwi_softc *sc = mac->mac_sc;
1140	uint32_t data_reg;
1141	int ofs;
1142
1143	data_reg = BWI_MOBJ_DATA;
1144	ofs = ofs0 / 4;
1145
1146	if (ofs0 % 4 != 0)
1147		data_reg = BWI_MOBJ_DATA_UNALIGN;
1148
1149	CSR_WRITE_4(sc, BWI_MOBJ_CTRL, BWI_MOBJ_CTRL_VAL(obj_id, ofs));
1150	return (CSR_READ_2(sc, data_reg));
1151}
1152
1153static uint32_t
1154bwi_memobj_read_4(struct bwi_mac *mac, uint16_t obj_id, uint16_t ofs0)
1155{
1156	struct bwi_softc *sc = mac->mac_sc;
1157	int ofs;
1158
1159	ofs = ofs0 / 4;
1160	if (ofs0 % 4 != 0) {
1161		uint32_t ret;
1162
1163		CSR_WRITE_4(sc, BWI_MOBJ_CTRL, BWI_MOBJ_CTRL_VAL(obj_id, ofs));
1164		ret = CSR_READ_2(sc, BWI_MOBJ_DATA_UNALIGN);
1165		ret <<= 16;
1166
1167		CSR_WRITE_4(sc, BWI_MOBJ_CTRL,
1168		    BWI_MOBJ_CTRL_VAL(obj_id, ofs + 1));
1169		ret |= CSR_READ_2(sc, BWI_MOBJ_DATA);
1170
1171		return (ret);
1172	} else {
1173		CSR_WRITE_4(sc, BWI_MOBJ_CTRL, BWI_MOBJ_CTRL_VAL(obj_id, ofs));
1174		return (CSR_READ_4(sc, BWI_MOBJ_DATA));
1175	}
1176}
1177
1178static void
1179bwi_memobj_write_2(struct bwi_mac *mac, uint16_t obj_id, uint16_t ofs0,
1180    uint16_t v)
1181{
1182	struct bwi_softc *sc = mac->mac_sc;
1183	uint32_t data_reg;
1184	int ofs;
1185
1186	data_reg = BWI_MOBJ_DATA;
1187	ofs = ofs0 / 4;
1188
1189	if (ofs0 % 4 != 0)
1190		data_reg = BWI_MOBJ_DATA_UNALIGN;
1191
1192	CSR_WRITE_4(sc, BWI_MOBJ_CTRL, BWI_MOBJ_CTRL_VAL(obj_id, ofs));
1193	CSR_WRITE_2(sc, data_reg, v);
1194}
1195
1196static void
1197bwi_memobj_write_4(struct bwi_mac *mac, uint16_t obj_id, uint16_t ofs0,
1198    uint32_t v)
1199{
1200	struct bwi_softc *sc = mac->mac_sc;
1201	int ofs;
1202
1203	ofs = ofs0 / 4;
1204	if (ofs0 % 4 != 0) {
1205		CSR_WRITE_4(sc, BWI_MOBJ_CTRL, BWI_MOBJ_CTRL_VAL(obj_id, ofs));
1206		CSR_WRITE_2(sc, BWI_MOBJ_DATA_UNALIGN, v >> 16);
1207		CSR_WRITE_4(sc, BWI_MOBJ_CTRL,
1208		    BWI_MOBJ_CTRL_VAL(obj_id, ofs + 1));
1209		CSR_WRITE_2(sc, BWI_MOBJ_DATA, v & 0xffff);
1210	} else {
1211		CSR_WRITE_4(sc, BWI_MOBJ_CTRL, BWI_MOBJ_CTRL_VAL(obj_id, ofs));
1212		CSR_WRITE_4(sc, BWI_MOBJ_DATA, v);
1213	}
1214}
1215
1216static int
1217bwi_mac_lateattach(struct bwi_mac *mac)
1218{
1219	int error;
1220
1221	if (mac->mac_rev >= 5)
1222		CSR_READ_4(mac->mac_sc, BWI_STATE_HI); /* dummy read */
1223
1224	bwi_mac_reset(mac, 1);
1225
1226	error = bwi_phy_attach(mac);
1227	if (error)
1228		return (error);
1229
1230	error = bwi_rf_attach(mac);
1231	if (error)
1232		return (error);
1233
1234	/* Link 11B/G PHY, unlink 11A PHY */
1235	if (mac->mac_phy.phy_mode == IEEE80211_MODE_11A)
1236		bwi_mac_reset(mac, 0);
1237	else
1238		bwi_mac_reset(mac, 1);
1239
1240	error = bwi_mac_test(mac);
1241	if (error)
1242		return (error);
1243
1244	error = bwi_mac_get_property(mac);
1245	if (error)
1246		return (error);
1247
1248	error = bwi_rf_map_txpower(mac);
1249	if (error)
1250		return (error);
1251
1252	bwi_rf_off(mac);
1253	CSR_WRITE_2(mac->mac_sc, BWI_BBP_ATTEN, BWI_BBP_ATTEN_MAGIC);
1254	bwi_regwin_disable(mac->mac_sc, &mac->mac_regwin, 0);
1255
1256	return (0);
1257}
1258
1259static int
1260bwi_mac_init(struct bwi_mac *mac)
1261{
1262	struct bwi_softc *sc = mac->mac_sc;
1263	int error, i;
1264
1265	/* Clear MAC/PHY/RF states */
1266	bwi_mac_setup_tpctl(mac);
1267	bwi_rf_clear_state(&mac->mac_rf);
1268	bwi_phy_clear_state(&mac->mac_phy);
1269
1270	/* Enable MAC and linked it to PHY */
1271	if (!bwi_regwin_is_enabled(sc, &mac->mac_regwin))
1272		bwi_mac_reset(mac, 1);
1273
1274	/* Initialize backplane */
1275	error = bwi_bus_init(sc, mac);
1276	if (error)
1277		return (error);
1278
1279	/* XXX work around for hardware bugs? */
1280	if (sc->sc_bus_regwin.rw_rev <= 5 &&
1281	    sc->sc_bus_regwin.rw_type != BWI_REGWIN_T_BUSPCIE) {
1282		CSR_SETBITS_4(sc, BWI_CONF_LO,
1283		__SHIFTIN(BWI_CONF_LO_SERVTO, BWI_CONF_LO_SERVTO_MASK) |
1284		__SHIFTIN(BWI_CONF_LO_REQTO, BWI_CONF_LO_REQTO_MASK));
1285	}
1286
1287	/* Calibrate PHY */
1288	error = bwi_phy_calibrate(mac);
1289	if (error) {
1290		aprint_error_dev(sc->sc_dev, "PHY calibrate failed\n");
1291		return (error);
1292	}
1293
1294	/* Prepare to initialize firmware */
1295	CSR_WRITE_4(sc, BWI_MAC_STATUS,
1296	    BWI_MAC_STATUS_UCODE_JUMP0 |
1297	    BWI_MAC_STATUS_IHREN);
1298
1299	/*
1300	 * Load and initialize firmwares
1301	 */
1302	error = bwi_mac_fw_alloc(mac);
1303	if (error)
1304		return (error);
1305
1306	error = bwi_mac_fw_load(mac);
1307	if (error)
1308		return (error);
1309
1310	error = bwi_mac_gpio_init(mac);
1311	if (error)
1312		return (error);
1313
1314	error = bwi_mac_fw_init(mac);
1315	if (error)
1316		return (error);
1317
1318	/*
1319	 * Turn on RF
1320	 */
1321	bwi_rf_on(mac);
1322
1323	/* TODO: LED, hardware rf enabled is only related to LED setting */
1324
1325	/*
1326	 * Initialize PHY
1327	 */
1328	CSR_WRITE_2(sc, BWI_BBP_ATTEN, 0);
1329	bwi_phy_init(mac);
1330
1331	/* TODO: interference mitigation */
1332
1333	/*
1334	 * Setup antenna mode
1335	 */
1336	bwi_rf_set_ant_mode(mac, mac->mac_rf.rf_ant_mode);
1337
1338	/*
1339	 * Initialize operation mode (RX configuration)
1340	 */
1341	bwi_mac_opmode_init(mac);
1342
1343	/* XXX what's these */
1344	if (mac->mac_rev < 3) {
1345		CSR_WRITE_2(sc, 0x60e, 0);
1346		CSR_WRITE_2(sc, 0x610, 0x8000);
1347		CSR_WRITE_2(sc, 0x604, 0);
1348		CSR_WRITE_2(sc, 0x606, 0x200);
1349	} else {
1350		CSR_WRITE_4(sc, 0x188, 0x80000000);
1351		CSR_WRITE_4(sc, 0x18c, 0x2000000);
1352	}
1353
1354	/*
1355	 * Initialize TX/RX interrupts' mask
1356	 */
1357	CSR_WRITE_4(sc, BWI_MAC_INTR_STATUS, BWI_INTR_TIMER1);
1358	for (i = 0; i < BWI_TXRX_NRING; ++i) {
1359		uint32_t intrs;
1360
1361		if (BWI_TXRX_IS_RX(i))
1362			intrs = BWI_TXRX_RX_INTRS;
1363		else
1364			intrs = BWI_TXRX_TX_INTRS;
1365		CSR_WRITE_4(sc, BWI_TXRX_INTR_MASK(i), intrs);
1366	}
1367
1368	/* XXX what's this */
1369	CSR_SETBITS_4(sc, BWI_STATE_LO, 0x100000);
1370
1371	/* Setup MAC power up delay */
1372	CSR_WRITE_2(sc, BWI_MAC_POWERUP_DELAY, sc->sc_pwron_delay);
1373
1374	/* Set MAC regwin revision */
1375	MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_MACREV, mac->mac_rev);
1376
1377	/*
1378	 * Initialize host flags
1379	 */
1380	bwi_mac_hostflags_init(mac);
1381
1382	/*
1383	 * Initialize BSS parameters
1384	 */
1385	bwi_mac_bss_param_init(mac);
1386
1387	/*
1388	 * Initialize TX rings
1389	 */
1390	for (i = 0; i < BWI_TX_NRING; ++i) {
1391		error = (sc->sc_init_tx_ring)(sc, i);
1392		if (error) {
1393			aprint_error_dev(sc->sc_dev,
1394			    "can't initialize %dth TX ring\n", i);
1395			return (error);
1396		}
1397	}
1398
1399	/*
1400	 * Initialize RX ring
1401	 */
1402	error = (sc->sc_init_rx_ring)(sc);
1403	if (error) {
1404		aprint_error_dev(sc->sc_dev, "can't initialize RX ring\n");
1405		return (error);
1406	}
1407
1408	/*
1409	 * Initialize TX stats if the current MAC uses that
1410	 */
1411	if (mac->mac_flags & BWI_MAC_F_HAS_TXSTATS) {
1412		error = (sc->sc_init_txstats)(sc);
1413		if (error) {
1414			aprint_error_dev(sc->sc_dev,
1415			    "can't initialize TX stats ring\n");
1416			return (error);
1417		}
1418	}
1419
1420	/* XXX what's these */
1421	CSR_WRITE_2(sc, 0x612, 0x50);	/* Force Pre-TBTT to 80? */
1422	MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, 0x416, 0x50);
1423	MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, 0x414, 0x1f4);
1424
1425	mac->mac_flags |= BWI_MAC_F_INITED;
1426
1427	return (0);
1428}
1429
1430static void
1431bwi_mac_reset(struct bwi_mac *mac, int link_phy)
1432{
1433	struct bwi_softc *sc = mac->mac_sc;
1434	uint32_t flags, state_lo, status;
1435
1436	flags = BWI_STATE_LO_FLAG_PHYRST | BWI_STATE_LO_FLAG_PHYCLKEN;
1437	if (link_phy)
1438		flags |= BWI_STATE_LO_FLAG_PHYLNK;
1439	bwi_regwin_enable(sc, &mac->mac_regwin, flags);
1440	DELAY(2000);
1441
1442	state_lo = CSR_READ_4(sc, BWI_STATE_LO);
1443	state_lo |= BWI_STATE_LO_GATED_CLOCK;
1444	state_lo &= ~__SHIFTIN(BWI_STATE_LO_FLAG_PHYRST,
1445			       BWI_STATE_LO_FLAGS_MASK);
1446	CSR_WRITE_4(sc, BWI_STATE_LO, state_lo);
1447	/* Flush pending bus write */
1448	CSR_READ_4(sc, BWI_STATE_LO);
1449	DELAY(1000);
1450
1451	state_lo &= ~BWI_STATE_LO_GATED_CLOCK;
1452	CSR_WRITE_4(sc, BWI_STATE_LO, state_lo);
1453	/* Flush pending bus write */
1454	CSR_READ_4(sc, BWI_STATE_LO);
1455	DELAY(1000);
1456
1457	CSR_WRITE_2(sc, BWI_BBP_ATTEN, 0);
1458
1459	status = CSR_READ_4(sc, BWI_MAC_STATUS);
1460	status |= BWI_MAC_STATUS_IHREN;
1461	if (link_phy)
1462		status |= BWI_MAC_STATUS_PHYLNK;
1463	else
1464		status &= ~BWI_MAC_STATUS_PHYLNK;
1465	CSR_WRITE_4(sc, BWI_MAC_STATUS, status);
1466
1467	if (link_phy) {
1468		DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_ATTACH | BWI_DBG_INIT,
1469		    "%s\n", "PHY is linked");
1470		mac->mac_phy.phy_flags |= BWI_PHY_F_LINKED;
1471	} else {
1472		DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_ATTACH | BWI_DBG_INIT,
1473		    "%s\n", "PHY is unlinked");
1474		mac->mac_phy.phy_flags &= ~BWI_PHY_F_LINKED;
1475	}
1476}
1477
1478static void
1479bwi_mac_set_tpctl_11bg(struct bwi_mac *mac, const struct bwi_tpctl *new_tpctl)
1480{
1481	struct bwi_rf *rf = &mac->mac_rf;
1482	struct bwi_tpctl *tpctl = &mac->mac_tpctl;
1483
1484	if (new_tpctl != NULL) {
1485		KASSERT(new_tpctl->bbp_atten <= BWI_BBP_ATTEN_MAX);
1486		KASSERT(new_tpctl->rf_atten <=
1487		    (rf->rf_rev < 6 ? BWI_RF_ATTEN_MAX0
1488		    : BWI_RF_ATTEN_MAX1));
1489		KASSERT(new_tpctl->tp_ctrl1 <= BWI_TPCTL1_MAX);
1490
1491		tpctl->bbp_atten = new_tpctl->bbp_atten;
1492		tpctl->rf_atten = new_tpctl->rf_atten;
1493		tpctl->tp_ctrl1 = new_tpctl->tp_ctrl1;
1494	}
1495
1496	/* Set BBP attenuation */
1497	bwi_phy_set_bbp_atten(mac, tpctl->bbp_atten);
1498
1499	/* Set RF attenuation */
1500	RF_WRITE(mac, BWI_RFR_ATTEN, tpctl->rf_atten);
1501	MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_RF_ATTEN,
1502	    tpctl->rf_atten);
1503
1504	/* Set TX power */
1505	if (rf->rf_type == BWI_RF_T_BCM2050) {
1506		RF_FILT_SETBITS(mac, BWI_RFR_TXPWR, ~BWI_RFR_TXPWR1_MASK,
1507		    __SHIFTIN(tpctl->tp_ctrl1, BWI_RFR_TXPWR1_MASK));
1508	}
1509
1510	/* Adjust RF Local Oscillator */
1511	if (mac->mac_phy.phy_mode == IEEE80211_MODE_11G)
1512		bwi_rf_lo_adjust(mac, tpctl);
1513}
1514
1515static int
1516bwi_mac_test(struct bwi_mac *mac)
1517{
1518	struct bwi_softc *sc = mac->mac_sc;
1519	uint32_t orig_val, val;
1520
1521#define TEST_VAL1	0xaa5555aa
1522#define TEST_VAL2	0x55aaaa55
1523	/* Save it for later restoring */
1524	orig_val = MOBJ_READ_4(mac, BWI_COMM_MOBJ, 0);
1525
1526	/* Test 1 */
1527	MOBJ_WRITE_4(mac, BWI_COMM_MOBJ, 0, TEST_VAL1);
1528	val = MOBJ_READ_4(mac, BWI_COMM_MOBJ, 0);
1529	if (val != TEST_VAL1) {
1530		aprint_error_dev(sc->sc_dev, "TEST1 failed\n");
1531		return (ENXIO);
1532	}
1533
1534	/* Test 2 */
1535	MOBJ_WRITE_4(mac, BWI_COMM_MOBJ, 0, TEST_VAL2);
1536	val = MOBJ_READ_4(mac, BWI_COMM_MOBJ, 0);
1537	if (val != TEST_VAL2) {
1538		aprint_error_dev(sc->sc_dev, "TEST2 failed\n");
1539		return (ENXIO);
1540	}
1541
1542	/* Restore to the original value */
1543	MOBJ_WRITE_4(mac, BWI_COMM_MOBJ, 0, orig_val);
1544
1545	val = CSR_READ_4(sc, BWI_MAC_STATUS);
1546	if ((val & ~BWI_MAC_STATUS_PHYLNK) != BWI_MAC_STATUS_IHREN) {
1547		aprint_error_dev(sc->sc_dev, "%s failed, MAC status 0x%08x\n",
1548		    __func__, val);
1549		return (ENXIO);
1550	}
1551
1552	val = CSR_READ_4(sc, BWI_MAC_INTR_STATUS);
1553	if (val != 0) {
1554		aprint_error_dev(sc->sc_dev, "%s failed, intr status %08x\n",
1555		    __func__, val);
1556		return (ENXIO);
1557	}
1558#undef TEST_VAL2
1559#undef TEST_VAL1
1560
1561	return (0);
1562}
1563
1564static void
1565bwi_mac_setup_tpctl(struct bwi_mac *mac)
1566{
1567	struct bwi_softc *sc = mac->mac_sc;
1568	struct bwi_rf *rf = &mac->mac_rf;
1569	struct bwi_phy *phy = &mac->mac_phy;
1570	struct bwi_tpctl *tpctl = &mac->mac_tpctl;
1571
1572	/* Calc BBP attenuation */
1573	if (rf->rf_type == BWI_RF_T_BCM2050 && rf->rf_rev < 6)
1574		tpctl->bbp_atten = 0;
1575	else
1576		tpctl->bbp_atten = 2;
1577
1578	/* Calc TX power CTRL1?? */
1579	tpctl->tp_ctrl1 = 0;
1580	if (rf->rf_type == BWI_RF_T_BCM2050) {
1581		if (rf->rf_rev == 1)
1582			tpctl->tp_ctrl1 = 3;
1583		else if (rf->rf_rev < 6)
1584			tpctl->tp_ctrl1 = 2;
1585		else if (rf->rf_rev == 8)
1586			tpctl->tp_ctrl1 = 1;
1587	}
1588
1589	/* Empty TX power CTRL2?? */
1590	tpctl->tp_ctrl2 = 0xffff;
1591
1592	/*
1593	 * Calc RF attenuation
1594	 */
1595	if (phy->phy_mode == IEEE80211_MODE_11A) {
1596		tpctl->rf_atten = 0x60;
1597		goto back;
1598	}
1599
1600	if (BWI_IS_BRCM_BCM4309G(sc) && sc->sc_pci_revid < 0x51) {
1601		tpctl->rf_atten = sc->sc_pci_revid < 0x43 ? 2 : 3;
1602		goto back;
1603	}
1604
1605	tpctl->rf_atten = 5;
1606
1607	if (rf->rf_type != BWI_RF_T_BCM2050) {
1608		if (rf->rf_type == BWI_RF_T_BCM2053 && rf->rf_rev == 1)
1609			tpctl->rf_atten = 6;
1610		goto back;
1611	}
1612
1613	/*
1614	 * NB: If we reaches here and the card is BRCM_BCM4309G,
1615	 *     then the card's PCI revision must >= 0x51
1616	 */
1617
1618	/* BCM2050 RF */
1619	switch (rf->rf_rev) {
1620	case 1:
1621		if (phy->phy_mode == IEEE80211_MODE_11G) {
1622			if (BWI_IS_BRCM_BCM4309G(sc) || BWI_IS_BRCM_BU4306(sc))
1623				tpctl->rf_atten = 3;
1624			else
1625				tpctl->rf_atten = 1;
1626		} else {
1627			if (BWI_IS_BRCM_BCM4309G(sc))
1628				tpctl->rf_atten = 7;
1629			else
1630				tpctl->rf_atten = 6;
1631		}
1632		break;
1633	case 2:
1634		if (phy->phy_mode == IEEE80211_MODE_11G) {
1635			/*
1636			 * NOTE: Order of following conditions is critical
1637			 */
1638			if (BWI_IS_BRCM_BCM4309G(sc))
1639				tpctl->rf_atten = 3;
1640			else if (BWI_IS_BRCM_BU4306(sc))
1641				tpctl->rf_atten = 5;
1642			else if (sc->sc_bbp_id == BWI_BBPID_BCM4320)
1643				tpctl->rf_atten = 4;
1644			else
1645				tpctl->rf_atten = 3;
1646		} else {
1647			tpctl->rf_atten = 6;
1648		}
1649		break;
1650	case 4:
1651	case 5:
1652		tpctl->rf_atten = 1;
1653		break;
1654	case 8:
1655		tpctl->rf_atten = 0x1a;
1656		break;
1657	}
1658back:
1659	DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_INIT | BWI_DBG_TXPOWER,
1660	    "bbp atten: %u, rf atten: %u, ctrl1: %u, ctrl2: %u\n",
1661	    tpctl->bbp_atten, tpctl->rf_atten,
1662	    tpctl->tp_ctrl1, tpctl->tp_ctrl2);
1663}
1664
1665static void
1666bwi_mac_dummy_xmit(struct bwi_mac *mac)
1667{
1668#define PACKET_LEN	5
1669	static const uint32_t	packet_11a[PACKET_LEN] =
1670	    { 0x000201cc, 0x00d40000, 0x00000000, 0x01000000, 0x00000000 };
1671	static const uint32_t	packet_11bg[PACKET_LEN] =
1672	    { 0x000b846e, 0x00d40000, 0x00000000, 0x01000000, 0x00000000 };
1673
1674	struct bwi_softc *sc = mac->mac_sc;
1675	struct bwi_rf *rf = &mac->mac_rf;
1676	const uint32_t *packet;
1677	uint16_t val_50c;
1678	int wait_max, i;
1679
1680	if (mac->mac_phy.phy_mode == IEEE80211_MODE_11A) {
1681		wait_max = 30;
1682		packet = packet_11a;
1683		val_50c = 1;
1684	} else {
1685		wait_max = 250;
1686		packet = packet_11bg;
1687		val_50c = 0;
1688	}
1689
1690	for (i = 0; i < PACKET_LEN; ++i)
1691		TMPLT_WRITE_4(mac, i * 4, packet[i]);
1692
1693	CSR_READ_4(sc, BWI_MAC_STATUS);	/* dummy read */
1694
1695	CSR_WRITE_2(sc, 0x568, 0);
1696	CSR_WRITE_2(sc, 0x7c0, 0);
1697	CSR_WRITE_2(sc, 0x50c, val_50c);
1698	CSR_WRITE_2(sc, 0x508, 0);
1699	CSR_WRITE_2(sc, 0x50a, 0);
1700	CSR_WRITE_2(sc, 0x54c, 0);
1701	CSR_WRITE_2(sc, 0x56a, 0x14);
1702	CSR_WRITE_2(sc, 0x568, 0x826);
1703	CSR_WRITE_2(sc, 0x500, 0);
1704	CSR_WRITE_2(sc, 0x502, 0x30);
1705
1706	if (rf->rf_type == BWI_RF_T_BCM2050 && rf->rf_rev <= 5)
1707		RF_WRITE(mac, 0x51, 0x17);
1708
1709	for (i = 0; i < wait_max; ++i) {
1710		if (CSR_READ_2(sc, 0x50e) & 0x80)
1711			break;
1712		DELAY(10);
1713	}
1714	for (i = 0; i < 10; ++i) {
1715		if (CSR_READ_2(sc, 0x50e) & 0x400)
1716			break;
1717		DELAY(10);
1718	}
1719	for (i = 0; i < 10; ++i) {
1720		if ((CSR_READ_2(sc, 0x690) & 0x100) == 0)
1721			break;
1722		DELAY(10);
1723	}
1724
1725	if (rf->rf_type == BWI_RF_T_BCM2050 && rf->rf_rev <= 5)
1726		RF_WRITE(mac, 0x51, 0x37);
1727#undef PACKET_LEN
1728}
1729
1730static void
1731bwi_mac_init_tpctl_11bg(struct bwi_mac *mac)
1732{
1733	struct bwi_softc *sc = mac->mac_sc;
1734	struct bwi_phy *phy = &mac->mac_phy;
1735	struct bwi_rf *rf = &mac->mac_rf;
1736	struct bwi_tpctl tpctl_orig;
1737	int restore_tpctl = 0;
1738
1739	KASSERT(phy->phy_mode != IEEE80211_MODE_11A);
1740
1741	if (BWI_IS_BRCM_BU4306(sc))
1742		return;
1743
1744	PHY_WRITE(mac, 0x28, 0x8018);
1745	CSR_CLRBITS_2(sc, BWI_BBP_ATTEN, 0x20);
1746
1747	if (phy->phy_mode == IEEE80211_MODE_11G) {
1748		if ((phy->phy_flags & BWI_PHY_F_LINKED) == 0)
1749			return;
1750		PHY_WRITE(mac, 0x47a, 0xc111);
1751	}
1752	if (mac->mac_flags & BWI_MAC_F_TPCTL_INITED)
1753		return;
1754
1755	if (phy->phy_mode == IEEE80211_MODE_11B && phy->phy_rev >= 2 &&
1756	    rf->rf_type == BWI_RF_T_BCM2050) {
1757		RF_SETBITS(mac, 0x76, 0x84);
1758	} else {
1759		struct bwi_tpctl tpctl;
1760
1761		/* Backup original TX power control variables */
1762		memcpy(&tpctl_orig, &mac->mac_tpctl, sizeof(tpctl_orig));
1763		restore_tpctl = 1;
1764
1765		memcpy(&tpctl, &mac->mac_tpctl, sizeof(tpctl));
1766		tpctl.bbp_atten = 11;
1767		tpctl.tp_ctrl1 = 0;
1768#ifdef notyet
1769		if (rf->rf_rev >= 6 && rf->rf_rev <= 8)
1770			tpctl.rf_atten = 31;
1771		else
1772#endif
1773			tpctl.rf_atten = 9;
1774
1775		bwi_mac_set_tpctl_11bg(mac, &tpctl);
1776	}
1777
1778	bwi_mac_dummy_xmit(mac);
1779
1780	mac->mac_flags |= BWI_MAC_F_TPCTL_INITED;
1781	rf->rf_base_tssi = PHY_READ(mac, 0x29);
1782	DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_INIT | BWI_DBG_TXPOWER,
1783	    "base tssi %d\n", rf->rf_base_tssi);
1784
1785	if (abs(rf->rf_base_tssi - rf->rf_idle_tssi) >= 20) {
1786		aprint_error_dev(sc->sc_dev, "base tssi measure failed\n");
1787		mac->mac_flags |= BWI_MAC_F_TPCTL_ERROR;
1788	}
1789
1790	if (restore_tpctl)
1791		bwi_mac_set_tpctl_11bg(mac, &tpctl_orig);
1792	else
1793		RF_CLRBITS(mac, 0x76, 0x84);
1794
1795	bwi_rf_clear_tssi(mac);
1796}
1797
1798static void
1799bwi_mac_detach(struct bwi_mac *mac)
1800{
1801	bwi_mac_fw_free(mac);
1802}
1803
1804static int
1805bwi_mac_fw_alloc(struct bwi_mac *mac)
1806{
1807	struct bwi_softc *sc = mac->mac_sc;
1808	int idx, error;
1809
1810	error = bwi_mac_fw_image_alloc(mac, BWI_FW_UCODE_PREFIX,
1811	    mac->mac_rev >= 5 ? 5 : mac->mac_rev, &mac->mac_ucode_fwi,
1812	    BWI_FW_T_UCODE);
1813	if (error)
1814		goto fail_ucode;
1815
1816	error = bwi_mac_fw_image_alloc(mac, BWI_FW_PCM_PREFIX,
1817	    mac->mac_rev >= 5 ? 5 : mac->mac_rev, &mac->mac_pcm_fwi,
1818	    BWI_FW_T_PCM);
1819	if (error)
1820		goto fail_pcm;
1821
1822	/* TODO: 11A */
1823	if (mac->mac_rev == 2 || mac->mac_rev == 4)
1824		idx = 2;
1825	else if (mac->mac_rev >= 5 && mac->mac_rev <= 20)
1826		idx = 5;
1827	else {
1828		aprint_error_dev(sc->sc_dev,
1829		    "no suitable IV for MAC rev %d\n", mac->mac_rev);
1830		error = ENODEV;
1831		goto fail_iv;
1832	}
1833
1834	error = bwi_mac_fw_image_alloc(mac, BWI_FW_IV_PREFIX, idx,
1835	    &mac->mac_iv_fwi, BWI_FW_T_IV);
1836	if (error)
1837		goto fail_iv;
1838
1839	/* TODO: 11A */
1840	if (mac->mac_rev == 2 || mac->mac_rev == 4 ||
1841	    mac->mac_rev >= 11)
1842		/* No extended IV */
1843		goto back;
1844	else if (mac->mac_rev >= 5 && mac->mac_rev <= 10)
1845		idx = 5;
1846	else {
1847		aprint_error_dev(sc->sc_dev,
1848		    "no suitable ExtIV for MAC rev %d\n", mac->mac_rev);
1849		error = ENODEV;
1850		goto fail_iv_ext;
1851	}
1852
1853	error = bwi_mac_fw_image_alloc(mac, BWI_FW_IV_EXT_PREFIX, idx,
1854	    &mac->mac_iv_ext_fwi, BWI_FW_T_IV);
1855	if (error)
1856		goto fail_iv_ext;
1857
1858back:	return (0);
1859
1860fail_iv_ext:
1861	bwi_mac_fw_image_free(mac, &mac->mac_iv_fwi);
1862
1863fail_iv:
1864	bwi_mac_fw_image_free(mac, &mac->mac_pcm_fwi);
1865
1866fail_pcm:
1867	bwi_mac_fw_image_free(mac, &mac->mac_ucode_fwi);
1868
1869fail_ucode:
1870	return (error);
1871}
1872
1873static void
1874bwi_mac_fw_free(struct bwi_mac *mac)
1875{
1876	bwi_mac_fw_image_free(mac, &mac->mac_ucode_fwi);
1877	bwi_mac_fw_image_free(mac, &mac->mac_pcm_fwi);
1878	bwi_mac_fw_image_free(mac, &mac->mac_iv_fwi);
1879	bwi_mac_fw_image_free(mac, &mac->mac_iv_ext_fwi);
1880}
1881
1882static int
1883bwi_mac_fw_image_alloc(struct bwi_mac *mac, const char *prefix, int idx,
1884    struct bwi_fw_image *fwi, uint8_t fw_type)
1885{
1886	struct bwi_softc *sc = mac->mac_sc;
1887	char *fw_name = fwi->fwi_name;
1888	size_t fw_name_size = sizeof(fwi->fwi_name);
1889	firmware_handle_t fwh;
1890	const struct bwi_fwhdr *hdr;
1891	int error;
1892
1893	/* [TRC: XXX ???] */
1894	if (fwi->fwi_data != NULL)
1895		return (0);
1896
1897	snprintf(fw_name, fw_name_size, BWI_FW_NAME_FORMAT, sc->sc_fw_version,
1898	    prefix, idx);
1899
1900	DPRINTF(sc, BWI_DBG_FIRMWARE, "opening firmware %s\n", fw_name);
1901
1902	error = firmware_open("bwi", fw_name, &fwh);
1903	if (error) {
1904		aprint_error_dev(sc->sc_dev, "firmware_open failed on %s\n",
1905		    fw_name);
1906		goto fail;
1907	}
1908
1909	fwi->fwi_size = firmware_get_size(fwh);
1910	if (fwi->fwi_size < sizeof(struct bwi_fwhdr)) {
1911		aprint_error_dev(sc->sc_dev,
1912		    "firmware image %s has no header\n",
1913		    fw_name);
1914		error = EIO;
1915		goto fail;
1916	}
1917
1918	DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_INIT | BWI_DBG_FIRMWARE,
1919	    "firmware image %s, size %zx\n", fw_name, fwi->fwi_size);
1920
1921	fwi->fwi_data = firmware_malloc(fwi->fwi_size);
1922	if (fwi->fwi_data == NULL) {
1923		error = ENOMEM;
1924		firmware_close(fwh);
1925		goto fail;
1926	}
1927
1928	DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_INIT | BWI_DBG_FIRMWARE,
1929	    "firmware image %s loaded at %p\n", fw_name, fwi->fwi_data);
1930
1931	fwi->fwi_data = firmware_malloc(fwi->fwi_size);
1932	error = firmware_read(fwh, 0, fwi->fwi_data, fwi->fwi_size);
1933	firmware_close(fwh);
1934	if (error)
1935		goto free_and_fail;
1936
1937	hdr = (const struct bwi_fwhdr *)fwi->fwi_data;
1938
1939	if (fw_type != BWI_FW_T_IV) {
1940		/*
1941		 * Don't verify IV's size, it has different meaning
1942		 */
1943		size_t fw_size = (size_t)be32toh(hdr->fw_size);
1944		if (fw_size != fwi->fwi_size - sizeof(*hdr)) {
1945			aprint_error_dev(sc->sc_dev, "firmware image %s"
1946			    " size mismatch, fw %zx, real %zx\n", fw_name,
1947			    fw_size, fwi->fwi_size - sizeof(*hdr));
1948			goto invalid;
1949		}
1950	}
1951
1952	if (hdr->fw_type != fw_type) {
1953		aprint_error_dev(sc->sc_dev, "firmware image %s"
1954		    " type mismatch, fw `%c', target `%c'\n", fw_name,
1955		    hdr->fw_type, fw_type);
1956		goto invalid;
1957	}
1958
1959	if (hdr->fw_gen != BWI_FW_GEN_1) {
1960		aprint_error_dev(sc->sc_dev, "firmware image %s"
1961		    " generation mismatch, fw %d, target %d\n", fw_name,
1962		    hdr->fw_gen, BWI_FW_GEN_1);
1963		goto invalid;
1964	}
1965
1966	DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_INIT | BWI_DBG_FIRMWARE,
1967	    "firmware image %s loaded successfully\n", fw_name);
1968
1969	return (0);
1970
1971invalid:
1972	error = EINVAL;
1973
1974free_and_fail:
1975	firmware_free(fwi->fwi_data, fwi->fwi_size);
1976	fwi->fwi_data = NULL;
1977	fwi->fwi_size = 0;
1978
1979fail:
1980	return (error);
1981}
1982
1983static void
1984bwi_mac_fw_image_free(struct bwi_mac *mac, struct bwi_fw_image *fwi)
1985{
1986	if (fwi->fwi_data != NULL) {
1987		DPRINTF(mac->mac_sc, BWI_DBG_FIRMWARE, "freeing firmware %s\n",
1988		    fwi->fwi_name);
1989		firmware_free(fwi->fwi_data, fwi->fwi_size);
1990		fwi->fwi_data = NULL;
1991		fwi->fwi_size = 0;
1992	}
1993}
1994
1995static int
1996bwi_mac_fw_load(struct bwi_mac *mac)
1997{
1998	struct bwi_softc *sc = mac->mac_sc;
1999	const uint32_t *fw;
2000	uint16_t fw_rev;
2001	size_t fw_len, i;
2002
2003	/*
2004	 * Load ucode image
2005	 */
2006	fw = (const uint32_t *)(mac->mac_ucode + BWI_FWHDR_SZ);
2007	fw_len = (mac->mac_ucode_size - BWI_FWHDR_SZ) / sizeof(uint32_t);
2008
2009	DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_INIT | BWI_DBG_FIRMWARE,
2010	    "loading ucode image at %p, length %zx\n",
2011	    fw, fw_len);
2012
2013	CSR_WRITE_4(sc, BWI_MOBJ_CTRL,
2014	    BWI_MOBJ_CTRL_VAL(BWI_FW_UCODE_MOBJ | BWI_WR_MOBJ_AUTOINC, 0));
2015	for (i = 0; i < fw_len; ++i) {
2016		CSR_WRITE_4(sc, BWI_MOBJ_DATA, be32toh(fw[i]));
2017		DELAY(10);
2018	}
2019
2020	/*
2021	 * Load PCM image
2022	 */
2023	fw = (const uint32_t *)(mac->mac_pcm + BWI_FWHDR_SZ);
2024	fw_len = (mac->mac_pcm_size - BWI_FWHDR_SZ) / sizeof(uint32_t);
2025
2026	DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_INIT | BWI_DBG_FIRMWARE,
2027	    "loading PCM image at %p, length %zx\n",
2028	    fw, fw_len);
2029
2030	CSR_WRITE_4(sc, BWI_MOBJ_CTRL,
2031	    BWI_MOBJ_CTRL_VAL(BWI_FW_PCM_MOBJ, 0x01ea));
2032	CSR_WRITE_4(sc, BWI_MOBJ_DATA, 0x4000);
2033
2034	CSR_WRITE_4(sc, BWI_MOBJ_CTRL,
2035	    BWI_MOBJ_CTRL_VAL(BWI_FW_PCM_MOBJ, 0x01eb));
2036	for (i = 0; i < fw_len; ++i) {
2037		CSR_WRITE_4(sc, BWI_MOBJ_DATA, be32toh(fw[i]));
2038		DELAY(10);
2039	}
2040
2041	CSR_WRITE_4(sc, BWI_MAC_INTR_STATUS, BWI_ALL_INTRS);
2042	CSR_WRITE_4(sc, BWI_MAC_STATUS,
2043	    BWI_MAC_STATUS_UCODE_START |
2044	    BWI_MAC_STATUS_IHREN |
2045	    BWI_MAC_STATUS_INFRA);
2046#define NRETRY	200
2047	for (i = 0; i < NRETRY; ++i) {
2048		uint32_t intr_status;
2049
2050		intr_status = CSR_READ_4(sc, BWI_MAC_INTR_STATUS);
2051		if (intr_status == BWI_INTR_READY)
2052			break;
2053		DELAY(10);
2054	}
2055	if (i == NRETRY) {
2056		aprint_error_dev(sc->sc_dev,
2057		    "timeout loading ucode & pcm firmware\n");
2058		return (ETIMEDOUT);
2059	}
2060#undef NRETRY
2061
2062	CSR_READ_4(sc, BWI_MAC_INTR_STATUS);	/* dummy read */
2063
2064	fw_rev = MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_FWREV);
2065	if (fw_rev > BWI_FW_VERSION3_REVMAX) {
2066		aprint_error_dev(sc->sc_dev,
2067		    "firmware version 4 is not supported yet\n");
2068		return (ENODEV);
2069	}
2070
2071	aprint_normal_dev(sc->sc_dev, "firmware rev 0x%04x,"
2072	    " patch level 0x%04x\n", fw_rev,
2073	    MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_FWPATCHLV));
2074
2075	return (0);
2076}
2077
2078static int
2079bwi_mac_gpio_init(struct bwi_mac *mac)
2080{
2081	struct bwi_softc *sc = mac->mac_sc;
2082	struct bwi_regwin *old, *gpio_rw;
2083	uint32_t filt, bits;
2084	int error;
2085
2086	CSR_CLRBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_GPOSEL_MASK);
2087	/* TODO: LED */
2088
2089	CSR_SETBITS_2(sc, BWI_MAC_GPIO_MASK, 0xf);
2090
2091	filt = 0x1f;
2092	bits = 0xf;
2093	if (sc->sc_bbp_id == BWI_BBPID_BCM4301) {
2094		filt |= 0x60;
2095		bits |= 0x60;
2096	}
2097	if (sc->sc_card_flags & BWI_CARD_F_PA_GPIO9) {
2098		CSR_SETBITS_2(sc, BWI_MAC_GPIO_MASK, 0x200);
2099		filt |= 0x200;
2100		bits |= 0x200;
2101	}
2102
2103	gpio_rw = BWI_GPIO_REGWIN(sc);
2104	error = bwi_regwin_switch(sc, gpio_rw, &old);
2105	if (error)
2106		return (error);
2107
2108	CSR_FILT_SETBITS_4(sc, BWI_GPIO_CTRL, filt, bits);
2109
2110	return (bwi_regwin_switch(sc, old, NULL));
2111}
2112
2113static int
2114bwi_mac_gpio_fini(struct bwi_mac *mac)
2115{
2116	struct bwi_softc *sc = mac->mac_sc;
2117	struct bwi_regwin *old, *gpio_rw;
2118	int error;
2119
2120	gpio_rw = BWI_GPIO_REGWIN(sc);
2121	error = bwi_regwin_switch(sc, gpio_rw, &old);
2122	if (error)
2123		return (error);
2124
2125	CSR_WRITE_4(sc, BWI_GPIO_CTRL, 0);
2126
2127	return (bwi_regwin_switch(sc, old, NULL));
2128}
2129
2130static int
2131bwi_mac_fw_load_iv(struct bwi_mac *mac, const struct bwi_fw_image *fwi)
2132{
2133	struct bwi_softc *sc = mac->mac_sc;
2134	const struct bwi_fwhdr *hdr;
2135	const struct bwi_fw_iv *iv;
2136	size_t iv_img_size;
2137	int n, i;
2138
2139	DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_INIT | BWI_DBG_FIRMWARE,
2140	    "loading %s at %p\n", fwi->fwi_name, fwi->fwi_data);
2141
2142	/* Get the number of IVs in the IV image */
2143	hdr = (const struct bwi_fwhdr *)fwi->fwi_data;
2144	n = be32toh(hdr->fw_iv_cnt);
2145	DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_INIT | BWI_DBG_FIRMWARE,
2146	    "IV count %d\n", n);
2147
2148	/* Calculate the IV image size, for later sanity check */
2149	iv_img_size = fwi->fwi_size - sizeof(*hdr);
2150
2151	/* Locate the first IV */
2152	iv = (const struct bwi_fw_iv *)(fwi->fwi_data + sizeof(*hdr));
2153
2154	for (i = 0; i < n; ++i) {
2155		uint16_t iv_ofs, ofs;
2156		int sz = 0;
2157
2158		if (iv_img_size < sizeof(iv->iv_ofs)) {
2159			aprint_error_dev(sc->sc_dev,
2160			    "invalid IV image, ofs\n");
2161			return (EINVAL);
2162		}
2163		iv_img_size -= sizeof(iv->iv_ofs);
2164		sz += sizeof(iv->iv_ofs);
2165
2166		iv_ofs = be16toh(iv->iv_ofs);
2167
2168		ofs = __SHIFTOUT(iv_ofs, BWI_FW_IV_OFS_MASK);
2169		if (ofs >= 0x1000) {
2170			aprint_error_dev(sc->sc_dev, "invalid ofs (0x%04x) "
2171			    "for %dth iv\n", ofs, i);
2172			return (EINVAL);
2173		}
2174
2175		if (iv_ofs & BWI_FW_IV_IS_32BIT) {
2176			uint32_t val32;
2177
2178			if (iv_img_size < sizeof(iv->iv_val.val32)) {
2179				aprint_error_dev(sc->sc_dev,
2180				    "invalid IV image, val32\n");
2181				return (EINVAL);
2182			}
2183			iv_img_size -= sizeof(iv->iv_val.val32);
2184			sz += sizeof(iv->iv_val.val32);
2185
2186			val32 = be32toh(iv->iv_val.val32);
2187			CSR_WRITE_4(sc, ofs, val32);
2188		} else {
2189			uint16_t val16;
2190
2191			if (iv_img_size < sizeof(iv->iv_val.val16)) {
2192				aprint_error_dev(sc->sc_dev,
2193				    "invalid IV image, val16\n");
2194				return (EINVAL);
2195			}
2196			iv_img_size -= sizeof(iv->iv_val.val16);
2197			sz += sizeof(iv->iv_val.val16);
2198
2199			val16 = be16toh(iv->iv_val.val16);
2200			CSR_WRITE_2(sc, ofs, val16);
2201		}
2202
2203		iv = (const struct bwi_fw_iv *)((const uint8_t *)iv + sz);
2204	}
2205
2206	if (iv_img_size != 0) {
2207		aprint_error_dev(sc->sc_dev,
2208		    "invalid IV image, size left %zx\n", iv_img_size);
2209		return (EINVAL);
2210	}
2211
2212	return (0);
2213}
2214
2215static int
2216bwi_mac_fw_init(struct bwi_mac *mac)
2217{
2218	struct bwi_softc *sc = mac->mac_sc;
2219	int error;
2220
2221	error = bwi_mac_fw_load_iv(mac, &mac->mac_iv_fwi);
2222	if (error) {
2223		aprint_error_dev(sc->sc_dev, "load IV failed\n");
2224		return (error);
2225	}
2226
2227	if (mac->mac_iv_ext != NULL) {
2228		error = bwi_mac_fw_load_iv(mac, &mac->mac_iv_ext_fwi);
2229		if (error)
2230			aprint_error_dev(sc->sc_dev, "load ExtIV failed\n");
2231	}
2232
2233	return (error);
2234}
2235
2236static void
2237bwi_mac_opmode_init(struct bwi_mac *mac)
2238{
2239	struct bwi_softc *sc = mac->mac_sc;
2240	struct ieee80211com *ic = &sc->sc_ic;
2241	uint32_t mac_status;
2242	uint16_t pre_tbtt;
2243
2244	CSR_CLRBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_INFRA);
2245	CSR_SETBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_INFRA);
2246	CSR_SETBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_PASS_BCN);
2247
2248	/* Set probe resp timeout to infinite */
2249	MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_PROBE_RESP_TO, 0);
2250
2251	/*
2252	 * TODO: factor out following part
2253	 */
2254
2255	mac_status = CSR_READ_4(sc, BWI_MAC_STATUS);
2256	mac_status &= ~(BWI_MAC_STATUS_OPMODE_HOSTAP |
2257	    BWI_MAC_STATUS_PASS_CTL |
2258	    BWI_MAC_STATUS_PASS_BADPLCP |
2259	    BWI_MAC_STATUS_PASS_BADFCS |
2260	    BWI_MAC_STATUS_PROMISC);
2261	mac_status |= BWI_MAC_STATUS_INFRA;
2262
2263	/* Always turn on PROMISC on old hardware */
2264	if (mac->mac_rev < 5)
2265		mac_status |= BWI_MAC_STATUS_PROMISC;
2266
2267	switch (ic->ic_opmode) {
2268	case IEEE80211_M_IBSS:
2269		mac_status &= ~BWI_MAC_STATUS_INFRA;
2270		break;
2271	case IEEE80211_M_HOSTAP:
2272		mac_status |= BWI_MAC_STATUS_OPMODE_HOSTAP;
2273		break;
2274	case IEEE80211_M_MONITOR:
2275#if 0
2276		/* Do you want data from your microwave oven? */
2277		mac_status |= BWI_MAC_STATUS_PASS_CTL |
2278			      BWI_MAC_STATUS_PASS_BADPLCP |
2279			      BWI_MAC_STATUS_PASS_BADFCS;
2280#else
2281		mac_status |= BWI_MAC_STATUS_PASS_CTL;
2282#endif
2283		/* Promisc? */
2284		break;
2285	default:
2286		break;
2287	}
2288
2289	if (sc->sc_if.if_flags & IFF_PROMISC)
2290		mac_status |= BWI_MAC_STATUS_PROMISC;
2291
2292	CSR_WRITE_4(sc, BWI_MAC_STATUS, mac_status);
2293
2294	if (ic->ic_opmode != IEEE80211_M_IBSS &&
2295	    ic->ic_opmode != IEEE80211_M_HOSTAP) {
2296		if (sc->sc_bbp_id == BWI_BBPID_BCM4306 && sc->sc_bbp_rev == 3)
2297			pre_tbtt = 100;
2298		else
2299			pre_tbtt = 50;
2300	} else
2301		pre_tbtt = 2;
2302	CSR_WRITE_2(sc, BWI_MAC_PRE_TBTT, pre_tbtt);
2303}
2304
2305static void
2306bwi_mac_hostflags_init(struct bwi_mac *mac)
2307{
2308	struct bwi_softc *sc = mac->mac_sc;
2309	struct bwi_phy *phy = &mac->mac_phy;
2310	struct bwi_rf *rf = &mac->mac_rf;
2311	uint64_t host_flags;
2312
2313	if (phy->phy_mode == IEEE80211_MODE_11A)
2314		return;
2315
2316	host_flags = HFLAGS_READ(mac);
2317	host_flags |= BWI_HFLAG_SYM_WA;
2318
2319	if (phy->phy_mode == IEEE80211_MODE_11G) {
2320		if (phy->phy_rev == 1)
2321			host_flags |= BWI_HFLAG_GDC_WA;
2322		if (sc->sc_card_flags & BWI_CARD_F_PA_GPIO9)
2323			host_flags |= BWI_HFLAG_OFDM_PA;
2324	} else if (phy->phy_mode == IEEE80211_MODE_11B) {
2325		if (phy->phy_rev >= 2 && rf->rf_type == BWI_RF_T_BCM2050)
2326			host_flags &= ~BWI_HFLAG_GDC_WA;
2327	} else {
2328		panic("unknown PHY mode %u\n", phy->phy_mode);
2329	}
2330
2331	HFLAGS_WRITE(mac, host_flags);
2332}
2333
2334static void
2335bwi_mac_bss_param_init(struct bwi_mac *mac)
2336{
2337	struct bwi_softc *sc = mac->mac_sc;
2338	struct bwi_phy *phy = &mac->mac_phy;
2339	struct bwi_retry_lim lim;
2340	uint16_t cw_min;
2341
2342	/*
2343	 * Set short/long retry limits
2344	 */
2345	memset(&lim, 0, sizeof(lim));
2346	lim.shretry = BWI_SHRETRY;
2347	lim.shretry_fb = BWI_SHRETRY_FB;
2348	lim.lgretry = BWI_LGRETRY;
2349	lim.lgretry_fb = BWI_LGRETRY_FB;
2350	bwi_mac_set_retry_lim(mac, &lim);
2351
2352	/*
2353	 * Implicitly prevent firmware from sending probe response
2354	 * by setting its "probe response timeout" to 1us.
2355	 */
2356	MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_PROBE_RESP_TO, 1);
2357
2358	/*
2359	 * XXX MAC level acknowledge and CW min/max should depend
2360	 * on the char rateset of the IBSS/BSS to join.
2361	 */
2362
2363	/*
2364	 * Set MAC level acknowledge rates
2365	 */
2366	bwi_mac_set_ackrates(mac, &sc->sc_ic.ic_sup_rates[phy->phy_mode]);
2367
2368	/*
2369	 * Set CW min
2370	 */
2371	if (phy->phy_mode == IEEE80211_MODE_11B)
2372		cw_min = IEEE80211_CW_MIN_0;
2373	else
2374		cw_min = IEEE80211_CW_MIN_1;
2375	MOBJ_WRITE_2(mac, BWI_80211_MOBJ, BWI_80211_MOBJ_CWMIN, cw_min);
2376
2377	/*
2378	 * Set CW max
2379	 */
2380	MOBJ_WRITE_2(mac, BWI_80211_MOBJ, BWI_80211_MOBJ_CWMAX,
2381	    IEEE80211_CW_MAX);
2382}
2383
2384static void
2385bwi_mac_set_retry_lim(struct bwi_mac *mac, const struct bwi_retry_lim *lim)
2386{
2387	/* Short/Long retry limit */
2388	MOBJ_WRITE_2(mac, BWI_80211_MOBJ, BWI_80211_MOBJ_SHRETRY,
2389	    lim->shretry);
2390	MOBJ_WRITE_2(mac, BWI_80211_MOBJ, BWI_80211_MOBJ_LGRETRY,
2391	    lim->lgretry);
2392
2393	/* Short/Long retry fallback limit */
2394	MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_SHRETRY_FB,
2395	    lim->shretry_fb);
2396	MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_LGRETEY_FB,
2397	    lim->lgretry_fb);
2398}
2399
2400static void
2401bwi_mac_set_ackrates(struct bwi_mac *mac, const struct ieee80211_rateset *rs)
2402{
2403	int i;
2404
2405	/* XXX not standard conforming */
2406	for (i = 0; i < rs->rs_nrates; ++i) {
2407		enum bwi_ieee80211_modtype modtype;
2408		uint16_t ofs;
2409
2410		modtype = bwi_ieee80211_rate2modtype(rs->rs_rates[i]);
2411		switch (modtype) {
2412		case IEEE80211_MODTYPE_DS:
2413			ofs = 0x4c0;
2414			ofs += (bwi_ieee80211_rate2plcp(rs->rs_rates[i],
2415			    IEEE80211_MODE_11B) & 0xf) * 2;
2416			break;
2417		case IEEE80211_MODTYPE_OFDM:
2418			ofs = 0x480;
2419			ofs += (bwi_ieee80211_rate2plcp(rs->rs_rates[i],
2420			    IEEE80211_MODE_11G) & 0xf) * 2;
2421			break;
2422		default:
2423			panic("unsupported modtype %u\n", modtype);
2424		}
2425
2426		MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, ofs + 0x20,
2427		    MOBJ_READ_2(mac, BWI_COMM_MOBJ, ofs));
2428	}
2429}
2430
2431static int
2432bwi_mac_start(struct bwi_mac *mac)
2433{
2434	struct bwi_softc *sc = mac->mac_sc;
2435
2436	CSR_SETBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_ENABLE);
2437	CSR_WRITE_4(sc, BWI_MAC_INTR_STATUS, BWI_INTR_READY);
2438
2439	/* Flush pending bus writes */
2440	CSR_READ_4(sc, BWI_MAC_STATUS);
2441	CSR_READ_4(sc, BWI_MAC_INTR_STATUS);
2442
2443	return (bwi_mac_config_ps(mac));
2444}
2445
2446static int
2447bwi_mac_stop(struct bwi_mac *mac)
2448{
2449	struct bwi_softc *sc = mac->mac_sc;
2450	int error, i;
2451
2452	error = bwi_mac_config_ps(mac);
2453	if (error)
2454		return (error);
2455
2456	CSR_CLRBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_ENABLE);
2457
2458	/* Flush pending bus write */
2459	CSR_READ_4(sc, BWI_MAC_STATUS);
2460
2461#define NRETRY	10000
2462	for (i = 0; i < NRETRY; ++i) {
2463		if (CSR_READ_4(sc, BWI_MAC_INTR_STATUS) & BWI_INTR_READY)
2464			break;
2465		DELAY(1);
2466	}
2467	if (i == NRETRY) {
2468		aprint_error_dev(sc->sc_dev, "can't stop MAC\n");
2469		return (ETIMEDOUT);
2470	}
2471#undef NRETRY
2472
2473	return (0);
2474}
2475
2476static int
2477bwi_mac_config_ps(struct bwi_mac *mac)
2478{
2479	struct bwi_softc *sc = mac->mac_sc;
2480	uint32_t status;
2481
2482	status = CSR_READ_4(sc, BWI_MAC_STATUS);
2483
2484	status &= ~BWI_MAC_STATUS_HW_PS;
2485	status |= BWI_MAC_STATUS_WAKEUP;
2486	CSR_WRITE_4(sc, BWI_MAC_STATUS, status);
2487
2488	/* Flush pending bus write */
2489	CSR_READ_4(sc, BWI_MAC_STATUS);
2490
2491	if (mac->mac_rev >= 5) {
2492		int i;
2493
2494#define NRETRY	100
2495		for (i = 0; i < NRETRY; ++i) {
2496			if (MOBJ_READ_2(mac, BWI_COMM_MOBJ,
2497			    BWI_COMM_MOBJ_UCODE_STATE) != BWI_UCODE_STATE_PS)
2498				break;
2499			DELAY(10);
2500		}
2501		if (i == NRETRY) {
2502			aprint_error_dev(sc->sc_dev, "config PS failed\n");
2503			return (ETIMEDOUT);
2504		}
2505#undef NRETRY
2506	}
2507	return (0);
2508}
2509
2510static void
2511bwi_mac_reset_hwkeys(struct bwi_mac *mac)
2512{
2513	/* TODO: firmware crypto */
2514	MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_KEYTABLE_OFS);
2515}
2516
2517static void
2518bwi_mac_shutdown(struct bwi_mac *mac)
2519{
2520	struct bwi_softc *sc = mac->mac_sc;
2521	int i;
2522
2523	if (mac->mac_flags & BWI_MAC_F_HAS_TXSTATS)
2524		(sc->sc_free_txstats)(sc);
2525
2526	(sc->sc_free_rx_ring)(sc);
2527
2528	for (i = 0; i < BWI_TX_NRING; ++i)
2529		(sc->sc_free_tx_ring)(sc, i);
2530
2531	bwi_rf_off(mac);
2532
2533	/* TODO: LED */
2534
2535	bwi_mac_gpio_fini(mac);
2536
2537	bwi_rf_off(mac); /* XXX again */
2538	CSR_WRITE_2(sc, BWI_BBP_ATTEN, BWI_BBP_ATTEN_MAGIC);
2539	bwi_regwin_disable(sc, &mac->mac_regwin, 0);
2540
2541	mac->mac_flags &= ~BWI_MAC_F_INITED;
2542}
2543
2544static int
2545bwi_mac_get_property(struct bwi_mac *mac)
2546{
2547	struct bwi_softc *sc = mac->mac_sc;
2548	enum bwi_bus_space old_bus_space;
2549	uint32_t val;
2550
2551	/*
2552	 * Byte swap
2553	 */
2554	val = CSR_READ_4(sc, BWI_MAC_STATUS);
2555	if (val & BWI_MAC_STATUS_BSWAP) {
2556		DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_ATTACH, "need byte swap\n");
2557		mac->mac_flags |= BWI_MAC_F_BSWAP;
2558	}
2559
2560	/*
2561	 * DMA address space
2562	 */
2563	old_bus_space = sc->sc_bus_space;
2564
2565	val = CSR_READ_4(sc, BWI_STATE_HI);
2566	if (__SHIFTOUT(val, BWI_STATE_HI_FLAGS_MASK) &
2567	    BWI_STATE_HI_FLAG_64BIT) {
2568		/* 64bit address */
2569		sc->sc_bus_space = BWI_BUS_SPACE_64BIT;
2570		DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_ATTACH, "64bit bus space\n");
2571	} else {
2572		uint32_t txrx_reg = BWI_TXRX_CTRL_BASE + BWI_TX32_CTRL;
2573
2574		CSR_WRITE_4(sc, txrx_reg, BWI_TXRX32_CTRL_ADDRHI_MASK);
2575		if (CSR_READ_4(sc, txrx_reg) & BWI_TXRX32_CTRL_ADDRHI_MASK) {
2576			/* 32bit address */
2577			sc->sc_bus_space = BWI_BUS_SPACE_32BIT;
2578			DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_ATTACH,
2579			    "32bit bus space\n");
2580		} else {
2581			/* 30bit address */
2582			sc->sc_bus_space = BWI_BUS_SPACE_30BIT;
2583			DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_ATTACH,
2584			    "30bit bus space\n");
2585		}
2586	}
2587
2588	if (old_bus_space != 0 && old_bus_space != sc->sc_bus_space) {
2589		aprint_error_dev(sc->sc_dev, "MACs bus space mismatch!\n");
2590		return (ENXIO);
2591	}
2592
2593	return (0);
2594}
2595
2596static void
2597bwi_mac_updateslot(struct bwi_mac *mac, int shslot)
2598{
2599	uint16_t slot_time;
2600
2601	if (mac->mac_phy.phy_mode == IEEE80211_MODE_11B)
2602		return;
2603
2604	if (shslot)
2605		slot_time = IEEE80211_DUR_SHSLOT;
2606	else
2607		slot_time = IEEE80211_DUR_SLOT;
2608
2609	CSR_WRITE_2(mac->mac_sc, BWI_MAC_SLOTTIME,
2610	    slot_time + BWI_MAC_SLOTTIME_ADJUST);
2611	MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_SLOTTIME, slot_time);
2612}
2613
2614static int
2615bwi_mac_attach(struct bwi_softc *sc, int id, uint8_t rev)
2616{
2617	struct bwi_mac *mac;
2618	int i;
2619
2620	KASSERT(sc->sc_nmac <= BWI_MAC_MAX && sc->sc_nmac >= 0);
2621
2622	if (sc->sc_nmac == BWI_MAC_MAX) {
2623		aprint_error_dev(sc->sc_dev, "too many MACs\n");
2624		return (0);
2625	}
2626
2627	/*
2628	 * More than one MAC is only supported by BCM4309
2629	 */
2630	if (sc->sc_nmac != 0 &&
2631	    sc->sc_pci_did != PCI_PRODUCT_BROADCOM_BCM4309) {
2632		DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_ATTACH,
2633		    "ignore %dth MAC\n", sc->sc_nmac);
2634		return (0);
2635	}
2636
2637	mac = &sc->sc_mac[sc->sc_nmac];
2638
2639	/* XXX will this happen? */
2640	if (BWI_REGWIN_EXIST(&mac->mac_regwin)) {
2641		aprint_error_dev(sc->sc_dev, "%dth MAC already attached\n",
2642		    sc->sc_nmac);
2643		return (0);
2644	}
2645
2646	/*
2647	 * Test whether the revision of this MAC is supported
2648	 */
2649	for (i = 0; i < __arraycount(bwi_sup_macrev); ++i) {
2650		if (bwi_sup_macrev[i] == rev)
2651			break;
2652	}
2653	if (i == __arraycount(bwi_sup_macrev)) {
2654		aprint_error_dev(sc->sc_dev, "MAC rev %u is not supported\n",
2655		    rev);
2656		return (ENXIO);
2657	}
2658
2659	BWI_CREATE_MAC(mac, sc, id, rev);
2660	sc->sc_nmac++;
2661
2662	if (mac->mac_rev < 5) {
2663		mac->mac_flags |= BWI_MAC_F_HAS_TXSTATS;
2664		DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_ATTACH, "has TX stats\n");
2665	} else {
2666		mac->mac_flags |= BWI_MAC_F_PHYE_RESET;
2667	}
2668
2669	aprint_normal_dev(sc->sc_dev, "MAC: rev %u\n", rev);
2670	return (0);
2671}
2672
2673static void
2674bwi_mac_balance_atten(int *bbp_atten0, int *rf_atten0)
2675{
2676	int bbp_atten, rf_atten, rf_atten_lim = -1;
2677
2678	bbp_atten = *bbp_atten0;
2679	rf_atten = *rf_atten0;
2680
2681	/*
2682	 * RF attenuation affects TX power BWI_RF_ATTEN_FACTOR times
2683	 * as much as BBP attenuation, so we try our best to keep RF
2684	 * attenuation within range.  BBP attenuation will be clamped
2685	 * later if it is out of range during balancing.
2686	 *
2687	 * BWI_RF_ATTEN_MAX0 is used as RF attenuation upper limit.
2688	 */
2689
2690	/*
2691	 * Use BBP attenuation to balance RF attenuation
2692	 */
2693	if (rf_atten < 0)
2694		rf_atten_lim = 0;
2695	else if (rf_atten > BWI_RF_ATTEN_MAX0)
2696		rf_atten_lim = BWI_RF_ATTEN_MAX0;
2697
2698	if (rf_atten_lim >= 0) {
2699		bbp_atten += (BWI_RF_ATTEN_FACTOR * (rf_atten - rf_atten_lim));
2700		rf_atten = rf_atten_lim;
2701	}
2702
2703	/*
2704	 * If possible, use RF attenuation to balance BBP attenuation
2705	 * NOTE: RF attenuation is still kept within range.
2706	 */
2707	while (rf_atten < BWI_RF_ATTEN_MAX0 && bbp_atten > BWI_BBP_ATTEN_MAX) {
2708		bbp_atten -= BWI_RF_ATTEN_FACTOR;
2709		++rf_atten;
2710	}
2711	while (rf_atten > 0 && bbp_atten < 0) {
2712		bbp_atten += BWI_RF_ATTEN_FACTOR;
2713		--rf_atten;
2714	}
2715
2716	/* RF attenuation MUST be within range */
2717	KASSERT(rf_atten >= 0 && rf_atten <= BWI_RF_ATTEN_MAX0);
2718
2719	/*
2720	 * Clamp BBP attenuation
2721	 */
2722	if (bbp_atten < 0)
2723		bbp_atten = 0;
2724	else if (bbp_atten > BWI_BBP_ATTEN_MAX)
2725		bbp_atten = BWI_BBP_ATTEN_MAX;
2726
2727	*rf_atten0 = rf_atten;
2728	*bbp_atten0 = bbp_atten;
2729}
2730
2731static void
2732bwi_mac_adjust_tpctl(struct bwi_mac *mac, int rf_atten_adj, int bbp_atten_adj)
2733{
2734	struct bwi_softc *sc = mac->mac_sc;
2735	struct bwi_rf *rf = &mac->mac_rf;
2736	struct bwi_tpctl tpctl;
2737	int bbp_atten, rf_atten, tp_ctrl1;
2738
2739	memcpy(&tpctl, &mac->mac_tpctl, sizeof(tpctl));
2740
2741	/* NOTE: Use signed value to do calulation */
2742	bbp_atten = tpctl.bbp_atten;
2743	rf_atten = tpctl.rf_atten;
2744	tp_ctrl1 = tpctl.tp_ctrl1;
2745
2746	bbp_atten += bbp_atten_adj;
2747	rf_atten += rf_atten_adj;
2748
2749	bwi_mac_balance_atten(&bbp_atten, &rf_atten);
2750
2751	if (rf->rf_type == BWI_RF_T_BCM2050 && rf->rf_rev == 2) {
2752		if (rf_atten <= 1) {
2753			if (tp_ctrl1 == 0) {
2754				tp_ctrl1 = 3;
2755				bbp_atten += 2;
2756				rf_atten += 2;
2757			} else if (sc->sc_card_flags & BWI_CARD_F_PA_GPIO9) {
2758				bbp_atten +=
2759				(BWI_RF_ATTEN_FACTOR * (rf_atten - 2));
2760				rf_atten = 2;
2761			}
2762		} else if (rf_atten > 4 && tp_ctrl1 != 0) {
2763			tp_ctrl1 = 0;
2764			if (bbp_atten < 3) {
2765				bbp_atten += 2;
2766				rf_atten -= 3;
2767			} else {
2768				bbp_atten -= 2;
2769				rf_atten -= 2;
2770			}
2771		}
2772		bwi_mac_balance_atten(&bbp_atten, &rf_atten);
2773	}
2774
2775	tpctl.bbp_atten = bbp_atten;
2776	tpctl.rf_atten = rf_atten;
2777	tpctl.tp_ctrl1 = tp_ctrl1;
2778
2779	bwi_mac_lock(mac);
2780	bwi_mac_set_tpctl_11bg(mac, &tpctl);
2781	bwi_mac_unlock(mac);
2782}
2783
2784/*
2785 * http://bcm-specs.sipsolutions.net/RecalculateTransmissionPower
2786 */
2787static void
2788bwi_mac_calibrate_txpower(struct bwi_mac *mac, enum bwi_txpwrcb_type type)
2789{
2790	struct bwi_softc *sc = mac->mac_sc;
2791	struct bwi_rf *rf = &mac->mac_rf;
2792	int8_t tssi[4], tssi_avg, cur_txpwr;
2793	int error, i, ofdm_tssi;
2794	int txpwr_diff, rf_atten_adj, bbp_atten_adj;
2795
2796	if (!sc->sc_txpwr_calib)
2797		return;
2798
2799	if (mac->mac_flags & BWI_MAC_F_TPCTL_ERROR) {
2800		DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_TXPOWER,
2801		    "tpctl error happened, can't set txpower\n");
2802		return;
2803	}
2804
2805	if (BWI_IS_BRCM_BU4306(sc)) {
2806		DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_TXPOWER,
2807		    "BU4306, can't set txpower\n");
2808		return;
2809	}
2810
2811	/*
2812	 * Save latest TSSI and reset the related memory objects
2813	 */
2814	ofdm_tssi = 0;
2815	error = bwi_rf_get_latest_tssi(mac, tssi, BWI_COMM_MOBJ_TSSI_DS);
2816	if (error) {
2817		DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_TXPOWER, "no DS tssi\n");
2818
2819		if (mac->mac_phy.phy_mode == IEEE80211_MODE_11B) {
2820			if (type == BWI_TXPWR_FORCE) {
2821				rf_atten_adj = 0;
2822				bbp_atten_adj = 1;
2823				goto calib;
2824			} else {
2825				return;
2826			}
2827		}
2828
2829		error = bwi_rf_get_latest_tssi(mac, tssi,
2830		    BWI_COMM_MOBJ_TSSI_OFDM);
2831		if (error) {
2832			DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_TXPOWER,
2833			    "no OFDM tssi\n");
2834			if (type == BWI_TXPWR_FORCE) {
2835				rf_atten_adj = 0;
2836				bbp_atten_adj = 1;
2837				goto calib;
2838			} else {
2839				return;
2840			}
2841		}
2842
2843		for (i = 0; i < 4; ++i) {
2844			tssi[i] += 0x20;
2845			tssi[i] &= 0x3f;
2846		}
2847		ofdm_tssi = 1;
2848	}
2849	bwi_rf_clear_tssi(mac);
2850
2851	DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_TXPOWER,
2852	    "tssi0 %d, tssi1 %d, tssi2 %d, tssi3 %d\n",
2853	    tssi[0], tssi[1], tssi[2], tssi[3]);
2854
2855	/*
2856	 * Calculate RF/BBP attenuation adjustment based on
2857	 * the difference between desired TX power and sampled
2858	 * TX power.
2859	 */
2860	/* +8 == "each incremented by 1/2" */
2861	tssi_avg = (tssi[0] + tssi[1] + tssi[2] + tssi[3] + 8) / 4;
2862	if (ofdm_tssi && (HFLAGS_READ(mac) & BWI_HFLAG_PWR_BOOST_DS))
2863		tssi_avg -= 13;
2864
2865	DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_TXPOWER, "tssi avg %d\n", tssi_avg);
2866
2867	error = bwi_rf_tssi2dbm(mac, tssi_avg, &cur_txpwr);
2868	if (error)
2869		return;
2870	DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_TXPOWER, "current txpower %d\n",
2871	    cur_txpwr);
2872
2873	txpwr_diff = rf->rf_txpower_max - cur_txpwr; /* XXX ni_txpower */
2874
2875	rf_atten_adj = -howmany(txpwr_diff, 8);
2876
2877	if (type == BWI_TXPWR_INIT) {
2878		/*
2879		 * Move toward EEPROM max TX power as fast as we can
2880		 */
2881		bbp_atten_adj = -txpwr_diff;
2882	} else {
2883		bbp_atten_adj = -(txpwr_diff / 2);
2884	}
2885	bbp_atten_adj -= (BWI_RF_ATTEN_FACTOR * rf_atten_adj);
2886
2887	if (rf_atten_adj == 0 && bbp_atten_adj == 0) {
2888		DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_TXPOWER, "%s\n",
2889		    "no need to adjust RF/BBP attenuation");
2890		/* TODO: LO */
2891		return;
2892	}
2893
2894calib:
2895	DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_TXPOWER,
2896	    "rf atten adjust %d, bbp atten adjust %d\n",
2897	    rf_atten_adj, bbp_atten_adj);
2898	bwi_mac_adjust_tpctl(mac, rf_atten_adj, bbp_atten_adj);
2899	/* TODO: LO */
2900}
2901
2902static void
2903bwi_mac_lock(struct bwi_mac *mac)
2904{
2905	struct bwi_softc *sc = mac->mac_sc;
2906	struct ieee80211com *ic = &sc->sc_ic;
2907
2908	KASSERT((mac->mac_flags & BWI_MAC_F_LOCKED) == 0);
2909
2910	if (mac->mac_rev < 3)
2911		bwi_mac_stop(mac);
2912	else if (ic->ic_opmode != IEEE80211_M_HOSTAP)
2913		bwi_mac_config_ps(mac);
2914
2915	CSR_SETBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_RFLOCK);
2916
2917	/* Flush pending bus write */
2918	CSR_READ_4(sc, BWI_MAC_STATUS);
2919	DELAY(10);
2920
2921	mac->mac_flags |= BWI_MAC_F_LOCKED;
2922}
2923
2924static void
2925bwi_mac_unlock(struct bwi_mac *mac)
2926{
2927	struct bwi_softc *sc = mac->mac_sc;
2928	struct ieee80211com *ic = &sc->sc_ic;
2929
2930	KASSERT(mac->mac_flags & BWI_MAC_F_LOCKED);
2931
2932	CSR_READ_2(sc, BWI_PHYINFO); /* dummy read */
2933
2934	CSR_CLRBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_RFLOCK);
2935
2936	if (mac->mac_rev < 3)
2937		bwi_mac_start(mac);
2938	else if (ic->ic_opmode != IEEE80211_M_HOSTAP)
2939		bwi_mac_config_ps(mac);
2940
2941	mac->mac_flags &= ~BWI_MAC_F_LOCKED;
2942}
2943
2944static void
2945bwi_mac_set_promisc(struct bwi_mac *mac, int promisc)
2946{
2947	struct bwi_softc *sc = mac->mac_sc;
2948
2949	if (mac->mac_rev < 5) /* Promisc is always on */
2950		return;
2951
2952	if (promisc)
2953		CSR_SETBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_PROMISC);
2954	else
2955		CSR_CLRBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_PROMISC);
2956}
2957
2958/* PHY */
2959
2960static void
2961bwi_phy_write(struct bwi_mac *mac, uint16_t ctrl, uint16_t data)
2962{
2963	struct bwi_softc *sc = mac->mac_sc;
2964
2965	/* TODO: 11A */
2966	CSR_WRITE_2(sc, BWI_PHY_CTRL, ctrl);
2967	CSR_WRITE_2(sc, BWI_PHY_DATA, data);
2968}
2969
2970static uint16_t
2971bwi_phy_read(struct bwi_mac *mac, uint16_t ctrl)
2972{
2973	struct bwi_softc *sc = mac->mac_sc;
2974
2975	/* TODO: 11A */
2976	CSR_WRITE_2(sc, BWI_PHY_CTRL, ctrl);
2977	return (CSR_READ_2(sc, BWI_PHY_DATA));
2978}
2979
2980static int
2981bwi_phy_attach(struct bwi_mac *mac)
2982{
2983	struct bwi_softc *sc = mac->mac_sc;
2984	struct bwi_phy *phy = &mac->mac_phy;
2985	uint8_t phyrev, phytype, phyver;
2986	uint16_t val;
2987	int i;
2988
2989	/* Get PHY type/revision/version */
2990	val = CSR_READ_2(sc, BWI_PHYINFO);
2991	phyrev = __SHIFTOUT(val, BWI_PHYINFO_REV_MASK);
2992	phytype = __SHIFTOUT(val, BWI_PHYINFO_TYPE_MASK);
2993	phyver = __SHIFTOUT(val, BWI_PHYINFO_VER_MASK);
2994	aprint_normal_dev(sc->sc_dev, "PHY type %d, rev %d, ver %d\n",
2995	    phytype, phyrev, phyver);
2996
2997	/*
2998	 * Verify whether the revision of the PHY type is supported
2999	 * Convert PHY type to ieee80211_phymode
3000	 */
3001	switch (phytype) {
3002	case BWI_PHYINFO_TYPE_11A:
3003		if (phyrev >= 4) {
3004			aprint_error_dev(sc->sc_dev,
3005			    "unsupported 11A PHY, rev %u\n",
3006			    phyrev);
3007			return (ENXIO);
3008		}
3009		phy->phy_init = bwi_phy_init_11a;
3010		phy->phy_mode = IEEE80211_MODE_11A;
3011		phy->phy_tbl_ctrl = BWI_PHYR_TBL_CTRL_11A;
3012		phy->phy_tbl_data_lo = BWI_PHYR_TBL_DATA_LO_11A;
3013		phy->phy_tbl_data_hi = BWI_PHYR_TBL_DATA_HI_11A;
3014		break;
3015	case BWI_PHYINFO_TYPE_11B:
3016		for (i = 0; i < __arraycount(bwi_sup_bphy); ++i) {
3017			if (phyrev == bwi_sup_bphy[i].rev) {
3018				phy->phy_init = bwi_sup_bphy[i].init;
3019				break;
3020			}
3021		}
3022		if (i == __arraycount(bwi_sup_bphy)) {
3023			aprint_error_dev(sc->sc_dev,
3024			    "unsupported 11B PHY, rev %u\n",
3025			    phyrev);
3026			return (ENXIO);
3027		}
3028		phy->phy_mode = IEEE80211_MODE_11B;
3029		break;
3030	case BWI_PHYINFO_TYPE_11G:
3031		if (phyrev > 8) {
3032			aprint_error_dev(sc->sc_dev,
3033			    "unsupported 11G PHY, rev %u\n",
3034			    phyrev);
3035			return (ENXIO);
3036		}
3037		phy->phy_init = bwi_phy_init_11g;
3038		phy->phy_mode = IEEE80211_MODE_11G;
3039		phy->phy_tbl_ctrl = BWI_PHYR_TBL_CTRL_11G;
3040		phy->phy_tbl_data_lo = BWI_PHYR_TBL_DATA_LO_11G;
3041		phy->phy_tbl_data_hi = BWI_PHYR_TBL_DATA_HI_11G;
3042		break;
3043	default:
3044		aprint_error_dev(sc->sc_dev, "unsupported PHY type %d\n",
3045		    phytype);
3046		return (ENXIO);
3047	}
3048	phy->phy_rev = phyrev;
3049	phy->phy_version = phyver;
3050
3051	return (0);
3052}
3053
3054static void
3055bwi_phy_set_bbp_atten(struct bwi_mac *mac, uint16_t bbp_atten)
3056{
3057	struct bwi_phy *phy = &mac->mac_phy;
3058	uint16_t mask = 0x000f;
3059
3060	if (phy->phy_version == 0) {
3061		CSR_FILT_SETBITS_2(mac->mac_sc, BWI_BBP_ATTEN, ~mask,
3062		    __SHIFTIN(bbp_atten, mask));
3063	} else {
3064		if (phy->phy_version > 1)
3065			mask <<= 2;
3066		else
3067			mask <<= 3;
3068		PHY_FILT_SETBITS(mac, BWI_PHYR_BBP_ATTEN, ~mask,
3069		    __SHIFTIN(bbp_atten, mask));
3070	}
3071}
3072
3073static int
3074bwi_phy_calibrate(struct bwi_mac *mac)
3075{
3076	struct bwi_phy *phy = &mac->mac_phy;
3077
3078	/* Dummy read */
3079	CSR_READ_4(mac->mac_sc, BWI_MAC_STATUS);
3080
3081	/* Don't re-init */
3082	if (phy->phy_flags & BWI_PHY_F_CALIBRATED)
3083		return (0);
3084
3085	if (phy->phy_mode == IEEE80211_MODE_11G && phy->phy_rev == 1) {
3086		bwi_mac_reset(mac, 0);
3087		bwi_phy_init_11g(mac);
3088		bwi_mac_reset(mac, 1);
3089	}
3090
3091	phy->phy_flags |= BWI_PHY_F_CALIBRATED;
3092
3093	return (0);
3094}
3095
3096static void
3097bwi_tbl_write_2(struct bwi_mac *mac, uint16_t ofs, uint16_t data)
3098{
3099	struct bwi_phy *phy = &mac->mac_phy;
3100
3101	KASSERT(phy->phy_tbl_ctrl != 0 && phy->phy_tbl_data_lo != 0);
3102	PHY_WRITE(mac, phy->phy_tbl_ctrl, ofs);
3103	PHY_WRITE(mac, phy->phy_tbl_data_lo, data);
3104}
3105
3106static void
3107bwi_tbl_write_4(struct bwi_mac *mac, uint16_t ofs, uint32_t data)
3108{
3109	struct bwi_phy *phy = &mac->mac_phy;
3110
3111	KASSERT(phy->phy_tbl_data_lo != 0 && phy->phy_tbl_data_hi != 0 &&
3112	    phy->phy_tbl_ctrl != 0);
3113
3114	PHY_WRITE(mac, phy->phy_tbl_ctrl, ofs);
3115	PHY_WRITE(mac, phy->phy_tbl_data_hi, data >> 16);
3116	PHY_WRITE(mac, phy->phy_tbl_data_lo, data & 0xffff);
3117}
3118
3119static void
3120bwi_nrssi_write(struct bwi_mac *mac, uint16_t ofs, int16_t data)
3121{
3122	PHY_WRITE(mac, BWI_PHYR_NRSSI_CTRL, ofs);
3123	PHY_WRITE(mac, BWI_PHYR_NRSSI_DATA, (uint16_t)data);
3124}
3125
3126static int16_t
3127bwi_nrssi_read(struct bwi_mac *mac, uint16_t ofs)
3128{
3129	PHY_WRITE(mac, BWI_PHYR_NRSSI_CTRL, ofs);
3130	return ((int16_t)PHY_READ(mac, BWI_PHYR_NRSSI_DATA));
3131}
3132
3133static void
3134bwi_phy_init_11a(struct bwi_mac *mac)
3135{
3136	/* TODO: 11A */
3137}
3138
3139static void
3140bwi_phy_init_11g(struct bwi_mac *mac)
3141{
3142	struct bwi_softc *sc = mac->mac_sc;
3143	struct bwi_phy *phy = &mac->mac_phy;
3144	struct bwi_rf *rf = &mac->mac_rf;
3145	const struct bwi_tpctl *tpctl = &mac->mac_tpctl;
3146
3147	if (phy->phy_rev == 1)
3148		bwi_phy_init_11b_rev5(mac);
3149	else
3150		bwi_phy_init_11b_rev6(mac);
3151
3152	if (phy->phy_rev >= 2 || (phy->phy_flags & BWI_PHY_F_LINKED))
3153		bwi_phy_config_11g(mac);
3154
3155	if (phy->phy_rev >= 2) {
3156		PHY_WRITE(mac, 0x814, 0);
3157		PHY_WRITE(mac, 0x815, 0);
3158
3159		if (phy->phy_rev == 2) {
3160			PHY_WRITE(mac, 0x811, 0);
3161			PHY_WRITE(mac, 0x15, 0xc0);
3162		} else if (phy->phy_rev > 5) {
3163			PHY_WRITE(mac, 0x811, 0x400);
3164			PHY_WRITE(mac, 0x15, 0xc0);
3165		}
3166	}
3167
3168	if (phy->phy_rev >= 2 || (phy->phy_flags & BWI_PHY_F_LINKED)) {
3169		uint16_t val;
3170
3171		val = PHY_READ(mac, 0x400) & 0xff;
3172		if (val == 3 || val == 5) {
3173			PHY_WRITE(mac, 0x4c2, 0x1816);
3174			PHY_WRITE(mac, 0x4c3, 0x8006);
3175			if (val == 5) {
3176				PHY_FILT_SETBITS(mac, 0x4cc,
3177						 0xff, 0x1f00);
3178			}
3179		}
3180	}
3181
3182	if ((phy->phy_rev <= 2 && (phy->phy_flags & BWI_PHY_F_LINKED)) ||
3183	    phy->phy_rev >= 2)
3184		PHY_WRITE(mac, 0x47e, 0x78);
3185
3186	if (rf->rf_rev == 8) {
3187		PHY_SETBITS(mac, 0x801, 0x80);
3188		PHY_SETBITS(mac, 0x43e, 0x4);
3189	}
3190
3191	if (phy->phy_rev >= 2 && (phy->phy_flags & BWI_PHY_F_LINKED))
3192		bwi_rf_get_gains(mac);
3193
3194	if (rf->rf_rev != 8)
3195		bwi_rf_init(mac);
3196
3197	if (tpctl->tp_ctrl2 == 0xffff) {
3198		bwi_rf_lo_update(mac);
3199	} else {
3200		if (rf->rf_type == BWI_RF_T_BCM2050 && rf->rf_rev == 8) {
3201			RF_WRITE(mac, 0x52,
3202			    (tpctl->tp_ctrl1 << 4) | tpctl->tp_ctrl2);
3203		} else {
3204			RF_FILT_SETBITS(mac, 0x52, 0xfff0, tpctl->tp_ctrl2);
3205		}
3206
3207		if (phy->phy_rev >= 6) {
3208			PHY_FILT_SETBITS(mac, 0x36, 0xfff,
3209			    tpctl->tp_ctrl2 << 12);
3210		}
3211
3212		if (sc->sc_card_flags & BWI_CARD_F_PA_GPIO9)
3213			PHY_WRITE(mac, 0x2e, 0x8075);
3214		else
3215			PHY_WRITE(mac, 0x2e, 0x807f);
3216
3217		if (phy->phy_rev < 2)
3218			PHY_WRITE(mac, 0x2f, 0x101);
3219		else
3220			PHY_WRITE(mac, 0x2f, 0x202);
3221	}
3222
3223	if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) {
3224		bwi_rf_lo_adjust(mac, tpctl);
3225		PHY_WRITE(mac, 0x80f, 0x8078);
3226	}
3227
3228	if ((sc->sc_card_flags & BWI_CARD_F_SW_NRSSI) == 0) {
3229		bwi_rf_init_hw_nrssi_table(mac, 0xffff /* XXX */);
3230		bwi_rf_set_nrssi_thr(mac);
3231	} else if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) {
3232		if (rf->rf_nrssi[0] == BWI_INVALID_NRSSI) {
3233			KASSERT(rf->rf_nrssi[1] == BWI_INVALID_NRSSI);
3234			bwi_rf_calc_nrssi_slope(mac);
3235		} else {
3236			KASSERT(rf->rf_nrssi[1] != BWI_INVALID_NRSSI);
3237			bwi_rf_set_nrssi_thr(mac);
3238		}
3239	}
3240
3241	if (rf->rf_rev == 8)
3242		PHY_WRITE(mac, 0x805, 0x3230);
3243
3244	bwi_mac_init_tpctl_11bg(mac);
3245
3246	if (sc->sc_bbp_id == BWI_BBPID_BCM4306 && sc->sc_bbp_pkg == 2) {
3247		PHY_CLRBITS(mac, 0x429, 0x4000);
3248		PHY_CLRBITS(mac, 0x4c3, 0x8000);
3249	}
3250}
3251
3252static void
3253bwi_phy_init_11b_rev2(struct bwi_mac *mac)
3254{
3255	struct bwi_softc *sc;
3256
3257	sc = mac->mac_sc;
3258
3259	/* TODO: 11B */
3260	aprint_error_dev(sc->sc_dev, "%s is not implemented yet\n", __func__);
3261}
3262
3263static void
3264bwi_phy_init_11b_rev4(struct bwi_mac *mac)
3265{
3266	struct bwi_softc *sc = mac->mac_sc;
3267	struct bwi_rf *rf = &mac->mac_rf;
3268	uint16_t val, ofs;
3269	uint chan;
3270
3271	CSR_WRITE_2(sc, BWI_BPHY_CTRL, BWI_BPHY_CTRL_INIT);
3272
3273	PHY_WRITE(mac, 0x20, 0x301c);
3274	PHY_WRITE(mac, 0x26, 0);
3275	PHY_WRITE(mac, 0x30, 0xc6);
3276	PHY_WRITE(mac, 0x88, 0x3e00);
3277
3278	for (ofs = 0, val = 0x3c3d; ofs < 30; ++ofs, val -= 0x202)
3279		PHY_WRITE(mac, 0x89 + ofs, val);
3280
3281	CSR_WRITE_2(sc, BWI_PHY_MAGIC_REG1, BWI_PHY_MAGIC_REG1_VAL1);
3282
3283	chan = rf->rf_curchan;
3284	if (chan == IEEE80211_CHAN_ANY)
3285		chan = 6;	/* Force to channel 6 */
3286	bwi_rf_set_chan(mac, chan, 0);
3287
3288	if (rf->rf_type != BWI_RF_T_BCM2050) {
3289		RF_WRITE(mac, 0x75, 0x80);
3290		RF_WRITE(mac, 0x79, 0x81);
3291	}
3292
3293	RF_WRITE(mac, 0x50, 0x20);
3294	RF_WRITE(mac, 0x50, 0x23);
3295
3296	if (rf->rf_type == BWI_RF_T_BCM2050) {
3297		RF_WRITE(mac, 0x50, 0x20);
3298		RF_WRITE(mac, 0x5a, 0x70);
3299		RF_WRITE(mac, 0x5b, 0x7b);
3300		RF_WRITE(mac, 0x5c, 0xb0);
3301		RF_WRITE(mac, 0x7a, 0xf);
3302		PHY_WRITE(mac, 0x38, 0x677);
3303		bwi_rf_init_bcm2050(mac);
3304	}
3305
3306	PHY_WRITE(mac, 0x14, 0x80);
3307	PHY_WRITE(mac, 0x32, 0xca);
3308	if (rf->rf_type == BWI_RF_T_BCM2050)
3309		PHY_WRITE(mac, 0x32, 0xe0);
3310	PHY_WRITE(mac, 0x35, 0x7c2);
3311
3312	bwi_rf_lo_update(mac);
3313
3314	PHY_WRITE(mac, 0x26, 0xcc00);
3315	if (rf->rf_type == BWI_RF_T_BCM2050)
3316		PHY_WRITE(mac, 0x26, 0xce00);
3317
3318	CSR_WRITE_2(sc, BWI_RF_CHAN_EX, 0x1100);
3319
3320	PHY_WRITE(mac, 0x2a, 0x88a3);
3321	if (rf->rf_type == BWI_RF_T_BCM2050)
3322		PHY_WRITE(mac, 0x2a, 0x88c2);
3323
3324	bwi_mac_set_tpctl_11bg(mac, NULL);
3325	if (sc->sc_card_flags & BWI_CARD_F_SW_NRSSI) {
3326		bwi_rf_calc_nrssi_slope(mac);
3327		bwi_rf_set_nrssi_thr(mac);
3328	}
3329	bwi_mac_init_tpctl_11bg(mac);
3330}
3331
3332static void
3333bwi_phy_init_11b_rev5(struct bwi_mac *mac)
3334{
3335	struct bwi_softc *sc = mac->mac_sc;
3336	struct bwi_rf *rf = &mac->mac_rf;
3337	struct bwi_phy *phy = &mac->mac_phy;
3338	uint orig_chan;
3339
3340	if (phy->phy_version == 1)
3341		RF_SETBITS(mac, 0x7a, 0x50);
3342
3343	if (sc->sc_pci_subvid != PCI_VENDOR_BROADCOM &&
3344	    sc->sc_pci_subdid != BWI_PCI_SUBDEVICE_BU4306) {
3345		uint16_t ofs, val;
3346
3347		val = 0x2120;
3348		for (ofs = 0xa8; ofs < 0xc7; ++ofs) {
3349			PHY_WRITE(mac, ofs, val);
3350			val += 0x202;
3351		}
3352	}
3353
3354	PHY_FILT_SETBITS(mac, 0x35, 0xf0ff, 0x700);
3355
3356	if (rf->rf_type == BWI_RF_T_BCM2050)
3357		PHY_WRITE(mac, 0x38, 0x667);
3358
3359	if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) {
3360		if (rf->rf_type == BWI_RF_T_BCM2050) {
3361			RF_SETBITS(mac, 0x7a, 0x20);
3362			RF_SETBITS(mac, 0x51, 0x4);
3363		}
3364
3365		CSR_WRITE_2(sc, BWI_RF_ANTDIV, 0);
3366
3367		PHY_SETBITS(mac, 0x802, 0x100);
3368		PHY_SETBITS(mac, 0x42b, 0x2000);
3369		PHY_WRITE(mac, 0x1c, 0x186a);
3370
3371		PHY_FILT_SETBITS(mac, 0x13, 0xff, 0x1900);
3372		PHY_FILT_SETBITS(mac, 0x35, 0xffc0, 0x64);
3373		PHY_FILT_SETBITS(mac, 0x5d, 0xff80, 0xa);
3374	}
3375
3376	/* TODO: bad_frame_preempt? */
3377
3378	if (phy->phy_version == 1) {
3379	    	PHY_WRITE(mac, 0x26, 0xce00);
3380		PHY_WRITE(mac, 0x21, 0x3763);
3381		PHY_WRITE(mac, 0x22, 0x1bc3);
3382		PHY_WRITE(mac, 0x23, 0x6f9);
3383		PHY_WRITE(mac, 0x24, 0x37e);
3384	} else
3385		PHY_WRITE(mac, 0x26, 0xcc00);
3386	PHY_WRITE(mac, 0x30, 0xc6);
3387
3388	CSR_WRITE_2(sc, BWI_BPHY_CTRL, BWI_BPHY_CTRL_INIT);
3389
3390	if (phy->phy_version == 1)
3391		PHY_WRITE(mac, 0x20, 0x3e1c);
3392	else
3393		PHY_WRITE(mac, 0x20, 0x301c);
3394
3395	if (phy->phy_version == 0)
3396		CSR_WRITE_2(sc, BWI_PHY_MAGIC_REG1, BWI_PHY_MAGIC_REG1_VAL1);
3397
3398	/* Force to channel 7 */
3399	orig_chan = rf->rf_curchan;
3400	bwi_rf_set_chan(mac, 7, 0);
3401
3402	if (rf->rf_type != BWI_RF_T_BCM2050) {
3403		RF_WRITE(mac, 0x75, 0x80);
3404		RF_WRITE(mac, 0x79, 0x81);
3405	}
3406
3407	RF_WRITE(mac, 0x50, 0x20);
3408	RF_WRITE(mac, 0x50, 0x23);
3409
3410	if (rf->rf_type == BWI_RF_T_BCM2050) {
3411		RF_WRITE(mac, 0x50, 0x20);
3412		RF_WRITE(mac, 0x5a, 0x70);
3413	}
3414
3415	RF_WRITE(mac, 0x5b, 0x7b);
3416	RF_WRITE(mac, 0x5c, 0xb0);
3417	RF_SETBITS(mac, 0x7a, 0x7);
3418
3419	bwi_rf_set_chan(mac, orig_chan, 0);
3420
3421	PHY_WRITE(mac, 0x14, 0x80);
3422	PHY_WRITE(mac, 0x32, 0xca);
3423	PHY_WRITE(mac, 0x2a, 0x88a3);
3424
3425	bwi_mac_set_tpctl_11bg(mac, NULL);
3426
3427	if (rf->rf_type == BWI_RF_T_BCM2050)
3428		RF_WRITE(mac, 0x5d, 0xd);
3429
3430	CSR_FILT_SETBITS_2(sc, BWI_PHY_MAGIC_REG1, 0xffc0, 0x4);
3431}
3432
3433static void
3434bwi_phy_init_11b_rev6(struct bwi_mac *mac)
3435{
3436	struct bwi_softc *sc = mac->mac_sc;
3437	struct bwi_rf *rf = &mac->mac_rf;
3438	struct bwi_phy *phy = &mac->mac_phy;
3439	uint16_t val, ofs;
3440	uint orig_chan;
3441
3442	PHY_WRITE(mac, 0x3e, 0x817a);
3443	RF_SETBITS(mac, 0x7a, 0x58);
3444
3445	if (rf->rf_rev == 4 || rf->rf_rev == 5) {
3446		RF_WRITE(mac, 0x51, 0x37);
3447		RF_WRITE(mac, 0x52, 0x70);
3448		RF_WRITE(mac, 0x53, 0xb3);
3449		RF_WRITE(mac, 0x54, 0x9b);
3450		RF_WRITE(mac, 0x5a, 0x88);
3451		RF_WRITE(mac, 0x5b, 0x88);
3452		RF_WRITE(mac, 0x5d, 0x88);
3453		RF_WRITE(mac, 0x5e, 0x88);
3454		RF_WRITE(mac, 0x7d, 0x88);
3455		HFLAGS_SETBITS(mac, BWI_HFLAG_MAGIC1);
3456	} else if (rf->rf_rev == 8) {
3457		RF_WRITE(mac, 0x51, 0);
3458		RF_WRITE(mac, 0x52, 0x40);
3459		RF_WRITE(mac, 0x53, 0xb7);
3460		RF_WRITE(mac, 0x54, 0x98);
3461		RF_WRITE(mac, 0x5a, 0x88);
3462		RF_WRITE(mac, 0x5b, 0x6b);
3463		RF_WRITE(mac, 0x5c, 0xf);
3464		if (sc->sc_card_flags & BWI_CARD_F_ALT_IQ) {
3465			RF_WRITE(mac, 0x5d, 0xfa);
3466			RF_WRITE(mac, 0x5e, 0xd8);
3467		} else {
3468			RF_WRITE(mac, 0x5d, 0xf5);
3469			RF_WRITE(mac, 0x5e, 0xb8);
3470		}
3471		RF_WRITE(mac, 0x73, 0x3);
3472		RF_WRITE(mac, 0x7d, 0xa8);
3473		RF_WRITE(mac, 0x7c, 0x1);
3474		RF_WRITE(mac, 0x7e, 0x8);
3475	}
3476
3477	val = 0x1e1f;
3478	for (ofs = 0x88; ofs < 0x98; ++ofs) {
3479		PHY_WRITE(mac, ofs, val);
3480		val -= 0x202;
3481	}
3482
3483	val = 0x3e3f;
3484	for (ofs = 0x98; ofs < 0xa8; ++ofs) {
3485		PHY_WRITE(mac, ofs, val);
3486		val -= 0x202;
3487	}
3488
3489	val = 0x2120;
3490	for (ofs = 0xa8; ofs < 0xc8; ++ofs) {
3491		PHY_WRITE(mac, ofs, (val & 0x3f3f));
3492		val += 0x202;
3493	}
3494
3495	if (phy->phy_mode == IEEE80211_MODE_11G) {
3496		RF_SETBITS(mac, 0x7a, 0x20);
3497		RF_SETBITS(mac, 0x51, 0x4);
3498		PHY_SETBITS(mac, 0x802, 0x100);
3499		PHY_SETBITS(mac, 0x42b, 0x2000);
3500		PHY_WRITE(mac, 0x5b, 0);
3501		PHY_WRITE(mac, 0x5c, 0);
3502	}
3503
3504	/* Force to channel 7 */
3505	orig_chan = rf->rf_curchan;
3506	if (orig_chan >= 8)
3507		bwi_rf_set_chan(mac, 1, 0);
3508	else
3509		bwi_rf_set_chan(mac, 13, 0);
3510
3511	RF_WRITE(mac, 0x50, 0x20);
3512	RF_WRITE(mac, 0x50, 0x23);
3513
3514	DELAY(40);
3515
3516	if (rf->rf_rev < 6 || rf->rf_rev == 8) {
3517		RF_SETBITS(mac, 0x7c, 0x2);
3518		RF_WRITE(mac, 0x50, 0x20);
3519	}
3520	if (rf->rf_rev <= 2) {
3521		RF_WRITE(mac, 0x7c, 0x20);
3522		RF_WRITE(mac, 0x5a, 0x70);
3523		RF_WRITE(mac, 0x5b, 0x7b);
3524		RF_WRITE(mac, 0x5c, 0xb0);
3525	}
3526
3527	RF_FILT_SETBITS(mac, 0x7a, 0xf8, 0x7);
3528
3529	bwi_rf_set_chan(mac, orig_chan, 0);
3530
3531	PHY_WRITE(mac, 0x14, 0x200);
3532	if (rf->rf_rev >= 6)
3533		PHY_WRITE(mac, 0x2a, 0x88c2);
3534	else
3535		PHY_WRITE(mac, 0x2a, 0x8ac0);
3536	PHY_WRITE(mac, 0x38, 0x668);
3537
3538	bwi_mac_set_tpctl_11bg(mac, NULL);
3539
3540	if (rf->rf_rev <= 5) {
3541		PHY_FILT_SETBITS(mac, 0x5d, 0xff80, 0x3);
3542		if (rf->rf_rev <= 2)
3543			RF_WRITE(mac, 0x5d, 0xd);
3544	}
3545
3546	if (phy->phy_version == 4) {
3547		CSR_WRITE_2(sc, BWI_PHY_MAGIC_REG1, BWI_PHY_MAGIC_REG1_VAL2);
3548		PHY_CLRBITS(mac, 0x61, 0xf000);
3549	} else {
3550		PHY_FILT_SETBITS(mac, 0x2, 0xffc0, 0x4);
3551	}
3552
3553	if (phy->phy_mode == IEEE80211_MODE_11B) {
3554		CSR_WRITE_2(sc, BWI_BBP_ATTEN, BWI_BBP_ATTEN_MAGIC2);
3555		PHY_WRITE(mac, 0x16, 0x410);
3556		PHY_WRITE(mac, 0x17, 0x820);
3557		PHY_WRITE(mac, 0x62, 0x7);
3558
3559		bwi_rf_init_bcm2050(mac);
3560		bwi_rf_lo_update(mac);
3561		if (sc->sc_card_flags & BWI_CARD_F_SW_NRSSI) {
3562			bwi_rf_calc_nrssi_slope(mac);
3563			bwi_rf_set_nrssi_thr(mac);
3564		}
3565		bwi_mac_init_tpctl_11bg(mac);
3566	} else
3567		CSR_WRITE_2(sc, BWI_BBP_ATTEN, 0);
3568}
3569
3570static void
3571bwi_phy_config_11g(struct bwi_mac *mac)
3572{
3573	struct bwi_softc *sc = mac->mac_sc;
3574	struct bwi_phy *phy = &mac->mac_phy;
3575	const uint16_t *tbl;
3576	uint16_t wrd_ofs1, wrd_ofs2;
3577	int i, n;
3578
3579	if (phy->phy_rev == 1) {
3580		PHY_WRITE(mac, 0x406, 0x4f19);
3581		PHY_FILT_SETBITS(mac, 0x429, 0xfc3f, 0x340);
3582		PHY_WRITE(mac, 0x42c, 0x5a);
3583		PHY_WRITE(mac, 0x427, 0x1a);
3584
3585		/* Fill frequency table */
3586		for (i = 0; i < __arraycount(bwi_phy_freq_11g_rev1); ++i) {
3587			bwi_tbl_write_2(mac, BWI_PHYTBL_FREQ + i,
3588			    bwi_phy_freq_11g_rev1[i]);
3589		}
3590
3591		/* Fill noise table */
3592		for (i = 0; i < __arraycount(bwi_phy_noise_11g_rev1); ++i) {
3593			bwi_tbl_write_2(mac, BWI_PHYTBL_NOISE + i,
3594			    bwi_phy_noise_11g_rev1[i]);
3595		}
3596
3597		/* Fill rotor table */
3598		for (i = 0; i < __arraycount(bwi_phy_rotor_11g_rev1); ++i) {
3599			/* NB: data length is 4 bytes */
3600			bwi_tbl_write_4(mac, BWI_PHYTBL_ROTOR + i,
3601			    bwi_phy_rotor_11g_rev1[i]);
3602		}
3603	} else {
3604		bwi_nrssi_write(mac, 0xba98, (int16_t)0x7654); /* XXX */
3605
3606		if (phy->phy_rev == 2) {
3607			PHY_WRITE(mac, 0x4c0, 0x1861);
3608			PHY_WRITE(mac, 0x4c1, 0x271);
3609		} else if (phy->phy_rev > 2) {
3610			PHY_WRITE(mac, 0x4c0, 0x98);
3611			PHY_WRITE(mac, 0x4c1, 0x70);
3612			PHY_WRITE(mac, 0x4c9, 0x80);
3613		}
3614		PHY_SETBITS(mac, 0x42b, 0x800);
3615
3616		/* Fill RSSI table */
3617		for (i = 0; i < 64; ++i)
3618			bwi_tbl_write_2(mac, BWI_PHYTBL_RSSI + i, i);
3619
3620		/* Fill noise table */
3621		for (i = 0; i < __arraycount(bwi_phy_noise_11g); ++i) {
3622			bwi_tbl_write_2(mac, BWI_PHYTBL_NOISE + i,
3623			    bwi_phy_noise_11g[i]);
3624		}
3625	}
3626
3627	/*
3628	 * Fill noise scale table
3629	 */
3630	if (phy->phy_rev <= 2) {
3631		tbl = bwi_phy_noise_scale_11g_rev2;
3632		n = __arraycount(bwi_phy_noise_scale_11g_rev2);
3633	} else if (phy->phy_rev >= 7 && (PHY_READ(mac, 0x449) & 0x200)) {
3634		tbl = bwi_phy_noise_scale_11g_rev7;
3635		n = __arraycount(bwi_phy_noise_scale_11g_rev7);
3636	} else {
3637		tbl = bwi_phy_noise_scale_11g;
3638		n = __arraycount(bwi_phy_noise_scale_11g);
3639	}
3640	for (i = 0; i < n; ++i)
3641		bwi_tbl_write_2(mac, BWI_PHYTBL_NOISE_SCALE + i, tbl[i]);
3642
3643	/*
3644	 * Fill sigma square table
3645	 */
3646	if (phy->phy_rev == 2) {
3647		tbl = bwi_phy_sigma_sq_11g_rev2;
3648		n = __arraycount(bwi_phy_sigma_sq_11g_rev2);
3649	} else if (phy->phy_rev > 2 && phy->phy_rev <= 8) {
3650		tbl = bwi_phy_sigma_sq_11g_rev7;
3651		n = __arraycount(bwi_phy_sigma_sq_11g_rev7);
3652	} else {
3653		tbl = NULL;
3654		n = 0;
3655	}
3656	for (i = 0; i < n; ++i)
3657		bwi_tbl_write_2(mac, BWI_PHYTBL_SIGMA_SQ + i, tbl[i]);
3658
3659	if (phy->phy_rev == 1) {
3660		/* Fill delay table */
3661		for (i = 0; i < __arraycount(bwi_phy_delay_11g_rev1); ++i) {
3662			bwi_tbl_write_4(mac, BWI_PHYTBL_DELAY + i,
3663			    bwi_phy_delay_11g_rev1[i]);
3664		}
3665
3666		/* Fill WRSSI (Wide-Band RSSI) table */
3667		for (i = 4; i < 20; ++i)
3668			bwi_tbl_write_2(mac, BWI_PHYTBL_WRSSI_REV1 + i, 0x20);
3669
3670		bwi_phy_config_agc(mac);
3671
3672		wrd_ofs1 = 0x5001;
3673		wrd_ofs2 = 0x5002;
3674	} else {
3675		/* Fill WRSSI (Wide-Band RSSI) table */
3676		for (i = 0; i < 0x20; ++i)
3677			bwi_tbl_write_2(mac, BWI_PHYTBL_WRSSI + i, 0x820);
3678
3679		bwi_phy_config_agc(mac);
3680
3681		PHY_READ(mac, 0x400);	/* Dummy read */
3682		PHY_WRITE(mac, 0x403, 0x1000);
3683		bwi_tbl_write_2(mac, 0x3c02, 0xf);
3684		bwi_tbl_write_2(mac, 0x3c03, 0x14);
3685
3686		wrd_ofs1 = 0x401;
3687		wrd_ofs2 = 0x402;
3688	}
3689
3690	if (!(BWI_IS_BRCM_BU4306(sc) && sc->sc_pci_revid == 0x17)) {
3691		bwi_tbl_write_2(mac, wrd_ofs1, 0x2);
3692		bwi_tbl_write_2(mac, wrd_ofs2, 0x1);
3693	}
3694
3695	/* phy->phy_flags & BWI_PHY_F_LINKED ? */
3696	if (sc->sc_card_flags & BWI_CARD_F_PA_GPIO9)
3697		PHY_WRITE(mac, 0x46e, 0x3cf);
3698}
3699
3700/*
3701 * Configure Automatic Gain Controller
3702 */
3703static void
3704bwi_phy_config_agc(struct bwi_mac *mac)
3705{
3706	struct bwi_phy *phy = &mac->mac_phy;
3707	uint16_t ofs;
3708
3709	ofs = phy->phy_rev == 1 ? 0x4c00 : 0;
3710
3711	bwi_tbl_write_2(mac, ofs, 0xfe);
3712	bwi_tbl_write_2(mac, ofs + 1, 0xd);
3713	bwi_tbl_write_2(mac, ofs + 2, 0x13);
3714	bwi_tbl_write_2(mac, ofs + 3, 0x19);
3715
3716	if (phy->phy_rev == 1) {
3717		bwi_tbl_write_2(mac, 0x1800, 0x2710);
3718		bwi_tbl_write_2(mac, 0x1801, 0x9b83);
3719		bwi_tbl_write_2(mac, 0x1802, 0x9b83);
3720		bwi_tbl_write_2(mac, 0x1803, 0xf8d);
3721		PHY_WRITE(mac, 0x455, 0x4);
3722	}
3723
3724	PHY_FILT_SETBITS(mac, 0x4a5, 0xff, 0x5700);
3725	PHY_FILT_SETBITS(mac, 0x41a, 0xff80, 0xf);
3726	PHY_FILT_SETBITS(mac, 0x41a, 0xc07f, 0x2b80);
3727	PHY_FILT_SETBITS(mac, 0x48c, 0xf0ff, 0x300);
3728
3729	RF_SETBITS(mac, 0x7a, 0x8);
3730
3731	PHY_FILT_SETBITS(mac, 0x4a0, 0xfff0, 0x8);
3732	PHY_FILT_SETBITS(mac, 0x4a1, 0xf0ff, 0x600);
3733	PHY_FILT_SETBITS(mac, 0x4a2, 0xf0ff, 0x700);
3734	PHY_FILT_SETBITS(mac, 0x4a0, 0xf0ff, 0x100);
3735
3736	if (phy->phy_rev == 1)
3737		PHY_FILT_SETBITS(mac, 0x4a2, 0xfff0, 0x7);
3738
3739	PHY_FILT_SETBITS(mac, 0x488, 0xff00, 0x1c);
3740	PHY_FILT_SETBITS(mac, 0x488, 0xc0ff, 0x200);
3741	PHY_FILT_SETBITS(mac, 0x496, 0xff00, 0x1c);
3742	PHY_FILT_SETBITS(mac, 0x489, 0xff00, 0x20);
3743	PHY_FILT_SETBITS(mac, 0x489, 0xc0ff, 0x200);
3744	PHY_FILT_SETBITS(mac, 0x482, 0xff00, 0x2e);
3745	PHY_FILT_SETBITS(mac, 0x496, 0xff, 0x1a00);
3746	PHY_FILT_SETBITS(mac, 0x481, 0xff00, 0x28);
3747	PHY_FILT_SETBITS(mac, 0x481, 0xff, 0x2c00);
3748
3749	if (phy->phy_rev == 1) {
3750		PHY_WRITE(mac, 0x430, 0x92b);
3751		PHY_FILT_SETBITS(mac, 0x41b, 0xffe1, 0x2);
3752	} else {
3753		PHY_CLRBITS(mac, 0x41b, 0x1e);
3754		PHY_WRITE(mac, 0x41f, 0x287a);
3755		PHY_FILT_SETBITS(mac, 0x420, 0xfff0, 0x4);
3756
3757		if (phy->phy_rev >= 6) {
3758			PHY_WRITE(mac, 0x422, 0x287a);
3759			PHY_FILT_SETBITS(mac, 0x420, 0xfff, 0x3000);
3760		}
3761	}
3762
3763	PHY_FILT_SETBITS(mac, 0x4a8, 0x8080, 0x7874);
3764	PHY_WRITE(mac, 0x48e, 0x1c00);
3765
3766	if (phy->phy_rev == 1) {
3767		PHY_FILT_SETBITS(mac, 0x4ab, 0xf0ff, 0x600);
3768		PHY_WRITE(mac, 0x48b, 0x5e);
3769		PHY_FILT_SETBITS(mac, 0x48c, 0xff00, 0x1e);
3770		PHY_WRITE(mac, 0x48d, 0x2);
3771	}
3772
3773	bwi_tbl_write_2(mac, ofs + 0x800, 0);
3774	bwi_tbl_write_2(mac, ofs + 0x801, 7);
3775	bwi_tbl_write_2(mac, ofs + 0x802, 16);
3776	bwi_tbl_write_2(mac, ofs + 0x803, 28);
3777
3778	if (phy->phy_rev >= 6) {
3779		PHY_CLRBITS(mac, 0x426, 0x3);
3780		PHY_CLRBITS(mac, 0x426, 0x1000);
3781	}
3782}
3783
3784static void
3785bwi_set_gains(struct bwi_mac *mac, const struct bwi_gains *gains)
3786{
3787	struct bwi_phy *phy = &mac->mac_phy;
3788	uint16_t tbl_gain_ofs1, tbl_gain_ofs2, tbl_gain;
3789	int i;
3790
3791	if (phy->phy_rev <= 1) {
3792		tbl_gain_ofs1 = 0x5000;
3793		tbl_gain_ofs2 = tbl_gain_ofs1 + 16;
3794	} else {
3795		tbl_gain_ofs1 = 0x400;
3796		tbl_gain_ofs2 = tbl_gain_ofs1 + 8;
3797	}
3798
3799	for (i = 0; i < 4; ++i) {
3800		if (gains != NULL) {
3801			tbl_gain = gains->tbl_gain1;
3802		} else {
3803			/* Bit swap */
3804			tbl_gain = (i & 0x1) << 1;
3805			tbl_gain |= (i & 0x2) >> 1;
3806		}
3807		bwi_tbl_write_2(mac, tbl_gain_ofs1 + i, tbl_gain);
3808	}
3809
3810	for (i = 0; i < 16; ++i) {
3811		if (gains != NULL)
3812			tbl_gain = gains->tbl_gain2;
3813		else
3814			tbl_gain = i;
3815		bwi_tbl_write_2(mac, tbl_gain_ofs2 + i, tbl_gain);
3816	}
3817
3818	if (gains == NULL || gains->phy_gain != -1) {
3819		uint16_t phy_gain1, phy_gain2;
3820
3821		if (gains != NULL) {
3822			phy_gain1 =
3823			((uint16_t)gains->phy_gain << 14) |
3824			((uint16_t)gains->phy_gain << 6);
3825			phy_gain2 = phy_gain1;
3826		} else {
3827			phy_gain1 = 0x4040;
3828			phy_gain2 = 0x4000;
3829		}
3830		PHY_FILT_SETBITS(mac, 0x4a0, 0xbfbf, phy_gain1);
3831		PHY_FILT_SETBITS(mac, 0x4a1, 0xbfbf, phy_gain1);
3832		PHY_FILT_SETBITS(mac, 0x4a2, 0xbfbf, phy_gain2);
3833	}
3834	bwi_mac_dummy_xmit(mac);
3835}
3836
3837static void
3838bwi_phy_clear_state(struct bwi_phy *phy)
3839{
3840	phy->phy_flags &= ~BWI_CLEAR_PHY_FLAGS;
3841}
3842
3843/* RF */
3844
3845static int16_t
3846bwi_nrssi_11g(struct bwi_mac *mac)
3847{
3848	int16_t val;
3849
3850#define NRSSI_11G_MASK		0x3f00
3851	val = (int16_t)__SHIFTOUT(PHY_READ(mac, 0x47f), NRSSI_11G_MASK);
3852	if (val >= 32)
3853		val -= 64;
3854
3855	return (val);
3856#undef NRSSI_11G_MASK
3857}
3858
3859static struct bwi_rf_lo *
3860bwi_get_rf_lo(struct bwi_mac *mac, uint16_t rf_atten, uint16_t bbp_atten)
3861{
3862	int n;
3863
3864	n = rf_atten + (14 * (bbp_atten / 2));
3865	KASSERT(n < BWI_RFLO_MAX);
3866
3867	return (&mac->mac_rf.rf_lo[n]);
3868}
3869
3870static int
3871bwi_rf_lo_isused(struct bwi_mac *mac, const struct bwi_rf_lo *lo)
3872{
3873	struct bwi_rf *rf = &mac->mac_rf;
3874	int idx;
3875
3876	idx = lo - rf->rf_lo;
3877	KASSERT(idx >= 0 && idx < BWI_RFLO_MAX);
3878
3879	return (isset(rf->rf_lo_used, idx));
3880}
3881
3882static void
3883bwi_rf_write(struct bwi_mac *mac, uint16_t ctrl, uint16_t data)
3884{
3885	struct bwi_softc *sc = mac->mac_sc;
3886
3887	CSR_WRITE_2(sc, BWI_RF_CTRL, ctrl);
3888	CSR_WRITE_2(sc, BWI_RF_DATA_LO, data);
3889}
3890
3891static uint16_t
3892bwi_rf_read(struct bwi_mac *mac, uint16_t ctrl)
3893{
3894	struct bwi_rf *rf = &mac->mac_rf;
3895	struct bwi_softc *sc = mac->mac_sc;
3896
3897	ctrl |= rf->rf_ctrl_rd;
3898	if (rf->rf_ctrl_adj) {
3899		/* XXX */
3900		if (ctrl < 0x70)
3901			ctrl += 0x80;
3902		else if (ctrl < 0x80)
3903			ctrl += 0x70;
3904	}
3905
3906	CSR_WRITE_2(sc, BWI_RF_CTRL, ctrl);
3907	return (CSR_READ_2(sc, BWI_RF_DATA_LO));
3908}
3909
3910static int
3911bwi_rf_attach(struct bwi_mac *mac)
3912{
3913	struct bwi_softc *sc = mac->mac_sc;
3914	struct bwi_phy *phy = &mac->mac_phy;
3915	struct bwi_rf *rf = &mac->mac_rf;
3916	uint16_t type, manu;
3917	uint8_t rev;
3918
3919	/*
3920	 * Get RF manufacture/type/revision
3921	 */
3922	if (sc->sc_bbp_id == BWI_BBPID_BCM4317) {
3923		/*
3924		 * Fake a BCM2050 RF
3925		 */
3926		manu = BWI_RF_MANUFACT_BCM;
3927		type = BWI_RF_T_BCM2050;
3928		if (sc->sc_bbp_rev == 0)
3929			rev = 3;
3930		else if (sc->sc_bbp_rev == 1)
3931			rev = 4;
3932		else
3933			rev = 5;
3934	} else {
3935		uint32_t val;
3936
3937		CSR_WRITE_2(sc, BWI_RF_CTRL, BWI_RF_CTRL_RFINFO);
3938		val = CSR_READ_2(sc, BWI_RF_DATA_HI);
3939		val <<= 16;
3940
3941		CSR_WRITE_2(sc, BWI_RF_CTRL, BWI_RF_CTRL_RFINFO);
3942		val |= CSR_READ_2(sc, BWI_RF_DATA_LO);
3943
3944		manu = __SHIFTOUT(val, BWI_RFINFO_MANUFACT_MASK);
3945		type = __SHIFTOUT(val, BWI_RFINFO_TYPE_MASK);
3946		rev = __SHIFTOUT(val, BWI_RFINFO_REV_MASK);
3947	}
3948	aprint_normal_dev(sc->sc_dev, "RF manu 0x%03x, type 0x%04x, rev %u\n",
3949	    manu, type, rev);
3950
3951	/*
3952	 * Verify whether the RF is supported
3953	 */
3954	rf->rf_ctrl_rd = 0;
3955	rf->rf_ctrl_adj = 0;
3956	switch (phy->phy_mode) {
3957	case IEEE80211_MODE_11A:
3958		if (manu != BWI_RF_MANUFACT_BCM ||
3959		    type != BWI_RF_T_BCM2060 ||
3960		    rev != 1) {
3961			aprint_error_dev(sc->sc_dev,
3962			    "only BCM2060 rev 1 RF is supported for"
3963			    " 11A PHY\n");
3964			return (ENXIO);
3965		}
3966		rf->rf_ctrl_rd = BWI_RF_CTRL_RD_11A;
3967		rf->rf_on = bwi_rf_on_11a;
3968		rf->rf_off = bwi_rf_off_11a;
3969		rf->rf_calc_rssi = bwi_rf_calc_rssi_bcm2060;
3970		break;
3971	case IEEE80211_MODE_11B:
3972		if (type == BWI_RF_T_BCM2050) {
3973			rf->rf_ctrl_rd = BWI_RF_CTRL_RD_11BG;
3974			rf->rf_calc_rssi = bwi_rf_calc_rssi_bcm2050;
3975		} else if (type == BWI_RF_T_BCM2053) {
3976			rf->rf_ctrl_adj = 1;
3977			rf->rf_calc_rssi = bwi_rf_calc_rssi_bcm2053;
3978		} else {
3979			aprint_error_dev(sc->sc_dev,
3980			    "only BCM2050/BCM2053 RF is supported for"
3981			    " 11B phy\n");
3982			return (ENXIO);
3983		}
3984		rf->rf_on = bwi_rf_on_11bg;
3985		rf->rf_off = bwi_rf_off_11bg;
3986		rf->rf_calc_nrssi_slope = bwi_rf_calc_nrssi_slope_11b;
3987		rf->rf_set_nrssi_thr = bwi_rf_set_nrssi_thr_11b;
3988		if (phy->phy_rev == 6)
3989			rf->rf_lo_update = bwi_rf_lo_update_11g;
3990		else
3991			rf->rf_lo_update = bwi_rf_lo_update_11b;
3992		break;
3993	case IEEE80211_MODE_11G:
3994		if (type != BWI_RF_T_BCM2050) {
3995			aprint_error_dev(sc->sc_dev,
3996			    "only BCM2050 RF is supported for"
3997			    " 11G PHY\n");
3998			return (ENXIO);
3999		}
4000		rf->rf_ctrl_rd = BWI_RF_CTRL_RD_11BG;
4001		rf->rf_on = bwi_rf_on_11bg;
4002		if (mac->mac_rev >= 5)
4003			rf->rf_off = bwi_rf_off_11g_rev5;
4004		else
4005			rf->rf_off = bwi_rf_off_11bg;
4006		rf->rf_calc_nrssi_slope = bwi_rf_calc_nrssi_slope_11g;
4007		rf->rf_set_nrssi_thr = bwi_rf_set_nrssi_thr_11g;
4008		rf->rf_calc_rssi = bwi_rf_calc_rssi_bcm2050;
4009		rf->rf_lo_update = bwi_rf_lo_update_11g;
4010		break;
4011	default:
4012		aprint_error_dev(sc->sc_dev, "unsupported PHY mode\n");
4013		return (ENXIO);
4014	}
4015
4016	rf->rf_type = type;
4017	rf->rf_rev = rev;
4018	rf->rf_manu = manu;
4019	rf->rf_curchan = IEEE80211_CHAN_ANY;
4020	rf->rf_ant_mode = BWI_ANT_MODE_AUTO;
4021
4022	return (0);
4023}
4024
4025static void
4026bwi_rf_set_chan(struct bwi_mac *mac, uint chan, int work_around)
4027{
4028	struct bwi_softc *sc = mac->mac_sc;
4029
4030	if (chan == IEEE80211_CHAN_ANY)
4031		return;
4032
4033	MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_CHAN, chan);
4034
4035	/* TODO: 11A */
4036
4037	if (work_around)
4038		bwi_rf_workaround(mac, chan);
4039
4040	CSR_WRITE_2(sc, BWI_RF_CHAN, BWI_RF_2GHZ_CHAN(chan));
4041
4042	if (chan == 14) {
4043		if (sc->sc_locale == BWI_SPROM_LOCALE_JAPAN)
4044			HFLAGS_CLRBITS(mac, BWI_HFLAG_NOT_JAPAN);
4045		else
4046			HFLAGS_SETBITS(mac, BWI_HFLAG_NOT_JAPAN);
4047		CSR_SETBITS_2(sc, BWI_RF_CHAN_EX, (1 << 11)); /* XXX */
4048	} else {
4049		CSR_CLRBITS_2(sc, BWI_RF_CHAN_EX, 0x840); /* XXX */
4050	}
4051	DELAY(8000);	/* DELAY(2000); */
4052
4053	mac->mac_rf.rf_curchan = chan;
4054}
4055
4056static void
4057bwi_rf_get_gains(struct bwi_mac *mac)
4058{
4059#define SAVE_PHY_MAX	15
4060#define SAVE_RF_MAX	3
4061	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
4062	    { 0x52, 0x43, 0x7a };
4063	static const uint16_t save_phy_regs[SAVE_PHY_MAX] = {
4064	    0x0429, 0x0001, 0x0811, 0x0812,
4065	    0x0814, 0x0815, 0x005a, 0x0059,
4066	    0x0058, 0x000a, 0x0003, 0x080f,
4067	    0x0810, 0x002b, 0x0015
4068	};
4069
4070	struct bwi_phy *phy = &mac->mac_phy;
4071	struct bwi_rf *rf = &mac->mac_rf;
4072	uint16_t save_phy[SAVE_PHY_MAX];
4073	uint16_t save_rf[SAVE_RF_MAX];
4074	uint16_t trsw;
4075	int i, j, loop1_max, loop1, loop2;
4076
4077	/*
4078	 * Save PHY/RF registers for later restoration
4079	 */
4080	for (i = 0; i < SAVE_PHY_MAX; ++i)
4081		save_phy[i] = PHY_READ(mac, save_phy_regs[i]);
4082	PHY_READ(mac, 0x2d); /* dummy read */
4083
4084	for (i = 0; i < SAVE_RF_MAX; ++i)
4085		save_rf[i] = RF_READ(mac, save_rf_regs[i]);
4086
4087	PHY_CLRBITS(mac, 0x429, 0xc000);
4088	PHY_SETBITS(mac, 0x1, 0x8000);
4089
4090	PHY_SETBITS(mac, 0x811, 0x2);
4091	PHY_CLRBITS(mac, 0x812, 0x2);
4092	PHY_SETBITS(mac, 0x811, 0x1);
4093	PHY_CLRBITS(mac, 0x812, 0x1);
4094
4095	PHY_SETBITS(mac, 0x814, 0x1);
4096	PHY_CLRBITS(mac, 0x815, 0x1);
4097	PHY_SETBITS(mac, 0x814, 0x2);
4098	PHY_CLRBITS(mac, 0x815, 0x2);
4099
4100	PHY_SETBITS(mac, 0x811, 0xc);
4101	PHY_SETBITS(mac, 0x812, 0xc);
4102	PHY_SETBITS(mac, 0x811, 0x30);
4103	PHY_FILT_SETBITS(mac, 0x812, 0xffcf, 0x10);
4104
4105	PHY_WRITE(mac, 0x5a, 0x780);
4106	PHY_WRITE(mac, 0x59, 0xc810);
4107	PHY_WRITE(mac, 0x58, 0xd);
4108	PHY_SETBITS(mac, 0xa, 0x2000);
4109
4110	PHY_SETBITS(mac, 0x814, 0x4);
4111	PHY_CLRBITS(mac, 0x815, 0x4);
4112
4113	PHY_FILT_SETBITS(mac, 0x3, 0xff9f, 0x40);
4114
4115	if (rf->rf_rev == 8) {
4116		loop1_max = 15;
4117		RF_WRITE(mac, 0x43, loop1_max);
4118	} else {
4119		loop1_max = 9;
4120	    	RF_WRITE(mac, 0x52, 0x0);
4121		RF_FILT_SETBITS(mac, 0x43, 0xfff0, loop1_max);
4122	}
4123
4124	bwi_phy_set_bbp_atten(mac, 11);
4125
4126	if (phy->phy_rev >= 3)
4127		PHY_WRITE(mac, 0x80f, 0xc020);
4128	else
4129		PHY_WRITE(mac, 0x80f, 0x8020);
4130	PHY_WRITE(mac, 0x810, 0);
4131
4132	PHY_FILT_SETBITS(mac, 0x2b, 0xffc0, 0x1);
4133	PHY_FILT_SETBITS(mac, 0x2b, 0xc0ff, 0x800);
4134	PHY_SETBITS(mac, 0x811, 0x100);
4135	PHY_CLRBITS(mac, 0x812, 0x3000);
4136
4137	if ((mac->mac_sc->sc_card_flags & BWI_CARD_F_EXT_LNA) &&
4138	    phy->phy_rev >= 7) {
4139		PHY_SETBITS(mac, 0x811, 0x800);
4140		PHY_SETBITS(mac, 0x812, 0x8000);
4141	}
4142	RF_CLRBITS(mac, 0x7a, 0xff08);
4143
4144	/*
4145	 * Find out 'loop1/loop2', which will be used to calculate
4146	 * max loopback gain later
4147	 */
4148	j = 0;
4149	for (i = 0; i < loop1_max; ++i) {
4150		for (j = 0; j < 16; ++j) {
4151			RF_WRITE(mac, 0x43, i);
4152
4153			if (bwi_rf_gain_max_reached(mac, j))
4154				goto loop1_exit;
4155		}
4156	}
4157loop1_exit:
4158	loop1 = i;
4159	loop2 = j;
4160
4161	/*
4162	 * Find out 'trsw', which will be used to calculate
4163	 * TRSW(TX/RX switch) RX gain later
4164	 */
4165	if (loop2 >= 8) {
4166		PHY_SETBITS(mac, 0x812, 0x30);
4167		trsw = 0x1b;
4168		for (i = loop2 - 8; i < 16; ++i) {
4169			trsw -= 3;
4170			if (bwi_rf_gain_max_reached(mac, i))
4171				break;
4172		}
4173	} else {
4174		trsw = 0x18;
4175	}
4176
4177	/*
4178	 * Restore saved PHY/RF registers
4179	 */
4180	/* First 4 saved PHY registers need special processing */
4181	for (i = 4; i < SAVE_PHY_MAX; ++i)
4182		PHY_WRITE(mac, save_phy_regs[i], save_phy[i]);
4183
4184	bwi_phy_set_bbp_atten(mac, mac->mac_tpctl.bbp_atten);
4185
4186	for (i = 0; i < SAVE_RF_MAX; ++i)
4187		RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
4188
4189	PHY_WRITE(mac, save_phy_regs[2], save_phy[2] | 0x3);
4190	DELAY(10);
4191	PHY_WRITE(mac, save_phy_regs[2], save_phy[2]);
4192	PHY_WRITE(mac, save_phy_regs[3], save_phy[3]);
4193	PHY_WRITE(mac, save_phy_regs[0], save_phy[0]);
4194	PHY_WRITE(mac, save_phy_regs[1], save_phy[1]);
4195
4196	/*
4197	 * Calculate gains
4198	 */
4199	rf->rf_lo_gain = (loop2 * 6) - (loop1 * 4) - 11;
4200	rf->rf_rx_gain = trsw * 2;
4201	DPRINTF(mac->mac_sc, BWI_DBG_RF | BWI_DBG_INIT,
4202	    "lo gain: %u, rx gain: %u\n",
4203	    rf->rf_lo_gain, rf->rf_rx_gain);
4204
4205#undef SAVE_RF_MAX
4206#undef SAVE_PHY_MAX
4207}
4208
4209static void
4210bwi_rf_init(struct bwi_mac *mac)
4211{
4212	struct bwi_rf *rf = &mac->mac_rf;
4213
4214	if (rf->rf_type == BWI_RF_T_BCM2060) {
4215		/* TODO: 11A */
4216	} else {
4217		if (rf->rf_flags & BWI_RF_F_INITED)
4218			RF_WRITE(mac, 0x78, rf->rf_calib);
4219		else
4220			bwi_rf_init_bcm2050(mac);
4221	}
4222}
4223
4224static void
4225bwi_rf_off_11a(struct bwi_mac *mac)
4226{
4227	RF_WRITE(mac, 0x4, 0xff);
4228	RF_WRITE(mac, 0x5, 0xfb);
4229
4230	PHY_SETBITS(mac, 0x10, 0x8);
4231	PHY_SETBITS(mac, 0x11, 0x8);
4232
4233	PHY_WRITE(mac, 0x15, 0xaa00);
4234}
4235
4236static void
4237bwi_rf_off_11bg(struct bwi_mac *mac)
4238{
4239	PHY_WRITE(mac, 0x15, 0xaa00);
4240}
4241
4242static void
4243bwi_rf_off_11g_rev5(struct bwi_mac *mac)
4244{
4245	PHY_SETBITS(mac, 0x811, 0x8c);
4246	PHY_CLRBITS(mac, 0x812, 0x8c);
4247}
4248
4249static void
4250bwi_rf_workaround(struct bwi_mac *mac, uint chan)
4251{
4252	struct bwi_softc *sc = mac->mac_sc;
4253	struct bwi_rf *rf = &mac->mac_rf;
4254
4255	if (chan == IEEE80211_CHAN_ANY) {
4256		aprint_error_dev(sc->sc_dev, "%s invalid channel!\n",
4257		    __func__);
4258		return;
4259	}
4260
4261	if (rf->rf_type != BWI_RF_T_BCM2050 || rf->rf_rev >= 6)
4262		return;
4263
4264	if (chan <= 10)
4265		CSR_WRITE_2(sc, BWI_RF_CHAN, BWI_RF_2GHZ_CHAN(chan + 4));
4266	else
4267		CSR_WRITE_2(sc, BWI_RF_CHAN, BWI_RF_2GHZ_CHAN(1));
4268	DELAY(1000);
4269	CSR_WRITE_2(sc, BWI_RF_CHAN, BWI_RF_2GHZ_CHAN(chan));
4270}
4271
4272static struct bwi_rf_lo *
4273bwi_rf_lo_find(struct bwi_mac *mac, const struct bwi_tpctl *tpctl)
4274{
4275	uint16_t rf_atten, bbp_atten;
4276	int remap_rf_atten;
4277
4278	remap_rf_atten = 1;
4279	if (tpctl == NULL) {
4280		bbp_atten = 2;
4281		rf_atten = 3;
4282	} else {
4283		if (tpctl->tp_ctrl1 == 3)
4284			remap_rf_atten = 0;
4285
4286		bbp_atten = tpctl->bbp_atten;
4287		rf_atten = tpctl->rf_atten;
4288
4289		if (bbp_atten > 6)
4290			bbp_atten = 6;
4291	}
4292
4293	if (remap_rf_atten) {
4294#define MAP_MAX	10
4295		static const uint16_t map[MAP_MAX] =
4296		    { 11, 10, 11, 12, 13, 12, 13, 12, 13, 12 };
4297#if 0
4298		KASSERT(rf_atten < MAP_MAX);
4299		rf_atten = map[rf_atten];
4300#else
4301		if (rf_atten >= MAP_MAX) {
4302			rf_atten = 0;	/* XXX */
4303		} else {
4304			rf_atten = map[rf_atten];
4305		}
4306#endif
4307#undef MAP_MAX
4308	}
4309
4310	return (bwi_get_rf_lo(mac, rf_atten, bbp_atten));
4311}
4312
4313static void
4314bwi_rf_lo_adjust(struct bwi_mac *mac, const struct bwi_tpctl *tpctl)
4315{
4316	const struct bwi_rf_lo *lo;
4317
4318	lo = bwi_rf_lo_find(mac, tpctl);
4319	RF_LO_WRITE(mac, lo);
4320}
4321
4322static void
4323bwi_rf_lo_write(struct bwi_mac *mac, const struct bwi_rf_lo *lo)
4324{
4325	uint16_t val;
4326
4327	val = (uint8_t)lo->ctrl_lo;
4328	val |= ((uint8_t)lo->ctrl_hi) << 8;
4329
4330	PHY_WRITE(mac, BWI_PHYR_RF_LO, val);
4331}
4332
4333static int
4334bwi_rf_gain_max_reached(struct bwi_mac *mac, int idx)
4335{
4336	PHY_FILT_SETBITS(mac, 0x812, 0xf0ff, idx << 8);
4337	PHY_FILT_SETBITS(mac, 0x15, 0xfff, 0xa000);
4338	PHY_SETBITS(mac, 0x15, 0xf000);
4339
4340	DELAY(20);
4341
4342	return ((PHY_READ(mac, 0x2d) >= 0xdfc));
4343}
4344
4345/* XXX use bitmap array */
4346static uint16_t
4347bwi_bitswap4(uint16_t val)
4348{
4349	uint16_t ret;
4350
4351	ret = (val & 0x8) >> 3;
4352	ret |= (val & 0x4) >> 1;
4353	ret |= (val & 0x2) << 1;
4354	ret |= (val & 0x1) << 3;
4355
4356	return (ret);
4357}
4358
4359static uint16_t
4360bwi_phy812_value(struct bwi_mac *mac, uint16_t lpd)
4361{
4362	struct bwi_softc *sc = mac->mac_sc;
4363	struct bwi_phy *phy = &mac->mac_phy;
4364	struct bwi_rf *rf = &mac->mac_rf;
4365	uint16_t lo_gain, ext_lna, loop;
4366
4367	if ((phy->phy_flags & BWI_PHY_F_LINKED) == 0)
4368		return (0);
4369
4370	lo_gain = rf->rf_lo_gain;
4371	if (rf->rf_rev == 8)
4372		lo_gain += 0x3e;
4373	else
4374		lo_gain += 0x26;
4375
4376	if (lo_gain >= 0x46) {
4377		lo_gain -= 0x46;
4378		ext_lna = 0x3000;
4379	} else if (lo_gain >= 0x3a) {
4380		lo_gain -= 0x3a;
4381		ext_lna = 0x1000;
4382	} else if (lo_gain >= 0x2e) {
4383		lo_gain -= 0x2e;
4384		ext_lna = 0x2000;
4385	} else {
4386		lo_gain -= 0x10;
4387		ext_lna = 0;
4388	}
4389
4390	for (loop = 0; loop < 16; ++loop) {
4391		lo_gain -= (6 * loop);
4392		if (lo_gain < 6)
4393			break;
4394	}
4395
4396	if (phy->phy_rev >= 7 && (sc->sc_card_flags & BWI_CARD_F_EXT_LNA)) {
4397		if (ext_lna)
4398			ext_lna |= 0x8000;
4399		ext_lna |= (loop << 8);
4400		switch (lpd) {
4401		case 0x011:
4402			return (0x8f92);
4403		case 0x001:
4404			return (0x8092 | ext_lna);
4405		case 0x101:
4406			return (0x2092 | ext_lna);
4407		case 0x100:
4408			return (0x2093 | ext_lna);
4409		default:
4410			panic("unsupported lpd\n");
4411		}
4412	} else {
4413		ext_lna |= (loop << 8);
4414		switch (lpd) {
4415		case 0x011:
4416			return (0xf92);
4417		case 0x001:
4418		case 0x101:
4419			return (0x92 | ext_lna);
4420		case 0x100:
4421			return (0x93 | ext_lna);
4422		default:
4423			panic("unsupported lpd\n");
4424		}
4425	}
4426
4427	panic("never reached\n");
4428	return (0);
4429}
4430
4431static void
4432bwi_rf_init_bcm2050(struct bwi_mac *mac)
4433{
4434#define SAVE_RF_MAX		3
4435#define SAVE_PHY_COMM_MAX	4
4436#define SAVE_PHY_11G_MAX	6
4437	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
4438	    { 0x0043, 0x0051, 0x0052 };
4439	static const uint16_t save_phy_regs_comm[SAVE_PHY_COMM_MAX] =
4440	    { 0x0015, 0x005a, 0x0059, 0x0058 };
4441	static const uint16_t save_phy_regs_11g[SAVE_PHY_11G_MAX] =
4442	    { 0x0811, 0x0812, 0x0814, 0x0815, 0x0429, 0x0802 };
4443
4444	uint16_t save_rf[SAVE_RF_MAX];
4445	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
4446	uint16_t save_phy_11g[SAVE_PHY_11G_MAX];
4447	uint16_t phyr_35, phyr_30 = 0, rfr_78, phyr_80f = 0, phyr_810 = 0;
4448	uint16_t bphy_ctrl = 0, bbp_atten, rf_chan_ex;
4449	uint16_t phy812_val;
4450	uint16_t calib;
4451	uint32_t test_lim, test;
4452	struct bwi_softc *sc = mac->mac_sc;
4453	struct bwi_phy *phy = &mac->mac_phy;
4454	struct bwi_rf *rf = &mac->mac_rf;
4455	int i;
4456
4457	/*
4458	 * Save registers for later restoring
4459	 */
4460	for (i = 0; i < SAVE_RF_MAX; ++i)
4461		save_rf[i] = RF_READ(mac, save_rf_regs[i]);
4462	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
4463		save_phy_comm[i] = PHY_READ(mac, save_phy_regs_comm[i]);
4464
4465	if (phy->phy_mode == IEEE80211_MODE_11B) {
4466		phyr_30 = PHY_READ(mac, 0x30);
4467		bphy_ctrl = CSR_READ_2(sc, BWI_BPHY_CTRL);
4468
4469		PHY_WRITE(mac, 0x30, 0xff);
4470		CSR_WRITE_2(sc, BWI_BPHY_CTRL, 0x3f3f);
4471	} else if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) {
4472		for (i = 0; i < SAVE_PHY_11G_MAX; ++i) {
4473			save_phy_11g[i] = PHY_READ(mac, save_phy_regs_11g[i]);
4474		}
4475
4476		PHY_SETBITS(mac, 0x814, 0x3);
4477		PHY_CLRBITS(mac, 0x815, 0x3);
4478		PHY_CLRBITS(mac, 0x429, 0x8000);
4479		PHY_CLRBITS(mac, 0x802, 0x3);
4480
4481		phyr_80f = PHY_READ(mac, 0x80f);
4482		phyr_810 = PHY_READ(mac, 0x810);
4483
4484		if (phy->phy_rev >= 3)
4485			PHY_WRITE(mac, 0x80f, 0xc020);
4486		else
4487			PHY_WRITE(mac, 0x80f, 0x8020);
4488		PHY_WRITE(mac, 0x810, 0);
4489
4490		phy812_val = bwi_phy812_value(mac, 0x011);
4491		PHY_WRITE(mac, 0x812, phy812_val);
4492		if (phy->phy_rev < 7 ||
4493		    (sc->sc_card_flags & BWI_CARD_F_EXT_LNA) == 0)
4494			PHY_WRITE(mac, 0x811, 0x1b3);
4495		else
4496			PHY_WRITE(mac, 0x811, 0x9b3);
4497	}
4498	CSR_SETBITS_2(sc, BWI_RF_ANTDIV, 0x8000);
4499
4500	phyr_35 = PHY_READ(mac, 0x35);
4501	PHY_CLRBITS(mac, 0x35, 0x80);
4502
4503	bbp_atten = CSR_READ_2(sc, BWI_BBP_ATTEN);
4504	rf_chan_ex = CSR_READ_2(sc, BWI_RF_CHAN_EX);
4505
4506	if (phy->phy_version == 0) {
4507		CSR_WRITE_2(sc, BWI_BBP_ATTEN, 0x122);
4508	} else {
4509		if (phy->phy_version >= 2)
4510			PHY_FILT_SETBITS(mac, 0x3, 0xffbf, 0x40);
4511		CSR_SETBITS_2(sc, BWI_RF_CHAN_EX, 0x2000);
4512	}
4513
4514	calib = bwi_rf_calibval(mac);
4515
4516	if (phy->phy_mode == IEEE80211_MODE_11B)
4517		RF_WRITE(mac, 0x78, 0x26);
4518
4519	if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) {
4520		phy812_val = bwi_phy812_value(mac, 0x011);
4521		PHY_WRITE(mac, 0x812, phy812_val);
4522	}
4523
4524	PHY_WRITE(mac, 0x15, 0xbfaf);
4525	PHY_WRITE(mac, 0x2b, 0x1403);
4526
4527	if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) {
4528		phy812_val = bwi_phy812_value(mac, 0x001);
4529		PHY_WRITE(mac, 0x812, phy812_val);
4530	}
4531
4532	PHY_WRITE(mac, 0x15, 0xbfa0);
4533
4534	RF_SETBITS(mac, 0x51, 0x4);
4535	if (rf->rf_rev == 8)
4536		RF_WRITE(mac, 0x43, 0x1f);
4537	else {
4538		RF_WRITE(mac, 0x52, 0);
4539		RF_FILT_SETBITS(mac, 0x43, 0xfff0, 0x9);
4540	}
4541
4542	test_lim = 0;
4543	PHY_WRITE(mac, 0x58, 0);
4544	for (i = 0; i < 16; ++i) {
4545		PHY_WRITE(mac, 0x5a, 0x480);
4546		PHY_WRITE(mac, 0x59, 0xc810);
4547
4548		PHY_WRITE(mac, 0x58, 0xd);
4549		if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) {
4550			phy812_val = bwi_phy812_value(mac, 0x101);
4551			PHY_WRITE(mac, 0x812, phy812_val);
4552		}
4553		PHY_WRITE(mac, 0x15, 0xafb0);
4554		DELAY(10);
4555
4556		if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) {
4557			phy812_val = bwi_phy812_value(mac, 0x101);
4558			PHY_WRITE(mac, 0x812, phy812_val);
4559		}
4560		PHY_WRITE(mac, 0x15, 0xefb0);
4561		DELAY(10);
4562
4563		if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) {
4564			phy812_val = bwi_phy812_value(mac, 0x100);
4565			PHY_WRITE(mac, 0x812, phy812_val);
4566		}
4567		PHY_WRITE(mac, 0x15, 0xfff0);
4568		DELAY(20);
4569
4570		test_lim += PHY_READ(mac, 0x2d);
4571
4572		PHY_WRITE(mac, 0x58, 0);
4573		if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) {
4574			phy812_val = bwi_phy812_value(mac, 0x101);
4575			PHY_WRITE(mac, 0x812, phy812_val);
4576		}
4577		PHY_WRITE(mac, 0x15, 0xafb0);
4578	}
4579	++test_lim;
4580	test_lim >>= 9;
4581
4582	DELAY(10);
4583
4584	test = 0;
4585	PHY_WRITE(mac, 0x58, 0);
4586	for (i = 0; i < 16; ++i) {
4587		int j;
4588
4589		rfr_78 = (bwi_bitswap4(i) << 1) | 0x20;
4590		RF_WRITE(mac, 0x78, rfr_78);
4591		DELAY(10);
4592
4593		/* NB: This block is slight different than the above one */
4594		for (j = 0; j < 16; ++j) {
4595			PHY_WRITE(mac, 0x5a, 0xd80);
4596			PHY_WRITE(mac, 0x59, 0xc810);
4597
4598			PHY_WRITE(mac, 0x58, 0xd);
4599			if ((phy->phy_flags & BWI_PHY_F_LINKED) ||
4600			    phy->phy_rev >= 2) {
4601				phy812_val = bwi_phy812_value(mac, 0x101);
4602				PHY_WRITE(mac, 0x812, phy812_val);
4603			}
4604			PHY_WRITE(mac, 0x15, 0xafb0);
4605			DELAY(10);
4606
4607			if ((phy->phy_flags & BWI_PHY_F_LINKED) ||
4608			    phy->phy_rev >= 2) {
4609				phy812_val = bwi_phy812_value(mac, 0x101);
4610				PHY_WRITE(mac, 0x812, phy812_val);
4611			}
4612			PHY_WRITE(mac, 0x15, 0xefb0);
4613			DELAY(10);
4614
4615			if ((phy->phy_flags & BWI_PHY_F_LINKED) ||
4616			    phy->phy_rev >= 2) {
4617				phy812_val = bwi_phy812_value(mac, 0x100);
4618				PHY_WRITE(mac, 0x812, phy812_val);
4619			}
4620			PHY_WRITE(mac, 0x15, 0xfff0);
4621			DELAY(10);
4622
4623			test += PHY_READ(mac, 0x2d);
4624
4625			PHY_WRITE(mac, 0x58, 0);
4626			if ((phy->phy_flags & BWI_PHY_F_LINKED) ||
4627			    phy->phy_rev >= 2) {
4628				phy812_val = bwi_phy812_value(mac, 0x101);
4629				PHY_WRITE(mac, 0x812, phy812_val);
4630			}
4631			PHY_WRITE(mac, 0x15, 0xafb0);
4632		}
4633
4634		++test;
4635		test >>= 8;
4636
4637		if (test > test_lim)
4638			break;
4639	}
4640	if (i > 15)
4641		rf->rf_calib = rfr_78;
4642	else
4643		rf->rf_calib = calib;
4644	if (rf->rf_calib != 0xffff) {
4645		DPRINTF(sc, BWI_DBG_RF | BWI_DBG_INIT,
4646		    "RF calibration value: 0x%04x\n", rf->rf_calib);
4647		rf->rf_flags |= BWI_RF_F_INITED;
4648	}
4649
4650	/*
4651	 * Restore trashes registers
4652	 */
4653	PHY_WRITE(mac, save_phy_regs_comm[0], save_phy_comm[0]);
4654
4655	for (i = 0; i < SAVE_RF_MAX; ++i) {
4656		int pos = (i + 1) % SAVE_RF_MAX;
4657
4658		RF_WRITE(mac, save_rf_regs[pos], save_rf[pos]);
4659	}
4660	for (i = 1; i < SAVE_PHY_COMM_MAX; ++i)
4661		PHY_WRITE(mac, save_phy_regs_comm[i], save_phy_comm[i]);
4662
4663	CSR_WRITE_2(sc, BWI_BBP_ATTEN, bbp_atten);
4664	if (phy->phy_version != 0)
4665		CSR_WRITE_2(sc, BWI_RF_CHAN_EX, rf_chan_ex);
4666
4667	PHY_WRITE(mac, 0x35, phyr_35);
4668	bwi_rf_workaround(mac, rf->rf_curchan);
4669
4670	if (phy->phy_mode == IEEE80211_MODE_11B) {
4671		PHY_WRITE(mac, 0x30, phyr_30);
4672		CSR_WRITE_2(sc, BWI_BPHY_CTRL, bphy_ctrl);
4673	} else if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) {
4674		/* XXX Spec only says when PHY is linked (gmode) */
4675		CSR_CLRBITS_2(sc, BWI_RF_ANTDIV, 0x8000);
4676
4677		for (i = 0; i < SAVE_PHY_11G_MAX; ++i) {
4678			PHY_WRITE(mac, save_phy_regs_11g[i],
4679			    save_phy_11g[i]);
4680		}
4681
4682		PHY_WRITE(mac, 0x80f, phyr_80f);
4683		PHY_WRITE(mac, 0x810, phyr_810);
4684	}
4685
4686#undef SAVE_PHY_11G_MAX
4687#undef SAVE_PHY_COMM_MAX
4688#undef SAVE_RF_MAX
4689}
4690
4691static uint16_t
4692bwi_rf_calibval(struct bwi_mac *mac)
4693{
4694	/* http://bcm-specs.sipsolutions.net/RCCTable */
4695	static const uint16_t rf_calibvals[] = {
4696	    0x2, 0x3, 0x1, 0xf, 0x6, 0x7, 0x5, 0xf,
4697	    0xa, 0xb, 0x9, 0xf, 0xe, 0xf, 0xd, 0xf
4698	};
4699
4700	uint16_t val, calib;
4701	int idx;
4702
4703	val = RF_READ(mac, BWI_RFR_BBP_ATTEN);
4704	idx = __SHIFTOUT(val, BWI_RFR_BBP_ATTEN_CALIB_IDX);
4705	KASSERT(idx < (int)(sizeof(rf_calibvals) / sizeof(rf_calibvals[0])));
4706
4707	calib = rf_calibvals[idx] << 1;
4708	if (val & BWI_RFR_BBP_ATTEN_CALIB_BIT)
4709		calib |= 0x1;
4710	calib |= 0x20;
4711
4712	return (calib);
4713}
4714
4715static int32_t
4716_bwi_adjust_devide(int32_t num, int32_t den)
4717{
4718	if (num < 0)
4719		return (num / den);
4720	else
4721		return ((num + den / 2) / den);
4722}
4723
4724/*
4725 * http://bcm-specs.sipsolutions.net/TSSI_to_DBM_Table
4726 * "calculating table entries"
4727 */
4728static int
4729bwi_rf_calc_txpower(int8_t *txpwr, uint8_t idx, const int16_t pa_params[])
4730{
4731	int32_t m1, m2, f, dbm;
4732	int i;
4733
4734	m1 = _bwi_adjust_devide(16 * pa_params[0] + idx * pa_params[1], 32);
4735	m2 = imax(_bwi_adjust_devide(32768 + idx * pa_params[2], 256), 1);
4736
4737#define ITER_MAX	16
4738	f = 256;
4739	for (i = 0; i < ITER_MAX; ++i) {
4740		int32_t q, d;
4741
4742		q = _bwi_adjust_devide(
4743		    f * 4096 - _bwi_adjust_devide(m2 * f, 16) * f, 2048);
4744		d = abs(q - f);
4745		f = q;
4746
4747		if (d < 2)
4748			break;
4749	}
4750	if (i == ITER_MAX)
4751		return (EINVAL);
4752#undef ITER_MAX
4753
4754	dbm = _bwi_adjust_devide(m1 * f, 8192);
4755	if (dbm < -127)
4756		dbm = -127;
4757	else if (dbm > 128)
4758		dbm = 128;
4759
4760	*txpwr = dbm;
4761
4762	return (0);
4763}
4764
4765static int
4766bwi_rf_map_txpower(struct bwi_mac *mac)
4767{
4768	struct bwi_softc *sc = mac->mac_sc;
4769	struct bwi_rf *rf = &mac->mac_rf;
4770	struct bwi_phy *phy = &mac->mac_phy;
4771	uint16_t sprom_ofs, val, mask;
4772	int16_t pa_params[3];
4773	int error = 0, i, ant_gain, reg_txpower_max;
4774#ifdef BWI_DEBUG
4775	int debug = sc->sc_debug &
4776	    (BWI_DBG_RF | BWI_DBG_TXPOWER | BWI_DBG_ATTACH);
4777#endif
4778
4779	/*
4780	 * Find out max TX power
4781	 */
4782	val = bwi_read_sprom(sc, BWI_SPROM_MAX_TXPWR);
4783	if (phy->phy_mode == IEEE80211_MODE_11A) {
4784		rf->rf_txpower_max = __SHIFTOUT(val,
4785		    BWI_SPROM_MAX_TXPWR_MASK_11A);
4786	} else {
4787		rf->rf_txpower_max = __SHIFTOUT(val,
4788		    BWI_SPROM_MAX_TXPWR_MASK_11BG);
4789
4790		if ((sc->sc_card_flags & BWI_CARD_F_PA_GPIO9) &&
4791		    phy->phy_mode == IEEE80211_MODE_11G)
4792			rf->rf_txpower_max -= 3;
4793	}
4794	if (rf->rf_txpower_max <= 0) {
4795		aprint_error_dev(sc->sc_dev,
4796		    "invalid max txpower in sprom\n");
4797		rf->rf_txpower_max = 74;
4798	}
4799	DPRINTF(sc, BWI_DBG_RF | BWI_DBG_TXPOWER | BWI_DBG_ATTACH,
4800	    "max txpower from sprom: %d dBm\n", rf->rf_txpower_max);
4801
4802	/*
4803	 * Find out region/domain max TX power, which is adjusted
4804	 * by antenna gain and 1.5 dBm fluctuation as mentioned
4805	 * in v3 spec.
4806	 */
4807	val = bwi_read_sprom(sc, BWI_SPROM_ANT_GAIN);
4808	if (phy->phy_mode == IEEE80211_MODE_11A)
4809		ant_gain = __SHIFTOUT(val, BWI_SPROM_ANT_GAIN_MASK_11A);
4810	else
4811		ant_gain = __SHIFTOUT(val, BWI_SPROM_ANT_GAIN_MASK_11BG);
4812	if (ant_gain == 0xff) {
4813		/* XXX why this always invalid? */
4814		aprint_error_dev(sc->sc_dev,
4815		    "invalid antenna gain in sprom\n");
4816		ant_gain = 2;
4817	}
4818	ant_gain *= 4;
4819	DPRINTF(sc, BWI_DBG_RF | BWI_DBG_TXPOWER | BWI_DBG_ATTACH,
4820	    "ant gain %d dBm\n", ant_gain);
4821
4822	reg_txpower_max = 90 - ant_gain - 6;	/* XXX magic number */
4823	DPRINTF(sc, BWI_DBG_RF | BWI_DBG_TXPOWER | BWI_DBG_ATTACH,
4824	    "region/domain max txpower %d dBm\n", reg_txpower_max);
4825
4826	/*
4827	 * Force max TX power within region/domain TX power limit
4828	 */
4829	if (rf->rf_txpower_max > reg_txpower_max)
4830		rf->rf_txpower_max = reg_txpower_max;
4831	DPRINTF(sc, BWI_DBG_RF | BWI_DBG_TXPOWER | BWI_DBG_ATTACH,
4832	    "max txpower %d dBm\n", rf->rf_txpower_max);
4833
4834	/*
4835	 * Create TSSI to TX power mapping
4836	 */
4837
4838	if (sc->sc_bbp_id == BWI_BBPID_BCM4301 &&
4839	    rf->rf_type != BWI_RF_T_BCM2050) {
4840		rf->rf_idle_tssi0 = BWI_DEFAULT_IDLE_TSSI;
4841		memcpy(rf->rf_txpower_map0, bwi_txpower_map_11b,
4842		      sizeof(rf->rf_txpower_map0));
4843		goto back;
4844	}
4845
4846#define IS_VALID_PA_PARAM(p)	((p) != 0 && (p) != -1)
4847	/*
4848	 * Extract PA parameters
4849	 */
4850	if (phy->phy_mode == IEEE80211_MODE_11A)
4851		sprom_ofs = BWI_SPROM_PA_PARAM_11A;
4852	else
4853		sprom_ofs = BWI_SPROM_PA_PARAM_11BG;
4854	for (i = 0; i < __arraycount(pa_params); ++i)
4855		pa_params[i] = (int16_t)bwi_read_sprom(sc, sprom_ofs + (i * 2));
4856
4857	for (i = 0; i < __arraycount(pa_params); ++i) {
4858		/*
4859		 * If one of the PA parameters from SPROM is not valid,
4860		 * fall back to the default values, if there are any.
4861		 */
4862		if (!IS_VALID_PA_PARAM(pa_params[i])) {
4863			const int8_t *txpower_map;
4864
4865			if (phy->phy_mode == IEEE80211_MODE_11A) {
4866				aprint_error_dev(sc->sc_dev,
4867				    "no tssi2dbm table for 11a PHY\n");
4868				return (ENXIO);
4869			}
4870
4871			if (phy->phy_mode == IEEE80211_MODE_11G) {
4872				DPRINTF(sc,
4873				    BWI_DBG_RF | BWI_DBG_TXPOWER |
4874					BWI_DBG_ATTACH,
4875				    "use default 11g TSSI map\n");
4876				txpower_map = bwi_txpower_map_11g;
4877			} else {
4878				DPRINTF(sc,
4879				    BWI_DBG_RF | BWI_DBG_TXPOWER |
4880					BWI_DBG_ATTACH,
4881				    "use default 11b TSSI map\n");
4882				txpower_map = bwi_txpower_map_11b;
4883			}
4884
4885			rf->rf_idle_tssi0 = BWI_DEFAULT_IDLE_TSSI;
4886			memcpy(rf->rf_txpower_map0, txpower_map,
4887			      sizeof(rf->rf_txpower_map0));
4888			goto back;
4889		}
4890	}
4891
4892	/*
4893	 * All of the PA parameters from SPROM are valid.
4894	 */
4895
4896	/*
4897	 * Extract idle TSSI from SPROM.
4898	 */
4899	val = bwi_read_sprom(sc, BWI_SPROM_IDLE_TSSI);
4900	DPRINTF(sc, BWI_DBG_RF | BWI_DBG_TXPOWER | BWI_DBG_ATTACH,
4901	    "sprom idle tssi: 0x%04x\n", val);
4902
4903	if (phy->phy_mode == IEEE80211_MODE_11A)
4904		mask = BWI_SPROM_IDLE_TSSI_MASK_11A;
4905	else
4906		mask = BWI_SPROM_IDLE_TSSI_MASK_11BG;
4907
4908	rf->rf_idle_tssi0 = (int)__SHIFTOUT(val, mask);
4909	if (!IS_VALID_PA_PARAM(rf->rf_idle_tssi0))
4910		rf->rf_idle_tssi0 = 62;
4911
4912#undef IS_VALID_PA_PARAM
4913
4914	/*
4915	 * Calculate TX power map, which is indexed by TSSI
4916	 */
4917	DPRINTF(sc, BWI_DBG_RF | BWI_DBG_TXPOWER | BWI_DBG_ATTACH,
4918	    "TSSI-TX power map:\n");
4919	for (i = 0; i < BWI_TSSI_MAX; ++i) {
4920		error = bwi_rf_calc_txpower(&rf->rf_txpower_map0[i], i,
4921					    pa_params);
4922		if (error) {
4923			aprint_error_dev(sc->sc_dev,
4924			    "bwi_rf_calc_txpower failed\n");
4925			break;
4926		}
4927#ifdef BWI_DEBUG
4928		if (debug) {
4929			if (i % 8 == 0) {
4930				if (i != 0)
4931					aprint_debug("\n");
4932				aprint_debug_dev(sc->sc_dev, "");
4933			}
4934			aprint_debug(" %d", rf->rf_txpower_map0[i]);
4935		}
4936#endif
4937	}
4938#ifdef BWI_DEBUG
4939	if (debug)
4940		aprint_debug("\n");
4941#endif
4942back:
4943	DPRINTF(sc, BWI_DBG_RF | BWI_DBG_TXPOWER | BWI_DBG_ATTACH,
4944	    "idle tssi0: %d\n", rf->rf_idle_tssi0);
4945
4946	return (error);
4947}
4948
4949static void
4950bwi_rf_lo_update_11g(struct bwi_mac *mac)
4951{
4952	struct bwi_softc *sc = mac->mac_sc;
4953	struct ifnet *ifp = &sc->sc_if;
4954	struct bwi_rf *rf = &mac->mac_rf;
4955	struct bwi_phy *phy = &mac->mac_phy;
4956	struct bwi_tpctl *tpctl = &mac->mac_tpctl;
4957	struct rf_saveregs regs;
4958	uint16_t ant_div, chan_ex;
4959	uint8_t devi_ctrl;
4960	uint orig_chan;
4961
4962	DPRINTF(sc, BWI_DBG_RF | BWI_DBG_INIT, "%s enter\n", __func__);
4963
4964	/*
4965	 * Save RF/PHY registers for later restoration
4966	 */
4967	orig_chan = rf->rf_curchan;
4968	memset(&regs, 0, sizeof(regs));
4969
4970	if (phy->phy_flags & BWI_PHY_F_LINKED) {
4971		SAVE_PHY_REG(mac, &regs, 429);
4972		SAVE_PHY_REG(mac, &regs, 802);
4973
4974		PHY_WRITE(mac, 0x429, regs.phy_429 & 0x7fff);
4975		PHY_WRITE(mac, 0x802, regs.phy_802 & 0xfffc);
4976	}
4977
4978	ant_div = CSR_READ_2(sc, BWI_RF_ANTDIV);
4979	CSR_WRITE_2(sc, BWI_RF_ANTDIV, ant_div | 0x8000);
4980	chan_ex = CSR_READ_2(sc, BWI_RF_CHAN_EX);
4981
4982	SAVE_PHY_REG(mac, &regs, 15);
4983	SAVE_PHY_REG(mac, &regs, 2a);
4984	SAVE_PHY_REG(mac, &regs, 35);
4985	SAVE_PHY_REG(mac, &regs, 60);
4986	SAVE_RF_REG(mac, &regs, 43);
4987	SAVE_RF_REG(mac, &regs, 7a);
4988	SAVE_RF_REG(mac, &regs, 52);
4989	if (phy->phy_flags & BWI_PHY_F_LINKED) {
4990		SAVE_PHY_REG(mac, &regs, 811);
4991		SAVE_PHY_REG(mac, &regs, 812);
4992		SAVE_PHY_REG(mac, &regs, 814);
4993		SAVE_PHY_REG(mac, &regs, 815);
4994	}
4995
4996	/* Force to channel 6 */
4997	bwi_rf_set_chan(mac, 6, 0);
4998
4999	if (phy->phy_flags & BWI_PHY_F_LINKED) {
5000		PHY_WRITE(mac, 0x429, regs.phy_429 & 0x7fff);
5001		PHY_WRITE(mac, 0x802, regs.phy_802 & 0xfffc);
5002		bwi_mac_dummy_xmit(mac);
5003	}
5004	RF_WRITE(mac, 0x43, 0x6);
5005
5006	bwi_phy_set_bbp_atten(mac, 2);
5007
5008	CSR_WRITE_2(sc, BWI_RF_CHAN_EX, 0);
5009
5010	PHY_WRITE(mac, 0x2e, 0x7f);
5011	PHY_WRITE(mac, 0x80f, 0x78);
5012	PHY_WRITE(mac, 0x35, regs.phy_35 & 0xff7f);
5013	RF_WRITE(mac, 0x7a, regs.rf_7a & 0xfff0);
5014	PHY_WRITE(mac, 0x2b, 0x203);
5015	PHY_WRITE(mac, 0x2a, 0x8a3);
5016
5017	if (phy->phy_flags & BWI_PHY_F_LINKED) {
5018		PHY_WRITE(mac, 0x814, regs.phy_814 | 0x3);
5019		PHY_WRITE(mac, 0x815, regs.phy_815 & 0xfffc);
5020		PHY_WRITE(mac, 0x811, 0x1b3);
5021		PHY_WRITE(mac, 0x812, 0xb2);
5022	}
5023
5024	if ((ifp->if_flags & IFF_RUNNING) == 0)
5025		tpctl->tp_ctrl2 = bwi_rf_get_tp_ctrl2(mac);
5026	PHY_WRITE(mac, 0x80f, 0x8078);
5027
5028	/*
5029	 * Measure all RF LO
5030	 */
5031	devi_ctrl = _bwi_rf_lo_update_11g(mac, regs.rf_7a);
5032
5033	/*
5034	 * Restore saved RF/PHY registers
5035	 */
5036	if (phy->phy_flags & BWI_PHY_F_LINKED) {
5037		PHY_WRITE(mac, 0x15, 0xe300);
5038		PHY_WRITE(mac, 0x812, (devi_ctrl << 8) | 0xa0);
5039		DELAY(5);
5040		PHY_WRITE(mac, 0x812, (devi_ctrl << 8) | 0xa2);
5041		DELAY(2);
5042		PHY_WRITE(mac, 0x812, (devi_ctrl << 8) | 0xa3);
5043	} else
5044		PHY_WRITE(mac, 0x15, devi_ctrl | 0xefa0);
5045
5046	if ((ifp->if_flags & IFF_RUNNING) == 0)
5047		tpctl = NULL;
5048	bwi_rf_lo_adjust(mac, tpctl);
5049
5050	PHY_WRITE(mac, 0x2e, 0x807f);
5051	if (phy->phy_flags & BWI_PHY_F_LINKED)
5052		PHY_WRITE(mac, 0x2f, 0x202);
5053	else
5054		PHY_WRITE(mac, 0x2f, 0x101);
5055
5056	CSR_WRITE_2(sc, BWI_RF_CHAN_EX, chan_ex);
5057
5058	RESTORE_PHY_REG(mac, &regs, 15);
5059	RESTORE_PHY_REG(mac, &regs, 2a);
5060	RESTORE_PHY_REG(mac, &regs, 35);
5061	RESTORE_PHY_REG(mac, &regs, 60);
5062
5063	RESTORE_RF_REG(mac, &regs, 43);
5064	RESTORE_RF_REG(mac, &regs, 7a);
5065
5066	regs.rf_52 &= 0xf0;
5067	regs.rf_52 |= (RF_READ(mac, 0x52) & 0xf);
5068	RF_WRITE(mac, 0x52, regs.rf_52);
5069
5070	CSR_WRITE_2(sc, BWI_RF_ANTDIV, ant_div);
5071
5072	if (phy->phy_flags & BWI_PHY_F_LINKED) {
5073		RESTORE_PHY_REG(mac, &regs, 811);
5074		RESTORE_PHY_REG(mac, &regs, 812);
5075		RESTORE_PHY_REG(mac, &regs, 814);
5076		RESTORE_PHY_REG(mac, &regs, 815);
5077		RESTORE_PHY_REG(mac, &regs, 429);
5078		RESTORE_PHY_REG(mac, &regs, 802);
5079	}
5080
5081	bwi_rf_set_chan(mac, orig_chan, 1);
5082}
5083
5084static uint32_t
5085bwi_rf_lo_devi_measure(struct bwi_mac *mac, uint16_t ctrl)
5086{
5087	struct bwi_phy *phy = &mac->mac_phy;
5088	uint32_t devi = 0;
5089	int i;
5090
5091	if (phy->phy_flags & BWI_PHY_F_LINKED)
5092		ctrl <<= 8;
5093
5094	for (i = 0; i < 8; ++i) {
5095		if (phy->phy_flags & BWI_PHY_F_LINKED) {
5096			PHY_WRITE(mac, 0x15, 0xe300);
5097			PHY_WRITE(mac, 0x812, ctrl | 0xb0);
5098			DELAY(5);
5099			PHY_WRITE(mac, 0x812, ctrl | 0xb2);
5100			DELAY(2);
5101			PHY_WRITE(mac, 0x812, ctrl | 0xb3);
5102			DELAY(4);
5103			PHY_WRITE(mac, 0x15, 0xf300);
5104		} else {
5105			PHY_WRITE(mac, 0x15, ctrl | 0xefa0);
5106			DELAY(2);
5107			PHY_WRITE(mac, 0x15, ctrl | 0xefe0);
5108			DELAY(4);
5109			PHY_WRITE(mac, 0x15, ctrl | 0xffe0);
5110		}
5111		DELAY(8);
5112		devi += PHY_READ(mac, 0x2d);
5113	}
5114
5115	return (devi);
5116}
5117
5118static uint16_t
5119bwi_rf_get_tp_ctrl2(struct bwi_mac *mac)
5120{
5121	uint32_t devi_min;
5122	uint16_t tp_ctrl2 = 0;
5123	int i;
5124
5125	RF_WRITE(mac, 0x52, 0);
5126	DELAY(10);
5127	devi_min = bwi_rf_lo_devi_measure(mac, 0);
5128
5129	for (i = 0; i < 16; ++i) {
5130		uint32_t devi;
5131
5132		RF_WRITE(mac, 0x52, i);
5133		DELAY(10);
5134		devi = bwi_rf_lo_devi_measure(mac, 0);
5135
5136		if (devi < devi_min) {
5137			devi_min = devi;
5138			tp_ctrl2 = i;
5139		}
5140	}
5141
5142	return (tp_ctrl2);
5143}
5144
5145static uint8_t
5146_bwi_rf_lo_update_11g(struct bwi_mac *mac, uint16_t orig_rf7a)
5147{
5148#define RF_ATTEN_LISTSZ	14
5149#define BBP_ATTEN_MAX	4	/* half */
5150	static const int rf_atten_list[RF_ATTEN_LISTSZ] =
5151	    { 3, 1, 5, 7, 9, 2, 0, 4, 6, 8, 1, 2, 3, 4 };
5152	static const int rf_atten_init_list[RF_ATTEN_LISTSZ] =
5153            { 0, 3, 1, 5, 7, 3, 2, 0, 4, 6, -1, -1, -1, -1 };
5154	static const int rf_lo_measure_order[RF_ATTEN_LISTSZ] =
5155	    { 3, 1, 5, 7, 9, 2, 0, 4, 6, 8, 10, 11, 12, 13 };
5156
5157	struct ifnet *ifp = &mac->mac_sc->sc_if;
5158	struct bwi_rf_lo lo_save, *lo;
5159	uint8_t devi_ctrl = 0;
5160	int idx, adj_rf7a = 0;
5161
5162	memset(&lo_save, 0, sizeof(lo_save));
5163	for (idx = 0; idx < RF_ATTEN_LISTSZ; ++idx) {
5164		int init_rf_atten = rf_atten_init_list[idx];
5165		int rf_atten = rf_atten_list[idx];
5166		int bbp_atten;
5167
5168		for (bbp_atten = 0; bbp_atten < BBP_ATTEN_MAX; ++bbp_atten) {
5169			uint16_t tp_ctrl2, rf7a;
5170
5171			if ((ifp->if_flags & IFF_RUNNING) == 0) {
5172				if (idx == 0) {
5173					memset(&lo_save, 0, sizeof(lo_save));
5174				} else if (init_rf_atten < 0) {
5175					lo = bwi_get_rf_lo(mac,
5176					    rf_atten, 2 * bbp_atten);
5177					memcpy(&lo_save, lo, sizeof(lo_save));
5178				} else {
5179					lo = bwi_get_rf_lo(mac,
5180					    init_rf_atten, 0);
5181					memcpy(&lo_save, lo, sizeof(lo_save));
5182				}
5183
5184				devi_ctrl = 0;
5185				adj_rf7a = 0;
5186
5187				/*
5188				 * XXX
5189				 * Linux driver overflows 'val'
5190				 */
5191				if (init_rf_atten >= 0) {
5192					int val;
5193
5194					val = rf_atten * 2 + bbp_atten;
5195					if (val > 14) {
5196						adj_rf7a = 1;
5197						if (val > 17)
5198							devi_ctrl = 1;
5199						if (val > 19)
5200							devi_ctrl = 2;
5201					}
5202				}
5203			} else {
5204				lo = bwi_get_rf_lo(mac,
5205					rf_atten, 2 * bbp_atten);
5206				if (!bwi_rf_lo_isused(mac, lo))
5207					continue;
5208				memcpy(&lo_save, lo, sizeof(lo_save));
5209
5210				devi_ctrl = 3;
5211				adj_rf7a = 0;
5212			}
5213
5214			RF_WRITE(mac, BWI_RFR_ATTEN, rf_atten);
5215
5216			tp_ctrl2 = mac->mac_tpctl.tp_ctrl2;
5217			if (init_rf_atten < 0)
5218				tp_ctrl2 |= (3 << 4);
5219			RF_WRITE(mac, BWI_RFR_TXPWR, tp_ctrl2);
5220
5221			DELAY(10);
5222
5223			bwi_phy_set_bbp_atten(mac, bbp_atten * 2);
5224
5225			rf7a = orig_rf7a & 0xfff0;
5226			if (adj_rf7a)
5227				rf7a |= 0x8;
5228			RF_WRITE(mac, 0x7a, rf7a);
5229
5230			lo = bwi_get_rf_lo(mac,
5231				rf_lo_measure_order[idx], bbp_atten * 2);
5232			bwi_rf_lo_measure_11g(mac, &lo_save, lo, devi_ctrl);
5233		}
5234	}
5235
5236	return (devi_ctrl);
5237
5238#undef RF_ATTEN_LISTSZ
5239#undef BBP_ATTEN_MAX
5240}
5241
5242static void
5243bwi_rf_lo_measure_11g(struct bwi_mac *mac, const struct bwi_rf_lo *src_lo,
5244    struct bwi_rf_lo *dst_lo, uint8_t devi_ctrl)
5245{
5246#define LO_ADJUST_MIN	1
5247#define LO_ADJUST_MAX	8
5248#define LO_ADJUST(hi, lo)	{ .ctrl_hi = hi, .ctrl_lo = lo }
5249	static const struct bwi_rf_lo rf_lo_adjust[LO_ADJUST_MAX] = {
5250		LO_ADJUST(1,	1),
5251		LO_ADJUST(1,	0),
5252		LO_ADJUST(1,	-1),
5253		LO_ADJUST(0,	-1),
5254		LO_ADJUST(-1,	-1),
5255		LO_ADJUST(-1,	0),
5256		LO_ADJUST(-1,	1),
5257		LO_ADJUST(0,	1)
5258	};
5259#undef LO_ADJUST
5260
5261	struct bwi_rf_lo lo_min;
5262	uint32_t devi_min;
5263	int found, loop_count, adjust_state;
5264
5265	memcpy(&lo_min, src_lo, sizeof(lo_min));
5266	RF_LO_WRITE(mac, &lo_min);
5267	devi_min = bwi_rf_lo_devi_measure(mac, devi_ctrl);
5268
5269	loop_count = 12;	/* XXX */
5270	adjust_state = 0;
5271	do {
5272		struct bwi_rf_lo lo_base;
5273		int i, fin;
5274
5275		found = 0;
5276		if (adjust_state == 0) {
5277			i = LO_ADJUST_MIN;
5278			fin = LO_ADJUST_MAX;
5279		} else if (adjust_state % 2 == 0) {
5280			i = adjust_state - 1;
5281			fin = adjust_state + 1;
5282		} else {
5283			i = adjust_state - 2;
5284			fin = adjust_state + 2;
5285		}
5286
5287		if (i < LO_ADJUST_MIN)
5288			i += LO_ADJUST_MAX;
5289		KASSERT(i <= LO_ADJUST_MAX && i >= LO_ADJUST_MIN);
5290
5291		if (fin > LO_ADJUST_MAX)
5292			fin -= LO_ADJUST_MAX;
5293		KASSERT(fin <= LO_ADJUST_MAX && fin >= LO_ADJUST_MIN);
5294
5295		memcpy(&lo_base, &lo_min, sizeof(lo_base));
5296		for (;;) {
5297			struct bwi_rf_lo lo;
5298
5299			lo.ctrl_hi = lo_base.ctrl_hi +
5300				rf_lo_adjust[i - 1].ctrl_hi;
5301			lo.ctrl_lo = lo_base.ctrl_lo +
5302				rf_lo_adjust[i - 1].ctrl_lo;
5303
5304			if (abs(lo.ctrl_lo) < 9 && abs(lo.ctrl_hi) < 9) {
5305				uint32_t devi;
5306
5307				RF_LO_WRITE(mac, &lo);
5308				devi = bwi_rf_lo_devi_measure(mac, devi_ctrl);
5309				if (devi < devi_min) {
5310					devi_min = devi;
5311					adjust_state = i;
5312					found = 1;
5313					memcpy(&lo_min, &lo, sizeof(lo_min));
5314				}
5315			}
5316			if (i == fin)
5317				break;
5318			if (i == LO_ADJUST_MAX)
5319				i = LO_ADJUST_MIN;
5320			else
5321				++i;
5322		}
5323	} while (loop_count-- && found);
5324
5325	memcpy(dst_lo, &lo_min, sizeof(*dst_lo));
5326
5327#undef LO_ADJUST_MIN
5328#undef LO_ADJUST_MAX
5329}
5330
5331static void
5332bwi_rf_calc_nrssi_slope_11b(struct bwi_mac *mac)
5333{
5334#define SAVE_RF_MAX	3
5335#define SAVE_PHY_MAX	8
5336	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
5337	    { 0x7a, 0x52, 0x43 };
5338	static const uint16_t save_phy_regs[SAVE_PHY_MAX] =
5339	    { 0x30, 0x26, 0x15, 0x2a, 0x20, 0x5a, 0x59, 0x58 };
5340
5341	struct bwi_softc *sc = mac->mac_sc;
5342	struct bwi_rf *rf = &mac->mac_rf;
5343	struct bwi_phy *phy = &mac->mac_phy;
5344	uint16_t save_rf[SAVE_RF_MAX];
5345	uint16_t save_phy[SAVE_PHY_MAX];
5346	uint16_t ant_div, chan_ex;
5347	int16_t nrssi[2];
5348	int i;
5349
5350	/*
5351	 * Save RF/PHY registers for later restoration
5352	 */
5353	for (i = 0; i < SAVE_RF_MAX; ++i)
5354		save_rf[i] = RF_READ(mac, save_rf_regs[i]);
5355	for (i = 0; i < SAVE_PHY_MAX; ++i)
5356		save_phy[i] = PHY_READ(mac, save_phy_regs[i]);
5357
5358	ant_div = CSR_READ_2(sc, BWI_RF_ANTDIV);
5359	(void)CSR_READ_2(sc, BWI_BBP_ATTEN);
5360	chan_ex = CSR_READ_2(sc, BWI_RF_CHAN_EX);
5361
5362	/*
5363	 * Calculate nrssi0
5364	 */
5365	if (phy->phy_rev >= 5)
5366		RF_CLRBITS(mac, 0x7a, 0xff80);
5367	else
5368		RF_CLRBITS(mac, 0x7a, 0xfff0);
5369	PHY_WRITE(mac, 0x30, 0xff);
5370
5371	CSR_WRITE_2(sc, BWI_BPHY_CTRL, 0x7f7f);
5372
5373	PHY_WRITE(mac, 0x26, 0);
5374	PHY_SETBITS(mac, 0x15, 0x20);
5375	PHY_WRITE(mac, 0x2a, 0x8a3);
5376	RF_SETBITS(mac, 0x7a, 0x80);
5377
5378	nrssi[0] = (int16_t)PHY_READ(mac, 0x27);
5379
5380	/*
5381	 * Calculate nrssi1
5382	 */
5383	RF_CLRBITS(mac, 0x7a, 0xff80);
5384	if (phy->phy_version >= 2)
5385		CSR_WRITE_2(sc, BWI_BBP_ATTEN, 0x40);
5386	else if (phy->phy_version == 0)
5387		CSR_WRITE_2(sc, BWI_BBP_ATTEN, 0x122);
5388	else
5389		CSR_CLRBITS_2(sc, BWI_RF_CHAN_EX, 0xdfff);
5390
5391	PHY_WRITE(mac, 0x20, 0x3f3f);
5392	PHY_WRITE(mac, 0x15, 0xf330);
5393
5394	RF_WRITE(mac, 0x5a, 0x60);
5395	RF_CLRBITS(mac, 0x43, 0xff0f);
5396
5397	PHY_WRITE(mac, 0x5a, 0x480);
5398	PHY_WRITE(mac, 0x59, 0x810);
5399	PHY_WRITE(mac, 0x58, 0xd);
5400
5401	DELAY(20);
5402
5403	nrssi[1] = (int16_t)PHY_READ(mac, 0x27);
5404
5405	/*
5406	 * Restore saved RF/PHY registers
5407	 */
5408	PHY_WRITE(mac, save_phy_regs[0], save_phy[0]);
5409	RF_WRITE(mac, save_rf_regs[0], save_rf[0]);
5410
5411	CSR_WRITE_2(sc, BWI_RF_ANTDIV, ant_div);
5412
5413	for (i = 1; i < 4; ++i)
5414		PHY_WRITE(mac, save_phy_regs[i], save_phy[i]);
5415
5416	bwi_rf_workaround(mac, rf->rf_curchan);
5417
5418	if (phy->phy_version != 0)
5419		CSR_WRITE_2(sc, BWI_RF_CHAN_EX, chan_ex);
5420
5421	for (; i < SAVE_PHY_MAX; ++i)
5422		PHY_WRITE(mac, save_phy_regs[i], save_phy[i]);
5423
5424	for (i = 1; i < SAVE_RF_MAX; ++i)
5425		RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
5426
5427	/*
5428	 * Install calculated narrow RSSI values
5429	 */
5430	if (nrssi[0] == nrssi[1])
5431		rf->rf_nrssi_slope = 0x10000;
5432	else
5433		rf->rf_nrssi_slope = 0x400000 / (nrssi[0] - nrssi[1]);
5434	if (nrssi[0] <= -4) {
5435		rf->rf_nrssi[0] = nrssi[0];
5436		rf->rf_nrssi[1] = nrssi[1];
5437	}
5438
5439#undef SAVE_RF_MAX
5440#undef SAVE_PHY_MAX
5441}
5442
5443static void
5444bwi_rf_set_nrssi_ofs_11g(struct bwi_mac *mac)
5445{
5446#define SAVE_RF_MAX		2
5447#define SAVE_PHY_COMM_MAX	10
5448#define SAVE_PHY6_MAX		8
5449	static const uint16_t save_rf_regs[SAVE_RF_MAX] = { 0x7a, 0x43 };
5450	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] = {
5451		0x0001, 0x0811, 0x0812, 0x0814,
5452		0x0815, 0x005a, 0x0059, 0x0058,
5453		0x000a, 0x0003
5454	};
5455	static const uint16_t save_phy6_regs[SAVE_PHY6_MAX] = {
5456		0x002e, 0x002f, 0x080f, 0x0810,
5457		0x0801, 0x0060, 0x0014, 0x0478
5458	};
5459
5460	struct bwi_phy *phy = &mac->mac_phy;
5461	uint16_t save_rf[SAVE_RF_MAX];
5462	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
5463	uint16_t save_phy6[SAVE_PHY6_MAX];
5464	uint16_t rf7b = 0xffff;
5465	int16_t nrssi;
5466	int i, phy6_idx = 0;
5467
5468	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
5469		save_phy_comm[i] = PHY_READ(mac, save_phy_comm_regs[i]);
5470	for (i = 0; i < SAVE_RF_MAX; ++i)
5471		save_rf[i] = RF_READ(mac, save_rf_regs[i]);
5472
5473	PHY_CLRBITS(mac, 0x429, 0x8000);
5474	PHY_FILT_SETBITS(mac, 0x1, 0x3fff, 0x4000);
5475	PHY_SETBITS(mac, 0x811, 0xc);
5476	PHY_FILT_SETBITS(mac, 0x812, 0xfff3, 0x4);
5477	PHY_CLRBITS(mac, 0x802, 0x3);
5478
5479	if (phy->phy_rev >= 6) {
5480		for (i = 0; i < SAVE_PHY6_MAX; ++i)
5481			save_phy6[i] = PHY_READ(mac, save_phy6_regs[i]);
5482
5483		PHY_WRITE(mac, 0x2e, 0);
5484		PHY_WRITE(mac, 0x2f, 0);
5485		PHY_WRITE(mac, 0x80f, 0);
5486		PHY_WRITE(mac, 0x810, 0);
5487		PHY_SETBITS(mac, 0x478, 0x100);
5488		PHY_SETBITS(mac, 0x801, 0x40);
5489		PHY_SETBITS(mac, 0x60, 0x40);
5490		PHY_SETBITS(mac, 0x14, 0x200);
5491	}
5492
5493	RF_SETBITS(mac, 0x7a, 0x70);
5494	RF_SETBITS(mac, 0x7a, 0x80);
5495
5496	DELAY(30);
5497
5498	nrssi = bwi_nrssi_11g(mac);
5499	if (nrssi == 31) {
5500		for (i = 7; i >= 4; --i) {
5501			RF_WRITE(mac, 0x7b, i);
5502			DELAY(20);
5503			nrssi = bwi_nrssi_11g(mac);
5504			if (nrssi < 31 && rf7b == 0xffff)
5505				rf7b = i;
5506		}
5507		if (rf7b == 0xffff)
5508			rf7b = 4;
5509	} else {
5510		struct bwi_gains gains;
5511
5512		RF_CLRBITS(mac, 0x7a, 0xff80);
5513
5514		PHY_SETBITS(mac, 0x814, 0x1);
5515		PHY_CLRBITS(mac, 0x815, 0x1);
5516		PHY_SETBITS(mac, 0x811, 0xc);
5517		PHY_SETBITS(mac, 0x812, 0xc);
5518		PHY_SETBITS(mac, 0x811, 0x30);
5519		PHY_SETBITS(mac, 0x812, 0x30);
5520		PHY_WRITE(mac, 0x5a, 0x480);
5521		PHY_WRITE(mac, 0x59, 0x810);
5522		PHY_WRITE(mac, 0x58, 0xd);
5523		if (phy->phy_version == 0)
5524			PHY_WRITE(mac, 0x3, 0x122);
5525		else
5526			PHY_SETBITS(mac, 0xa, 0x2000);
5527		PHY_SETBITS(mac, 0x814, 0x4);
5528		PHY_CLRBITS(mac, 0x815, 0x4);
5529		PHY_FILT_SETBITS(mac, 0x3, 0xff9f, 0x40);
5530		RF_SETBITS(mac, 0x7a, 0xf);
5531
5532		memset(&gains, 0, sizeof(gains));
5533		gains.tbl_gain1 = 3;
5534		gains.tbl_gain2 = 0;
5535		gains.phy_gain = 1;
5536		bwi_set_gains(mac, &gains);
5537
5538		RF_FILT_SETBITS(mac, 0x43, 0xf0, 0xf);
5539		DELAY(30);
5540
5541		nrssi = bwi_nrssi_11g(mac);
5542		if (nrssi == -32) {
5543			for (i = 0; i < 4; ++i) {
5544				RF_WRITE(mac, 0x7b, i);
5545				DELAY(20);
5546				nrssi = bwi_nrssi_11g(mac);
5547				if (nrssi > -31 && rf7b == 0xffff)
5548					rf7b = i;
5549			}
5550			if (rf7b == 0xffff)
5551				rf7b = 3;
5552		} else {
5553			rf7b = 0;
5554		}
5555	}
5556	RF_WRITE(mac, 0x7b, rf7b);
5557
5558	/*
5559	 * Restore saved RF/PHY registers
5560	 */
5561	if (phy->phy_rev >= 6) {
5562		for (phy6_idx = 0; phy6_idx < 4; ++phy6_idx) {
5563			PHY_WRITE(mac, save_phy6_regs[phy6_idx],
5564			    save_phy6[phy6_idx]);
5565		}
5566	}
5567
5568	/* Saved PHY registers 0, 1, 2 are handled later */
5569	for (i = 3; i < SAVE_PHY_COMM_MAX; ++i)
5570		PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
5571
5572	for (i = SAVE_RF_MAX - 1; i >= 0; --i)
5573		RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
5574
5575	PHY_SETBITS(mac, 0x802, 0x3);
5576	PHY_SETBITS(mac, 0x429, 0x8000);
5577
5578	bwi_set_gains(mac, NULL);
5579
5580	if (phy->phy_rev >= 6) {
5581		for (; phy6_idx < SAVE_PHY6_MAX; ++phy6_idx) {
5582			PHY_WRITE(mac, save_phy6_regs[phy6_idx],
5583			    save_phy6[phy6_idx]);
5584		}
5585	}
5586
5587	PHY_WRITE(mac, save_phy_comm_regs[0], save_phy_comm[0]);
5588	PHY_WRITE(mac, save_phy_comm_regs[2], save_phy_comm[2]);
5589	PHY_WRITE(mac, save_phy_comm_regs[1], save_phy_comm[1]);
5590
5591#undef SAVE_RF_MAX
5592#undef SAVE_PHY_COMM_MAX
5593#undef SAVE_PHY6_MAX
5594}
5595
5596static void
5597bwi_rf_calc_nrssi_slope_11g(struct bwi_mac *mac)
5598{
5599#define SAVE_RF_MAX		3
5600#define SAVE_PHY_COMM_MAX	4
5601#define SAVE_PHY3_MAX		8
5602	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
5603	    { 0x7a, 0x52, 0x43 };
5604	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] =
5605	    { 0x15, 0x5a, 0x59, 0x58 };
5606	static const uint16_t save_phy3_regs[SAVE_PHY3_MAX] = {
5607		0x002e, 0x002f, 0x080f, 0x0810,
5608		0x0801, 0x0060, 0x0014, 0x0478
5609	};
5610
5611	struct bwi_softc *sc = mac->mac_sc;
5612	struct bwi_phy *phy = &mac->mac_phy;
5613	struct bwi_rf *rf = &mac->mac_rf;
5614	uint16_t save_rf[SAVE_RF_MAX];
5615	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
5616	uint16_t save_phy3[SAVE_PHY3_MAX];
5617	uint16_t ant_div, bbp_atten, chan_ex;
5618	struct bwi_gains gains;
5619	int16_t nrssi[2];
5620	int i, phy3_idx = 0;
5621
5622	if (rf->rf_rev >= 9)
5623		return;
5624	else if (rf->rf_rev == 8)
5625		bwi_rf_set_nrssi_ofs_11g(mac);
5626
5627	PHY_CLRBITS(mac, 0x429, 0x8000);
5628	PHY_CLRBITS(mac, 0x802, 0x3);
5629
5630	/*
5631	 * Save RF/PHY registers for later restoration
5632	 */
5633	ant_div = CSR_READ_2(sc, BWI_RF_ANTDIV);
5634	CSR_SETBITS_2(sc, BWI_RF_ANTDIV, 0x8000);
5635
5636	for (i = 0; i < SAVE_RF_MAX; ++i)
5637		save_rf[i] = RF_READ(mac, save_rf_regs[i]);
5638	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
5639		save_phy_comm[i] = PHY_READ(mac, save_phy_comm_regs[i]);
5640
5641	bbp_atten = CSR_READ_2(sc, BWI_BBP_ATTEN);
5642	chan_ex = CSR_READ_2(sc, BWI_RF_CHAN_EX);
5643
5644	if (phy->phy_rev >= 3) {
5645		for (i = 0; i < SAVE_PHY3_MAX; ++i)
5646			save_phy3[i] = PHY_READ(mac, save_phy3_regs[i]);
5647
5648		PHY_WRITE(mac, 0x2e, 0);
5649		PHY_WRITE(mac, 0x810, 0);
5650
5651		if (phy->phy_rev == 4 || phy->phy_rev == 6 ||
5652		    phy->phy_rev == 7) {
5653			PHY_SETBITS(mac, 0x478, 0x100);
5654			PHY_SETBITS(mac, 0x810, 0x40);
5655		} else if (phy->phy_rev == 3 || phy->phy_rev == 5)
5656			PHY_CLRBITS(mac, 0x810, 0x40);
5657
5658		PHY_SETBITS(mac, 0x60, 0x40);
5659		PHY_SETBITS(mac, 0x14, 0x200);
5660	}
5661
5662	/*
5663	 * Calculate nrssi0
5664	 */
5665	RF_SETBITS(mac, 0x7a, 0x70);
5666
5667	memset(&gains, 0, sizeof(gains));
5668	gains.tbl_gain1 = 0;
5669	gains.tbl_gain2 = 8;
5670	gains.phy_gain = 0;
5671	bwi_set_gains(mac, &gains);
5672
5673	RF_CLRBITS(mac, 0x7a, 0xff08);
5674	if (phy->phy_rev >= 2) {
5675		PHY_FILT_SETBITS(mac, 0x811, 0xffcf, 0x30);
5676		PHY_FILT_SETBITS(mac, 0x812, 0xffcf, 0x10);
5677	}
5678
5679	RF_SETBITS(mac, 0x7a, 0x80);
5680	DELAY(20);
5681	nrssi[0] = bwi_nrssi_11g(mac);
5682
5683	/*
5684	 * Calculate nrssi1
5685	 */
5686	RF_CLRBITS(mac, 0x7a, 0xff80);
5687	if (phy->phy_version >= 2)
5688		PHY_FILT_SETBITS(mac, 0x3, 0xff9f, 0x40);
5689	CSR_SETBITS_2(sc, BWI_RF_CHAN_EX, 0x2000);
5690
5691	RF_SETBITS(mac, 0x7a, 0xf);
5692	PHY_WRITE(mac, 0x15, 0xf330);
5693	if (phy->phy_rev >= 2) {
5694		PHY_FILT_SETBITS(mac, 0x812, 0xffcf, 0x20);
5695		PHY_FILT_SETBITS(mac, 0x811, 0xffcf, 0x20);
5696	}
5697
5698	memset(&gains, 0, sizeof(gains));
5699	gains.tbl_gain1 = 3;
5700	gains.tbl_gain2 = 0;
5701	gains.phy_gain = 1;
5702	bwi_set_gains(mac, &gains);
5703
5704	if (rf->rf_rev == 8) {
5705		RF_WRITE(mac, 0x43, 0x1f);
5706	} else {
5707		RF_FILT_SETBITS(mac, 0x52, 0xff0f, 0x60);
5708		RF_FILT_SETBITS(mac, 0x43, 0xfff0, 0x9);
5709	}
5710	PHY_WRITE(mac, 0x5a, 0x480);
5711	PHY_WRITE(mac, 0x59, 0x810);
5712	PHY_WRITE(mac, 0x58, 0xd);
5713	DELAY(20);
5714
5715	nrssi[1] = bwi_nrssi_11g(mac);
5716
5717	/*
5718	 * Install calculated narrow RSSI values
5719	 */
5720	if (nrssi[1] == nrssi[0])
5721		rf->rf_nrssi_slope = 0x10000;
5722	else
5723		rf->rf_nrssi_slope = 0x400000 / (nrssi[0] - nrssi[1]);
5724	if (nrssi[0] >= -4) {
5725		rf->rf_nrssi[0] = nrssi[1];
5726		rf->rf_nrssi[1] = nrssi[0];
5727	}
5728
5729	/*
5730	 * Restore saved RF/PHY registers
5731	 */
5732	if (phy->phy_rev >= 3) {
5733		for (phy3_idx = 0; phy3_idx < 4; ++phy3_idx) {
5734			PHY_WRITE(mac, save_phy3_regs[phy3_idx],
5735				  save_phy3[phy3_idx]);
5736		}
5737	}
5738	if (phy->phy_rev >= 2) {
5739		PHY_CLRBITS(mac, 0x812, 0x30);
5740		PHY_CLRBITS(mac, 0x811, 0x30);
5741	}
5742
5743	for (i = 0; i < SAVE_RF_MAX; ++i)
5744		RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
5745
5746	CSR_WRITE_2(sc, BWI_RF_ANTDIV, ant_div);
5747	CSR_WRITE_2(sc, BWI_BBP_ATTEN, bbp_atten);
5748	CSR_WRITE_2(sc, BWI_RF_CHAN_EX, chan_ex);
5749
5750	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
5751		PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
5752
5753	bwi_rf_workaround(mac, rf->rf_curchan);
5754	PHY_SETBITS(mac, 0x802, 0x3);
5755	bwi_set_gains(mac, NULL);
5756	PHY_SETBITS(mac, 0x429, 0x8000);
5757
5758	if (phy->phy_rev >= 3) {
5759		for (; phy3_idx < SAVE_PHY3_MAX; ++phy3_idx) {
5760			PHY_WRITE(mac, save_phy3_regs[phy3_idx],
5761			    save_phy3[phy3_idx]);
5762		}
5763	}
5764
5765	bwi_rf_init_sw_nrssi_table(mac);
5766	bwi_rf_set_nrssi_thr_11g(mac);
5767
5768#undef SAVE_RF_MAX
5769#undef SAVE_PHY_COMM_MAX
5770#undef SAVE_PHY3_MAX
5771}
5772
5773static void
5774bwi_rf_init_sw_nrssi_table(struct bwi_mac *mac)
5775{
5776	struct bwi_rf *rf = &mac->mac_rf;
5777	int d, i;
5778
5779	d = 0x1f - rf->rf_nrssi[0];
5780	for (i = 0; i < BWI_NRSSI_TBLSZ; ++i) {
5781		int val;
5782
5783		val = (((i - d) * rf->rf_nrssi_slope) / 0x10000) + 0x3a;
5784		if (val < 0)
5785			val = 0;
5786		else if (val > 0x3f)
5787			val = 0x3f;
5788
5789		rf->rf_nrssi_table[i] = val;
5790	}
5791}
5792
5793static void
5794bwi_rf_init_hw_nrssi_table(struct bwi_mac *mac, uint16_t adjust)
5795{
5796	int i;
5797
5798	for (i = 0; i < BWI_NRSSI_TBLSZ; ++i) {
5799		int16_t val;
5800
5801		val = bwi_nrssi_read(mac, i);
5802
5803		val -= adjust;
5804		if (val < -32)
5805			val = -32;
5806		else if (val > 31)
5807			val = 31;
5808
5809		bwi_nrssi_write(mac, i, val);
5810	}
5811}
5812
5813static void
5814bwi_rf_set_nrssi_thr_11b(struct bwi_mac *mac)
5815{
5816	struct bwi_rf *rf = &mac->mac_rf;
5817	int32_t thr;
5818
5819	if (rf->rf_type != BWI_RF_T_BCM2050 ||
5820	    (mac->mac_sc->sc_card_flags & BWI_CARD_F_SW_NRSSI) == 0)
5821		return;
5822
5823	/*
5824	 * Calculate nrssi threshold
5825	 */
5826	if (rf->rf_rev >= 6) {
5827		thr = (rf->rf_nrssi[1] - rf->rf_nrssi[0]) * 32;
5828		thr += 20 * (rf->rf_nrssi[0] + 1);
5829		thr /= 40;
5830	} else {
5831		thr = rf->rf_nrssi[1] - 5;
5832	}
5833	if (thr < 0)
5834		thr = 0;
5835	else if (thr > 0x3e)
5836		thr = 0x3e;
5837
5838	PHY_READ(mac, BWI_PHYR_NRSSI_THR_11B);	/* dummy read */
5839	PHY_WRITE(mac, BWI_PHYR_NRSSI_THR_11B, (((uint16_t)thr) << 8) | 0x1c);
5840
5841	if (rf->rf_rev >= 6) {
5842		PHY_WRITE(mac, 0x87, 0xe0d);
5843		PHY_WRITE(mac, 0x86, 0xc0b);
5844		PHY_WRITE(mac, 0x85, 0xa09);
5845		PHY_WRITE(mac, 0x84, 0x808);
5846		PHY_WRITE(mac, 0x83, 0x808);
5847		PHY_WRITE(mac, 0x82, 0x604);
5848		PHY_WRITE(mac, 0x81, 0x302);
5849		PHY_WRITE(mac, 0x80, 0x100);
5850	}
5851}
5852
5853static int32_t
5854_nrssi_threshold(const struct bwi_rf *rf, int32_t val)
5855{
5856	val *= (rf->rf_nrssi[1] - rf->rf_nrssi[0]);
5857	val += (rf->rf_nrssi[0] << 6);
5858	if (val < 32)
5859		val += 31;
5860	else
5861		val += 32;
5862	val >>= 6;
5863	if (val < -31)
5864		val = -31;
5865	else if (val > 31)
5866		val = 31;
5867
5868	return (val);
5869}
5870
5871static void
5872bwi_rf_set_nrssi_thr_11g(struct bwi_mac *mac)
5873{
5874	int32_t thr1, thr2;
5875	uint16_t thr;
5876
5877	/*
5878	 * Find the two nrssi thresholds
5879	 */
5880	if ((mac->mac_phy.phy_flags & BWI_PHY_F_LINKED) == 0 ||
5881	    (mac->mac_sc->sc_card_flags & BWI_CARD_F_SW_NRSSI) == 0) {
5882	    	int16_t nrssi;
5883
5884		nrssi = bwi_nrssi_read(mac, 0x20);
5885		if (nrssi >= 32)
5886			nrssi -= 64;
5887
5888		if (nrssi < 3) {
5889			thr1 = 0x2b;
5890			thr2 = 0x27;
5891		} else {
5892			thr1 = 0x2d;
5893			thr2 = 0x2b;
5894		}
5895	} else {
5896		/* TODO Interfere mode */
5897		thr1 = _nrssi_threshold(&mac->mac_rf, 0x11);
5898		thr2 = _nrssi_threshold(&mac->mac_rf, 0xe);
5899	}
5900
5901#define NRSSI_THR1_MASK		0x003f
5902#define NRSSI_THR2_MASK		0x0fc0
5903	thr = __SHIFTIN((uint32_t)thr1, NRSSI_THR1_MASK) |
5904	    __SHIFTIN((uint32_t)thr2, NRSSI_THR2_MASK);
5905	PHY_FILT_SETBITS(mac, BWI_PHYR_NRSSI_THR_11G, 0xf000, thr);
5906#undef NRSSI_THR1_MASK
5907#undef NRSSI_THR2_MASK
5908}
5909
5910static void
5911bwi_rf_clear_tssi(struct bwi_mac *mac)
5912{
5913	/* XXX use function pointer */
5914	if (mac->mac_phy.phy_mode == IEEE80211_MODE_11A) {
5915		/* TODO: 11A */
5916	} else {
5917		uint16_t val;
5918		int i;
5919
5920		val = __SHIFTIN(BWI_INVALID_TSSI, BWI_LO_TSSI_MASK) |
5921		    __SHIFTIN(BWI_INVALID_TSSI, BWI_HI_TSSI_MASK);
5922
5923		for (i = 0; i < 2; ++i) {
5924			MOBJ_WRITE_2(mac, BWI_COMM_MOBJ,
5925			    BWI_COMM_MOBJ_TSSI_DS + (i * 2), val);
5926		}
5927
5928		for (i = 0; i < 2; ++i) {
5929			MOBJ_WRITE_2(mac, BWI_COMM_MOBJ,
5930			    BWI_COMM_MOBJ_TSSI_OFDM + (i * 2), val);
5931		}
5932	}
5933}
5934
5935static void
5936bwi_rf_clear_state(struct bwi_rf *rf)
5937{
5938	int i;
5939
5940	rf->rf_flags &= ~BWI_RF_CLEAR_FLAGS;
5941	memset(rf->rf_lo, 0, sizeof(rf->rf_lo));
5942	memset(rf->rf_lo_used, 0, sizeof(rf->rf_lo_used));
5943
5944	rf->rf_nrssi_slope = 0;
5945	rf->rf_nrssi[0] = BWI_INVALID_NRSSI;
5946	rf->rf_nrssi[1] = BWI_INVALID_NRSSI;
5947
5948	for (i = 0; i < BWI_NRSSI_TBLSZ; ++i)
5949		rf->rf_nrssi_table[i] = i;
5950
5951	rf->rf_lo_gain = 0;
5952	rf->rf_rx_gain = 0;
5953
5954	memcpy(rf->rf_txpower_map, rf->rf_txpower_map0,
5955	      sizeof(rf->rf_txpower_map));
5956	rf->rf_idle_tssi = rf->rf_idle_tssi0;
5957}
5958
5959static void
5960bwi_rf_on_11a(struct bwi_mac *mac)
5961{
5962	/* TODO: 11A */
5963}
5964
5965static void
5966bwi_rf_on_11bg(struct bwi_mac *mac)
5967{
5968	struct bwi_phy *phy = &mac->mac_phy;
5969
5970	PHY_WRITE(mac, 0x15, 0x8000);
5971	PHY_WRITE(mac, 0x15, 0xcc00);
5972	if (phy->phy_flags & BWI_PHY_F_LINKED)
5973		PHY_WRITE(mac, 0x15, 0xc0);
5974	else
5975		PHY_WRITE(mac, 0x15, 0);
5976
5977	bwi_rf_set_chan(mac, 6 /* XXX */, 1);
5978}
5979
5980static void
5981bwi_rf_set_ant_mode(struct bwi_mac *mac, int ant_mode)
5982{
5983	struct bwi_softc *sc = mac->mac_sc;
5984	struct bwi_phy *phy = &mac->mac_phy;
5985	uint16_t val;
5986
5987	KASSERT(ant_mode == BWI_ANT_MODE_0 ||
5988	    ant_mode == BWI_ANT_MODE_1 ||
5989	    ant_mode == BWI_ANT_MODE_AUTO);
5990
5991	HFLAGS_CLRBITS(mac, BWI_HFLAG_AUTO_ANTDIV);
5992
5993	if (phy->phy_mode == IEEE80211_MODE_11B) {
5994		/* NOTE: v4/v3 conflicts, take v3 */
5995		if (mac->mac_rev == 2)
5996			val = BWI_ANT_MODE_AUTO;
5997		else
5998			val = ant_mode;
5999		val <<= 7;
6000		PHY_FILT_SETBITS(mac, 0x3e2, 0xfe7f, val);
6001	} else {	/* 11a/g */
6002		/* XXX reg/value naming */
6003		val = ant_mode << 7;
6004		PHY_FILT_SETBITS(mac, 0x401, 0x7e7f, val);
6005
6006		if (ant_mode == BWI_ANT_MODE_AUTO)
6007			PHY_CLRBITS(mac, 0x42b, 0x100);
6008
6009		if (phy->phy_mode == IEEE80211_MODE_11A) {
6010			/* TODO: 11A */
6011		} else {	/* 11g */
6012			if (ant_mode == BWI_ANT_MODE_AUTO)
6013				PHY_SETBITS(mac, 0x48c, 0x2000);
6014			else
6015				PHY_CLRBITS(mac, 0x48c, 0x2000);
6016
6017			if (phy->phy_rev >= 2) {
6018				PHY_SETBITS(mac, 0x461, 0x10);
6019				PHY_FILT_SETBITS(mac, 0x4ad, 0xff00, 0x15);
6020				if (phy->phy_rev == 2) {
6021					PHY_WRITE(mac, 0x427, 0x8);
6022				} else {
6023					PHY_FILT_SETBITS(mac, 0x427,
6024							 0xff00, 0x8);
6025				}
6026
6027				if (phy->phy_rev >= 6)
6028					PHY_WRITE(mac, 0x49b, 0xdc);
6029			}
6030		}
6031	}
6032
6033	/* XXX v4 set AUTO_ANTDIV unconditionally */
6034	if (ant_mode == BWI_ANT_MODE_AUTO)
6035		HFLAGS_SETBITS(mac, BWI_HFLAG_AUTO_ANTDIV);
6036
6037	val = ant_mode << 8;
6038	MOBJ_FILT_SETBITS_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_TX_BEACON,
6039	    0xfc3f, val);
6040	MOBJ_FILT_SETBITS_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_TX_ACK,
6041	    0xfc3f, val);
6042	MOBJ_FILT_SETBITS_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_TX_PROBE_RESP,
6043	    0xfc3f, val);
6044
6045	/* XXX what's these */
6046	if (phy->phy_mode == IEEE80211_MODE_11B)
6047		CSR_SETBITS_2(sc, 0x5e, 0x4);
6048
6049	CSR_WRITE_4(sc, 0x100, 0x1000000);
6050	if (mac->mac_rev < 5)
6051		CSR_WRITE_4(sc, 0x10c, 0x1000000);
6052
6053	mac->mac_rf.rf_ant_mode = ant_mode;
6054}
6055
6056static int
6057bwi_rf_get_latest_tssi(struct bwi_mac *mac, int8_t tssi[], uint16_t ofs)
6058{
6059	int i;
6060
6061	for (i = 0; i < 4; ) {
6062		uint16_t val;
6063
6064		val = MOBJ_READ_2(mac, BWI_COMM_MOBJ, ofs + i);
6065		tssi[i++] = (int8_t)__SHIFTOUT(val, BWI_LO_TSSI_MASK);
6066		tssi[i++] = (int8_t)__SHIFTOUT(val, BWI_HI_TSSI_MASK);
6067	}
6068
6069	for (i = 0; i < 4; ++i) {
6070		if (tssi[i] == BWI_INVALID_TSSI)
6071			return (EINVAL);
6072	}
6073
6074	return (0);
6075}
6076
6077static int
6078bwi_rf_tssi2dbm(struct bwi_mac *mac, int8_t tssi, int8_t *txpwr)
6079{
6080	struct bwi_rf *rf = &mac->mac_rf;
6081	int pwr_idx;
6082
6083	pwr_idx = rf->rf_idle_tssi + (int)tssi - rf->rf_base_tssi;
6084#if 0
6085	if (pwr_idx < 0 || pwr_idx >= BWI_TSSI_MAX)
6086		return (EINVAL);
6087#else
6088	if (pwr_idx < 0)
6089		pwr_idx = 0;
6090	else if (pwr_idx >= BWI_TSSI_MAX)
6091		pwr_idx = BWI_TSSI_MAX - 1;
6092#endif
6093	*txpwr = rf->rf_txpower_map[pwr_idx];
6094
6095	return (0);
6096}
6097
6098static int
6099bwi_rf_calc_rssi_bcm2050(struct bwi_mac *mac, const struct bwi_rxbuf_hdr *hdr)
6100{
6101	uint16_t flags1, flags3;
6102	int rssi, lna_gain;
6103
6104	rssi = hdr->rxh_rssi;
6105	flags1 = le16toh(hdr->rxh_flags1);
6106	flags3 = le16toh(hdr->rxh_flags3);
6107
6108#define NEW_BCM2050_RSSI
6109#ifdef NEW_BCM2050_RSSI
6110	if (flags1 & BWI_RXH_F1_OFDM) {
6111		if (rssi > 127)
6112			rssi -= 256;
6113		if (flags3 & BWI_RXH_F3_BCM2050_RSSI)
6114			rssi += 17;
6115		else
6116			rssi -= 4;
6117		return (rssi);
6118	}
6119
6120	if (mac->mac_sc->sc_card_flags & BWI_CARD_F_SW_NRSSI) {
6121		struct bwi_rf *rf = &mac->mac_rf;
6122
6123		if (rssi >= BWI_NRSSI_TBLSZ)
6124			rssi = BWI_NRSSI_TBLSZ - 1;
6125
6126		rssi = ((31 - (int)rf->rf_nrssi_table[rssi]) * -131) / 128;
6127		rssi -= 67;
6128	} else {
6129		rssi = ((31 - rssi) * -149) / 128;
6130		rssi -= 68;
6131	}
6132
6133	if (mac->mac_phy.phy_mode != IEEE80211_MODE_11G)
6134		return (rssi);
6135
6136	if (flags3 & BWI_RXH_F3_BCM2050_RSSI)
6137		rssi += 20;
6138
6139	lna_gain = __SHIFTOUT(le16toh(hdr->rxh_phyinfo),
6140	    BWI_RXH_PHYINFO_LNAGAIN);
6141/*	[TRC: XXX This causes some seriously verbose output.  I hope it
6142	just verbose and not actually a symptom of a problem.]
6143
6144	DPRINTF(mac->mac_sc, BWI_DBG_RF | BWI_DBG_RX,
6145	    "lna_gain %d, phyinfo 0x%04x\n",
6146	    lna_gain, le16toh(hdr->rxh_phyinfo));
6147*/
6148	switch (lna_gain) {
6149	case 0:
6150		rssi += 27;
6151		break;
6152	case 1:
6153		rssi += 6;
6154		break;
6155	case 2:
6156		rssi += 12;
6157		break;
6158	case 3:
6159		/*
6160		 * XXX
6161		 * According to v3 spec, we should do _nothing_ here,
6162		 * but it seems that the result RSSI will be too low
6163		 * (relative to what ath(4) says).  Raise it a little
6164		 * bit.
6165		 */
6166		rssi += 5;
6167		break;
6168	default:
6169		panic("impossible lna gain %d", lna_gain);
6170	}
6171#else	/* !NEW_BCM2050_RSSI */
6172	lna_gain = 0; /* shut up gcc warning */
6173
6174	if (flags1 & BWI_RXH_F1_OFDM) {
6175		if (rssi > 127)
6176			rssi -= 256;
6177		rssi = (rssi * 73) / 64;
6178
6179		if (flags3 & BWI_RXH_F3_BCM2050_RSSI)
6180			rssi += 25;
6181		else
6182			rssi -= 3;
6183		return (rssi);
6184	}
6185
6186	if (mac->mac_sc->sc_card_flags & BWI_CARD_F_SW_NRSSI) {
6187		struct bwi_rf *rf = &mac->mac_rf;
6188
6189		if (rssi >= BWI_NRSSI_TBLSZ)
6190			rssi = BWI_NRSSI_TBLSZ - 1;
6191
6192		rssi = ((31 - (int)rf->rf_nrssi_table[rssi]) * -131) / 128;
6193		rssi -= 57;
6194	} else {
6195		rssi = ((31 - rssi) * -149) / 128;
6196		rssi -= 68;
6197	}
6198
6199	if (mac->mac_phy.phy_mode != IEEE80211_MODE_11G)
6200		return (rssi);
6201
6202	if (flags3 & BWI_RXH_F3_BCM2050_RSSI)
6203		rssi += 25;
6204#endif	/* NEW_BCM2050_RSSI */
6205	return (rssi);
6206}
6207
6208static int
6209bwi_rf_calc_rssi_bcm2053(struct bwi_mac *mac, const struct bwi_rxbuf_hdr *hdr)
6210{
6211	uint16_t flags1;
6212	int rssi;
6213
6214	rssi = (((int)hdr->rxh_rssi - 11) * 103) / 64;
6215
6216	flags1 = le16toh(hdr->rxh_flags1);
6217	if (flags1 & BWI_RXH_F1_BCM2053_RSSI)
6218		rssi -= 109;
6219	else
6220		rssi -= 83;
6221
6222	return (rssi);
6223}
6224
6225static int
6226bwi_rf_calc_rssi_bcm2060(struct bwi_mac *mac, const struct bwi_rxbuf_hdr *hdr)
6227{
6228	int rssi;
6229
6230	rssi = hdr->rxh_rssi;
6231	if (rssi > 127)
6232		rssi -= 256;
6233
6234	return (rssi);
6235}
6236
6237static uint16_t
6238bwi_rf_lo_measure_11b(struct bwi_mac *mac)
6239{
6240	uint16_t val;
6241	int i;
6242
6243	val = 0;
6244	for (i = 0; i < 10; ++i) {
6245		PHY_WRITE(mac, 0x15, 0xafa0);
6246		DELAY(1);
6247		PHY_WRITE(mac, 0x15, 0xefa0);
6248		DELAY(10);
6249		PHY_WRITE(mac, 0x15, 0xffa0);
6250		DELAY(40);
6251
6252		val += PHY_READ(mac, 0x2c);
6253	}
6254
6255	return (val);
6256}
6257
6258static void
6259bwi_rf_lo_update_11b(struct bwi_mac *mac)
6260{
6261	struct bwi_softc *sc = mac->mac_sc;
6262	struct bwi_rf *rf = &mac->mac_rf;
6263	struct rf_saveregs regs;
6264	uint16_t rf_val, phy_val, min_val, val;
6265	uint16_t rf52, bphy_ctrl;
6266	int i;
6267
6268	DPRINTF(sc, BWI_DBG_RF | BWI_DBG_INIT, "%s enter\n", __func__);
6269
6270	memset(&regs, 0, sizeof(regs));
6271	bphy_ctrl = 0;
6272
6273	/*
6274	 * Save RF/PHY registers for later restoration
6275	 */
6276	SAVE_PHY_REG(mac, &regs, 15);
6277	rf52 = RF_READ(mac, 0x52) & 0xfff0;
6278	if (rf->rf_type == BWI_RF_T_BCM2050) {
6279		SAVE_PHY_REG(mac, &regs, 0a);
6280		SAVE_PHY_REG(mac, &regs, 2a);
6281		SAVE_PHY_REG(mac, &regs, 35);
6282		SAVE_PHY_REG(mac, &regs, 03);
6283		SAVE_PHY_REG(mac, &regs, 01);
6284		SAVE_PHY_REG(mac, &regs, 30);
6285
6286		SAVE_RF_REG(mac, &regs, 43);
6287		SAVE_RF_REG(mac, &regs, 7a);
6288
6289		bphy_ctrl = CSR_READ_2(sc, BWI_BPHY_CTRL);
6290
6291		SAVE_RF_REG(mac, &regs, 52);
6292		regs.rf_52 &= 0xf0;
6293
6294		PHY_WRITE(mac, 0x30, 0xff);
6295		CSR_WRITE_2(sc, BWI_PHY_CTRL, 0x3f3f);
6296		PHY_WRITE(mac, 0x35, regs.phy_35 & 0xff7f);
6297		RF_WRITE(mac, 0x7a, regs.rf_7a & 0xfff0);
6298	}
6299
6300	PHY_WRITE(mac, 0x15, 0xb000);
6301
6302	if (rf->rf_type == BWI_RF_T_BCM2050) {
6303		PHY_WRITE(mac, 0x2b, 0x203);
6304		PHY_WRITE(mac, 0x2a, 0x8a3);
6305	} else {
6306		PHY_WRITE(mac, 0x2b, 0x1402);
6307	}
6308
6309	/*
6310	 * Setup RF signal
6311	 */
6312	rf_val = 0;
6313	min_val = UINT16_MAX;
6314
6315	for (i = 0; i < 4; ++i) {
6316		RF_WRITE(mac, 0x52, rf52 | i);
6317		bwi_rf_lo_measure_11b(mac);	/* Ignore return value */
6318	}
6319	for (i = 0; i < 10; ++i) {
6320		RF_WRITE(mac, 0x52, rf52 | i);
6321
6322		val = bwi_rf_lo_measure_11b(mac) / 10;
6323		if (val < min_val) {
6324			min_val = val;
6325			rf_val = i;
6326		}
6327	}
6328	RF_WRITE(mac, 0x52, rf52 | rf_val);
6329
6330	/*
6331	 * Setup PHY signal
6332	 */
6333	phy_val = 0;
6334	min_val = UINT16_MAX;
6335
6336	for (i = -4; i < 5; i += 2) {
6337		int j;
6338
6339		for (j = -4; j < 5; j += 2) {
6340			uint16_t phy2f;
6341
6342			phy2f = (0x100 * i) + j;
6343			if (j < 0)
6344				phy2f += 0x100;
6345			PHY_WRITE(mac, 0x2f, phy2f);
6346
6347			val = bwi_rf_lo_measure_11b(mac) / 10;
6348			if (val < min_val) {
6349				min_val = val;
6350				phy_val = phy2f;
6351			}
6352		}
6353	}
6354	PHY_WRITE(mac, 0x2f, phy_val + 0x101);
6355
6356	/*
6357	 * Restore saved RF/PHY registers
6358	 */
6359	if (rf->rf_type == BWI_RF_T_BCM2050) {
6360		RESTORE_PHY_REG(mac, &regs, 0a);
6361		RESTORE_PHY_REG(mac, &regs, 2a);
6362		RESTORE_PHY_REG(mac, &regs, 35);
6363		RESTORE_PHY_REG(mac, &regs, 03);
6364		RESTORE_PHY_REG(mac, &regs, 01);
6365		RESTORE_PHY_REG(mac, &regs, 30);
6366
6367		RESTORE_RF_REG(mac, &regs, 43);
6368		RESTORE_RF_REG(mac, &regs, 7a);
6369
6370		RF_FILT_SETBITS(mac, 0x52, 0xf, regs.rf_52);
6371
6372		CSR_WRITE_2(sc, BWI_BPHY_CTRL, bphy_ctrl);
6373	}
6374	RESTORE_PHY_REG(mac, &regs, 15);
6375
6376	bwi_rf_workaround(mac, rf->rf_curchan);
6377}
6378
6379/* INTERFACE */
6380
6381static uint16_t
6382bwi_read_sprom(struct bwi_softc *sc, uint16_t ofs)
6383{
6384	return (CSR_READ_2(sc, ofs + BWI_SPROM_START));
6385}
6386
6387static void
6388bwi_setup_desc32(struct bwi_softc *sc, struct bwi_desc32 *desc_array,
6389    int ndesc, int desc_idx, bus_addr_t paddr, int buf_len, int tx)
6390{
6391	struct bwi_desc32 *desc = &desc_array[desc_idx];
6392	uint32_t ctrl, addr, addr_hi, addr_lo;
6393
6394	addr_lo = __SHIFTOUT(paddr, BWI_DESC32_A_ADDR_MASK);
6395	addr_hi = __SHIFTOUT(paddr, BWI_DESC32_A_FUNC_MASK);
6396
6397	addr = __SHIFTIN(addr_lo, BWI_DESC32_A_ADDR_MASK) |
6398	    __SHIFTIN(BWI_DESC32_A_FUNC_TXRX, BWI_DESC32_A_FUNC_MASK);
6399
6400	ctrl = __SHIFTIN(buf_len, BWI_DESC32_C_BUFLEN_MASK) |
6401	     __SHIFTIN(addr_hi, BWI_DESC32_C_ADDRHI_MASK);
6402	if (desc_idx == ndesc - 1)
6403		ctrl |= BWI_DESC32_C_EOR;
6404	if (tx) {
6405		/* XXX */
6406		ctrl |= BWI_DESC32_C_FRAME_START |
6407		    BWI_DESC32_C_FRAME_END |
6408		    BWI_DESC32_C_INTR;
6409	}
6410
6411	desc->addr = htole32(addr);
6412	desc->ctrl = htole32(ctrl);
6413}
6414
6415static void
6416bwi_power_on(struct bwi_softc *sc, int with_pll)
6417{
6418	uint32_t gpio_in, gpio_out, gpio_en, status;
6419
6420	DPRINTF(sc, BWI_DBG_MISC, "%s\n", __func__);
6421
6422	gpio_in = (sc->sc_conf_read)(sc, BWI_PCIR_GPIO_IN);
6423	if (gpio_in & BWI_PCIM_GPIO_PWR_ON)
6424		goto back;
6425
6426	gpio_out = (sc->sc_conf_read)(sc, BWI_PCIR_GPIO_OUT);
6427	gpio_en = (sc->sc_conf_read)(sc, BWI_PCIR_GPIO_ENABLE);
6428
6429	gpio_out |= BWI_PCIM_GPIO_PWR_ON;
6430	gpio_en |= BWI_PCIM_GPIO_PWR_ON;
6431	if (with_pll) {
6432		/* Turn off PLL first */
6433		gpio_out |= BWI_PCIM_GPIO_PLL_PWR_OFF;
6434		gpio_en |= BWI_PCIM_GPIO_PLL_PWR_OFF;
6435	}
6436
6437	(sc->sc_conf_write)(sc, BWI_PCIR_GPIO_OUT, gpio_out);
6438	(sc->sc_conf_write)(sc, BWI_PCIR_GPIO_ENABLE, gpio_en);
6439	DELAY(1000);
6440
6441	if (with_pll) {
6442		/* Turn on PLL */
6443		gpio_out &= ~BWI_PCIM_GPIO_PLL_PWR_OFF;
6444		(sc->sc_conf_write)(sc, BWI_PCIR_GPIO_OUT, gpio_out);
6445		DELAY(5000);
6446	}
6447
6448back:
6449	/* [TRC: XXX This looks totally wrong -- what's PCI doing in here?] */
6450	/* Clear "Signaled Target Abort" */
6451	status = (sc->sc_conf_read)(sc, PCI_COMMAND_STATUS_REG);
6452	status &= ~PCI_STATUS_TARGET_TARGET_ABORT;
6453	(sc->sc_conf_write)(sc, PCI_COMMAND_STATUS_REG, status);
6454}
6455
6456static int
6457bwi_power_off(struct bwi_softc *sc, int with_pll)
6458{
6459	uint32_t gpio_out, gpio_en;
6460
6461	DPRINTF(sc, BWI_DBG_MISC, "%s\n", __func__);
6462
6463	(sc->sc_conf_read)(sc, BWI_PCIR_GPIO_IN); /* dummy read */
6464	gpio_out = (sc->sc_conf_read)(sc, BWI_PCIR_GPIO_OUT);
6465	gpio_en = (sc->sc_conf_read)(sc, BWI_PCIR_GPIO_ENABLE);
6466
6467	gpio_out &= ~BWI_PCIM_GPIO_PWR_ON;
6468	gpio_en |= BWI_PCIM_GPIO_PWR_ON;
6469	if (with_pll) {
6470		gpio_out |= BWI_PCIM_GPIO_PLL_PWR_OFF;
6471		gpio_en |= BWI_PCIM_GPIO_PLL_PWR_OFF;
6472	}
6473
6474	(sc->sc_conf_write)(sc, BWI_PCIR_GPIO_OUT, gpio_out);
6475	(sc->sc_conf_write)(sc, BWI_PCIR_GPIO_ENABLE, gpio_en);
6476
6477	return (0);
6478}
6479
6480static int
6481bwi_regwin_switch(struct bwi_softc *sc, struct bwi_regwin *rw,
6482    struct bwi_regwin **old_rw)
6483{
6484	int error;
6485
6486	if (old_rw != NULL)
6487		*old_rw = NULL;
6488
6489	if (!BWI_REGWIN_EXIST(rw))
6490		return (EINVAL);
6491
6492	if (sc->sc_cur_regwin != rw) {
6493		error = bwi_regwin_select(sc, rw->rw_id);
6494		if (error) {
6495			aprint_error_dev(sc->sc_dev,
6496			    "can't select regwin %d\n", rw->rw_id);
6497			return (error);
6498		}
6499	}
6500
6501	if (old_rw != NULL)
6502		*old_rw = sc->sc_cur_regwin;
6503	sc->sc_cur_regwin = rw;
6504
6505	return (0);
6506}
6507
6508static int
6509bwi_regwin_select(struct bwi_softc *sc, int id)
6510{
6511	uint32_t win = BWI_PCIM_REGWIN(id);
6512	int i;
6513
6514#define RETRY_MAX	50
6515	for (i = 0; i < RETRY_MAX; ++i) {
6516		(sc->sc_conf_write)(sc, BWI_PCIR_SEL_REGWIN, win);
6517		if ((sc->sc_conf_read)(sc, BWI_PCIR_SEL_REGWIN) == win)
6518			return (0);
6519		DELAY(10);
6520	}
6521#undef RETRY_MAX
6522
6523	return (ENXIO);
6524}
6525
6526static void
6527bwi_regwin_info(struct bwi_softc *sc, uint16_t *type, uint8_t *rev)
6528{
6529	uint32_t val;
6530
6531	val = CSR_READ_4(sc, BWI_ID_HI);
6532	*type = BWI_ID_HI_REGWIN_TYPE(val);
6533	*rev = BWI_ID_HI_REGWIN_REV(val);
6534
6535	DPRINTF(sc, BWI_DBG_ATTACH, "regwin: type 0x%03x, rev %d,"
6536	    " vendor 0x%04x\n", *type, *rev,
6537	    __SHIFTOUT(val, BWI_ID_HI_REGWIN_VENDOR_MASK));
6538}
6539
6540static void
6541bwi_led_attach(struct bwi_softc *sc)
6542{
6543	const uint8_t *led_act = NULL;
6544	uint16_t gpio, val[BWI_LED_MAX];
6545	int i;
6546
6547	for (i = 0; i < __arraycount(bwi_vendor_led_act); ++i) {
6548		if (sc->sc_pci_subvid == bwi_vendor_led_act[i].vid) {
6549			led_act = bwi_vendor_led_act[i].led_act;
6550			break;
6551		}
6552	}
6553	if (led_act == NULL)
6554		led_act = bwi_default_led_act;
6555
6556	gpio = bwi_read_sprom(sc, BWI_SPROM_GPIO01);
6557	val[0] = __SHIFTOUT(gpio, BWI_SPROM_GPIO_0);
6558	val[1] = __SHIFTOUT(gpio, BWI_SPROM_GPIO_1);
6559
6560	gpio = bwi_read_sprom(sc, BWI_SPROM_GPIO23);
6561	val[2] = __SHIFTOUT(gpio, BWI_SPROM_GPIO_2);
6562	val[3] = __SHIFTOUT(gpio, BWI_SPROM_GPIO_3);
6563
6564	for (i = 0; i < BWI_LED_MAX; ++i) {
6565		struct bwi_led *led = &sc->sc_leds[i];
6566
6567		if (val[i] == 0xff) {
6568			led->l_act = led_act[i];
6569		} else {
6570			if (val[i] & BWI_LED_ACT_LOW)
6571				led->l_flags |= BWI_LED_F_ACTLOW;
6572			led->l_act = __SHIFTOUT(val[i], BWI_LED_ACT_MASK);
6573		}
6574		led->l_mask = (1 << i);
6575
6576		if (led->l_act == BWI_LED_ACT_BLINK_SLOW ||
6577		    led->l_act == BWI_LED_ACT_BLINK_POLL ||
6578		    led->l_act == BWI_LED_ACT_BLINK) {
6579			led->l_flags |= BWI_LED_F_BLINK;
6580			if (led->l_act == BWI_LED_ACT_BLINK_POLL)
6581				led->l_flags |= BWI_LED_F_POLLABLE;
6582			else if (led->l_act == BWI_LED_ACT_BLINK_SLOW)
6583				led->l_flags |= BWI_LED_F_SLOW;
6584
6585			if (sc->sc_blink_led == NULL) {
6586				sc->sc_blink_led = led;
6587				if (led->l_flags & BWI_LED_F_SLOW)
6588					BWI_LED_SLOWDOWN(sc->sc_led_idle);
6589			}
6590		}
6591
6592		DPRINTF(sc, BWI_DBG_LED | BWI_DBG_ATTACH,
6593		    "%dth led, act %d, lowact %d\n", i, led->l_act,
6594		    led->l_flags & BWI_LED_F_ACTLOW);
6595	}
6596	callout_init(&sc->sc_led_blink_ch, 0);
6597}
6598
6599static uint16_t
6600bwi_led_onoff(const struct bwi_led *led, uint16_t val, int on)
6601{
6602	if (led->l_flags & BWI_LED_F_ACTLOW)
6603		on = !on;
6604	if (on)
6605		val |= led->l_mask;
6606	else
6607		val &= ~led->l_mask;
6608
6609	return (val);
6610}
6611
6612static void
6613bwi_led_newstate(struct bwi_softc *sc, enum ieee80211_state nstate)
6614{
6615	struct ieee80211com *ic = &sc->sc_ic;
6616	struct ifnet *ifp = &sc->sc_if;
6617	uint16_t val;
6618	int i;
6619
6620	if (nstate == IEEE80211_S_INIT) {
6621		callout_stop(&sc->sc_led_blink_ch);
6622		sc->sc_led_blinking = 0;
6623	}
6624
6625	if ((ifp->if_flags & IFF_RUNNING) == 0)
6626		return;
6627
6628	val = CSR_READ_2(sc, BWI_MAC_GPIO_CTRL);
6629	for (i = 0; i < BWI_LED_MAX; ++i) {
6630		struct bwi_led *led = &sc->sc_leds[i];
6631		int on;
6632
6633		if (led->l_act == BWI_LED_ACT_UNKN ||
6634		    led->l_act == BWI_LED_ACT_NULL)
6635			continue;
6636
6637		if ((led->l_flags & BWI_LED_F_BLINK) &&
6638		    nstate != IEEE80211_S_INIT)
6639			continue;
6640
6641		switch (led->l_act) {
6642		case BWI_LED_ACT_ON:	/* Always on */
6643			on = 1;
6644			break;
6645		case BWI_LED_ACT_OFF:	/* Always off */
6646		case BWI_LED_ACT_5GHZ:	/* TODO: 11A */
6647			on = 0;
6648			break;
6649		default:
6650			on = 1;
6651			switch (nstate) {
6652			case IEEE80211_S_INIT:
6653				on = 0;
6654				break;
6655			case IEEE80211_S_RUN:
6656				if (led->l_act == BWI_LED_ACT_11G &&
6657				    ic->ic_curmode != IEEE80211_MODE_11G)
6658					on = 0;
6659				break;
6660			default:
6661				if (led->l_act == BWI_LED_ACT_ASSOC)
6662					on = 0;
6663				break;
6664			}
6665			break;
6666		}
6667
6668		val = bwi_led_onoff(led, val, on);
6669	}
6670	CSR_WRITE_2(sc, BWI_MAC_GPIO_CTRL, val);
6671}
6672
6673static void
6674bwi_led_event(struct bwi_softc *sc, int event)
6675{
6676	struct bwi_led *led = sc->sc_blink_led;
6677	int rate;
6678
6679	if (event == BWI_LED_EVENT_POLL) {
6680		if ((led->l_flags & BWI_LED_F_POLLABLE) == 0)
6681			return;
6682		if (ticks - sc->sc_led_ticks < sc->sc_led_idle)
6683			return;
6684	}
6685
6686	sc->sc_led_ticks = ticks;
6687	if (sc->sc_led_blinking)
6688		return;
6689
6690	switch (event) {
6691	case BWI_LED_EVENT_RX:
6692		rate = sc->sc_rx_rate;
6693		break;
6694	case BWI_LED_EVENT_TX:
6695		rate = sc->sc_tx_rate;
6696		break;
6697	case BWI_LED_EVENT_POLL:
6698		rate = 0;
6699		break;
6700	default:
6701		panic("unknown LED event %d\n", event);
6702		break;
6703	}
6704	bwi_led_blink_start(sc, bwi_led_duration[rate].on_dur,
6705	    bwi_led_duration[rate].off_dur);
6706}
6707
6708static void
6709bwi_led_blink_start(struct bwi_softc *sc, int on_dur, int off_dur)
6710{
6711	struct bwi_led *led = sc->sc_blink_led;
6712	uint16_t val;
6713
6714	val = CSR_READ_2(sc, BWI_MAC_GPIO_CTRL);
6715	val = bwi_led_onoff(led, val, 1);
6716	CSR_WRITE_2(sc, BWI_MAC_GPIO_CTRL, val);
6717
6718	if (led->l_flags & BWI_LED_F_SLOW) {
6719		BWI_LED_SLOWDOWN(on_dur);
6720		BWI_LED_SLOWDOWN(off_dur);
6721	}
6722
6723	sc->sc_led_blinking = 1;
6724	sc->sc_led_blink_offdur = off_dur;
6725
6726	callout_reset(&sc->sc_led_blink_ch, on_dur, bwi_led_blink_next, sc);
6727}
6728
6729static void
6730bwi_led_blink_next(void *xsc)
6731{
6732	struct bwi_softc *sc = xsc;
6733	uint16_t val;
6734
6735	val = CSR_READ_2(sc, BWI_MAC_GPIO_CTRL);
6736	val = bwi_led_onoff(sc->sc_blink_led, val, 0);
6737	CSR_WRITE_2(sc, BWI_MAC_GPIO_CTRL, val);
6738
6739	callout_reset(&sc->sc_led_blink_ch, sc->sc_led_blink_offdur,
6740	    bwi_led_blink_end, sc);
6741}
6742
6743static void
6744bwi_led_blink_end(void *xsc)
6745{
6746	struct bwi_softc *sc = xsc;
6747
6748	sc->sc_led_blinking = 0;
6749}
6750
6751static int
6752bwi_bbp_attach(struct bwi_softc *sc)
6753{
6754	uint16_t bbp_id, rw_type;
6755	uint8_t rw_rev;
6756	uint32_t info;
6757	int error, nregwin, i;
6758
6759	/*
6760	 * Get 0th regwin information
6761	 * NOTE: 0th regwin should exist
6762	 */
6763	error = bwi_regwin_select(sc, 0);
6764	if (error) {
6765		aprint_error_dev(sc->sc_dev, "can't select regwin 0\n");
6766		return (error);
6767	}
6768	bwi_regwin_info(sc, &rw_type, &rw_rev);
6769
6770	/*
6771	 * Find out BBP id
6772	 */
6773	bbp_id = 0;
6774	info = 0;
6775	if (rw_type == BWI_REGWIN_T_COM) {
6776		info = CSR_READ_4(sc, BWI_INFO);
6777		bbp_id = __SHIFTOUT(info, BWI_INFO_BBPID_MASK);
6778
6779		BWI_CREATE_REGWIN(&sc->sc_com_regwin, 0, rw_type, rw_rev);
6780
6781		sc->sc_cap = CSR_READ_4(sc, BWI_CAPABILITY);
6782	} else {
6783		uint16_t did = sc->sc_pci_did;
6784		uint8_t revid = sc->sc_pci_revid;
6785
6786		for (i = 0; i < __arraycount(bwi_bbpid_map); ++i) {
6787			if (did >= bwi_bbpid_map[i].did_min &&
6788			    did <= bwi_bbpid_map[i].did_max) {
6789				bbp_id = bwi_bbpid_map[i].bbp_id;
6790				break;
6791			}
6792		}
6793		if (bbp_id == 0) {
6794			aprint_error_dev(sc->sc_dev, "no BBP id for device id"
6795			    " 0x%04x\n", did);
6796			return (ENXIO);
6797		}
6798
6799		info = __SHIFTIN(revid, BWI_INFO_BBPREV_MASK) |
6800		    __SHIFTIN(0, BWI_INFO_BBPPKG_MASK);
6801	}
6802
6803	/*
6804	 * Find out number of regwins
6805	 */
6806	nregwin = 0;
6807	if (rw_type == BWI_REGWIN_T_COM && rw_rev >= 4) {
6808		nregwin = __SHIFTOUT(info, BWI_INFO_NREGWIN_MASK);
6809	} else {
6810		for (i = 0; i < __arraycount(bwi_regwin_count); ++i) {
6811			if (bwi_regwin_count[i].bbp_id == bbp_id) {
6812				nregwin = bwi_regwin_count[i].nregwin;
6813				break;
6814			}
6815		}
6816		if (nregwin == 0) {
6817			aprint_error_dev(sc->sc_dev, "no number of win for"
6818			    " BBP id 0x%04x\n", bbp_id);
6819			return (ENXIO);
6820		}
6821	}
6822
6823	/* Record BBP id/rev for later using */
6824	sc->sc_bbp_id = bbp_id;
6825	sc->sc_bbp_rev = __SHIFTOUT(info, BWI_INFO_BBPREV_MASK);
6826	sc->sc_bbp_pkg = __SHIFTOUT(info, BWI_INFO_BBPPKG_MASK);
6827	aprint_normal_dev(sc->sc_dev,
6828	    "BBP id 0x%04x, BBP rev 0x%x, BBP pkg %d\n",
6829	    sc->sc_bbp_id, sc->sc_bbp_rev, sc->sc_bbp_pkg);
6830	DPRINTF(sc, BWI_DBG_ATTACH, "nregwin %d, cap 0x%08x\n",
6831	    nregwin, sc->sc_cap);
6832
6833	/*
6834	 * Create rest of the regwins
6835	 */
6836
6837	/* Don't re-create common regwin, if it is already created */
6838	i = BWI_REGWIN_EXIST(&sc->sc_com_regwin) ? 1 : 0;
6839
6840	for (; i < nregwin; ++i) {
6841		/*
6842		 * Get regwin information
6843		 */
6844		error = bwi_regwin_select(sc, i);
6845		if (error) {
6846			aprint_error_dev(sc->sc_dev, "can't select regwin"
6847			    " %d\n", i);
6848			return (error);
6849		}
6850		bwi_regwin_info(sc, &rw_type, &rw_rev);
6851
6852		/*
6853		 * Try attach:
6854		 * 1) Bus (PCI/PCIE) regwin
6855		 * 2) MAC regwin
6856		 * Ignore rest types of regwin
6857		 */
6858		if (rw_type == BWI_REGWIN_T_BUSPCI ||
6859		    rw_type == BWI_REGWIN_T_BUSPCIE) {
6860			if (BWI_REGWIN_EXIST(&sc->sc_bus_regwin)) {
6861				aprint_error_dev(sc->sc_dev,
6862				    "bus regwin already exists\n");
6863			} else {
6864				BWI_CREATE_REGWIN(&sc->sc_bus_regwin, i,
6865				    rw_type, rw_rev);
6866			}
6867		} else if (rw_type == BWI_REGWIN_T_MAC) {
6868			/* XXX ignore return value */
6869			bwi_mac_attach(sc, i, rw_rev);
6870		}
6871	}
6872
6873	/* At least one MAC shold exist */
6874	if (!BWI_REGWIN_EXIST(&sc->sc_mac[0].mac_regwin)) {
6875		aprint_error_dev(sc->sc_dev, "no MAC was found\n");
6876		return (ENXIO);
6877	}
6878	KASSERT(sc->sc_nmac > 0);
6879
6880	/* Bus regwin must exist */
6881	if (!BWI_REGWIN_EXIST(&sc->sc_bus_regwin)) {
6882		aprint_error_dev(sc->sc_dev, "no bus regwin was found\n");
6883		return (ENXIO);
6884	}
6885
6886	/* Start with first MAC */
6887	error = bwi_regwin_switch(sc, &sc->sc_mac[0].mac_regwin, NULL);
6888	if (error)
6889		return (error);
6890
6891	return (0);
6892}
6893
6894static int
6895bwi_bus_init(struct bwi_softc *sc, struct bwi_mac *mac)
6896{
6897	struct bwi_regwin *old, *bus;
6898	uint32_t val;
6899	int error;
6900
6901	bus = &sc->sc_bus_regwin;
6902	KASSERT(sc->sc_cur_regwin == &mac->mac_regwin);
6903
6904	/*
6905	 * Tell bus to generate requested interrupts
6906	 */
6907	if (bus->rw_rev < 6 && bus->rw_type == BWI_REGWIN_T_BUSPCI) {
6908		/*
6909		 * NOTE: Read BWI_FLAGS from MAC regwin
6910		 */
6911		val = CSR_READ_4(sc, BWI_FLAGS);
6912
6913		error = bwi_regwin_switch(sc, bus, &old);
6914		if (error)
6915			return (error);
6916
6917		CSR_SETBITS_4(sc, BWI_INTRVEC, (val & BWI_FLAGS_INTR_MASK));
6918	} else {
6919		uint32_t mac_mask;
6920
6921		mac_mask = 1 << mac->mac_id;
6922
6923		error = bwi_regwin_switch(sc, bus, &old);
6924		if (error)
6925			return (error);
6926
6927		val = (sc->sc_conf_read)(sc, BWI_PCIR_INTCTL);
6928		val |= mac_mask << 8;
6929		(sc->sc_conf_write)(sc, BWI_PCIR_INTCTL, val);
6930	}
6931
6932	if (sc->sc_flags & BWI_F_BUS_INITED)
6933		goto back;
6934
6935	if (bus->rw_type == BWI_REGWIN_T_BUSPCI) {
6936		/*
6937		 * Enable prefetch and burst
6938		 */
6939		CSR_SETBITS_4(sc, BWI_BUS_CONFIG,
6940		    BWI_BUS_CONFIG_PREFETCH | BWI_BUS_CONFIG_BURST);
6941
6942		if (bus->rw_rev < 5) {
6943			struct bwi_regwin *com = &sc->sc_com_regwin;
6944
6945			/*
6946			 * Configure timeouts for bus operation
6947			 */
6948
6949			/*
6950			 * Set service timeout and request timeout
6951			 */
6952			CSR_SETBITS_4(sc, BWI_CONF_LO,
6953			    __SHIFTIN(BWI_CONF_LO_SERVTO,
6954				BWI_CONF_LO_SERVTO_MASK) |
6955			    __SHIFTIN(BWI_CONF_LO_REQTO,
6956				BWI_CONF_LO_REQTO_MASK));
6957
6958			/*
6959			 * If there is common regwin, we switch to that regwin
6960			 * and switch back to bus regwin once we have done.
6961			 */
6962			if (BWI_REGWIN_EXIST(com)) {
6963				error = bwi_regwin_switch(sc, com, NULL);
6964				if (error)
6965					return (error);
6966			}
6967
6968			/* Let bus know what we have changed */
6969			CSR_WRITE_4(sc, BWI_BUS_ADDR, BWI_BUS_ADDR_MAGIC);
6970			CSR_READ_4(sc, BWI_BUS_ADDR); /* Flush */
6971			CSR_WRITE_4(sc, BWI_BUS_DATA, 0);
6972			CSR_READ_4(sc, BWI_BUS_DATA); /* Flush */
6973
6974			if (BWI_REGWIN_EXIST(com)) {
6975				error = bwi_regwin_switch(sc, bus, NULL);
6976				if (error)
6977					return (error);
6978			}
6979		} else if (bus->rw_rev >= 11) {
6980			/*
6981			 * Enable memory read multiple
6982			 */
6983			CSR_SETBITS_4(sc, BWI_BUS_CONFIG, BWI_BUS_CONFIG_MRM);
6984		}
6985	} else {
6986		/* TODO: PCIE */
6987	}
6988
6989	sc->sc_flags |= BWI_F_BUS_INITED;
6990back:
6991	return (bwi_regwin_switch(sc, old, NULL));
6992}
6993
6994static void
6995bwi_get_card_flags(struct bwi_softc *sc)
6996{
6997	sc->sc_card_flags = bwi_read_sprom(sc, BWI_SPROM_CARD_FLAGS);
6998	if (sc->sc_card_flags == 0xffff)
6999		sc->sc_card_flags = 0;
7000
7001	if (sc->sc_pci_subvid == PCI_VENDOR_APPLE &&
7002	    sc->sc_pci_subdid == 0x4e && /* XXX */
7003	    sc->sc_pci_revid > 0x40)
7004		sc->sc_card_flags |= BWI_CARD_F_PA_GPIO9;
7005
7006	DPRINTF(sc, BWI_DBG_ATTACH, "card flags 0x%04x\n", sc->sc_card_flags);
7007}
7008
7009static void
7010bwi_get_eaddr(struct bwi_softc *sc, uint16_t eaddr_ofs, uint8_t *eaddr)
7011{
7012	int i;
7013
7014	for (i = 0; i < 3; ++i) {
7015		*((uint16_t *)eaddr + i) =
7016		    htobe16(bwi_read_sprom(sc, eaddr_ofs + 2 * i));
7017	}
7018}
7019
7020static void
7021bwi_get_clock_freq(struct bwi_softc *sc, struct bwi_clock_freq *freq)
7022{
7023	struct bwi_regwin *com;
7024	uint32_t val;
7025	uint div;
7026	int src;
7027
7028	memset(freq, 0, sizeof(*freq));
7029	com = &sc->sc_com_regwin;
7030
7031	KASSERT(BWI_REGWIN_EXIST(com));
7032	KASSERT(sc->sc_cur_regwin == com);
7033	KASSERT(sc->sc_cap & BWI_CAP_CLKMODE);
7034
7035	/*
7036	 * Calculate clock frequency
7037	 */
7038	src = -1;
7039	div = 0;
7040	if (com->rw_rev < 6) {
7041		val = (sc->sc_conf_read)(sc, BWI_PCIR_GPIO_OUT);
7042		if (val & BWI_PCIM_GPIO_OUT_CLKSRC) {
7043			src = BWI_CLKSRC_PCI;
7044			div = 64;
7045		} else {
7046			src = BWI_CLKSRC_CS_OSC;
7047			div = 32;
7048		}
7049	} else if (com->rw_rev < 10) {
7050		val = CSR_READ_4(sc, BWI_CLOCK_CTRL);
7051
7052		src = __SHIFTOUT(val, BWI_CLOCK_CTRL_CLKSRC);
7053		if (src == BWI_CLKSRC_LP_OSC)
7054			div = 1;
7055		else {
7056			div = (__SHIFTOUT(val, BWI_CLOCK_CTRL_FDIV) + 1) << 2;
7057
7058			/* Unknown source */
7059			if (src >= BWI_CLKSRC_MAX)
7060				src = BWI_CLKSRC_CS_OSC;
7061		}
7062	} else {
7063		val = CSR_READ_4(sc, BWI_CLOCK_INFO);
7064
7065		src = BWI_CLKSRC_CS_OSC;
7066		div = (__SHIFTOUT(val, BWI_CLOCK_INFO_FDIV) + 1) << 2;
7067	}
7068
7069	KASSERT(src >= 0 && src < BWI_CLKSRC_MAX);
7070	KASSERT(div != 0);
7071
7072	DPRINTF(sc, BWI_DBG_ATTACH, "clksrc %s\n",
7073	    src == BWI_CLKSRC_PCI ? "PCI" :
7074	    (src == BWI_CLKSRC_LP_OSC ? "LP_OSC" : "CS_OSC"));
7075
7076	freq->clkfreq_min = bwi_clkfreq[src].freq_min / div;
7077	freq->clkfreq_max = bwi_clkfreq[src].freq_max / div;
7078
7079	DPRINTF(sc, BWI_DBG_ATTACH, "clkfreq min %u, max %u\n",
7080	    freq->clkfreq_min, freq->clkfreq_max);
7081}
7082
7083static int
7084bwi_set_clock_mode(struct bwi_softc *sc, enum bwi_clock_mode clk_mode)
7085{
7086	struct bwi_regwin *old, *com;
7087	uint32_t clk_ctrl, clk_src;
7088	int error, pwr_off = 0;
7089
7090	com = &sc->sc_com_regwin;
7091	if (!BWI_REGWIN_EXIST(com))
7092		return (0);
7093
7094	if (com->rw_rev >= 10 || com->rw_rev < 6)
7095		return (0);
7096
7097	/*
7098	 * For common regwin whose rev is [6, 10), the chip
7099	 * must be capable to change clock mode.
7100	 */
7101	if ((sc->sc_cap & BWI_CAP_CLKMODE) == 0)
7102		return (0);
7103
7104	error = bwi_regwin_switch(sc, com, &old);
7105	if (error)
7106		return (error);
7107
7108	if (clk_mode == BWI_CLOCK_MODE_FAST)
7109		bwi_power_on(sc, 0);	/* Don't turn on PLL */
7110
7111	clk_ctrl = CSR_READ_4(sc, BWI_CLOCK_CTRL);
7112	clk_src = __SHIFTOUT(clk_ctrl, BWI_CLOCK_CTRL_CLKSRC);
7113
7114	switch (clk_mode) {
7115	case BWI_CLOCK_MODE_FAST:
7116		clk_ctrl &= ~BWI_CLOCK_CTRL_SLOW;
7117		clk_ctrl |= BWI_CLOCK_CTRL_IGNPLL;
7118		break;
7119	case BWI_CLOCK_MODE_SLOW:
7120		clk_ctrl |= BWI_CLOCK_CTRL_SLOW;
7121		break;
7122	case BWI_CLOCK_MODE_DYN:
7123		clk_ctrl &= ~(BWI_CLOCK_CTRL_SLOW |
7124		    BWI_CLOCK_CTRL_IGNPLL |
7125		    BWI_CLOCK_CTRL_NODYN);
7126		if (clk_src != BWI_CLKSRC_CS_OSC) {
7127			clk_ctrl |= BWI_CLOCK_CTRL_NODYN;
7128			pwr_off = 1;
7129		}
7130		break;
7131	}
7132	CSR_WRITE_4(sc, BWI_CLOCK_CTRL, clk_ctrl);
7133
7134	if (pwr_off)
7135		bwi_power_off(sc, 0);	/* Leave PLL as it is */
7136
7137	return (bwi_regwin_switch(sc, old, NULL));
7138}
7139
7140static int
7141bwi_set_clock_delay(struct bwi_softc *sc)
7142{
7143	struct bwi_regwin *old, *com;
7144	int error;
7145
7146	com = &sc->sc_com_regwin;
7147	if (!BWI_REGWIN_EXIST(com))
7148		return (0);
7149
7150	error = bwi_regwin_switch(sc, com, &old);
7151	if (error)
7152		return (error);
7153
7154	if (sc->sc_bbp_id == BWI_BBPID_BCM4321) {
7155		if (sc->sc_bbp_rev == 0)
7156			CSR_WRITE_4(sc, BWI_CONTROL, BWI_CONTROL_MAGIC0);
7157		else if (sc->sc_bbp_rev == 1)
7158			CSR_WRITE_4(sc, BWI_CONTROL, BWI_CONTROL_MAGIC1);
7159	}
7160
7161	if (sc->sc_cap & BWI_CAP_CLKMODE) {
7162		if (com->rw_rev >= 10)
7163			CSR_FILT_SETBITS_4(sc, BWI_CLOCK_INFO, 0xffff, 0x40000);
7164		else {
7165			struct bwi_clock_freq freq;
7166
7167			bwi_get_clock_freq(sc, &freq);
7168			CSR_WRITE_4(sc, BWI_PLL_ON_DELAY,
7169			    howmany(freq.clkfreq_max * 150, 1000000));
7170			CSR_WRITE_4(sc, BWI_FREQ_SEL_DELAY,
7171			    howmany(freq.clkfreq_max * 15, 1000000));
7172		}
7173	}
7174
7175	return (bwi_regwin_switch(sc, old, NULL));
7176}
7177
7178static int
7179bwi_init(struct ifnet *ifp)
7180{
7181	struct bwi_softc *sc = ifp->if_softc;
7182
7183	bwi_init_statechg(sc, 1);
7184
7185	return (0);
7186}
7187
7188static void
7189bwi_init_statechg(struct bwi_softc *sc, int statechg)
7190{
7191	struct ieee80211com *ic = &sc->sc_ic;
7192	struct ifnet *ifp = &sc->sc_if;
7193	struct bwi_mac *mac;
7194	int error;
7195
7196	DPRINTF(sc, BWI_DBG_MISC, "%s\n", __func__);
7197
7198	bwi_stop(ifp, statechg);
7199
7200	/* power on cardbus socket */
7201	if (sc->sc_enable != NULL)
7202		(sc->sc_enable)(sc, 0);
7203
7204	bwi_bbp_power_on(sc, BWI_CLOCK_MODE_FAST);
7205
7206	/* TODO: 2 MAC */
7207
7208	mac = &sc->sc_mac[0];
7209	error = bwi_regwin_switch(sc, &mac->mac_regwin, NULL);
7210	if (error)
7211		goto back;
7212
7213	error = bwi_mac_init(mac);
7214	if (error)
7215		goto back;
7216
7217	bwi_bbp_power_on(sc, BWI_CLOCK_MODE_DYN);
7218
7219	IEEE80211_ADDR_COPY(ic->ic_myaddr, CLLADDR(ifp->if_sadl));
7220
7221	bwi_set_bssid(sc, bwi_zero_addr);	/* Clear BSSID */
7222	bwi_set_addr_filter(sc, BWI_ADDR_FILTER_MYADDR, ic->ic_myaddr);
7223
7224	bwi_mac_reset_hwkeys(mac);
7225
7226	if ((mac->mac_flags & BWI_MAC_F_HAS_TXSTATS) == 0) {
7227		int i;
7228
7229#define NRETRY	1000
7230		/*
7231		 * Drain any possible pending TX status
7232		 */
7233		for (i = 0; i < NRETRY; ++i) {
7234			if ((CSR_READ_4(sc, BWI_TXSTATUS_0) &
7235			     BWI_TXSTATUS_0_MORE) == 0)
7236				break;
7237			CSR_READ_4(sc, BWI_TXSTATUS_1);
7238		}
7239		if (i == NRETRY)
7240			aprint_error_dev(sc->sc_dev,
7241			    "can't drain TX status\n");
7242#undef NRETRY
7243	}
7244
7245	if (mac->mac_phy.phy_mode == IEEE80211_MODE_11G)
7246		bwi_mac_updateslot(mac, 1);
7247
7248	/* Start MAC */
7249	error = bwi_mac_start(mac);
7250	if (error)
7251		goto back;
7252
7253	/* Enable intrs */
7254	bwi_enable_intrs(sc, BWI_INIT_INTRS);
7255
7256	ifp->if_flags |= IFF_RUNNING;
7257	ifp->if_flags &= ~IFF_OACTIVE;
7258
7259	if (statechg) {
7260		if (ic->ic_opmode != IEEE80211_M_MONITOR) {
7261			/* [TRC: XXX OpenBSD omits this conditional.] */
7262			if (ic->ic_roaming != IEEE80211_ROAMING_MANUAL)
7263				ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
7264		} else {
7265			ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
7266		}
7267	} else {
7268		ieee80211_new_state(ic, ic->ic_state, -1);
7269	}
7270
7271back:
7272	if (error)
7273		bwi_stop(ifp, 1);
7274	else
7275		/* [TRC: XXX DragonFlyBD uses ifp->if_start(ifp).] */
7276		bwi_start(ifp);
7277}
7278
7279static int
7280bwi_ioctl(struct ifnet *ifp, u_long cmd, void *data)
7281{
7282	struct bwi_softc *sc = ifp->if_softc;
7283	struct ieee80211com *ic = &sc->sc_ic;
7284	int s, error = 0;
7285
7286	/* [TRC: XXX Superstitiously cargo-culted from wi(4).] */
7287	if (!device_is_active(sc->sc_dev))
7288		return (ENXIO);
7289
7290	s = splnet();
7291
7292	switch (cmd) {
7293	case SIOCSIFFLAGS:
7294		if ((error = ifioctl_common(ifp, cmd, data)) != 0)
7295			break;
7296		if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
7297		    (IFF_UP | IFF_RUNNING)) {
7298			struct bwi_mac *mac;
7299			int promisc = -1;
7300
7301			KASSERT(sc->sc_cur_regwin->rw_type ==
7302			    BWI_REGWIN_T_MAC);
7303			mac = (struct bwi_mac *)sc->sc_cur_regwin;
7304
7305			if ((ifp->if_flags & IFF_PROMISC) &&
7306			    (sc->sc_flags & BWI_F_PROMISC) == 0) {
7307				promisc = 1;
7308				sc->sc_flags |= BWI_F_PROMISC;
7309			} else if ((ifp->if_flags & IFF_PROMISC) == 0 &&
7310				   (sc->sc_flags & BWI_F_PROMISC)) {
7311				promisc = 0;
7312				sc->sc_flags &= ~BWI_F_PROMISC;
7313			}
7314
7315			if (promisc >= 0)
7316				bwi_mac_set_promisc(mac, promisc);
7317		}
7318
7319		if (ifp->if_flags & IFF_UP) {
7320			if (!(ifp->if_flags & IFF_RUNNING))
7321				bwi_init(ifp);
7322		} else {
7323			if (ifp->if_flags & IFF_RUNNING)
7324				bwi_stop(ifp, 1);
7325		}
7326		break;
7327
7328	case SIOCADDMULTI:
7329	case SIOCDELMULTI:
7330		/* [TRC: Several other drivers appear to have this
7331		   copied & pasted, so I'm following suit.] */
7332		/* XXX no h/w multicast filter? --dyoung */
7333		if ((error = ether_ioctl(ifp, cmd, data)) == ENETRESET) {
7334			/* setup multicast filter, etc */
7335			error = 0;
7336		}
7337		break;
7338
7339	case SIOCS80211CHANNEL:
7340		/* [TRC: Pilfered from OpenBSD.  No clue whether it works.] */
7341		/* allow fast channel switching in monitor mode */
7342		error = ieee80211_ioctl(ic, cmd, data);
7343		if (error == ENETRESET &&
7344		    ic->ic_opmode == IEEE80211_M_MONITOR) {
7345			if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
7346			    (IFF_UP | IFF_RUNNING)) {
7347				/* [TRC: XXX ????] */
7348				ic->ic_bss->ni_chan = ic->ic_ibss_chan;
7349				ic->ic_curchan = ic->ic_ibss_chan;
7350				bwi_set_chan(sc, ic->ic_bss->ni_chan);
7351			}
7352			error = 0;
7353		}
7354		break;
7355
7356	default:
7357		error = ieee80211_ioctl(ic, cmd, data);
7358		break;
7359	}
7360
7361	if (error == ENETRESET) {
7362		if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
7363		    (IFF_UP | IFF_RUNNING) &&
7364		    /* [TRC: XXX Superstitiously cargo-culted from iwi(4). */
7365		    (ic->ic_roaming != IEEE80211_ROAMING_MANUAL))
7366			bwi_init(ifp);
7367		error = 0;
7368	}
7369
7370	splx(s);
7371
7372	return (error);
7373}
7374
7375static void
7376bwi_start(struct ifnet *ifp)
7377{
7378	struct bwi_softc *sc = ifp->if_softc;
7379	struct ieee80211com *ic = &sc->sc_ic;
7380	struct bwi_txbuf_data *tbd = &sc->sc_tx_bdata[BWI_TX_DATA_RING];
7381	int trans, idx;
7382
7383	/* [TRC: XXX I'm not sure under which conditions we're actually
7384	   supposed to refuse to start, so I'm copying what OpenBSD and
7385	   DragonFlyBSD do, even if no one else on NetBSD does it. */
7386	if ((ifp->if_flags & IFF_OACTIVE) ||
7387	    (ifp->if_flags & IFF_RUNNING) == 0)
7388		return;
7389
7390	trans = 0;
7391	idx = tbd->tbd_idx;
7392
7393	while (tbd->tbd_buf[idx].tb_mbuf == NULL) {
7394		struct ieee80211_frame *wh;
7395		struct ieee80211_node *ni;
7396		struct mbuf *m;
7397		int mgt_pkt = 0;
7398
7399		IF_DEQUEUE(&ic->ic_mgtq, m);
7400		if (m != NULL) {
7401			ni = M_GETCTX(m, struct ieee80211_node *);
7402			M_CLEARCTX(m);
7403
7404			mgt_pkt = 1;
7405		} else {
7406			struct ether_header *eh;
7407
7408			if (ic->ic_state != IEEE80211_S_RUN)
7409				break;
7410
7411			IFQ_DEQUEUE(&ifp->if_snd, m);
7412			if (m == NULL)
7413				break;
7414
7415			if (m->m_len < sizeof(*eh)) {
7416				m = m_pullup(m, sizeof(*eh));
7417				if (m == NULL) {
7418					if_statinc(ifp, if_oerrors);
7419					continue;
7420				}
7421			}
7422			eh = mtod(m, struct ether_header *);
7423
7424			ni = ieee80211_find_txnode(ic, eh->ether_dhost);
7425			if (ni == NULL) {
7426				if_statinc(ifp, if_oerrors);
7427				m_freem(m);
7428				continue;
7429			}
7430
7431			/* [TRC: XXX Superstitiously cargo-culted from
7432			   ath(4) and wi(4).] */
7433			if ((ni->ni_flags & IEEE80211_NODE_PWR_MGT) &&
7434			    (m->m_flags & M_PWR_SAV) == 0) {
7435				ieee80211_pwrsave(ic, ni, m);
7436				ieee80211_free_node(ni);
7437				continue;
7438			}
7439
7440			/* [TRC: XXX I *think* we're supposed to do
7441			   this, but honestly I have no clue.  We don't
7442			   use M_WME_GETAC, so...] */
7443			if (ieee80211_classify(ic, m, ni)) {
7444				/* [TRC: XXX What debug flag?] */
7445				DPRINTF(sc, BWI_DBG_MISC,
7446				    "%s: discard, classification failure\n",
7447				    __func__);
7448				if_statinc(ifp, if_oerrors);
7449				m_freem(m);
7450				ieee80211_free_node(ni);
7451				continue;
7452			}
7453
7454			/* [TRC: XXX wi(4) and awi(4) do this; iwi(4)
7455			   doesn't.] */
7456			if_statinc(ifp, if_opackets);
7457
7458			/* [TRC: XXX When should the packet be
7459			   filtered?  Different drivers appear to do it
7460			   at different times.] */
7461			/* TODO: PS */
7462			bpf_mtap(ifp, m, BPF_D_OUT);
7463			m = ieee80211_encap(ic, m, ni);
7464			if (m == NULL) {
7465				if_statinc(ifp, if_oerrors);
7466				ieee80211_free_node(ni);
7467				continue;
7468			}
7469		}
7470		bpf_mtap3(ic->ic_rawbpf, m, BPF_D_OUT);
7471
7472		wh = mtod(m, struct ieee80211_frame *);
7473		/* [TRC: XXX What about ic->ic_flags & IEEE80211_F_PRIVACY?] */
7474		if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
7475			if (ieee80211_crypto_encap(ic, ni, m) == NULL) {
7476				if_statinc(ifp, if_oerrors);
7477				m_freem(m);
7478				ieee80211_free_node(ni);
7479				continue;
7480			}
7481		}
7482		wh = NULL;	/* [TRC: XXX Huh?] */
7483
7484		if (bwi_encap(sc, idx, m, &ni, mgt_pkt) != 0) {
7485			/* 'm' is freed in bwi_encap() if we reach here */
7486			if_statinc(ifp, if_oerrors);
7487			if (ni != NULL)
7488				ieee80211_free_node(ni);
7489			continue;
7490		}
7491
7492		trans = 1;
7493		tbd->tbd_used++;
7494		idx = (idx + 1) % BWI_TX_NDESC;
7495
7496		if (tbd->tbd_used + BWI_TX_NSPRDESC >= BWI_TX_NDESC) {
7497			ifp->if_flags |= IFF_OACTIVE;
7498			break;
7499		}
7500	}
7501	tbd->tbd_idx = idx;
7502
7503	if (trans)
7504		sc->sc_tx_timer = 5;
7505	ifp->if_timer = 1;
7506}
7507
7508static void
7509bwi_watchdog(struct ifnet *ifp)
7510{
7511	struct bwi_softc *sc = ifp->if_softc;
7512
7513	ifp->if_timer = 0;
7514
7515	if ((ifp->if_flags & IFF_RUNNING) == 0 ||
7516	    !device_is_active(sc->sc_dev))
7517		return;
7518
7519	if (sc->sc_tx_timer) {
7520		if (--sc->sc_tx_timer == 0) {
7521			aprint_error_dev(sc->sc_dev, "device timeout\n");
7522			if_statinc(ifp, if_oerrors);
7523			/* TODO */
7524			/* [TRC: XXX TODO what?  Stop the device?
7525			   Bring it down?  iwi(4) does this.] */
7526		} else
7527			ifp->if_timer = 1;
7528	}
7529
7530	ieee80211_watchdog(&sc->sc_ic);
7531}
7532
7533static void
7534bwi_stop(struct ifnet *ifp, int state_chg)
7535{
7536	struct bwi_softc *sc = ifp->if_softc;
7537	struct ieee80211com *ic = &sc->sc_ic;
7538	struct bwi_mac *mac;
7539	int i, error, pwr_off = 0;
7540
7541	DPRINTF(sc, BWI_DBG_MISC, "%s\n", __func__);
7542
7543	if (state_chg)
7544		ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
7545	else
7546		bwi_newstate_begin(sc, IEEE80211_S_INIT);
7547
7548	if (ifp->if_flags & IFF_RUNNING) {
7549		KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC);
7550		mac = (struct bwi_mac *)sc->sc_cur_regwin;
7551
7552		bwi_disable_intrs(sc, BWI_ALL_INTRS);
7553		CSR_READ_4(sc, BWI_MAC_INTR_MASK);
7554		bwi_mac_stop(mac);
7555	}
7556
7557	for (i = 0; i < sc->sc_nmac; ++i) {
7558		struct bwi_regwin *old_rw;
7559
7560		mac = &sc->sc_mac[i];
7561		if ((mac->mac_flags & BWI_MAC_F_INITED) == 0)
7562			continue;
7563
7564		error = bwi_regwin_switch(sc, &mac->mac_regwin, &old_rw);
7565		if (error)
7566			continue;
7567
7568		bwi_mac_shutdown(mac);
7569		pwr_off = 1;
7570
7571		bwi_regwin_switch(sc, old_rw, NULL);
7572	}
7573
7574	if (pwr_off)
7575		bwi_bbp_power_off(sc);
7576
7577	sc->sc_tx_timer = 0;
7578	ifp->if_timer = 0;
7579	ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
7580
7581	/* power off cardbus socket */
7582	if (sc->sc_disable != NULL)
7583		(sc->sc_disable)(sc, 0);
7584
7585	return;
7586}
7587
7588static void
7589bwi_newstate_begin(struct bwi_softc *sc, enum ieee80211_state nstate)
7590{
7591	callout_stop(&sc->sc_scan_ch);
7592	callout_stop(&sc->sc_calib_ch);
7593
7594	bwi_led_newstate(sc, nstate);
7595
7596	if (nstate == IEEE80211_S_INIT)
7597		sc->sc_txpwrcb_type = BWI_TXPWR_INIT;
7598}
7599
7600static int
7601bwi_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
7602{
7603	struct bwi_softc *sc = ic->ic_ifp->if_softc;
7604	struct ieee80211_node *ni;
7605	int error;
7606
7607	/* [TRC: XXX amrr] */
7608	callout_stop(&sc->sc_amrr_ch);
7609
7610	bwi_newstate_begin(sc, nstate);
7611
7612	if (nstate == IEEE80211_S_INIT)
7613		goto back;
7614
7615	/* [TRC: XXX What channel do we set this to? */
7616	error = bwi_set_chan(sc, ic->ic_curchan);
7617	if (error) {
7618		aprint_error_dev(sc->sc_dev, "can't set channel to %u\n",
7619		    ieee80211_chan2ieee(ic, ic->ic_curchan));
7620		return (error);
7621	}
7622
7623	if (ic->ic_opmode == IEEE80211_M_MONITOR) {
7624		/* Nothing to do */
7625	} else if (nstate == IEEE80211_S_RUN) {
7626		struct bwi_mac *mac;
7627
7628		ni = ic->ic_bss;
7629
7630		bwi_set_bssid(sc, ic->ic_bss->ni_bssid);
7631
7632		KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC);
7633		mac = (struct bwi_mac *)sc->sc_cur_regwin;
7634
7635		/* Initial TX power calibration */
7636		bwi_mac_calibrate_txpower(mac, BWI_TXPWR_INIT);
7637#ifdef notyet
7638		sc->sc_txpwrcb_type = BWI_TXPWR_FORCE;
7639#else
7640		sc->sc_txpwrcb_type = BWI_TXPWR_CALIB;
7641#endif
7642		/* [TRC: XXX amrr] */
7643		if (ic->ic_opmode == IEEE80211_M_STA) {
7644			/* fake a join to init the tx rate */
7645			bwi_newassoc(ni, 1);
7646		}
7647
7648		if (ic->ic_opmode != IEEE80211_M_MONITOR) {
7649			/* start automatic rate control timer */
7650			if (ic->ic_fixed_rate == -1)
7651				callout_schedule(&sc->sc_amrr_ch, hz / 2);
7652		}
7653	} else
7654		bwi_set_bssid(sc, bwi_zero_addr);
7655
7656back:
7657	error = (sc->sc_newstate)(ic, nstate, arg);
7658
7659	if (nstate == IEEE80211_S_SCAN) {
7660		callout_schedule(&sc->sc_scan_ch,
7661		    (sc->sc_dwell_time * hz) / 1000);
7662	} else if (nstate == IEEE80211_S_RUN) {
7663		/* XXX 15 seconds */
7664		callout_schedule(&sc->sc_calib_ch, hz);
7665	}
7666
7667	return (error);
7668}
7669
7670static int
7671bwi_media_change(struct ifnet *ifp)
7672{
7673	int error;
7674
7675	error = ieee80211_media_change(ifp);
7676	if (error != ENETRESET)
7677		return (error);
7678
7679	if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING))
7680		bwi_init(ifp);
7681
7682	return (0);
7683}
7684
7685/* [TRC: XXX amrr] */
7686static void
7687bwi_iter_func(void *arg, struct ieee80211_node *ni)
7688{
7689	struct bwi_softc *sc = arg;
7690	struct bwi_node *bn = (struct bwi_node *)ni;
7691
7692	ieee80211_amrr_choose(&sc->sc_amrr, ni, &bn->amn);
7693}
7694
7695static void
7696bwi_amrr_timeout(void *arg)
7697{
7698	struct bwi_softc *sc = arg;
7699	struct ieee80211com *ic = &sc->sc_ic;
7700	int s;
7701
7702	s = splnet();
7703	if (ic->ic_opmode == IEEE80211_M_STA)
7704		bwi_iter_func(sc, ic->ic_bss);
7705	else
7706		/* [TRC: XXX I'm making a wild guess about what to
7707		   supply for the node table.] */
7708		ieee80211_iterate_nodes(&ic->ic_sta, bwi_iter_func, sc);
7709
7710	callout_schedule(&sc->sc_amrr_ch, hz / 2);
7711	splx(s);
7712}
7713
7714static void
7715bwi_newassoc(struct ieee80211_node *ni, int isnew)
7716{
7717	struct ieee80211com *ic = ni->ni_ic;
7718	struct bwi_softc *sc = ic->ic_ifp->if_softc;
7719	int i;
7720
7721	DPRINTF(sc, BWI_DBG_STATION, "%s\n", __func__);
7722
7723	ieee80211_amrr_node_init(&sc->sc_amrr, &((struct bwi_node *)ni)->amn);
7724
7725	/* set rate to some reasonable initial value */
7726	for (i = ni->ni_rates.rs_nrates - 1;
7727	    i > 0 && (ni->ni_rates.rs_rates[i] & IEEE80211_RATE_VAL) > 72;
7728	    i--);
7729
7730	ni->ni_txrate = i;
7731}
7732
7733static struct ieee80211_node *
7734bwi_node_alloc(struct ieee80211_node_table *nt)
7735{
7736	struct bwi_node *bn;
7737
7738	bn = malloc(sizeof(struct bwi_node), M_80211_NODE, M_NOWAIT | M_ZERO);
7739
7740	return ((struct ieee80211_node *)bn);
7741}
7742/* [TRC: XXX amrr end] */
7743
7744static int
7745bwi_dma_alloc(struct bwi_softc *sc)
7746{
7747	int error, i, has_txstats;
7748	/* [TRC: XXX DragonFlyBSD adjusts the low address for different
7749	   bus spaces.  Should we?] */
7750	bus_size_t tx_ring_sz, rx_ring_sz, desc_sz = 0;
7751	uint32_t txrx_ctrl_step = 0;
7752
7753	has_txstats = 0;
7754	for (i = 0; i < sc->sc_nmac; ++i) {
7755		if (sc->sc_mac[i].mac_flags & BWI_MAC_F_HAS_TXSTATS) {
7756			has_txstats = 1;
7757			break;
7758		}
7759	}
7760
7761	switch (sc->sc_bus_space) {
7762	case BWI_BUS_SPACE_30BIT:
7763	case BWI_BUS_SPACE_32BIT:
7764		desc_sz = sizeof(struct bwi_desc32);
7765		txrx_ctrl_step = 0x20;
7766
7767		sc->sc_init_tx_ring = bwi_init_tx_ring32;
7768		sc->sc_free_tx_ring = bwi_free_tx_ring32;
7769		sc->sc_init_rx_ring = bwi_init_rx_ring32;
7770		sc->sc_free_rx_ring = bwi_free_rx_ring32;
7771		sc->sc_setup_rxdesc = bwi_setup_rx_desc32;
7772		sc->sc_setup_txdesc = bwi_setup_tx_desc32;
7773		sc->sc_rxeof = bwi_rxeof32;
7774		sc->sc_start_tx = bwi_start_tx32;
7775		if (has_txstats) {
7776			sc->sc_init_txstats = bwi_init_txstats32;
7777			sc->sc_free_txstats = bwi_free_txstats32;
7778			sc->sc_txeof_status = bwi_txeof_status32;
7779		}
7780		break;
7781
7782	case BWI_BUS_SPACE_64BIT:
7783		desc_sz = sizeof(struct bwi_desc64);
7784		txrx_ctrl_step = 0x40;
7785
7786		sc->sc_init_tx_ring = bwi_init_tx_ring64;
7787		sc->sc_free_tx_ring = bwi_free_tx_ring64;
7788		sc->sc_init_rx_ring = bwi_init_rx_ring64;
7789		sc->sc_free_rx_ring = bwi_free_rx_ring64;
7790		sc->sc_setup_rxdesc = bwi_setup_rx_desc64;
7791		sc->sc_setup_txdesc = bwi_setup_tx_desc64;
7792		sc->sc_rxeof = bwi_rxeof64;
7793		sc->sc_start_tx = bwi_start_tx64;
7794		if (has_txstats) {
7795			sc->sc_init_txstats = bwi_init_txstats64;
7796			sc->sc_free_txstats = bwi_free_txstats64;
7797			sc->sc_txeof_status = bwi_txeof_status64;
7798		}
7799		break;
7800	}
7801
7802	KASSERT(desc_sz != 0);
7803	KASSERT(txrx_ctrl_step != 0);
7804
7805	tx_ring_sz = roundup(desc_sz * BWI_TX_NDESC, BWI_RING_ALIGN);
7806	rx_ring_sz = roundup(desc_sz * BWI_RX_NDESC, BWI_RING_ALIGN);
7807
7808	/* [TRC: XXX Using OpenBSD's code, which is rather different
7809	   from DragonFlyBSD's.] */
7810#define TXRX_CTRL(idx)	(BWI_TXRX_CTRL_BASE + (idx) * txrx_ctrl_step)
7811	/*
7812	 * Create TX ring DMA stuffs
7813	 */
7814	for (i = 0; i < BWI_TX_NRING; ++i) {
7815		error = bus_dmamap_create(sc->sc_dmat, tx_ring_sz, 1,
7816		    tx_ring_sz, 0, BUS_DMA_NOWAIT,
7817		    &sc->sc_tx_rdata[i].rdata_dmap);
7818		if (error) {
7819			aprint_error_dev(sc->sc_dev,
7820			    "%dth TX ring DMA create failed\n", i);
7821			return (error);
7822		}
7823		error = bwi_dma_ring_alloc(sc,
7824		    &sc->sc_tx_rdata[i], tx_ring_sz, TXRX_CTRL(i));
7825		if (error) {
7826			aprint_error_dev(sc->sc_dev,
7827			    "%dth TX ring DMA alloc failed\n", i);
7828			return (error);
7829		}
7830	}
7831
7832	/*
7833	 * Create RX ring DMA stuffs
7834	 */
7835	error = bus_dmamap_create(sc->sc_dmat, rx_ring_sz, 1,
7836	    rx_ring_sz, 0, BUS_DMA_NOWAIT,
7837	    &sc->sc_rx_rdata.rdata_dmap);
7838	if (error) {
7839		aprint_error_dev(sc->sc_dev, "RX ring DMA create failed\n");
7840		return (error);
7841	}
7842
7843	error = bwi_dma_ring_alloc(sc, &sc->sc_rx_rdata,
7844	    rx_ring_sz, TXRX_CTRL(0));
7845	if (error) {
7846		aprint_error_dev(sc->sc_dev, "RX ring DMA alloc failed\n");
7847		return (error);
7848	}
7849
7850	if (has_txstats) {
7851		error = bwi_dma_txstats_alloc(sc, TXRX_CTRL(3), desc_sz);
7852		if (error) {
7853			aprint_error_dev(sc->sc_dev,
7854			    "TX stats DMA alloc failed\n");
7855			return (error);
7856		}
7857	}
7858#undef TXRX_CTRL
7859
7860	return (bwi_dma_mbuf_create(sc));
7861}
7862
7863static void
7864bwi_dma_free(struct bwi_softc *sc)
7865{
7866	int i;
7867
7868	for (i = 0; i < BWI_TX_NRING; ++i)
7869		bwi_ring_data_free(&sc->sc_tx_rdata[i], sc);
7870
7871	bwi_ring_data_free(&sc->sc_rx_rdata, sc);
7872	bwi_dma_txstats_free(sc);
7873	bwi_dma_mbuf_destroy(sc, BWI_TX_NRING, 1);
7874}
7875
7876static void
7877bwi_ring_data_free(struct bwi_ring_data *rd, struct bwi_softc *sc)
7878{
7879	if (rd->rdata_desc != NULL) {
7880		bus_dmamap_unload(sc->sc_dmat, rd->rdata_dmap);
7881		bus_dmamem_free(sc->sc_dmat, &rd->rdata_seg, 1);
7882	}
7883}
7884
7885static int
7886bwi_dma_ring_alloc(struct bwi_softc *sc,
7887    struct bwi_ring_data *rd, bus_size_t size, uint32_t txrx_ctrl)
7888{
7889	int error, nsegs;
7890
7891	error = bus_dmamem_alloc(sc->sc_dmat, size, BWI_ALIGN, 0,
7892	    &rd->rdata_seg, 1, &nsegs, BUS_DMA_NOWAIT);
7893	if (error) {
7894		aprint_error_dev(sc->sc_dev, "can't allocate DMA mem\n");
7895		return (error);
7896	}
7897
7898	error = bus_dmamem_map(sc->sc_dmat, &rd->rdata_seg, nsegs,
7899	    size, (void **)&rd->rdata_desc, BUS_DMA_NOWAIT);
7900	if (error) {
7901		aprint_error_dev(sc->sc_dev, "can't map DMA mem\n");
7902		return (error);
7903	}
7904
7905	error = bus_dmamap_load(sc->sc_dmat, rd->rdata_dmap, rd->rdata_desc,
7906	    size, NULL, BUS_DMA_WAITOK);
7907	if (error) {
7908		aprint_error_dev(sc->sc_dev, "can't load DMA mem\n");
7909		bus_dmamem_free(sc->sc_dmat, &rd->rdata_seg, nsegs);
7910		rd->rdata_desc = NULL;
7911		return (error);
7912	}
7913
7914	rd->rdata_paddr = rd->rdata_dmap->dm_segs[0].ds_addr;
7915	rd->rdata_txrx_ctrl = txrx_ctrl;
7916
7917	return (0);
7918}
7919
7920static int
7921bwi_dma_txstats_alloc(struct bwi_softc *sc, uint32_t ctrl_base,
7922    bus_size_t desc_sz)
7923{
7924	struct bwi_txstats_data *st;
7925	bus_size_t dma_size;
7926	int error, nsegs;
7927
7928	st = malloc(sizeof(*st), M_DEVBUF, M_WAITOK | M_ZERO);
7929	sc->sc_txstats = st;
7930
7931	/*
7932	 * Create TX stats descriptor DMA stuffs
7933	 */
7934	dma_size = roundup(desc_sz * BWI_TXSTATS_NDESC, BWI_RING_ALIGN);
7935
7936	error = bus_dmamap_create(sc->sc_dmat, dma_size, 1, dma_size, 0,
7937	    BUS_DMA_NOWAIT, &st->stats_ring_dmap);
7938	if (error) {
7939		aprint_error_dev(sc->sc_dev,
7940		    "can't create txstats ring DMA mem\n");
7941		return (error);
7942	}
7943
7944	error = bus_dmamem_alloc(sc->sc_dmat, dma_size, BWI_RING_ALIGN, 0,
7945	     &st->stats_ring_seg, 1, &nsegs, BUS_DMA_NOWAIT);
7946	if (error) {
7947		aprint_error_dev(sc->sc_dev,
7948		    "can't allocate txstats ring DMA mem\n");
7949		return (error);
7950	}
7951
7952	error = bus_dmamem_map(sc->sc_dmat, &st->stats_ring_seg, nsegs,
7953	    dma_size, (void **)&st->stats_ring, BUS_DMA_NOWAIT);
7954	if (error) {
7955		aprint_error_dev(sc->sc_dev,
7956		    "can't map txstats ring DMA mem\n");
7957		return (error);
7958	}
7959
7960	error = bus_dmamap_load(sc->sc_dmat, st->stats_ring_dmap,
7961	    st->stats_ring, dma_size, NULL, BUS_DMA_WAITOK);
7962	if (error) {
7963		aprint_error_dev(sc->sc_dev,
7964		    "can't load txstats ring DMA mem\n");
7965		bus_dmamem_free(sc->sc_dmat, &st->stats_ring_seg, nsegs);
7966		return (error);
7967	}
7968
7969	memset(st->stats_ring, 0, dma_size);
7970	st->stats_ring_paddr = st->stats_ring_dmap->dm_segs[0].ds_addr;
7971
7972	/*
7973	 * Create TX stats DMA stuffs
7974	 */
7975	dma_size = roundup(sizeof(struct bwi_txstats) * BWI_TXSTATS_NDESC,
7976	    BWI_ALIGN);
7977
7978	error = bus_dmamap_create(sc->sc_dmat, dma_size, 1, dma_size, 0,
7979	    BUS_DMA_NOWAIT, &st->stats_dmap);
7980	if (error) {
7981		aprint_error_dev(sc->sc_dev,
7982		    "can't create txstats ring DMA mem\n");
7983		return (error);
7984	}
7985
7986	error = bus_dmamem_alloc(sc->sc_dmat, dma_size, BWI_ALIGN, 0,
7987	    &st->stats_seg, 1, &nsegs, BUS_DMA_NOWAIT);
7988	if (error) {
7989		aprint_error_dev(sc->sc_dev,
7990		    "can't allocate txstats DMA mem\n");
7991		return (error);
7992	}
7993
7994	error = bus_dmamem_map(sc->sc_dmat, &st->stats_seg, nsegs,
7995	    dma_size, (void **)&st->stats, BUS_DMA_NOWAIT);
7996	if (error) {
7997		aprint_error_dev(sc->sc_dev, "can't map txstats DMA mem\n");
7998		return (error);
7999	}
8000
8001	error = bus_dmamap_load(sc->sc_dmat, st->stats_dmap, st->stats,
8002	    dma_size, NULL, BUS_DMA_WAITOK);
8003	if (error) {
8004		aprint_error_dev(sc->sc_dev, "can't load txstats DMA mem\n");
8005		bus_dmamem_free(sc->sc_dmat, &st->stats_seg, nsegs);
8006		return (error);
8007	}
8008
8009	memset(st->stats, 0, dma_size);
8010	st->stats_paddr = st->stats_dmap->dm_segs[0].ds_addr;
8011	st->stats_ctrl_base = ctrl_base;
8012
8013	return (0);
8014}
8015
8016static void
8017bwi_dma_txstats_free(struct bwi_softc *sc)
8018{
8019	struct bwi_txstats_data *st;
8020
8021	if (sc->sc_txstats == NULL)
8022		return;
8023	st = sc->sc_txstats;
8024
8025	bus_dmamap_unload(sc->sc_dmat, st->stats_ring_dmap);
8026	bus_dmamem_free(sc->sc_dmat, &st->stats_ring_seg, 1);
8027
8028	bus_dmamap_unload(sc->sc_dmat, st->stats_dmap);
8029	bus_dmamem_free(sc->sc_dmat, &st->stats_seg, 1);
8030
8031	free(st, M_DEVBUF);
8032}
8033
8034static int
8035bwi_dma_mbuf_create(struct bwi_softc *sc)
8036{
8037	struct bwi_rxbuf_data *rbd = &sc->sc_rx_bdata;
8038	int i, j, k, ntx, error;
8039
8040	ntx = 0;
8041
8042	/*
8043	 * Create TX mbuf DMA map
8044	 */
8045	for (i = 0; i < BWI_TX_NRING; ++i) {
8046		struct bwi_txbuf_data *tbd = &sc->sc_tx_bdata[i];
8047
8048		for (j = 0; j < BWI_TX_NDESC; ++j) {
8049			error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES,
8050			    0, BUS_DMA_NOWAIT, &tbd->tbd_buf[j].tb_dmap);
8051			if (error) {
8052				aprint_error_dev(sc->sc_dev,
8053				    "can't create %dth tbd, %dth DMA map\n",
8054				    i, j);
8055				ntx = i;
8056				for (k = 0; k < j; ++k) {
8057					bus_dmamap_destroy(sc->sc_dmat,
8058					    tbd->tbd_buf[k].tb_dmap);
8059				}
8060				goto fail;
8061			}
8062		}
8063	}
8064	ntx = BWI_TX_NRING;
8065
8066	/*
8067	 * Create RX mbuf DMA map and a spare DMA map
8068	 */
8069	error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, 0,
8070	    BUS_DMA_NOWAIT, &rbd->rbd_tmp_dmap);
8071	if (error) {
8072		aprint_error_dev(sc->sc_dev,
8073		    "can't create spare RX buf DMA map\n");
8074		goto fail;
8075	}
8076
8077	for (j = 0; j < BWI_RX_NDESC; ++j) {
8078		error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, 0,
8079		    BUS_DMA_NOWAIT, &rbd->rbd_buf[j].rb_dmap);
8080		if (error) {
8081			aprint_error_dev(sc->sc_dev,
8082			    "can't create %dth RX buf DMA map\n", j);
8083
8084			for (k = 0; k < j; ++k) {
8085				bus_dmamap_destroy(sc->sc_dmat,
8086				    rbd->rbd_buf[j].rb_dmap);
8087			}
8088			bus_dmamap_destroy(sc->sc_dmat,
8089			    rbd->rbd_tmp_dmap);
8090			goto fail;
8091		}
8092	}
8093
8094	return (0);
8095fail:
8096	bwi_dma_mbuf_destroy(sc, ntx, 0);
8097
8098	return (error);
8099}
8100
8101static void
8102bwi_dma_mbuf_destroy(struct bwi_softc *sc, int ntx, int nrx)
8103{
8104	int i, j;
8105
8106	for (i = 0; i < ntx; ++i) {
8107		struct bwi_txbuf_data *tbd = &sc->sc_tx_bdata[i];
8108
8109		for (j = 0; j < BWI_TX_NDESC; ++j) {
8110			struct bwi_txbuf *tb = &tbd->tbd_buf[j];
8111
8112			if (tb->tb_mbuf != NULL) {
8113				bus_dmamap_unload(sc->sc_dmat,
8114				    tb->tb_dmap);
8115				m_freem(tb->tb_mbuf);
8116			}
8117			if (tb->tb_ni != NULL)
8118				ieee80211_free_node(tb->tb_ni);
8119			bus_dmamap_destroy(sc->sc_dmat, tb->tb_dmap);
8120		}
8121	}
8122
8123	if (nrx) {
8124		struct bwi_rxbuf_data *rbd = &sc->sc_rx_bdata;
8125
8126		bus_dmamap_destroy(sc->sc_dmat, rbd->rbd_tmp_dmap);
8127		for (j = 0; j < BWI_RX_NDESC; ++j) {
8128			struct bwi_rxbuf *rb = &rbd->rbd_buf[j];
8129
8130			if (rb->rb_mbuf != NULL) {
8131				bus_dmamap_unload(sc->sc_dmat,
8132						  rb->rb_dmap);
8133				m_freem(rb->rb_mbuf);
8134			}
8135			bus_dmamap_destroy(sc->sc_dmat, rb->rb_dmap);
8136		}
8137	}
8138}
8139
8140static void
8141bwi_enable_intrs(struct bwi_softc *sc, uint32_t enable_intrs)
8142{
8143	CSR_SETBITS_4(sc, BWI_MAC_INTR_MASK, enable_intrs);
8144}
8145
8146static void
8147bwi_disable_intrs(struct bwi_softc *sc, uint32_t disable_intrs)
8148{
8149	CSR_CLRBITS_4(sc, BWI_MAC_INTR_MASK, disable_intrs);
8150}
8151
8152static int
8153bwi_init_tx_ring32(struct bwi_softc *sc, int ring_idx)
8154{
8155	struct bwi_ring_data *rd;
8156	struct bwi_txbuf_data *tbd;
8157	uint32_t val, addr_hi, addr_lo;
8158
8159	KASSERT(ring_idx < BWI_TX_NRING);
8160	rd = &sc->sc_tx_rdata[ring_idx];
8161	tbd = &sc->sc_tx_bdata[ring_idx];
8162
8163	tbd->tbd_idx = 0;
8164	tbd->tbd_used = 0;
8165
8166	memset(rd->rdata_desc, 0, sizeof(struct bwi_desc32) * BWI_TX_NDESC);
8167	bus_dmamap_sync(sc->sc_dmat, rd->rdata_dmap, 0,
8168	    rd->rdata_dmap->dm_mapsize, BUS_DMASYNC_PREWRITE);
8169
8170	addr_lo = __SHIFTOUT(rd->rdata_paddr, BWI_TXRX32_RINGINFO_ADDR_MASK);
8171	addr_hi = __SHIFTOUT(rd->rdata_paddr, BWI_TXRX32_RINGINFO_FUNC_MASK);
8172
8173	val = __SHIFTIN(addr_lo, BWI_TXRX32_RINGINFO_ADDR_MASK) |
8174	    __SHIFTIN(BWI_TXRX32_RINGINFO_FUNC_TXRX,
8175	    BWI_TXRX32_RINGINFO_FUNC_MASK);
8176	CSR_WRITE_4(sc, rd->rdata_txrx_ctrl + BWI_TX32_RINGINFO, val);
8177
8178	val = __SHIFTIN(addr_hi, BWI_TXRX32_CTRL_ADDRHI_MASK) |
8179	      BWI_TXRX32_CTRL_ENABLE;
8180	CSR_WRITE_4(sc, rd->rdata_txrx_ctrl + BWI_TX32_CTRL, val);
8181
8182	return (0);
8183}
8184
8185static void
8186bwi_init_rxdesc_ring32(struct bwi_softc *sc, uint32_t ctrl_base,
8187    bus_addr_t paddr, int hdr_size, int ndesc)
8188{
8189	uint32_t val, addr_hi, addr_lo;
8190
8191	addr_lo = __SHIFTOUT(paddr, BWI_TXRX32_RINGINFO_ADDR_MASK);
8192	addr_hi = __SHIFTOUT(paddr, BWI_TXRX32_RINGINFO_FUNC_MASK);
8193
8194	val = __SHIFTIN(addr_lo, BWI_TXRX32_RINGINFO_ADDR_MASK) |
8195	    __SHIFTIN(BWI_TXRX32_RINGINFO_FUNC_TXRX,
8196	      		BWI_TXRX32_RINGINFO_FUNC_MASK);
8197	CSR_WRITE_4(sc, ctrl_base + BWI_RX32_RINGINFO, val);
8198
8199	val = __SHIFTIN(hdr_size, BWI_RX32_CTRL_HDRSZ_MASK) |
8200	    __SHIFTIN(addr_hi, BWI_TXRX32_CTRL_ADDRHI_MASK) |
8201	    BWI_TXRX32_CTRL_ENABLE;
8202	CSR_WRITE_4(sc, ctrl_base + BWI_RX32_CTRL, val);
8203
8204	CSR_WRITE_4(sc, ctrl_base + BWI_RX32_INDEX,
8205	    (ndesc - 1) * sizeof(struct bwi_desc32));
8206}
8207
8208static int
8209bwi_init_rx_ring32(struct bwi_softc *sc)
8210{
8211	struct bwi_ring_data *rd = &sc->sc_rx_rdata;
8212	int i, error;
8213
8214	sc->sc_rx_bdata.rbd_idx = 0;
8215
8216	for (i = 0; i < BWI_RX_NDESC; ++i) {
8217		error = bwi_newbuf(sc, i, 1);
8218		if (error) {
8219			aprint_error_dev(sc->sc_dev,
8220			    "can't allocate %dth RX buffer\n", i);
8221			return (error);
8222		}
8223	}
8224	bus_dmamap_sync(sc->sc_dmat, rd->rdata_dmap, 0,
8225	    rd->rdata_dmap->dm_mapsize, BUS_DMASYNC_PREWRITE);
8226
8227	bwi_init_rxdesc_ring32(sc, rd->rdata_txrx_ctrl, rd->rdata_paddr,
8228	    sizeof(struct bwi_rxbuf_hdr), BWI_RX_NDESC);
8229	return (0);
8230}
8231
8232static int
8233bwi_init_txstats32(struct bwi_softc *sc)
8234{
8235	struct bwi_txstats_data *st = sc->sc_txstats;
8236	bus_addr_t stats_paddr;
8237	int i;
8238
8239	memset(st->stats, 0, BWI_TXSTATS_NDESC * sizeof(struct bwi_txstats));
8240	bus_dmamap_sync(sc->sc_dmat, st->stats_dmap, 0,
8241	    st->stats_dmap->dm_mapsize, BUS_DMASYNC_PREWRITE);
8242
8243	st->stats_idx = 0;
8244
8245	stats_paddr = st->stats_paddr;
8246	for (i = 0; i < BWI_TXSTATS_NDESC; ++i) {
8247		bwi_setup_desc32(sc, st->stats_ring, BWI_TXSTATS_NDESC, i,
8248				 stats_paddr, sizeof(struct bwi_txstats), 0);
8249		stats_paddr += sizeof(struct bwi_txstats);
8250	}
8251	bus_dmamap_sync(sc->sc_dmat, st->stats_ring_dmap, 0,
8252	    st->stats_ring_dmap->dm_mapsize, BUS_DMASYNC_PREWRITE);
8253
8254	bwi_init_rxdesc_ring32(sc, st->stats_ctrl_base,
8255	    st->stats_ring_paddr, 0, BWI_TXSTATS_NDESC);
8256
8257	return (0);
8258}
8259
8260static void
8261bwi_setup_rx_desc32(struct bwi_softc *sc, int buf_idx, bus_addr_t paddr,
8262    int buf_len)
8263{
8264	struct bwi_ring_data *rd = &sc->sc_rx_rdata;
8265
8266	KASSERT(buf_idx < BWI_RX_NDESC);
8267	bwi_setup_desc32(sc, rd->rdata_desc, BWI_RX_NDESC, buf_idx,
8268	    paddr, buf_len, 0);
8269}
8270
8271static void
8272bwi_setup_tx_desc32(struct bwi_softc *sc, struct bwi_ring_data *rd,
8273    int buf_idx, bus_addr_t paddr, int buf_len)
8274{
8275	KASSERT(buf_idx < BWI_TX_NDESC);
8276	bwi_setup_desc32(sc, rd->rdata_desc, BWI_TX_NDESC, buf_idx,
8277	    paddr, buf_len, 1);
8278}
8279static int
8280bwi_init_tx_ring64(struct bwi_softc *sc, int ring_idx)
8281{
8282	/* TODO: 64 */
8283	return (EOPNOTSUPP);
8284}
8285
8286static int
8287bwi_init_rx_ring64(struct bwi_softc *sc)
8288{
8289	/* TODO: 64 */
8290	return (EOPNOTSUPP);
8291}
8292
8293static int
8294bwi_init_txstats64(struct bwi_softc *sc)
8295{
8296	/* TODO: 64 */
8297	return (EOPNOTSUPP);
8298}
8299
8300static void
8301bwi_setup_rx_desc64(struct bwi_softc *sc, int buf_idx, bus_addr_t paddr,
8302    int buf_len)
8303{
8304	/* TODO: 64 */
8305}
8306
8307static void
8308bwi_setup_tx_desc64(struct bwi_softc *sc, struct bwi_ring_data *rd,
8309    int buf_idx, bus_addr_t paddr, int buf_len)
8310{
8311	/* TODO: 64 */
8312}
8313
8314static int
8315bwi_newbuf(struct bwi_softc *sc, int buf_idx, int init)
8316{
8317	struct bwi_rxbuf_data *rbd = &sc->sc_rx_bdata;
8318	struct bwi_rxbuf *rxbuf = &rbd->rbd_buf[buf_idx];
8319	struct bwi_rxbuf_hdr *hdr;
8320	bus_dmamap_t map;
8321	bus_addr_t paddr;
8322	struct mbuf *m;
8323	int error;
8324
8325	KASSERT(buf_idx < BWI_RX_NDESC);
8326
8327	MGETHDR(m, init ? M_WAITOK : M_DONTWAIT, MT_DATA);
8328	if (m == NULL)
8329		return (ENOBUFS);
8330	MCLGET(m, init ? M_WAITOK : M_DONTWAIT);
8331	if ((m->m_flags & M_EXT) == 0) {
8332		error = ENOBUFS;
8333
8334		/*
8335		 * If the NIC is up and running, we need to:
8336		 * - Clear RX buffer's header.
8337		 * - Restore RX descriptor settings.
8338		 */
8339		if (init)
8340			return error;
8341		else
8342			goto back;
8343	}
8344	m->m_len = m->m_pkthdr.len = MCLBYTES;
8345
8346	/*
8347	 * Try to load RX buf into temporary DMA map
8348	 */
8349	error = bus_dmamap_load_mbuf(sc->sc_dmat, rbd->rbd_tmp_dmap, m,
8350	    init ? BUS_DMA_WAITOK : BUS_DMA_NOWAIT);
8351	if (error) {
8352		m_freem(m);
8353
8354		/*
8355		 * See the comment above
8356		 */
8357		if (init)
8358			return error;
8359		else
8360			goto back;
8361	}
8362
8363	if (!init)
8364		bus_dmamap_unload(sc->sc_dmat, rxbuf->rb_dmap);
8365	rxbuf->rb_mbuf = m;
8366
8367	/*
8368	 * Swap RX buf's DMA map with the loaded temporary one
8369	 */
8370	map = rxbuf->rb_dmap;
8371	rxbuf->rb_dmap = rbd->rbd_tmp_dmap;
8372	rbd->rbd_tmp_dmap = map;
8373	paddr = rxbuf->rb_dmap->dm_segs[0].ds_addr;
8374	rxbuf->rb_paddr = paddr;
8375
8376back:
8377	/*
8378	 * Clear RX buf header
8379	 */
8380	hdr = mtod(rxbuf->rb_mbuf, struct bwi_rxbuf_hdr *);
8381	memset(hdr, 0, sizeof(*hdr));
8382	bus_dmamap_sync(sc->sc_dmat, rxbuf->rb_dmap, 0,
8383	    rxbuf->rb_dmap->dm_mapsize, BUS_DMASYNC_PREWRITE);
8384
8385	/*
8386	 * Setup RX buf descriptor
8387	 */
8388	(sc->sc_setup_rxdesc)(sc, buf_idx, rxbuf->rb_paddr,
8389	    rxbuf->rb_mbuf->m_len - sizeof(*hdr));
8390	return error;
8391}
8392
8393static void
8394bwi_set_addr_filter(struct bwi_softc *sc, uint16_t addr_ofs,
8395    const uint8_t *addr)
8396{
8397	int i;
8398
8399	CSR_WRITE_2(sc, BWI_ADDR_FILTER_CTRL,
8400	    BWI_ADDR_FILTER_CTRL_SET | addr_ofs);
8401
8402	for (i = 0; i < (IEEE80211_ADDR_LEN / 2); ++i) {
8403		uint16_t addr_val;
8404
8405		addr_val = (uint16_t)addr[i * 2] |
8406		    (((uint16_t)addr[(i * 2) + 1]) << 8);
8407		CSR_WRITE_2(sc, BWI_ADDR_FILTER_DATA, addr_val);
8408	}
8409}
8410
8411static int
8412bwi_set_chan(struct bwi_softc *sc, struct ieee80211_channel *c)
8413{
8414	struct ieee80211com *ic = &sc->sc_ic;
8415	struct bwi_mac *mac;
8416	/* uint16_t flags; */ /* [TRC: XXX See below.] */
8417	uint chan;
8418
8419	KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC);
8420	mac = (struct bwi_mac *)sc->sc_cur_regwin;
8421
8422	chan = ieee80211_chan2ieee(ic, c);
8423
8424	bwi_rf_set_chan(mac, chan, 0);
8425
8426	/* [TRC: XXX DragonFlyBSD sets up radio tap channel frequency
8427	   and flags here.  OpenBSD does not, and appears to do so
8428	   later (in bwi_rxeof and bwi_encap).] */
8429
8430	return (0);
8431}
8432
8433static void
8434bwi_next_scan(void *xsc)
8435{
8436	struct bwi_softc *sc = xsc;
8437	struct ieee80211com *ic = &sc->sc_ic;
8438	int s;
8439
8440	s = splnet();
8441
8442	if (ic->ic_state == IEEE80211_S_SCAN)
8443		ieee80211_next_scan(ic);
8444
8445	splx(s);
8446}
8447
8448static int
8449bwi_rxeof(struct bwi_softc *sc, int end_idx)
8450{
8451	struct bwi_ring_data *rd = &sc->sc_rx_rdata;
8452	struct bwi_rxbuf_data *rbd = &sc->sc_rx_bdata;
8453	struct ieee80211com *ic = &sc->sc_ic;
8454	struct ifnet *ifp = &sc->sc_if;
8455	int s, idx, rx_data = 0;
8456
8457	idx = rbd->rbd_idx;
8458	while (idx != end_idx) {
8459		struct bwi_rxbuf *rb = &rbd->rbd_buf[idx];
8460		struct bwi_rxbuf_hdr *hdr;
8461		struct ieee80211_frame_min *wh;
8462		struct ieee80211_node *ni;
8463		struct mbuf *m;
8464		const void *plcp;
8465		uint16_t flags2;
8466		int buflen, wh_ofs, hdr_extra, rssi, type, rate;
8467
8468		m = rb->rb_mbuf;
8469		bus_dmamap_sync(sc->sc_dmat, rb->rb_dmap, 0,
8470		    rb->rb_dmap->dm_mapsize, BUS_DMASYNC_POSTREAD);
8471
8472		if (bwi_newbuf(sc, idx, 0)) {
8473			if_statinc(ifp, if_ierrors);
8474			goto next;
8475		}
8476
8477		hdr = mtod(m, struct bwi_rxbuf_hdr *);
8478		flags2 = le16toh(hdr->rxh_flags2);
8479
8480		hdr_extra = 0;
8481		if (flags2 & BWI_RXH_F2_TYPE2FRAME)
8482			hdr_extra = 2;
8483		wh_ofs = hdr_extra + 6; /* XXX magic number */
8484
8485		buflen = le16toh(hdr->rxh_buflen);
8486		if (buflen < BWI_FRAME_MIN_LEN(wh_ofs)) {
8487			aprint_error_dev(sc->sc_dev, "short frame %d,"
8488			    " hdr_extra %d\n", buflen, hdr_extra);
8489			if_statinc(ifp, if_ierrors);
8490			m_freem(m);
8491			goto next;
8492		}
8493
8494		plcp = ((const uint8_t *)(hdr + 1) + hdr_extra);
8495		rssi = bwi_calc_rssi(sc, hdr);
8496
8497		m_set_rcvif(m, ifp);
8498		m->m_len = m->m_pkthdr.len = buflen + sizeof(*hdr);
8499		m_adj(m, sizeof(*hdr) + wh_ofs);
8500
8501		if (htole16(hdr->rxh_flags1) & BWI_RXH_F1_OFDM)
8502			rate = bwi_ofdm_plcp2rate(plcp);
8503		else
8504			rate = bwi_ds_plcp2rate(plcp);
8505
8506		s = splnet();
8507
8508		/* RX radio tap */
8509		if (sc->sc_drvbpf != NULL) {
8510			struct mbuf mb;
8511			struct bwi_rx_radiotap_hdr *tap = &sc->sc_rxtap;
8512
8513			tap->wr_tsf = hdr->rxh_tsf;
8514			tap->wr_flags = 0;
8515			tap->wr_rate = rate;
8516			tap->wr_chan_freq =
8517			    htole16(ic->ic_bss->ni_chan->ic_freq);
8518			tap->wr_chan_flags =
8519			    htole16(ic->ic_bss->ni_chan->ic_flags);
8520			tap->wr_antsignal = rssi;
8521			tap->wr_antnoise = BWI_NOISE_FLOOR;
8522
8523			mb.m_data = (void *)tap;
8524			mb.m_len = sc->sc_rxtap_len;
8525			mb.m_next = m;
8526			mb.m_nextpkt = NULL;
8527			mb.m_owner = NULL;
8528			mb.m_type = 0;
8529			mb.m_flags = 0;
8530			bpf_mtap3(sc->sc_drvbpf, &mb, BPF_D_IN);
8531		}
8532
8533		m_adj(m, -IEEE80211_CRC_LEN);
8534
8535		wh = mtod(m, struct ieee80211_frame_min *);
8536		ni = ieee80211_find_rxnode(ic, wh);
8537		type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
8538
8539		ieee80211_input(ic, m, ni, hdr->rxh_rssi,
8540		    le16toh(hdr->rxh_tsf));
8541
8542		ieee80211_free_node(ni);
8543
8544		if (type == IEEE80211_FC0_TYPE_DATA) {
8545			rx_data = 1;
8546			sc->sc_rx_rate = rate;
8547		}
8548
8549		splx(s);
8550next:
8551		idx = (idx + 1) % BWI_RX_NDESC;
8552	}
8553
8554	rbd->rbd_idx = idx;
8555	bus_dmamap_sync(sc->sc_dmat, rd->rdata_dmap, 0,
8556	    rd->rdata_dmap->dm_mapsize, BUS_DMASYNC_PREWRITE);
8557
8558	return (rx_data);
8559}
8560
8561static int
8562bwi_rxeof32(struct bwi_softc *sc)
8563{
8564	uint32_t val, rx_ctrl;
8565	int end_idx, rx_data;
8566
8567	rx_ctrl = sc->sc_rx_rdata.rdata_txrx_ctrl;
8568
8569	val = CSR_READ_4(sc, rx_ctrl + BWI_RX32_STATUS);
8570	end_idx = __SHIFTOUT(val, BWI_RX32_STATUS_INDEX_MASK) /
8571	    sizeof(struct bwi_desc32);
8572
8573	rx_data = bwi_rxeof(sc, end_idx);
8574
8575	CSR_WRITE_4(sc, rx_ctrl + BWI_RX32_INDEX,
8576	    end_idx * sizeof(struct bwi_desc32));
8577
8578	return (rx_data);
8579}
8580
8581static int
8582bwi_rxeof64(struct bwi_softc *sc)
8583{
8584	/* TODO: 64 */
8585	return (0);
8586}
8587
8588static void
8589bwi_reset_rx_ring32(struct bwi_softc *sc, uint32_t rx_ctrl)
8590{
8591	int i;
8592
8593	CSR_WRITE_4(sc, rx_ctrl + BWI_RX32_CTRL, 0);
8594
8595#define NRETRY 10
8596	for (i = 0; i < NRETRY; ++i) {
8597		uint32_t status;
8598
8599		status = CSR_READ_4(sc, rx_ctrl + BWI_RX32_STATUS);
8600		if (__SHIFTOUT(status, BWI_RX32_STATUS_STATE_MASK) ==
8601		    BWI_RX32_STATUS_STATE_DISABLED)
8602			break;
8603
8604		DELAY(1000);
8605	}
8606	if (i == NRETRY)
8607		aprint_error_dev(sc->sc_dev, "reset rx ring timedout\n");
8608#undef NRETRY
8609
8610	CSR_WRITE_4(sc, rx_ctrl + BWI_RX32_RINGINFO, 0);
8611}
8612
8613static void
8614bwi_free_txstats32(struct bwi_softc *sc)
8615{
8616	bwi_reset_rx_ring32(sc, sc->sc_txstats->stats_ctrl_base);
8617}
8618
8619static void
8620bwi_free_rx_ring32(struct bwi_softc *sc)
8621{
8622	struct bwi_ring_data *rd = &sc->sc_rx_rdata;
8623	struct bwi_rxbuf_data *rbd = &sc->sc_rx_bdata;
8624	int i;
8625
8626	bwi_reset_rx_ring32(sc, rd->rdata_txrx_ctrl);
8627
8628	for (i = 0; i < BWI_RX_NDESC; ++i) {
8629		struct bwi_rxbuf *rb = &rbd->rbd_buf[i];
8630
8631		if (rb->rb_mbuf != NULL) {
8632			bus_dmamap_unload(sc->sc_dmat, rb->rb_dmap);
8633			m_freem(rb->rb_mbuf);
8634			rb->rb_mbuf = NULL;
8635		}
8636	}
8637}
8638
8639static void
8640bwi_free_tx_ring32(struct bwi_softc *sc, int ring_idx)
8641{
8642	struct bwi_ring_data *rd;
8643	struct bwi_txbuf_data *tbd;
8644	uint32_t state, val;
8645	int i;
8646
8647	KASSERT(ring_idx < BWI_TX_NRING);
8648	rd = &sc->sc_tx_rdata[ring_idx];
8649	tbd = &sc->sc_tx_bdata[ring_idx];
8650
8651#define NRETRY 10
8652	for (i = 0; i < NRETRY; ++i) {
8653		val = CSR_READ_4(sc, rd->rdata_txrx_ctrl + BWI_TX32_STATUS);
8654		state = __SHIFTOUT(val, BWI_TX32_STATUS_STATE_MASK);
8655		if (state == BWI_TX32_STATUS_STATE_DISABLED ||
8656		    state == BWI_TX32_STATUS_STATE_IDLE ||
8657		    state == BWI_TX32_STATUS_STATE_STOPPED)
8658			break;
8659
8660		DELAY(1000);
8661	}
8662	if (i == NRETRY)
8663		aprint_error_dev(sc->sc_dev,
8664		    "wait for TX ring(%d) stable timed out\n", ring_idx);
8665
8666	CSR_WRITE_4(sc, rd->rdata_txrx_ctrl + BWI_TX32_CTRL, 0);
8667	for (i = 0; i < NRETRY; ++i) {
8668		val = CSR_READ_4(sc, rd->rdata_txrx_ctrl + BWI_TX32_STATUS);
8669		state = __SHIFTOUT(val, BWI_TX32_STATUS_STATE_MASK);
8670		if (state == BWI_TX32_STATUS_STATE_DISABLED)
8671			break;
8672
8673		DELAY(1000);
8674	}
8675	if (i == NRETRY)
8676		aprint_error_dev(sc->sc_dev, "reset TX ring (%d) timed out\n",
8677		    ring_idx);
8678#undef NRETRY
8679
8680	DELAY(1000);
8681
8682	CSR_WRITE_4(sc, rd->rdata_txrx_ctrl + BWI_TX32_RINGINFO, 0);
8683
8684	for (i = 0; i < BWI_TX_NDESC; ++i) {
8685		struct bwi_txbuf *tb = &tbd->tbd_buf[i];
8686
8687		if (tb->tb_mbuf != NULL) {
8688			bus_dmamap_unload(sc->sc_dmat, tb->tb_dmap);
8689			m_freem(tb->tb_mbuf);
8690			tb->tb_mbuf = NULL;
8691		}
8692		if (tb->tb_ni != NULL) {
8693			ieee80211_free_node(tb->tb_ni);
8694			tb->tb_ni = NULL;
8695		}
8696	}
8697}
8698
8699static void
8700bwi_free_txstats64(struct bwi_softc *sc)
8701{
8702	/* TODO: 64 */
8703}
8704
8705static void
8706bwi_free_rx_ring64(struct bwi_softc *sc)
8707{
8708	/* TODO: 64 */
8709}
8710
8711static void
8712bwi_free_tx_ring64(struct bwi_softc *sc, int ring_idx)
8713{
8714	/* TODO: 64 */
8715}
8716
8717/* XXX does not belong here */
8718/* [TRC: Begin pilferage from OpenBSD.] */
8719
8720/*
8721 * Convert bit rate (in 0.5Mbps units) to PLCP signal (R4-R1) and vice versa.
8722 */
8723uint8_t
8724bwi_ieee80211_rate2plcp(u_int8_t rate, enum ieee80211_phymode mode)
8725{
8726	rate &= IEEE80211_RATE_VAL;
8727
8728	if (mode == IEEE80211_MODE_11B) {
8729		/* IEEE Std 802.11b-1999 page 15, subclause 18.2.3.3 */
8730		switch (rate) {
8731		case 2:		return 10;
8732		case 4:		return 20;
8733		case 11:	return 55;
8734		case 22:	return 110;
8735		/* IEEE Std 802.11g-2003 page 19, subclause 19.3.2.1 */
8736		case 44:	return 220;
8737		}
8738	} else if (mode == IEEE80211_MODE_11G || mode == IEEE80211_MODE_11A) {
8739		/* IEEE Std 802.11a-1999 page 14, subclause 17.3.4.1 */
8740		switch (rate) {
8741		case 12:	return 0x0b;
8742		case 18:	return 0x0f;
8743		case 24:	return 0x0a;
8744		case 36:	return 0x0e;
8745		case 48:	return 0x09;
8746		case 72:	return 0x0d;
8747		case 96:	return 0x08;
8748		case 108:	return 0x0c;
8749		}
8750        } else
8751		panic("Unexpected mode %u", mode);
8752
8753	return 0;
8754}
8755
8756static uint8_t
8757bwi_ieee80211_plcp2rate(uint8_t plcp, enum ieee80211_phymode mode)
8758{
8759	if (mode == IEEE80211_MODE_11B) {
8760		/* IEEE Std 802.11g-2003 page 19, subclause 19.3.2.1 */
8761		switch (plcp) {
8762		case 10:	return 2;
8763		case 20:	return 4;
8764		case 55:	return 11;
8765		case 110:	return 22;
8766		/* IEEE Std 802.11g-2003 page 19, subclause 19.3.2.1 */
8767		case 220:	return 44;
8768		}
8769	} else if (mode == IEEE80211_MODE_11G || mode == IEEE80211_MODE_11A) {
8770		/* IEEE Std 802.11a-1999 page 14, subclause 17.3.4.1 */
8771		switch (plcp) {
8772		case 0x0b:	return 12;
8773		case 0x0f:	return 18;
8774		case 0x0a:	return 24;
8775		case 0x0e:	return 36;
8776		case 0x09:	return 48;
8777		case 0x0d:	return 72;
8778		case 0x08:	return 96;
8779		case 0x0c:	return 108;
8780		}
8781	} else
8782		panic("Unexpected mode %u", mode);
8783
8784	return 0;
8785}
8786/* [TRC: End pilferage from OpenBSD.] */
8787
8788static enum bwi_ieee80211_modtype
8789bwi_ieee80211_rate2modtype(uint8_t rate)
8790{
8791	rate &= IEEE80211_RATE_VAL;
8792
8793	if (rate == 44)
8794		return (IEEE80211_MODTYPE_PBCC);
8795	else if (rate == 22 || rate < 12)
8796		return (IEEE80211_MODTYPE_DS);
8797	else
8798		return (IEEE80211_MODTYPE_OFDM);
8799}
8800
8801static uint8_t
8802bwi_ofdm_plcp2rate(const void *plcp0)
8803{
8804	uint32_t plcp;
8805	uint8_t plcp_rate;
8806
8807	/* plcp0 may not be 32-bit aligned. */
8808	plcp = le32dec(plcp0);
8809	plcp_rate = __SHIFTOUT(plcp, IEEE80211_OFDM_PLCP_RATE_MASK);
8810
8811	return (bwi_ieee80211_plcp2rate(plcp_rate, IEEE80211_MODE_11G));
8812}
8813
8814static uint8_t
8815bwi_ds_plcp2rate(const struct ieee80211_ds_plcp_hdr *hdr)
8816{
8817	return (bwi_ieee80211_plcp2rate(hdr->i_signal, IEEE80211_MODE_11B));
8818}
8819
8820static void
8821bwi_ofdm_plcp_header(uint32_t *plcp0, int pkt_len, uint8_t rate)
8822{
8823	uint32_t plcp;
8824
8825	plcp = __SHIFTIN(bwi_ieee80211_rate2plcp(rate, IEEE80211_MODE_11G),
8826	    IEEE80211_OFDM_PLCP_RATE_MASK) |
8827	    __SHIFTIN(pkt_len, IEEE80211_OFDM_PLCP_LEN_MASK);
8828	*plcp0 = htole32(plcp);
8829}
8830
8831static void
8832bwi_ds_plcp_header(struct ieee80211_ds_plcp_hdr *plcp, int pkt_len,
8833    uint8_t rate)
8834{
8835	int len, service, pkt_bitlen;
8836
8837	pkt_bitlen = pkt_len * NBBY;
8838	len = howmany(pkt_bitlen * 2, rate);
8839
8840	service = IEEE80211_DS_PLCP_SERVICE_LOCKED;
8841	if (rate == (11 * 2)) {
8842		int pkt_bitlen1;
8843
8844		/*
8845		 * PLCP service field needs to be adjusted,
8846		 * if TX rate is 11Mbytes/s
8847		 */
8848		pkt_bitlen1 = len * 11;
8849		if (pkt_bitlen1 - pkt_bitlen >= NBBY)
8850			service |= IEEE80211_DS_PLCP_SERVICE_LENEXT7;
8851	}
8852
8853	plcp->i_signal = bwi_ieee80211_rate2plcp(rate, IEEE80211_MODE_11B);
8854	plcp->i_service = service;
8855	plcp->i_length = htole16(len);
8856	/* NOTE: do NOT touch i_crc */
8857}
8858
8859static void
8860bwi_plcp_header(void *plcp, int pkt_len, uint8_t rate)
8861{
8862	enum bwi_ieee80211_modtype modtype;
8863
8864	/*
8865	 * Assume caller has zeroed 'plcp'
8866	 */
8867
8868	modtype = bwi_ieee80211_rate2modtype(rate);
8869	if (modtype == IEEE80211_MODTYPE_OFDM)
8870		bwi_ofdm_plcp_header(plcp, pkt_len, rate);
8871	else if (modtype == IEEE80211_MODTYPE_DS)
8872		bwi_ds_plcp_header(plcp, pkt_len, rate);
8873	else
8874		panic("unsupport modulation type %u\n", modtype);
8875}
8876
8877static uint8_t
8878bwi_ieee80211_ack_rate(struct ieee80211_node *ni, uint8_t rate)
8879{
8880	const struct ieee80211_rateset *rs = &ni->ni_rates;
8881	uint8_t ack_rate = 0;
8882	enum bwi_ieee80211_modtype modtype;
8883	int i;
8884
8885	rate &= IEEE80211_RATE_VAL;
8886
8887	modtype = bwi_ieee80211_rate2modtype(rate);
8888
8889	for (i = 0; i < rs->rs_nrates; ++i) {
8890		uint8_t rate1 = rs->rs_rates[i] & IEEE80211_RATE_VAL;
8891
8892		if (rate1 > rate) {
8893			if (ack_rate != 0)
8894				return (ack_rate);
8895			else
8896				break;
8897		}
8898
8899		if ((rs->rs_rates[i] & IEEE80211_RATE_BASIC) &&
8900		    bwi_ieee80211_rate2modtype(rate1) == modtype)
8901			ack_rate = rate1;
8902	}
8903
8904	switch (rate) {
8905	/* CCK */
8906	case 2:
8907	case 4:
8908	case 11:
8909	case 22:
8910		ack_rate = rate;
8911		break;
8912	/* PBCC */
8913	case 44:
8914		ack_rate = 22;
8915		break;
8916
8917	/* OFDM */
8918	case 12:
8919	case 18:
8920		ack_rate = 12;
8921		break;
8922	case 24:
8923	case 36:
8924		ack_rate = 24;
8925		break;
8926	case 48:
8927	case 72:
8928	case 96:
8929	case 108:
8930		ack_rate = 48;
8931		break;
8932	default:
8933		panic("unsupported rate %d\n", rate);
8934	}
8935	return (ack_rate);
8936}
8937
8938/* [TRC: XXX does not belong here] */
8939
8940#define IEEE80211_OFDM_TXTIME(kbps, frmlen)	\
8941	(IEEE80211_OFDM_PREAMBLE_TIME +		\
8942	 IEEE80211_OFDM_SIGNAL_TIME +		\
8943	(IEEE80211_OFDM_NSYMS((kbps), (frmlen)) * IEEE80211_OFDM_SYM_TIME))
8944
8945#define IEEE80211_OFDM_SYM_TIME			4
8946#define IEEE80211_OFDM_PREAMBLE_TIME		16
8947#define IEEE80211_OFDM_SIGNAL_EXT_TIME		6
8948#define IEEE80211_OFDM_SIGNAL_TIME		4
8949
8950#define IEEE80211_OFDM_PLCP_SERVICE_NBITS	16
8951#define IEEE80211_OFDM_TAIL_NBITS		6
8952
8953#define IEEE80211_OFDM_NBITS(frmlen)		\
8954	(IEEE80211_OFDM_PLCP_SERVICE_NBITS +	\
8955	 ((frmlen) * NBBY) +			\
8956	 IEEE80211_OFDM_TAIL_NBITS)
8957
8958#define IEEE80211_OFDM_NBITS_PER_SYM(kbps)	\
8959	(((kbps) * IEEE80211_OFDM_SYM_TIME) / 1000)
8960
8961#define IEEE80211_OFDM_NSYMS(kbps, frmlen)	\
8962	howmany(IEEE80211_OFDM_NBITS((frmlen)),	\
8963	IEEE80211_OFDM_NBITS_PER_SYM((kbps)))
8964
8965#define IEEE80211_CCK_TXTIME(kbps, frmlen)	\
8966	(((IEEE80211_CCK_NBITS((frmlen)) * 1000) + (kbps) - 1) / (kbps))
8967
8968#define IEEE80211_CCK_PREAMBLE_LEN		144
8969#define IEEE80211_CCK_PLCP_HDR_TIME		48
8970#define IEEE80211_CCK_SHPREAMBLE_LEN		72
8971#define IEEE80211_CCK_SHPLCP_HDR_TIME		24
8972
8973#define IEEE80211_CCK_NBITS(frmlen)		((frmlen) * NBBY)
8974
8975static uint16_t
8976bwi_ieee80211_txtime(struct ieee80211com *ic, struct ieee80211_node *ni,
8977    uint len, uint8_t rs_rate, uint32_t flags)
8978{
8979	enum bwi_ieee80211_modtype modtype;
8980	uint16_t txtime;
8981	int rate;
8982
8983	rs_rate &= IEEE80211_RATE_VAL;
8984
8985	rate = rs_rate * 500;	/* ieee80211 rate -> kbps */
8986
8987	modtype = bwi_ieee80211_rate2modtype(rs_rate);
8988	if (modtype == IEEE80211_MODTYPE_OFDM) {
8989		/*
8990		 * IEEE Std 802.11a-1999, page 37, equation (29)
8991		 * IEEE Std 802.11g-2003, page 44, equation (42)
8992		 */
8993		txtime = IEEE80211_OFDM_TXTIME(rate, len);
8994		if (ic->ic_curmode == IEEE80211_MODE_11G)
8995			txtime += IEEE80211_OFDM_SIGNAL_EXT_TIME;
8996	} else {
8997		/*
8998		 * IEEE Std 802.11b-1999, page 28, subclause 18.3.4
8999		 * IEEE Std 802.11g-2003, page 45, equation (43)
9000		 */
9001		if (modtype == IEEE80211_MODTYPE_PBCC)
9002			++len;
9003		txtime = IEEE80211_CCK_TXTIME(rate, len);
9004
9005		/*
9006		 * Short preamble is not applicable for DS 1Mbits/s
9007		 */
9008		if (rs_rate != 2 && (flags & IEEE80211_F_SHPREAMBLE)) {
9009			txtime += IEEE80211_CCK_SHPREAMBLE_LEN +
9010				  IEEE80211_CCK_SHPLCP_HDR_TIME;
9011		} else {
9012			txtime += IEEE80211_CCK_PREAMBLE_LEN +
9013				  IEEE80211_CCK_PLCP_HDR_TIME;
9014		}
9015	}
9016	return (txtime);
9017}
9018
9019static int
9020bwi_encap(struct bwi_softc *sc, int idx, struct mbuf *m,
9021    struct ieee80211_node **nip, int mgt_pkt)
9022{
9023	struct ieee80211com *ic = &sc->sc_ic;
9024	struct ieee80211_node *ni = *nip;
9025	struct bwi_ring_data *rd = &sc->sc_tx_rdata[BWI_TX_DATA_RING];
9026	struct bwi_txbuf_data *tbd = &sc->sc_tx_bdata[BWI_TX_DATA_RING];
9027	struct bwi_txbuf *tb = &tbd->tbd_buf[idx];
9028	struct bwi_mac *mac;
9029	struct bwi_txbuf_hdr *hdr;
9030	struct ieee80211_frame *wh;
9031	uint8_t rate;		/* [TRC: XXX Use a fallback rate?] */
9032	uint32_t mac_ctrl;
9033	uint16_t phy_ctrl;
9034	bus_addr_t paddr;
9035	int pkt_len, error, mcast_pkt = 0;
9036#if 0
9037	const uint8_t *p;
9038	int i;
9039#endif
9040
9041	KASSERT(ni != NULL);
9042	KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC);
9043	mac = (struct bwi_mac *)sc->sc_cur_regwin;
9044
9045	wh = mtod(m, struct ieee80211_frame *);
9046
9047	/* Get 802.11 frame len before prepending TX header */
9048	pkt_len = m->m_pkthdr.len + IEEE80211_CRC_LEN;
9049
9050	/*
9051	 * Find TX rate
9052	 */
9053	memset(tb->tb_rate_idx, 0, sizeof(tb->tb_rate_idx));
9054	if (!mgt_pkt) {
9055		if (ic->ic_fixed_rate != -1) {
9056			rate = ic->ic_sup_rates[ic->ic_curmode].
9057			    rs_rates[ic->ic_fixed_rate];
9058			/* [TRC: XXX Set fallback rate.] */
9059		} else {
9060			/* AMRR rate control */
9061			/* [TRC: XXX amrr] */
9062			/* rate = ni->ni_rates.rs_rates[ni->ni_txrate]; */
9063			rate = (1 * 2);
9064			/* [TRC: XXX Set fallback rate.] */
9065		}
9066	} else {
9067		/* Fixed at 1Mbits/s for mgt frames */
9068		/* [TRC: XXX Set fallback rate.] */
9069		rate = (1 * 2);
9070	}
9071
9072	rate &= IEEE80211_RATE_VAL;
9073
9074	if (IEEE80211_IS_MULTICAST(wh->i_addr1)) {
9075		/* [TRC: XXX Set fallback rate.] */
9076		rate = ic->ic_mcast_rate;
9077		mcast_pkt = 1;
9078	}
9079
9080	/* [TRC: XXX Check fallback rate.] */
9081	if (rate == 0) {
9082		aprint_error_dev(sc->sc_dev, "invalid rate %u", rate);
9083		/* [TRC: In the margin of the following line,
9084		   DragonFlyBSD writes `Force 1Mbits/s', whereas
9085		   OpenBSD writes `Force 1Mbytes/s'.] */
9086		rate = (1 * 2);
9087		/* [TRC: XXX Set fallback rate.] */
9088	}
9089	sc->sc_tx_rate = rate;
9090
9091	/* TX radio tap */
9092	if (sc->sc_drvbpf != NULL) {
9093		struct mbuf mb;
9094		struct bwi_tx_radiotap_hdr *tap = &sc->sc_txtap;
9095
9096		tap->wt_flags = 0;
9097		tap->wt_rate = rate;
9098		tap->wt_chan_freq =
9099		    htole16(ic->ic_bss->ni_chan->ic_freq);
9100		tap->wt_chan_flags =
9101		    htole16(ic->ic_bss->ni_chan->ic_flags);
9102
9103		mb.m_data = (void *)tap;
9104		mb.m_len = sc->sc_txtap_len;
9105		mb.m_next = m;
9106		mb.m_nextpkt = NULL;
9107		mb.m_type = 0;
9108		mb.m_flags = 0;
9109		bpf_mtap3(sc->sc_drvbpf, &mb, BPF_D_OUT);
9110	}
9111
9112	/*
9113	 * Setup the embedded TX header
9114	 */
9115	M_PREPEND(m, sizeof(*hdr), M_DONTWAIT);
9116	if (m == NULL) {
9117		aprint_error_dev(sc->sc_dev, "prepend TX header failed\n");
9118		return (ENOBUFS);
9119	}
9120	hdr = mtod(m, struct bwi_txbuf_hdr *);
9121
9122	memset(hdr, 0, sizeof(*hdr));
9123
9124	memcpy(hdr->txh_fc, wh->i_fc, sizeof(hdr->txh_fc));
9125	memcpy(hdr->txh_addr1, wh->i_addr1, sizeof(hdr->txh_addr1));
9126
9127	if (!mcast_pkt) {
9128		uint16_t dur;
9129		uint8_t ack_rate;
9130
9131		/* [TRC: XXX Set fallback rate.] */
9132		ack_rate = bwi_ieee80211_ack_rate(ni, rate);
9133		dur = bwi_ieee80211_txtime(ic, ni,
9134		    sizeof(struct ieee80211_frame_ack) + IEEE80211_CRC_LEN,
9135		    ack_rate, ic->ic_flags & IEEE80211_F_SHPREAMBLE);
9136
9137		hdr->txh_fb_duration = htole16(dur);
9138	}
9139
9140	hdr->txh_id = htole16(
9141	    __SHIFTIN(BWI_TX_DATA_RING, BWI_TXH_ID_RING_MASK) |
9142	    __SHIFTIN(idx, BWI_TXH_ID_IDX_MASK));
9143
9144	bwi_plcp_header(hdr->txh_plcp, pkt_len, rate);
9145	/* [TRC: XXX Use fallback rate.] */
9146	bwi_plcp_header(hdr->txh_fb_plcp, pkt_len, rate);
9147
9148	phy_ctrl = __SHIFTIN(mac->mac_rf.rf_ant_mode,
9149	    BWI_TXH_PHY_C_ANTMODE_MASK);
9150	if (bwi_ieee80211_rate2modtype(rate) == IEEE80211_MODTYPE_OFDM)
9151		phy_ctrl |= BWI_TXH_PHY_C_OFDM;
9152	else if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) && rate != (2 * 1))
9153		phy_ctrl |= BWI_TXH_PHY_C_SHPREAMBLE;
9154
9155	mac_ctrl = BWI_TXH_MAC_C_HWSEQ | BWI_TXH_MAC_C_FIRST_FRAG;
9156	if (!IEEE80211_IS_MULTICAST(wh->i_addr1))
9157		mac_ctrl |= BWI_TXH_MAC_C_ACK;
9158	if (bwi_ieee80211_rate2modtype(rate) == IEEE80211_MODTYPE_OFDM)
9159		mac_ctrl |= BWI_TXH_MAC_C_FB_OFDM;
9160
9161	hdr->txh_mac_ctrl = htole32(mac_ctrl);
9162	hdr->txh_phy_ctrl = htole16(phy_ctrl);
9163
9164	/* Catch any further usage */
9165	hdr = NULL;
9166	wh = NULL;
9167
9168	/* DMA load */
9169	error = bus_dmamap_load_mbuf(sc->sc_dmat, tb->tb_dmap, m,
9170	    BUS_DMA_NOWAIT);
9171	if (error && error != EFBIG) {
9172		aprint_error_dev(sc->sc_dev, "can't load TX buffer (1) %d\n",
9173		    error);
9174		goto back;
9175	}
9176
9177	if (error) {	/* error == EFBIG */
9178		struct mbuf *m_new;
9179
9180		error = 0;
9181
9182		MGETHDR(m_new, M_DONTWAIT, MT_DATA);
9183		if (m_new == NULL) {
9184			error = ENOBUFS;
9185			aprint_error_dev(sc->sc_dev,
9186			    "can't defrag TX buffer (1)\n");
9187			goto back;
9188		}
9189
9190		m_copy_pkthdr(m_new, m);
9191		if (m->m_pkthdr.len > MHLEN) {
9192			MCLGET(m_new, M_DONTWAIT);
9193			if (!(m_new->m_flags & M_EXT)) {
9194				m_freem(m_new);
9195				error = ENOBUFS;
9196			}
9197		}
9198
9199		if (error) {
9200			aprint_error_dev(sc->sc_dev,
9201			    "can't defrag TX buffer (2)\n");
9202			goto back;
9203		}
9204
9205		m_copydata(m, 0, m->m_pkthdr.len, mtod(m_new, void *));
9206		m_freem(m);
9207		m_new->m_len = m_new->m_pkthdr.len;
9208		m = m_new;
9209
9210		error = bus_dmamap_load_mbuf(sc->sc_dmat, tb->tb_dmap, m,
9211		    BUS_DMA_NOWAIT);
9212		if (error) {
9213			aprint_error_dev(sc->sc_dev,
9214			    "can't load TX buffer (2) %d\n", error);
9215			goto back;
9216		}
9217	}
9218	error = 0;
9219
9220	bus_dmamap_sync(sc->sc_dmat, tb->tb_dmap, 0,
9221	    tb->tb_dmap->dm_mapsize, BUS_DMASYNC_PREWRITE);
9222
9223	if (mgt_pkt || mcast_pkt) {
9224		/* Don't involve mcast/mgt packets into TX rate control */
9225		ieee80211_free_node(ni);
9226		*nip = ni = NULL;
9227	}
9228
9229	tb->tb_mbuf = m;
9230	tb->tb_ni = ni;
9231
9232#if 0
9233	p = mtod(m, const uint8_t *);
9234	for (i = 0; i < m->m_pkthdr.len; ++i) {
9235		if (i % 8 == 0) {
9236			if (i != 0)
9237				aprint_debug("\n");
9238			aprint_debug_dev(sc->sc_dev, "");
9239		}
9240		aprint_debug(" %02x", p[i]);
9241	}
9242	aprint_debug("\n");
9243#endif
9244
9245	DPRINTF(sc, BWI_DBG_TX, "idx %d, pkt_len %d, buflen %d\n",
9246	    idx, pkt_len, m->m_pkthdr.len);
9247
9248	/* Setup TX descriptor */
9249	paddr = tb->tb_dmap->dm_segs[0].ds_addr;
9250	(sc->sc_setup_txdesc)(sc, rd, idx, paddr, m->m_pkthdr.len);
9251	bus_dmamap_sync(sc->sc_dmat, rd->rdata_dmap, 0,
9252	    rd->rdata_dmap->dm_mapsize, BUS_DMASYNC_PREWRITE);
9253
9254	/* Kick start */
9255	(sc->sc_start_tx)(sc, rd->rdata_txrx_ctrl, idx);
9256
9257back:
9258	if (error)
9259		m_freem(m);
9260	return (error);
9261}
9262
9263static void
9264bwi_start_tx32(struct bwi_softc *sc, uint32_t tx_ctrl, int idx)
9265{
9266	idx = (idx + 1) % BWI_TX_NDESC;
9267	CSR_WRITE_4(sc, tx_ctrl + BWI_TX32_INDEX,
9268	    idx * sizeof(struct bwi_desc32));
9269}
9270
9271static void
9272bwi_start_tx64(struct bwi_softc *sc, uint32_t tx_ctrl, int idx)
9273{
9274	/* TODO: 64 */
9275}
9276
9277static void
9278bwi_txeof_status32(struct bwi_softc *sc)
9279{
9280	struct ifnet *ifp = &sc->sc_if;
9281	uint32_t val, ctrl_base;
9282	int end_idx, s;
9283
9284	s = splnet();
9285
9286	ctrl_base = sc->sc_txstats->stats_ctrl_base;
9287
9288	val = CSR_READ_4(sc, ctrl_base + BWI_RX32_STATUS);
9289	end_idx = __SHIFTOUT(val, BWI_RX32_STATUS_INDEX_MASK) /
9290	    sizeof(struct bwi_desc32);
9291
9292	bwi_txeof_status(sc, end_idx);
9293
9294	CSR_WRITE_4(sc, ctrl_base + BWI_RX32_INDEX,
9295	    end_idx * sizeof(struct bwi_desc32));
9296
9297	if ((ifp->if_flags & IFF_OACTIVE) == 0)
9298		ifp->if_start(ifp); /* [TRC: XXX Why not bwi_start?] */
9299
9300	splx(s);
9301}
9302
9303static void
9304bwi_txeof_status64(struct bwi_softc *sc)
9305{
9306	/* TODO: 64 */
9307}
9308
9309static void
9310_bwi_txeof(struct bwi_softc *sc, uint16_t tx_id)
9311{
9312	struct ifnet *ifp = &sc->sc_if;
9313	struct bwi_txbuf_data *tbd;
9314	struct bwi_txbuf *tb;
9315	int ring_idx, buf_idx;
9316
9317	if (tx_id == 0) {
9318		/* [TRC: XXX What is the severity of this message?] */
9319		aprint_normal_dev(sc->sc_dev, "zero tx id\n");
9320		return;
9321	}
9322
9323	ring_idx = __SHIFTOUT(tx_id, BWI_TXH_ID_RING_MASK);
9324	buf_idx = __SHIFTOUT(tx_id, BWI_TXH_ID_IDX_MASK);
9325
9326	KASSERT(ring_idx == BWI_TX_DATA_RING);
9327	KASSERT(buf_idx < BWI_TX_NDESC);
9328	tbd = &sc->sc_tx_bdata[ring_idx];
9329	KASSERT(tbd->tbd_used > 0);
9330	tbd->tbd_used--;
9331
9332	tb = &tbd->tbd_buf[buf_idx];
9333
9334	bus_dmamap_unload(sc->sc_dmat, tb->tb_dmap);
9335	m_freem(tb->tb_mbuf);
9336	tb->tb_mbuf = NULL;
9337
9338	if (tb->tb_ni != NULL) {
9339		ieee80211_free_node(tb->tb_ni);
9340		tb->tb_ni = NULL;
9341	}
9342
9343	if (tbd->tbd_used == 0)
9344		sc->sc_tx_timer = 0;
9345
9346	ifp->if_flags &= ~IFF_OACTIVE;
9347}
9348
9349static void
9350bwi_txeof_status(struct bwi_softc *sc, int end_idx)
9351{
9352	struct bwi_txstats_data *st = sc->sc_txstats;
9353	int idx;
9354
9355	bus_dmamap_sync(sc->sc_dmat, st->stats_dmap, 0,
9356	    st->stats_dmap->dm_mapsize, BUS_DMASYNC_POSTREAD);
9357
9358	idx = st->stats_idx;
9359	while (idx != end_idx) {
9360		/* [TRC: XXX Filter this out if it is not pending; see
9361		   DragonFlyBSD's revision 1.5. */
9362		_bwi_txeof(sc, le16toh(st->stats[idx].txs_id));
9363		idx = (idx + 1) % BWI_TXSTATS_NDESC;
9364	}
9365	st->stats_idx = idx;
9366}
9367
9368static void
9369bwi_txeof(struct bwi_softc *sc)
9370{
9371	struct ifnet *ifp = &sc->sc_if;
9372	int s;
9373
9374	s = splnet();
9375
9376	for (;;) {
9377		uint32_t tx_status0;
9378		uint16_t tx_id, tx_info;
9379
9380		tx_status0 = CSR_READ_4(sc, BWI_TXSTATUS_0);
9381		if ((tx_status0 & BWI_TXSTATUS_0_MORE) == 0)
9382			break;
9383		(void)CSR_READ_4(sc, BWI_TXSTATUS_1);
9384
9385		tx_id = __SHIFTOUT(tx_status0, BWI_TXSTATUS_0_TXID_MASK);
9386		tx_info = BWI_TXSTATUS_0_INFO(tx_status0);
9387
9388		if (tx_info & 0x30) /* XXX */
9389			continue;
9390
9391		_bwi_txeof(sc, tx_id);
9392
9393		if_statinc(ifp, if_opackets);
9394	}
9395
9396	if ((ifp->if_flags & IFF_OACTIVE) == 0)
9397		ifp->if_start(ifp);
9398
9399	splx(s);
9400}
9401
9402static int
9403bwi_bbp_power_on(struct bwi_softc *sc, enum bwi_clock_mode clk_mode)
9404{
9405	bwi_power_on(sc, 1);
9406
9407	return (bwi_set_clock_mode(sc, clk_mode));
9408}
9409
9410static void
9411bwi_bbp_power_off(struct bwi_softc *sc)
9412{
9413	bwi_set_clock_mode(sc, BWI_CLOCK_MODE_SLOW);
9414	bwi_power_off(sc, 1);
9415}
9416
9417static int
9418bwi_get_pwron_delay(struct bwi_softc *sc)
9419{
9420	struct bwi_regwin *com, *old;
9421	struct bwi_clock_freq freq;
9422	uint32_t val;
9423	int error;
9424
9425	com = &sc->sc_com_regwin;
9426	KASSERT(BWI_REGWIN_EXIST(com));
9427
9428	if ((sc->sc_cap & BWI_CAP_CLKMODE) == 0)
9429		return (0);
9430
9431	error = bwi_regwin_switch(sc, com, &old);
9432	if (error)
9433		return (error);
9434
9435	bwi_get_clock_freq(sc, &freq);
9436
9437	val = CSR_READ_4(sc, BWI_PLL_ON_DELAY);
9438	sc->sc_pwron_delay = howmany((val + 2) * 1000000, freq.clkfreq_min);
9439	DPRINTF(sc, BWI_DBG_ATTACH, "power on delay %u\n", sc->sc_pwron_delay);
9440
9441	return (bwi_regwin_switch(sc, old, NULL));
9442}
9443
9444static int
9445bwi_bus_attach(struct bwi_softc *sc)
9446{
9447	struct bwi_regwin *bus, *old;
9448	int error;
9449
9450	bus = &sc->sc_bus_regwin;
9451
9452	error = bwi_regwin_switch(sc, bus, &old);
9453	if (error)
9454		return (error);
9455
9456	if (!bwi_regwin_is_enabled(sc, bus))
9457		bwi_regwin_enable(sc, bus, 0);
9458
9459	/* Disable interripts */
9460	CSR_WRITE_4(sc, BWI_INTRVEC, 0);
9461
9462	return (bwi_regwin_switch(sc, old, NULL));
9463}
9464
9465static const char *
9466bwi_regwin_name(const struct bwi_regwin *rw)
9467{
9468	switch (rw->rw_type) {
9469	case BWI_REGWIN_T_COM:
9470		return ("COM");
9471	case BWI_REGWIN_T_BUSPCI:
9472		return ("PCI");
9473	case BWI_REGWIN_T_MAC:
9474		return ("MAC");
9475	case BWI_REGWIN_T_BUSPCIE:
9476		return ("PCIE");
9477	}
9478	panic("unknown regwin type 0x%04x\n", rw->rw_type);
9479
9480	return (NULL);
9481}
9482
9483static uint32_t
9484bwi_regwin_disable_bits(struct bwi_softc *sc)
9485{
9486	uint32_t busrev;
9487
9488	/* XXX cache this */
9489	busrev = __SHIFTOUT(CSR_READ_4(sc, BWI_ID_LO), BWI_ID_LO_BUSREV_MASK);
9490	DPRINTF(sc, BWI_DBG_ATTACH | BWI_DBG_INIT | BWI_DBG_MISC,
9491	    "bus rev %u\n", busrev);
9492
9493	if (busrev == BWI_BUSREV_0)
9494		return (BWI_STATE_LO_DISABLE1);
9495	else if (busrev == BWI_BUSREV_1)
9496		return (BWI_STATE_LO_DISABLE2);
9497	else
9498		return (BWI_STATE_LO_DISABLE1 | BWI_STATE_LO_DISABLE2);
9499}
9500
9501static int
9502bwi_regwin_is_enabled(struct bwi_softc *sc, struct bwi_regwin *rw)
9503{
9504	uint32_t val, disable_bits;
9505
9506	disable_bits = bwi_regwin_disable_bits(sc);
9507	val = CSR_READ_4(sc, BWI_STATE_LO);
9508
9509	if ((val & (BWI_STATE_LO_CLOCK |
9510		    BWI_STATE_LO_RESET |
9511		    disable_bits)) == BWI_STATE_LO_CLOCK) {
9512		DPRINTF(sc, BWI_DBG_ATTACH | BWI_DBG_INIT, "%s is enabled\n",
9513		    bwi_regwin_name(rw));
9514		return (1);
9515	} else {
9516		DPRINTF(sc, BWI_DBG_ATTACH | BWI_DBG_INIT, "%s is disabled\n",
9517		    bwi_regwin_name(rw));
9518		return (0);
9519	}
9520}
9521
9522static void
9523bwi_regwin_disable(struct bwi_softc *sc, struct bwi_regwin *rw, uint32_t flags)
9524{
9525	uint32_t state_lo, disable_bits;
9526	int i;
9527
9528	state_lo = CSR_READ_4(sc, BWI_STATE_LO);
9529
9530	/*
9531	 * If current regwin is in 'reset' state, it was already disabled.
9532	 */
9533	if (state_lo & BWI_STATE_LO_RESET) {
9534		DPRINTF(sc, BWI_DBG_ATTACH | BWI_DBG_INIT,
9535		    "%s was already disabled\n", bwi_regwin_name(rw));
9536		return;
9537	}
9538
9539	disable_bits = bwi_regwin_disable_bits(sc);
9540
9541	/*
9542	 * Disable normal clock
9543	 */
9544	state_lo = BWI_STATE_LO_CLOCK | disable_bits;
9545	CSR_WRITE_4(sc, BWI_STATE_LO, state_lo);
9546
9547	/*
9548	 * Wait until normal clock is disabled
9549	 */
9550#define NRETRY	1000
9551	for (i = 0; i < NRETRY; ++i) {
9552		state_lo = CSR_READ_4(sc, BWI_STATE_LO);
9553		if (state_lo & disable_bits)
9554			break;
9555		DELAY(10);
9556	}
9557	if (i == NRETRY) {
9558		aprint_error_dev(sc->sc_dev, "%s disable clock timeout\n",
9559		    bwi_regwin_name(rw));
9560	}
9561
9562	for (i = 0; i < NRETRY; ++i) {
9563		uint32_t state_hi;
9564
9565		state_hi = CSR_READ_4(sc, BWI_STATE_HI);
9566		if ((state_hi & BWI_STATE_HI_BUSY) == 0)
9567			break;
9568		DELAY(10);
9569	}
9570	if (i == NRETRY) {
9571		aprint_error_dev(sc->sc_dev, "%s wait BUSY unset timeout\n",
9572		    bwi_regwin_name(rw));
9573	}
9574#undef NRETRY
9575
9576	/*
9577	 * Reset and disable regwin with gated clock
9578	 */
9579	state_lo = BWI_STATE_LO_RESET | disable_bits |
9580	    BWI_STATE_LO_CLOCK | BWI_STATE_LO_GATED_CLOCK |
9581	    __SHIFTIN(flags, BWI_STATE_LO_FLAGS_MASK);
9582	CSR_WRITE_4(sc, BWI_STATE_LO, state_lo);
9583
9584	/* Flush pending bus write */
9585	CSR_READ_4(sc, BWI_STATE_LO);
9586	DELAY(1);
9587
9588	/* Reset and disable regwin */
9589	state_lo = BWI_STATE_LO_RESET | disable_bits |
9590		   __SHIFTIN(flags, BWI_STATE_LO_FLAGS_MASK);
9591	CSR_WRITE_4(sc, BWI_STATE_LO, state_lo);
9592
9593	/* Flush pending bus write */
9594	CSR_READ_4(sc, BWI_STATE_LO);
9595	DELAY(1);
9596}
9597
9598static void
9599bwi_regwin_enable(struct bwi_softc *sc, struct bwi_regwin *rw, uint32_t flags)
9600{
9601	uint32_t state_lo, state_hi, imstate;
9602
9603	bwi_regwin_disable(sc, rw, flags);
9604
9605	/* Reset regwin with gated clock */
9606	state_lo = BWI_STATE_LO_RESET |
9607	    BWI_STATE_LO_CLOCK |
9608	    BWI_STATE_LO_GATED_CLOCK |
9609	    __SHIFTIN(flags, BWI_STATE_LO_FLAGS_MASK);
9610	CSR_WRITE_4(sc, BWI_STATE_LO, state_lo);
9611
9612	/* Flush pending bus write */
9613	CSR_READ_4(sc, BWI_STATE_LO);
9614	DELAY(1);
9615
9616	state_hi = CSR_READ_4(sc, BWI_STATE_HI);
9617	if (state_hi & BWI_STATE_HI_SERROR)
9618		CSR_WRITE_4(sc, BWI_STATE_HI, 0);
9619
9620	imstate = CSR_READ_4(sc, BWI_IMSTATE);
9621	if (imstate & (BWI_IMSTATE_INBAND_ERR | BWI_IMSTATE_TIMEOUT)) {
9622		imstate &= ~(BWI_IMSTATE_INBAND_ERR | BWI_IMSTATE_TIMEOUT);
9623		CSR_WRITE_4(sc, BWI_IMSTATE, imstate);
9624	}
9625
9626	/* Enable regwin with gated clock */
9627	state_lo = BWI_STATE_LO_CLOCK |
9628	    BWI_STATE_LO_GATED_CLOCK |
9629	    __SHIFTIN(flags, BWI_STATE_LO_FLAGS_MASK);
9630	CSR_WRITE_4(sc, BWI_STATE_LO, state_lo);
9631
9632	/* Flush pending bus write */
9633	CSR_READ_4(sc, BWI_STATE_LO);
9634	DELAY(1);
9635
9636	/* Enable regwin with normal clock */
9637	state_lo = BWI_STATE_LO_CLOCK |
9638	    __SHIFTIN(flags, BWI_STATE_LO_FLAGS_MASK);
9639	CSR_WRITE_4(sc, BWI_STATE_LO, state_lo);
9640
9641	/* Flush pending bus write */
9642	CSR_READ_4(sc, BWI_STATE_LO);
9643	DELAY(1);
9644}
9645
9646static void
9647bwi_set_bssid(struct bwi_softc *sc, const uint8_t *bssid)
9648{
9649	struct ieee80211com *ic = &sc->sc_ic;
9650	struct bwi_mac *mac;
9651	struct bwi_myaddr_bssid buf;
9652	const uint8_t *p;
9653	uint32_t val;
9654	int n, i;
9655
9656	KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC);
9657	mac = (struct bwi_mac *)sc->sc_cur_regwin;
9658
9659	bwi_set_addr_filter(sc, BWI_ADDR_FILTER_BSSID, bssid);
9660
9661	memcpy(buf.myaddr, ic->ic_myaddr, sizeof(buf.myaddr));
9662	memcpy(buf.bssid, bssid, sizeof(buf.bssid));
9663
9664	n = sizeof(buf) / sizeof(val);
9665	p = (const uint8_t *)&buf;
9666	for (i = 0; i < n; ++i) {
9667		int j;
9668
9669		val = 0;
9670		for (j = 0; j < sizeof(val); ++j)
9671			val |= ((uint32_t)(*p++)) << (j * 8);
9672
9673		TMPLT_WRITE_4(mac, 0x20 + (i * sizeof(val)), val);
9674	}
9675}
9676
9677static void
9678bwi_updateslot(struct ifnet *ifp)
9679{
9680	struct bwi_softc *sc = ifp->if_softc;
9681	struct ieee80211com *ic = &sc->sc_ic;
9682	struct bwi_mac *mac;
9683
9684	if ((ifp->if_flags & IFF_RUNNING) == 0)
9685		return;
9686
9687	DPRINTF(sc, BWI_DBG_80211, "%s\n", __func__);
9688
9689	KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC);
9690	mac = (struct bwi_mac *)sc->sc_cur_regwin;
9691
9692	bwi_mac_updateslot(mac, (ic->ic_flags & IEEE80211_F_SHSLOT));
9693}
9694
9695static void
9696bwi_calibrate(void *xsc)
9697{
9698	struct bwi_softc *sc = xsc;
9699	struct ieee80211com *ic = &sc->sc_ic;
9700	int s;
9701
9702	s = splnet();
9703
9704	if (ic->ic_state == IEEE80211_S_RUN) {
9705		struct bwi_mac *mac;
9706
9707		KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC);
9708		mac = (struct bwi_mac *)sc->sc_cur_regwin;
9709
9710		if (ic->ic_opmode != IEEE80211_M_MONITOR) {
9711			bwi_mac_calibrate_txpower(mac, sc->sc_txpwrcb_type);
9712			sc->sc_txpwrcb_type = BWI_TXPWR_CALIB;
9713		}
9714
9715		/* XXX 15 seconds */
9716		callout_schedule(&sc->sc_calib_ch, hz * 15);
9717	}
9718
9719	splx(s);
9720}
9721
9722static int
9723bwi_calc_rssi(struct bwi_softc *sc, const struct bwi_rxbuf_hdr *hdr)
9724{
9725	struct bwi_mac *mac;
9726
9727	KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC);
9728	mac = (struct bwi_mac *)sc->sc_cur_regwin;
9729
9730	return (bwi_rf_calc_rssi(mac, hdr));
9731}
9732
9733bool
9734bwi_suspend(device_t dv, const pmf_qual_t *qual)
9735{
9736	struct bwi_softc *sc = device_private(dv);
9737
9738	bwi_power_off(sc, 0);
9739	if (sc->sc_disable != NULL)
9740		(sc->sc_disable)(sc, 1);
9741
9742	return true;
9743}
9744
9745bool
9746bwi_resume(device_t dv, const pmf_qual_t *qual)
9747{
9748	struct bwi_softc *sc = device_private(dv);
9749
9750	if (sc->sc_enable != NULL)
9751		(sc->sc_enable)(sc, 1);
9752	bwi_power_on(sc, 1);
9753
9754	return true;
9755}
9756