xref: /freebsd/sys/dev/bwn/if_bwn_phy_g.c (revision 243e928310d073338c5ec089f0dce238a80b9866)
1 /*-
2  * Copyright (c) 2009-2010 Weongyo Jeong <weongyo@freebsd.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer,
10  *    without modification.
11  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13  *    redistribution must be conditioned upon including a substantially
14  *    similar Disclaimer requirement for further binary redistribution.
15  *
16  * NO WARRANTY
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
20  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
22  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27  * THE POSSIBILITY OF SUCH DAMAGES.
28  */
29 
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32 
33 #include "opt_bwn.h"
34 #include "opt_wlan.h"
35 
36 /*
37  * The Broadcom Wireless LAN controller driver.
38  */
39 
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/kernel.h>
43 #include <sys/malloc.h>
44 #include <sys/module.h>
45 #include <sys/endian.h>
46 #include <sys/errno.h>
47 #include <sys/firmware.h>
48 #include <sys/lock.h>
49 #include <sys/mutex.h>
50 #include <machine/bus.h>
51 #include <machine/resource.h>
52 #include <sys/bus.h>
53 #include <sys/rman.h>
54 #include <sys/socket.h>
55 #include <sys/sockio.h>
56 
57 #include <net/ethernet.h>
58 #include <net/if.h>
59 #include <net/if_var.h>
60 #include <net/if_arp.h>
61 #include <net/if_dl.h>
62 #include <net/if_llc.h>
63 #include <net/if_media.h>
64 #include <net/if_types.h>
65 
66 #include <dev/pci/pcivar.h>
67 #include <dev/pci/pcireg.h>
68 #include <dev/siba/siba_ids.h>
69 #include <dev/siba/sibareg.h>
70 #include <dev/siba/sibavar.h>
71 
72 #include <net80211/ieee80211_var.h>
73 #include <net80211/ieee80211_radiotap.h>
74 #include <net80211/ieee80211_regdomain.h>
75 #include <net80211/ieee80211_phy.h>
76 #include <net80211/ieee80211_ratectl.h>
77 
78 #include <dev/bwn/if_bwnreg.h>
79 #include <dev/bwn/if_bwnvar.h>
80 
81 #include <dev/bwn/if_bwn_debug.h>
82 #include <dev/bwn/if_bwn_misc.h>
83 #include <dev/bwn/if_bwn_phy_g.h>
84 
85 static void	bwn_phy_g_init_sub(struct bwn_mac *);
86 static uint8_t	bwn_has_hwpctl(struct bwn_mac *);
87 static void	bwn_phy_init_b5(struct bwn_mac *);
88 static void	bwn_phy_init_b6(struct bwn_mac *);
89 static void	bwn_phy_init_a(struct bwn_mac *);
90 static void	bwn_loopback_calcgain(struct bwn_mac *);
91 static uint16_t	bwn_rf_init_bcm2050(struct bwn_mac *);
92 static void	bwn_lo_g_init(struct bwn_mac *);
93 static void	bwn_lo_g_adjust(struct bwn_mac *);
94 static void	bwn_lo_get_powervector(struct bwn_mac *);
95 static struct bwn_lo_calib *bwn_lo_calibset(struct bwn_mac *,
96 		    const struct bwn_bbatt *, const struct bwn_rfatt *);
97 static void	bwn_lo_write(struct bwn_mac *, struct bwn_loctl *);
98 static void	bwn_phy_hwpctl_init(struct bwn_mac *);
99 static void	bwn_phy_g_switch_chan(struct bwn_mac *, int, uint8_t);
100 static void	bwn_phy_g_set_txpwr_sub(struct bwn_mac *,
101 		    const struct bwn_bbatt *, const struct bwn_rfatt *,
102 		    uint8_t);
103 static void	bwn_phy_g_set_bbatt(struct bwn_mac *, uint16_t);
104 static uint16_t	bwn_rf_2050_rfoverval(struct bwn_mac *, uint16_t, uint32_t);
105 static void	bwn_spu_workaround(struct bwn_mac *, uint8_t);
106 static void	bwn_wa_init(struct bwn_mac *);
107 static void	bwn_ofdmtab_write_2(struct bwn_mac *, uint16_t, uint16_t,
108 		    uint16_t);
109 static void	bwn_ofdmtab_write_4(struct bwn_mac *, uint16_t, uint16_t,
110 		    uint32_t);
111 static void	bwn_gtab_write(struct bwn_mac *, uint16_t, uint16_t,
112 		    uint16_t);
113 static int16_t	bwn_nrssi_read(struct bwn_mac *, uint16_t);
114 static void	bwn_nrssi_offset(struct bwn_mac *);
115 static void	bwn_nrssi_threshold(struct bwn_mac *);
116 static void	bwn_nrssi_slope_11g(struct bwn_mac *);
117 static void	bwn_set_all_gains(struct bwn_mac *, int16_t, int16_t,
118 		    int16_t);
119 static void	bwn_set_original_gains(struct bwn_mac *);
120 static void	bwn_hwpctl_early_init(struct bwn_mac *);
121 static void	bwn_hwpctl_init_gphy(struct bwn_mac *);
122 static uint16_t	bwn_phy_g_chan2freq(uint8_t);
123 static void	bwn_phy_g_dc_lookup_init(struct bwn_mac *, uint8_t);
124 
125 /* Stuff we need */
126 
127 static uint16_t	bwn_phy_g_txctl(struct bwn_mac *mac);
128 static int	bwn_phy_shm_tssi_read(struct bwn_mac *mac, uint16_t shm_offset);
129 static void	bwn_phy_g_setatt(struct bwn_mac *mac, int *bbattp, int *rfattp);
130 static void	bwn_phy_lock(struct bwn_mac *mac);
131 static void	bwn_phy_unlock(struct bwn_mac *mac);
132 static void	bwn_rf_lock(struct bwn_mac *mac);
133 static void	bwn_rf_unlock(struct bwn_mac *mac);
134 
135 static const uint16_t bwn_tab_noise_g1[] = BWN_TAB_NOISE_G1;
136 static const uint16_t bwn_tab_noise_g2[] = BWN_TAB_NOISE_G2;
137 static const uint16_t bwn_tab_noisescale_g1[] = BWN_TAB_NOISESCALE_G1;
138 static const uint16_t bwn_tab_noisescale_g2[] = BWN_TAB_NOISESCALE_G2;
139 static const uint16_t bwn_tab_noisescale_g3[] = BWN_TAB_NOISESCALE_G3;
140 const uint8_t bwn_bitrev_table[256] = BWN_BITREV_TABLE;
141 
142 static uint8_t
143 bwn_has_hwpctl(struct bwn_mac *mac)
144 {
145 
146 	if (mac->mac_phy.hwpctl == 0 || mac->mac_phy.use_hwpctl == NULL)
147 		return (0);
148 	return (mac->mac_phy.use_hwpctl(mac));
149 }
150 
151 int
152 bwn_phy_g_attach(struct bwn_mac *mac)
153 {
154 	struct bwn_softc *sc = mac->mac_sc;
155 	struct bwn_phy *phy = &mac->mac_phy;
156 	struct bwn_phy_g *pg = &phy->phy_g;
157 	unsigned int i;
158 	int16_t pab0, pab1, pab2;
159 	static int8_t bwn_phy_g_tssi2dbm_table[] = BWN_PHY_G_TSSI2DBM_TABLE;
160 	int8_t bg;
161 
162 	bg = (int8_t)siba_sprom_get_tssi_bg(sc->sc_dev);
163 	pab0 = (int16_t)siba_sprom_get_pa0b0(sc->sc_dev);
164 	pab1 = (int16_t)siba_sprom_get_pa0b1(sc->sc_dev);
165 	pab2 = (int16_t)siba_sprom_get_pa0b2(sc->sc_dev);
166 
167 	if ((siba_get_chipid(sc->sc_dev) == 0x4301) && (phy->rf_ver != 0x2050))
168 		device_printf(sc->sc_dev, "not supported anymore\n");
169 
170 	pg->pg_flags = 0;
171 	if (pab0 == 0 || pab1 == 0 || pab2 == 0 || pab0 == -1 || pab1 == -1 ||
172 	    pab2 == -1) {
173 		pg->pg_idletssi = 52;
174 		pg->pg_tssi2dbm = bwn_phy_g_tssi2dbm_table;
175 		return (0);
176 	}
177 
178 	pg->pg_idletssi = (bg == 0 || bg == -1) ? 62 : bg;
179 	pg->pg_tssi2dbm = (uint8_t *)malloc(64, M_DEVBUF, M_NOWAIT | M_ZERO);
180 	if (pg->pg_tssi2dbm == NULL) {
181 		device_printf(sc->sc_dev, "failed to allocate buffer\n");
182 		return (ENOMEM);
183 	}
184 	for (i = 0; i < 64; i++) {
185 		int32_t m1, m2, f, q, delta;
186 		int8_t j = 0;
187 
188 		m1 = BWN_TSSI2DBM(16 * pab0 + i * pab1, 32);
189 		m2 = MAX(BWN_TSSI2DBM(32768 + i * pab2, 256), 1);
190 		f = 256;
191 
192 		do {
193 			if (j > 15) {
194 				device_printf(sc->sc_dev,
195 				    "failed to generate tssi2dBm\n");
196 				free(pg->pg_tssi2dbm, M_DEVBUF);
197 				return (ENOMEM);
198 			}
199 			q = BWN_TSSI2DBM(f * 4096 - BWN_TSSI2DBM(m2 * f, 16) *
200 			    f, 2048);
201 			delta = abs(q - f);
202 			f = q;
203 			j++;
204 		} while (delta >= 2);
205 
206 		pg->pg_tssi2dbm[i] = MIN(MAX(BWN_TSSI2DBM(m1 * f, 8192), -127),
207 		    128);
208 	}
209 
210 	pg->pg_flags |= BWN_PHY_G_FLAG_TSSITABLE_ALLOC;
211 	return (0);
212 }
213 
214 void
215 bwn_phy_g_detach(struct bwn_mac *mac)
216 {
217 	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
218 
219 	if (pg->pg_flags & BWN_PHY_G_FLAG_TSSITABLE_ALLOC) {
220 		free(pg->pg_tssi2dbm, M_DEVBUF);
221 		pg->pg_tssi2dbm = NULL;
222 	}
223 	pg->pg_flags = 0;
224 }
225 
226 void
227 bwn_phy_g_init_pre(struct bwn_mac *mac)
228 {
229 	struct bwn_phy *phy = &mac->mac_phy;
230 	struct bwn_phy_g *pg = &phy->phy_g;
231 	void *tssi2dbm;
232 	int idletssi;
233 	unsigned int i;
234 
235 	tssi2dbm = pg->pg_tssi2dbm;
236 	idletssi = pg->pg_idletssi;
237 
238 	memset(pg, 0, sizeof(*pg));
239 
240 	pg->pg_tssi2dbm = tssi2dbm;
241 	pg->pg_idletssi = idletssi;
242 
243 	memset(pg->pg_minlowsig, 0xff, sizeof(pg->pg_minlowsig));
244 
245 	for (i = 0; i < N(pg->pg_nrssi); i++)
246 		pg->pg_nrssi[i] = -1000;
247 	for (i = 0; i < N(pg->pg_nrssi_lt); i++)
248 		pg->pg_nrssi_lt[i] = i;
249 	pg->pg_lofcal = 0xffff;
250 	pg->pg_initval = 0xffff;
251 	pg->pg_immode = BWN_IMMODE_NONE;
252 	pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_UNKNOWN;
253 	pg->pg_avgtssi = 0xff;
254 
255 	pg->pg_loctl.tx_bias = 0xff;
256 	TAILQ_INIT(&pg->pg_loctl.calib_list);
257 }
258 
259 int
260 bwn_phy_g_prepare_hw(struct bwn_mac *mac)
261 {
262 	struct bwn_phy *phy = &mac->mac_phy;
263 	struct bwn_phy_g *pg = &phy->phy_g;
264 	struct bwn_softc *sc = mac->mac_sc;
265 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
266 	static const struct bwn_rfatt rfatt0[] = {
267 		{ 3, 0 }, { 1, 0 }, { 5, 0 }, { 7, 0 },	{ 9, 0 }, { 2, 0 },
268 		{ 0, 0 }, { 4, 0 }, { 6, 0 }, { 8, 0 }, { 1, 1 }, { 2, 1 },
269 		{ 3, 1 }, { 4, 1 }
270 	};
271 	static const struct bwn_rfatt rfatt1[] = {
272 		{ 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 10, 1 }, { 12, 1 },
273 		{ 14, 1 }
274 	};
275 	static const struct bwn_rfatt rfatt2[] = {
276 		{ 0, 1 }, { 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 9, 1 },
277 		{ 9, 1 }
278 	};
279 	static const struct bwn_bbatt bbatt_0[] = {
280 		{ 0 }, { 1 }, { 2 }, { 3 }, { 4 }, { 5 }, { 6 }, { 7 }, { 8 }
281 	};
282 
283 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
284 
285 	if (phy->rf_ver == 0x2050 && phy->rf_rev < 6)
286 		pg->pg_bbatt.att = 0;
287 	else
288 		pg->pg_bbatt.att = 2;
289 
290 	/* prepare Radio Attenuation */
291 	pg->pg_rfatt.padmix = 0;
292 
293 	if (siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM &&
294 	    siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BCM4309G) {
295 		if (siba_get_pci_revid(sc->sc_dev) < 0x43) {
296 			pg->pg_rfatt.att = 2;
297 			goto done;
298 		} else if (siba_get_pci_revid(sc->sc_dev) < 0x51) {
299 			pg->pg_rfatt.att = 3;
300 			goto done;
301 		}
302 	}
303 
304 	if (phy->type == BWN_PHYTYPE_A) {
305 		pg->pg_rfatt.att = 0x60;
306 		goto done;
307 	}
308 
309 	switch (phy->rf_ver) {
310 	case 0x2050:
311 		switch (phy->rf_rev) {
312 		case 0:
313 			pg->pg_rfatt.att = 5;
314 			goto done;
315 		case 1:
316 			if (phy->type == BWN_PHYTYPE_G) {
317 				if (siba_get_pci_subvendor(sc->sc_dev) ==
318 				    SIBA_BOARDVENDOR_BCM &&
319 				    siba_get_pci_subdevice(sc->sc_dev) ==
320 				    SIBA_BOARD_BCM4309G &&
321 				    siba_get_pci_revid(sc->sc_dev) >= 30)
322 					pg->pg_rfatt.att = 3;
323 				else if (siba_get_pci_subvendor(sc->sc_dev) ==
324 				    SIBA_BOARDVENDOR_BCM &&
325 				    siba_get_pci_subdevice(sc->sc_dev) ==
326 				    SIBA_BOARD_BU4306)
327 					pg->pg_rfatt.att = 3;
328 				else
329 					pg->pg_rfatt.att = 1;
330 			} else {
331 				if (siba_get_pci_subvendor(sc->sc_dev) ==
332 				    SIBA_BOARDVENDOR_BCM &&
333 				    siba_get_pci_subdevice(sc->sc_dev) ==
334 				    SIBA_BOARD_BCM4309G &&
335 				    siba_get_pci_revid(sc->sc_dev) >= 30)
336 					pg->pg_rfatt.att = 7;
337 				else
338 					pg->pg_rfatt.att = 6;
339 			}
340 			goto done;
341 		case 2:
342 			if (phy->type == BWN_PHYTYPE_G) {
343 				if (siba_get_pci_subvendor(sc->sc_dev) ==
344 				    SIBA_BOARDVENDOR_BCM &&
345 				    siba_get_pci_subdevice(sc->sc_dev) ==
346 				    SIBA_BOARD_BCM4309G &&
347 				    siba_get_pci_revid(sc->sc_dev) >= 30)
348 					pg->pg_rfatt.att = 3;
349 				else if (siba_get_pci_subvendor(sc->sc_dev) ==
350 				    SIBA_BOARDVENDOR_BCM &&
351 				    siba_get_pci_subdevice(sc->sc_dev) ==
352 				    SIBA_BOARD_BU4306)
353 					pg->pg_rfatt.att = 5;
354 				else if (siba_get_chipid(sc->sc_dev) == 0x4320)
355 					pg->pg_rfatt.att = 4;
356 				else
357 					pg->pg_rfatt.att = 3;
358 			} else
359 				pg->pg_rfatt.att = 6;
360 			goto done;
361 		case 3:
362 			pg->pg_rfatt.att = 5;
363 			goto done;
364 		case 4:
365 		case 5:
366 			pg->pg_rfatt.att = 1;
367 			goto done;
368 		case 6:
369 		case 7:
370 			pg->pg_rfatt.att = 5;
371 			goto done;
372 		case 8:
373 			pg->pg_rfatt.att = 0xa;
374 			pg->pg_rfatt.padmix = 1;
375 			goto done;
376 		case 9:
377 		default:
378 			pg->pg_rfatt.att = 5;
379 			goto done;
380 		}
381 		break;
382 	case 0x2053:
383 		switch (phy->rf_rev) {
384 		case 1:
385 			pg->pg_rfatt.att = 6;
386 			goto done;
387 		}
388 		break;
389 	}
390 	pg->pg_rfatt.att = 5;
391 done:
392 	pg->pg_txctl = (bwn_phy_g_txctl(mac) << 4);
393 
394 	if (!bwn_has_hwpctl(mac)) {
395 		lo->rfatt.array = rfatt0;
396 		lo->rfatt.len = N(rfatt0);
397 		lo->rfatt.min = 0;
398 		lo->rfatt.max = 9;
399 		goto genbbatt;
400 	}
401 	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
402 		lo->rfatt.array = rfatt1;
403 		lo->rfatt.len = N(rfatt1);
404 		lo->rfatt.min = 0;
405 		lo->rfatt.max = 14;
406 		goto genbbatt;
407 	}
408 	lo->rfatt.array = rfatt2;
409 	lo->rfatt.len = N(rfatt2);
410 	lo->rfatt.min = 0;
411 	lo->rfatt.max = 9;
412 genbbatt:
413 	lo->bbatt.array = bbatt_0;
414 	lo->bbatt.len = N(bbatt_0);
415 	lo->bbatt.min = 0;
416 	lo->bbatt.max = 8;
417 
418 	BWN_READ_4(mac, BWN_MACCTL);
419 	if (phy->rev == 1) {
420 		phy->gmode = 0;
421 		bwn_reset_core(mac, 0);
422 		bwn_phy_g_init_sub(mac);
423 		phy->gmode = 1;
424 		bwn_reset_core(mac, 1);
425 	}
426 	return (0);
427 }
428 
429 static uint16_t
430 bwn_phy_g_txctl(struct bwn_mac *mac)
431 {
432 	struct bwn_phy *phy = &mac->mac_phy;
433 
434 	if (phy->rf_ver != 0x2050)
435 		return (0);
436 	if (phy->rf_rev == 1)
437 		return (BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX);
438 	if (phy->rf_rev < 6)
439 		return (BWN_TXCTL_PA2DB);
440 	if (phy->rf_rev == 8)
441 		return (BWN_TXCTL_TXMIX);
442 	return (0);
443 }
444 
445 int
446 bwn_phy_g_init(struct bwn_mac *mac)
447 {
448 
449 	bwn_phy_g_init_sub(mac);
450 	return (0);
451 }
452 
453 void
454 bwn_phy_g_exit(struct bwn_mac *mac)
455 {
456 	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
457 	struct bwn_lo_calib *cal, *tmp;
458 
459 	if (lo == NULL)
460 		return;
461 	TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
462 		TAILQ_REMOVE(&lo->calib_list, cal, list);
463 		free(cal, M_DEVBUF);
464 	}
465 }
466 
467 uint16_t
468 bwn_phy_g_read(struct bwn_mac *mac, uint16_t reg)
469 {
470 
471 	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
472 	return (BWN_READ_2(mac, BWN_PHYDATA));
473 }
474 
475 void
476 bwn_phy_g_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
477 {
478 
479 	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
480 	BWN_WRITE_2(mac, BWN_PHYDATA, value);
481 }
482 
483 uint16_t
484 bwn_phy_g_rf_read(struct bwn_mac *mac, uint16_t reg)
485 {
486 
487 	KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
488 	BWN_WRITE_2(mac, BWN_RFCTL, reg | 0x80);
489 	return (BWN_READ_2(mac, BWN_RFDATALO));
490 }
491 
492 void
493 bwn_phy_g_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
494 {
495 
496 	KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
497 	BWN_WRITE_2(mac, BWN_RFCTL, reg);
498 	BWN_WRITE_2(mac, BWN_RFDATALO, value);
499 }
500 
501 int
502 bwn_phy_g_hwpctl(struct bwn_mac *mac)
503 {
504 
505 	return (mac->mac_phy.rev >= 6);
506 }
507 
508 void
509 bwn_phy_g_rf_onoff(struct bwn_mac *mac, int on)
510 {
511 	struct bwn_phy *phy = &mac->mac_phy;
512 	struct bwn_phy_g *pg = &phy->phy_g;
513 	unsigned int channel;
514 	uint16_t rfover, rfoverval;
515 
516 	if (on) {
517 		if (phy->rf_on)
518 			return;
519 
520 		BWN_PHY_WRITE(mac, 0x15, 0x8000);
521 		BWN_PHY_WRITE(mac, 0x15, 0xcc00);
522 		BWN_PHY_WRITE(mac, 0x15, (phy->gmode ? 0xc0 : 0x0));
523 		if (pg->pg_flags & BWN_PHY_G_FLAG_RADIOCTX_VALID) {
524 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
525 			    pg->pg_radioctx_over);
526 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
527 			    pg->pg_radioctx_overval);
528 			pg->pg_flags &= ~BWN_PHY_G_FLAG_RADIOCTX_VALID;
529 		}
530 		channel = phy->chan;
531 		bwn_phy_g_switch_chan(mac, 6, 1);
532 		bwn_phy_g_switch_chan(mac, channel, 0);
533 		return;
534 	}
535 
536 	rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
537 	rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
538 	pg->pg_radioctx_over = rfover;
539 	pg->pg_radioctx_overval = rfoverval;
540 	pg->pg_flags |= BWN_PHY_G_FLAG_RADIOCTX_VALID;
541 	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover | 0x008c);
542 	BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval & 0xff73);
543 }
544 
545 int
546 bwn_phy_g_switch_channel(struct bwn_mac *mac, uint32_t newchan)
547 {
548 
549 	if ((newchan < 1) || (newchan > 14))
550 		return (EINVAL);
551 	bwn_phy_g_switch_chan(mac, newchan, 0);
552 
553 	return (0);
554 }
555 
556 uint32_t
557 bwn_phy_g_get_default_chan(struct bwn_mac *mac)
558 {
559 
560 	return (1);
561 }
562 
563 void
564 bwn_phy_g_set_antenna(struct bwn_mac *mac, int antenna)
565 {
566 	struct bwn_phy *phy = &mac->mac_phy;
567 	uint64_t hf;
568 	int autodiv = 0;
569 	uint16_t tmp;
570 
571 	if (antenna == BWN_ANTAUTO0 || antenna == BWN_ANTAUTO1)
572 		autodiv = 1;
573 
574 	hf = bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER;
575 	bwn_hf_write(mac, hf);
576 
577 	BWN_PHY_WRITE(mac, BWN_PHY_BBANDCFG,
578 	    (BWN_PHY_READ(mac, BWN_PHY_BBANDCFG) & ~BWN_PHY_BBANDCFG_RXANT) |
579 	    ((autodiv ? BWN_ANTAUTO1 : antenna)
580 		<< BWN_PHY_BBANDCFG_RXANT_SHIFT));
581 
582 	if (autodiv) {
583 		tmp = BWN_PHY_READ(mac, BWN_PHY_ANTDWELL);
584 		if (antenna == BWN_ANTAUTO1)
585 			tmp &= ~BWN_PHY_ANTDWELL_AUTODIV1;
586 		else
587 			tmp |= BWN_PHY_ANTDWELL_AUTODIV1;
588 		BWN_PHY_WRITE(mac, BWN_PHY_ANTDWELL, tmp);
589 	}
590 	tmp = BWN_PHY_READ(mac, BWN_PHY_ANTWRSETT);
591 	if (autodiv)
592 		tmp |= BWN_PHY_ANTWRSETT_ARXDIV;
593 	else
594 		tmp &= ~BWN_PHY_ANTWRSETT_ARXDIV;
595 	BWN_PHY_WRITE(mac, BWN_PHY_ANTWRSETT, tmp);
596 	if (phy->rev >= 2) {
597 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM61,
598 		    BWN_PHY_READ(mac, BWN_PHY_OFDM61) | BWN_PHY_OFDM61_10);
599 		BWN_PHY_WRITE(mac, BWN_PHY_DIVSRCHGAINBACK,
600 		    (BWN_PHY_READ(mac, BWN_PHY_DIVSRCHGAINBACK) & 0xff00) |
601 		    0x15);
602 		if (phy->rev == 2)
603 			BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED, 8);
604 		else
605 			BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED,
606 			    (BWN_PHY_READ(mac, BWN_PHY_ADIVRELATED) & 0xff00) |
607 			    8);
608 	}
609 	if (phy->rev >= 6)
610 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM9B, 0xdc);
611 
612 	hf |= BWN_HF_UCODE_ANTDIV_HELPER;
613 	bwn_hf_write(mac, hf);
614 }
615 
616 int
617 bwn_phy_g_im(struct bwn_mac *mac, int mode)
618 {
619 	struct bwn_phy *phy = &mac->mac_phy;
620 	struct bwn_phy_g *pg = &phy->phy_g;
621 
622 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
623 	KASSERT(mode == BWN_IMMODE_NONE, ("%s: fail", __func__));
624 
625 	if (phy->rev == 0 || !phy->gmode)
626 		return (ENODEV);
627 
628 	pg->pg_aci_wlan_automatic = 0;
629 	return (0);
630 }
631 
632 bwn_txpwr_result_t
633 bwn_phy_g_recalc_txpwr(struct bwn_mac *mac, int ignore_tssi)
634 {
635 	struct bwn_phy *phy = &mac->mac_phy;
636 	struct bwn_phy_g *pg = &phy->phy_g;
637 	struct bwn_softc *sc = mac->mac_sc;
638 	unsigned int tssi;
639 	int cck, ofdm;
640 	int power;
641 	int rfatt, bbatt;
642 	unsigned int max;
643 
644 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
645 
646 	cck = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_CCK);
647 	ofdm = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_OFDM_G);
648 	if (cck < 0 && ofdm < 0) {
649 		if (ignore_tssi == 0)
650 			return (BWN_TXPWR_RES_DONE);
651 		cck = 0;
652 		ofdm = 0;
653 	}
654 	tssi = (cck < 0) ? ofdm : ((ofdm < 0) ? cck : (cck + ofdm) / 2);
655 	if (pg->pg_avgtssi != 0xff)
656 		tssi = (tssi + pg->pg_avgtssi) / 2;
657 	pg->pg_avgtssi = tssi;
658 	KASSERT(tssi < BWN_TSSI_MAX, ("%s:%d: fail", __func__, __LINE__));
659 
660 	max = siba_sprom_get_maxpwr_bg(sc->sc_dev);
661 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
662 		max -= 3;
663 	if (max >= 120) {
664 		device_printf(sc->sc_dev, "invalid max TX-power value\n");
665 		max = 80;
666 		siba_sprom_set_maxpwr_bg(sc->sc_dev, max);
667 	}
668 
669 	power = MIN(MAX((phy->txpower < 0) ? 0 : (phy->txpower << 2), 0), max) -
670 	    (pg->pg_tssi2dbm[MIN(MAX(pg->pg_idletssi - pg->pg_curtssi +
671 	     tssi, 0x00), 0x3f)]);
672 	if (power == 0)
673 		return (BWN_TXPWR_RES_DONE);
674 
675 	rfatt = -((power + 7) / 8);
676 	bbatt = (-(power / 2)) - (4 * rfatt);
677 	if ((rfatt == 0) && (bbatt == 0))
678 		return (BWN_TXPWR_RES_DONE);
679 	pg->pg_bbatt_delta = bbatt;
680 	pg->pg_rfatt_delta = rfatt;
681 	return (BWN_TXPWR_RES_NEED_ADJUST);
682 }
683 
684 void
685 bwn_phy_g_set_txpwr(struct bwn_mac *mac)
686 {
687 	struct bwn_phy *phy = &mac->mac_phy;
688 	struct bwn_phy_g *pg = &phy->phy_g;
689 	struct bwn_softc *sc = mac->mac_sc;
690 	int rfatt, bbatt;
691 	uint8_t txctl;
692 
693 	bwn_mac_suspend(mac);
694 
695 	BWN_ASSERT_LOCKED(sc);
696 
697 	bbatt = pg->pg_bbatt.att;
698 	bbatt += pg->pg_bbatt_delta;
699 	rfatt = pg->pg_rfatt.att;
700 	rfatt += pg->pg_rfatt_delta;
701 
702 	bwn_phy_g_setatt(mac, &bbatt, &rfatt);
703 	txctl = pg->pg_txctl;
704 	if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 2)) {
705 		if (rfatt <= 1) {
706 			if (txctl == 0) {
707 				txctl = BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX;
708 				rfatt += 2;
709 				bbatt += 2;
710 			} else if (siba_sprom_get_bf_lo(sc->sc_dev) &
711 			    BWN_BFL_PACTRL) {
712 				bbatt += 4 * (rfatt - 2);
713 				rfatt = 2;
714 			}
715 		} else if (rfatt > 4 && txctl) {
716 			txctl = 0;
717 			if (bbatt < 3) {
718 				rfatt -= 3;
719 				bbatt += 2;
720 			} else {
721 				rfatt -= 2;
722 				bbatt -= 2;
723 			}
724 		}
725 	}
726 	pg->pg_txctl = txctl;
727 	bwn_phy_g_setatt(mac, &bbatt, &rfatt);
728 	pg->pg_rfatt.att = rfatt;
729 	pg->pg_bbatt.att = bbatt;
730 
731 	DPRINTF(sc, BWN_DEBUG_TXPOW, "%s: adjust TX power\n", __func__);
732 
733 	bwn_phy_lock(mac);
734 	bwn_rf_lock(mac);
735 	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
736 	    pg->pg_txctl);
737 	bwn_rf_unlock(mac);
738 	bwn_phy_unlock(mac);
739 
740 	bwn_mac_enable(mac);
741 }
742 
743 void
744 bwn_phy_g_task_15s(struct bwn_mac *mac)
745 {
746 	struct bwn_phy *phy = &mac->mac_phy;
747 	struct bwn_phy_g *pg = &phy->phy_g;
748 	struct bwn_softc *sc = mac->mac_sc;
749 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
750 	unsigned long expire, now;
751 	struct bwn_lo_calib *cal, *tmp;
752 	uint8_t expired = 0;
753 
754 	bwn_mac_suspend(mac);
755 
756 	if (lo == NULL)
757 		goto fail;
758 
759 	BWN_GETTIME(now);
760 	if (bwn_has_hwpctl(mac)) {
761 		expire = now - BWN_LO_PWRVEC_EXPIRE;
762 		if (ieee80211_time_before(lo->pwr_vec_read_time, expire)) {
763 			bwn_lo_get_powervector(mac);
764 			bwn_phy_g_dc_lookup_init(mac, 0);
765 		}
766 		goto fail;
767 	}
768 
769 	expire = now - BWN_LO_CALIB_EXPIRE;
770 	TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
771 		if (!ieee80211_time_before(cal->calib_time, expire))
772 			continue;
773 		if (BWN_BBATTCMP(&cal->bbatt, &pg->pg_bbatt) &&
774 		    BWN_RFATTCMP(&cal->rfatt, &pg->pg_rfatt)) {
775 			KASSERT(!expired, ("%s:%d: fail", __func__, __LINE__));
776 			expired = 1;
777 		}
778 
779 		DPRINTF(sc, BWN_DEBUG_LO, "expired BB %u RF %u %u I %d Q %d\n",
780 		    cal->bbatt.att, cal->rfatt.att, cal->rfatt.padmix,
781 		    cal->ctl.i, cal->ctl.q);
782 
783 		TAILQ_REMOVE(&lo->calib_list, cal, list);
784 		free(cal, M_DEVBUF);
785 	}
786 	if (expired || TAILQ_EMPTY(&lo->calib_list)) {
787 		cal = bwn_lo_calibset(mac, &pg->pg_bbatt,
788 		    &pg->pg_rfatt);
789 		if (cal == NULL) {
790 			device_printf(sc->sc_dev,
791 			    "failed to recalibrate LO\n");
792 			goto fail;
793 		}
794 		TAILQ_INSERT_TAIL(&lo->calib_list, cal, list);
795 		bwn_lo_write(mac, &cal->ctl);
796 	}
797 
798 fail:
799 	bwn_mac_enable(mac);
800 }
801 
802 void
803 bwn_phy_g_task_60s(struct bwn_mac *mac)
804 {
805 	struct bwn_phy *phy = &mac->mac_phy;
806 	struct bwn_softc *sc = mac->mac_sc;
807 	uint8_t old = phy->chan;
808 
809 	if (!(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI))
810 		return;
811 
812 	bwn_mac_suspend(mac);
813 	bwn_nrssi_slope_11g(mac);
814 	if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 8)) {
815 		bwn_switch_channel(mac, (old >= 8) ? 1 : 13);
816 		bwn_switch_channel(mac, old);
817 	}
818 	bwn_mac_enable(mac);
819 }
820 
821 void
822 bwn_phy_switch_analog(struct bwn_mac *mac, int on)
823 {
824 
825 	BWN_WRITE_2(mac, BWN_PHY0, on ? 0 : 0xf4);
826 }
827 
828 static void
829 bwn_phy_g_init_sub(struct bwn_mac *mac)
830 {
831 	struct bwn_phy *phy = &mac->mac_phy;
832 	struct bwn_phy_g *pg = &phy->phy_g;
833 	struct bwn_softc *sc = mac->mac_sc;
834 	uint16_t i, tmp;
835 
836 	if (phy->rev == 1)
837 		bwn_phy_init_b5(mac);
838 	else
839 		bwn_phy_init_b6(mac);
840 
841 	if (phy->rev >= 2 || phy->gmode)
842 		bwn_phy_init_a(mac);
843 
844 	if (phy->rev >= 2) {
845 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, 0);
846 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, 0);
847 	}
848 	if (phy->rev == 2) {
849 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
850 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
851 	}
852 	if (phy->rev > 5) {
853 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x400);
854 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
855 	}
856 	if (phy->gmode || phy->rev >= 2) {
857 		tmp = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
858 		tmp &= BWN_PHYVER_VERSION;
859 		if (tmp == 3 || tmp == 5) {
860 			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc2), 0x1816);
861 			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc3), 0x8006);
862 		}
863 		if (tmp == 5) {
864 			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xcc), 0x00ff,
865 			    0x1f00);
866 		}
867 	}
868 	if ((phy->rev <= 2 && phy->gmode) || phy->rev >= 2)
869 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x7e), 0x78);
870 	if (phy->rf_rev == 8) {
871 		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x80);
872 		BWN_PHY_SET(mac, BWN_PHY_OFDM(0x3e), 0x4);
873 	}
874 	if (BWN_HAS_LOOPBACK(phy))
875 		bwn_loopback_calcgain(mac);
876 
877 	if (phy->rf_rev != 8) {
878 		if (pg->pg_initval == 0xffff)
879 			pg->pg_initval = bwn_rf_init_bcm2050(mac);
880 		else
881 			BWN_RF_WRITE(mac, 0x0078, pg->pg_initval);
882 	}
883 	bwn_lo_g_init(mac);
884 	if (BWN_HAS_TXMAG(phy)) {
885 		BWN_RF_WRITE(mac, 0x52,
886 		    (BWN_RF_READ(mac, 0x52) & 0xff00)
887 		    | pg->pg_loctl.tx_bias |
888 		    pg->pg_loctl.tx_magn);
889 	} else {
890 		BWN_RF_SETMASK(mac, 0x52, 0xfff0, pg->pg_loctl.tx_bias);
891 	}
892 	if (phy->rev >= 6) {
893 		BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x36), 0x0fff,
894 		    (pg->pg_loctl.tx_bias << 12));
895 	}
896 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
897 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8075);
898 	else
899 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x807f);
900 	if (phy->rev < 2)
901 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x101);
902 	else
903 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x202);
904 	if (phy->gmode || phy->rev >= 2) {
905 		bwn_lo_g_adjust(mac);
906 		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
907 	}
908 
909 	if (!(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI)) {
910 		for (i = 0; i < 64; i++) {
911 			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, i);
912 			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_DATA,
913 			    (uint16_t)MIN(MAX(bwn_nrssi_read(mac, i) - 0xffff,
914 			    -32), 31));
915 		}
916 		bwn_nrssi_threshold(mac);
917 	} else if (phy->gmode || phy->rev >= 2) {
918 		if (pg->pg_nrssi[0] == -1000) {
919 			KASSERT(pg->pg_nrssi[1] == -1000,
920 			    ("%s:%d: fail", __func__, __LINE__));
921 			bwn_nrssi_slope_11g(mac);
922 		} else
923 			bwn_nrssi_threshold(mac);
924 	}
925 	if (phy->rf_rev == 8)
926 		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x05), 0x3230);
927 	bwn_phy_hwpctl_init(mac);
928 	if ((siba_get_chipid(sc->sc_dev) == 0x4306
929 	     && siba_get_chippkg(sc->sc_dev) == 2) || 0) {
930 		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0xbfff);
931 		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xc3), 0x7fff);
932 	}
933 }
934 
935 static void
936 bwn_phy_init_b5(struct bwn_mac *mac)
937 {
938 	struct bwn_phy *phy = &mac->mac_phy;
939 	struct bwn_phy_g *pg = &phy->phy_g;
940 	struct bwn_softc *sc = mac->mac_sc;
941 	uint16_t offset, value;
942 	uint8_t old_channel;
943 
944 	if (phy->analog == 1)
945 		BWN_RF_SET(mac, 0x007a, 0x0050);
946 	if ((siba_get_pci_subvendor(sc->sc_dev) != SIBA_BOARDVENDOR_BCM) &&
947 	    (siba_get_pci_subdevice(sc->sc_dev) != SIBA_BOARD_BU4306)) {
948 		value = 0x2120;
949 		for (offset = 0x00a8; offset < 0x00c7; offset++) {
950 			BWN_PHY_WRITE(mac, offset, value);
951 			value += 0x202;
952 		}
953 	}
954 	BWN_PHY_SETMASK(mac, 0x0035, 0xf0ff, 0x0700);
955 	if (phy->rf_ver == 0x2050)
956 		BWN_PHY_WRITE(mac, 0x0038, 0x0667);
957 
958 	if (phy->gmode || phy->rev >= 2) {
959 		if (phy->rf_ver == 0x2050) {
960 			BWN_RF_SET(mac, 0x007a, 0x0020);
961 			BWN_RF_SET(mac, 0x0051, 0x0004);
962 		}
963 		BWN_WRITE_2(mac, BWN_PHY_RADIO, 0x0000);
964 
965 		BWN_PHY_SET(mac, 0x0802, 0x0100);
966 		BWN_PHY_SET(mac, 0x042b, 0x2000);
967 
968 		BWN_PHY_WRITE(mac, 0x001c, 0x186a);
969 
970 		BWN_PHY_SETMASK(mac, 0x0013, 0x00ff, 0x1900);
971 		BWN_PHY_SETMASK(mac, 0x0035, 0xffc0, 0x0064);
972 		BWN_PHY_SETMASK(mac, 0x005d, 0xff80, 0x000a);
973 	}
974 
975 	if (mac->mac_flags & BWN_MAC_FLAG_BADFRAME_PREEMP)
976 		BWN_PHY_SET(mac, BWN_PHY_RADIO_BITFIELD, (1 << 11));
977 
978 	if (phy->analog == 1) {
979 		BWN_PHY_WRITE(mac, 0x0026, 0xce00);
980 		BWN_PHY_WRITE(mac, 0x0021, 0x3763);
981 		BWN_PHY_WRITE(mac, 0x0022, 0x1bc3);
982 		BWN_PHY_WRITE(mac, 0x0023, 0x06f9);
983 		BWN_PHY_WRITE(mac, 0x0024, 0x037e);
984 	} else
985 		BWN_PHY_WRITE(mac, 0x0026, 0xcc00);
986 	BWN_PHY_WRITE(mac, 0x0030, 0x00c6);
987 	BWN_WRITE_2(mac, 0x03ec, 0x3f22);
988 
989 	if (phy->analog == 1)
990 		BWN_PHY_WRITE(mac, 0x0020, 0x3e1c);
991 	else
992 		BWN_PHY_WRITE(mac, 0x0020, 0x301c);
993 
994 	if (phy->analog == 0)
995 		BWN_WRITE_2(mac, 0x03e4, 0x3000);
996 
997 	old_channel = phy->chan;
998 	bwn_phy_g_switch_chan(mac, 7, 0);
999 
1000 	if (phy->rf_ver != 0x2050) {
1001 		BWN_RF_WRITE(mac, 0x0075, 0x0080);
1002 		BWN_RF_WRITE(mac, 0x0079, 0x0081);
1003 	}
1004 
1005 	BWN_RF_WRITE(mac, 0x0050, 0x0020);
1006 	BWN_RF_WRITE(mac, 0x0050, 0x0023);
1007 
1008 	if (phy->rf_ver == 0x2050) {
1009 		BWN_RF_WRITE(mac, 0x0050, 0x0020);
1010 		BWN_RF_WRITE(mac, 0x005a, 0x0070);
1011 	}
1012 
1013 	BWN_RF_WRITE(mac, 0x005b, 0x007b);
1014 	BWN_RF_WRITE(mac, 0x005c, 0x00b0);
1015 	BWN_RF_SET(mac, 0x007a, 0x0007);
1016 
1017 	bwn_phy_g_switch_chan(mac, old_channel, 0);
1018 	BWN_PHY_WRITE(mac, 0x0014, 0x0080);
1019 	BWN_PHY_WRITE(mac, 0x0032, 0x00ca);
1020 	BWN_PHY_WRITE(mac, 0x002a, 0x88a3);
1021 
1022 	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
1023 	    pg->pg_txctl);
1024 
1025 	if (phy->rf_ver == 0x2050)
1026 		BWN_RF_WRITE(mac, 0x005d, 0x000d);
1027 
1028 	BWN_WRITE_2(mac, 0x03e4, (BWN_READ_2(mac, 0x03e4) & 0xffc0) | 0x0004);
1029 }
1030 
1031 static void
1032 bwn_loopback_calcgain(struct bwn_mac *mac)
1033 {
1034 	struct bwn_phy *phy = &mac->mac_phy;
1035 	struct bwn_phy_g *pg = &phy->phy_g;
1036 	struct bwn_softc *sc = mac->mac_sc;
1037 	uint16_t backup_phy[16] = { 0 };
1038 	uint16_t backup_radio[3];
1039 	uint16_t backup_bband;
1040 	uint16_t i, j, loop_i_max;
1041 	uint16_t trsw_rx;
1042 	uint16_t loop1_outer_done, loop1_inner_done;
1043 
1044 	backup_phy[0] = BWN_PHY_READ(mac, BWN_PHY_CRS0);
1045 	backup_phy[1] = BWN_PHY_READ(mac, BWN_PHY_CCKBBANDCFG);
1046 	backup_phy[2] = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
1047 	backup_phy[3] = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
1048 	if (phy->rev != 1) {
1049 		backup_phy[4] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
1050 		backup_phy[5] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
1051 	}
1052 	backup_phy[6] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
1053 	backup_phy[7] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
1054 	backup_phy[8] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
1055 	backup_phy[9] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x0a));
1056 	backup_phy[10] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x03));
1057 	backup_phy[11] = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
1058 	backup_phy[12] = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
1059 	backup_phy[13] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2b));
1060 	backup_phy[14] = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
1061 	backup_phy[15] = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
1062 	backup_bband = pg->pg_bbatt.att;
1063 	backup_radio[0] = BWN_RF_READ(mac, 0x52);
1064 	backup_radio[1] = BWN_RF_READ(mac, 0x43);
1065 	backup_radio[2] = BWN_RF_READ(mac, 0x7a);
1066 
1067 	BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x3fff);
1068 	BWN_PHY_SET(mac, BWN_PHY_CCKBBANDCFG, 0x8000);
1069 	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0002);
1070 	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffd);
1071 	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0001);
1072 	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffe);
1073 	if (phy->rev != 1) {
1074 		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0001);
1075 		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffe);
1076 		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0002);
1077 		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffd);
1078 	}
1079 	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x000c);
1080 	BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x000c);
1081 	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0030);
1082 	BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xffcf, 0x10);
1083 
1084 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0780);
1085 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
1086 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
1087 
1088 	BWN_PHY_SET(mac, BWN_PHY_CCK(0x0a), 0x2000);
1089 	if (phy->rev != 1) {
1090 		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0004);
1091 		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffb);
1092 	}
1093 	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xff9f, 0x40);
1094 
1095 	if (phy->rf_rev == 8)
1096 		BWN_RF_WRITE(mac, 0x43, 0x000f);
1097 	else {
1098 		BWN_RF_WRITE(mac, 0x52, 0);
1099 		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x9);
1100 	}
1101 	bwn_phy_g_set_bbatt(mac, 11);
1102 
1103 	if (phy->rev >= 3)
1104 		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
1105 	else
1106 		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
1107 	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
1108 
1109 	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xffc0, 0x01);
1110 	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xc0ff, 0x800);
1111 
1112 	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0100);
1113 	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xcfff);
1114 
1115 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA) {
1116 		if (phy->rev >= 7) {
1117 			BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0800);
1118 			BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x8000);
1119 		}
1120 	}
1121 	BWN_RF_MASK(mac, 0x7a, 0x00f7);
1122 
1123 	j = 0;
1124 	loop_i_max = (phy->rf_rev == 8) ? 15 : 9;
1125 	for (i = 0; i < loop_i_max; i++) {
1126 		for (j = 0; j < 16; j++) {
1127 			BWN_RF_WRITE(mac, 0x43, i);
1128 			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff,
1129 			    (j << 8));
1130 			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
1131 			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
1132 			DELAY(20);
1133 			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
1134 				goto done0;
1135 		}
1136 	}
1137 done0:
1138 	loop1_outer_done = i;
1139 	loop1_inner_done = j;
1140 	if (j >= 8) {
1141 		BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x30);
1142 		trsw_rx = 0x1b;
1143 		for (j = j - 8; j < 16; j++) {
1144 			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff, j << 8);
1145 			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
1146 			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
1147 			DELAY(20);
1148 			trsw_rx -= 3;
1149 			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
1150 				goto done1;
1151 		}
1152 	} else
1153 		trsw_rx = 0x18;
1154 done1:
1155 
1156 	if (phy->rev != 1) {
1157 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, backup_phy[4]);
1158 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, backup_phy[5]);
1159 	}
1160 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), backup_phy[6]);
1161 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), backup_phy[7]);
1162 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), backup_phy[8]);
1163 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x0a), backup_phy[9]);
1164 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x03), backup_phy[10]);
1165 	BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, backup_phy[11]);
1166 	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, backup_phy[12]);
1167 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), backup_phy[13]);
1168 	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, backup_phy[14]);
1169 
1170 	bwn_phy_g_set_bbatt(mac, backup_bband);
1171 
1172 	BWN_RF_WRITE(mac, 0x52, backup_radio[0]);
1173 	BWN_RF_WRITE(mac, 0x43, backup_radio[1]);
1174 	BWN_RF_WRITE(mac, 0x7a, backup_radio[2]);
1175 
1176 	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2] | 0x0003);
1177 	DELAY(10);
1178 	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2]);
1179 	BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, backup_phy[3]);
1180 	BWN_PHY_WRITE(mac, BWN_PHY_CRS0, backup_phy[0]);
1181 	BWN_PHY_WRITE(mac, BWN_PHY_CCKBBANDCFG, backup_phy[1]);
1182 
1183 	pg->pg_max_lb_gain =
1184 	    ((loop1_inner_done * 6) - (loop1_outer_done * 4)) - 11;
1185 	pg->pg_trsw_rx_gain = trsw_rx * 2;
1186 }
1187 
1188 static uint16_t
1189 bwn_rf_init_bcm2050(struct bwn_mac *mac)
1190 {
1191 	struct bwn_phy *phy = &mac->mac_phy;
1192 	uint32_t tmp1 = 0, tmp2 = 0;
1193 	uint16_t rcc, i, j, pgactl, cck0, cck1, cck2, cck3, rfover, rfoverval,
1194 	    analogover, analogoverval, crs0, classctl, lomask, loctl, syncctl,
1195 	    radio0, radio1, radio2, reg0, reg1, reg2, radio78, reg, index;
1196 	static const uint8_t rcc_table[] = {
1197 		0x02, 0x03, 0x01, 0x0f,
1198 		0x06, 0x07, 0x05, 0x0f,
1199 		0x0a, 0x0b, 0x09, 0x0f,
1200 		0x0e, 0x0f, 0x0d, 0x0f,
1201 	};
1202 
1203 	loctl = lomask = reg0 = classctl = crs0 = analogoverval = analogover =
1204 	    rfoverval = rfover = cck3 = 0;
1205 	radio0 = BWN_RF_READ(mac, 0x43);
1206 	radio1 = BWN_RF_READ(mac, 0x51);
1207 	radio2 = BWN_RF_READ(mac, 0x52);
1208 	pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
1209 	cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
1210 	cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
1211 	cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
1212 
1213 	if (phy->type == BWN_PHYTYPE_B) {
1214 		cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
1215 		reg0 = BWN_READ_2(mac, 0x3ec);
1216 
1217 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0xff);
1218 		BWN_WRITE_2(mac, 0x3ec, 0x3f3f);
1219 	} else if (phy->gmode || phy->rev >= 2) {
1220 		rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
1221 		rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
1222 		analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
1223 		analogoverval = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
1224 		crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
1225 		classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
1226 
1227 		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
1228 		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
1229 		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
1230 		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
1231 		if (BWN_HAS_LOOPBACK(phy)) {
1232 			lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
1233 			loctl = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
1234 			if (phy->rev >= 3)
1235 				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
1236 			else
1237 				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
1238 			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
1239 		}
1240 
1241 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
1242 		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
1243 			BWN_LPD(0, 1, 1)));
1244 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
1245 		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVER, 0));
1246 	}
1247 	BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2) | 0x8000);
1248 
1249 	syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
1250 	BWN_PHY_MASK(mac, BWN_PHY_SYNCCTL, 0xff7f);
1251 	reg1 = BWN_READ_2(mac, 0x3e6);
1252 	reg2 = BWN_READ_2(mac, 0x3f4);
1253 
1254 	if (phy->analog == 0)
1255 		BWN_WRITE_2(mac, 0x03e6, 0x0122);
1256 	else {
1257 		if (phy->analog >= 2)
1258 			BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xffbf, 0x40);
1259 		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
1260 		    (BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000));
1261 	}
1262 
1263 	reg = BWN_RF_READ(mac, 0x60);
1264 	index = (reg & 0x001e) >> 1;
1265 	rcc = (((rcc_table[index] << 1) | (reg & 0x0001)) | 0x0020);
1266 
1267 	if (phy->type == BWN_PHYTYPE_B)
1268 		BWN_RF_WRITE(mac, 0x78, 0x26);
1269 	if (phy->gmode || phy->rev >= 2) {
1270 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
1271 		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
1272 			BWN_LPD(0, 1, 1)));
1273 	}
1274 	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfaf);
1275 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1403);
1276 	if (phy->gmode || phy->rev >= 2) {
1277 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
1278 		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
1279 			BWN_LPD(0, 0, 1)));
1280 	}
1281 	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfa0);
1282 	BWN_RF_SET(mac, 0x51, 0x0004);
1283 	if (phy->rf_rev == 8)
1284 		BWN_RF_WRITE(mac, 0x43, 0x1f);
1285 	else {
1286 		BWN_RF_WRITE(mac, 0x52, 0);
1287 		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x0009);
1288 	}
1289 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
1290 
1291 	for (i = 0; i < 16; i++) {
1292 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0480);
1293 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
1294 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
1295 		if (phy->gmode || phy->rev >= 2) {
1296 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
1297 			    bwn_rf_2050_rfoverval(mac,
1298 				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
1299 		}
1300 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
1301 		DELAY(10);
1302 		if (phy->gmode || phy->rev >= 2) {
1303 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
1304 			    bwn_rf_2050_rfoverval(mac,
1305 				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
1306 		}
1307 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
1308 		DELAY(10);
1309 		if (phy->gmode || phy->rev >= 2) {
1310 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
1311 			    bwn_rf_2050_rfoverval(mac,
1312 				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
1313 		}
1314 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
1315 		DELAY(20);
1316 		tmp1 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
1317 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
1318 		if (phy->gmode || phy->rev >= 2) {
1319 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
1320 			    bwn_rf_2050_rfoverval(mac,
1321 				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
1322 		}
1323 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
1324 	}
1325 	DELAY(10);
1326 
1327 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
1328 	tmp1++;
1329 	tmp1 >>= 9;
1330 
1331 	for (i = 0; i < 16; i++) {
1332 		radio78 = (BWN_BITREV4(i) << 1) | 0x0020;
1333 		BWN_RF_WRITE(mac, 0x78, radio78);
1334 		DELAY(10);
1335 		for (j = 0; j < 16; j++) {
1336 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0d80);
1337 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
1338 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
1339 			if (phy->gmode || phy->rev >= 2) {
1340 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
1341 				    bwn_rf_2050_rfoverval(mac,
1342 					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
1343 			}
1344 			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
1345 			DELAY(10);
1346 			if (phy->gmode || phy->rev >= 2) {
1347 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
1348 				    bwn_rf_2050_rfoverval(mac,
1349 					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
1350 			}
1351 			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
1352 			DELAY(10);
1353 			if (phy->gmode || phy->rev >= 2) {
1354 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
1355 				    bwn_rf_2050_rfoverval(mac,
1356 					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
1357 			}
1358 			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
1359 			DELAY(10);
1360 			tmp2 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
1361 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
1362 			if (phy->gmode || phy->rev >= 2) {
1363 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
1364 				    bwn_rf_2050_rfoverval(mac,
1365 					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
1366 			}
1367 			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
1368 		}
1369 		tmp2++;
1370 		tmp2 >>= 8;
1371 		if (tmp1 < tmp2)
1372 			break;
1373 	}
1374 
1375 	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pgactl);
1376 	BWN_RF_WRITE(mac, 0x51, radio1);
1377 	BWN_RF_WRITE(mac, 0x52, radio2);
1378 	BWN_RF_WRITE(mac, 0x43, radio0);
1379 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), cck0);
1380 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), cck1);
1381 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), cck2);
1382 	BWN_WRITE_2(mac, 0x3e6, reg1);
1383 	if (phy->analog != 0)
1384 		BWN_WRITE_2(mac, 0x3f4, reg2);
1385 	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, syncctl);
1386 	bwn_spu_workaround(mac, phy->chan);
1387 	if (phy->type == BWN_PHYTYPE_B) {
1388 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), cck3);
1389 		BWN_WRITE_2(mac, 0x3ec, reg0);
1390 	} else if (phy->gmode) {
1391 		BWN_WRITE_2(mac, BWN_PHY_RADIO,
1392 			    BWN_READ_2(mac, BWN_PHY_RADIO)
1393 			    & 0x7fff);
1394 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover);
1395 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval);
1396 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, analogover);
1397 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
1398 			      analogoverval);
1399 		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, crs0);
1400 		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, classctl);
1401 		if (BWN_HAS_LOOPBACK(phy)) {
1402 			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, lomask);
1403 			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, loctl);
1404 		}
1405 	}
1406 
1407 	return ((i > 15) ? radio78 : rcc);
1408 }
1409 
1410 static void
1411 bwn_phy_init_b6(struct bwn_mac *mac)
1412 {
1413 	struct bwn_phy *phy = &mac->mac_phy;
1414 	struct bwn_phy_g *pg = &phy->phy_g;
1415 	struct bwn_softc *sc = mac->mac_sc;
1416 	uint16_t offset, val;
1417 	uint8_t old_channel;
1418 
1419 	KASSERT(!(phy->rf_rev == 6 || phy->rf_rev == 7),
1420 	    ("%s:%d: fail", __func__, __LINE__));
1421 
1422 	BWN_PHY_WRITE(mac, 0x003e, 0x817a);
1423 	BWN_RF_WRITE(mac, 0x007a, BWN_RF_READ(mac, 0x007a) | 0x0058);
1424 	if (phy->rf_rev == 4 || phy->rf_rev == 5) {
1425 		BWN_RF_WRITE(mac, 0x51, 0x37);
1426 		BWN_RF_WRITE(mac, 0x52, 0x70);
1427 		BWN_RF_WRITE(mac, 0x53, 0xb3);
1428 		BWN_RF_WRITE(mac, 0x54, 0x9b);
1429 		BWN_RF_WRITE(mac, 0x5a, 0x88);
1430 		BWN_RF_WRITE(mac, 0x5b, 0x88);
1431 		BWN_RF_WRITE(mac, 0x5d, 0x88);
1432 		BWN_RF_WRITE(mac, 0x5e, 0x88);
1433 		BWN_RF_WRITE(mac, 0x7d, 0x88);
1434 		bwn_hf_write(mac,
1435 		    bwn_hf_read(mac) | BWN_HF_TSSI_RESET_PSM_WORKAROUN);
1436 	}
1437 	if (phy->rf_rev == 8) {
1438 		BWN_RF_WRITE(mac, 0x51, 0);
1439 		BWN_RF_WRITE(mac, 0x52, 0x40);
1440 		BWN_RF_WRITE(mac, 0x53, 0xb7);
1441 		BWN_RF_WRITE(mac, 0x54, 0x98);
1442 		BWN_RF_WRITE(mac, 0x5a, 0x88);
1443 		BWN_RF_WRITE(mac, 0x5b, 0x6b);
1444 		BWN_RF_WRITE(mac, 0x5c, 0x0f);
1445 		if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_ALTIQ) {
1446 			BWN_RF_WRITE(mac, 0x5d, 0xfa);
1447 			BWN_RF_WRITE(mac, 0x5e, 0xd8);
1448 		} else {
1449 			BWN_RF_WRITE(mac, 0x5d, 0xf5);
1450 			BWN_RF_WRITE(mac, 0x5e, 0xb8);
1451 		}
1452 		BWN_RF_WRITE(mac, 0x0073, 0x0003);
1453 		BWN_RF_WRITE(mac, 0x007d, 0x00a8);
1454 		BWN_RF_WRITE(mac, 0x007c, 0x0001);
1455 		BWN_RF_WRITE(mac, 0x007e, 0x0008);
1456 	}
1457 	for (val = 0x1e1f, offset = 0x0088; offset < 0x0098; offset++) {
1458 		BWN_PHY_WRITE(mac, offset, val);
1459 		val -= 0x0202;
1460 	}
1461 	for (val = 0x3e3f, offset = 0x0098; offset < 0x00a8; offset++) {
1462 		BWN_PHY_WRITE(mac, offset, val);
1463 		val -= 0x0202;
1464 	}
1465 	for (val = 0x2120, offset = 0x00a8; offset < 0x00c8; offset++) {
1466 		BWN_PHY_WRITE(mac, offset, (val & 0x3f3f));
1467 		val += 0x0202;
1468 	}
1469 	if (phy->type == BWN_PHYTYPE_G) {
1470 		BWN_RF_SET(mac, 0x007a, 0x0020);
1471 		BWN_RF_SET(mac, 0x0051, 0x0004);
1472 		BWN_PHY_SET(mac, 0x0802, 0x0100);
1473 		BWN_PHY_SET(mac, 0x042b, 0x2000);
1474 		BWN_PHY_WRITE(mac, 0x5b, 0);
1475 		BWN_PHY_WRITE(mac, 0x5c, 0);
1476 	}
1477 
1478 	old_channel = phy->chan;
1479 	bwn_phy_g_switch_chan(mac, (old_channel >= 8) ? 1 : 13, 0);
1480 
1481 	BWN_RF_WRITE(mac, 0x0050, 0x0020);
1482 	BWN_RF_WRITE(mac, 0x0050, 0x0023);
1483 	DELAY(40);
1484 	if (phy->rf_rev < 6 || phy->rf_rev == 8) {
1485 		BWN_RF_WRITE(mac, 0x7c, BWN_RF_READ(mac, 0x7c) | 0x0002);
1486 		BWN_RF_WRITE(mac, 0x50, 0x20);
1487 	}
1488 	if (phy->rf_rev <= 2) {
1489 		BWN_RF_WRITE(mac, 0x7c, 0x20);
1490 		BWN_RF_WRITE(mac, 0x5a, 0x70);
1491 		BWN_RF_WRITE(mac, 0x5b, 0x7b);
1492 		BWN_RF_WRITE(mac, 0x5c, 0xb0);
1493 	}
1494 	BWN_RF_SETMASK(mac, 0x007a, 0x00f8, 0x0007);
1495 
1496 	bwn_phy_g_switch_chan(mac, old_channel, 0);
1497 
1498 	BWN_PHY_WRITE(mac, 0x0014, 0x0200);
1499 	if (phy->rf_rev >= 6)
1500 		BWN_PHY_WRITE(mac, 0x2a, 0x88c2);
1501 	else
1502 		BWN_PHY_WRITE(mac, 0x2a, 0x8ac0);
1503 	BWN_PHY_WRITE(mac, 0x0038, 0x0668);
1504 	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
1505 	    pg->pg_txctl);
1506 	if (phy->rf_rev <= 5)
1507 		BWN_PHY_SETMASK(mac, 0x5d, 0xff80, 0x0003);
1508 	if (phy->rf_rev <= 2)
1509 		BWN_RF_WRITE(mac, 0x005d, 0x000d);
1510 
1511 	if (phy->analog == 4) {
1512 		BWN_WRITE_2(mac, 0x3e4, 9);
1513 		BWN_PHY_MASK(mac, 0x61, 0x0fff);
1514 	} else
1515 		BWN_PHY_SETMASK(mac, 0x0002, 0xffc0, 0x0004);
1516 	if (phy->type == BWN_PHYTYPE_B)
1517 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
1518 	else if (phy->type == BWN_PHYTYPE_G)
1519 		BWN_WRITE_2(mac, 0x03e6, 0x0);
1520 }
1521 
1522 static void
1523 bwn_phy_init_a(struct bwn_mac *mac)
1524 {
1525 	struct bwn_phy *phy = &mac->mac_phy;
1526 	struct bwn_softc *sc = mac->mac_sc;
1527 
1528 	KASSERT(phy->type == BWN_PHYTYPE_A || phy->type == BWN_PHYTYPE_G,
1529 	    ("%s:%d: fail", __func__, __LINE__));
1530 
1531 	if (phy->rev >= 6) {
1532 		if (phy->type == BWN_PHYTYPE_A)
1533 			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x1000);
1534 		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) & BWN_PHY_ENCORE_EN)
1535 			BWN_PHY_SET(mac, BWN_PHY_ENCORE, 0x0010);
1536 		else
1537 			BWN_PHY_MASK(mac, BWN_PHY_ENCORE, ~0x1010);
1538 	}
1539 
1540 	bwn_wa_init(mac);
1541 
1542 	if (phy->type == BWN_PHYTYPE_G &&
1543 	    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL))
1544 		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x6e), 0xe000, 0x3cf);
1545 }
1546 
1547 static void
1548 bwn_wa_write_noisescale(struct bwn_mac *mac, const uint16_t *nst)
1549 {
1550 	int i;
1551 
1552 	for (i = 0; i < BWN_TAB_NOISESCALE_SIZE; i++)
1553 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_NOISESCALE, i, nst[i]);
1554 }
1555 
1556 static void
1557 bwn_wa_agc(struct bwn_mac *mac)
1558 {
1559 	struct bwn_phy *phy = &mac->mac_phy;
1560 
1561 	if (phy->rev == 1) {
1562 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 0, 254);
1563 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 1, 13);
1564 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 2, 19);
1565 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 3, 25);
1566 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 0, 0x2710);
1567 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 1, 0x9b83);
1568 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 2, 0x9b83);
1569 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 3, 0x0f8d);
1570 		BWN_PHY_WRITE(mac, BWN_PHY_LMS, 4);
1571 	} else {
1572 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 0, 254);
1573 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 1, 13);
1574 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 2, 19);
1575 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 3, 25);
1576 	}
1577 
1578 	BWN_PHY_SETMASK(mac, BWN_PHY_CCKSHIFTBITS_WA, (uint16_t)~0xff00,
1579 	    0x5700);
1580 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x007f, 0x000f);
1581 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x3f80, 0x2b80);
1582 	BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, 0xf0ff, 0x0300);
1583 	BWN_RF_SET(mac, 0x7a, 0x0008);
1584 	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x000f, 0x0008);
1585 	BWN_PHY_SETMASK(mac, BWN_PHY_P1P2GAIN, ~0x0f00, 0x0600);
1586 	BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x0f00, 0x0700);
1587 	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x0f00, 0x0100);
1588 	if (phy->rev == 1)
1589 		BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x000f, 0x0007);
1590 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x00ff, 0x001c);
1591 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x3f00, 0x0200);
1592 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), ~0x00ff, 0x001c);
1593 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x00ff, 0x0020);
1594 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x3f00, 0x0200);
1595 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x82), ~0x00ff, 0x002e);
1596 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), (uint16_t)~0xff00, 0x1a00);
1597 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), ~0x00ff, 0x0028);
1598 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), (uint16_t)~0xff00, 0x2c00);
1599 	if (phy->rev == 1) {
1600 		BWN_PHY_WRITE(mac, BWN_PHY_PEAK_COUNT, 0x092b);
1601 		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e, 0x0002);
1602 	} else {
1603 		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e);
1604 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x1f), 0x287a);
1605 		BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL, ~0x000f, 0x0004);
1606 		if (phy->rev >= 6) {
1607 			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x22), 0x287a);
1608 			BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL,
1609 			    (uint16_t)~0xf000, 0x3000);
1610 		}
1611 	}
1612 	BWN_PHY_SETMASK(mac, BWN_PHY_DIVSRCHIDX, 0x8080, 0x7874);
1613 	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8e), 0x1c00);
1614 	if (phy->rev == 1) {
1615 		BWN_PHY_SETMASK(mac, BWN_PHY_DIVP1P2GAIN, ~0x0f00, 0x0600);
1616 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8b), 0x005e);
1617 		BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, ~0x00ff, 0x001e);
1618 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8d), 0x0002);
1619 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 0, 0);
1620 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 1, 7);
1621 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 2, 16);
1622 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 3, 28);
1623 	} else {
1624 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 0, 0);
1625 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 1, 7);
1626 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 2, 16);
1627 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 3, 28);
1628 	}
1629 	if (phy->rev >= 6) {
1630 		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x0003);
1631 		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x1000);
1632 	}
1633 	BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
1634 }
1635 
1636 static void
1637 bwn_wa_grev1(struct bwn_mac *mac)
1638 {
1639 	struct bwn_phy *phy = &mac->mac_phy;
1640 	int i;
1641 	static const uint16_t bwn_tab_finefreqg[] = BWN_TAB_FINEFREQ_G;
1642 	static const uint32_t bwn_tab_retard[] = BWN_TAB_RETARD;
1643 	static const uint32_t bwn_tab_rotor[] = BWN_TAB_ROTOR;
1644 
1645 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
1646 
1647 	/* init CRSTHRES and ANTDWELL */
1648 	if (phy->rev == 1) {
1649 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
1650 	} else if (phy->rev == 2) {
1651 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
1652 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
1653 		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
1654 	} else {
1655 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
1656 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
1657 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
1658 		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
1659 	}
1660 	BWN_PHY_SETMASK(mac, BWN_PHY_CRS0, ~0x03c0, 0xd000);
1661 	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x2c), 0x005a);
1662 	BWN_PHY_WRITE(mac, BWN_PHY_CCKSHIFTBITS, 0x0026);
1663 
1664 	/* XXX support PHY-A??? */
1665 	for (i = 0; i < N(bwn_tab_finefreqg); i++)
1666 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DACRFPABB, i,
1667 		    bwn_tab_finefreqg[i]);
1668 
1669 	/* XXX support PHY-A??? */
1670 	if (phy->rev == 1)
1671 		for (i = 0; i < N(bwn_tab_noise_g1); i++)
1672 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
1673 			    bwn_tab_noise_g1[i]);
1674 	else
1675 		for (i = 0; i < N(bwn_tab_noise_g2); i++)
1676 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
1677 			    bwn_tab_noise_g2[i]);
1678 
1679 
1680 	for (i = 0; i < N(bwn_tab_rotor); i++)
1681 		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ROTOR, i,
1682 		    bwn_tab_rotor[i]);
1683 
1684 	/* XXX support PHY-A??? */
1685 	if (phy->rev >= 6) {
1686 		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
1687 		    BWN_PHY_ENCORE_EN)
1688 			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
1689 		else
1690 			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
1691 	} else
1692 		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
1693 
1694 	for (i = 0; i < N(bwn_tab_retard); i++)
1695 		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ADVRETARD, i,
1696 		    bwn_tab_retard[i]);
1697 
1698 	if (phy->rev == 1) {
1699 		for (i = 0; i < 16; i++)
1700 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1,
1701 			    i, 0x0020);
1702 	} else {
1703 		for (i = 0; i < 32; i++)
1704 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
1705 	}
1706 
1707 	bwn_wa_agc(mac);
1708 }
1709 
1710 static void
1711 bwn_wa_grev26789(struct bwn_mac *mac)
1712 {
1713 	struct bwn_phy *phy = &mac->mac_phy;
1714 	int i;
1715 	static const uint16_t bwn_tab_sigmasqr2[] = BWN_TAB_SIGMASQR2;
1716 	uint16_t ofdmrev;
1717 
1718 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
1719 
1720 	bwn_gtab_write(mac, BWN_GTAB_ORIGTR, 0, 0xc480);
1721 
1722 	/* init CRSTHRES and ANTDWELL */
1723 	if (phy->rev == 1)
1724 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
1725 	else if (phy->rev == 2) {
1726 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
1727 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
1728 		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
1729 	} else {
1730 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
1731 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
1732 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
1733 		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
1734 	}
1735 
1736 	for (i = 0; i < 64; i++)
1737 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_RSSI, i, i);
1738 
1739 	/* XXX support PHY-A??? */
1740 	if (phy->rev == 1)
1741 		for (i = 0; i < N(bwn_tab_noise_g1); i++)
1742 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
1743 			    bwn_tab_noise_g1[i]);
1744 	else
1745 		for (i = 0; i < N(bwn_tab_noise_g2); i++)
1746 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
1747 			    bwn_tab_noise_g2[i]);
1748 
1749 	/* XXX support PHY-A??? */
1750 	if (phy->rev >= 6) {
1751 		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
1752 		    BWN_PHY_ENCORE_EN)
1753 			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
1754 		else
1755 			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
1756 	} else
1757 		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
1758 
1759 	for (i = 0; i < N(bwn_tab_sigmasqr2); i++)
1760 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_MINSIGSQ, i,
1761 		    bwn_tab_sigmasqr2[i]);
1762 
1763 	if (phy->rev == 1) {
1764 		for (i = 0; i < 16; i++)
1765 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1, i,
1766 			    0x0020);
1767 	} else {
1768 		for (i = 0; i < 32; i++)
1769 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
1770 	}
1771 
1772 	bwn_wa_agc(mac);
1773 
1774 	ofdmrev = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM) & BWN_PHYVER_VERSION;
1775 	if (ofdmrev > 2) {
1776 		if (phy->type == BWN_PHYTYPE_A)
1777 			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1808);
1778 		else
1779 			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1000);
1780 	} else {
1781 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 3, 0x1044);
1782 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 4, 0x7201);
1783 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 6, 0x0040);
1784 	}
1785 
1786 	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 2, 15);
1787 	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 3, 20);
1788 }
1789 
1790 static void
1791 bwn_wa_init(struct bwn_mac *mac)
1792 {
1793 	struct bwn_phy *phy = &mac->mac_phy;
1794 	struct bwn_softc *sc = mac->mac_sc;
1795 
1796 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
1797 
1798 	switch (phy->rev) {
1799 	case 1:
1800 		bwn_wa_grev1(mac);
1801 		break;
1802 	case 2:
1803 	case 6:
1804 	case 7:
1805 	case 8:
1806 	case 9:
1807 		bwn_wa_grev26789(mac);
1808 		break;
1809 	default:
1810 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
1811 	}
1812 
1813 	if (siba_get_pci_subvendor(sc->sc_dev) != SIBA_BOARDVENDOR_BCM ||
1814 	    siba_get_pci_subdevice(sc->sc_dev) != SIBA_BOARD_BU4306 ||
1815 	    siba_get_pci_revid(sc->sc_dev) != 0x17) {
1816 		if (phy->rev < 2) {
1817 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 1,
1818 			    0x0002);
1819 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 2,
1820 			    0x0001);
1821 		} else {
1822 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 1, 0x0002);
1823 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 2, 0x0001);
1824 			if ((siba_sprom_get_bf_lo(sc->sc_dev) &
1825 			     BWN_BFL_EXTLNA) &&
1826 			    (phy->rev >= 7)) {
1827 				BWN_PHY_MASK(mac, BWN_PHY_EXTG(0x11), 0xf7ff);
1828 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
1829 				    0x0020, 0x0001);
1830 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
1831 				    0x0021, 0x0001);
1832 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
1833 				    0x0022, 0x0001);
1834 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
1835 				    0x0023, 0x0000);
1836 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
1837 				    0x0000, 0x0000);
1838 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
1839 				    0x0003, 0x0002);
1840 			}
1841 		}
1842 	}
1843 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM) {
1844 		BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, 0x3120);
1845 		BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, 0xc480);
1846 	}
1847 
1848 	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 0, 0);
1849 	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 1, 0);
1850 }
1851 
1852 static void
1853 bwn_ofdmtab_write_2(struct bwn_mac *mac, uint16_t table, uint16_t offset,
1854     uint16_t value)
1855 {
1856 	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
1857 	uint16_t addr;
1858 
1859 	addr = table + offset;
1860 	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
1861 	    (addr - 1 != pg->pg_ofdmtab_addr)) {
1862 		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
1863 		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
1864 	}
1865 	pg->pg_ofdmtab_addr = addr;
1866 	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
1867 }
1868 
1869 static void
1870 bwn_ofdmtab_write_4(struct bwn_mac *mac, uint16_t table, uint16_t offset,
1871     uint32_t value)
1872 {
1873 	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
1874 	uint16_t addr;
1875 
1876 	addr = table + offset;
1877 	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
1878 	    (addr - 1 != pg->pg_ofdmtab_addr)) {
1879 		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
1880 		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
1881 	}
1882 	pg->pg_ofdmtab_addr = addr;
1883 
1884 	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
1885 	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEQ, (value >> 16));
1886 }
1887 
1888 static void
1889 bwn_gtab_write(struct bwn_mac *mac, uint16_t table, uint16_t offset,
1890     uint16_t value)
1891 {
1892 
1893 	BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, table + offset);
1894 	BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, value);
1895 }
1896 
1897 static void
1898 bwn_lo_write(struct bwn_mac *mac, struct bwn_loctl *ctl)
1899 {
1900 	uint16_t value;
1901 
1902 	KASSERT(mac->mac_phy.type == BWN_PHYTYPE_G,
1903 	    ("%s:%d: fail", __func__, __LINE__));
1904 
1905 	value = (uint8_t) (ctl->q);
1906 	value |= ((uint8_t) (ctl->i)) << 8;
1907 	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, value);
1908 }
1909 
1910 static uint16_t
1911 bwn_lo_calcfeed(struct bwn_mac *mac,
1912     uint16_t lna, uint16_t pga, uint16_t trsw_rx)
1913 {
1914 	struct bwn_phy *phy = &mac->mac_phy;
1915 	struct bwn_softc *sc = mac->mac_sc;
1916 	uint16_t rfover;
1917 	uint16_t feedthrough;
1918 
1919 	if (phy->gmode) {
1920 		lna <<= BWN_PHY_RFOVERVAL_LNA_SHIFT;
1921 		pga <<= BWN_PHY_RFOVERVAL_PGA_SHIFT;
1922 
1923 		KASSERT((lna & ~BWN_PHY_RFOVERVAL_LNA) == 0,
1924 		    ("%s:%d: fail", __func__, __LINE__));
1925 		KASSERT((pga & ~BWN_PHY_RFOVERVAL_PGA) == 0,
1926 		    ("%s:%d: fail", __func__, __LINE__));
1927 
1928 		trsw_rx &= (BWN_PHY_RFOVERVAL_TRSWRX | BWN_PHY_RFOVERVAL_BW);
1929 
1930 		rfover = BWN_PHY_RFOVERVAL_UNK | pga | lna | trsw_rx;
1931 		if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA) &&
1932 		    phy->rev > 6)
1933 			rfover |= BWN_PHY_RFOVERVAL_EXTLNA;
1934 
1935 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
1936 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
1937 		DELAY(10);
1938 		rfover |= BWN_PHY_RFOVERVAL_BW_LBW;
1939 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
1940 		DELAY(10);
1941 		rfover |= BWN_PHY_RFOVERVAL_BW_LPF;
1942 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
1943 		DELAY(10);
1944 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xf300);
1945 	} else {
1946 		pga |= BWN_PHY_PGACTL_UNKNOWN;
1947 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
1948 		DELAY(10);
1949 		pga |= BWN_PHY_PGACTL_LOWBANDW;
1950 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
1951 		DELAY(10);
1952 		pga |= BWN_PHY_PGACTL_LPF;
1953 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
1954 	}
1955 	DELAY(21);
1956 	feedthrough = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
1957 
1958 	return (feedthrough);
1959 }
1960 
1961 static uint16_t
1962 bwn_lo_txctl_regtable(struct bwn_mac *mac,
1963     uint16_t *value, uint16_t *pad_mix_gain)
1964 {
1965 	struct bwn_phy *phy = &mac->mac_phy;
1966 	uint16_t reg, v, padmix;
1967 
1968 	if (phy->type == BWN_PHYTYPE_B) {
1969 		v = 0x30;
1970 		if (phy->rf_rev <= 5) {
1971 			reg = 0x43;
1972 			padmix = 0;
1973 		} else {
1974 			reg = 0x52;
1975 			padmix = 5;
1976 		}
1977 	} else {
1978 		if (phy->rev >= 2 && phy->rf_rev == 8) {
1979 			reg = 0x43;
1980 			v = 0x10;
1981 			padmix = 2;
1982 		} else {
1983 			reg = 0x52;
1984 			v = 0x30;
1985 			padmix = 5;
1986 		}
1987 	}
1988 	if (value)
1989 		*value = v;
1990 	if (pad_mix_gain)
1991 		*pad_mix_gain = padmix;
1992 
1993 	return (reg);
1994 }
1995 
1996 static void
1997 bwn_lo_measure_txctl_values(struct bwn_mac *mac)
1998 {
1999 	struct bwn_phy *phy = &mac->mac_phy;
2000 	struct bwn_phy_g *pg = &phy->phy_g;
2001 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2002 	uint16_t reg, mask;
2003 	uint16_t trsw_rx, pga;
2004 	uint16_t rf_pctl_reg;
2005 
2006 	static const uint8_t tx_bias_values[] = {
2007 		0x09, 0x08, 0x0a, 0x01, 0x00,
2008 		0x02, 0x05, 0x04, 0x06,
2009 	};
2010 	static const uint8_t tx_magn_values[] = {
2011 		0x70, 0x40,
2012 	};
2013 
2014 	if (!BWN_HAS_LOOPBACK(phy)) {
2015 		rf_pctl_reg = 6;
2016 		trsw_rx = 2;
2017 		pga = 0;
2018 	} else {
2019 		int lb_gain;
2020 
2021 		trsw_rx = 0;
2022 		lb_gain = pg->pg_max_lb_gain / 2;
2023 		if (lb_gain > 10) {
2024 			rf_pctl_reg = 0;
2025 			pga = abs(10 - lb_gain) / 6;
2026 			pga = MIN(MAX(pga, 0), 15);
2027 		} else {
2028 			int cmp_val;
2029 			int tmp;
2030 
2031 			pga = 0;
2032 			cmp_val = 0x24;
2033 			if ((phy->rev >= 2) &&
2034 			    (phy->rf_ver == 0x2050) && (phy->rf_rev == 8))
2035 				cmp_val = 0x3c;
2036 			tmp = lb_gain;
2037 			if ((10 - lb_gain) < cmp_val)
2038 				tmp = (10 - lb_gain);
2039 			if (tmp < 0)
2040 				tmp += 6;
2041 			else
2042 				tmp += 3;
2043 			cmp_val /= 4;
2044 			tmp /= 4;
2045 			if (tmp >= cmp_val)
2046 				rf_pctl_reg = cmp_val;
2047 			else
2048 				rf_pctl_reg = tmp;
2049 		}
2050 	}
2051 	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rf_pctl_reg);
2052 	bwn_phy_g_set_bbatt(mac, 2);
2053 
2054 	reg = bwn_lo_txctl_regtable(mac, &mask, NULL);
2055 	mask = ~mask;
2056 	BWN_RF_MASK(mac, reg, mask);
2057 
2058 	if (BWN_HAS_TXMAG(phy)) {
2059 		int i, j;
2060 		int feedthrough;
2061 		int min_feedth = 0xffff;
2062 		uint8_t tx_magn, tx_bias;
2063 
2064 		for (i = 0; i < N(tx_magn_values); i++) {
2065 			tx_magn = tx_magn_values[i];
2066 			BWN_RF_SETMASK(mac, 0x52, 0xff0f, tx_magn);
2067 			for (j = 0; j < N(tx_bias_values); j++) {
2068 				tx_bias = tx_bias_values[j];
2069 				BWN_RF_SETMASK(mac, 0x52, 0xfff0, tx_bias);
2070 				feedthrough = bwn_lo_calcfeed(mac, 0, pga,
2071 				    trsw_rx);
2072 				if (feedthrough < min_feedth) {
2073 					lo->tx_bias = tx_bias;
2074 					lo->tx_magn = tx_magn;
2075 					min_feedth = feedthrough;
2076 				}
2077 				if (lo->tx_bias == 0)
2078 					break;
2079 			}
2080 			BWN_RF_WRITE(mac, 0x52,
2081 					  (BWN_RF_READ(mac, 0x52)
2082 					   & 0xff00) | lo->tx_bias | lo->
2083 					  tx_magn);
2084 		}
2085 	} else {
2086 		lo->tx_magn = 0;
2087 		lo->tx_bias = 0;
2088 		BWN_RF_MASK(mac, 0x52, 0xfff0);
2089 	}
2090 
2091 	BWN_GETTIME(lo->txctl_measured_time);
2092 }
2093 
2094 static void
2095 bwn_lo_get_powervector(struct bwn_mac *mac)
2096 {
2097 	struct bwn_phy *phy = &mac->mac_phy;
2098 	struct bwn_phy_g *pg = &phy->phy_g;
2099 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2100 	int i;
2101 	uint64_t tmp;
2102 	uint64_t power_vector = 0;
2103 
2104 	for (i = 0; i < 8; i += 2) {
2105 		tmp = bwn_shm_read_2(mac, BWN_SHARED, 0x310 + i);
2106 		power_vector |= (tmp << (i * 8));
2107 		bwn_shm_write_2(mac, BWN_SHARED, 0x310 + i, 0);
2108 	}
2109 	if (power_vector)
2110 		lo->power_vector = power_vector;
2111 
2112 	BWN_GETTIME(lo->pwr_vec_read_time);
2113 }
2114 
2115 static void
2116 bwn_lo_measure_gain_values(struct bwn_mac *mac, int16_t max_rx_gain,
2117     int use_trsw_rx)
2118 {
2119 	struct bwn_phy *phy = &mac->mac_phy;
2120 	struct bwn_phy_g *pg = &phy->phy_g;
2121 	uint16_t tmp;
2122 
2123 	if (max_rx_gain < 0)
2124 		max_rx_gain = 0;
2125 
2126 	if (BWN_HAS_LOOPBACK(phy)) {
2127 		int trsw_rx = 0;
2128 		int trsw_rx_gain;
2129 
2130 		if (use_trsw_rx) {
2131 			trsw_rx_gain = pg->pg_trsw_rx_gain / 2;
2132 			if (max_rx_gain >= trsw_rx_gain) {
2133 				trsw_rx_gain = max_rx_gain - trsw_rx_gain;
2134 				trsw_rx = 0x20;
2135 			}
2136 		} else
2137 			trsw_rx_gain = max_rx_gain;
2138 		if (trsw_rx_gain < 9) {
2139 			pg->pg_lna_lod_gain = 0;
2140 		} else {
2141 			pg->pg_lna_lod_gain = 1;
2142 			trsw_rx_gain -= 8;
2143 		}
2144 		trsw_rx_gain = MIN(MAX(trsw_rx_gain, 0), 0x2d);
2145 		pg->pg_pga_gain = trsw_rx_gain / 3;
2146 		if (pg->pg_pga_gain >= 5) {
2147 			pg->pg_pga_gain -= 5;
2148 			pg->pg_lna_gain = 2;
2149 		} else
2150 			pg->pg_lna_gain = 0;
2151 	} else {
2152 		pg->pg_lna_gain = 0;
2153 		pg->pg_trsw_rx_gain = 0x20;
2154 		if (max_rx_gain >= 0x14) {
2155 			pg->pg_lna_lod_gain = 1;
2156 			pg->pg_pga_gain = 2;
2157 		} else if (max_rx_gain >= 0x12) {
2158 			pg->pg_lna_lod_gain = 1;
2159 			pg->pg_pga_gain = 1;
2160 		} else if (max_rx_gain >= 0xf) {
2161 			pg->pg_lna_lod_gain = 1;
2162 			pg->pg_pga_gain = 0;
2163 		} else {
2164 			pg->pg_lna_lod_gain = 0;
2165 			pg->pg_pga_gain = 0;
2166 		}
2167 	}
2168 
2169 	tmp = BWN_RF_READ(mac, 0x7a);
2170 	if (pg->pg_lna_lod_gain == 0)
2171 		tmp &= ~0x0008;
2172 	else
2173 		tmp |= 0x0008;
2174 	BWN_RF_WRITE(mac, 0x7a, tmp);
2175 }
2176 
2177 static void
2178 bwn_lo_save(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
2179 {
2180 	struct bwn_phy *phy = &mac->mac_phy;
2181 	struct bwn_phy_g *pg = &phy->phy_g;
2182 	struct bwn_softc *sc = mac->mac_sc;
2183 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2184 	struct timespec ts;
2185 	uint16_t tmp;
2186 
2187 	if (bwn_has_hwpctl(mac)) {
2188 		sav->phy_lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
2189 		sav->phy_extg = BWN_PHY_READ(mac, BWN_PHY_EXTG(0x01));
2190 		sav->phy_dacctl_hwpctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
2191 		sav->phy_cck4 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x14));
2192 		sav->phy_hpwr_tssictl = BWN_PHY_READ(mac, BWN_PHY_HPWR_TSSICTL);
2193 
2194 		BWN_PHY_SET(mac, BWN_PHY_HPWR_TSSICTL, 0x100);
2195 		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x40);
2196 		BWN_PHY_SET(mac, BWN_PHY_DACCTL, 0x40);
2197 		BWN_PHY_SET(mac, BWN_PHY_CCK(0x14), 0x200);
2198 	}
2199 	if (phy->type == BWN_PHYTYPE_B &&
2200 	    phy->rf_ver == 0x2050 && phy->rf_rev < 6) {
2201 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x16), 0x410);
2202 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x17), 0x820);
2203 	}
2204 	if (phy->rev >= 2) {
2205 		sav->phy_analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
2206 		sav->phy_analogoverval =
2207 		    BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
2208 		sav->phy_rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
2209 		sav->phy_rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
2210 		sav->phy_classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
2211 		sav->phy_cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x3e));
2212 		sav->phy_crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
2213 
2214 		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
2215 		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
2216 		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
2217 		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
2218 		if (phy->type == BWN_PHYTYPE_G) {
2219 			if ((phy->rev >= 7) &&
2220 			    (siba_sprom_get_bf_lo(sc->sc_dev) &
2221 			     BWN_BFL_EXTLNA)) {
2222 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x933);
2223 			} else {
2224 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x133);
2225 			}
2226 		} else {
2227 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
2228 		}
2229 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), 0);
2230 	}
2231 	sav->reg0 = BWN_READ_2(mac, 0x3f4);
2232 	sav->reg1 = BWN_READ_2(mac, 0x3e2);
2233 	sav->rf0 = BWN_RF_READ(mac, 0x43);
2234 	sav->rf1 = BWN_RF_READ(mac, 0x7a);
2235 	sav->phy_pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
2236 	sav->phy_cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2a));
2237 	sav->phy_syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
2238 	sav->phy_dacctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
2239 
2240 	if (!BWN_HAS_TXMAG(phy)) {
2241 		sav->rf2 = BWN_RF_READ(mac, 0x52);
2242 		sav->rf2 &= 0x00f0;
2243 	}
2244 	if (phy->type == BWN_PHYTYPE_B) {
2245 		sav->phy_cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
2246 		sav->phy_cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x06));
2247 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0x00ff);
2248 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), 0x3f3f);
2249 	} else {
2250 		BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2)
2251 			    | 0x8000);
2252 	}
2253 	BWN_WRITE_2(mac, 0x3f4, BWN_READ_2(mac, 0x3f4)
2254 		    & 0xf000);
2255 
2256 	tmp =
2257 	    (phy->type == BWN_PHYTYPE_G) ? BWN_PHY_LO_MASK : BWN_PHY_CCK(0x2e);
2258 	BWN_PHY_WRITE(mac, tmp, 0x007f);
2259 
2260 	tmp = sav->phy_syncctl;
2261 	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, tmp & 0xff7f);
2262 	tmp = sav->rf1;
2263 	BWN_RF_WRITE(mac, 0x007a, tmp & 0xfff0);
2264 
2265 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), 0x8a3);
2266 	if (phy->type == BWN_PHYTYPE_G ||
2267 	    (phy->type == BWN_PHYTYPE_B &&
2268 	     phy->rf_ver == 0x2050 && phy->rf_rev >= 6)) {
2269 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1003);
2270 	} else
2271 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x0802);
2272 	if (phy->rev >= 2)
2273 		bwn_dummy_transmission(mac, 0, 1);
2274 	bwn_phy_g_switch_chan(mac, 6, 0);
2275 	BWN_RF_READ(mac, 0x51);
2276 	if (phy->type == BWN_PHYTYPE_G)
2277 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0);
2278 
2279 	nanouptime(&ts);
2280 	if (ieee80211_time_before(lo->txctl_measured_time,
2281 	    (ts.tv_nsec / 1000000 + ts.tv_sec * 1000) - BWN_LO_TXCTL_EXPIRE))
2282 		bwn_lo_measure_txctl_values(mac);
2283 
2284 	if (phy->type == BWN_PHYTYPE_G && phy->rev >= 3)
2285 		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc078);
2286 	else {
2287 		if (phy->type == BWN_PHYTYPE_B)
2288 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
2289 		else
2290 			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
2291 	}
2292 }
2293 
2294 static void
2295 bwn_lo_restore(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
2296 {
2297 	struct bwn_phy *phy = &mac->mac_phy;
2298 	struct bwn_phy_g *pg = &phy->phy_g;
2299 	uint16_t tmp;
2300 
2301 	if (phy->rev >= 2) {
2302 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
2303 		tmp = (pg->pg_pga_gain << 8);
2304 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa0);
2305 		DELAY(5);
2306 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa2);
2307 		DELAY(2);
2308 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa3);
2309 	} else {
2310 		tmp = (pg->pg_pga_gain | 0xefa0);
2311 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, tmp);
2312 	}
2313 	if (phy->type == BWN_PHYTYPE_G) {
2314 		if (phy->rev >= 3)
2315 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0xc078);
2316 		else
2317 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
2318 		if (phy->rev >= 2)
2319 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0202);
2320 		else
2321 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0101);
2322 	}
2323 	BWN_WRITE_2(mac, 0x3f4, sav->reg0);
2324 	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, sav->phy_pgactl);
2325 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), sav->phy_cck2);
2326 	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, sav->phy_syncctl);
2327 	BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl);
2328 	BWN_RF_WRITE(mac, 0x43, sav->rf0);
2329 	BWN_RF_WRITE(mac, 0x7a, sav->rf1);
2330 	if (!BWN_HAS_TXMAG(phy)) {
2331 		tmp = sav->rf2;
2332 		BWN_RF_SETMASK(mac, 0x52, 0xff0f, tmp);
2333 	}
2334 	BWN_WRITE_2(mac, 0x3e2, sav->reg1);
2335 	if (phy->type == BWN_PHYTYPE_B &&
2336 	    phy->rf_ver == 0x2050 && phy->rf_rev <= 5) {
2337 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), sav->phy_cck0);
2338 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), sav->phy_cck1);
2339 	}
2340 	if (phy->rev >= 2) {
2341 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, sav->phy_analogover);
2342 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
2343 			      sav->phy_analogoverval);
2344 		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, sav->phy_classctl);
2345 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, sav->phy_rfover);
2346 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, sav->phy_rfoverval);
2347 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), sav->phy_cck3);
2348 		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, sav->phy_crs0);
2349 	}
2350 	if (bwn_has_hwpctl(mac)) {
2351 		tmp = (sav->phy_lomask & 0xbfff);
2352 		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, tmp);
2353 		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x01), sav->phy_extg);
2354 		BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl_hwpctl);
2355 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x14), sav->phy_cck4);
2356 		BWN_PHY_WRITE(mac, BWN_PHY_HPWR_TSSICTL, sav->phy_hpwr_tssictl);
2357 	}
2358 	bwn_phy_g_switch_chan(mac, sav->old_channel, 1);
2359 }
2360 
2361 static int
2362 bwn_lo_probe_loctl(struct bwn_mac *mac,
2363     struct bwn_loctl *probe, struct bwn_lo_g_sm *d)
2364 {
2365 	struct bwn_phy *phy = &mac->mac_phy;
2366 	struct bwn_phy_g *pg = &phy->phy_g;
2367 	struct bwn_loctl orig, test;
2368 	struct bwn_loctl prev = { -100, -100 };
2369 	static const struct bwn_loctl modifiers[] = {
2370 		{  1,  1,}, {  1,  0,}, {  1, -1,}, {  0, -1,},
2371 		{ -1, -1,}, { -1,  0,}, { -1,  1,}, {  0,  1,}
2372 	};
2373 	int begin, end, lower = 0, i;
2374 	uint16_t feedth;
2375 
2376 	if (d->curstate == 0) {
2377 		begin = 1;
2378 		end = 8;
2379 	} else if (d->curstate % 2 == 0) {
2380 		begin = d->curstate - 1;
2381 		end = d->curstate + 1;
2382 	} else {
2383 		begin = d->curstate - 2;
2384 		end = d->curstate + 2;
2385 	}
2386 	if (begin < 1)
2387 		begin += 8;
2388 	if (end > 8)
2389 		end -= 8;
2390 
2391 	memcpy(&orig, probe, sizeof(struct bwn_loctl));
2392 	i = begin;
2393 	d->curstate = i;
2394 	while (1) {
2395 		KASSERT(i >= 1 && i <= 8, ("%s:%d: fail", __func__, __LINE__));
2396 		memcpy(&test, &orig, sizeof(struct bwn_loctl));
2397 		test.i += modifiers[i - 1].i * d->multipler;
2398 		test.q += modifiers[i - 1].q * d->multipler;
2399 		if ((test.i != prev.i || test.q != prev.q) &&
2400 		    (abs(test.i) <= 16 && abs(test.q) <= 16)) {
2401 			bwn_lo_write(mac, &test);
2402 			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
2403 			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
2404 			if (feedth < d->feedth) {
2405 				memcpy(probe, &test,
2406 				    sizeof(struct bwn_loctl));
2407 				lower = 1;
2408 				d->feedth = feedth;
2409 				if (d->nmeasure < 2 && !BWN_HAS_LOOPBACK(phy))
2410 					break;
2411 			}
2412 		}
2413 		memcpy(&prev, &test, sizeof(prev));
2414 		if (i == end)
2415 			break;
2416 		if (i == 8)
2417 			i = 1;
2418 		else
2419 			i++;
2420 		d->curstate = i;
2421 	}
2422 
2423 	return (lower);
2424 }
2425 
2426 static void
2427 bwn_lo_probe_sm(struct bwn_mac *mac, struct bwn_loctl *loctl, int *rxgain)
2428 {
2429 	struct bwn_phy *phy = &mac->mac_phy;
2430 	struct bwn_phy_g *pg = &phy->phy_g;
2431 	struct bwn_lo_g_sm d;
2432 	struct bwn_loctl probe;
2433 	int lower, repeat, cnt = 0;
2434 	uint16_t feedth;
2435 
2436 	d.nmeasure = 0;
2437 	d.multipler = 1;
2438 	if (BWN_HAS_LOOPBACK(phy))
2439 		d.multipler = 3;
2440 
2441 	memcpy(&d.loctl, loctl, sizeof(struct bwn_loctl));
2442 	repeat = (BWN_HAS_LOOPBACK(phy)) ? 4 : 1;
2443 
2444 	do {
2445 		bwn_lo_write(mac, &d.loctl);
2446 		feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
2447 		    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
2448 		if (feedth < 0x258) {
2449 			if (feedth >= 0x12c)
2450 				*rxgain += 6;
2451 			else
2452 				*rxgain += 3;
2453 			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
2454 			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
2455 		}
2456 		d.feedth = feedth;
2457 		d.curstate = 0;
2458 		do {
2459 			KASSERT(d.curstate >= 0 && d.curstate <= 8,
2460 			    ("%s:%d: fail", __func__, __LINE__));
2461 			memcpy(&probe, &d.loctl,
2462 			       sizeof(struct bwn_loctl));
2463 			lower = bwn_lo_probe_loctl(mac, &probe, &d);
2464 			if (!lower)
2465 				break;
2466 			if ((probe.i == d.loctl.i) && (probe.q == d.loctl.q))
2467 				break;
2468 			memcpy(&d.loctl, &probe, sizeof(struct bwn_loctl));
2469 			d.nmeasure++;
2470 		} while (d.nmeasure < 24);
2471 		memcpy(loctl, &d.loctl, sizeof(struct bwn_loctl));
2472 
2473 		if (BWN_HAS_LOOPBACK(phy)) {
2474 			if (d.feedth > 0x1194)
2475 				*rxgain -= 6;
2476 			else if (d.feedth < 0x5dc)
2477 				*rxgain += 3;
2478 			if (cnt == 0) {
2479 				if (d.feedth <= 0x5dc) {
2480 					d.multipler = 1;
2481 					cnt++;
2482 				} else
2483 					d.multipler = 2;
2484 			} else if (cnt == 2)
2485 				d.multipler = 1;
2486 		}
2487 		bwn_lo_measure_gain_values(mac, *rxgain, BWN_HAS_LOOPBACK(phy));
2488 	} while (++cnt < repeat);
2489 }
2490 
2491 static struct bwn_lo_calib *
2492 bwn_lo_calibset(struct bwn_mac *mac,
2493     const struct bwn_bbatt *bbatt, const struct bwn_rfatt *rfatt)
2494 {
2495 	struct bwn_phy *phy = &mac->mac_phy;
2496 	struct bwn_phy_g *pg = &phy->phy_g;
2497 	struct bwn_loctl loctl = { 0, 0 };
2498 	struct bwn_lo_calib *cal;
2499 	struct bwn_lo_g_value sval = { 0 };
2500 	int rxgain;
2501 	uint16_t pad, reg, value;
2502 
2503 	sval.old_channel = phy->chan;
2504 	bwn_mac_suspend(mac);
2505 	bwn_lo_save(mac, &sval);
2506 
2507 	reg = bwn_lo_txctl_regtable(mac, &value, &pad);
2508 	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rfatt->att);
2509 	BWN_RF_SETMASK(mac, reg, ~value, (rfatt->padmix ? value :0));
2510 
2511 	rxgain = (rfatt->att * 2) + (bbatt->att / 2);
2512 	if (rfatt->padmix)
2513 		rxgain -= pad;
2514 	if (BWN_HAS_LOOPBACK(phy))
2515 		rxgain += pg->pg_max_lb_gain;
2516 	bwn_lo_measure_gain_values(mac, rxgain, BWN_HAS_LOOPBACK(phy));
2517 	bwn_phy_g_set_bbatt(mac, bbatt->att);
2518 	bwn_lo_probe_sm(mac, &loctl, &rxgain);
2519 
2520 	bwn_lo_restore(mac, &sval);
2521 	bwn_mac_enable(mac);
2522 
2523 	cal = malloc(sizeof(*cal), M_DEVBUF, M_NOWAIT | M_ZERO);
2524 	if (!cal) {
2525 		device_printf(mac->mac_sc->sc_dev, "out of memory\n");
2526 		return (NULL);
2527 	}
2528 	memcpy(&cal->bbatt, bbatt, sizeof(*bbatt));
2529 	memcpy(&cal->rfatt, rfatt, sizeof(*rfatt));
2530 	memcpy(&cal->ctl, &loctl, sizeof(loctl));
2531 
2532 	BWN_GETTIME(cal->calib_time);
2533 
2534 	return (cal);
2535 }
2536 
2537 static struct bwn_lo_calib *
2538 bwn_lo_get_calib(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
2539     const struct bwn_rfatt *rfatt)
2540 {
2541 	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
2542 	struct bwn_lo_calib *c;
2543 
2544 	TAILQ_FOREACH(c, &lo->calib_list, list) {
2545 		if (!BWN_BBATTCMP(&c->bbatt, bbatt))
2546 			continue;
2547 		if (!BWN_RFATTCMP(&c->rfatt, rfatt))
2548 			continue;
2549 		return (c);
2550 	}
2551 
2552 	c = bwn_lo_calibset(mac, bbatt, rfatt);
2553 	if (!c)
2554 		return (NULL);
2555 	TAILQ_INSERT_TAIL(&lo->calib_list, c, list);
2556 
2557 	return (c);
2558 }
2559 
2560 static void
2561 bwn_phy_g_dc_lookup_init(struct bwn_mac *mac, uint8_t update)
2562 {
2563 	struct bwn_phy *phy = &mac->mac_phy;
2564 	struct bwn_phy_g *pg = &phy->phy_g;
2565 	struct bwn_softc *sc = mac->mac_sc;
2566 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2567 	const struct bwn_rfatt *rfatt;
2568 	const struct bwn_bbatt *bbatt;
2569 	uint64_t pvector;
2570 	int i;
2571 	int rf_offset, bb_offset;
2572 	uint8_t changed = 0;
2573 
2574 	KASSERT(BWN_DC_LT_SIZE == 32, ("%s:%d: fail", __func__, __LINE__));
2575 	KASSERT(lo->rfatt.len * lo->bbatt.len <= 64,
2576 	    ("%s:%d: fail", __func__, __LINE__));
2577 
2578 	pvector = lo->power_vector;
2579 	if (!update && !pvector)
2580 		return;
2581 
2582 	bwn_mac_suspend(mac);
2583 
2584 	for (i = 0; i < BWN_DC_LT_SIZE * 2; i++) {
2585 		struct bwn_lo_calib *cal;
2586 		int idx;
2587 		uint16_t val;
2588 
2589 		if (!update && !(pvector & (((uint64_t)1ULL) << i)))
2590 			continue;
2591 		bb_offset = i / lo->rfatt.len;
2592 		rf_offset = i % lo->rfatt.len;
2593 		bbatt = &(lo->bbatt.array[bb_offset]);
2594 		rfatt = &(lo->rfatt.array[rf_offset]);
2595 
2596 		cal = bwn_lo_calibset(mac, bbatt, rfatt);
2597 		if (!cal) {
2598 			device_printf(sc->sc_dev, "LO: Could not "
2599 			    "calibrate DC table entry\n");
2600 			continue;
2601 		}
2602 		val = (uint8_t)(cal->ctl.q);
2603 		val |= ((uint8_t)(cal->ctl.i)) << 4;
2604 		free(cal, M_DEVBUF);
2605 
2606 		idx = i / 2;
2607 		if (i % 2)
2608 			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0x00ff)
2609 			    | ((val & 0x00ff) << 8);
2610 		else
2611 			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0xff00)
2612 			    | (val & 0x00ff);
2613 		changed = 1;
2614 	}
2615 	if (changed) {
2616 		for (i = 0; i < BWN_DC_LT_SIZE; i++)
2617 			BWN_PHY_WRITE(mac, 0x3a0 + i, lo->dc_lt[i]);
2618 	}
2619 	bwn_mac_enable(mac);
2620 }
2621 
2622 static void
2623 bwn_lo_fixup_rfatt(struct bwn_rfatt *rf)
2624 {
2625 
2626 	if (!rf->padmix)
2627 		return;
2628 	if ((rf->att != 1) && (rf->att != 2) && (rf->att != 3))
2629 		rf->att = 4;
2630 }
2631 
2632 static void
2633 bwn_lo_g_adjust(struct bwn_mac *mac)
2634 {
2635 	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
2636 	struct bwn_lo_calib *cal;
2637 	struct bwn_rfatt rf;
2638 
2639 	memcpy(&rf, &pg->pg_rfatt, sizeof(rf));
2640 	bwn_lo_fixup_rfatt(&rf);
2641 
2642 	cal = bwn_lo_get_calib(mac, &pg->pg_bbatt, &rf);
2643 	if (!cal)
2644 		return;
2645 	bwn_lo_write(mac, &cal->ctl);
2646 }
2647 
2648 static void
2649 bwn_lo_g_init(struct bwn_mac *mac)
2650 {
2651 
2652 	if (!bwn_has_hwpctl(mac))
2653 		return;
2654 
2655 	bwn_lo_get_powervector(mac);
2656 	bwn_phy_g_dc_lookup_init(mac, 1);
2657 }
2658 
2659 static int16_t
2660 bwn_nrssi_read(struct bwn_mac *mac, uint16_t offset)
2661 {
2662 
2663 	BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, offset);
2664 	return ((int16_t)BWN_PHY_READ(mac, BWN_PHY_NRSSI_DATA));
2665 }
2666 
2667 static void
2668 bwn_nrssi_threshold(struct bwn_mac *mac)
2669 {
2670 	struct bwn_phy *phy = &mac->mac_phy;
2671 	struct bwn_phy_g *pg = &phy->phy_g;
2672 	struct bwn_softc *sc = mac->mac_sc;
2673 	int32_t a, b;
2674 	int16_t tmp16;
2675 	uint16_t tmpu16;
2676 
2677 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2678 
2679 	if (phy->gmode && (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI)) {
2680 		if (!pg->pg_aci_wlan_automatic && pg->pg_aci_enable) {
2681 			a = 0x13;
2682 			b = 0x12;
2683 		} else {
2684 			a = 0xe;
2685 			b = 0x11;
2686 		}
2687 
2688 		a = a * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
2689 		a += (pg->pg_nrssi[0] << 6);
2690 		a += (a < 32) ? 31 : 32;
2691 		a = a >> 6;
2692 		a = MIN(MAX(a, -31), 31);
2693 
2694 		b = b * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
2695 		b += (pg->pg_nrssi[0] << 6);
2696 		if (b < 32)
2697 			b += 31;
2698 		else
2699 			b += 32;
2700 		b = b >> 6;
2701 		b = MIN(MAX(b, -31), 31);
2702 
2703 		tmpu16 = BWN_PHY_READ(mac, 0x048a) & 0xf000;
2704 		tmpu16 |= ((uint32_t)b & 0x0000003f);
2705 		tmpu16 |= (((uint32_t)a & 0x0000003f) << 6);
2706 		BWN_PHY_WRITE(mac, 0x048a, tmpu16);
2707 		return;
2708 	}
2709 
2710 	tmp16 = bwn_nrssi_read(mac, 0x20);
2711 	if (tmp16 >= 0x20)
2712 		tmp16 -= 0x40;
2713 	BWN_PHY_SETMASK(mac, 0x048a, 0xf000, (tmp16 < 3) ? 0x09eb : 0x0aed);
2714 }
2715 
2716 static void
2717 bwn_nrssi_slope_11g(struct bwn_mac *mac)
2718 {
2719 #define	SAVE_RF_MAX		3
2720 #define	SAVE_PHY_COMM_MAX	4
2721 #define	SAVE_PHY3_MAX		8
2722 	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
2723 		{ 0x7a, 0x52, 0x43 };
2724 	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] =
2725 		{ 0x15, 0x5a, 0x59, 0x58 };
2726 	static const uint16_t save_phy3_regs[SAVE_PHY3_MAX] = {
2727 		0x002e, 0x002f, 0x080f, BWN_PHY_G_LOCTL,
2728 		0x0801, 0x0060, 0x0014, 0x0478
2729 	};
2730 	struct bwn_phy *phy = &mac->mac_phy;
2731 	struct bwn_phy_g *pg = &phy->phy_g;
2732 	int32_t i, tmp32, phy3_idx = 0;
2733 	uint16_t delta, tmp;
2734 	uint16_t save_rf[SAVE_RF_MAX];
2735 	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
2736 	uint16_t save_phy3[SAVE_PHY3_MAX];
2737 	uint16_t ant_div, phy0, chan_ex;
2738 	int16_t nrssi0, nrssi1;
2739 
2740 	KASSERT(phy->type == BWN_PHYTYPE_G,
2741 	    ("%s:%d: fail", __func__, __LINE__));
2742 
2743 	if (phy->rf_rev >= 9)
2744 		return;
2745 	if (phy->rf_rev == 8)
2746 		bwn_nrssi_offset(mac);
2747 
2748 	BWN_PHY_MASK(mac, BWN_PHY_G_CRS, 0x7fff);
2749 	BWN_PHY_MASK(mac, 0x0802, 0xfffc);
2750 
2751 	/*
2752 	 * Save RF/PHY registers for later restoration
2753 	 */
2754 	ant_div = BWN_READ_2(mac, 0x03e2);
2755 	BWN_WRITE_2(mac, 0x03e2, BWN_READ_2(mac, 0x03e2) | 0x8000);
2756 	for (i = 0; i < SAVE_RF_MAX; ++i)
2757 		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
2758 	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
2759 		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
2760 
2761 	phy0 = BWN_READ_2(mac, BWN_PHY0);
2762 	chan_ex = BWN_READ_2(mac, BWN_CHANNEL_EXT);
2763 	if (phy->rev >= 3) {
2764 		for (i = 0; i < SAVE_PHY3_MAX; ++i)
2765 			save_phy3[i] = BWN_PHY_READ(mac, save_phy3_regs[i]);
2766 		BWN_PHY_WRITE(mac, 0x002e, 0);
2767 		BWN_PHY_WRITE(mac, BWN_PHY_G_LOCTL, 0);
2768 		switch (phy->rev) {
2769 		case 4:
2770 		case 6:
2771 		case 7:
2772 			BWN_PHY_SET(mac, 0x0478, 0x0100);
2773 			BWN_PHY_SET(mac, 0x0801, 0x0040);
2774 			break;
2775 		case 3:
2776 		case 5:
2777 			BWN_PHY_MASK(mac, 0x0801, 0xffbf);
2778 			break;
2779 		}
2780 		BWN_PHY_SET(mac, 0x0060, 0x0040);
2781 		BWN_PHY_SET(mac, 0x0014, 0x0200);
2782 	}
2783 	/*
2784 	 * Calculate nrssi0
2785 	 */
2786 	BWN_RF_SET(mac, 0x007a, 0x0070);
2787 	bwn_set_all_gains(mac, 0, 8, 0);
2788 	BWN_RF_MASK(mac, 0x007a, 0x00f7);
2789 	if (phy->rev >= 2) {
2790 		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0030);
2791 		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0010);
2792 	}
2793 	BWN_RF_SET(mac, 0x007a, 0x0080);
2794 	DELAY(20);
2795 
2796 	nrssi0 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
2797 	if (nrssi0 >= 0x0020)
2798 		nrssi0 -= 0x0040;
2799 
2800 	/*
2801 	 * Calculate nrssi1
2802 	 */
2803 	BWN_RF_MASK(mac, 0x007a, 0x007f);
2804 	if (phy->rev >= 2)
2805 		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
2806 
2807 	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
2808 	    BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000);
2809 	BWN_RF_SET(mac, 0x007a, 0x000f);
2810 	BWN_PHY_WRITE(mac, 0x0015, 0xf330);
2811 	if (phy->rev >= 2) {
2812 		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0020);
2813 		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0020);
2814 	}
2815 
2816 	bwn_set_all_gains(mac, 3, 0, 1);
2817 	if (phy->rf_rev == 8) {
2818 		BWN_RF_WRITE(mac, 0x0043, 0x001f);
2819 	} else {
2820 		tmp = BWN_RF_READ(mac, 0x0052) & 0xff0f;
2821 		BWN_RF_WRITE(mac, 0x0052, tmp | 0x0060);
2822 		tmp = BWN_RF_READ(mac, 0x0043) & 0xfff0;
2823 		BWN_RF_WRITE(mac, 0x0043, tmp | 0x0009);
2824 	}
2825 	BWN_PHY_WRITE(mac, 0x005a, 0x0480);
2826 	BWN_PHY_WRITE(mac, 0x0059, 0x0810);
2827 	BWN_PHY_WRITE(mac, 0x0058, 0x000d);
2828 	DELAY(20);
2829 	nrssi1 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
2830 
2831 	/*
2832 	 * Install calculated narrow RSSI values
2833 	 */
2834 	if (nrssi1 >= 0x0020)
2835 		nrssi1 -= 0x0040;
2836 	if (nrssi0 == nrssi1)
2837 		pg->pg_nrssi_slope = 0x00010000;
2838 	else
2839 		pg->pg_nrssi_slope = 0x00400000 / (nrssi0 - nrssi1);
2840 	if (nrssi0 >= -4) {
2841 		pg->pg_nrssi[0] = nrssi1;
2842 		pg->pg_nrssi[1] = nrssi0;
2843 	}
2844 
2845 	/*
2846 	 * Restore saved RF/PHY registers
2847 	 */
2848 	if (phy->rev >= 3) {
2849 		for (phy3_idx = 0; phy3_idx < 4; ++phy3_idx) {
2850 			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
2851 			    save_phy3[phy3_idx]);
2852 		}
2853 	}
2854 	if (phy->rev >= 2) {
2855 		BWN_PHY_MASK(mac, 0x0812, 0xffcf);
2856 		BWN_PHY_MASK(mac, 0x0811, 0xffcf);
2857 	}
2858 
2859 	for (i = 0; i < SAVE_RF_MAX; ++i)
2860 		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
2861 
2862 	BWN_WRITE_2(mac, 0x03e2, ant_div);
2863 	BWN_WRITE_2(mac, 0x03e6, phy0);
2864 	BWN_WRITE_2(mac, BWN_CHANNEL_EXT, chan_ex);
2865 
2866 	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
2867 		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
2868 
2869 	bwn_spu_workaround(mac, phy->chan);
2870 	BWN_PHY_SET(mac, 0x0802, (0x0001 | 0x0002));
2871 	bwn_set_original_gains(mac);
2872 	BWN_PHY_SET(mac, BWN_PHY_G_CRS, 0x8000);
2873 	if (phy->rev >= 3) {
2874 		for (; phy3_idx < SAVE_PHY3_MAX; ++phy3_idx) {
2875 			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
2876 			    save_phy3[phy3_idx]);
2877 		}
2878 	}
2879 
2880 	delta = 0x1f - pg->pg_nrssi[0];
2881 	for (i = 0; i < 64; i++) {
2882 		tmp32 = (((i - delta) * pg->pg_nrssi_slope) / 0x10000) + 0x3a;
2883 		tmp32 = MIN(MAX(tmp32, 0), 0x3f);
2884 		pg->pg_nrssi_lt[i] = tmp32;
2885 	}
2886 
2887 	bwn_nrssi_threshold(mac);
2888 #undef SAVE_RF_MAX
2889 #undef SAVE_PHY_COMM_MAX
2890 #undef SAVE_PHY3_MAX
2891 }
2892 
2893 static void
2894 bwn_nrssi_offset(struct bwn_mac *mac)
2895 {
2896 #define	SAVE_RF_MAX		2
2897 #define	SAVE_PHY_COMM_MAX	10
2898 #define	SAVE_PHY6_MAX		8
2899 	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
2900 		{ 0x7a, 0x43 };
2901 	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] = {
2902 		0x0001, 0x0811, 0x0812, 0x0814,
2903 		0x0815, 0x005a, 0x0059, 0x0058,
2904 		0x000a, 0x0003
2905 	};
2906 	static const uint16_t save_phy6_regs[SAVE_PHY6_MAX] = {
2907 		0x002e, 0x002f, 0x080f, 0x0810,
2908 		0x0801, 0x0060, 0x0014, 0x0478
2909 	};
2910 	struct bwn_phy *phy = &mac->mac_phy;
2911 	int i, phy6_idx = 0;
2912 	uint16_t save_rf[SAVE_RF_MAX];
2913 	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
2914 	uint16_t save_phy6[SAVE_PHY6_MAX];
2915 	int16_t nrssi;
2916 	uint16_t saved = 0xffff;
2917 
2918 	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
2919 		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
2920 	for (i = 0; i < SAVE_RF_MAX; ++i)
2921 		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
2922 
2923 	BWN_PHY_MASK(mac, 0x0429, 0x7fff);
2924 	BWN_PHY_SETMASK(mac, 0x0001, 0x3fff, 0x4000);
2925 	BWN_PHY_SET(mac, 0x0811, 0x000c);
2926 	BWN_PHY_SETMASK(mac, 0x0812, 0xfff3, 0x0004);
2927 	BWN_PHY_MASK(mac, 0x0802, ~(0x1 | 0x2));
2928 	if (phy->rev >= 6) {
2929 		for (i = 0; i < SAVE_PHY6_MAX; ++i)
2930 			save_phy6[i] = BWN_PHY_READ(mac, save_phy6_regs[i]);
2931 
2932 		BWN_PHY_WRITE(mac, 0x002e, 0);
2933 		BWN_PHY_WRITE(mac, 0x002f, 0);
2934 		BWN_PHY_WRITE(mac, 0x080f, 0);
2935 		BWN_PHY_WRITE(mac, 0x0810, 0);
2936 		BWN_PHY_SET(mac, 0x0478, 0x0100);
2937 		BWN_PHY_SET(mac, 0x0801, 0x0040);
2938 		BWN_PHY_SET(mac, 0x0060, 0x0040);
2939 		BWN_PHY_SET(mac, 0x0014, 0x0200);
2940 	}
2941 	BWN_RF_SET(mac, 0x007a, 0x0070);
2942 	BWN_RF_SET(mac, 0x007a, 0x0080);
2943 	DELAY(30);
2944 
2945 	nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
2946 	if (nrssi >= 0x20)
2947 		nrssi -= 0x40;
2948 	if (nrssi == 31) {
2949 		for (i = 7; i >= 4; i--) {
2950 			BWN_RF_WRITE(mac, 0x007b, i);
2951 			DELAY(20);
2952 			nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) &
2953 			    0x003f);
2954 			if (nrssi >= 0x20)
2955 				nrssi -= 0x40;
2956 			if (nrssi < 31 && saved == 0xffff)
2957 				saved = i;
2958 		}
2959 		if (saved == 0xffff)
2960 			saved = 4;
2961 	} else {
2962 		BWN_RF_MASK(mac, 0x007a, 0x007f);
2963 		if (phy->rev != 1) {
2964 			BWN_PHY_SET(mac, 0x0814, 0x0001);
2965 			BWN_PHY_MASK(mac, 0x0815, 0xfffe);
2966 		}
2967 		BWN_PHY_SET(mac, 0x0811, 0x000c);
2968 		BWN_PHY_SET(mac, 0x0812, 0x000c);
2969 		BWN_PHY_SET(mac, 0x0811, 0x0030);
2970 		BWN_PHY_SET(mac, 0x0812, 0x0030);
2971 		BWN_PHY_WRITE(mac, 0x005a, 0x0480);
2972 		BWN_PHY_WRITE(mac, 0x0059, 0x0810);
2973 		BWN_PHY_WRITE(mac, 0x0058, 0x000d);
2974 		if (phy->rev == 0)
2975 			BWN_PHY_WRITE(mac, 0x0003, 0x0122);
2976 		else
2977 			BWN_PHY_SET(mac, 0x000a, 0x2000);
2978 		if (phy->rev != 1) {
2979 			BWN_PHY_SET(mac, 0x0814, 0x0004);
2980 			BWN_PHY_MASK(mac, 0x0815, 0xfffb);
2981 		}
2982 		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
2983 		BWN_RF_SET(mac, 0x007a, 0x000f);
2984 		bwn_set_all_gains(mac, 3, 0, 1);
2985 		BWN_RF_SETMASK(mac, 0x0043, 0x00f0, 0x000f);
2986 		DELAY(30);
2987 		nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
2988 		if (nrssi >= 0x20)
2989 			nrssi -= 0x40;
2990 		if (nrssi == -32) {
2991 			for (i = 0; i < 4; i++) {
2992 				BWN_RF_WRITE(mac, 0x007b, i);
2993 				DELAY(20);
2994 				nrssi = (int16_t)((BWN_PHY_READ(mac,
2995 				    0x047f) >> 8) & 0x003f);
2996 				if (nrssi >= 0x20)
2997 					nrssi -= 0x40;
2998 				if (nrssi > -31 && saved == 0xffff)
2999 					saved = i;
3000 			}
3001 			if (saved == 0xffff)
3002 				saved = 3;
3003 		} else
3004 			saved = 0;
3005 	}
3006 	BWN_RF_WRITE(mac, 0x007b, saved);
3007 
3008 	/*
3009 	 * Restore saved RF/PHY registers
3010 	 */
3011 	if (phy->rev >= 6) {
3012 		for (phy6_idx = 0; phy6_idx < 4; ++phy6_idx) {
3013 			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
3014 			    save_phy6[phy6_idx]);
3015 		}
3016 	}
3017 	if (phy->rev != 1) {
3018 		for (i = 3; i < 5; i++)
3019 			BWN_PHY_WRITE(mac, save_phy_comm_regs[i],
3020 			    save_phy_comm[i]);
3021 	}
3022 	for (i = 5; i < SAVE_PHY_COMM_MAX; i++)
3023 		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
3024 
3025 	for (i = SAVE_RF_MAX - 1; i >= 0; --i)
3026 		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
3027 
3028 	BWN_PHY_WRITE(mac, 0x0802, BWN_PHY_READ(mac, 0x0802) | 0x1 | 0x2);
3029 	BWN_PHY_SET(mac, 0x0429, 0x8000);
3030 	bwn_set_original_gains(mac);
3031 	if (phy->rev >= 6) {
3032 		for (; phy6_idx < SAVE_PHY6_MAX; ++phy6_idx) {
3033 			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
3034 			    save_phy6[phy6_idx]);
3035 		}
3036 	}
3037 
3038 	BWN_PHY_WRITE(mac, save_phy_comm_regs[0], save_phy_comm[0]);
3039 	BWN_PHY_WRITE(mac, save_phy_comm_regs[2], save_phy_comm[2]);
3040 	BWN_PHY_WRITE(mac, save_phy_comm_regs[1], save_phy_comm[1]);
3041 }
3042 
3043 static void
3044 bwn_set_all_gains(struct bwn_mac *mac, int16_t first, int16_t second,
3045     int16_t third)
3046 {
3047 	struct bwn_phy *phy = &mac->mac_phy;
3048 	uint16_t i;
3049 	uint16_t start = 0x08, end = 0x18;
3050 	uint16_t tmp;
3051 	uint16_t table;
3052 
3053 	if (phy->rev <= 1) {
3054 		start = 0x10;
3055 		end = 0x20;
3056 	}
3057 
3058 	table = BWN_OFDMTAB_GAINX;
3059 	if (phy->rev <= 1)
3060 		table = BWN_OFDMTAB_GAINX_R1;
3061 	for (i = 0; i < 4; i++)
3062 		bwn_ofdmtab_write_2(mac, table, i, first);
3063 
3064 	for (i = start; i < end; i++)
3065 		bwn_ofdmtab_write_2(mac, table, i, second);
3066 
3067 	if (third != -1) {
3068 		tmp = ((uint16_t) third << 14) | ((uint16_t) third << 6);
3069 		BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, tmp);
3070 		BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, tmp);
3071 		BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, tmp);
3072 	}
3073 	bwn_dummy_transmission(mac, 0, 1);
3074 }
3075 
3076 static void
3077 bwn_set_original_gains(struct bwn_mac *mac)
3078 {
3079 	struct bwn_phy *phy = &mac->mac_phy;
3080 	uint16_t i, tmp;
3081 	uint16_t table;
3082 	uint16_t start = 0x0008, end = 0x0018;
3083 
3084 	if (phy->rev <= 1) {
3085 		start = 0x0010;
3086 		end = 0x0020;
3087 	}
3088 
3089 	table = BWN_OFDMTAB_GAINX;
3090 	if (phy->rev <= 1)
3091 		table = BWN_OFDMTAB_GAINX_R1;
3092 	for (i = 0; i < 4; i++) {
3093 		tmp = (i & 0xfffc);
3094 		tmp |= (i & 0x0001) << 1;
3095 		tmp |= (i & 0x0002) >> 1;
3096 
3097 		bwn_ofdmtab_write_2(mac, table, i, tmp);
3098 	}
3099 
3100 	for (i = start; i < end; i++)
3101 		bwn_ofdmtab_write_2(mac, table, i, i - start);
3102 
3103 	BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, 0x4040);
3104 	BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, 0x4040);
3105 	BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, 0x4000);
3106 	bwn_dummy_transmission(mac, 0, 1);
3107 }
3108 
3109 static void
3110 bwn_phy_hwpctl_init(struct bwn_mac *mac)
3111 {
3112 	struct bwn_phy *phy = &mac->mac_phy;
3113 	struct bwn_phy_g *pg = &phy->phy_g;
3114 	struct bwn_rfatt old_rfatt, rfatt;
3115 	struct bwn_bbatt old_bbatt, bbatt;
3116 	struct bwn_softc *sc = mac->mac_sc;
3117 	uint8_t old_txctl = 0;
3118 
3119 	KASSERT(phy->type == BWN_PHYTYPE_G,
3120 	    ("%s:%d: fail", __func__, __LINE__));
3121 
3122 	if ((siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM) &&
3123 	    (siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306))
3124 		return;
3125 
3126 	BWN_PHY_WRITE(mac, 0x0028, 0x8018);
3127 
3128 	BWN_WRITE_2(mac, BWN_PHY0, BWN_READ_2(mac, BWN_PHY0) & 0xffdf);
3129 
3130 	if (!phy->gmode)
3131 		return;
3132 	bwn_hwpctl_early_init(mac);
3133 	if (pg->pg_curtssi == 0) {
3134 		if (phy->rf_ver == 0x2050 && phy->analog == 0) {
3135 			BWN_RF_SETMASK(mac, 0x0076, 0x00f7, 0x0084);
3136 		} else {
3137 			memcpy(&old_rfatt, &pg->pg_rfatt, sizeof(old_rfatt));
3138 			memcpy(&old_bbatt, &pg->pg_bbatt, sizeof(old_bbatt));
3139 			old_txctl = pg->pg_txctl;
3140 
3141 			bbatt.att = 11;
3142 			if (phy->rf_rev == 8) {
3143 				rfatt.att = 15;
3144 				rfatt.padmix = 1;
3145 			} else {
3146 				rfatt.att = 9;
3147 				rfatt.padmix = 0;
3148 			}
3149 			bwn_phy_g_set_txpwr_sub(mac, &bbatt, &rfatt, 0);
3150 		}
3151 		bwn_dummy_transmission(mac, 0, 1);
3152 		pg->pg_curtssi = BWN_PHY_READ(mac, BWN_PHY_TSSI);
3153 		if (phy->rf_ver == 0x2050 && phy->analog == 0)
3154 			BWN_RF_MASK(mac, 0x0076, 0xff7b);
3155 		else
3156 			bwn_phy_g_set_txpwr_sub(mac, &old_bbatt,
3157 			    &old_rfatt, old_txctl);
3158 	}
3159 	bwn_hwpctl_init_gphy(mac);
3160 
3161 	/* clear TSSI */
3162 	bwn_shm_write_2(mac, BWN_SHARED, 0x0058, 0x7f7f);
3163 	bwn_shm_write_2(mac, BWN_SHARED, 0x005a, 0x7f7f);
3164 	bwn_shm_write_2(mac, BWN_SHARED, 0x0070, 0x7f7f);
3165 	bwn_shm_write_2(mac, BWN_SHARED, 0x0072, 0x7f7f);
3166 }
3167 
3168 static void
3169 bwn_hwpctl_early_init(struct bwn_mac *mac)
3170 {
3171 	struct bwn_phy *phy = &mac->mac_phy;
3172 
3173 	if (!bwn_has_hwpctl(mac)) {
3174 		BWN_PHY_WRITE(mac, 0x047a, 0xc111);
3175 		return;
3176 	}
3177 
3178 	BWN_PHY_MASK(mac, 0x0036, 0xfeff);
3179 	BWN_PHY_WRITE(mac, 0x002f, 0x0202);
3180 	BWN_PHY_SET(mac, 0x047c, 0x0002);
3181 	BWN_PHY_SET(mac, 0x047a, 0xf000);
3182 	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
3183 		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
3184 		BWN_PHY_SET(mac, 0x005d, 0x8000);
3185 		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
3186 		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
3187 		BWN_PHY_SET(mac, 0x0036, 0x0400);
3188 	} else {
3189 		BWN_PHY_SET(mac, 0x0036, 0x0200);
3190 		BWN_PHY_SET(mac, 0x0036, 0x0400);
3191 		BWN_PHY_MASK(mac, 0x005d, 0x7fff);
3192 		BWN_PHY_MASK(mac, 0x004f, 0xfffe);
3193 		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
3194 		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
3195 		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
3196 	}
3197 }
3198 
3199 static void
3200 bwn_hwpctl_init_gphy(struct bwn_mac *mac)
3201 {
3202 	struct bwn_phy *phy = &mac->mac_phy;
3203 	struct bwn_phy_g *pg = &phy->phy_g;
3204 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
3205 	int i;
3206 	uint16_t nr_written = 0, tmp, value;
3207 	uint8_t rf, bb;
3208 
3209 	if (!bwn_has_hwpctl(mac)) {
3210 		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_HW_POWERCTL);
3211 		return;
3212 	}
3213 
3214 	BWN_PHY_SETMASK(mac, 0x0036, 0xffc0,
3215 	    (pg->pg_idletssi - pg->pg_curtssi));
3216 	BWN_PHY_SETMASK(mac, 0x0478, 0xff00,
3217 	    (pg->pg_idletssi - pg->pg_curtssi));
3218 
3219 	for (i = 0; i < 32; i++)
3220 		bwn_ofdmtab_write_2(mac, 0x3c20, i, pg->pg_tssi2dbm[i]);
3221 	for (i = 32; i < 64; i++)
3222 		bwn_ofdmtab_write_2(mac, 0x3c00, i - 32, pg->pg_tssi2dbm[i]);
3223 	for (i = 0; i < 64; i += 2) {
3224 		value = (uint16_t) pg->pg_tssi2dbm[i];
3225 		value |= ((uint16_t) pg->pg_tssi2dbm[i + 1]) << 8;
3226 		BWN_PHY_WRITE(mac, 0x380 + (i / 2), value);
3227 	}
3228 
3229 	for (rf = 0; rf < lo->rfatt.len; rf++) {
3230 		for (bb = 0; bb < lo->bbatt.len; bb++) {
3231 			if (nr_written >= 0x40)
3232 				return;
3233 			tmp = lo->bbatt.array[bb].att;
3234 			tmp <<= 8;
3235 			if (phy->rf_rev == 8)
3236 				tmp |= 0x50;
3237 			else
3238 				tmp |= 0x40;
3239 			tmp |= lo->rfatt.array[rf].att;
3240 			BWN_PHY_WRITE(mac, 0x3c0 + nr_written, tmp);
3241 			nr_written++;
3242 		}
3243 	}
3244 
3245 	BWN_PHY_MASK(mac, 0x0060, 0xffbf);
3246 	BWN_PHY_WRITE(mac, 0x0014, 0x0000);
3247 
3248 	KASSERT(phy->rev >= 6, ("%s:%d: fail", __func__, __LINE__));
3249 	BWN_PHY_SET(mac, 0x0478, 0x0800);
3250 	BWN_PHY_MASK(mac, 0x0478, 0xfeff);
3251 	BWN_PHY_MASK(mac, 0x0801, 0xffbf);
3252 
3253 	bwn_phy_g_dc_lookup_init(mac, 1);
3254 	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_HW_POWERCTL);
3255 }
3256 
3257 static void
3258 bwn_phy_g_switch_chan(struct bwn_mac *mac, int channel, uint8_t spu)
3259 {
3260 	struct bwn_softc *sc = mac->mac_sc;
3261 
3262 	if (spu != 0)
3263 		bwn_spu_workaround(mac, channel);
3264 
3265 	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
3266 
3267 	if (channel == 14) {
3268 		if (siba_sprom_get_ccode(sc->sc_dev) == SIBA_CCODE_JAPAN)
3269 			bwn_hf_write(mac,
3270 			    bwn_hf_read(mac) & ~BWN_HF_JAPAN_CHAN14_OFF);
3271 		else
3272 			bwn_hf_write(mac,
3273 			    bwn_hf_read(mac) | BWN_HF_JAPAN_CHAN14_OFF);
3274 		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
3275 		    BWN_READ_2(mac, BWN_CHANNEL_EXT) | (1 << 11));
3276 		return;
3277 	}
3278 
3279 	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
3280 	    BWN_READ_2(mac, BWN_CHANNEL_EXT) & 0xf7bf);
3281 }
3282 
3283 static uint16_t
3284 bwn_phy_g_chan2freq(uint8_t channel)
3285 {
3286 	static const uint8_t bwn_phy_g_rf_channels[] = BWN_PHY_G_RF_CHANNELS;
3287 
3288 	KASSERT(channel >= 1 && channel <= 14,
3289 	    ("%s:%d: fail", __func__, __LINE__));
3290 
3291 	return (bwn_phy_g_rf_channels[channel - 1]);
3292 }
3293 
3294 static void
3295 bwn_phy_g_set_txpwr_sub(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
3296     const struct bwn_rfatt *rfatt, uint8_t txctl)
3297 {
3298 	struct bwn_phy *phy = &mac->mac_phy;
3299 	struct bwn_phy_g *pg = &phy->phy_g;
3300 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
3301 	uint16_t bb, rf;
3302 	uint16_t tx_bias, tx_magn;
3303 
3304 	bb = bbatt->att;
3305 	rf = rfatt->att;
3306 	tx_bias = lo->tx_bias;
3307 	tx_magn = lo->tx_magn;
3308 	if (tx_bias == 0xff)
3309 		tx_bias = 0;
3310 
3311 	pg->pg_txctl = txctl;
3312 	memmove(&pg->pg_rfatt, rfatt, sizeof(*rfatt));
3313 	pg->pg_rfatt.padmix = (txctl & BWN_TXCTL_TXMIX) ? 1 : 0;
3314 	memmove(&pg->pg_bbatt, bbatt, sizeof(*bbatt));
3315 	bwn_phy_g_set_bbatt(mac, bb);
3316 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RADIO_ATT, rf);
3317 	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8)
3318 		BWN_RF_WRITE(mac, 0x43, (rf & 0x000f) | (txctl & 0x0070));
3319 	else {
3320 		BWN_RF_SETMASK(mac, 0x43, 0xfff0, (rf & 0x000f));
3321 		BWN_RF_SETMASK(mac, 0x52, ~0x0070, (txctl & 0x0070));
3322 	}
3323 	if (BWN_HAS_TXMAG(phy))
3324 		BWN_RF_WRITE(mac, 0x52, tx_magn | tx_bias);
3325 	else
3326 		BWN_RF_SETMASK(mac, 0x52, 0xfff0, (tx_bias & 0x000f));
3327 	bwn_lo_g_adjust(mac);
3328 }
3329 
3330 static void
3331 bwn_phy_g_set_bbatt(struct bwn_mac *mac,
3332     uint16_t bbatt)
3333 {
3334 	struct bwn_phy *phy = &mac->mac_phy;
3335 
3336 	if (phy->analog == 0) {
3337 		BWN_WRITE_2(mac, BWN_PHY0,
3338 		    (BWN_READ_2(mac, BWN_PHY0) & 0xfff0) | bbatt);
3339 		return;
3340 	}
3341 	if (phy->analog > 1) {
3342 		BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xffc3, bbatt << 2);
3343 		return;
3344 	}
3345 	BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xff87, bbatt << 3);
3346 }
3347 
3348 static uint16_t
3349 bwn_rf_2050_rfoverval(struct bwn_mac *mac, uint16_t reg, uint32_t lpd)
3350 {
3351 	struct bwn_phy *phy = &mac->mac_phy;
3352 	struct bwn_phy_g *pg = &phy->phy_g;
3353 	struct bwn_softc *sc = mac->mac_sc;
3354 	int max_lb_gain;
3355 	uint16_t extlna;
3356 	uint16_t i;
3357 
3358 	if (phy->gmode == 0)
3359 		return (0);
3360 
3361 	if (BWN_HAS_LOOPBACK(phy)) {
3362 		max_lb_gain = pg->pg_max_lb_gain;
3363 		max_lb_gain += (phy->rf_rev == 8) ? 0x3e : 0x26;
3364 		if (max_lb_gain >= 0x46) {
3365 			extlna = 0x3000;
3366 			max_lb_gain -= 0x46;
3367 		} else if (max_lb_gain >= 0x3a) {
3368 			extlna = 0x1000;
3369 			max_lb_gain -= 0x3a;
3370 		} else if (max_lb_gain >= 0x2e) {
3371 			extlna = 0x2000;
3372 			max_lb_gain -= 0x2e;
3373 		} else {
3374 			extlna = 0;
3375 			max_lb_gain -= 0x10;
3376 		}
3377 
3378 		for (i = 0; i < 16; i++) {
3379 			max_lb_gain -= (i * 6);
3380 			if (max_lb_gain < 6)
3381 				break;
3382 		}
3383 
3384 		if ((phy->rev < 7) ||
3385 		    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA)) {
3386 			if (reg == BWN_PHY_RFOVER) {
3387 				return (0x1b3);
3388 			} else if (reg == BWN_PHY_RFOVERVAL) {
3389 				extlna |= (i << 8);
3390 				switch (lpd) {
3391 				case BWN_LPD(0, 1, 1):
3392 					return (0x0f92);
3393 				case BWN_LPD(0, 0, 1):
3394 				case BWN_LPD(1, 0, 1):
3395 					return (0x0092 | extlna);
3396 				case BWN_LPD(1, 0, 0):
3397 					return (0x0093 | extlna);
3398 				}
3399 				KASSERT(0 == 1,
3400 				    ("%s:%d: fail", __func__, __LINE__));
3401 			}
3402 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3403 		} else {
3404 			if (reg == BWN_PHY_RFOVER)
3405 				return (0x9b3);
3406 			if (reg == BWN_PHY_RFOVERVAL) {
3407 				if (extlna)
3408 					extlna |= 0x8000;
3409 				extlna |= (i << 8);
3410 				switch (lpd) {
3411 				case BWN_LPD(0, 1, 1):
3412 					return (0x8f92);
3413 				case BWN_LPD(0, 0, 1):
3414 					return (0x8092 | extlna);
3415 				case BWN_LPD(1, 0, 1):
3416 					return (0x2092 | extlna);
3417 				case BWN_LPD(1, 0, 0):
3418 					return (0x2093 | extlna);
3419 				}
3420 				KASSERT(0 == 1,
3421 				    ("%s:%d: fail", __func__, __LINE__));
3422 			}
3423 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3424 		}
3425 		return (0);
3426 	}
3427 
3428 	if ((phy->rev < 7) ||
3429 	    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA)) {
3430 		if (reg == BWN_PHY_RFOVER) {
3431 			return (0x1b3);
3432 		} else if (reg == BWN_PHY_RFOVERVAL) {
3433 			switch (lpd) {
3434 			case BWN_LPD(0, 1, 1):
3435 				return (0x0fb2);
3436 			case BWN_LPD(0, 0, 1):
3437 				return (0x00b2);
3438 			case BWN_LPD(1, 0, 1):
3439 				return (0x30b2);
3440 			case BWN_LPD(1, 0, 0):
3441 				return (0x30b3);
3442 			}
3443 			KASSERT(0 == 1,
3444 			    ("%s:%d: fail", __func__, __LINE__));
3445 		}
3446 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3447 	} else {
3448 		if (reg == BWN_PHY_RFOVER) {
3449 			return (0x9b3);
3450 		} else if (reg == BWN_PHY_RFOVERVAL) {
3451 			switch (lpd) {
3452 			case BWN_LPD(0, 1, 1):
3453 				return (0x8fb2);
3454 			case BWN_LPD(0, 0, 1):
3455 				return (0x80b2);
3456 			case BWN_LPD(1, 0, 1):
3457 				return (0x20b2);
3458 			case BWN_LPD(1, 0, 0):
3459 				return (0x20b3);
3460 			}
3461 			KASSERT(0 == 1,
3462 			    ("%s:%d: fail", __func__, __LINE__));
3463 		}
3464 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3465 	}
3466 	return (0);
3467 }
3468 
3469 static void
3470 bwn_spu_workaround(struct bwn_mac *mac, uint8_t channel)
3471 {
3472 
3473 	if (mac->mac_phy.rf_ver != 0x2050 || mac->mac_phy.rf_rev >= 6)
3474 		return;
3475 	BWN_WRITE_2(mac, BWN_CHANNEL, (channel <= 10) ?
3476 	    bwn_phy_g_chan2freq(channel + 4) : bwn_phy_g_chan2freq(1));
3477 	DELAY(1000);
3478 	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
3479 }
3480 
3481 static int
3482 bwn_phy_shm_tssi_read(struct bwn_mac *mac, uint16_t shm_offset)
3483 {
3484 	const uint8_t ofdm = (shm_offset != BWN_SHARED_TSSI_CCK);
3485 	unsigned int a, b, c, d;
3486 	unsigned int avg;
3487 	uint32_t tmp;
3488 
3489 	tmp = bwn_shm_read_4(mac, BWN_SHARED, shm_offset);
3490 	a = tmp & 0xff;
3491 	b = (tmp >> 8) & 0xff;
3492 	c = (tmp >> 16) & 0xff;
3493 	d = (tmp >> 24) & 0xff;
3494 	if (a == 0 || a == BWN_TSSI_MAX || b == 0 || b == BWN_TSSI_MAX ||
3495 	    c == 0 || c == BWN_TSSI_MAX || d == 0 || d == BWN_TSSI_MAX)
3496 		return (ENOENT);
3497 	bwn_shm_write_4(mac, BWN_SHARED, shm_offset,
3498 	    BWN_TSSI_MAX | (BWN_TSSI_MAX << 8) |
3499 	    (BWN_TSSI_MAX << 16) | (BWN_TSSI_MAX << 24));
3500 
3501 	if (ofdm) {
3502 		a = (a + 32) & 0x3f;
3503 		b = (b + 32) & 0x3f;
3504 		c = (c + 32) & 0x3f;
3505 		d = (d + 32) & 0x3f;
3506 	}
3507 
3508 	avg = (a + b + c + d + 2) / 4;
3509 	if (ofdm) {
3510 		if (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO)
3511 		    & BWN_HF_4DB_CCK_POWERBOOST)
3512 			avg = (avg >= 13) ? (avg - 13) : 0;
3513 	}
3514 	return (avg);
3515 }
3516 
3517 static void
3518 bwn_phy_g_setatt(struct bwn_mac *mac, int *bbattp, int *rfattp)
3519 {
3520 	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
3521 	int rfatt = *rfattp;
3522 	int bbatt = *bbattp;
3523 
3524 	while (1) {
3525 		if (rfatt > lo->rfatt.max && bbatt > lo->bbatt.max - 4)
3526 			break;
3527 		if (rfatt < lo->rfatt.min && bbatt < lo->bbatt.min + 4)
3528 			break;
3529 		if (bbatt > lo->bbatt.max && rfatt > lo->rfatt.max - 1)
3530 			break;
3531 		if (bbatt < lo->bbatt.min && rfatt < lo->rfatt.min + 1)
3532 			break;
3533 		if (bbatt > lo->bbatt.max) {
3534 			bbatt -= 4;
3535 			rfatt += 1;
3536 			continue;
3537 		}
3538 		if (bbatt < lo->bbatt.min) {
3539 			bbatt += 4;
3540 			rfatt -= 1;
3541 			continue;
3542 		}
3543 		if (rfatt > lo->rfatt.max) {
3544 			rfatt -= 1;
3545 			bbatt += 4;
3546 			continue;
3547 		}
3548 		if (rfatt < lo->rfatt.min) {
3549 			rfatt += 1;
3550 			bbatt -= 4;
3551 			continue;
3552 		}
3553 		break;
3554 	}
3555 
3556 	*rfattp = MIN(MAX(rfatt, lo->rfatt.min), lo->rfatt.max);
3557 	*bbattp = MIN(MAX(bbatt, lo->bbatt.min), lo->bbatt.max);
3558 }
3559 
3560 static void
3561 bwn_phy_lock(struct bwn_mac *mac)
3562 {
3563 	struct bwn_softc *sc = mac->mac_sc;
3564 	struct ieee80211com *ic = &sc->sc_ic;
3565 
3566 	KASSERT(siba_get_revid(sc->sc_dev) >= 3,
3567 	    ("%s: unsupported rev %d", __func__, siba_get_revid(sc->sc_dev)));
3568 
3569 	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
3570 		bwn_psctl(mac, BWN_PS_AWAKE);
3571 }
3572 
3573 static void
3574 bwn_phy_unlock(struct bwn_mac *mac)
3575 {
3576 	struct bwn_softc *sc = mac->mac_sc;
3577 	struct ieee80211com *ic = &sc->sc_ic;
3578 
3579 	KASSERT(siba_get_revid(sc->sc_dev) >= 3,
3580 	    ("%s: unsupported rev %d", __func__, siba_get_revid(sc->sc_dev)));
3581 
3582 	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
3583 		bwn_psctl(mac, 0);
3584 }
3585 
3586 static void
3587 bwn_rf_lock(struct bwn_mac *mac)
3588 {
3589 
3590 	BWN_WRITE_4(mac, BWN_MACCTL,
3591 	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_RADIO_LOCK);
3592 	BWN_READ_4(mac, BWN_MACCTL);
3593 	DELAY(10);
3594 }
3595 
3596 static void
3597 bwn_rf_unlock(struct bwn_mac *mac)
3598 {
3599 
3600 	BWN_READ_2(mac, BWN_PHYVER);
3601 	BWN_WRITE_4(mac, BWN_MACCTL,
3602 	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_RADIO_LOCK);
3603 }
3604