diff options
author | Marcus Glocker <mglocker@cvs.openbsd.org> | 2007-02-23 19:44:38 +0000 |
---|---|---|
committer | Marcus Glocker <mglocker@cvs.openbsd.org> | 2007-02-23 19:44:38 +0000 |
commit | 1928a52e3abf7e784e5ece98fb453f65391e5080 (patch) | |
tree | 9b26b9b78517378d18e7ced333182bdf6e0039eb /sys/dev/ic | |
parent | 511a59a5d5ab3884513bde966075484634776ce8 (diff) |
Add bcw_phy_xmitpower().
Diffstat (limited to 'sys/dev/ic')
-rw-r--r-- | sys/dev/ic/bcw.c | 210 | ||||
-rw-r--r-- | sys/dev/ic/bcwvar.h | 5 |
2 files changed, 207 insertions, 8 deletions
diff --git a/sys/dev/ic/bcw.c b/sys/dev/ic/bcw.c index d211613381b..66201456b8c 100644 --- a/sys/dev/ic/bcw.c +++ b/sys/dev/ic/bcw.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bcw.c,v 1.50 2007/02/23 14:27:00 mglocker Exp $ */ +/* $OpenBSD: bcw.c,v 1.51 2007/02/23 19:44:37 mglocker Exp $ */ /* * Copyright (c) 2006 Jon Simola <jsimola@gmail.com> @@ -73,6 +73,8 @@ int bcw_radio_read16(struct bcw_softc *, uint16_t); void bcw_phy_write16(struct bcw_softc *, uint16_t, uint16_t); int bcw_phy_read16(struct bcw_softc *, uint16_t); void bcw_ram_write(struct bcw_softc *, uint16_t, uint32_t); +int bcw_lv(int, int, int); + void bcw_dummy_transmission(struct bcw_softc *); struct bcw_lopair * bcw_get_lopair(struct bcw_softc *sc, uint16_t radio_atten, @@ -131,6 +133,8 @@ void bcw_phy_agcsetup(struct bcw_softc *); void bcw_phy_init_pctl(struct bcw_softc *); void bcw_phy_init_noisescaletbl(struct bcw_softc *); void bcw_phy_set_baseband_atten(struct bcw_softc *, uint16_t); +int8_t bcw_phy_estimate_powerout(struct bcw_softc *, int8_t tssi); +void bcw_phy_xmitpower(struct bcw_softc *); uint16_t bcw_phy_lo_b_r15_loop(struct bcw_softc *); void bcw_phy_lo_b_measure(struct bcw_softc *); void bcw_phy_lo_g_measure(struct bcw_softc *); @@ -138,6 +142,7 @@ void bcw_phy_lo_g_measure_txctl2(struct bcw_softc *); uint32_t bcw_phy_lo_g_singledeviation(struct bcw_softc *, uint16_t); uint16_t bcw_phy_lo_g_deviation_subval(struct bcw_softc *, uint16_t); void bcw_phy_lo_adjust(struct bcw_softc *, int fixed); +void bcw_phy_lo_mark_current_used(struct bcw_softc *); struct bcw_lopair * bcw_phy_find_lopair(struct bcw_softc *, uint16_t, uint16_t, uint16_t); @@ -580,6 +585,17 @@ bcw_ram_write(struct bcw_softc *sc, uint16_t offset, uint32_t val) BCW_WRITE(sc, BCW_MMIO_RAM_DATA, val); } +int +bcw_lv(int number, int min, int max) +{ + if (number < min) + return (min); + else if (number > max) + return (max); + else + return (number); +} + void bcw_dummy_transmission(struct bcw_softc *sc) { @@ -3182,10 +3198,10 @@ bcw_phy_initg(struct bcw_softc *sc) bcw_radio_calc_nrssi_threshold(sc); } else if (sc->sc_phy_connected) { if (sc->sc_radio_nrssi[0] == -1000) { - /* XXX assert() ? */ + /* XXX assert() */ bcw_radio_calc_nrssi_slope(sc); } else { - /* XXX assert() ? */ + /* XXX assert() */ bcw_radio_calc_nrssi_threshold(sc); } } @@ -4097,7 +4113,7 @@ bcw_phy_init_pctl(struct bcw_softc *sc) uint16_t saved_batt = 0, saved_ratt = 0, saved_txctl1 = 0; int must_reset_txpower = 0; - /* XXX assert() ? */ + /* XXX assert() */ /* TODO board_vendor, board_type */ BCW_WRITE16(sc, 0x03e6, BCW_READ16(sc, 0x03e6) & 0xffdf); @@ -4193,6 +4209,177 @@ bcw_phy_set_baseband_atten(struct bcw_softc *sc, bcw_phy_write16(sc, 0x0060, val); } +int8_t +bcw_phy_estimate_powerout(struct bcw_softc *sc, int8_t tssi) +{ + int8_t dbm = 0; + int32_t tmp; + + tmp = sc->sc_phy_idle_tssi; + tmp += tssi; + tmp -= sc->sc_phy_savedpctlreg; + + switch (sc->sc_phy_type) { + case BCW_PHY_TYPEA: + tmp += 0x80; + tmp = bcw_lv(tmp, 0x00, 0xff); + //dbm = sc->sc_phy_tssi2dbm[tmp]; /* XXX */ + break; + case BCW_PHY_TYPEB: + case BCW_PHY_TYPEG: + tmp = bcw_lv(tmp, 0x00, 0x3f); + //dbm = sc->sc_phy_tssi2dbm[tmp]; /* XXX "/ + break; + default: + /* XXX assert() */ + break; + } + + return (dbm); +} + +void +bcw_phy_xmitpower(struct bcw_softc *sc) +{ + if (sc->sc_phy_savedpctlreg == 0xffff) + return; + if (1) /* XXX board_vendor, board_type */ + return; + + switch (sc->sc_phy_type) { + case BCW_PHY_TYPEA: + /* nohting todo for A PHYs yet */ + break; + case BCW_PHY_TYPEB: + case BCW_PHY_TYPEG: { + uint16_t tmp; + uint16_t txpower; + int8_t v0, v1, v2, v3; + int8_t average; + uint8_t max_pwr; + int16_t desired_pwr, estimated_pwr, pwr_adjust; + int16_t radio_att_delta, baseband_att_delta; + int16_t radio_attenuation, baseband_attenuation; + + tmp = bcw_shm_read16(sc, BCW_SHM_CONTROL_SHARED, 0x0058); + v0 = (int8_t)(tmp & 0x00ff); + v1 = (int8_t)((tmp & 0xff00) >> 8); + tmp = bcw_shm_read16(sc, BCW_SHM_CONTROL_SHARED, 0x005a); + v2 = (int8_t)(tmp & 0x00ff); + v3 = (int8_t)((tmp & 0xff00) >> 8); + tmp = 0; + + if (v0 == 0x7f || v1 == 0x7f || v2 == 0x7f || v3 == 0x07) { + tmp = bcw_shm_read16(sc, BCW_SHM_CONTROL_SHARED, + 0x0070); + v0 = (int8_t)(tmp & 0x00ff); + v1 = (int8_t)((tmp & 0xff00) >> 8); + tmp = bcw_shm_read16(sc, BCW_SHM_CONTROL_SHARED, + 0x0072); + + v2 = (int8_t)(tmp & 0x00ff); + v3 = (int8_t)((tmp & 0xff00) >> 8); + if (v0 == 0x7f || v1 == 0x7f || v2 == 0x7f || + v3 == 0x7f) + return; + v0 = (v0 + 0x20) & 0x3f; + v1 = (v1 + 0x20) & 0x3f; + v2 = (v2 + 0x20) & 0x3f; + v3 = (v3 + 0x20) & 0x3f; + tmp = 1; + } + bcw_radio_clear_tssi(sc); + + average = (v0 + v1 + v2 + v3 + 2) / 4; + + if (tmp && (bcw_shm_read16(sc, BCW_SHM_CONTROL_SHARED, 0x005e) & + 0x8)) + average -= 13; + + bcw_phy_estimate_powerout(sc, average); + + if ((sc->sc_boardflags & BCW_BF_PACTRL) && + (sc->sc_phy_type == BCW_PHY_TYPEG)) + max_pwr -= 0x3; + + desired_pwr = bcw_lv(sc->sc_radio_txpower_desired, 0, max_pwr); + /* check if we need to adjust the current power */ + pwr_adjust = desired_pwr - estimated_pwr; + radio_att_delta = -(pwr_adjust + 7) >> 3; + baseband_att_delta = -(pwr_adjust >> 1) - (4 * radio_att_delta); + if ((radio_att_delta == 0) && (baseband_att_delta == 0)) { + bcw_phy_lo_mark_current_used(sc); + return; + } + + /* calculate the new attenuation values */ + baseband_attenuation = sc->sc_radio_baseband_atten; + baseband_attenuation += baseband_att_delta; + radio_attenuation = sc->sc_radio_radio_atten; + radio_attenuation += radio_att_delta; + + if (radio_attenuation < 0) { + baseband_attenuation -= (4 * -radio_attenuation); + radio_attenuation = 0; + } else if (radio_attenuation > 9) { + baseband_attenuation += (4 * (radio_attenuation - 9)); + radio_attenuation = 9; + } else { + while (baseband_attenuation < 0 && + radio_attenuation > 0) { + baseband_attenuation += 4; + radio_attenuation--; + } + while (baseband_attenuation > 11 && + radio_attenuation < 9) { + baseband_attenuation -= 4; + radio_attenuation++; + } + } + baseband_attenuation = bcw_lv(baseband_attenuation, 0, 11); + + txpower = sc->sc_radio_txctl1; + if ((sc->sc_radio_ver == 0x02050) && (sc->sc_radio_rev == 2)) { + if (radio_attenuation <= 1) { + if (txpower == 0) { + txpower = 3; + radio_attenuation += 2; + baseband_attenuation += 2; + } else if (sc->sc_boardflags & BCW_BF_PACTRL) { + baseband_attenuation += 4 * + (radio_attenuation - 2); + radio_attenuation = 2; + } + } else if (radio_attenuation > 4 && txpower != 0) { + txpower = 0; + if (baseband_attenuation < 3) { + radio_attenuation -= 3; + baseband_attenuation += 2; + } else { + radio_attenuation -= 2; + baseband_attenuation -= 2; + } + } + } + sc->sc_radio_txctl1 = txpower; + baseband_attenuation = bcw_lv(baseband_attenuation, 0, 11); + radio_attenuation = bcw_lv(radio_attenuation, 0, 9); + + /* TODO bcw_phy_lock() */ + /* TODO bcw_radio_lock() */ + bcw_radio_set_txpower_bg(sc, baseband_attenuation, + radio_attenuation, txpower); + bcw_phy_lo_mark_current_used(sc); + /* TODO bcw_radio_unlock() */ + /* TODO bcw_phy_unlock() */ + break; + } + default: + /* XXX assert() */ + break; + } +} + uint16_t bcw_phy_lo_b_r15_loop(struct bcw_softc *sc) { @@ -4590,6 +4777,15 @@ bcw_phy_lo_adjust(struct bcw_softc *sc, int fixed) bcw_lowrite(sc, pair); } +void +bcw_phy_lo_mark_current_used(struct bcw_softc *sc) +{ + struct bcw_lopair *pair; + + pair = bcw_phy_current_lopair(sc); + pair->used = 1; +} + struct bcw_lopair * bcw_phy_find_lopair(struct bcw_softc *sc, uint16_t baseband_atten, uint16_t radio_atten, uint16_t tx) @@ -4802,7 +4998,7 @@ bcw_radio_calc_nrssi_threshold(struct bcw_softc *sc) } break; default: - /* XXX assert() ?*/ + /* XXX assert() */ return; } } @@ -5403,7 +5599,7 @@ bcw_radio_init2060(struct bcw_softc *sc) error = bcw_radio_channel(sc, BCW_RADIO_DEFAULT_CHANNEL_A, 0); - /* XXX assert(error == 0) ? */ + /* XXX assert() */ delay(1000); } @@ -5473,7 +5669,7 @@ bcw_radio_channel(struct bcw_softc *sc, uint8_t channel, int spw) bcw_radio_set_tx_iq(sc); - /* TODO bcw_radio_phy_xmitpower() */ + bcw_phy_xmitpower(sc); } else { if (spw) bcw_radio_spw(sc, channel); diff --git a/sys/dev/ic/bcwvar.h b/sys/dev/ic/bcwvar.h index 632a36e22ba..1fea0d8079e 100644 --- a/sys/dev/ic/bcwvar.h +++ b/sys/dev/ic/bcwvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bcwvar.h,v 1.20 2007/02/23 10:40:54 mglocker Exp $ */ +/* $OpenBSD: bcwvar.h,v 1.21 2007/02/23 19:44:37 mglocker Exp $ */ /* * Copyright (c) 2006 Jon Simola <jsimola@gmail.com> @@ -240,6 +240,8 @@ struct bcw_softc { uint16_t sc_phy_savedpctlreg; uint16_t sc_phy_minlowsig[2]; uint16_t sc_phy_minlowsigpos[2]; + int8_t sc_phy_idle_tssi; + const int8_t sc_phy_tssi2dbm; // uint16_t sc_corerev; uint32_t sc_radio_mnf; uint16_t sc_radio_rev; @@ -253,6 +255,7 @@ struct bcw_softc { int32_t sc_radio_nrssislope; uint16_t sc_radio_txpwr_offset; uint16_t sc_radio_lofcal; + uint16_t sc_radio_txpower_desired; uint32_t sc_phyinfo; uint16_t sc_numcores; uint16_t sc_havecommon; |