summaryrefslogtreecommitdiff
path: root/sys/dev/ic
diff options
context:
space:
mode:
authorMarcus Glocker <mglocker@cvs.openbsd.org>2008-02-16 14:56:01 +0000
committerMarcus Glocker <mglocker@cvs.openbsd.org>2008-02-16 14:56:01 +0000
commit2923f2b1356331230722f35e24ccdaca83d6dbfe (patch)
tree29f45d07e63599a78e27ce357546273c049ebd57 /sys/dev/ic
parentac6104755b585d7cc38eea2e11c6afa624589741 (diff)
Better support for 11b mode.
From the DragonFlyBSD driver.
Diffstat (limited to 'sys/dev/ic')
-rw-r--r--sys/dev/ic/bwi.c258
-rw-r--r--sys/dev/ic/bwivar.h13
2 files changed, 249 insertions, 22 deletions
diff --git a/sys/dev/ic/bwi.c b/sys/dev/ic/bwi.c
index ab6202e825e..f935cb51d88 100644
--- a/sys/dev/ic/bwi.c
+++ b/sys/dev/ic/bwi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: bwi.c,v 1.65 2008/02/16 12:36:07 mglocker Exp $ */
+/* $OpenBSD: bwi.c,v 1.66 2008/02/16 14:56:00 mglocker Exp $ */
/*
* Copyright (c) 2007 The DragonFly Project. All rights reserved.
@@ -209,7 +209,7 @@ void bwi_rf_init(struct bwi_mac *);
void bwi_rf_off_11a(struct bwi_mac *);
void bwi_rf_off_11bg(struct bwi_mac *);
void bwi_rf_off_11g_rev5(struct bwi_mac *);
-void bwi_rf_work_around(struct bwi_mac *, uint);
+void bwi_rf_workaround(struct bwi_mac *, uint);
struct bwi_rf_lo
*bwi_rf_lo_find(struct bwi_mac *, const struct bwi_tpctl *);
void bwi_rf_lo_adjust(struct bwi_mac *, const struct bwi_tpctl *);
@@ -222,12 +222,14 @@ uint16_t bwi_rf_calibval(struct bwi_mac *);
int32_t _bwi_adjust_devide(int32_t, int32_t);
int bwi_rf_calc_txpower(int8_t *, uint8_t, const int16_t[]);
int bwi_rf_map_txpower(struct bwi_mac *);
-void bwi_rf_lo_update(struct bwi_mac *);
+
+void bwi_rf_lo_update_11g(struct bwi_mac *);
uint32_t bwi_rf_lo_devi_measure(struct bwi_mac *, uint16_t);
uint16_t bwi_rf_get_tp_ctrl2(struct bwi_mac *);
-uint8_t _bwi_rf_lo_update(struct bwi_mac *, uint16_t);
-void bwi_rf_lo_measure(struct bwi_mac *,
+uint8_t _bwi_rf_lo_update_11g(struct bwi_mac *, uint16_t);
+void bwi_rf_lo_measure_11g(struct bwi_mac *,
const struct bwi_rf_lo *, struct bwi_rf_lo *, uint8_t);
+
void bwi_rf_calc_nrssi_slope_11b(struct bwi_mac *);
void bwi_rf_set_nrssi_ofs_11g(struct bwi_mac *);
void bwi_rf_calc_nrssi_slope_11g(struct bwi_mac *);
@@ -243,6 +245,9 @@ void bwi_rf_on_11bg(struct bwi_mac *);
void bwi_rf_set_ant_mode(struct bwi_mac *, int);
int bwi_rf_get_latest_tssi(struct bwi_mac *, int8_t[], uint16_t);
int bwi_rf_tssi2dbm(struct bwi_mac *, int8_t, int8_t *);
+uint16_t bwi_rf_lo_measure_11b(struct bwi_mac *);
+void bwi_rf_lo_update_11b(struct bwi_mac *);
+
uint16_t bwi_read_sprom(struct bwi_softc *, uint16_t);
void bwi_setup_desc32(struct bwi_softc *, struct bwi_desc32 *, int,
int, bus_addr_t, int, int);
@@ -411,8 +416,12 @@ static const uint32_t bwi_phy_delay_11g_rev1[] =
#define BWI_DEFAULT_IDLE_TSSI 52
struct rf_saveregs {
+ uint16_t phy_01;
+ uint16_t phy_03;
+ uint16_t phy_0a;
uint16_t phy_15;
uint16_t phy_2a;
+ uint16_t phy_30;
uint16_t phy_35;
uint16_t phy_60;
uint16_t phy_429;
@@ -3056,13 +3065,70 @@ bwi_phy_init_11b_rev2(struct bwi_mac *mac)
void
bwi_phy_init_11b_rev4(struct bwi_mac *mac)
{
- struct bwi_softc *sc;
+ struct bwi_softc *sc = mac->mac_sc;
+ struct bwi_rf *rf = &mac->mac_rf;
+ uint16_t val, ofs;
+ u_int chan;
- sc = mac->mac_sc;
+ CSR_WRITE_2(sc, BWI_BPHY_CTRL, BWI_BPHY_CTRL_INIT);
- /* TODO: 11B */
- DPRINTF(1, "%s: %s is not implemented yet\n",
- sc->sc_dev.dv_xname, __func__);
+ PHY_WRITE(mac, 0x20, 0x301c);
+ PHY_WRITE(mac, 0x26, 0);
+ PHY_WRITE(mac, 0x30, 0xc6);
+ PHY_WRITE(mac, 0x88, 0x3e00);
+
+ for (ofs = 0, val = 0x3c3d; ofs < 30; ++ofs, val -= 0x202)
+ PHY_WRITE(mac, 0x89 + ofs, val);
+
+ CSR_WRITE_2(sc, BWI_PHY_MAGIC_REG1, BWI_PHY_MAGIC_REG1_VAL1);
+
+ chan = rf->rf_curchan;
+ if (chan == IEEE80211_CHAN_ANY)
+ chan = 6; /* Force to channel 6 */
+ bwi_rf_set_chan(mac, chan, 0);
+
+ if (rf->rf_type != BWI_RF_T_BCM2050) {
+ RF_WRITE(mac, 0x75, 0x80);
+ RF_WRITE(mac, 0x79, 0x81);
+ }
+
+ RF_WRITE(mac, 0x50, 0x20);
+ RF_WRITE(mac, 0x50, 0x23);
+
+ if (rf->rf_type == BWI_RF_T_BCM2050) {
+ RF_WRITE(mac, 0x50, 0x20);
+ RF_WRITE(mac, 0x5a, 0x70);
+ RF_WRITE(mac, 0x5b, 0x7b);
+ RF_WRITE(mac, 0x5c, 0xb0);
+ RF_WRITE(mac, 0x7a, 0xf);
+ PHY_WRITE(mac, 0x38, 0x677);
+ bwi_rf_init_bcm2050(mac);
+ }
+
+ PHY_WRITE(mac, 0x14, 0x80);
+ PHY_WRITE(mac, 0x32, 0xca);
+ if (rf->rf_type == BWI_RF_T_BCM2050)
+ PHY_WRITE(mac, 0x32, 0xe0);
+ PHY_WRITE(mac, 0x35, 0x7c2);
+
+ bwi_rf_lo_update(mac);
+
+ PHY_WRITE(mac, 0x26, 0xcc00);
+ if (rf->rf_type == BWI_RF_T_BCM2050)
+ PHY_WRITE(mac, 0x26, 0xce00);
+
+ CSR_WRITE_2(sc, BWI_RF_CHAN_EX, 0x1100);
+
+ PHY_WRITE(mac, 0x2a, 0x88a3);
+ if (rf->rf_type == BWI_RF_T_BCM2050)
+ PHY_WRITE(mac, 0x2a, 0x88c2);
+
+ bwi_mac_set_tpctl_11bg(mac, NULL);
+ if (sc->sc_card_flags & BWI_CARD_F_SW_NRSSI) {
+ bwi_rf_calc_nrssi_slope(mac);
+ bwi_rf_set_nrssi_thr(mac);
+ }
+ bwi_mac_init_tpctl_11bg(mac);
}
void
@@ -3649,6 +3715,7 @@ int
bwi_rf_attach(struct bwi_mac *mac)
{
struct bwi_softc *sc = mac->mac_sc;
+ struct bwi_phy *phy = &mac->mac_phy;
struct bwi_rf *rf = &mac->mac_rf;
uint16_t type, manu;
uint8_t rev;
@@ -3690,7 +3757,7 @@ bwi_rf_attach(struct bwi_mac *mac)
*/
rf->rf_ctrl_rd = 0;
rf->rf_ctrl_adj = 0;
- switch (mac->mac_phy.phy_mode) {
+ switch (phy->phy_mode) {
case IEEE80211_MODE_11A:
if (manu != BWI_RF_MANUFACT_BCM ||
type != BWI_RF_T_BCM2060 ||
@@ -3717,6 +3784,10 @@ bwi_rf_attach(struct bwi_mac *mac)
rf->rf_off = bwi_rf_off_11bg;
rf->rf_calc_nrssi_slope = bwi_rf_calc_nrssi_slope_11b;
rf->rf_set_nrssi_thr = bwi_rf_set_nrssi_thr_11b;
+ if (phy->phy_rev == 6)
+ rf->rf_lo_update = bwi_rf_lo_update_11g;
+ else
+ rf->rf_lo_update = bwi_rf_lo_update_11b;
break;
case IEEE80211_MODE_11G:
if (type != BWI_RF_T_BCM2050) {
@@ -3732,6 +3803,7 @@ bwi_rf_attach(struct bwi_mac *mac)
rf->rf_off = bwi_rf_off_11bg;
rf->rf_calc_nrssi_slope = bwi_rf_calc_nrssi_slope_11g;
rf->rf_set_nrssi_thr = bwi_rf_set_nrssi_thr_11g;
+ rf->rf_lo_update = bwi_rf_lo_update_11g;
break;
default:
DPRINTF(1, "%s: unsupported PHY mode\n", sc->sc_dev.dv_xname);
@@ -3760,7 +3832,7 @@ bwi_rf_set_chan(struct bwi_mac *mac, uint chan, int work_around)
/* TODO: 11A */
if (work_around)
- bwi_rf_work_around(mac, chan);
+ bwi_rf_workaround(mac, chan);
CSR_WRITE_2(sc, BWI_RF_CHAN, BWI_RF_2GHZ_CHAN(chan));
@@ -3974,7 +4046,7 @@ bwi_rf_off_11g_rev5(struct bwi_mac *mac)
}
void
-bwi_rf_work_around(struct bwi_mac *mac, uint chan)
+bwi_rf_workaround(struct bwi_mac *mac, uint chan)
{
struct bwi_softc *sc = mac->mac_sc;
struct bwi_rf *rf = &mac->mac_rf;
@@ -4394,7 +4466,7 @@ bwi_rf_init_bcm2050(struct bwi_mac *mac)
CSR_WRITE_2(sc, BWI_RF_CHAN_EX, rf_chan_ex);
PHY_WRITE(mac, 0x35, phyr_35);
- bwi_rf_work_around(mac, rf->rf_curchan);
+ bwi_rf_workaround(mac, rf->rf_curchan);
if (phy->phy_mode == IEEE80211_MODE_11B) {
PHY_WRITE(mac, 0x30, phyr_30);
@@ -4654,7 +4726,7 @@ back:
}
void
-bwi_rf_lo_update(struct bwi_mac *mac)
+bwi_rf_lo_update_11g(struct bwi_mac *mac)
{
struct bwi_softc *sc = mac->mac_sc;
struct ifnet *ifp = &sc->sc_ic.ic_if;
@@ -4666,6 +4738,8 @@ bwi_rf_lo_update(struct bwi_mac *mac)
uint8_t devi_ctrl;
uint orig_chan;
+ DPRINTF(1, "%s: %s\n", sc->sc_dev.dv_xname, __func__);
+
/*
* Save RF/PHY registers for later restoration
*/
@@ -4733,7 +4807,7 @@ bwi_rf_lo_update(struct bwi_mac *mac)
/*
* Measure all RF LO
*/
- devi_ctrl = _bwi_rf_lo_update(mac, regs.rf_7a);
+ devi_ctrl = _bwi_rf_lo_update_11g(mac, regs.rf_7a);
/*
* Restore saved RF/PHY registers
@@ -4848,7 +4922,7 @@ bwi_rf_get_tp_ctrl2(struct bwi_mac *mac)
}
uint8_t
-_bwi_rf_lo_update(struct bwi_mac *mac, uint16_t orig_rf7a)
+_bwi_rf_lo_update_11g(struct bwi_mac *mac, uint16_t orig_rf7a)
{
#define RF_ATTEN_LISTSZ 14
#define BBP_ATTEN_MAX 4 /* half */
@@ -4934,7 +5008,7 @@ _bwi_rf_lo_update(struct bwi_mac *mac, uint16_t orig_rf7a)
lo = bwi_get_rf_lo(mac,
rf_lo_measure_order[idx], bbp_atten * 2);
- bwi_rf_lo_measure(mac, &lo_save, lo, devi_ctrl);
+ bwi_rf_lo_measure_11g(mac, &lo_save, lo, devi_ctrl);
}
}
@@ -4945,7 +5019,7 @@ _bwi_rf_lo_update(struct bwi_mac *mac, uint16_t orig_rf7a)
}
void
-bwi_rf_lo_measure(struct bwi_mac *mac, const struct bwi_rf_lo *src_lo,
+bwi_rf_lo_measure_11g(struct bwi_mac *mac, const struct bwi_rf_lo *src_lo,
struct bwi_rf_lo *dst_lo, uint8_t devi_ctrl)
{
#define LO_ADJUST_MIN 1
@@ -5118,7 +5192,7 @@ bwi_rf_calc_nrssi_slope_11b(struct bwi_mac *mac)
for (i = 1; i < 4; ++i)
PHY_WRITE(mac, save_phy_regs[i], save_phy[i]);
- bwi_rf_work_around(mac, rf->rf_curchan);
+ bwi_rf_workaround(mac, rf->rf_curchan);
if (phy->phy_version != 0)
CSR_WRITE_2(sc, BWI_RF_CHAN_EX, chan_ex);
@@ -5455,7 +5529,7 @@ bwi_rf_calc_nrssi_slope_11g(struct bwi_mac *mac)
for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
- bwi_rf_work_around(mac, rf->rf_curchan);
+ bwi_rf_workaround(mac, rf->rf_curchan);
PHY_SETBITS(mac, 0x802, 0x3);
bwi_set_gains(mac, NULL);
PHY_SETBITS(mac, 0x429, 0x8000);
@@ -5800,6 +5874,148 @@ bwi_rf_tssi2dbm(struct bwi_mac *mac, int8_t tssi, int8_t *txpwr)
return (0);
}
+uint16_t
+bwi_rf_lo_measure_11b(struct bwi_mac *mac)
+{
+ uint16_t val;
+ int i;
+
+ val = 0;
+ for (i = 0; i < 10; ++i) {
+ PHY_WRITE(mac, 0x15, 0xafa0);
+ DELAY(1);
+ PHY_WRITE(mac, 0x15, 0xefa0);
+ DELAY(10);
+ PHY_WRITE(mac, 0x15, 0xffa0);
+ DELAY(40);
+
+ val += PHY_READ(mac, 0x2c);
+ }
+
+ return (val);
+}
+
+void
+bwi_rf_lo_update_11b(struct bwi_mac *mac)
+{
+ struct bwi_softc *sc = mac->mac_sc;
+ struct bwi_rf *rf = &mac->mac_rf;
+ struct rf_saveregs regs;
+ uint16_t rf_val, phy_val, min_val, val;
+ uint16_t rf52, bphy_ctrl;
+ int i;
+
+ DPRINTF(1, "%s: %s\n", sc->sc_dev.dv_xname, __func__);
+
+ bzero(&regs, sizeof(regs));
+ bphy_ctrl = 0;
+
+ /*
+ * Save RF/PHY registers for later restoration
+ */
+ SAVE_PHY_REG(mac, &regs, 15);
+ rf52 = RF_READ(mac, 0x52) & 0xfff0;
+ if (rf->rf_type == BWI_RF_T_BCM2050) {
+ SAVE_PHY_REG(mac, &regs, 0a);
+ SAVE_PHY_REG(mac, &regs, 2a);
+ SAVE_PHY_REG(mac, &regs, 35);
+ SAVE_PHY_REG(mac, &regs, 03);
+ SAVE_PHY_REG(mac, &regs, 01);
+ SAVE_PHY_REG(mac, &regs, 30);
+
+ SAVE_RF_REG(mac, &regs, 43);
+ SAVE_RF_REG(mac, &regs, 7a);
+
+ bphy_ctrl = CSR_READ_2(sc, BWI_BPHY_CTRL);
+
+ SAVE_RF_REG(mac, &regs, 52);
+ regs.rf_52 &= 0xf0;
+
+ PHY_WRITE(mac, 0x30, 0xff);
+ CSR_WRITE_2(sc, BWI_PHY_CTRL, 0x3f3f);
+ PHY_WRITE(mac, 0x35, regs.phy_35 & 0xff7f);
+ RF_WRITE(mac, 0x7a, regs.rf_7a & 0xfff0);
+ }
+
+ PHY_WRITE(mac, 0x15, 0xb000);
+
+ if (rf->rf_type == BWI_RF_T_BCM2050) {
+ PHY_WRITE(mac, 0x2b, 0x203);
+ PHY_WRITE(mac, 0x2a, 0x8a3);
+ } else {
+ PHY_WRITE(mac, 0x2b, 0x1402);
+ }
+
+ /*
+ * Setup RF signal
+ */
+ rf_val = 0;
+ min_val = 65535;
+
+ for (i = 0; i < 4; ++i) {
+ RF_WRITE(mac, 0x52, rf52 | i);
+ bwi_rf_lo_measure_11b(mac); /* Ignore return value */
+ }
+ for (i = 0; i < 10; ++i) {
+ RF_WRITE(mac, 0x52, rf52 | i);
+
+ val = bwi_rf_lo_measure_11b(mac) / 10;
+ if (val < min_val) {
+ min_val = val;
+ rf_val = i;
+ }
+ }
+ RF_WRITE(mac, 0x52, rf52 | rf_val);
+
+ /*
+ * Setup PHY signal
+ */
+ phy_val = 0;
+ min_val = 65535;
+
+ for (i = -4; i < 5; i += 2) {
+ int j;
+
+ for (j = -4; j < 5; j += 2) {
+ uint16_t phy2f;
+
+ phy2f = (0x100 * i) + j;
+ if (j < 0)
+ phy2f += 0x100;
+ PHY_WRITE(mac, 0x2f, phy2f);
+
+ val = bwi_rf_lo_measure_11b(mac) / 10;
+ if (val < min_val) {
+ min_val = val;
+ phy_val = phy2f;
+ }
+ }
+ }
+ PHY_WRITE(mac, 0x2f, phy_val + 0x101);
+
+ /*
+ * Restore saved RF/PHY registers
+ */
+ if (rf->rf_type == BWI_RF_T_BCM2050) {
+ RESTORE_PHY_REG(mac, &regs, 0a);
+ RESTORE_PHY_REG(mac, &regs, 2a);
+ RESTORE_PHY_REG(mac, &regs, 35);
+ RESTORE_PHY_REG(mac, &regs, 03);
+ RESTORE_PHY_REG(mac, &regs, 01);
+ RESTORE_PHY_REG(mac, &regs, 30);
+
+ RESTORE_RF_REG(mac, &regs, 43);
+ RESTORE_RF_REG(mac, &regs, 7a);
+
+ RF_FILT_SETBITS(mac, 0x52, 0xf, regs.rf_52);
+
+ CSR_WRITE_2(sc, BWI_BPHY_CTRL, bphy_ctrl);
+ }
+ RESTORE_PHY_REG(mac, &regs, 15);
+
+ bwi_rf_workaround(mac, rf->rf_curchan);
+}
+
/* IF_BWI */
uint16_t
diff --git a/sys/dev/ic/bwivar.h b/sys/dev/ic/bwivar.h
index c90269b08b0..5f248c036ff 100644
--- a/sys/dev/ic/bwivar.h
+++ b/sys/dev/ic/bwivar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: bwivar.h,v 1.20 2007/11/17 16:50:02 mglocker Exp $ */
+/* $OpenBSD: bwivar.h,v 1.21 2008/02/16 14:56:00 mglocker Exp $ */
/*
* Copyright (c) 2007 The DragonFly Project. All rights reserved.
@@ -372,6 +372,11 @@ struct bwi_rf {
void (*rf_set_nrssi_thr)(struct bwi_mac *);
void (*rf_calc_nrssi_slope)(struct bwi_mac *);
+ int (*rf_calc_rssi)
+ (struct bwi_mac *,
+ const struct bwi_rxbuf_hdr *);
+
+ void (*rf_lo_update)(struct bwi_mac *);
#define BWI_TSSI_MAX 64
int8_t rf_txpower_map0[BWI_TSSI_MAX];
@@ -699,6 +704,12 @@ bwi_rf_set_nrssi_thr(struct bwi_mac *_mac)
_mac->mac_rf.rf_set_nrssi_thr(_mac);
}
+static __inline void
+bwi_rf_lo_update(struct bwi_mac *_mac)
+{
+ return (_mac->mac_rf.rf_lo_update(_mac));
+}
+
#define RF_WRITE(mac, ofs, val) bwi_rf_write((mac), (ofs), (val))
#define RF_READ(mac, ofs) bwi_rf_read((mac), (ofs))