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