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