summaryrefslogtreecommitdiff
path: root/sys/dev/ic
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/ic')
-rw-r--r--sys/dev/ic/ar5210.c359
-rw-r--r--sys/dev/ic/ar5210reg.h62
-rw-r--r--sys/dev/ic/ar5210var.h6
-rw-r--r--sys/dev/ic/ar5xxx.c986
-rw-r--r--sys/dev/ic/ar5xxx.h672
-rw-r--r--sys/dev/ic/ath.c41
6 files changed, 1759 insertions, 367 deletions
diff --git a/sys/dev/ic/ar5210.c b/sys/dev/ic/ar5210.c
index daa9283a6a1..1a7cf2ebcda 100644
--- a/sys/dev/ic/ar5210.c
+++ b/sys/dev/ic/ar5210.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ar5210.c,v 1.7 2004/11/23 10:13:04 reyk Exp $ */
+/* $OpenBSD: ar5210.c,v 1.8 2004/12/31 01:00:23 reyk Exp $ */
/*
* Copyright (c) 2004 Reyk Floeter <reyk@vantronix.net>.
@@ -36,10 +36,10 @@
HAL_BOOL ar5k_ar5210_nic_reset(struct ath_hal *, u_int32_t);
HAL_BOOL ar5k_ar5210_nic_wakeup(struct ath_hal *, HAL_BOOL, HAL_BOOL);
-u_int32_t ar5k_ar5210_chan2athchan(HAL_CHANNEL *);
-HAL_BOOL ar5k_ar5210_set_channel(struct ath_hal *, HAL_CHANNEL *);
void ar5k_ar5210_init_tx_queue(struct ath_hal *, u_int, HAL_BOOL);
const void ar5k_ar5210_fill(struct ath_hal *);
+HAL_BOOL ar5k_ar5210_calibrate(struct ath_hal *, HAL_CHANNEL *);
+HAL_BOOL ar5k_ar5210_noise_floor(struct ath_hal *, HAL_CHANNEL *);
AR5K_HAL_FUNCTIONS(extern, ar5k_ar5210,);
@@ -168,12 +168,10 @@ ar5k_ar5210_fill(hal)
*/
AR5K_HAL_FUNCTION(hal, ar5210, get_capabilities);
AR5K_HAL_FUNCTION(hal, ar5210, radar_alert);
- AR5K_HAL_FUNCTION(hal, ar5210, regulation_domain);
/*
* EEPROM access
*/
- AR5K_HAL_FUNCTION(hal, ar5210, eeprom_init);
AR5K_HAL_FUNCTION(hal, ar5210, eeprom_is_busy);
AR5K_HAL_FUNCTION(hal, ar5210, eeprom_read);
AR5K_HAL_FUNCTION(hal, ar5210, eeprom_write);
@@ -209,10 +207,15 @@ ar5k_ar5210_attach(device, sc, st, sh, status)
for (i = 0; i < 4; i++)
AR5K_REG_WRITE(AR5K_AR5210_PHY(0x20), 0x00010000);
hal->ah_radio_5ghz_revision = (u_int16_t)
- (ar5k_bitswap((AR5K_REG_READ(AR5K_AR5210_PHY(256) >> 28) &
- 0xf), 4) + 1);
+ (ar5k_bitswap((AR5K_REG_READ(AR5K_AR5210_PHY(256) >> 28) & 0xf), 4)
+ + 1);
hal->ah_radio_2ghz_revision = 0;
+ /* Identify the chipset */
+ hal->ah_version = AR5K_AR5210;
+ hal->ah_radio = AR5K_AR5110;
+ hal->ah_phy = AR5K_AR5210_PHY(0);
+
memset(&mac, 0xff, sizeof(mac));
ar5k_ar5210_writeAssocid(hal, mac, 0, 0);
ar5k_ar5210_getMacAddress(hal, mac);
@@ -250,7 +253,7 @@ ar5k_ar5210_nic_reset(hal, val)
/*
* Reset configuration register
*/
- if ((val & AR5K_AR5210_RC_MAC) == 0)
+ if ((val & AR5K_AR5210_RC_MAC) == 0)
AR5K_REG_WRITE(AR5K_AR5210_CFG, AR5K_AR5210_INIT_CFG);
return (ret);
@@ -321,68 +324,6 @@ ar5k_ar5210_nic_wakeup(hal, turbo, initial)
return (AH_TRUE);
}
-u_int32_t
-ar5k_ar5210_chan2athchan(channel)
- HAL_CHANNEL *channel;
-{
- u_int32_t athchan;
-
- /*
- * Convert IEEE channel/MHz to an internal channel value used
- * by the AR5210 chipset. This has not been verified with
- * newer chipsets like the AR5212A who have a completely
- * different RF/PHY part.
- */
- athchan = (ar5k_bitswap((ieee80211_mhz2ieee(channel->c_channel,
- channel->c_channel_flags) - 24)
- / 2, 5) << 1) | (1 << 6) | 0x1;
-
- return (athchan);
-}
-
-HAL_BOOL
-ar5k_ar5210_set_channel(hal, channel)
- struct ath_hal *hal;
- HAL_CHANNEL *channel;
-{
- u_int32_t data;
-
- /* Disable phy and wait */
- AR5K_REG_WRITE(AR5K_AR5210_PHY_ACTIVE, AR5K_AR5210_PHY_DISABLE);
- AR5K_DELAY(1000);
-
- /*
- * Check bounds supported by the PHY
- * (don't care about regulation restrictions at this point)
- */
- if (channel->c_channel < hal->ah_capabilities.cap_range.range_5ghz_min ||
- channel->c_channel > hal->ah_capabilities.cap_range.range_5ghz_max) {
- AR5K_PRINTF("channel out of supported range (%uMHz)\n",
- channel->c_channel);
- return (AH_FALSE);
- }
-
- /*
- * Set the channel and wait
- */
- data = ar5k_ar5210_chan2athchan(channel);
- AR5K_REG_WRITE(AR5K_AR5210_PHY(0x27), data);
- AR5K_REG_WRITE(AR5K_AR5210_PHY(0x30), 0);
- AR5K_DELAY(1000);
-
- /*
- * Activate phy and wait
- */
- AR5K_REG_WRITE(AR5K_AR5210_PHY_ACTIVE, AR5K_AR5210_PHY_ENABLE);
- AR5K_DELAY(1000);
-
- hal->ah_current_channel.channel = channel->c_channel;
- hal->ah_current_channel.channelFlags = channel->c_channel_flags;
- hal->ah_turbo = channel->c_channel_flags == CHANNEL_T ? AH_TRUE : AH_FALSE;
-
- return (AH_TRUE);
-}
-
const HAL_RATE_TABLE *
ar5k_ar5210_getRateTable(hal, mode)
struct ath_hal *hal;
@@ -423,6 +364,9 @@ ar5k_ar5210_reset(hal, op_mode, channel, change_channel, status)
int i;
struct ar5k_ini initial[] = AR5K_AR5210_INI;
+ /* Not used, keep for HAL compatibility */
+ *status = HAL_OK;
+
if (ar5k_ar5210_nic_wakeup(hal,
channel->c_channel_flags & IEEE80211_CHAN_T ?
AH_TRUE : AH_FALSE, AH_FALSE) == AH_FALSE)
@@ -444,12 +388,12 @@ ar5k_ar5210_reset(hal, op_mode, channel, change_channel, status)
continue;
switch (initial[i].ini_mode) {
- case INI_READ:
+ case AR5K_INI_READ:
/* Cleared on read */
AR5K_REG_READ(initial[i].ini_register);
break;
- case INI_WRITE:
+ case AR5K_INI_WRITE:
default:
AR5K_REG_WRITE(initial[i].ini_register,
initial[i].ini_value);
@@ -461,13 +405,29 @@ ar5k_ar5210_reset(hal, op_mode, channel, change_channel, status)
/*
* Set channel and calibrate the PHY
*/
- if (ar5k_ar5210_perCalibration(hal, channel) == AH_FALSE)
+
+ /* Disable phy and wait */
+ AR5K_REG_WRITE(AR5K_AR5210_PHY_ACTIVE, AR5K_AR5210_PHY_DISABLE);
+ AR5K_DELAY(1000);
+
+ if (ar5k_channel(hal, channel) == AH_FALSE)
+ return (AH_FALSE);
+
+ /*
+ * Activate phy and wait
+ */
+ AR5K_REG_WRITE(AR5K_AR5210_PHY_ACTIVE, AR5K_AR5210_PHY_ENABLE);
+ AR5K_DELAY(1000);
+
+ ar5k_ar5210_calibrate(hal, channel);
+ if (ar5k_ar5210_noise_floor(hal, channel) == AH_FALSE)
return (AH_FALSE);
/*
* Set RF kill flags if supported by the device (read from the EEPROM)
*/
- if (hal->ah_capabilities.cap_eeprom.ee_rfkill != 0) {
+ if (AR5K_EEPROM_HDR_RFKILL(hal->ah_capabilities.cap_eeprom.ee_header)) {
+ ar5k_ar5210_gpioCfgInput(hal, 0);
if ((hal->ah_gpio[0] = ar5k_ar5210_gpioGet(hal, 0)) == 0)
ar5k_ar5210_gpioSetIntr(hal, 0, 1);
else
@@ -545,6 +505,20 @@ ar5k_ar5210_perCalibration(hal, channel)
struct ath_hal *hal;
HAL_CHANNEL *channel;
{
+ HAL_BOOL ret = AH_TRUE;
+ u_int32_t phy_sig, phy_agc, phy_sat;
+
+#define AGC_DISABLE { \
+ AR5K_REG_ENABLE_BITS(AR5K_AR5210_PHY_AGC, \
+ AR5K_AR5210_PHY_AGC_DISABLE); \
+ AR5K_DELAY(10); \
+}
+
+#define AGC_ENABLE { \
+ AR5K_REG_DISABLE_BITS(AR5K_AR5210_PHY_AGC, \
+ AR5K_AR5210_PHY_AGC_DISABLE); \
+}
+
/*
* Disable beacons and RX/TX queues, wait
*/
@@ -557,38 +531,138 @@ ar5k_ar5210_perCalibration(hal, channel)
/*
* Set the channel (with AGC turned off)
*/
- AR5K_REG_ENABLE_BITS(AR5K_AR5210_PHY_AGC, AR5K_AR5210_PHY_AGC_DISABLE);
+ AGC_DISABLE;
+ ret = ar5k_channel(hal, channel);
+
+ /*
+ * Activate PHY and wait
+ */
+ AR5K_REG_WRITE(AR5K_AR5210_PHY_ACTIVE, AR5K_AR5210_PHY_ENABLE);
+ AR5K_DELAY(1000);
+
+ AGC_ENABLE;
+
+ if (ret == AH_FALSE)
+ return (ret);
+
+ /*
+ * Calibrate the radio chip
+ */
+
+ /* Remember normal state */
+ phy_sig = AR5K_REG_READ(AR5K_AR5210_PHY_SIG);
+ phy_agc = AR5K_REG_READ(AR5K_AR5210_PHY_AGCCOARSE);
+ phy_sat = AR5K_REG_READ(AR5K_AR5210_PHY_ADCSAT);
+
+ /* Update radio registers */
+ AR5K_REG_WRITE(AR5K_AR5210_PHY_SIG,
+ (phy_sig & ~(AR5K_AR5210_PHY_SIG_FIRPWR)) |
+ AR5K_REG_SM(-1, AR5K_AR5210_PHY_SIG_FIRPWR));
+
+ AR5K_REG_WRITE(AR5K_AR5210_PHY_AGCCOARSE,
+ (phy_agc & ~(AR5K_AR5210_PHY_AGCCOARSE_HI |
+ AR5K_AR5210_PHY_AGCCOARSE_LO)) |
+ AR5K_REG_SM(-1, AR5K_AR5210_PHY_AGCCOARSE_HI) |
+ AR5K_REG_SM(-127, AR5K_AR5210_PHY_AGCCOARSE_LO));
+
+ AR5K_REG_WRITE(AR5K_AR5210_PHY_ADCSAT,
+ (phy_sat & ~(AR5K_AR5210_PHY_ADCSAT_ICNT |
+ AR5K_AR5210_PHY_ADCSAT_THR)) |
+ AR5K_REG_SM(2, AR5K_AR5210_PHY_ADCSAT_ICNT) |
+ AR5K_REG_SM(12, AR5K_AR5210_PHY_ADCSAT_THR));
- if (ar5k_ar5210_set_channel(hal, channel) != AH_TRUE)
+ AR5K_DELAY(20);
+
+ AGC_DISABLE;
+ AR5K_REG_WRITE(AR5K_AR5210_PHY_RFSTG, AR5K_AR5210_PHY_RFSTG_DISABLE);
+ AGC_ENABLE;
+
+ AR5K_DELAY(1000);
+
+ ret = ar5k_ar5210_calibrate(hal, channel);
+
+ /* Reset to normal state */
+ AR5K_REG_WRITE(AR5K_AR5210_PHY_SIG, phy_sig);
+ AR5K_REG_WRITE(AR5K_AR5210_PHY_AGCCOARSE, phy_agc);
+ AR5K_REG_WRITE(AR5K_AR5210_PHY_ADCSAT, phy_sat);
+
+ if (ret == AH_FALSE)
return (AH_FALSE);
- AR5K_REG_DISABLE_BITS(AR5K_AR5210_PHY_AGC, AR5K_AR5210_PHY_AGC_DISABLE);
+ if (ar5k_ar5210_noise_floor(hal, channel) == AH_FALSE)
+ return (AH_FALSE);
/*
- * Enable noise floor calibration and wait until completion
+ * Re-enable RX/TX and beacons
+ */
+ AR5K_REG_DISABLE_BITS(AR5K_AR5210_DIAG_SW,
+ AR5K_AR5210_DIAG_SW_DIS_TX | AR5K_AR5210_DIAG_SW_DIS_RX);
+ AR5K_REG_ENABLE_BITS(AR5K_AR5210_BEACON, AR5K_AR5210_BEACON_EN);
+
+#undef AGC_ENABLE
+#undef AGC_DISABLE
+
+ return (AH_TRUE);
+}
+
+HAL_BOOL
+ar5k_ar5210_calibrate(hal, channel)
+ struct ath_hal *hal;
+ HAL_CHANNEL *channel;
+{
+ /*
+ * Enable calibration and wait until completion
*/
AR5K_REG_ENABLE_BITS(AR5K_AR5210_PHY_AGCCTL,
- AR5K_AR5210_PHY_AGC_CAL);
+ AR5K_AR5210_PHY_AGCCTL_CAL);
if (ar5k_register_timeout(hal, AR5K_AR5210_PHY_AGCCTL,
- AR5K_AR5210_PHY_AGC_CAL, 0, AH_FALSE) == AH_FALSE) {
+ AR5K_AR5210_PHY_AGCCTL_CAL, 0, AH_FALSE) == AH_FALSE) {
AR5K_PRINTF("calibration timeout (%uMHz)\n",
channel->c_channel);
return (AH_FALSE);
}
+ return (AH_TRUE);
+}
+
+HAL_BOOL
+ar5k_ar5210_noise_floor(hal, channel)
+ struct ath_hal *hal;
+ HAL_CHANNEL *channel;
+{
+ int i;
+ u_int32_t noise_floor;
+
/*
- * XXX Check the current noise floor?
+ * Enable noise floor calibration and wait until completion
*/
AR5K_REG_ENABLE_BITS(AR5K_AR5210_PHY_AGCCTL,
- AR5K_AR5210_PHY_AGC_NF);
+ AR5K_AR5210_PHY_AGCCTL_NF);
- /*
- * Re-enable RX/TX and beacons
- */
- AR5K_REG_DISABLE_BITS(AR5K_AR5210_DIAG_SW,
- AR5K_AR5210_DIAG_SW_DIS_TX | AR5K_AR5210_DIAG_SW_DIS_RX);
- AR5K_REG_ENABLE_BITS(AR5K_AR5210_BEACON, AR5K_AR5210_BEACON_EN);
+ if (ar5k_register_timeout(hal, AR5K_AR5210_PHY_AGCCTL,
+ AR5K_AR5210_PHY_AGCCTL_NF, 0, AH_FALSE) == AH_FALSE) {
+ AR5K_PRINTF("noise floor calibration timeout (%uMHz)\n",
+ channel->c_channel);
+ return (AH_FALSE);
+ }
+
+ /* wait until the noise floor is calibrated */
+ for (i = 20; i > 0; i--) {
+ AR5K_DELAY(1000);
+ noise_floor = AR5K_REG_READ(AR5K_AR5210_PHY_NF);
+ if (AR5K_AR5210_PHY_NF_RVAL(noise_floor) &
+ AR5K_AR5210_PHY_NF_ACTIVE)
+ noise_floor = AR5K_AR5210_PHY_NF_AVAL(noise_floor);
+ if (noise_floor <= AR5K_TUNE_NOISE_FLOOR)
+ break;
+ }
+
+ if (noise_floor > AR5K_TUNE_NOISE_FLOOR) {
+ AR5K_PRINTF("noise floor calibration failed (%uMHz)\n",
+ channel->c_channel);
+ return (AH_FALSE);
+ }
return (AH_TRUE);
}
@@ -654,7 +728,7 @@ ar5k_ar5210_setupTxQueue(hal, queue_type, queue_info)
queue = 1;
break;
default:
- return (EINVAL);
+ return (-1);
}
/*
@@ -666,10 +740,10 @@ ar5k_ar5210_setupTxQueue(hal, queue_type, queue_info)
if (queue_info != NULL) {
if (ar5k_ar5210_setTxQueueProps(hal,
queue, queue_info) != AH_TRUE)
- return (AH_FALSE);
+ return (-1);
}
- return (0);
+ return (queue);
}
HAL_BOOL
@@ -720,7 +794,8 @@ ar5k_ar5210_init_tx_queue(hal, aifs, turbo)
* Write initial mode register settings
*/
for (i = 0; i < AR5K_ELEMENTS(initial); i++)
- AR5K_REG_WRITE(initial[i].mode_register, turbo == AH_TRUE ?
+ AR5K_REG_WRITE((u_int32_t)initial[i].mode_register,
+ turbo == AH_TRUE ?
initial[i].mode_turbo : initial[i].mode_base);
}
@@ -983,6 +1058,7 @@ ar5k_ar5210_setupTxDesc(hal, desc, packet_length, header_length, type, tx_power,
tx_desc->xmit_rate = tx_rate0;
tx_desc->ant_mode_xmit = antenna_mode ? 1 : 0;
tx_desc->clear_dest_mask = flags & HAL_TXDESC_CLRDMASK ? 1 : 0;
+ tx_desc->inter_req = flags & HAL_TXDESC_INTREQ ? 1 : 0;
/*
* WEP crap
@@ -995,7 +1071,7 @@ ar5k_ar5210_setupTxDesc(hal, desc, packet_length, header_length, type, tx_power,
/*
* RTS/CTS
*/
- if (flags & (HAL_TXDESC_RTSENA|HAL_TXDESC_CTSENA)) {
+ if (flags & (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA)) {
tx_desc->rts_cts_enable = 1;
tx_desc->rts_duration = rtscts_duration;
}
@@ -1087,7 +1163,6 @@ ar5k_ar5210_procTxDesc(hal, desc)
if (tx_status->filtered)
desc->ds_us.tx.ts_status |= HAL_TXERR_FILT;
}
-
#if 0
/*
* Reset descriptor
@@ -1339,6 +1414,7 @@ void
ar5k_ar5210_dumpState(hal)
struct ath_hal *hal;
{
+#ifdef AR5K_DEBUG
#define AR5K_PRINT_REGISTER(_x) \
printf("(%s: %08x) ", #_x, AR5K_REG_READ(AR5K_AR5210_##_x));
@@ -1422,6 +1498,7 @@ ar5k_ar5210_dumpState(hal)
AR5K_PRINT_REGISTER(PHY_ACTIVE);
AR5K_PRINT_REGISTER(PHY_AGCCTL);
printf("\n");
+#endif
}
HAL_BOOL
@@ -1474,7 +1551,7 @@ ar5k_ar5210_setRegulatoryDomain(hal, regdomain, status)
HAL_STATUS *status;
{
- if (ar5k_ar5210_regulation_domain(hal, AH_TRUE,
+ if (ar5k_eeprom_regulation_domain(hal, AH_TRUE,
ar5k_regdomain_to_ieee((u_int8_t)regdomain)) == AH_TRUE) {
*status = HAL_OK;
return (AH_TRUE);
@@ -1675,7 +1752,7 @@ ar5k_ar5210_getRegDomain(hal)
u_int16_t regdomain;
ieee80211_regdomain_t ieee_regdomain;
- if (ar5k_ar5210_regulation_domain(hal,
+ if (ar5k_eeprom_regulation_domain(hal,
AH_FALSE, &ieee_regdomain) == AH_TRUE) {
regdomain = ar5k_regdomain_from_ieee(&ieee_regdomain);
return (regdomain > 0 ? regdomain : hal->ah_regdomain);
@@ -1695,10 +1772,10 @@ ar5k_ar5210_detectCardPresent(hal)
* if the card is still present. I didn't find another suitable
* way to do this.
*/
- if (ar5k_ar5210_eeprom_read(hal, AR5K_AR5210_EEPROM_MAGIC, &magic) != 0)
+ if (ar5k_ar5210_eeprom_read(hal, AR5K_EEPROM_MAGIC, &magic) != 0)
return (AH_FALSE);
- return (magic == AR5K_AR5210_EEPROM_MAGIC_VALUE ? AH_TRUE : AH_FALSE);
+ return (magic == AR5K_EEPROM_MAGIC_VALUE ? AH_TRUE : AH_FALSE);
}
void
@@ -1950,29 +2027,30 @@ HAL_BOOL
ar5k_ar5210_setPowerMode(hal, mode, set_chip, sleep_duration)
struct ath_hal *hal;
HAL_POWER_MODE mode;
- int set_chip;
+ HAL_BOOL set_chip;
u_int16_t sleep_duration;
{
int i;
switch (mode) {
case HAL_PM_AUTO:
- if (set_chip)
+ if (set_chip == AH_TRUE)
AR5K_REG_WRITE(AR5K_AR5210_SCR,
AR5K_AR5210_SCR_SLE | sleep_duration);
break;
case HAL_PM_FULL_SLEEP:
- if (set_chip)
+ if (set_chip == AH_TRUE)
AR5K_REG_WRITE(AR5K_AR5210_SCR,
AR5K_AR5210_SCR_SLE_SLP);
break;
case HAL_PM_AWAKE:
- if (!set_chip)
+ if (set_chip == AH_FALSE)
goto commit;
AR5K_REG_WRITE(AR5K_AR5210_SCR, AR5K_AR5210_SCR_SLE_WAKE);
+ AR5K_DELAY(2000);
for (i = 5000; i > 0; i--) {
/* Check if the AR5210 did wake up */
@@ -2318,12 +2396,6 @@ HAL_BOOL
ar5k_ar5210_get_capabilities(hal)
struct ath_hal *hal;
{
- /*
- * Get the value stored in the EEPROM
- */
- if (ar5k_ar5210_eeprom_init(hal) != 0)
- return (AH_FALSE);
-
/* Set number of supported TX queues */
hal->ah_capabilities.cap_queues.q_tx_num = AR5K_AR5210_TX_NUM_QUEUES;
@@ -2366,81 +2438,10 @@ ar5k_ar5210_radar_alert(hal, enable)
AR5K_REG_WRITE(AR5K_AR5210_IER, AR5K_AR5210_IER_ENABLE);
}
-HAL_BOOL
-ar5k_ar5210_regulation_domain(hal, write, regdomain)
- struct ath_hal *hal;
- HAL_BOOL write;
- ieee80211_regdomain_t *regdomain;
-{
- /* Read current value */
- if (write != AH_TRUE) {
- memcpy(regdomain,
- &hal->ah_capabilities.cap_regdomain.reg_current,
- sizeof(ieee80211_regdomain_t));
- return (AH_TRUE);
- }
-
- /* Try to write a new value */
- memcpy(&hal->ah_capabilities.cap_regdomain.reg_current, regdomain,
- sizeof(ieee80211_regdomain_t));
-
- if (hal->ah_capabilities.cap_eeprom.ee_protect &
- AR5K_AR5210_EEPROM_PROTECT_128_191)
- return (AH_FALSE);
-
- hal->ah_capabilities.cap_eeprom.ee_regdomain =
- ar5k_regdomain_from_ieee(regdomain);
-
- AR5K_PRINTF("writing new regulation domain to EEPROM: 0x%04x\n",
- hal->ah_capabilities.cap_eeprom.ee_regdomain);
-
- if (ar5k_ar5210_eeprom_write(hal, AR5K_AR5210_EEPROM_REG_DOMAIN,
- hal->ah_capabilities.cap_eeprom.ee_regdomain) != 0)
- return (AH_FALSE);
-
- return (AH_TRUE);
-}
-
/*
* EEPROM access functions
*/
-int
-ar5k_ar5210_eeprom_init(hal)
- struct ath_hal *hal;
-{
- int ret;
-
- /* Check if EEPROM is busy */
- if (ar5k_ar5210_eeprom_is_busy(hal) == AH_TRUE)
- return (EBUSY);
-
- /*
- * Read values from EEPROM and store them in the capability structure
- */
- if ((ret = ar5k_ar5210_eeprom_read(hal, AR5K_AR5210_EEPROM_MAGIC,
- &hal->ah_capabilities.cap_eeprom.ee_magic)) != 0)
- return (ret);
-
- if (hal->ah_capabilities.cap_eeprom.ee_magic !=
- AR5K_AR5210_EEPROM_MAGIC_VALUE)
- return (EFTYPE);
-
- if ((ret = ar5k_ar5210_eeprom_read(hal, AR5K_AR5210_EEPROM_INFO_VERSION,
- &hal->ah_capabilities.cap_eeprom.ee_version)) != 0)
- return (ret);
-
- if ((ret = ar5k_ar5210_eeprom_read(hal, AR5K_AR5210_EEPROM_PROTECT,
- &hal->ah_capabilities.cap_eeprom.ee_protect)) != 0)
- return (ret);
-
- if ((ret = ar5k_ar5210_eeprom_read(hal, AR5K_AR5210_EEPROM_REG_DOMAIN,
- &hal->ah_capabilities.cap_eeprom.ee_regdomain)) != 0)
- return (ret);
-
- return (0);
-}
-
HAL_BOOL
ar5k_ar5210_eeprom_is_busy(hal)
struct ath_hal *hal;
diff --git a/sys/dev/ic/ar5210reg.h b/sys/dev/ic/ar5210reg.h
index 49296f3f697..d1f68d0b5b3 100644
--- a/sys/dev/ic/ar5210reg.h
+++ b/sys/dev/ic/ar5210reg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ar5210reg.h,v 1.4 2004/11/03 19:44:12 reyk Exp $ */
+/* $OpenBSD: ar5210reg.h,v 1.5 2004/12/31 01:00:23 reyk Exp $ */
/*
* Copyright (c) 2004 Reyk Floeter <reyk@vantronix.net>.
@@ -341,20 +341,6 @@ typedef enum {
#define AR5K_AR5210_EEPROM_STAT_WRDONE 0x0008
/*
- * AR5210 EEPROM data registers
- */
-#define AR5K_AR5210_EEPROM_MAGIC 0x3d
-#define AR5K_AR5210_EEPROM_MAGIC_VALUE 0x5aa5
-#define AR5K_AR5210_EEPROM_PROTECT 0x3f
-#define AR5K_AR5210_EEPROM_PROTECT_128_191 0x80
-#define AR5K_AR5210_EEPROM_REG_DOMAIN 0xbf
-#define AR5K_AR5210_EEPROM_INFO_BASE 0xc0
-#define AR5K_AR5210_EEPROM_INFO_VERSION \
- (AR5K_AR5210_EEPROM_INFO_BASE + 1)
-#define AR5K_AR5210_EEPROM_INFO_MAX \
- (0x400 - AR5K_AR5210_EEPROM_INFO_BASE)
-
-/*
* PCU registers
*/
@@ -672,11 +658,53 @@ typedef enum {
#define AR5K_AR5210_PHY_DISABLE 0x00000002
/*
+ * PHY signal register
+ */
+#define AR5K_AR5210_PHY_SIG 0x9858
+#define AR5K_AR5210_PHY_SIG_FIRSTEP 0x0003f000
+#define AR5K_AR5210_PHY_SIG_FIRSTEP_S 12
+#define AR5K_AR5210_PHY_SIG_FIRPWR 0x03fc0000
+#define AR5K_AR5210_PHY_SIG_FIRPWR_S 18
+
+/*
+ * PHY coarse agility control register
+ */
+#define AR5K_AR5210_PHY_AGCCOARSE 0x985c
+#define AR5K_AR5210_PHY_AGCCOARSE_LO 0x00007f80
+#define AR5K_AR5210_PHY_AGCCOARSE_LO_S 7
+#define AR5K_AR5210_PHY_AGCCOARSE_HI 0x003f8000
+#define AR5K_AR5210_PHY_AGCCOARSE_HI_S 15
+
+/*
* PHY agility control register
*/
#define AR5K_AR5210_PHY_AGCCTL 0x9860
-#define AR5K_AR5210_PHY_AGC_CAL 0x00000001
-#define AR5K_AR5210_PHY_AGC_NF 0x00000002
+#define AR5K_AR5210_PHY_AGCCTL_CAL 0x00000001
+#define AR5K_AR5210_PHY_AGCCTL_NF 0x00000002
+
+/*
+ * PHY noise floor status register
+ */
+#define AR5K_AR5210_PHY_NF 0x9864
+#define AR5K_AR5210_PHY_NF_M 0x000001ff
+#define AR5K_AR5210_PHY_NF_ACTIVE 0x00000100
+#define AR5K_AR5210_PHY_NF_RVAL(_n) (((_n) >> 19) & AR5K_AR5210_PHY_NF_M)
+#define AR5K_AR5210_PHY_NF_AVAL(_n) (-((_n) ^ AR5K_AR5210_PHY_NF_M) + 1)
+
+/*
+ * PHY ADC saturation register
+ */
+#define AR5K_AR5210_PHY_ADCSAT 0x9868
+#define AR5K_AR5210_PHY_ADCSAT_ICNT 0x0001f800
+#define AR5K_AR5210_PHY_ADCSAT_ICNT_S 11
+#define AR5K_AR5210_PHY_ADCSAT_THR 0x000007e0
+#define AR5K_AR5210_PHY_ADCSAT_THR_S 5
+
+/*
+ * PHY RF stage register
+ */
+#define AR5K_AR5210_PHY_RFSTG 0x98d4
+#define AR5K_AR5210_PHY_RFSTG_DISABLE 0x00000021
/*
* Misc PHY/radio registers
diff --git a/sys/dev/ic/ar5210var.h b/sys/dev/ic/ar5210var.h
index 604cb888f60..10de004b69c 100644
--- a/sys/dev/ic/ar5210var.h
+++ b/sys/dev/ic/ar5210var.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ar5210var.h,v 1.4 2004/11/08 16:48:25 reyk Exp $ */
+/* $OpenBSD: ar5210var.h,v 1.5 2004/12/31 01:00:23 reyk Exp $ */
/*
* Copyright (c) 2004 Reyk Floeter <reyk@vantronix.net>.
@@ -231,10 +231,10 @@ extern ar5k_attach_t ar5k_ar5210_attach;
{ AR5K_AR5210_TXDP1, 0 }, \
{ AR5K_AR5210_RXDP, 0 }, \
{ AR5K_AR5210_CR, 0 }, \
- { AR5K_AR5210_ISR, 0, INI_READ }, \
+ { AR5K_AR5210_ISR, 0, AR5K_INI_READ }, \
{ AR5K_AR5210_IMR, 0 }, \
{ AR5K_AR5210_IER, AR5K_AR5210_IER_DISABLE }, \
- { AR5K_AR5210_BSR, 0, INI_READ }, \
+ { AR5K_AR5210_BSR, 0, AR5K_INI_READ }, \
{ AR5K_AR5210_TXCFG, AR5K_AR5210_DMASIZE_128B }, \
{ AR5K_AR5210_RXCFG, AR5K_AR5210_DMASIZE_128B }, \
{ AR5K_AR5210_CFG, AR5K_AR5210_INIT_CFG }, \
diff --git a/sys/dev/ic/ar5xxx.c b/sys/dev/ic/ar5xxx.c
index ec0b6777fa9..8b8ad0b8f53 100644
--- a/sys/dev/ic/ar5xxx.c
+++ b/sys/dev/ic/ar5xxx.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ar5xxx.c,v 1.5 2004/11/11 20:11:28 reyk Exp $ */
+/* $OpenBSD: ar5xxx.c,v 1.6 2004/12/31 01:00:23 reyk Exp $ */
/*
* Copyright (c) 2004 Reyk Floeter <reyk@vantronix.net>.
@@ -27,7 +27,7 @@
/*
* HAL interface for Atheros Wireless LAN devices.
- * (Please have a look at ar5k.h for further information)
+ * (Please have a look at ar5xxx.h for further information)
*/
#include <dev/pci/pcidevs.h>
@@ -35,7 +35,6 @@
#include <dev/ic/ar5xxx.h>
extern ar5k_attach_t ar5k_ar5210_attach;
-
#ifdef notyet
extern ar5k_attach_t ar5k_ar5211_attach;
extern ar5k_attach_t ar5k_ar5212_attach;
@@ -61,6 +60,7 @@ static const struct {
ar5k_ar5210_attach },
{ PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5210_DEFAULT,
ar5k_ar5210_attach },
+
#ifdef notyet
{ PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5211,
ar5k_ar5211_attach },
@@ -85,8 +85,32 @@ static const struct {
{ PCI_VENDOR_3COM2, PCI_PRODUCT_3COM2_3CRPAG175,
ar5k_ar5212_attach },
#endif
+
};
+int ar5k_eeprom_read_ants(struct ath_hal *, u_int32_t *, u_int);
+int ar5k_eeprom_read_modes(struct ath_hal *, u_int32_t *, u_int);
+u_int16_t ar5k_eeprom_bin2freq(struct ath_hal *, u_int16_t, u_int);
+
+HAL_BOOL ar5k_ar5110_channel(struct ath_hal *, HAL_CHANNEL *);
+HAL_BOOL ar5k_ar5110_chan2athchan(HAL_CHANNEL *);
+HAL_BOOL ar5k_ar5111_channel(struct ath_hal *, HAL_CHANNEL *);
+HAL_BOOL ar5k_ar5111_chan2athchan(u_int, struct ar5k_athchan_2ghz *);
+HAL_BOOL ar5k_ar5112_channel(struct ath_hal *, HAL_CHANNEL *);
+
+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);
+
+/*
+ * 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;
+
/*
* Perform a lookup if the device is supported by the HAL
*/
@@ -120,10 +144,12 @@ ath_hal_attach(device, sc, st, sh, status)
bus_space_handle_t sh;
int *status;
{
+ ieee80211_regdomain_t ieee_regdomain;
HAL_RATE_TABLE rt_11a = AR5K_RATES_11A;
HAL_RATE_TABLE rt_11b = AR5K_RATES_11B;
HAL_RATE_TABLE rt_11g = AR5K_RATES_11G;
HAL_RATE_TABLE rt_turbo = AR5K_RATES_TURBO;
+ u_int16_t regdomain;
struct ath_hal *hal = NULL;
ar5k_attach_t *attach = NULL;
u_int8_t mac[IEEE80211_ADDR_LEN];
@@ -166,16 +192,19 @@ ath_hal_attach(device, sc, st, sh, status)
*/
hal->ah_abi = HAL_ABI_VERSION;
hal->ah_country_code = CTRY_DEFAULT;
+ hal->ah_capabilities.cap_regdomain.reg_current = AR5K_TUNE_REGDOMAIN;
hal->ah_op_mode = HAL_M_STA;
hal->ah_radar.r_enabled = AR5K_TUNE_RADAR_ALERT;
- hal->ah_capabilities.cap_eeprom.ee_regdomain = DMN_DEFAULT;
hal->ah_turbo = AH_FALSE;
+ hal->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER;
+ hal->ah_txpower.txp_max = AR5K_TUNE_MAX_TXPOWER;
hal->ah_imr = 0;
hal->ah_atim_window = 0;
hal->ah_aifs = AR5K_TUNE_AIFS;
hal->ah_cw_min = AR5K_TUNE_CWMIN;
hal->ah_limit_tx_retries = AR5K_INIT_TX_RETRY;
hal->ah_software_retry = AH_FALSE;
+ hal->ah_ant_diversity = AR5K_TUNE_ANT_DIVERSITY;
if (attach(device, hal, st, sh, status) == NULL)
goto failed;
@@ -184,12 +213,36 @@ ath_hal_attach(device, sc, st, sh, status)
* Get card capabilities, values, ...
*/
+ if (ar5k_eeprom_init(hal) != 0) {
+ AR5K_PRINT("unable to init EEPROM\n");
+ goto failed;
+ }
+
+ /* Set regulation domain */
+ if ((regdomain =
+ (u_int16_t)hal->ah_capabilities.cap_eeprom.ee_regdomain) != 0) {
+ ieee_regdomain = *ar5k_regdomain_to_ieee(regdomain);
+ memcpy(&hal->ah_capabilities.cap_regdomain.reg_current,
+ &ieee_regdomain, sizeof(ieee80211_regdomain_t));
+ } else {
+ ieee_regdomain =
+ hal->ah_capabilities.cap_regdomain.reg_current;
+
+ /* Try to write default regulation domain to EEPROM */
+ ar5k_eeprom_regulation_domain(hal, AH_TRUE, &ieee_regdomain);
+ }
+
+ memcpy(&hal->ah_capabilities.cap_regdomain.reg_hw,
+ &ieee_regdomain, sizeof(ieee80211_regdomain_t));
+
+ /* Get misc capabilities */
if (hal->ah_get_capabilities(hal) != AH_TRUE) {
AR5K_PRINTF("unable to get device capabilities: 0x%04x\n",
device);
goto failed;
}
+ /* Get MAC address */
if ((*status = ar5k_eeprom_read_mac(hal, mac)) != HAL_OK) {
AR5K_PRINTF("unable to read address from EEPROM: 0x%04x\n",
device);
@@ -198,6 +251,7 @@ ath_hal_attach(device, sc, st, sh, status)
hal->ah_setMacAddress(hal, mac);
+ /* Get rate tables */
if (hal->ah_capabilities.cap_mode & HAL_MODE_11A)
ar5k_rt_copy(&hal->ah_rt_11a, &rt_11a);
if (hal->ah_capabilities.cap_mode & HAL_MODE_11B)
@@ -419,60 +473,19 @@ ar5k_radar_alert(hal)
hal->ah_radar.r_last_alert, hal->ah_current_channel.channel);
}
-int
-ar5k_eeprom_read_mac(hal, mac)
- struct ath_hal *hal;
- u_int8_t *mac;
-{
- u_int32_t total, offset;
- u_int16_t data;
- int octet;
- u_int8_t mac_d[IEEE80211_ADDR_LEN];
-
- bzero(mac, IEEE80211_ADDR_LEN);
- bzero(&mac_d, IEEE80211_ADDR_LEN);
-
- if (hal->ah_eeprom_is_busy(hal))
- return (EBUSY);
-
- /*
- * XXX Does this work with newer EEPROMs?
- */
- if (hal->ah_eeprom_read(hal, 0x20, &data) != 0)
- return (EIO);
-
- for (offset = 0x1f, octet = 0, total = 0;
- offset >= 0x1d; offset--) {
- if (hal->ah_eeprom_read(hal, offset, &data) != 0)
- return (EIO);
-
- total += data;
- mac_d[octet + 1] = data & 0xff;
- mac_d[octet] = data >> 8;
- octet += 2;
- }
-
- memcpy(mac, &mac_d, IEEE80211_ADDR_LEN);
-
- if ((!total) || total == (3 * 0xffff))
- return (EINVAL);
-
- return (0);
-}
-
-u_int8_t
+u_int16_t
ar5k_regdomain_from_ieee(regdomain)
ieee80211_regdomain_t *regdomain;
{
/*
* XXX Fix
*/
- return ((u_int8_t)*regdomain);
+ return ((u_int16_t)*regdomain);
}
ieee80211_regdomain_t *
ar5k_regdomain_to_ieee(regdomain)
- u_int8_t regdomain;
+ u_int16_t regdomain;
{
/*
* XXX Fix
@@ -530,11 +543,13 @@ ar5k_register_timeout(hal, reg, flag, val, is_set)
HAL_BOOL is_set;
{
int i;
+ u_int32_t data;
for (i = AR5K_TUNE_REGISTER_TIMEOUT; i > 0; i--) {
- if ((is_set == AH_TRUE) && (AR5K_REG_READ(reg) & flag))
+ data = AR5K_REG_READ(reg);
+ if ((is_set == AH_TRUE) && (data & flag))
break;
- else if ((AR5K_REG_READ(reg) & flag) == val)
+ else if ((data & flag) == val)
break;
AR5K_DELAY(15);
}
@@ -544,3 +559,874 @@ ar5k_register_timeout(hal, reg, flag, val, is_set)
return (AH_TRUE);
}
+
+/*
+ * Common ar5xx EEPROM access functions
+ */
+
+u_int16_t
+ar5k_eeprom_bin2freq(hal, bin, mode)
+ struct ath_hal *hal;
+ u_int16_t bin;
+ u_int mode;
+{
+ u_int16_t val;
+
+ if (bin == AR5K_EEPROM_CHANNEL_DIS)
+ return (bin);
+
+ if (mode == AR5K_EEPROM_MODE_11A) {
+ if (hal->ah_ee_version > AR5K_EEPROM_VERSION_3_2)
+ val = (5 * bin) + 4800;
+ else
+ val = bin > 62 ?
+ (10 * 62) + (5 * (bin - 62)) + 5100 :
+ (bin * 10) + 5100;
+ } else {
+ if (hal->ah_ee_version > AR5K_EEPROM_VERSION_3_2)
+ val = bin + 2300;
+ else
+ val = bin + 2400;
+ }
+
+ return (val);
+}
+
+#define EEPROM_READ_VAL(_o, _v) { \
+ if ((ret = hal->ah_eeprom_read(hal, (_o), \
+ &(_v))) != 0) \
+ return (ret); \
+}
+
+#define EEPROM_READ_HDR(_o, _v) { \
+ if ((ret = hal->ah_eeprom_read(hal, (_o), \
+ &hal->ah_capabilities.cap_eeprom.##_v)) != 0) \
+ return (ret); \
+}
+
+int
+ar5k_eeprom_read_ants(hal, offset, mode)
+ struct ath_hal *hal;
+ u_int32_t *offset;
+ u_int mode;
+{
+ struct ar5k_eeprom_info *ee = &hal->ah_capabilities.cap_eeprom;
+ u_int32_t o = *offset;
+ u_int16_t val;
+ int ret, i = 0;
+
+ EEPROM_READ_VAL(o++, val);
+ ee->ee_switch_settling[mode] = (val >> 8) & 0x7f;
+ ee->ee_ant_tx_rx[mode] = (val >> 2) & 0x3f;
+ ee->ee_ant_control[mode][i] = (val << 4) & 0x3f;
+
+ EEPROM_READ_VAL(o++, val);
+ ee->ee_ant_control[mode][i++] |= (val >> 12) & 0xf;
+ ee->ee_ant_control[mode][i++] = (val >> 6) & 0x3f;
+ ee->ee_ant_control[mode][i++] = val & 0x3f;
+
+ EEPROM_READ_VAL(o++, val);
+ ee->ee_ant_control[mode][i++] = (val >> 10) & 0x3f;
+ ee->ee_ant_control[mode][i++] = (val >> 4) & 0x3f;
+ ee->ee_ant_control[mode][i] = (val << 2) & 0x3f;
+
+ EEPROM_READ_VAL(o++, val);
+ ee->ee_ant_control[mode][i++] |= (val >> 14) & 0x3;
+ ee->ee_ant_control[mode][i++] = (val >> 8) & 0x3f;
+ ee->ee_ant_control[mode][i++] = (val >> 2) & 0x3f;
+ ee->ee_ant_control[mode][i] = (val << 4) & 0x3f;
+
+ EEPROM_READ_VAL(o++, val);
+ ee->ee_ant_control[mode][i++] |= (val >> 12) & 0xf;
+ ee->ee_ant_control[mode][i++] = (val >> 6) & 0x3f;
+ ee->ee_ant_control[mode][i++] = val & 0x3f;
+
+ /* Get antenna modes */
+ hal->ah_antenna[mode][0] =
+ (ee->ee_ant_control[mode][0] << 4) | 0x1;
+ hal->ah_antenna[mode][HAL_ANT_FIXED_A] =
+ ee->ee_ant_control[mode][1] |
+ (ee->ee_ant_control[mode][2] << 6) |
+ (ee->ee_ant_control[mode][3] << 12) |
+ (ee->ee_ant_control[mode][4] << 18) |
+ (ee->ee_ant_control[mode][5] << 24);
+ hal->ah_antenna[mode][HAL_ANT_FIXED_B] =
+ ee->ee_ant_control[mode][6] |
+ (ee->ee_ant_control[mode][7] << 6) |
+ (ee->ee_ant_control[mode][8] << 12) |
+ (ee->ee_ant_control[mode][9] << 18) |
+ (ee->ee_ant_control[mode][10] << 24);
+
+ /* return new offset */
+ *offset = o;
+
+ return (0);
+}
+
+int
+ar5k_eeprom_read_modes(hal, offset, mode)
+ struct ath_hal *hal;
+ u_int32_t *offset;
+ u_int mode;
+{
+ struct ar5k_eeprom_info *ee = &hal->ah_capabilities.cap_eeprom;
+ u_int32_t o = *offset;
+ u_int16_t val;
+ int ret;
+
+ EEPROM_READ_VAL(o++, val);
+ ee->ee_tx_end2xlna_enable[mode] = (val >> 8) & 0xff;
+ ee->ee_thr_62[mode] = val & 0xff;
+
+ if (hal->ah_ee_version <= AR5K_EEPROM_VERSION_3_2)
+ ee->ee_thr_62[mode] =
+ mode == AR5K_EEPROM_MODE_11A ? 15 : 28;
+
+ EEPROM_READ_VAL(o++, val);
+ ee->ee_tx_end2xpa_disable[mode] = (val >> 8) & 0xff;
+ ee->ee_tx_frm2xpa_enable[mode] = val & 0xff;
+
+ EEPROM_READ_VAL(o++, val);
+ ee->ee_pga_desired_size[mode] = (val >> 8) & 0xff;
+
+ if ((val & 0xff) & 0x80)
+ ee->ee_noise_floor_thr[mode] = -((((val & 0xff) ^ 0xff)) + 1);
+ else
+ ee->ee_noise_floor_thr[mode] = val & 0xff;
+
+ if (hal->ah_ee_version <= AR5K_EEPROM_VERSION_3_2)
+ ee->ee_noise_floor_thr[mode] =
+ mode == AR5K_EEPROM_MODE_11A ? -54 : -1;
+
+ EEPROM_READ_VAL(o++, val);
+ ee->ee_xlna_gain[mode] = (val >> 5) & 0xff;
+ ee->ee_x_gain[mode] = (val >> 1) & 0xf;
+ ee->ee_xpd[mode] = val & 0x1;
+
+ if (hal->ah_ee_version >= AR5K_EEPROM_VERSION_4_0)
+ ee->ee_fixed_bias[mode] = (val >> 13) & 0x1;
+
+ if (hal->ah_ee_version >= AR5K_EEPROM_VERSION_3_3) {
+ EEPROM_READ_VAL(o++, val);
+ ee->ee_false_detect[mode] = (val >> 6) & 0x7f;
+
+ if (mode == AR5K_EEPROM_MODE_11A)
+ ee->ee_xr_power[mode] = val & 0x3f;
+ else {
+ ee->ee_ob[mode][0] = val & 0x7;
+ ee->ee_db[mode][0] = (val >> 3) & 0x7;
+ }
+ }
+
+ if (hal->ah_ee_version < AR5K_EEPROM_VERSION_3_4) {
+ ee->ee_i_gain[mode] = AR5K_EEPROM_I_GAIN;
+ ee->ee_cck_ofdm_power_delta = AR5K_EEPROM_CCK_OFDM_DELTA;
+ } else {
+ ee->ee_i_gain[mode] = (val >> 13) & 0x7;
+
+ EEPROM_READ_VAL(o++, val);
+ ee->ee_i_gain[mode] |= (val << 3) & 0x38;
+
+ if (mode == AR5K_EEPROM_MODE_11G)
+ ee->ee_cck_ofdm_power_delta = (val >> 3) & 0xff;
+ }
+
+ if (hal->ah_ee_version >= AR5K_EEPROM_VERSION_4_0 &&
+ mode == AR5K_EEPROM_MODE_11A) {
+ ee->ee_i_cal[mode] = (val >> 8) & 0x3f;
+ ee->ee_q_cal[mode] = (val >> 3) & 0x1f;
+ }
+
+ if (hal->ah_ee_version >= AR5K_EEPROM_VERSION_4_6 &&
+ mode == AR5K_EEPROM_MODE_11G)
+ ee->ee_scaled_cck_delta = (val >> 11) & 0x1f;
+
+ /* return new offset */
+ *offset = o;
+
+ return (0);
+}
+
+int
+ar5k_eeprom_init(hal)
+ struct ath_hal *hal;
+{
+ struct ar5k_eeprom_info *ee = &hal->ah_capabilities.cap_eeprom;
+ u_int32_t offset;
+ u_int16_t val;
+ int ret, i;
+ u_int mode;
+
+ /* Check if EEPROM is busy */
+ if (hal->ah_eeprom_is_busy(hal) == AH_TRUE)
+ return (EBUSY);
+
+ /* Initial TX thermal adjustment values */
+ ee->ee_tx_clip = 4;
+ ee->ee_pwd_84 = ee->ee_pwd_90 = 1;
+ ee->ee_gain_select = 1;
+
+ /*
+ * Read values from EEPROM and store them in the capability structure
+ */
+ EEPROM_READ_HDR(AR5K_EEPROM_MAGIC, ee_magic);
+ EEPROM_READ_HDR(AR5K_EEPROM_PROTECT, ee_protect);
+ EEPROM_READ_HDR(AR5K_EEPROM_REG_DOMAIN, ee_regdomain);
+ EEPROM_READ_HDR(AR5K_EEPROM_VERSION, ee_version);
+ EEPROM_READ_HDR(AR5K_EEPROM_HDR, ee_header);
+
+ /* Return if we have an old EEPROM */
+ if (hal->ah_ee_version < AR5K_EEPROM_VERSION_3_0)
+ return (0);
+
+ EEPROM_READ_HDR(AR5K_EEPROM_ANT_GAIN(hal->ah_ee_version), ee_ant_gain);
+
+ if (hal->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) {
+ EEPROM_READ_HDR(AR5K_EEPROM_MISC0, ee_misc0);
+ EEPROM_READ_HDR(AR5K_EEPROM_MISC1, ee_misc1);
+ }
+
+ if (hal->ah_ee_version < AR5K_EEPROM_VERSION_3_3) {
+ EEPROM_READ_VAL(AR5K_EEPROM_OBDB0_2GHZ, val);
+ ee->ee_ob[AR5K_EEPROM_MODE_11B][0] = val & 0x7;
+ ee->ee_db[AR5K_EEPROM_MODE_11B][0] = (val >> 3) & 0x7;
+
+ EEPROM_READ_VAL(AR5K_EEPROM_OBDB1_2GHZ, val);
+ ee->ee_ob[AR5K_EEPROM_MODE_11G][0] = val & 0x7;
+ ee->ee_db[AR5K_EEPROM_MODE_11G][0] = (val >> 3) & 0x7;
+ }
+
+ /*
+ * Get conformance test limit values
+ */
+ offset = AR5K_EEPROM_CTL(hal->ah_ee_version);
+ ee->ee_ctls = AR5K_EEPROM_N_CTLS(hal->ah_ee_version);
+
+ for (i = 0; i < ee->ee_ctls; i++) {
+ EEPROM_READ_VAL(offset++, val);
+ ee->ee_ctl[i] = (val >> 8) & 0xff;
+ ee->ee_ctl[i + 1] = val & 0xff;
+ }
+
+ /*
+ * Get values for 802.11a (5GHz)
+ */
+ mode = AR5K_EEPROM_MODE_11A;
+
+ ee->ee_turbo_max_power[mode] =
+ AR5K_EEPROM_HDR_T_5GHZ_DBM(ee->ee_header);
+
+ offset = AR5K_EEPROM_MODES_11A(hal->ah_ee_version);
+
+ if ((ret = ar5k_eeprom_read_ants(hal, &offset, mode)) != 0)
+ return (ret);
+
+ EEPROM_READ_VAL(offset++, val);
+ ee->ee_adc_desired_size[mode] = (int8_t)((val >> 8) & 0xff);
+ ee->ee_ob[mode][3] = (val >> 5) & 0x7;
+ ee->ee_db[mode][3] = (val >> 2) & 0x7;
+ ee->ee_ob[mode][2] = (val << 1) & 0x7;
+
+ EEPROM_READ_VAL(offset++, val);
+ ee->ee_ob[mode][2] |= (val >> 15) & 0x1;
+ ee->ee_db[mode][2] = (val >> 12) & 0x7;
+ ee->ee_ob[mode][1] = (val >> 9) & 0x7;
+ ee->ee_db[mode][1] = (val >> 6) & 0x7;
+ ee->ee_ob[mode][0] = (val >> 3) & 0x7;
+ ee->ee_db[mode][0] = val & 0x7;
+
+ if ((ret = ar5k_eeprom_read_modes(hal, &offset, mode)) != 0)
+ return (ret);
+
+ if (hal->ah_ee_version >= AR5K_EEPROM_VERSION_4_1) {
+ EEPROM_READ_VAL(offset++, val);
+ ee->ee_margin_tx_rx[mode] = val & 0x3f;
+ }
+
+ /*
+ * Get values for 802.11b (2.4GHz)
+ */
+ mode = AR5K_EEPROM_MODE_11B;
+ offset = AR5K_EEPROM_MODES_11B(hal->ah_ee_version);
+
+ if ((ret = ar5k_eeprom_read_ants(hal, &offset, mode)) != 0)
+ return (ret);
+
+ EEPROM_READ_VAL(offset++, val);
+ ee->ee_adc_desired_size[mode] = (int8_t)((val >> 8) & 0xff);
+ ee->ee_ob[mode][1] = (val >> 4) & 0x7;
+ ee->ee_db[mode][1] = val & 0x7;
+
+ if ((ret = ar5k_eeprom_read_modes(hal, &offset, mode)) != 0)
+ return (ret);
+
+ if (hal->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) {
+ EEPROM_READ_VAL(offset++, val);
+ ee->ee_cal_pier[mode][0] =
+ ar5k_eeprom_bin2freq(hal, val & 0xff, mode);
+ ee->ee_cal_pier[mode][1] =
+ ar5k_eeprom_bin2freq(hal, (val >> 8) & 0xff, mode);
+
+ EEPROM_READ_VAL(offset++, val);
+ ee->ee_cal_pier[mode][2] =
+ ar5k_eeprom_bin2freq(hal, val & 0xff, mode);
+ }
+
+ if (hal->ah_ee_version >= AR5K_EEPROM_VERSION_4_1) {
+ ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f;
+ }
+
+ /*
+ * Get values for 802.11g (2.4GHz)
+ */
+ mode = AR5K_EEPROM_MODE_11G;
+ offset = AR5K_EEPROM_MODES_11G(hal->ah_ee_version);
+
+ if ((ret = ar5k_eeprom_read_ants(hal, &offset, mode)) != 0)
+ return (ret);
+
+ EEPROM_READ_VAL(offset++, val);
+ ee->ee_adc_desired_size[mode] = (int8_t)((val >> 8) & 0xff);
+ ee->ee_ob[mode][1] = (val >> 4) & 0x7;
+ ee->ee_db[mode][1] = val & 0x7;
+
+ if ((ret = ar5k_eeprom_read_modes(hal, &offset, mode)) != 0)
+ return (ret);
+
+ if (hal->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) {
+ EEPROM_READ_VAL(offset++, val);
+ ee->ee_cal_pier[mode][0] =
+ ar5k_eeprom_bin2freq(hal, val & 0xff, mode);
+ ee->ee_cal_pier[mode][1] =
+ ar5k_eeprom_bin2freq(hal, (val >> 8) & 0xff, mode);
+
+ EEPROM_READ_VAL(offset++, val);
+ ee->ee_turbo_max_power[mode] = val & 0x7f;
+ ee->ee_xr_power[mode] = (val >> 7) & 0x3f;
+
+ EEPROM_READ_VAL(offset++, val);
+ ee->ee_cal_pier[mode][2] =
+ ar5k_eeprom_bin2freq(hal, val & 0xff, mode);
+
+ if (hal->ah_ee_version >= AR5K_EEPROM_VERSION_4_1) {
+ ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f;
+ }
+
+ EEPROM_READ_VAL(offset++, val);
+ ee->ee_i_cal[mode] = (val >> 8) & 0x3f;
+ ee->ee_q_cal[mode] = (val >> 3) & 0x1f;
+
+ if (hal->ah_ee_version >= AR5K_EEPROM_VERSION_4_2) {
+ EEPROM_READ_VAL(offset++, val);
+ ee->ee_cck_ofdm_gain_delta = val & 0xff;
+ }
+ }
+
+ /*
+ * Read 5GHz EEPROM channels
+ */
+
+ return (0);
+}
+
+#undef EEPROM_READ_VAL
+#undef EEPROM_READ_HDR
+
+int
+ar5k_eeprom_read_mac(hal, mac)
+ struct ath_hal *hal;
+ u_int8_t *mac;
+{
+ u_int32_t total, offset;
+ u_int16_t data;
+ int octet;
+ u_int8_t mac_d[IEEE80211_ADDR_LEN];
+
+ bzero(mac, IEEE80211_ADDR_LEN);
+ bzero(&mac_d, IEEE80211_ADDR_LEN);
+
+ if (hal->ah_eeprom_is_busy(hal))
+ return (EBUSY);
+
+ if (hal->ah_eeprom_read(hal, 0x20, &data) != 0)
+ return (EIO);
+
+ for (offset = 0x1f, octet = 0, total = 0;
+ offset >= 0x1d; offset--) {
+ if (hal->ah_eeprom_read(hal, offset, &data) != 0)
+ return (EIO);
+
+ total += data;
+ mac_d[octet + 1] = data & 0xff;
+ mac_d[octet] = data >> 8;
+ octet += 2;
+ }
+
+ memcpy(mac, &mac_d, IEEE80211_ADDR_LEN);
+
+ if ((!total) || total == (3 * 0xffff))
+ return (EINVAL);
+
+ return (0);
+}
+
+HAL_BOOL
+ar5k_eeprom_regulation_domain(hal, write, regdomain)
+ struct ath_hal *hal;
+ HAL_BOOL write;
+ ieee80211_regdomain_t *regdomain;
+{
+ /* Read current value */
+ if (write != AH_TRUE) {
+ memcpy(regdomain,
+ &hal->ah_capabilities.cap_regdomain.reg_current,
+ sizeof(ieee80211_regdomain_t));
+ return (AH_TRUE);
+ }
+
+ /* Try to write a new value */
+ memcpy(&hal->ah_capabilities.cap_regdomain.reg_current, regdomain,
+ sizeof(ieee80211_regdomain_t));
+
+ if (hal->ah_capabilities.cap_eeprom.ee_protect &
+ AR5K_EEPROM_PROTECT_WR_128_191)
+ return (AH_FALSE);
+
+ hal->ah_capabilities.cap_eeprom.ee_regdomain =
+ ar5k_regdomain_from_ieee(regdomain);
+
+ if (hal->ah_eeprom_write(hal, AR5K_EEPROM_REG_DOMAIN,
+ hal->ah_capabilities.cap_eeprom.ee_regdomain) != 0)
+ return (AH_FALSE);
+
+ return (AH_TRUE);
+}
+
+/*
+ * PHY/RF access functions
+ */
+
+HAL_BOOL
+ar5k_channel(hal, channel)
+ struct ath_hal *hal;
+ HAL_CHANNEL *channel;
+{
+ HAL_BOOL ret;
+ AR5K_TRACE;
+
+ /*
+ * Check bounds supported by the PHY
+ * (don't care about regulation restrictions at this point)
+ */
+ if ((channel->channel < hal->ah_capabilities.cap_range.range_2ghz_min ||
+ channel->channel > hal->ah_capabilities.cap_range.range_2ghz_max) &&
+ (channel->channel < hal->ah_capabilities.cap_range.range_5ghz_min ||
+ channel->channel > hal->ah_capabilities.cap_range.range_5ghz_max)) {
+ AR5K_PRINTF("channel out of supported range (%u MHz)\n",
+ channel->channel);
+ return (AH_FALSE);
+ }
+
+ /*
+ * Set the channel and wait
+ */
+ if (hal->ah_radio == AR5K_AR5110) {
+ ret = ar5k_ar5110_channel(hal, channel);
+ } else if (hal->ah_radio == AR5K_AR5111) {
+ ret = ar5k_ar5111_channel(hal, channel);
+ } else {
+ ret = ar5k_ar5112_channel(hal, channel);
+ }
+
+ if (ret == AH_FALSE)
+ return (ret);
+
+ hal->ah_current_channel.c_channel = channel->c_channel;
+ hal->ah_current_channel.c_channel_flags = channel->c_channel_flags;
+ hal->ah_turbo = channel->c_channel_flags == CHANNEL_T ?
+ AH_TRUE : AH_FALSE;
+
+ return (AH_TRUE);
+}
+
+u_int32_t
+ar5k_ar5110_chan2athchan(channel)
+ HAL_CHANNEL *channel;
+{
+ u_int32_t athchan;
+
+ /*
+ * Convert IEEE channel/MHz to an internal channel value used
+ * by the AR5210 chipset. This has not been verified with
+ * newer chipsets like the AR5212A who have a completely
+ * different RF/PHY part.
+ */
+ athchan = (ar5k_bitswap((ieee80211_mhz2ieee(channel->c_channel,
+ channel->c_channel_flags) - 24)
+ / 2, 5) << 1) | (1 << 6) | 0x1;
+
+ return (athchan);
+}
+
+HAL_BOOL
+ar5k_ar5110_channel(hal, channel)
+ struct ath_hal *hal;
+ HAL_CHANNEL *channel;
+{
+ u_int32_t data;
+
+ /*
+ * Set the channel and wait
+ */
+ data = ar5k_ar5110_chan2athchan(channel);
+ AR5K_PHY_WRITE(0x27, data);
+ AR5K_PHY_WRITE(0x30, 0);
+ AR5K_DELAY(1000);
+
+ return (AH_TRUE);
+}
+
+HAL_BOOL
+ar5k_ar5111_chan2athchan(ieee, athchan)
+ u_int ieee;
+ struct ar5k_athchan_2ghz *athchan;
+{
+ int channel;
+
+ /* Cast this value to catch negative channel numbers (>= -19) */
+ channel = (int)ieee;
+
+ /*
+ * Map 2GHz IEEE channel to 5GHz Atheros channel
+ */
+ if (channel <= 13) {
+ athchan->a2_athchan = 115 + channel;
+ athchan->a2_flags = 0x46;
+ } else if (channel == 14) {
+ athchan->a2_athchan = 124;
+ athchan->a2_flags = 0x44;
+ } else if (channel >= 15 && channel <= 26) {
+ athchan->a2_athchan = ((channel - 14) * 4) + 132;
+ athchan->a2_flags = 0x46;
+ } else
+ return (AH_FALSE);
+
+ return (AH_TRUE);
+}
+
+HAL_BOOL
+ar5k_ar5111_channel(hal, channel)
+ struct ath_hal *hal;
+ HAL_CHANNEL *channel;
+{
+ u_int ieee_channel, ath_channel;
+ u_int32_t data0, data1, clock;
+ struct ar5k_athchan_2ghz ath_channel_2ghz;
+
+ AR5K_TRACE;
+
+ /*
+ * Set the channel on the AR5111 radio
+ */
+ data0 = 0;
+ ath_channel = ieee_channel = ath_hal_mhz2ieee(channel->c_channel,
+ channel->c_channel_flags);
+
+ if (channel->c_channel_flags & IEEE80211_CHAN_2GHZ) {
+ /* Map 2GHz channel to 5GHz Atheros channel ID */
+ if (ar5k_ar5111_chan2athchan(ieee_channel,
+ &ath_channel_2ghz) == AH_FALSE)
+ return (AH_FALSE);
+
+ ath_channel = ath_channel_2ghz.a2_athchan;
+ data0 = ((ar5k_bitswap(ath_channel_2ghz.a2_flags, 8) & 0xff)
+ << 5) | (1 << 4);
+ }
+
+ if (ath_channel < 145 || !(ath_channel & 1)) {
+ clock = 1;
+ data1 = ((ar5k_bitswap(ath_channel - 24, 8) & 0xff) << 2)
+ | (clock << 1) | (1 << 10) | 1;
+ } else {
+ clock = 0;
+ data1 = ((ar5k_bitswap((ath_channel - 24) / 2, 8) & 0xff) << 2)
+ | (clock << 1) | (1 << 10) | 1;
+ }
+
+ AR5K_PHY_WRITE(0x27, (data1 & 0xff) | ((data0 & 0xff) << 8));
+ AR5K_PHY_WRITE(0x34, ((data1 >> 8) & 0xff) | (data0 & 0xff00));
+
+ return (AH_TRUE);
+}
+
+HAL_BOOL
+ar5k_ar5112_channel(hal, channel)
+ struct ath_hal *hal;
+ HAL_CHANNEL *channel;
+{
+ u_int32_t data, data0, data1, data2;
+ u_int16_t c;
+
+ AR5K_TRACE;
+
+ c = channel->c_channel;
+
+ /*
+ * Set the channel on the AR5112 or newer
+ */
+ if (c < 4800) {
+ if (!((c - 2224) % 5)) {
+ data0 = ((2 * (c - 704)) - 3040) / 10;
+ data1 = 1;
+ } else if (!((c - 2192) % 5)) {
+ data0 = ((2 * (c - 672)) - 3040) / 10;
+ data1 = 0;
+ } else
+ return (AH_FALSE);
+
+ data0 = ar5k_bitswap((data0 << 2) & 0xff, 8);
+ } else {
+ if (!(c % 20) && c >= 5120) {
+ data0 = ar5k_bitswap(((c - 4800) / 20 << 2), 8);
+ data2 = ar5k_bitswap(3, 2);
+ } else if (!(c % 10)) {
+ data0 = ar5k_bitswap(((c - 4800) / 10 << 1), 8);
+ data2 = ar5k_bitswap(2, 2);
+ } else if (!(c % 5)) {
+ data0 = ar5k_bitswap((c - 4800) / 5, 8);
+ data2 = ar5k_bitswap(1, 2);
+ } else
+ return (AH_FALSE);
+ }
+
+ data = (data0 << 4) | (data1 << 1) | (data2 << 2) | 0x1001;
+
+ AR5K_PHY_WRITE(0x27, data & 0xff);
+ AR5K_PHY_WRITE(0x36, (data >> 8) & 0x7f);
+
+ return (AH_TRUE);
+}
+
+int
+ar5k_rfregs_set(rf, offset, reg, bits, first, col)
+ u_int32_t *rf;
+ u_int32_t offset, reg, bits, first, col;
+{
+ u_int32_t tmp, mask, entry, last;
+ int32_t position, left;
+ int i;
+
+ if (!(col <= 3 && bits <= 32 && first + bits <= 319)) {
+ AR5K_PRINTF("invalid values at offset %u\n", offset);
+ return (-1);
+ }
+
+ 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++) {
+ 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;
+ left -= 8 - position;
+ tmp >>= (8 - position);
+ }
+
+ return (i);
+}
+
+HAL_BOOL
+ar5k_rfregs(hal, channel, mode)
+ struct ath_hal *hal;
+ HAL_CHANNEL *channel;
+ u_int mode;
+{
+ 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));
+}
+
+HAL_BOOL
+ar5k_ar5111_rfregs(hal, channel, mode)
+ struct ath_hal *hal;
+ HAL_CHANNEL *channel;
+ u_int mode;
+{
+ struct ar5k_eeprom_info *ee = &hal->ah_capabilities.cap_eeprom;
+ 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];
+
+ AR5K_ASSERT_ENTRY(mode, AR5K_INI_VAL_MAX);
+
+ /* Copy values to modify them */
+ for (i = 0; i < rf_size; i++) {
+ if (ar5111_rf[i].rf_bank >=
+ AR5K_AR5111_INI_RF_MAX_BANKS) {
+ AR5K_PRINT("invalid bank\n");
+ return (AH_FALSE);
+ }
+
+ if (bank != ar5111_rf[i].rf_bank) {
+ bank = ar5111_rf[i].rf_bank;
+ offset[bank] = i;
+ }
+
+ rf[i] = ar5111_rf[i].rf_value[mode];
+ }
+
+ if (channel->c_channel_flags & IEEE80211_CHAN_2GHZ) {
+ if (channel->c_channel_flags & IEEE80211_CHAN_B)
+ ee_mode = AR5K_EEPROM_MODE_11B;
+ else
+ 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)
+ return (AH_FALSE);
+
+ if (ar5k_rfregs_set(rf, offset[0],
+ ee->ee_ob[ee_mode][obdb], 3, 122, 0) < 0)
+ return (AH_FALSE);
+
+ obdb = 1;
+ } else {
+ /* For 11a, Turbo and XR */
+ ee_mode = AR5K_EEPROM_MODE_11A;
+ obdb = channel->c_channel >= 5725 ? 3 :
+ (channel->c_channel >= 5500 ? 2 :
+ (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)
+ return (AH_FALSE);
+
+ if (ar5k_rfregs_set(rf, offset[6],
+ ee->ee_pwd_90, 1, 45, 3) < 0)
+ return (AH_FALSE);
+ }
+
+ if (ar5k_rfregs_set(rf, offset[6],
+ !ee->ee_xpd[ee_mode], 1, 95, 0) < 0)
+ return (AH_FALSE);
+
+ if (ar5k_rfregs_set(rf, offset[6],
+ ee->ee_x_gain[ee_mode], 4, 96, 0) < 0)
+ return (AH_FALSE);
+
+ if (ar5k_rfregs_set(rf, offset[6],
+ obdb >= 0 ? ee->ee_ob[ee_mode][obdb] : 0, 3, 104, 0) < 0)
+ return (AH_FALSE);
+
+ if (ar5k_rfregs_set(rf, offset[6],
+ obdb >= 0 ? ee->ee_db[ee_mode][obdb] : 0, 3, 107, 0) < 0)
+ return (AH_FALSE);
+
+ if (ar5k_rfregs_set(rf, offset[7],
+ ee->ee_i_gain[ee_mode], 6, 29, 0) < 0)
+ return (AH_FALSE);
+
+ if (ar5k_rfregs_set(rf, offset[7],
+ ee->ee_xpd[ee_mode], 1, 4, 0) < 0)
+ return (AH_FALSE);
+
+ /* Write RF values */
+ for (i = 0; i < rf_size; i++) {
+ AR5K_REG_WRITE(ar5111_rf[i].rf_register, rf[i]);
+ AR5K_DELAY(1);
+ }
+
+ return (AH_TRUE);
+}
+
+HAL_BOOL
+ar5k_ar5112_rfregs(hal, channel, mode)
+ struct ath_hal *hal;
+ HAL_CHANNEL *channel;
+ u_int mode;
+{
+ struct ar5k_eeprom_info *ee = &hal->ah_capabilities.cap_eeprom;
+ 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];
+
+ AR5K_ASSERT_ENTRY(mode, AR5K_INI_VAL_MAX);
+
+ /* Copy values to modify them */
+ for (i = 0; i < rf_size; i++) {
+ if (ar5112_rf[i].rf_bank >=
+ AR5K_AR5112_INI_RF_MAX_BANKS) {
+ AR5K_PRINT("invalid bank\n");
+ return (AH_FALSE);
+ }
+
+ if (bank != ar5112_rf[i].rf_bank) {
+ bank = ar5112_rf[i].rf_bank;
+ offset[bank] = i;
+ }
+
+ rf[i] = ar5112_rf[i].rf_value[mode];
+ }
+
+ if (channel->c_channel_flags & IEEE80211_CHAN_2GHZ) {
+ if (channel->c_channel_flags & IEEE80211_CHAN_B)
+ ee_mode = AR5K_EEPROM_MODE_11B;
+ else
+ 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)
+ return (AH_FALSE);
+
+ if (ar5k_rfregs_set(rf, offset[6],
+ ee->ee_ob[ee_mode][obdb], 3, 290, 0) < 0)
+ return (AH_FALSE);
+ } else {
+ /* For 11a, Turbo and XR */
+ ee_mode = AR5K_EEPROM_MODE_11A;
+ obdb = channel->c_channel >= 5725 ? 3 :
+ (channel->c_channel >= 5500 ? 2 :
+ (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)
+ return (AH_FALSE);
+
+ if (ar5k_rfregs_set(rf, offset[6],
+ ee->ee_ob[ee_mode][obdb], 3, 282, 0) < 0)
+ 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);
+#endif
+
+ if (ar5k_rfregs_set(rf, offset[6],
+ ee->ee_xpd[ee_mode], 1, 302, 0) < 0)
+ return (AH_FALSE);
+
+ if (ar5k_rfregs_set(rf, offset[7],
+ ee->ee_i_gain[ee_mode], 6, 14, 0) < 0)
+ return (AH_FALSE);
+
+ /* Write RF values */
+ for (i = 0; i < rf_size; i++) {
+ AR5K_REG_WRITE(ar5112_rf[i].rf_register, rf[i]);
+ AR5K_DELAY(1);
+ }
+
+ return (AH_TRUE);
+}
diff --git a/sys/dev/ic/ar5xxx.h b/sys/dev/ic/ar5xxx.h
index a254cbb10ba..18a53abbaee 100644
--- a/sys/dev/ic/ar5xxx.h
+++ b/sys/dev/ic/ar5xxx.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ar5xxx.h,v 1.6 2004/11/23 10:13:04 reyk Exp $ */
+/* $OpenBSD: ar5xxx.h,v 1.7 2004/12/31 01:00:23 reyk Exp $ */
/*
* Copyright (c) 2004 Reyk Floeter <reyk@vantronix.net>.
@@ -67,9 +67,26 @@
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_compat.h>
+#include <net80211/ieee80211_radiotap.h>
#include <net80211/ieee80211_regdomain.h>
/*
+ * Possible chipsets (could appear in different combinations)
+ */
+
+enum ar5k_version {
+ AR5K_AR5210 = 0,
+ AR5K_AR5211 = 1,
+ AR5K_AR5212 = 2,
+};
+
+enum ar5k_radio {
+ AR5K_AR5110 = 0,
+ AR5K_AR5111 = 1,
+ AR5K_AR5112 = 2,
+};
+
+/*
* Generic definitions
*/
@@ -83,12 +100,19 @@ typedef enum {
HAL_MODE_TURBO = 0x002,
HAL_MODE_11B = 0x004,
HAL_MODE_PUREG = 0x008,
- HAL_MODE_11G = 0x008, /* 0x010 for dynamic OFDM/CCK */
+ HAL_MODE_11G = 0x010,
HAL_MODE_108G = 0x020,
HAL_MODE_ALL = 0xfff
} HAL_MODE;
typedef enum {
+ HAL_ANT_VARIABLE = 0,
+ HAL_ANT_FIXED_A = 1,
+ HAL_ANT_FIXED_B = 2,
+ HAL_ANT_MAX = 3,
+} HAL_ANT_SETTING;
+
+typedef enum {
HAL_M_STA = 1,
HAL_M_IBSS = 0,
HAL_M_HOSTAP = 6,
@@ -115,6 +139,14 @@ typedef enum {
#define HAL_NUM_TX_QUEUES 10
typedef enum {
+ HAL_TX_QUEUE_ID_DATA_MIN = 0,
+ HAL_TX_QUEUE_ID_DATA_MAX = 6,
+ HAL_TX_QUEUE_ID_PSPOLL = 7,
+ HAL_TX_QUEUE_ID_BEACON = 8,
+ HAL_TX_QUEUE_ID_CAB = 9,
+} HAL_TX_QUEUE_ID;
+
+typedef enum {
HAL_WME_AC_BK = 0,
HAL_WME_AC_BE = 1,
HAL_WME_AC_VI = 2,
@@ -128,6 +160,7 @@ typedef enum {
#define AR5K_TXQ_FLAG_COMPRESSION_ENABLE 0x0008
#define AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE 0x0010
#define AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE 0x0020
+#define AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS 0x0040
typedef struct {
u_int32_t tqi_ver;
@@ -215,15 +248,15 @@ typedef enum {
* RX definitions
*/
-#define HAL_RX_FILTER_UCAST 0x00000001
-#define HAL_RX_FILTER_MCAST 0x00000002
-#define HAL_RX_FILTER_BCAST 0x00000004
-#define HAL_RX_FILTER_CONTROL 0x00000008
-#define HAL_RX_FILTER_BEACON 0x00000010
-#define HAL_RX_FILTER_PROM 0x00000020
-#define HAL_RX_FILTER_PROBEREQ 0x00000080
-#define HAL_RX_FILTER_PHYERR 0x00000100
-#define HAL_RX_FILTER_PHYRADAR 0x00000200
+#define HAL_RX_FILTER_UCAST 0x00000001
+#define HAL_RX_FILTER_MCAST 0x00000002
+#define HAL_RX_FILTER_BCAST 0x00000004
+#define HAL_RX_FILTER_CONTROL 0x00000008
+#define HAL_RX_FILTER_BEACON 0x00000010
+#define HAL_RX_FILTER_PROM 0x00000020
+#define HAL_RX_FILTER_PROBEREQ 0x00000080
+#define HAL_RX_FILTER_PHYERR 0x00000100
+#define HAL_RX_FILTER_PHYRADAR 0x00000200
typedef struct {
u_int32_t ackrcv_bad;
@@ -237,9 +270,9 @@ typedef struct {
* Beacon/AP definitions
*/
-#define HAL_BEACON_PERIOD 0x0000ffff
-#define HAL_BEACON_ENA 0x00800000
-#define HAL_BEACON_RESET_TSF 0x01000000
+#define HAL_BEACON_PERIOD 0x0000ffff
+#define HAL_BEACON_ENA 0x00800000
+#define HAL_BEACON_RESET_TSF 0x01000000
typedef struct {
u_int32_t bs_next_beacon;
@@ -342,6 +375,28 @@ typedef struct {
{ 1, IEEE80211_T_OFDM, 54000, 12, 0, 108, 4 } } \
}
+#define AR5K_RATES_11B { 4, { 0 }, { \
+ { 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 }, { \
+ { 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 }, \
+ { 0, IEEE80211_T_OFDM, 6000, 11, 0, 12, 4 }, \
+ { 0, IEEE80211_T_OFDM, 9000, 15, 0, 18, 4 }, \
+ { 1, IEEE80211_T_OFDM, 12000, 10, 0, 24, 6 }, \
+ { 1, IEEE80211_T_OFDM, 18000, 14, 0, 36, 6 }, \
+ { 1, IEEE80211_T_OFDM, 24000, 9, 0, 48, 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 } } \
+}
+
#define AR5K_RATES_TURBO { 8, { 0 }, { \
{ 1, IEEE80211_T_TURBO, 6000, 11, 0, 140, 0 }, \
{ 1, IEEE80211_T_TURBO, 9000, 15, 0, 18, 0 }, \
@@ -353,10 +408,6 @@ typedef struct {
{ 1, IEEE80211_T_TURBO, 54000, 12, 0, 108, 4 } } \
}
-/* XXX TODO: 2GHz rates for 11b/11g */
-#define AR5K_RATES_11B { 0, }
-#define AR5K_RATES_11G { 0, }
-
typedef enum {
HAL_RFGAIN_INACTIVE = 0,
HAL_RFGAIN_READ_REQUESTED,
@@ -373,7 +424,7 @@ typedef struct {
} HAL_CHANNEL;
#define HAL_SLOT_TIME_9 9
-#define HAL_SLOT_TIME_20 20
+#define HAL_SLOT_TIME_20 20
#define HAL_SLOT_TIME_MAX ar5k_clocktoh(0xffff, hal->ah_turbo)
#define CHANNEL_A (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM)
@@ -384,6 +435,21 @@ typedef struct {
#define CHANNEL_TG (CHANNEL_PUREG | IEEE80211_CHAN_TURBO)
#define CHANNEL_XR (CHANNEL_A | IEEE80211_CHAN_XR)
+typedef enum {
+ HAL_CHIP_5GHZ = IEEE80211_CHAN_5GHZ,
+ HAL_CHIP_2GHZ = IEEE80211_CHAN_2GHZ,
+} HAL_CHIP;
+
+/*
+ * The following structure will be used to map 2GHz channels to
+ * 5GHz Atheros channels.
+ */
+
+struct ar5k_athchan_2ghz {
+ u_int32_t a2_flags;
+ u_int16_t a2_athchan;
+};
+
/*
* Regulation stuff
*/
@@ -394,9 +460,9 @@ typedef enum ieee80211_countrycode HAL_CTRY_CODE;
* HAL interrupt abstraction
*/
-#define HAL_INT_RX 0x00000001
-#define HAL_INT_RXDESC 0x00000002
-#define HAL_INT_RXNOFRM 0x00000008
+#define HAL_INT_RX 0x00000001
+#define HAL_INT_RXDESC 0x00000002
+#define HAL_INT_RXNOFRM 0x00000008
#define HAL_INT_RXEOL 0x00000010
#define HAL_INT_RXORN 0x00000020
#define HAL_INT_TX 0x00000040
@@ -434,6 +500,182 @@ typedef enum ieee80211_state HAL_LED_STATE;
#define HAL_LED_RUN IEEE80211_S_RUN
/*
+ * Common ar5xxx EEPROM data registers
+ */
+
+#define AR5K_EEPROM_MAGIC 0x003d
+#define AR5K_EEPROM_MAGIC_VALUE 0x5aa5
+#define AR5K_EEPROM_PROTECT 0x003f
+#define AR5K_EEPROM_PROTECT_RD_0_31 0x0001
+#define AR5K_EEPROM_PROTECT_WR_0_31 0x0002
+#define AR5K_EEPROM_PROTECT_RD_32_63 0x0004
+#define AR5K_EEPROM_PROTECT_WR_32_63 0x0008
+#define AR5K_EEPROM_PROTECT_RD_64_127 0x0010
+#define AR5K_EEPROM_PROTECT_WR_64_127 0x0020
+#define AR5K_EEPROM_PROTECT_RD_128_191 0x0040
+#define AR5K_EEPROM_PROTECT_WR_128_191 0x0080
+#define AR5K_EEPROM_PROTECT_RD_192_207 0x0100
+#define AR5K_EEPROM_PROTECT_WR_192_207 0x0200
+#define AR5K_EEPROM_PROTECT_RD_208_223 0x0400
+#define AR5K_EEPROM_PROTECT_WR_208_223 0x0800
+#define AR5K_EEPROM_PROTECT_RD_224_239 0x1000
+#define AR5K_EEPROM_PROTECT_WR_224_239 0x2000
+#define AR5K_EEPROM_PROTECT_RD_240_255 0x4000
+#define AR5K_EEPROM_PROTECT_WR_240_255 0x8000
+#define AR5K_EEPROM_REG_DOMAIN 0x00bf
+#define AR5K_EEPROM_INFO_BASE 0x00c0
+#define AR5K_EEPROM_INFO_MAX \
+ (0x400 - AR5K_EEPROM_INFO_BASE)
+#define AR5K_EEPROM_INFO(_n) (AR5K_EEPROM_INFO_BASE + (_n))
+
+#define AR5K_EEPROM_VERSION AR5K_EEPROM_INFO(1)
+#define AR5K_EEPROM_VERSION_3_0 0x3000
+#define AR5K_EEPROM_VERSION_3_1 0x3001
+#define AR5K_EEPROM_VERSION_3_2 0x3002
+#define AR5K_EEPROM_VERSION_3_3 0x3003
+#define AR5K_EEPROM_VERSION_3_4 0x3004
+#define AR5K_EEPROM_VERSION_4_0 0x4000
+#define AR5K_EEPROM_VERSION_4_1 0x4001
+#define AR5K_EEPROM_VERSION_4_2 0x4002
+#define AR5K_EEPROM_VERSION_4_3 0x4003
+#define AR5K_EEPROM_VERSION_4_6 0x4006
+#define AR5K_EEPROM_VERSION_4_7 0x3007
+
+#define AR5K_EEPROM_MODE_11A 0
+#define AR5K_EEPROM_MODE_11B 1
+#define AR5K_EEPROM_MODE_11G 2
+
+#define AR5K_EEPROM_HDR AR5K_EEPROM_INFO(2)
+#define AR5K_EEPROM_HDR_11A(_v) (((_v) >> AR5K_EEPROM_MODE_11A) & 0x1)
+#define AR5K_EEPROM_HDR_11B(_v) (((_v) >> AR5K_EEPROM_MODE_11B) & 0x1)
+#define AR5K_EEPROM_HDR_11G(_v) (((_v) >> AR5K_EEPROM_MODE_11G) & 0x1)
+#define AR5K_EEPROM_HDR_T_2GHZ_DIS(_v) (((_v) >> 3) & 0x1)
+#define AR5K_EEPROM_HDR_T_5GHZ_DBM(_v) (((_v) >> 4) & 0x7f)
+#define AR5K_EEPROM_HDR_DEVICE(_v) (((_v) >> 11) & 0x7)
+#define AR5K_EEPROM_HDR_T_5GHZ_DIS(_v) (((_v) >> 15) & 0x1)
+#define AR5K_EEPROM_HDR_RFKILL(_v) (((_v) >> 14) & 0x1)
+
+#define AR5K_EEPROM_RFKILL_GPIO_SEL 0x0000001c
+#define AR5K_EEPROM_RFKILL_GPIO_SEL_S 2
+#define AR5K_EEPROM_RFKILL_POLARITY 0x00000002
+#define AR5K_EEPROM_RFKILL_POLARITY_S 1
+
+/* Newer EEPROMs are using a different offset */
+#define AR5K_EEPROM_OFF(_v, _v3_0, _v3_3) \
+ (((_v) >= AR5K_EEPROM_VERSION_3_3) ? _v3_3 : _v3_0)
+
+#define AR5K_EEPROM_ANT_GAIN(_v) AR5K_EEPROM_OFF(_v, 0x00c4, 0x00c3)
+#define AR5K_EEPROM_ANT_GAIN_5GHZ(_v) ((int8_t)(((_v) >> 8) >> 0xff))
+#define AR5K_EEPROM_ANT_GAIN_2GHZ(_v) ((int8_t)((_v) & 0xff))
+
+#define AR5K_EEPROM_MODES_11A(_v) AR5K_EEPROM_OFF(_v, 0x00c5, 0x00d4)
+#define AR5K_EEPROM_MODES_11B(_v) AR5K_EEPROM_OFF(_v, 0x00d0, 0x00f2)
+#define AR5K_EEPROM_MODES_11G(_v) AR5K_EEPROM_OFF(_v, 0x00da, 0x010d)
+#define AR5K_EEPROM_CTL(_v) AR5K_EEPROM_OFF(_v, 0x00e4, 0x0128)
+
+/* Since 3.1 */
+#define AR5K_EEPROM_OBDB0_2GHZ 0x00ec
+#define AR5K_EEPROM_OBDB1_2GHZ 0x00ed
+
+/* Misc values available since EEPROM 4.0 */
+#define AR5K_EEPROM_MISC0 0x00c4
+#define AR5K_EEPROM_EARSTART(_v) ((_v) & 0xfff)
+#define AR5K_EEPROM_EEMAP(_v) (((_v) >> 14) & 0x3)
+#define AR5K_EEPROM_MISC1 0x00c5
+#define AR5K_EEPROM_TARGET_PWRSTART(_v) ((_v) & 0xfff)
+#define AR5K_EEPROM_HAS32KHZCRYSTAL(_v) (((_v) >> 14) & 0x1)
+
+/* Some EEPROM defines */
+#define AR5K_EEPROM_EEP_SCALE 100
+#define AR5K_EEPROM_EEP_DELTA 10
+#define AR5K_EEPROM_N_MODES 3
+#define AR5K_EEPROM_N_5GHZ_CHAN 10
+#define AR5K_EEPROM_N_2GHZ_CHAN 3
+#define AR5K_EEPROM_MAX_CHAN 10
+#define AR5K_EEPROM_N_PCDAC 11
+#define AR5K_EEPROM_N_TEST_FREQ 8
+#define AR5K_EEPROM_N_EDGES 8
+#define AR5K_EEPROM_N_INTERCEPTS 11
+#define AR5K_EEPROM_FREQ_M(_v) AR5K_EEPROM_OFF(_v, 0x7f, 0xff)
+#define AR5K_EEPROM_PCDAC_M 0x3f
+#define AR5K_EEPROM_PCDAC_START 1
+#define AR5K_EEPROM_PCDAC_STOP 63
+#define AR5K_EEPROM_PCDAC_STEP 1
+#define AR5K_EEPROM_NON_EDGE_M 0x40
+#define AR5K_EEPROM_CHANNEL_POWER 8
+#define AR5K_EEPROM_N_OBDB 4
+#define AR5K_EEPROM_OBDB_DIS 0xffff
+#define AR5K_EEPROM_CHANNEL_DIS 0xff
+#define AR5K_EEPROM_SCALE_OC_DELTA(_x) (((_x) * 2) / 10)
+#define AR5K_EEPROM_N_CTLS(_v) AR5K_EEPROM_OFF(_v, 16, 32)
+#define AR5K_EEPROM_MAX_CTLS 32
+#define AR5K_EEPROM_N_XPD_PER_CHANNEL 4
+#define AR5K_EEPROM_N_XPD0_POINTS 4
+#define AR5K_EEPROM_N_XPD3_POINTS 3
+#define AR5K_EEPROM_N_INTERCEPT_10_2GHZ 35
+#define AR5K_EEPROM_N_INTERCEPT_10_5GHZ 55
+#define AR5K_EEPROM_POWER_M 0x3f
+#define AR5K_EEPROM_POWER_MIN 0
+#define AR5K_EEPROM_POWER_MAX 3150
+#define AR5K_EEPROM_POWER_STEP 50
+#define AR5K_EEPROM_POWER_TABLE_SIZE 64
+#define AR5K_EEPROM_N_POWER_LOC_11B 4
+#define AR5K_EEPROM_N_POWER_LOC_11G 6
+#define AR5K_EEPROM_I_GAIN 10
+#define AR5K_EEPROM_CCK_OFDM_DELTA 15
+#define AR5K_EEPROM_N_IQ_CAL 2
+
+struct ar5k_eeprom_info {
+ u_int16_t ee_magic;
+ u_int16_t ee_protect;
+ u_int16_t ee_regdomain;
+ u_int16_t ee_version;
+ u_int16_t ee_header;
+ u_int16_t ee_ant_gain;
+ u_int16_t ee_misc0;
+ u_int16_t ee_misc1;
+ u_int16_t ee_cck_ofdm_gain_delta;
+ u_int16_t ee_cck_ofdm_power_delta;
+ u_int16_t ee_scaled_cck_delta;
+ u_int16_t ee_tx_clip;
+ u_int16_t ee_pwd_84;
+ u_int16_t ee_pwd_90;
+ u_int16_t ee_gain_select;
+
+ u_int16_t ee_i_cal[AR5K_EEPROM_N_MODES];
+ u_int16_t ee_q_cal[AR5K_EEPROM_N_MODES];
+ u_int16_t ee_fixed_bias[AR5K_EEPROM_N_MODES];
+ u_int16_t ee_turbo_max_power[AR5K_EEPROM_N_MODES];
+ u_int16_t ee_xr_power[AR5K_EEPROM_N_MODES];
+ u_int16_t ee_switch_settling[AR5K_EEPROM_N_MODES];
+ u_int16_t ee_ant_tx_rx[AR5K_EEPROM_N_MODES];
+ u_int16_t ee_ant_control[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_PCDAC];
+ u_int16_t ee_ob[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_OBDB];
+ u_int16_t ee_db[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_OBDB];
+ u_int16_t ee_tx_end2xlna_enable[AR5K_EEPROM_N_MODES];
+ u_int16_t ee_tx_end2xpa_disable[AR5K_EEPROM_N_MODES];
+ u_int16_t ee_tx_frm2xpa_enable[AR5K_EEPROM_N_MODES];
+ u_int16_t ee_thr_62[AR5K_EEPROM_N_MODES];
+ u_int16_t ee_xlna_gain[AR5K_EEPROM_N_MODES];
+ u_int16_t ee_xpd[AR5K_EEPROM_N_MODES];
+ u_int16_t ee_x_gain[AR5K_EEPROM_N_MODES];
+ u_int16_t ee_i_gain[AR5K_EEPROM_N_MODES];
+ u_int16_t ee_margin_tx_rx[AR5K_EEPROM_N_MODES];
+ u_int16_t ee_false_detect[AR5K_EEPROM_N_MODES];
+ u_int16_t ee_cal_pier[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_2GHZ_CHAN];
+ u_int16_t ee_channel[AR5K_EEPROM_N_MODES][AR5K_EEPROM_MAX_CHAN];
+
+ u_int16_t ee_ctls;
+ u_int16_t ee_ctl[AR5K_EEPROM_MAX_CTLS];
+
+ int16_t ee_noise_floor_thr[AR5K_EEPROM_N_MODES];
+ int8_t ee_adc_desired_size[AR5K_EEPROM_N_MODES];
+ int8_t ee_pga_desired_size[AR5K_EEPROM_N_MODES];
+
+
+};
+
+/*
* Chipset capabilities
*/
@@ -465,15 +707,8 @@ typedef struct {
/*
* Values stored in the EEPROM (some of them...)
*/
- struct {
- u_int16_t ee_magic;
- u_int16_t ee_antenna;
- u_int16_t ee_protect;
- u_int16_t ee_regdomain;
- u_int8_t ee_rfkill;
- u_int16_t ee_version;
- } cap_eeprom;
-
+ struct ar5k_eeprom_info cap_eeprom;
+
/*
* Queue information
*/
@@ -483,6 +718,18 @@ typedef struct {
} ar5k_capabilities_t;
/*
+ * TX power and TPC settings
+ */
+
+#define AR5K_TXPOWER_OFDM(_r, _v) ( \
+ ((0 & 1) << ((_v) + 6)) | (((_r) & 0x3f) << (_v)) \
+)
+
+#define AR5K_TXPOWER_CCK(_r, _v) ( \
+ ((_r) & 0x3f) << (_v) \
+)
+
+/*
* Atheros descriptor definitions
*/
@@ -498,10 +745,10 @@ struct ath_tx_status {
u_int8_t ts_antenna;
};
-#define HAL_TXSTAT_ALTRATE 0x80
-#define HAL_TXERR_XRETRY 0x01
-#define HAL_TXERR_FILT 0x02
-#define HAL_TXERR_FIFO 0x04
+#define HAL_TXSTAT_ALTRATE 0x80
+#define HAL_TXERR_XRETRY 0x01
+#define HAL_TXERR_FILT 0x02
+#define HAL_TXERR_FIFO 0x04
struct ath_rx_status {
u_int16_t rs_datalen;
@@ -515,34 +762,34 @@ struct ath_rx_status {
u_int8_t rs_more;
};
-#define HAL_RXERR_CRC 0x01
-#define HAL_RXERR_PHY 0x02
-#define HAL_RXERR_FIFO 0x04
-#define HAL_RXERR_DECRYPT 0x08
-#define HAL_RXERR_MIC 0x10
-#define HAL_RXKEYIX_INVALID ((u_int8_t) - 1)
-#define HAL_TXKEYIX_INVALID ((u_int32_t) - 1)
-
-#define HAL_PHYERR_UNDERRUN 0x00
-#define HAL_PHYERR_TIMING 0x01
-#define HAL_PHYERR_PARITY 0x02
-#define HAL_PHYERR_RATE 0x03
-#define HAL_PHYERR_LENGTH 0x04
-#define HAL_PHYERR_RADAR 0x05
-#define HAL_PHYERR_SERVICE 0x06
-#define HAL_PHYERR_TOR 0x07
-#define HAL_PHYERR_OFDM_TIMING 0x11
-#define HAL_PHYERR_OFDM_SIGNAL_PARITY 0x12
-#define HAL_PHYERR_OFDM_RATE_ILLEGAL 0x13
-#define HAL_PHYERR_OFDM_LENGTH_ILLEGAL 0x14
-#define HAL_PHYERR_OFDM_POWER_DROP 0x15
-#define HAL_PHYERR_OFDM_SERVICE 0x16
-#define HAL_PHYERR_OFDM_RESTART 0x17
-#define HAL_PHYERR_CCK_TIMING 0x19
-#define HAL_PHYERR_CCK_HEADER_CRC 0x1a
-#define HAL_PHYERR_CCK_RATE_ILLEGAL 0x1b
-#define HAL_PHYERR_CCK_SERVICE 0x1e
-#define HAL_PHYERR_CCK_RESTART 0x1f
+#define HAL_RXERR_CRC 0x01
+#define HAL_RXERR_PHY 0x02
+#define HAL_RXERR_FIFO 0x04
+#define HAL_RXERR_DECRYPT 0x08
+#define HAL_RXERR_MIC 0x10
+#define HAL_RXKEYIX_INVALID ((u_int8_t) - 1)
+#define HAL_TXKEYIX_INVALID ((u_int32_t) - 1)
+
+#define HAL_PHYERR_UNDERRUN 0x00
+#define HAL_PHYERR_TIMING 0x01
+#define HAL_PHYERR_PARITY 0x02
+#define HAL_PHYERR_RATE 0x03
+#define HAL_PHYERR_LENGTH 0x04
+#define HAL_PHYERR_RADAR 0x05
+#define HAL_PHYERR_SERVICE 0x06
+#define HAL_PHYERR_TOR 0x07
+#define HAL_PHYERR_OFDM_TIMING 0x11
+#define HAL_PHYERR_OFDM_SIGNAL_PARITY 0x12
+#define HAL_PHYERR_OFDM_RATE_ILLEGAL 0x13
+#define HAL_PHYERR_OFDM_LENGTH_ILLEGAL 0x14
+#define HAL_PHYERR_OFDM_POWER_DROP 0x15
+#define HAL_PHYERR_OFDM_SERVICE 0x16
+#define HAL_PHYERR_OFDM_RESTART 0x17
+#define HAL_PHYERR_CCK_TIMING 0x19
+#define HAL_PHYERR_CCK_HEADER_CRC 0x1a
+#define HAL_PHYERR_CCK_RATE_ILLEGAL 0x1b
+#define HAL_PHYERR_CCK_SERVICE 0x1e
+#define HAL_PHYERR_CCK_RESTART 0x1f
struct ath_desc {
u_int32_t ds_link;
@@ -556,19 +803,19 @@ struct ath_desc {
struct ath_tx_status tx;
} ds_us;
-#define ds_rxstat ds_us.rx
-#define ds_txstat ds_us.tx
+#define ds_rxstat ds_us.rx
+#define ds_txstat ds_us.tx
} __packed;
-#define HAL_RXDESC_INTREQ 0x0020
+#define HAL_RXDESC_INTREQ 0x0020
-#define HAL_TXDESC_CLRDMASK 0x0001
-#define HAL_TXDESC_NOACK 0x0002
-#define HAL_TXDESC_RTSENA 0x0004
-#define HAL_TXDESC_CTSENA 0x0008
-#define HAL_TXDESC_INTREQ 0x0010
-#define HAL_TXDESC_VEOL 0x0020
+#define HAL_TXDESC_CLRDMASK 0x0001
+#define HAL_TXDESC_NOACK 0x0002
+#define HAL_TXDESC_RTSENA 0x0004
+#define HAL_TXDESC_CTSENA 0x0008
+#define HAL_TXDESC_INTREQ 0x0010
+#define HAL_TXDESC_VEOL 0x0020
/*
* Hardware abstraction layer structure
@@ -688,7 +935,7 @@ struct ath_desc {
/* Power Management Functions */ \
_t HAL_BOOL (_a _n##_setPowerMode)(struct ath_hal*, \
HAL_POWER_MODE mode, \
- int setChip, u_int16_t sleepDuration); \
+ HAL_BOOL set_chip, u_int16_t sleep_duration); \
_t HAL_POWER_MODE (_a _n##_getPowerMode)(struct ath_hal*); \
_t HAL_BOOL (_a _n##_queryPSPollSupport)(struct ath_hal*); \
_t HAL_BOOL (_a _n##_initPSPoll)(struct ath_hal*); \
@@ -713,9 +960,6 @@ struct ath_desc {
/* Chipset functions (ar5k-specific, non-HAL) */ \
_t HAL_BOOL (_a _n##_get_capabilities)(struct ath_hal *); \
_t void (_a _n##_radar_alert)(struct ath_hal *, HAL_BOOL enable); \
- _t HAL_BOOL (_a _n##_regulation_domain)(struct ath_hal *, \
- HAL_BOOL read, ieee80211_regdomain_t *); \
- _t int (_a _n##_eeprom_init)(struct ath_hal *); \
_t HAL_BOOL (_a _n##_eeprom_is_busy)(struct ath_hal *); \
_t int (_a _n##_eeprom_read)(struct ath_hal *, u_int32_t offset, \
u_int16_t *data); \
@@ -741,6 +985,8 @@ struct ath_hal {
HAL_POWER_MODE ah_power_mode;
HAL_CHANNEL ah_current_channel;
HAL_BOOL ah_turbo;
+ HAL_BOOL ah_calibration;
+ HAL_BOOL ah_running;
#define ah_countryCode ah_country_code
@@ -755,19 +1001,32 @@ struct ath_hal {
u_int16_t ah_radio_5ghz_revision;
u_int16_t ah_radio_2ghz_revision;
+ enum ar5k_version ah_version;
+ enum ar5k_radio ah_radio;
+ u_int32_t ah_phy;
+
+ HAL_BOOL ah_5ghz;
+ HAL_BOOL ah_2ghz;
+
#define ah_macVersion ah_mac_version
#define ah_macRev ah_mac_revision
#define ah_phyRev ah_phy_revision
#define ah_analog5GhzRev ah_radio_5ghz_revision
#define ah_analog2GhzRev ah_radio_2ghz_revision
-#define ah_regdomain ah_capabilities.cap_eeprom.ee_regdomain
+#define ah_regdomain ah_capabilities.cap_regdomain.reg_current
+#define ah_modes ah_capabilities.cap_mode
+#define ah_ee_version ah_capabilities.cap_eeprom.ee_version
u_int32_t ah_atim_window;
u_int32_t ah_aifs;
u_int32_t ah_cw_min;
+ u_int32_t ah_cw_max;
HAL_BOOL ah_software_retry;
u_int32_t ah_limit_tx_retries;
+ u_int32_t ah_antenna[AR5K_EEPROM_N_MODES][HAL_ANT_MAX];
+ HAL_BOOL ah_ant_diversity;
+
u_int8_t ah_sta_id[IEEE80211_ADDR_LEN];
u_int8_t ah_bssid[IEEE80211_ADDR_LEN];
@@ -777,6 +1036,14 @@ struct ath_hal {
ar5k_capabilities_t ah_capabilities;
HAL_TXQ_INFO ah_txq[HAL_NUM_TX_QUEUES];
+ u_int32_t ah_txq_interrupts;
+
+ struct {
+ u_int16_t txp_pcdac[AR5K_EEPROM_POWER_TABLE_SIZE];
+ u_int16_t txp_rates[AR5K_MAX_RATES];
+ u_int txp_max;
+ HAL_BOOL txp_tpc;
+ } ah_txpower;
struct {
HAL_BOOL r_enabled;
@@ -791,14 +1058,43 @@ struct ath_hal {
};
/*
+ * Common silicon revision/version values
+ */
+#define AR5K_SREV_REV_FPGA 1
+#define AR5K_SREV_REV_PROTO 2
+#define AR5K_SREV_REV_PROTOA 3
+#define AR5K_SREV_REV_AR5210 4
+#define AR5K_SREV_REV_AR5210M 5
+#define AR5K_SREV_REV_AR5210M23 7
+#define AR5K_SREV_REV_AR521023 8
+
+#define AR5K_SREV_VER_AR5210 0
+#define AR5K_SREV_VER_AR5311 1
+#define AR5K_SREV_VER_AR5311A 2
+#define AR5K_SREV_VER_AR5311B 3
+#define AR5K_SREV_VER_AR5211 4
+#define AR5K_SREV_VER_AR5212 5
+
+#define AR5K_SREV_RAD_5111 0x10
+#define AR5K_SREV_RAD_5111A 0x15
+#define AR5K_SREV_RAD_2111 0x20
+#define AR5K_SREV_RAD_5112 0x30
+#define AR5K_SREV_RAD_5112A 0x35
+#define AR5K_SREV_RAD_2112A 0x45
+
+/*
* Misc defines
*/
#define HAL_ABI_VERSION 0x04090901 /* YYMMDDnn */
#define AR5K_PRINTF(fmt, ...) printf("%s: " fmt, __func__, ##__VA_ARGS__)
-#define AR5K_PRINT(fmt) printf("%s: " fmt, __func__)
+#define AR5K_PRINT(fmt) printf("%s: " fmt, __func__)
+#ifdef AR5K_DEBUG
#define AR5K_TRACE printf("%s:%d\n", __func__, __LINE__)
+#else
+#define AR5K_TRACE
+#endif
#define AR5K_DELAY(_n) delay(_n)
#define AR5K_ELEMENTS(_array) (sizeof(_array) / sizeof(_array[0]))
@@ -820,12 +1116,29 @@ typedef struct ath_hal*(ar5k_attach_t)
#define AR5K_TUNE_REGISTER_DWELL_TIME 20000
#define AR5K_TUNE_BEACON_INTERVAL 100
#define AR5K_TUNE_AIFS 2
+#define AR5K_TUNE_AIFS_11B 2
+#define AR5K_TUNE_AIFS_XR 0
#define AR5K_TUNE_CWMIN 15
+#define AR5K_TUNE_CWMIN_11B 31
+#define AR5K_TUNE_CWMIN_XR 3
+#define AR5K_TUNE_CWMAX 1023
+#define AR5K_TUNE_CWMAX_11B 1023
+#define AR5K_TUNE_CWMAX_XR 7
+#define AR5K_TUNE_NOISE_FLOOR -72
+#define AR5K_TUNE_MAX_TXPOWER 60
+#define AR5K_TUNE_TPC_TXPOWER AH_FALSE
+#define AR5K_TUNE_ANT_DIVERSITY AH_TRUE
+
+/* Default regulation domain if stored value EEPROM value is invalid */
+#define AR5K_TUNE_REGDOMAIN DMN_FCC1_FCCA
/*
* Common initial register values
*/
+#define AR5K_INIT_MODE ( \
+ IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM \
+)
#define AR5K_INIT_TX_LATENCY 502
#define AR5K_INIT_USEC 39
#define AR5K_INIT_USEC_TURBO 79
@@ -884,51 +1197,197 @@ typedef struct ath_hal*(ar5k_attach_t)
#define AR5K_REG_READ(_reg) \
((u_int32_t)bus_space_read_4(hal->ah_st, hal->ah_sh, (_reg)))
-#define AR5K_REG_SM(_val, _flags) \
+#define AR5K_REG_SM(_val, _flags) \
(((_val) << _flags##_S) & (_flags))
-#define AR5K_REG_MS(_val, _flags) \
+#define AR5K_REG_MS(_val, _flags) \
(((_val) & (_flags)) >> _flags##_S)
-#define AR5K_REG_WRITE_BITS(_reg, _flags, _val) \
+#define AR5K_REG_WRITE_BITS(_reg, _flags, _val) \
AR5K_REG_WRITE(_reg, (AR5K_REG_READ(_reg) &~ (_flags)) | \
(((_val) << _flags##_S) & (_flags)))
-#define AR5K_REG_ENABLE_BITS(_reg, _flags) \
+#define AR5K_REG_MASKED_BITS(_reg, _flags, _mask) \
+ AR5K_REG_WRITE(_reg, (AR5K_REG_READ(_reg) & (_mask)) | (_flags))
+#define AR5K_REG_ENABLE_BITS(_reg, _flags) \
AR5K_REG_WRITE(_reg, AR5K_REG_READ(_reg) | (_flags))
-#define AR5K_REG_DISABLE_BITS(_reg, _flags) \
+#define AR5K_REG_DISABLE_BITS(_reg, _flags) \
AR5K_REG_WRITE(_reg, AR5K_REG_READ(_reg) &~ (_flags))
-/*
- * Initial register values
- */
+#define AR5K_PHY_WRITE(_reg, _val) \
+ AR5K_REG_WRITE(hal->ah_phy + ((_reg) << 2), _val)
+#define AR5K_PHY_READ(_reg) \
+ AR5K_REG_READ(hal->ah_phy + ((_reg) << 2))
-struct ar5k_ini {
- u_int32_t ini_register;
- u_int32_t ini_value;
+/* Read status of selected queue */
+#define AR5K_REG_READ_Q(_reg, _queue) \
+ (AR5K_REG_READ(_reg) & (1 << _queue)) \
- enum {
- INI_WRITE = 0,
- INI_READ = 1,
- } ini_mode;
-};
+#define AR5K_REG_WRITE_Q(_reg, _queue) \
+ AR5K_REG_WRITE(_reg, (1 << _queue))
+
+#define AR5K_Q_ENABLE_BITS(_reg, _queue) do { \
+ _reg |= 1 << _queue; \
+} while (0)
+
+#define AR5K_Q_DISABLE_BITS(_reg, _queue) do { \
+ _reg &= ~(1 << _queue); \
+} while (0)
/*
* Unaligned little endian access
*/
-#define AR5K_LE_READ_2(_p) \
+#define AR5K_LE_READ_2(_p) \
(((const u_int8_t *)(_p))[0] | (((const u_int8_t *)(_p))[1] << 8))
-#define AR5K_LE_READ_4(_p) \
- (((const u_int8_t *)(_p))[0] | (((const u_int8_t *)(_p))[1] << 8) | \
+#define AR5K_LE_READ_4(_p) \
+ (((const u_int8_t *)(_p))[0] | (((const u_int8_t *)(_p))[1] << 8) | \
(((const u_int8_t *)(_p))[2] << 16) | (((const u_int8_t *)(_p))[3] << 24))
-#define AR5K_LE_WRITE_2(_p, _val) \
- ((((u_int8_t *)(_p))[0] = ((u_int32_t)(_val) & 0xff)), \
+#define AR5K_LE_WRITE_2(_p, _val) \
+ ((((u_int8_t *)(_p))[0] = ((u_int32_t)(_val) & 0xff)), \
(((u_int8_t *)(_p))[1] = (((u_int32_t)(_val) >> 8) & 0xff)))
-#define AR5K_LE_WRITE_4(_p, _val) \
+#define AR5K_LE_WRITE_4(_p, _val) \
((((u_int8_t *)(_p))[0] = ((u_int32_t)(_val) & 0xff)), \
(((u_int8_t *)(_p))[1] = (((u_int32_t)(_val) >> 8) & 0xff)), \
(((u_int8_t *)(_p))[2] = (((u_int32_t)(_val) >> 16) & 0xff)), \
(((u_int8_t *)(_p))[3] = (((u_int32_t)(_val) >> 24) & 0xff)))
/*
+ * Initial register values
+ */
+
+struct ar5k_ini {
+ u_int16_t ini_register;
+ u_int32_t ini_value;
+
+ enum {
+ AR5K_INI_WRITE = 0,
+ AR5K_INI_READ = 1,
+ } ini_mode;
+};
+
+#define AR5K_INI_VAL_11A 0
+#define AR5K_INI_VAL_11A_TURBO 1
+#define AR5K_INI_VAL_11B 2
+#define AR5K_INI_VAL_11G 3
+#define AR5K_INI_VAL_11G_TURBO 4
+#define AR5K_INI_VAL_XR 0
+#define AR5K_INI_VAL_MAX 5
+
+#define AR5K_AR5111_INI_RF_MAX_BANKS 8
+#define AR5K_AR5112_INI_RF_MAX_BANKS 8
+
+struct ar5k_ini_rf {
+ u_int8_t rf_bank;
+ u_int16_t rf_register;
+ u_int32_t rf_value[5];
+};
+
+#define AR5K_AR5111_INI_RF { \
+ { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, \
+ { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, \
+ { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, \
+ { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, \
+ { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, \
+ { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, \
+ { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, \
+ { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, \
+ { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, \
+ { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, \
+ { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, \
+ { 0, 0x989c, { 0x00380000, 0x00380000, 0x00380000, 0x00380000, 0x00380000 } }, \
+ { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, \
+ { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, \
+ { 0, 0x989c, { 0x00000000, 0x00000000, 0x000000c0, 0x00000080, 0x00000080 } }, \
+ { 0, 0x989c, { 0x000400f9, 0x000400f9, 0x000400ff, 0x000400fd, 0x000400fd } }, \
+ { 0, 0x98d4, { 0x00000000, 0x00000000, 0x00000004, 0x00000004, 0x00000004 } }, \
+ { 1, 0x98d4, { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, \
+ { 2, 0x98d4, { 0x00000010, 0x00000014, 0x00000010, 0x00000010, 0x00000014 } }, \
+ { 3, 0x98d8, { 0x00601068, 0x00601068, 0x00601068, 0x00601068, 0x00601068 } }, \
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, \
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, \
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, \
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, \
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, \
+ { 6, 0x989c, { 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 } }, \
+ { 6, 0x989c, { 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000 } }, \
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, \
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, \
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, \
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x0a000000, 0x00000000, 0x00000000 } }, \
+ { 6, 0x989c, { 0x003800c0, 0x00380080, 0x023800c0, 0x003800c0, 0x003800c0 } }, \
+ { 6, 0x989c, { 0x00020006, 0x00020006, 0x00000006, 0x00020006, 0x00020006 } }, \
+ { 6, 0x989c, { 0x00000089, 0x00000089, 0x00000089, 0x00000089, 0x00000089 } }, \
+ { 6, 0x989c, { 0x000000a0, 0x000000a0, 0x000000a0, 0x000000a0, 0x000000a0 } }, \
+ { 6, 0x989c, { 0x00040007, 0x00040007, 0x00040007, 0x00040007, 0x00040007 } }, \
+ { 6, 0x98d4, { 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a } }, \
+ { 7, 0x989c, { 0x00000040, 0x00000048, 0x00000040, 0x00000040, 0x00000040 } }, \
+ { 7, 0x989c, { 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 } }, \
+ { 7, 0x989c, { 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008 } }, \
+ { 7, 0x989c, { 0x0000004f, 0x0000004f, 0x0000004f, 0x0000004f, 0x0000004f } }, \
+ { 7, 0x989c, { 0x000000f1, 0x000000f1, 0x00000061, 0x000000f1, 0x000000f1 } }, \
+ { 7, 0x989c, { 0x0000904f, 0x0000904f, 0x0000904c, 0x0000904f, 0x0000904f } }, \
+ { 7, 0x989c, { 0x0000125a, 0x0000125a, 0x0000129a, 0x0000125a, 0x0000125a } }, \
+ { 7, 0x98cc, { 0x0000000e, 0x0000000e, 0x0000000f, 0x0000000e, 0x0000000e } }, \
+}
+
+#define AR5K_AR5112_INI_RF { \
+ { 1, 0x98d4, { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, \
+ { 2, 0x98d0, { 0x03060408, 0x03070408, 0x03060408, 0x03060408, 0x03070408 } }, \
+ { 3, 0x98dc, { 0x00a0c0c0, 0x00a0c0c0, 0x00e0c0c0, 0x00e0c0c0, 0x00e0c0c0 } }, \
+ { 6, 0x989c, { 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000 } }, \
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, \
+ { 6, 0x989c, { 0x00800000, 0x00800000, 0x00800000, 0x00800000, 0x00800000 } }, \
+ { 6, 0x989c, { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } }, \
+ { 6, 0x989c, { 0x00010000, 0x00010000, 0x00010000, 0x00010000, 0x00010000 } }, \
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, \
+ { 6, 0x989c, { 0x00180000, 0x00180000, 0x00180000, 0x00180000, 0x00180000 } }, \
+ { 6, 0x989c, { 0x00600000, 0x00600000, 0x006e0000, 0x006e0000, 0x006e0000 } }, \
+ { 6, 0x989c, { 0x00c70000, 0x00c70000, 0x00c70000, 0x00c70000, 0x00c70000 } }, \
+ { 6, 0x989c, { 0x004b0000, 0x004b0000, 0x004b0000, 0x004b0000, 0x004b0000 } }, \
+ { 6, 0x989c, { 0x04480000, 0x04480000, 0x04480000, 0x04480000, 0x04480000 } }, \
+ { 6, 0x989c, { 0x00220000, 0x00220000, 0x00220000, 0x00220000, 0x00220000 } }, \
+ { 6, 0x989c, { 0x00e40000, 0x00e40000, 0x00e40000, 0x00e40000, 0x00e40000 } }, \
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, \
+ { 6, 0x989c, { 0x00fc0000, 0x00fc0000, 0x00fc0000, 0x00fc0000, 0x00fc0000 } }, \
+ { 6, 0x989c, { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, \
+ { 6, 0x989c, { 0x043f0000, 0x043f0000, 0x043f0000, 0x043f0000, 0x043f0000 } }, \
+ { 6, 0x989c, { 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000 } }, \
+ { 6, 0x989c, { 0x02190000, 0x02190000, 0x02190000, 0x02190000, 0x02190000 } }, \
+ { 6, 0x989c, { 0x00240000, 0x00240000, 0x00240000, 0x00240000, 0x00240000 } }, \
+ { 6, 0x989c, { 0x00b40000, 0x00b40000, 0x00b40000, 0x00b40000, 0x00b40000 } }, \
+ { 6, 0x989c, { 0x00990000, 0x00990000, 0x00990000, 0x00990000, 0x00990000 } }, \
+ { 6, 0x989c, { 0x00500000, 0x00500000, 0x00500000, 0x00500000, 0x00500000 } }, \
+ { 6, 0x989c, { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } }, \
+ { 6, 0x989c, { 0x00120000, 0x00120000, 0x00120000, 0x00120000, 0x00120000 } }, \
+ { 6, 0x989c, { 0xc0320000, 0xc0320000, 0xc0320000, 0xc0320000, 0xc0320000 } }, \
+ { 6, 0x989c, { 0x01740000, 0x01740000, 0x01740000, 0x01740000, 0x01740000 } }, \
+ { 6, 0x989c, { 0x00110000, 0x00110000, 0x00110000, 0x00110000, 0x00110000 } }, \
+ { 6, 0x989c, { 0x86280000, 0x86280000, 0x86280000, 0x86280000, 0x86280000 } }, \
+ { 6, 0x989c, { 0x31840000, 0x31840000, 0x31840000, 0x31840000, 0x31840000 } }, \
+ { 6, 0x989c, { 0x00f20080, 0x00f20080, 0x00f20080, 0x00f20080, 0x00f20080 } }, \
+ { 6, 0x989c, { 0x00070019, 0x00070019, 0x00070019, 0x00070019, 0x00070019 } }, \
+ { 6, 0x989c, { 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003 } }, \
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, \
+ { 6, 0x989c, { 0x000000b2, 0x000000b2, 0x000000b2, 0x000000b2, 0x000000b2 } }, \
+ { 6, 0x989c, { 0x00b02084, 0x00b02084, 0x00b02084, 0x00b02084, 0x00b02084 } }, \
+ { 6, 0x989c, { 0x004125a4, 0x004125a4, 0x004125a4, 0x004125a4, 0x004125a4 } }, \
+ { 6, 0x989c, { 0x00119220, 0x00119220, 0x00119220, 0x00119220, 0x00119220 } }, \
+ { 6, 0x989c, { 0x001a4800, 0x001a4800, 0x001a4800, 0x001a4800, 0x001a4800 } }, \
+ { 6, 0x98d8, { 0x000b0230, 0x000b0230, 0x000b0230, 0x000b0230, 0x000b0230 } }, \
+ { 7, 0x989c, { 0x00000094, 0x00000094, 0x00000094, 0x00000094, 0x00000094 } }, \
+ { 7, 0x989c, { 0x00000091, 0x00000091, 0x00000091, 0x00000091, 0x00000091 } }, \
+ { 7, 0x989c, { 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012 } }, \
+ { 7, 0x989c, { 0x00000080, 0x00000080, 0x00000080, 0x00000080, 0x00000080 } }, \
+ { 7, 0x989c, { 0x000000d9, 0x000000d9, 0x000000d9, 0x000000d9, 0x000000d9 } }, \
+ { 7, 0x989c, { 0x00000060, 0x00000060, 0x00000060, 0x00000060, 0x00000060 } }, \
+ { 7, 0x989c, { 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0 } }, \
+ { 7, 0x989c, { 0x000000a2, 0x000000a2, 0x000000a2, 0x000000a2, 0x000000a2 } }, \
+ { 7, 0x989c, { 0x00000052, 0x00000052, 0x00000052, 0x00000052, 0x00000052 } }, \
+ { 7, 0x989c, { 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4 } }, \
+ { 7, 0x989c, { 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc } }, \
+ { 7, 0x989c, { 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c } }, \
+ { 7, 0x98c4, { 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003 } }, \
+}
+
+/*
* Prototypes
*/
@@ -949,9 +1408,8 @@ HAL_BOOL ath_hal_init_channels(struct ath_hal *, HAL_CHANNEL *,
u_int, u_int *, HAL_CTRY_CODE, u_int16_t, HAL_BOOL, HAL_BOOL);
void ar5k_radar_alert(struct ath_hal *);
-int ar5k_eeprom_read_mac(struct ath_hal *, u_int8_t *);
-ieee80211_regdomain_t *ar5k_regdomain_to_ieee(u_int8_t);
-u_int8_t ar5k_regdomain_from_ieee(ieee80211_regdomain_t *);
+ieee80211_regdomain_t *ar5k_regdomain_to_ieee(u_int16_t);
+u_int16_t ar5k_regdomain_from_ieee(ieee80211_regdomain_t *);
u_int32_t ar5k_bitswap(u_int32_t, u_int);
u_int ar5k_clocktoh(u_int, HAL_BOOL);
u_int ar5k_htoclock(u_int, HAL_BOOL);
@@ -960,6 +1418,14 @@ void ar5k_rt_copy(HAL_RATE_TABLE *, HAL_RATE_TABLE *);
HAL_BOOL ar5k_register_timeout(struct ath_hal *, u_int32_t,
u_int32_t, u_int32_t, HAL_BOOL);
+int ar5k_eeprom_init(struct ath_hal *);
+int ar5k_eeprom_read_mac(struct ath_hal *, u_int8_t *);
+HAL_BOOL ar5k_eeprom_regulation_domain(struct ath_hal *,
+ HAL_BOOL, ieee80211_regdomain_t *);
+
+HAL_BOOL ar5k_channel(struct ath_hal *, HAL_CHANNEL *);
+HAL_BOOL ar5k_rfregs(struct ath_hal *, HAL_CHANNEL *, u_int);
+
__END_DECLS
#endif /* _AR5K_H */
diff --git a/sys/dev/ic/ath.c b/sys/dev/ic/ath.c
index 83bc54de7cc..51939fe7907 100644
--- a/sys/dev/ic/ath.c
+++ b/sys/dev/ic/ath.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ath.c,v 1.4 2004/11/23 09:39:28 reyk Exp $ */
+/* $OpenBSD: ath.c,v 1.5 2004/12/31 01:00:23 reyk Exp $ */
/* $NetBSD: ath.c,v 1.37 2004/08/18 21:59:39 dyoung Exp $ */
/*-
@@ -415,7 +415,7 @@ ath_attach(u_int16_t devid, struct ath_softc *sc)
struct ath_hal *ah;
HAL_STATUS status;
HAL_TXQ_INFO qinfo;
- int error = 0;
+ int error = 0, i = 0;
DPRINTF(ATH_DEBUG_ANY, ("%s: devid 0x%x\n", __func__, devid));
@@ -443,12 +443,25 @@ ath_attach(u_int16_t devid, struct ath_softc *sc)
if_printf(ifp, "mac %d.%d phy %d.%d",
ah->ah_macVersion, ah->ah_macRev,
ah->ah_phyRev >> 4, ah->ah_phyRev & 0xf);
- if (ah->ah_analog5GhzRev != 0)
- printf(" 5GHz radio %d.%d",
- ah->ah_analog5GhzRev >> 4, ah->ah_analog5GhzRev & 0xf);
+ printf(" radio %d.%d", ah->ah_analog5GhzRev >> 4,
+ ah->ah_analog5GhzRev & 0xf);
if (ah->ah_analog2GhzRev != 0)
- printf(" 2GHz radio %d.%d",
- ah->ah_analog2GhzRev >> 4, ah->ah_analog2GhzRev & 0xf);
+ printf(" %d.%d", ah->ah_analog2GhzRev >> 4,
+ ah->ah_analog2GhzRev & 0xf);
+#define ah_mode(_m) { \
+ if (i++) \
+ printf("/%s", #_m); \
+ else \
+ printf(", 802.11%s", #_m); \
+} \
+ if (ah->ah_modes & HAL_MODE_11A)
+ ah_mode(a);
+ if (ah->ah_modes & HAL_MODE_11B)
+ ah_mode(b);
+ if (ah->ah_modes & HAL_MODE_11G)
+ ah_mode(g);
+#undef ah_mode
+
sc->sc_ah = ah;
sc->sc_invalid = 0; /* ready to go, enable interrupt handling */
@@ -1228,7 +1241,6 @@ ath_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
s = splnet();
switch (cmd) {
-#if 0
case SIOCSIFMTU:
if (ifr->ifr_mtu > ETHERMTU || ifr->ifr_mtu < ETHERMIN) {
error = EINVAL;
@@ -1236,7 +1248,6 @@ ath_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
ifp->if_mtu = ifr->ifr_mtu;
}
break;
-#endif
case SIOCSIFADDR:
ifp->if_flags |= IFF_UP;
#ifdef INET
@@ -2821,7 +2832,7 @@ ath_tx_proc(void *arg, int npending)
struct ath_desc *ds;
struct ieee80211_node *ni;
struct ath_node *an;
- int sr, lr, s, s2;
+ int sr, lr, s;
HAL_STATUS status;
DPRINTF(ATH_DEBUG_TX_PROC, ("%s: pending %u tx queue %p, link %p\n",
@@ -2890,9 +2901,9 @@ ath_tx_proc(void *arg, int npending)
bf->bf_m = NULL;
bf->bf_node = NULL;
- s2 = splnet();
+ s = splnet();
TAILQ_INSERT_TAIL(&sc->sc_txbuf, bf, bf_list);
- splx(s2);
+ splx(s);
}
ifp->if_flags &= ~IFF_OACTIVE;
sc->sc_tx_timer = 0;
@@ -2911,7 +2922,7 @@ ath_draintxq(struct ath_softc *sc)
struct ifnet *ifp = &ic->ic_if;
struct ieee80211_node *ni;
struct ath_buf *bf;
- int s, s2;
+ int s;
/* XXX return value */
if (!sc->sc_invalid) {
@@ -2946,7 +2957,7 @@ ath_draintxq(struct ath_softc *sc)
bf->bf_m = NULL;
ni = bf->bf_node;
bf->bf_node = NULL;
- s2 = splnet();
+ s = splnet();
if (ni != NULL && ni != ic->ic_bss) {
/*
* Reclaim node reference.
@@ -2954,7 +2965,7 @@ ath_draintxq(struct ath_softc *sc)
ieee80211_free_node(ic, ni);
}
TAILQ_INSERT_TAIL(&sc->sc_txbuf, bf, bf_list);
- splx(s2);
+ splx(s);
}
ifp->if_flags &= ~IFF_OACTIVE;
sc->sc_tx_timer = 0;