summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/dev/ic/ar5212.c119
-rw-r--r--sys/dev/ic/ar5212reg.h10
-rw-r--r--sys/dev/ic/ar5xxx.c307
-rw-r--r--sys/dev/ic/ar5xxx.h140
4 files changed, 486 insertions, 90 deletions
diff --git a/sys/dev/ic/ar5212.c b/sys/dev/ic/ar5212.c
index a8a0e9da7d5..b7dfd0d586d 100644
--- a/sys/dev/ic/ar5212.c
+++ b/sys/dev/ic/ar5212.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ar5212.c,v 1.6 2005/03/13 18:32:21 reyk Exp $ */
+/* $OpenBSD: ar5212.c,v 1.7 2005/03/18 20:46:32 reyk Exp $ */
/*
* Copyright (c) 2004, 2005 Reyk Floeter <reyk@vantronix.net>
@@ -397,6 +397,8 @@ ar5k_ar5212_getRateTable(hal, mode)
case HAL_MODE_11G:
case HAL_MODE_PUREG:
return (&hal->ah_rt_11g);
+ case HAL_MODE_XR:
+ return (&hal->ah_rt_xr);
default:
return (NULL);
}
@@ -424,9 +426,27 @@ ar5k_ar5212_reset(hal, op_mode, channel, change_channel, status)
{
struct ar5k_eeprom_info *ee = &hal->ah_capabilities.cap_eeprom;
u_int8_t mac[IEEE80211_ADDR_LEN];
- u_int32_t data;
+ u_int32_t data, s_seq, s_ant, s_led[3];
u_int i, phy, mode, freq, ee_mode, ant[2];
- HAL_BOOL ar5112;
+ const HAL_RATE_TABLE *rt;
+
+ /*
+ * Save some registers before a reset
+ */
+ if (change_channel == AH_TRUE) {
+ s_seq = AR5K_REG_READ(AR5K_AR5212_DCU_SEQNUM(0));
+ s_ant = AR5K_REG_READ(AR5K_AR5212_DEFAULT_ANTENNA);
+ } else {
+ s_seq = 0;
+ s_ant = 1;
+ }
+
+ s_led[0] = AR5K_REG_READ(AR5K_AR5212_PCICFG) &
+ AR5K_AR5212_PCICFG_LEDSTATE;
+ s_led[1] = AR5K_REG_READ(AR5K_AR5212_GPIOCR);
+ s_led[2] = AR5K_REG_READ(AR5K_AR5212_GPIODO);
+
+ ar5k_ar5212_getRfGain(hal);
if (ar5k_ar5212_nic_wakeup(hal, channel->c_channel_flags) == AH_FALSE)
return (AH_FALSE);
@@ -436,8 +456,6 @@ ar5k_ar5212_reset(hal, op_mode, channel, change_channel, status)
*/
hal->ah_op_mode = op_mode;
- ar5112 = hal->ah_radio >= AR5K_AR5112 ? AH_TRUE : AH_FALSE;
-
if (channel->c_channel_flags & IEEE80211_CHAN_A) {
mode = AR5K_INI_VAL_11A;
freq = AR5K_INI_RFGAIN_5GHZ;
@@ -479,7 +497,7 @@ ar5k_ar5212_reset(hal, op_mode, channel, change_channel, status)
ar5212_ini[i].ini_register <= AR5K_AR5212_PCU_MAX)
continue;
- if (ar5112 == AH_TRUE) {
+ if (hal->ah_radio == AR5K_AR5112) {
if (!(ar5212_mode[i].mode_flags & AR5K_INI_FLAG_5112))
continue;
} else {
@@ -498,10 +516,10 @@ ar5k_ar5212_reset(hal, op_mode, channel, change_channel, status)
if (ar5212_mode[i].mode_flags == AR5K_INI_FLAG_511X)
phy = AR5K_INI_PHY_511X;
else if (ar5212_mode[i].mode_flags & AR5K_INI_FLAG_5111 &&
- ar5112 == AH_FALSE)
+ hal->ah_radio == AR5K_AR5111)
phy = AR5K_INI_PHY_5111;
else if (ar5212_mode[i].mode_flags & AR5K_INI_FLAG_5112 &&
- ar5112 == AH_TRUE)
+ hal->ah_radio == AR5K_AR5112)
phy = AR5K_INI_PHY_5112;
else
continue;
@@ -511,9 +529,39 @@ ar5k_ar5212_reset(hal, op_mode, channel, change_channel, status)
}
/*
+ * Set rate duration table
+ */
+ rt = ar5k_ar5212_getRateTable(hal,
+ channel->c_channel_flags & IEEE80211_CHAN_TURBO ?
+ HAL_MODE_TURBO : HAL_MODE_XR);
+
+ for (i = 0; i < rt->rt_rate_count; i++) {
+ AR5K_REG_WRITE(AR5K_AR5212_RATE_DUR(rt->rt_info[i].r_rate_code),
+ ath_hal_computetxtime(hal, rt, 14,
+ rt->rt_info[i].r_control_rate, AH_FALSE));
+ }
+
+ if (!(channel->c_channel_flags & IEEE80211_CHAN_TURBO)) {
+ rt = ar5k_ar5212_getRateTable(hal, HAL_MODE_11B);
+ for (i = 0; i < rt->rt_rate_count; i++) {
+ data = AR5K_AR5212_RATE_DUR(rt->rt_info[i].r_rate_code);
+ AR5K_REG_WRITE(data,
+ ath_hal_computetxtime(hal, rt, 14,
+ rt->rt_info[i].r_control_rate, AH_FALSE));
+ if (rt->rt_info[i].r_short_preamble) {
+ AR5K_REG_WRITE(data +
+ (rt->rt_info[i].r_short_preamble << 2),
+ ath_hal_computetxtime(hal, rt, 14,
+ rt->rt_info[i].r_control_rate, AH_FALSE));
+ }
+ }
+ }
+
+ /*
* Write initial RF gain settings
*/
- phy = ar5112 == AH_TRUE ? AR5K_INI_PHY_5112 : AR5K_INI_PHY_5111;
+ phy = hal->ah_radio == AR5K_AR5112 ?
+ AR5K_INI_PHY_5112 : AR5K_INI_PHY_5111;
if (ar5k_rfgain(hal, phy, freq) == AH_FALSE)
return (AH_FALSE);
@@ -582,7 +630,7 @@ ar5k_ar5212_reset(hal, op_mode, channel, change_channel, status)
hal->ah_antenna[ee_mode][ant[1]]);
/* Commit values from EEPROM */
- if (ar5112 == AH_FALSE)
+ if (hal->ah_radio == AR5K_AR5112)
AR5K_REG_WRITE_BITS(AR5K_AR5212_PHY_FC,
AR5K_AR5212_PHY_FC_TX_CLIP, ee->ee_tx_clip);
@@ -620,7 +668,18 @@ ar5k_ar5212_reset(hal, op_mode, channel, change_channel, status)
ee->ee_margin_tx_rx[ee_mode]);
}
- /* Misc */
+ /*
+ * Restore saved values
+ */
+ AR5K_REG_WRITE(AR5K_AR5212_DCU_SEQNUM(0), s_seq);
+ AR5K_REG_WRITE(AR5K_AR5212_DEFAULT_ANTENNA, s_ant);
+ AR5K_REG_ENABLE_BITS(AR5K_AR5212_PCICFG, s_led[0]);
+ AR5K_REG_WRITE(AR5K_AR5212_GPIOCR, s_led[1]);
+ AR5K_REG_WRITE(AR5K_AR5212_GPIODO, s_led[2]);
+
+ /*
+ * Misc
+ */
bcopy(etherbroadcastaddr, mac, IEEE80211_ADDR_LEN);
ar5k_ar5212_writeAssocid(hal, mac, 0, 0);
ar5k_ar5212_setPCUConfig(hal);
@@ -2021,7 +2080,40 @@ HAL_RFGAIN
ar5k_ar5212_getRfGain(hal)
struct ath_hal *hal;
{
- return (HAL_RFGAIN_INACTIVE);
+ u_int32_t data, type;
+
+ if (!hal->ah_gain.g_active)
+ return (HAL_RFGAIN_INACTIVE);
+
+ if (hal->ah_rf_gain != HAL_RFGAIN_READ_REQUESTED)
+ goto done;
+
+ data = AR5K_REG_READ(AR5K_AR5212_PHY_PAPD_PROBE);
+
+ if (!(data & AR5K_AR5212_PHY_PAPD_PROBE_TX_NEXT)) {
+ hal->ah_gain.g_current =
+ data >> AR5K_AR5212_PHY_PAPD_PROBE_GAINF_S;
+ type = AR5K_REG_MS(data, AR5K_AR5212_PHY_PAPD_PROBE_TYPE);
+
+ if (type == AR5K_AR5212_PHY_PAPD_PROBE_TYPE_CCK)
+ hal->ah_gain.g_current += AR5K_GAIN_CCK_PROBE_CORR;
+
+ if (hal->ah_radio == AR5K_AR5112) {
+ ar5k_rfregs_gainf_corr(hal);
+ hal->ah_gain.g_current =
+ hal->ah_gain.g_current >= hal->ah_gain.g_f_corr ?
+ (hal->ah_gain.g_current - hal->ah_gain.g_f_corr) :
+ 0;
+ }
+
+ if (ar5k_rfregs_gain_readback(hal) &&
+ AR5K_GAIN_CHECK_ADJUST(&hal->ah_gain) &&
+ ar5k_rfregs_gain_adjust(hal))
+ hal->ah_rf_gain = HAL_RFGAIN_NEED_CHANGE;
+ }
+
+ done:
+ return (hal->ah_rf_gain);
}
HAL_BOOL
@@ -2685,7 +2777,8 @@ ar5k_ar5212_get_capabilities(hal)
hal->ah_capabilities.cap_range.range_5ghz_max = 6100;
/* Set supported modes */
- hal->ah_capabilities.cap_mode = HAL_MODE_11A | HAL_MODE_TURBO;
+ hal->ah_capabilities.cap_mode =
+ HAL_MODE_11A | HAL_MODE_TURBO | HAL_MODE_XR;
}
/* This chip will support 802.11b if the 2GHz radio is connected */
diff --git a/sys/dev/ic/ar5212reg.h b/sys/dev/ic/ar5212reg.h
index bf3e76bc861..89cca021405 100644
--- a/sys/dev/ic/ar5212reg.h
+++ b/sys/dev/ic/ar5212reg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ar5212reg.h,v 1.2 2005/03/10 08:30:56 reyk Exp $ */
+/* $OpenBSD: ar5212reg.h,v 1.3 2005/03/18 20:46:32 reyk Exp $ */
/*
* Copyright (c) 2004, 2005 Reyk Floeter <reyk@vantronix.net>
@@ -611,6 +611,9 @@ typedef enum {
#define AR5K_AR5212_PCICFG_LEDBLINK 0x00700000
#define AR5K_AR5212_PCICFG_LEDBLINK_S 20
#define AR5K_AR5212_PCICFG_LEDSLOW 0x00800000
+#define AR5K_AR5212_PCICFG_LEDSTATE \
+ (AR5K_AR5212_PCICFG_LED | AR5K_AR5212_PCICFG_LEDMODE | \
+ AR5K_AR5212_PCICFG_LEDBLINK | AR5K_AR5212_PCICFG_LEDSLOW)
/*
* "General Purpose Input/Output" (GPIO) control register
@@ -1123,6 +1126,11 @@ typedef enum {
#define AR5K_AR5212_PHY_PAPD_PROBE_TXPOWER 0x00007e00
#define AR5K_AR5212_PHY_PAPD_PROBE_TXPOWER_S 9
#define AR5K_AR5212_PHY_PAPD_PROBE_TX_NEXT 0x00008000
+#define AR5K_AR5212_PHY_PAPD_PROBE_TYPE 0x01800000
+#define AR5K_AR5212_PHY_PAPD_PROBE_TYPE_S 23
+#define AR5K_AR5212_PHY_PAPD_PROBE_TYPE_OFDM 0
+#define AR5K_AR5212_PHY_PAPD_PROBE_TYPE_XR 1
+#define AR5K_AR5212_PHY_PAPD_PROBE_TYPE_CCK 2
#define AR5K_AR5212_PHY_PAPD_PROBE_GAINF 0xfe000000
#define AR5K_AR5212_PHY_PAPD_PROBE_GAINF_S 25
diff --git a/sys/dev/ic/ar5xxx.c b/sys/dev/ic/ar5xxx.c
index 1c3ccfd023e..6532bed0be6 100644
--- a/sys/dev/ic/ar5xxx.c
+++ b/sys/dev/ic/ar5xxx.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ar5xxx.c,v 1.17 2005/03/10 08:30:56 reyk Exp $ */
+/* $OpenBSD: ar5xxx.c,v 1.18 2005/03/18 20:46:32 reyk Exp $ */
/*
* Copyright (c) 2004, 2005 Reyk Floeter <reyk@vantronix.net>
@@ -29,12 +29,6 @@ extern ar5k_attach_t ar5k_ar5210_attach;
extern ar5k_attach_t ar5k_ar5211_attach;
extern ar5k_attach_t ar5k_ar5212_attach;
-static const struct
-ieee80211_regchannel ar5k_5ghz_channels[] = IEEE80211_CHANNELS_5GHZ;
-
-static const struct
-ieee80211_regchannel ar5k_2ghz_channels[] = IEEE80211_CHANNELS_2GHZ;
-
static const struct {
u_int16_t vendor;
u_int16_t device;
@@ -86,18 +80,29 @@ HAL_BOOL ar5k_check_channel(struct ath_hal *, u_int16_t, u_int flags);
HAL_BOOL ar5k_ar5111_rfregs(struct ath_hal *, HAL_CHANNEL *, u_int);
HAL_BOOL ar5k_ar5112_rfregs(struct ath_hal *, HAL_CHANNEL *, u_int);
-int ar5k_rfregs_set(u_int32_t *, u_int32_t, u_int32_t, u_int32_t,
- u_int32_t, u_int32_t);
+int ar5k_rfregs_op(u_int32_t *, u_int32_t, u_int32_t, u_int32_t,
+ u_int32_t, u_int32_t, HAL_BOOL);
+
+/*
+ * Supported channels
+ */
+static const struct
+ieee80211_regchannel ar5k_5ghz_channels[] = IEEE80211_CHANNELS_5GHZ;
+static const struct
+ieee80211_regchannel ar5k_2ghz_channels[] = IEEE80211_CHANNELS_2GHZ;
+
+/*
+ * Initial gain optimization values
+ */
+static const struct ar5k_gain_opt ar5111_gain_opt = AR5K_AR5111_GAIN_OPT;
+static const struct ar5k_gain_opt ar5112_gain_opt = AR5K_AR5112_GAIN_OPT;
/*
* Initial register for the radio chipsets
*/
-static const struct ar5k_ini_rf ar5111_rf[] =
- AR5K_AR5111_INI_RF;
-static const struct ar5k_ini_rf ar5112_rf[] =
- AR5K_AR5112_INI_RF;
-static const struct ar5k_ini_rfgain ar5k_rfg[] =
- AR5K_INI_RFGAIN;
+static const struct ar5k_ini_rf ar5111_rf[] = AR5K_AR5111_INI_RF;
+static const struct ar5k_ini_rf ar5112_rf[] = AR5K_AR5112_INI_RF;
+static const struct ar5k_ini_rfgain ar5k_rfg[] = AR5K_INI_RFGAIN;
/*
* Enable to overwrite the country code (use "00" for debug)
@@ -144,6 +149,7 @@ ath_hal_attach(device, sc, st, sh, status)
HAL_RATE_TABLE rt_11b = AR5K_RATES_11B;
HAL_RATE_TABLE rt_11g = AR5K_RATES_11G;
HAL_RATE_TABLE rt_turbo = AR5K_RATES_TURBO;
+ HAL_RATE_TABLE rt_xr = AR5K_RATES_XR;
u_int16_t regdomain;
struct ath_hal *hal = NULL;
ar5k_attach_t *attach = NULL;
@@ -256,6 +262,25 @@ ath_hal_attach(device, sc, st, sh, status)
ar5k_rt_copy(&hal->ah_rt_11g, &rt_11g);
if (hal->ah_capabilities.cap_mode & HAL_MODE_TURBO)
ar5k_rt_copy(&hal->ah_rt_turbo, &rt_turbo);
+ if (hal->ah_capabilities.cap_mode & HAL_MODE_XR)
+ ar5k_rt_copy(&hal->ah_rt_xr, &rt_xr);
+
+ /* Initialize the gain optimization values */
+ if (hal->ah_radio == AR5K_AR5111) {
+ hal->ah_gain.g_step_idx = ar5111_gain_opt.go_default;
+ hal->ah_gain.g_step =
+ &ar5111_gain_opt.go_step[hal->ah_gain.g_step_idx];
+ hal->ah_gain.g_low = 20;
+ hal->ah_gain.g_high = 35;
+ hal->ah_gain.g_active = 1;
+ } else if (hal->ah_radio == AR5K_AR5112) {
+ hal->ah_gain.g_step_idx = ar5112_gain_opt.go_default;
+ hal->ah_gain.g_step =
+ &ar5111_gain_opt.go_step[hal->ah_gain.g_step_idx];
+ hal->ah_gain.g_low = 20;
+ hal->ah_gain.g_high = 85;
+ hal->ah_gain.g_active = 1;
+ }
*status = HAL_OK;
@@ -1273,34 +1298,174 @@ ar5k_ar5112_channel(hal, channel)
}
int
-ar5k_rfregs_set(rf, offset, reg, bits, first, col)
+ar5k_rfregs_op(rf, offset, reg, bits, first, col, set)
u_int32_t *rf;
u_int32_t offset, reg, bits, first, col;
+ HAL_BOOL set;
{
- u_int32_t tmp, mask, entry, last;
- int32_t position, left;
+ u_int32_t mask, entry, last, data, shift, position;
+ int32_t left;
int i;
if (!(col <= 3 && bits <= 32 && first + bits <= 319)) {
AR5K_PRINTF("invalid values at offset %u\n", offset);
- return (-1);
+ return (0);
}
- tmp = ar5k_bitswap(reg, bits);
entry = ((first - 1) / 8) + offset;
position = (first - 1) % 8;
- for (i = 0, left = bits; left > 0; position = 0, entry++, i++) {
+ if (set == AH_TRUE)
+ data = ar5k_bitswap(reg, bits);
+
+ for (i = shift = 0, left = bits; left > 0; position = 0, entry++, i++) {
last = (position + left > 8) ? 8 : position + left;
mask = (((1 << last) - 1) ^ ((1 << position) - 1)) <<
(col * 8);
- rf[entry] &= ~mask;
- rf[entry] |= ((tmp << position) << (col * 8)) & mask;
+
+ if (set == AH_TRUE) {
+ rf[entry] &= ~mask;
+ rf[entry] |= ((data << position) << (col * 8)) & mask;
+ data >>= (8 - position);
+ } else {
+ data = (((rf[entry] & mask) >> (col * 8)) >>
+ position) << shift;
+ shift += last - position;
+ }
+
left -= 8 - position;
- tmp >>= (8 - position);
}
- return (i);
+ data = set == AH_TRUE ? 1 : ar5k_bitswap(data, bits);
+
+ return (data);
+}
+
+u_int32_t
+ar5k_rfregs_gainf_corr(hal)
+ struct ath_hal *hal;
+{
+ u_int32_t mix, step;
+
+ hal->ah_gain.g_f_corr = 0;
+
+ if (ar5k_rfregs_op(NULL, hal->ah_offset[7], 0, 1, 36, 0, AH_FALSE) != 1)
+ return (0);
+
+ step = ar5k_rfregs_op(NULL, hal->ah_offset[7], 0, 4, 32, 0, AH_FALSE);
+ mix = hal->ah_gain.g_step->gos_param[0];
+
+ switch (mix) {
+ case 3:
+ hal->ah_gain.g_f_corr = step * 2;
+ break;
+ case 2:
+ hal->ah_gain.g_f_corr = (step - 5) * 2;
+ break;
+ case 1:
+ hal->ah_gain.g_f_corr = step;
+ break;
+ default:
+ hal->ah_gain.g_f_corr = 0;
+ break;
+ }
+
+ return (hal->ah_gain.g_f_corr);
+}
+
+HAL_BOOL
+ar5k_rfregs_gain_readback(hal)
+ struct ath_hal *hal;
+{
+ u_int32_t step, mix, level[4];
+
+ if (hal->ah_radio == AR5K_AR5111) {
+ step = ar5k_rfregs_op(NULL, hal->ah_offset[7],
+ 0, 6, 37, 0, AH_FALSE);
+ level[0] = 0;
+ level[1] = (step == 0x3f) ? 0x32 : step + 4;
+ level[2] = (step != 0x3f) ? 0x40 : level[0];
+ level[3] = level[2] + 0x32;
+
+ hal->ah_gain.g_high = level[3] -
+ (step == 0x3f ? AR5K_GAIN_DYN_ADJUST_HI_MARGIN : -5);
+ hal->ah_gain.g_low = level[0] +
+ (step == 0x3f ? AR5K_GAIN_DYN_ADJUST_LO_MARGIN : 0);
+ } else {
+ mix = ar5k_rfregs_op(NULL, hal->ah_offset[7],
+ 0, 1, 36, 0, AH_FALSE);
+ level[0] = level[2] = 0;
+
+ if (mix == 1) {
+ level[1] = level[3] = 83;
+ } else {
+ level[1] = level[3] = 107;
+ hal->ah_gain.g_high = 55;
+ }
+ }
+
+ return ((hal->ah_gain.g_current >= level[0] &&
+ hal->ah_gain.g_current <= level[1]) ||
+ (hal->ah_gain.g_current >= level[2] &&
+ hal->ah_gain.g_current <= level[3]));
+}
+
+int32_t
+ar5k_rfregs_gain_adjust(hal)
+ struct ath_hal *hal;
+{
+ int ret = 0;
+ const struct ar5k_gain_opt *go;
+
+ go = hal->ah_radio == AR5K_AR5111 ?
+ &ar5111_gain_opt : &ar5112_gain_opt;
+
+ hal->ah_gain.g_step = &go->go_step[hal->ah_gain.g_step_idx];
+
+ if (hal->ah_gain.g_current >= hal->ah_gain.g_high) {
+ if (hal->ah_gain.g_step_idx == 0)
+ return (-1);
+ for (hal->ah_gain.g_target = hal->ah_gain.g_current;
+ hal->ah_gain.g_target >= hal->ah_gain.g_high &&
+ hal->ah_gain.g_step_idx > 0;
+ hal->ah_gain.g_step =
+ &go->go_step[hal->ah_gain.g_step_idx]) {
+ hal->ah_gain.g_target -= 2 *
+ (go->go_step[--(hal->ah_gain.g_step_idx)].gos_gain -
+ hal->ah_gain.g_step->gos_gain);
+ }
+
+ ret = 1;
+ goto done;
+ }
+
+ if (hal->ah_gain.g_current <= hal->ah_gain.g_low) {
+ if (hal->ah_gain.g_step_idx == (go->go_steps_count - 1))
+ return (-2);
+ for (hal->ah_gain.g_target = hal->ah_gain.g_current;
+ hal->ah_gain.g_target <= hal->ah_gain.g_low &&
+ hal->ah_gain.g_step_idx < (go->go_steps_count - 1);
+ hal->ah_gain.g_step =
+ &go->go_step[hal->ah_gain.g_step_idx]) {
+ hal->ah_gain.g_target -= 2 *
+ (go->go_step[++(hal->ah_gain.g_step_idx)].gos_gain -
+ hal->ah_gain.g_step->gos_gain);
+ }
+
+ ret = 2;
+ goto done;
+ }
+
+ done:
+#ifdef AR5K_DEBUG
+ AR5K_PRINTF("ret %d, gain step %u, current gain %u, target gain %u\n",
+ g,
+ hal->ah_gain.g_step_idx,
+ hal->ah_gain.g_current,
+ hal->ah_gain.g_target);
+#endif
+
+ return (ret);
}
HAL_BOOL
@@ -1309,12 +1474,20 @@ ar5k_rfregs(hal, channel, mode)
HAL_CHANNEL *channel;
u_int mode;
{
+ HAL_BOOL ret;
+
if (hal->ah_radio < AR5K_AR5111)
return (AH_FALSE);
- else if (hal->ah_radio < AR5K_AR5112)
- return (ar5k_ar5111_rfregs(hal, channel, mode));
- return (ar5k_ar5112_rfregs(hal, channel, mode));
+ if (hal->ah_radio == AR5K_AR5111)
+ ret = ar5k_ar5111_rfregs(hal, channel, mode);
+ else
+ ret = ar5k_ar5112_rfregs(hal, channel, mode);
+
+ if (ret == AH_TRUE)
+ hal->ah_rf_gain = HAL_RFGAIN_INACTIVE;
+
+ return (ret);
}
HAL_BOOL
@@ -1327,7 +1500,7 @@ ar5k_ar5111_rfregs(hal, channel, mode)
const u_int rf_size = AR5K_ELEMENTS(ar5111_rf);
u_int32_t rf[rf_size];
int i, obdb = -1, bank = -1;
- u_int32_t ee_mode, offset[AR5K_AR5111_INI_RF_MAX_BANKS];
+ u_int32_t ee_mode;
AR5K_ASSERT_ENTRY(mode, AR5K_INI_VAL_MAX);
@@ -1341,7 +1514,7 @@ ar5k_ar5111_rfregs(hal, channel, mode)
if (bank != ar5111_rf[i].rf_bank) {
bank = ar5111_rf[i].rf_bank;
- offset[bank] = i;
+ hal->ah_offset[bank] = i;
}
rf[i] = ar5111_rf[i].rf_value[mode];
@@ -1354,12 +1527,12 @@ ar5k_ar5111_rfregs(hal, channel, mode)
ee_mode = AR5K_EEPROM_MODE_11G;
obdb = 0;
- if (ar5k_rfregs_set(rf, offset[0],
- ee->ee_ob[ee_mode][obdb], 3, 119, 0) < 0)
+ if (!ar5k_rfregs_op(rf, hal->ah_offset[0],
+ ee->ee_ob[ee_mode][obdb], 3, 119, 0, AH_TRUE))
return (AH_FALSE);
- if (ar5k_rfregs_set(rf, offset[0],
- ee->ee_ob[ee_mode][obdb], 3, 122, 0) < 0)
+ if (!ar5k_rfregs_op(rf, hal->ah_offset[0],
+ ee->ee_ob[ee_mode][obdb], 3, 122, 0, AH_TRUE))
return (AH_FALSE);
obdb = 1;
@@ -1371,37 +1544,37 @@ ar5k_ar5111_rfregs(hal, channel, mode)
(channel->c_channel >= 5260 ? 1 :
(channel->c_channel > 4000 ? 0 : -1)));
- if (ar5k_rfregs_set(rf, offset[6],
- ee->ee_pwd_84, 1, 51, 3) < 0)
+ if (!ar5k_rfregs_op(rf, hal->ah_offset[6],
+ ee->ee_pwd_84, 1, 51, 3, AH_TRUE))
return (AH_FALSE);
- if (ar5k_rfregs_set(rf, offset[6],
- ee->ee_pwd_90, 1, 45, 3) < 0)
+ if (!ar5k_rfregs_op(rf, hal->ah_offset[6],
+ ee->ee_pwd_90, 1, 45, 3, AH_TRUE))
return (AH_FALSE);
}
- if (ar5k_rfregs_set(rf, offset[6],
- !ee->ee_xpd[ee_mode], 1, 95, 0) < 0)
+ if (!ar5k_rfregs_op(rf, hal->ah_offset[6],
+ !ee->ee_xpd[ee_mode], 1, 95, 0, AH_TRUE))
return (AH_FALSE);
- if (ar5k_rfregs_set(rf, offset[6],
- ee->ee_x_gain[ee_mode], 4, 96, 0) < 0)
+ if (!ar5k_rfregs_op(rf, hal->ah_offset[6],
+ ee->ee_x_gain[ee_mode], 4, 96, 0, AH_TRUE))
return (AH_FALSE);
- if (ar5k_rfregs_set(rf, offset[6],
- obdb >= 0 ? ee->ee_ob[ee_mode][obdb] : 0, 3, 104, 0) < 0)
+ if (!ar5k_rfregs_op(rf, hal->ah_offset[6],
+ obdb >= 0 ? ee->ee_ob[ee_mode][obdb] : 0, 3, 104, 0, AH_TRUE))
return (AH_FALSE);
- if (ar5k_rfregs_set(rf, offset[6],
- obdb >= 0 ? ee->ee_db[ee_mode][obdb] : 0, 3, 107, 0) < 0)
+ if (!ar5k_rfregs_op(rf, hal->ah_offset[6],
+ obdb >= 0 ? ee->ee_db[ee_mode][obdb] : 0, 3, 107, 0, AH_TRUE))
return (AH_FALSE);
- if (ar5k_rfregs_set(rf, offset[7],
- ee->ee_i_gain[ee_mode], 6, 29, 0) < 0)
+ if (!ar5k_rfregs_op(rf, hal->ah_offset[7],
+ ee->ee_i_gain[ee_mode], 6, 29, 0, AH_TRUE))
return (AH_FALSE);
- if (ar5k_rfregs_set(rf, offset[7],
- ee->ee_xpd[ee_mode], 1, 4, 0) < 0)
+ if (!ar5k_rfregs_op(rf, hal->ah_offset[7],
+ ee->ee_xpd[ee_mode], 1, 4, 0, AH_TRUE))
return (AH_FALSE);
/* Write RF values */
@@ -1423,7 +1596,7 @@ ar5k_ar5112_rfregs(hal, channel, mode)
const u_int rf_size = AR5K_ELEMENTS(ar5112_rf);
u_int32_t rf[rf_size];
int i, obdb = -1, bank = -1;
- u_int32_t ee_mode, offset[AR5K_AR5112_INI_RF_MAX_BANKS];
+ u_int32_t ee_mode;
AR5K_ASSERT_ENTRY(mode, AR5K_INI_VAL_MAX);
@@ -1437,7 +1610,7 @@ ar5k_ar5112_rfregs(hal, channel, mode)
if (bank != ar5112_rf[i].rf_bank) {
bank = ar5112_rf[i].rf_bank;
- offset[bank] = i;
+ hal->ah_offset[bank] = i;
}
rf[i] = ar5112_rf[i].rf_value[mode];
@@ -1450,12 +1623,12 @@ ar5k_ar5112_rfregs(hal, channel, mode)
ee_mode = AR5K_EEPROM_MODE_11G;
obdb = 0;
- if (ar5k_rfregs_set(rf, offset[6],
- ee->ee_ob[ee_mode][obdb], 3, 287, 0) < 0)
+ if (!ar5k_rfregs_op(rf, hal->ah_offset[6],
+ ee->ee_ob[ee_mode][obdb], 3, 287, 0, AH_TRUE))
return (AH_FALSE);
- if (ar5k_rfregs_set(rf, offset[6],
- ee->ee_ob[ee_mode][obdb], 3, 290, 0) < 0)
+ if (!ar5k_rfregs_op(rf, hal->ah_offset[6],
+ ee->ee_ob[ee_mode][obdb], 3, 290, 0, AH_TRUE))
return (AH_FALSE);
} else {
/* For 11a, Turbo and XR */
@@ -1465,26 +1638,28 @@ ar5k_ar5112_rfregs(hal, channel, mode)
(channel->c_channel >= 5260 ? 1 :
(channel->c_channel > 4000 ? 0 : -1)));
- if (ar5k_rfregs_set(rf, offset[6],
- ee->ee_ob[ee_mode][obdb], 3, 279, 0) < 0)
+ if (!ar5k_rfregs_op(rf, hal->ah_offset[6],
+ ee->ee_ob[ee_mode][obdb], 3, 279, 0, AH_TRUE))
return (AH_FALSE);
- if (ar5k_rfregs_set(rf, offset[6],
- ee->ee_ob[ee_mode][obdb], 3, 282, 0) < 0)
+ if (!ar5k_rfregs_op(rf, hal->ah_offset[6],
+ ee->ee_ob[ee_mode][obdb], 3, 282, 0, AH_TRUE))
return (AH_FALSE);
}
#ifdef notyet
- ar5k_rfregs_set(rf, offset[6], ee->ee_x_gain[ee_mode], 2, 270, 0);
- ar5k_rfregs_set(rf, offset[6], ee->ee_x_gain[ee_mode], 2, 257, 0);
+ ar5k_rfregs_op(rf, hal->ah_offset[6],
+ ee->ee_x_gain[ee_mode], 2, 270, 0, AH_TRUE);
+ ar5k_rfregs_op(rf, hal->ah_offset[6],
+ ee->ee_x_gain[ee_mode], 2, 257, 0, AH_TRUE);
#endif
- if (ar5k_rfregs_set(rf, offset[6],
- ee->ee_xpd[ee_mode], 1, 302, 0) < 0)
+ if (!ar5k_rfregs_op(rf, hal->ah_offset[6],
+ ee->ee_xpd[ee_mode], 1, 302, 0, AH_TRUE))
return (AH_FALSE);
- if (ar5k_rfregs_set(rf, offset[7],
- ee->ee_i_gain[ee_mode], 6, 14, 0) < 0)
+ if (!ar5k_rfregs_op(rf, hal->ah_offset[7],
+ ee->ee_i_gain[ee_mode], 6, 14, 0, AH_TRUE))
return (AH_FALSE);
/* Write RF values */
diff --git a/sys/dev/ic/ar5xxx.h b/sys/dev/ic/ar5xxx.h
index 967f8d2d73d..facb48e9182 100644
--- a/sys/dev/ic/ar5xxx.h
+++ b/sys/dev/ic/ar5xxx.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ar5xxx.h,v 1.12 2005/02/25 22:25:30 reyk Exp $ */
+/* $OpenBSD: ar5xxx.h,v 1.13 2005/03/18 20:46:32 reyk Exp $ */
/*
* Copyright (c) 2004, 2005 Reyk Floeter <reyk@vantronix.net>
@@ -93,6 +93,7 @@ typedef enum {
HAL_MODE_PUREG = 0x008,
HAL_MODE_11G = 0x010,
HAL_MODE_108G = 0x020,
+ HAL_MODE_XR = 0x040,
HAL_MODE_ALL = 0xfff
} HAL_MODE;
@@ -338,7 +339,8 @@ typedef struct {
#define r_valid valid
#define r_phy phy
#define r_rate_kbps rateKbps
-#define r_short_preamble short_preamble
+#define r_rate_code rateCode
+#define r_short_preamble shortPreamble
#define r_dot11_rate dot11Rate
#define r_control_rate controlRate
@@ -355,7 +357,10 @@ typedef struct {
} HAL_RATE_TABLE;
-#define AR5K_RATES_11A { 8, { 0 }, { \
+#define AR5K_RATES_11A { 8, { \
+ 255, 255, 255, 255, 255, 255, 255, 255, 6, 4, 2, 0, \
+ 7, 5, 3, 1, 255, 255, 255, 255, 255, 255, 255, 255, \
+ 255, 255, 255, 255, 255, 255, 255, 255 }, { \
{ 1, IEEE80211_T_OFDM, 6000, 11, 0, 140, 0 }, \
{ 1, IEEE80211_T_OFDM, 9000, 15, 0, 18, 0 }, \
{ 1, IEEE80211_T_OFDM, 12000, 10, 0, 152, 2 }, \
@@ -366,14 +371,20 @@ typedef struct {
{ 1, IEEE80211_T_OFDM, 54000, 12, 0, 108, 4 } } \
}
-#define AR5K_RATES_11B { 4, { 0 }, { \
+#define AR5K_RATES_11B { 4, { \
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, \
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, \
+ 3, 2, 1, 0, 255, 255, 255, 255 }, { \
{ 1, IEEE80211_T_CCK, 1000, 27, 0x00, 130, 0 }, \
{ 1, IEEE80211_T_CCK, 2000, 26, 0x00, 132, 1 }, \
{ 1, IEEE80211_T_CCK, 5500, 25, 0x00, 139, 1 }, \
{ 1, IEEE80211_T_CCK, 11000, 24, 0x00, 150, 1 } } \
}
-#define AR5K_RATES_11G { 12, { 0 }, { \
+#define AR5K_RATES_11G { 12, { \
+ 255, 255, 255, 255, 255, 255, 255, 255, 10, 8, 6, 4, \
+ 11, 9, 7, 5, 255, 255, 255, 255, 255, 255, 255, 255, \
+ 3, 2, 1, 0, 255, 255, 255, 255 }, { \
{ 1, IEEE80211_T_CCK, 1000, 27, 0x00, 130, 0 }, \
{ 1, IEEE80211_T_CCK, 2000, 26, 0x00, 132, 1 }, \
{ 1, IEEE80211_T_CCK, 5500, 25, 0x00, 139, 1 }, \
@@ -388,7 +399,10 @@ typedef struct {
{ 1, IEEE80211_T_OFDM, 54000, 12, 0, 108, 8 } } \
}
-#define AR5K_RATES_TURBO { 8, { 0 }, { \
+#define AR5K_RATES_TURBO { 8, { \
+ 255, 255, 255, 255, 255, 255, 255, 255, 6, 4, 2, 0, \
+ 7, 5, 3, 1, 255, 255, 255, 255, 255, 255, 255, 255, \
+ 255, 255, 255, 255, 255, 255, 255, 255 }, { \
{ 1, IEEE80211_T_TURBO, 6000, 11, 0, 140, 0 }, \
{ 1, IEEE80211_T_TURBO, 9000, 15, 0, 18, 0 }, \
{ 1, IEEE80211_T_TURBO, 12000, 10, 0, 152, 2 }, \
@@ -399,6 +413,24 @@ typedef struct {
{ 1, IEEE80211_T_TURBO, 54000, 12, 0, 108, 4 } } \
}
+#define AR5K_RATES_XR { 12, { \
+ 255, 3, 1, 255, 255, 255, 2, 0, 10, 8, 6, 4, \
+ 11, 9, 7, 5, 255, 255, 255, 255, 255, 255, 255, 255, \
+ 255, 255, 255, 255, 255, 255, 255, 255 }, { \
+ { 1, IEEE80211_T_XR, 500, 7, 0, 129, 0 }, \
+ { 1, IEEE80211_T_XR, 1000, 2, 0, 139, 1 }, \
+ { 1, IEEE80211_T_XR, 2000, 6, 0, 150, 2 }, \
+ { 1, IEEE80211_T_XR, 3000, 1, 0, 150, 3 }, \
+ { 1, IEEE80211_T_OFDM, 6000, 11, 0, 140, 4 }, \
+ { 1, IEEE80211_T_OFDM, 9000, 15, 0, 18, 4 }, \
+ { 1, IEEE80211_T_OFDM, 12000, 10, 0, 152, 6 }, \
+ { 1, IEEE80211_T_OFDM, 18000, 14, 0, 36, 6 }, \
+ { 1, IEEE80211_T_OFDM, 24000, 9, 0, 176, 8 }, \
+ { 1, IEEE80211_T_OFDM, 36000, 13, 0, 72, 8 }, \
+ { 1, IEEE80211_T_OFDM, 48000, 8, 0, 96, 8 }, \
+ { 1, IEEE80211_T_OFDM, 54000, 12, 0, 108, 8 } } \
+}
+
typedef enum {
HAL_RFGAIN_INACTIVE = 0,
HAL_RFGAIN_READ_REQUESTED,
@@ -491,6 +523,85 @@ typedef enum ieee80211_state HAL_LED_STATE;
#define HAL_LED_RUN IEEE80211_S_RUN
/*
+ * Gain settings
+ */
+
+#define AR5K_GAIN_CRN_FIX_BITS_5111 4
+#define AR5K_GAIN_CRN_FIX_BITS_5112 7
+#define AR5K_GAIN_CRN_MAX_FIX_BITS AR5K_GAIN_CRN_FIX_BITS_5112
+#define AR5K_GAIN_DYN_ADJUST_HI_MARGIN 15
+#define AR5K_GAIN_DYN_ADJUST_LO_MARGIN 20
+#define AR5K_GAIN_CCK_PROBE_CORR 5
+#define AR5K_GAIN_CCK_OFDM_GAIN_DELTA 15
+#define AR5K_GAIN_STEP_COUNT 10
+#define AR5K_GAIN_PARAM_TX_CLIP 0
+#define AR5K_GAIN_PARAM_PD_90 1
+#define AR5K_GAIN_PARAM_PD_84 2
+#define AR5K_GAIN_PARAM_GAIN_SEL 3
+#define AR5K_GAIN_PARAM_MIX_ORN 0
+#define AR5K_GAIN_PARAM_PD_138 1
+#define AR5K_GAIN_PARAM_PD_137 2
+#define AR5K_GAIN_PARAM_PD_136 3
+#define AR5K_GAIN_PARAM_PD_132 4
+#define AR5K_GAIN_PARAM_PD_131 5
+#define AR5K_GAIN_PARAM_PD_130 6
+#define AR5K_GAIN_CHECK_ADJUST(_g) \
+ ((_g)->g_current <= (_g)->g_low || (_g)->g_current >= (_g)->g_high)
+
+struct ar5k_gain_opt_step {
+ int16_t gos_param[AR5K_GAIN_CRN_MAX_FIX_BITS];
+ int32_t gos_gain;
+};
+
+struct ar5k_gain_opt {
+ u_int32_t go_default;
+ u_int32_t go_steps_count;
+ const struct ar5k_gain_opt_step go_step[AR5K_GAIN_STEP_COUNT];
+};
+
+struct ar5k_gain {
+ u_int32_t g_step_idx;
+ u_int32_t g_current;
+ u_int32_t g_target;
+ u_int32_t g_low;
+ u_int32_t g_high;
+ u_int32_t g_f_corr;
+ u_int32_t g_active;
+ const struct ar5k_gain_opt_step *g_step;
+};
+
+#define AR5K_AR5111_GAIN_OPT { \
+ 4, \
+ 9, \
+ { \
+ { { 4, 1, 1, 1 }, 6 }, \
+ { { 4, 0, 1, 1 }, 4 }, \
+ { { 3, 1, 1, 1 }, 3 }, \
+ { { 4, 0, 0, 1 }, 1 }, \
+ { { 4, 1, 1, 0 }, 0 }, \
+ { { 4, 0, 1, 0 }, -2 }, \
+ { { 3, 1, 1, 0 }, -3 }, \
+ { { 4, 0, 0, 0 }, -4 }, \
+ { { 2, 1, 1, 0 }, -6 } \
+ } \
+}
+
+#define AR5K_AR5112_GAIN_OPT { \
+ 1, \
+ 8, \
+ { \
+ { { 3, 0, 0, 0, 0, 0, 0 }, 6 }, \
+ { { 2, 0, 0, 0, 0, 0, 0 }, 0 }, \
+ { { 1, 0, 0, 0, 0, 0, 0 }, -3 }, \
+ { { 0, 0, 0, 0, 0, 0, 0 }, -6 }, \
+ { { 0, 1, 1, 0, 0, 0, 0 }, -8 }, \
+ { { 0, 1, 1, 0, 1, 1, 0 }, -10 }, \
+ { { 0, 1, 0, 1, 1, 1, 0 }, -13 }, \
+ { { 0, 1, 0, 1, 1, 0, 1 }, -16 }, \
+ } \
+}
+
+/*
* Common ar5xxx EEPROM data registers
*/
@@ -959,7 +1070,8 @@ struct ath_desc {
_t int (_a _n##_eeprom_write)(struct ath_hal *, u_int32_t offset, \
u_int16_t data);
-#define AR5K_MAX_GPIO 10
+#define AR5K_MAX_GPIO 10
+#define AR5K_MAX_RF_BANKS 8
struct ath_hal {
u_int32_t ah_magic;
@@ -980,6 +1092,7 @@ struct ath_hal {
HAL_BOOL ah_turbo;
HAL_BOOL ah_calibration;
HAL_BOOL ah_running;
+ HAL_RFGAIN ah_rf_gain;
#define ah_countryCode ah_country_code
@@ -987,6 +1100,7 @@ struct ath_hal {
HAL_RATE_TABLE ah_rt_11b;
HAL_RATE_TABLE ah_rt_11g;
HAL_RATE_TABLE ah_rt_turbo;
+ HAL_RATE_TABLE ah_rt_xr;
u_int32_t ah_mac_version;
u_int16_t ah_mac_revision;
@@ -1029,7 +1143,10 @@ struct ath_hal {
ar5k_capabilities_t ah_capabilities;
HAL_TXQ_INFO ah_txq[HAL_NUM_TX_QUEUES];
- u_int32_t ah_txq_interrupts;
+ u_int32_t ah_txq_interrupts;
+
+ struct ar5k_gain ah_gain;
+ u_int32_t ah_offset[AR5K_MAX_RF_BANKS];
struct {
u_int16_t txp_pcdac[AR5K_EEPROM_POWER_TABLE_SIZE];
@@ -1279,8 +1396,8 @@ struct ar5k_ini {
#define AR5K_INI_PHY_5112 1
#define AR5K_INI_PHY_511X 1
-#define AR5K_AR5111_INI_RF_MAX_BANKS 8
-#define AR5K_AR5112_INI_RF_MAX_BANKS 8
+#define AR5K_AR5111_INI_RF_MAX_BANKS AR5K_MAX_RF_BANKS
+#define AR5K_AR5112_INI_RF_MAX_BANKS AR5K_MAX_RF_BANKS
struct ar5k_ini_rf {
u_int8_t rf_bank;
@@ -1675,6 +1792,9 @@ HAL_BOOL ar5k_eeprom_regulation_domain(struct ath_hal *,
HAL_BOOL ar5k_channel(struct ath_hal *, HAL_CHANNEL *);
HAL_BOOL ar5k_rfregs(struct ath_hal *, HAL_CHANNEL *, u_int);
+u_int32_t ar5k_rfregs_gainf_corr(struct ath_hal *);
+HAL_BOOL ar5k_rfregs_gain_readback(struct ath_hal *);
+int32_t ar5k_rfregs_gain_adjust(struct ath_hal *);
HAL_BOOL ar5k_rfgain(struct ath_hal *, u_int, u_int);
__END_DECLS