diff options
-rw-r--r-- | sys/dev/ic/ar5212.c | 119 | ||||
-rw-r--r-- | sys/dev/ic/ar5212reg.h | 10 | ||||
-rw-r--r-- | sys/dev/ic/ar5xxx.c | 307 | ||||
-rw-r--r-- | sys/dev/ic/ar5xxx.h | 140 |
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 |