diff options
-rw-r--r-- | sys/dev/ic/bwi.c | 258 | ||||
-rw-r--r-- | sys/dev/ic/bwivar.h | 13 |
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(®s, sizeof(regs)); + bphy_ctrl = 0; + + /* + * Save RF/PHY registers for later restoration + */ + SAVE_PHY_REG(mac, ®s, 15); + rf52 = RF_READ(mac, 0x52) & 0xfff0; + if (rf->rf_type == BWI_RF_T_BCM2050) { + SAVE_PHY_REG(mac, ®s, 0a); + SAVE_PHY_REG(mac, ®s, 2a); + SAVE_PHY_REG(mac, ®s, 35); + SAVE_PHY_REG(mac, ®s, 03); + SAVE_PHY_REG(mac, ®s, 01); + SAVE_PHY_REG(mac, ®s, 30); + + SAVE_RF_REG(mac, ®s, 43); + SAVE_RF_REG(mac, ®s, 7a); + + bphy_ctrl = CSR_READ_2(sc, BWI_BPHY_CTRL); + + SAVE_RF_REG(mac, ®s, 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, ®s, 0a); + RESTORE_PHY_REG(mac, ®s, 2a); + RESTORE_PHY_REG(mac, ®s, 35); + RESTORE_PHY_REG(mac, ®s, 03); + RESTORE_PHY_REG(mac, ®s, 01); + RESTORE_PHY_REG(mac, ®s, 30); + + RESTORE_RF_REG(mac, ®s, 43); + RESTORE_RF_REG(mac, ®s, 7a); + + RF_FILT_SETBITS(mac, 0x52, 0xf, regs.rf_52); + + CSR_WRITE_2(sc, BWI_BPHY_CTRL, bphy_ctrl); + } + RESTORE_PHY_REG(mac, ®s, 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)) |