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