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