diff options
Diffstat (limited to 'sys/dev/ic')
-rw-r--r-- | sys/dev/ic/ar5210.c | 359 | ||||
-rw-r--r-- | sys/dev/ic/ar5210reg.h | 62 | ||||
-rw-r--r-- | sys/dev/ic/ar5210var.h | 6 | ||||
-rw-r--r-- | sys/dev/ic/ar5xxx.c | 986 | ||||
-rw-r--r-- | sys/dev/ic/ar5xxx.h | 672 | ||||
-rw-r--r-- | sys/dev/ic/ath.c | 41 |
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; |