diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/Jamfile b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/Jamfile index 86f474bfa9..69200286ab 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/Jamfile +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/Jamfile @@ -22,6 +22,10 @@ Depends atheroswifi : atheroswifi_rate.o ; KernelAddon atheroswifi : if_ath.c if_ath_pci.c + if_ath_keycache.c + if_ath_sysctl.c + if_ath_tx.c + if_ath_tx_ht.c glue.c atheroswifi_hal.o atheroswifi_rate.o @@ -36,11 +40,15 @@ SEARCH_SOURCE += [ FDirName $(SUBDIR) dev ath ath_hal ar5211 ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) dev ath ath_hal ar5212 ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) dev ath ath_hal ar5312 ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) dev ath ath_hal ar5416 ] ; +SEARCH_SOURCE += [ FDirName $(SUBDIR) dev ath ath_hal ar9001 ] ; +SEARCH_SOURCE += [ FDirName $(SUBDIR) dev ath ath_hal ar9002 ] ; +SEARCH_SOURCE += [ FDirName $(SUBDIR) dev ath ath_dfs null ] ; KernelMergeObject atheroswifi_hal.o : ah_osdep.c ah.c ah_regdomain.c + ah_eeprom_9287.c ah_eeprom_v3.c # AR5210 support @@ -112,16 +120,31 @@ KernelMergeObject atheroswifi_hal.o : ar5416_reset.c ar5416_xmit.c - # AR9k support - ar9160_attach.c - ar9280.c - ar9280_attach.c - ar9285.c - ar9285_attach.c - ar9285_reset.c - # RF backend for 5416 and 9160 ar2133.c + + # AR9001 and AR9002 support + ar9130_attach.c + ar9130_eeprom.c + ar9130_phy.c + ar9160_attach.c + ar9280_attach.c + ar9280_olc.c + ar9285_attach.c + ar9285_cal.c + ar9285_diversity.c + ar9285_phy.c + ar9285_reset.c + ar9287_attach.c + ar9287_cal.c + ar9287_olc.c + ar9287_reset.c + + ar9280.c + ar9285.c + ar9287.c + + dfs_null.c ; SEARCH_SOURCE += [ FDirName $(SUBDIR) dev ath ath_rate sample ] ; diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ah_osdep.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ah_osdep.c index 6b11b212fe..cceb9a4a4c 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ah_osdep.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ah_osdep.c @@ -71,7 +71,7 @@ extern void ath_hal_assert_failed(const char* filename, int lineno, const char* msg); #endif #ifdef AH_DEBUG -extern void HALDEBUG(struct ath_hal *ah, u_int mask, const char* fmt, ...); +extern void DO_HALDEBUG(struct ath_hal *ah, u_int mask, const char* fmt, ...); #endif /* AH_DEBUG */ /* NB: put this here instead of the driver to avoid circular references */ @@ -79,26 +79,12 @@ SYSCTL_NODE(_hw, OID_AUTO, ath, CTLFLAG_RD, 0, "Atheros driver parameters"); SYSCTL_NODE(_hw_ath, OID_AUTO, hal, CTLFLAG_RD, 0, "Atheros HAL parameters"); #ifdef AH_DEBUG -static int ath_hal_debug = 0; +int ath_hal_debug = 0; SYSCTL_INT(_hw_ath_hal, OID_AUTO, debug, CTLFLAG_RW, &ath_hal_debug, - 0, "Atheros HAL debugging printfs"); + 0, "Atheros HAL debugging printfs"); TUNABLE_INT("hw.ath.hal.debug", &ath_hal_debug); #endif /* AH_DEBUG */ -/* NB: these are deprecated; they exist for now for compatibility */ -int ath_hal_dma_beacon_response_time = 2; /* in TU's */ -SYSCTL_INT(_hw_ath_hal, OID_AUTO, dma_brt, CTLFLAG_RW, - &ath_hal_dma_beacon_response_time, 0, - "Atheros HAL DMA beacon response time"); -int ath_hal_sw_beacon_response_time = 10; /* in TU's */ -SYSCTL_INT(_hw_ath_hal, OID_AUTO, sw_brt, CTLFLAG_RW, - &ath_hal_sw_beacon_response_time, 0, - "Atheros HAL software beacon response time"); -int ath_hal_additional_swba_backoff = 0; /* in TU's */ -SYSCTL_INT(_hw_ath_hal, OID_AUTO, swba_backoff, CTLFLAG_RW, - &ath_hal_additional_swba_backoff, 0, - "Atheros HAL additional SWBA backoff time"); - MALLOC_DEFINE(M_ATH_HAL, "ath_hal", "ath hal data"); void* @@ -135,16 +121,22 @@ ath_hal_ether_sprintf(const u_int8_t *mac) } #ifdef AH_DEBUG + +/* This must match the definition in ath_hal/ah_debug.h */ +#define HAL_DEBUG_UNMASKABLE 0xf0000000 void -HALDEBUG(struct ath_hal *ah, u_int mask, const char* fmt, ...) +DO_HALDEBUG(struct ath_hal *ah, u_int mask, const char* fmt, ...) { - if (ath_hal_debug & mask) { + if ((mask == HAL_DEBUG_UNMASKABLE) || + (ah->ah_config.ah_debug & mask) || + (ath_hal_debug & mask)) { __va_list ap; va_start(ap, fmt); ath_hal_vprintf(ah, fmt, ap); va_end(ap); } } +#undef HAL_DEBUG_UNMASKABLE #endif /* AH_DEBUG */ #ifdef AH_DEBUG_ALQ @@ -168,7 +160,11 @@ HALDEBUG(struct ath_hal *ah, u_int mask, const char* fmt, ...) static struct alq *ath_hal_alq; static int ath_hal_alq_emitdev; /* need to emit DEVICE record */ static u_int ath_hal_alq_lost; /* count of lost records */ -static const char *ath_hal_logfile = "/tmp/ath_hal.log"; +static char ath_hal_logfile[MAXPATHLEN] = "/tmp/ath_hal.log"; + +SYSCTL_STRING(_hw_ath_hal, OID_AUTO, alq_logfile, CTLFLAG_RW, + &ath_hal_logfile, sizeof(kernelname), "Name of ALQ logfile"); + static u_int ath_hal_alq_qsize = 64*1024; static int diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_dfs/null/dfs_null.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_dfs/null/dfs_null.c new file mode 100644 index 0000000000..a3bae91458 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_dfs/null/dfs_null.c @@ -0,0 +1,228 @@ +/*- + * Copyright (c) 2011 Adrian Chadd, Xenion Pty Ltd + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. + * + * $FreeBSD$ + */ +#include +__FBSDID("$FreeBSD$"); + +/* + * This implements an empty DFS module. + */ +#include "opt_inet.h" +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include /* XXX for ether_sprintf */ + +#include + +#include + +#ifdef INET +#include +#include +#endif + +#include +#include + +#include + +/* + * Methods which are required + */ + +/* + * Attach DFS to the given interface + */ +int +ath_dfs_attach(struct ath_softc *sc) +{ + return 1; +} + +/* + * Detach DFS from the given interface + */ +int +ath_dfs_detach(struct ath_softc *sc) +{ + return 1; +} + +/* + * Enable radar check + */ +void +ath_dfs_radar_enable(struct ath_softc *sc, struct ieee80211_channel *chan) +{ + /* Check if the current channel is radar-enabled */ + if (! IEEE80211_IS_CHAN_DFS(chan)) + return; +} + +/* + * Process DFS related PHY errors + */ +void +ath_dfs_process_phy_err(struct ath_softc *sc, const char *buf, + uint64_t tsf, struct ath_rx_status *rxstat) +{ + +} + +/* + * Process the radar events and determine whether a DFS event has occured. + * + * This is designed to run outside of the RX processing path. + * The RX path will call ath_dfs_tasklet_needed() to see whether + * the task/callback running this routine needs to be called. + */ +int +ath_dfs_process_radar_event(struct ath_softc *sc, + struct ieee80211_channel *chan) +{ + return 0; +} + +/* + * Determine whether the the DFS check task needs to be queued. + * + * This is called in the RX task when the current batch of packets + * have been received. It will return whether there are any radar + * events for ath_dfs_process_radar_event() to handle. + */ +int +ath_dfs_tasklet_needed(struct ath_softc *sc, struct ieee80211_channel *chan) +{ + return 0; +} + +/* + * Handle ioctl requests from the diagnostic interface. + * + * The initial part of this code resembles ath_ioctl_diag(); + * it's likely a good idea to reduce duplication between + * these two routines. + */ +int +ath_ioctl_phyerr(struct ath_softc *sc, struct ath_diag *ad) +{ + unsigned int id = ad->ad_id & ATH_DIAG_ID; + void *indata = NULL; + void *outdata = NULL; + u_int32_t insize = ad->ad_in_size; + u_int32_t outsize = ad->ad_out_size; + int error = 0; + HAL_PHYERR_PARAM peout; + HAL_PHYERR_PARAM *pe; + + if (ad->ad_id & ATH_DIAG_IN) { + /* + * Copy in data. + */ + indata = malloc(insize, M_TEMP, M_NOWAIT); + if (indata == NULL) { + error = ENOMEM; + goto bad; + } + error = copyin(ad->ad_in_data, indata, insize); + if (error) + goto bad; + } + if (ad->ad_id & ATH_DIAG_DYN) { + /* + * Allocate a buffer for the results (otherwise the HAL + * returns a pointer to a buffer where we can read the + * results). Note that we depend on the HAL leaving this + * pointer for us to use below in reclaiming the buffer; + * may want to be more defensive. + */ + outdata = malloc(outsize, M_TEMP, M_NOWAIT); + if (outdata == NULL) { + error = ENOMEM; + goto bad; + } + } + switch (id) { + case DFS_SET_THRESH: + if (insize < sizeof(HAL_PHYERR_PARAM)) { + error = EINVAL; + break; + } + pe = (HAL_PHYERR_PARAM *) indata; + ath_hal_enabledfs(sc->sc_ah, pe); + break; + case DFS_GET_THRESH: + memset(&peout, 0, sizeof(peout)); + outsize = sizeof(HAL_PHYERR_PARAM); + ath_hal_getdfsthresh(sc->sc_ah, &peout); + pe = (HAL_PHYERR_PARAM *) outdata; + memcpy(pe, &peout, sizeof(*pe)); + break; + default: + error = EINVAL; + } + if (outsize < ad->ad_out_size) + ad->ad_out_size = outsize; + if (outdata && copyout(outdata, ad->ad_out_data, ad->ad_out_size)) + error = EFAULT; +bad: + if ((ad->ad_id & ATH_DIAG_IN) && indata != NULL) + free(indata, M_TEMP); + if ((ad->ad_id & ATH_DIAG_DYN) && outdata != NULL) + free(outdata, M_TEMP); + return error; +} + +/* + * Get the current DFS thresholds from the HAL + */ +int +ath_dfs_get_thresholds(struct ath_softc *sc, HAL_PHYERR_PARAM *param) +{ + ath_hal_getdfsthresh(sc->sc_ah, param); + return 1; +} diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah.c index cff9613616..4055079dc7 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah.c @@ -21,6 +21,7 @@ #include "ah.h" #include "ah_internal.h" #include "ah_devid.h" +#include "ah_eeprom.h" /* for 5ghz fast clock flag */ #include "ar5416/ar5416reg.h" /* NB: includes ar5212reg.h */ @@ -53,7 +54,7 @@ ath_hal_probe(uint16_t vendorid, uint16_t devid) */ struct ath_hal* ath_hal_attach(uint16_t devid, HAL_SOFTC sc, - HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *error) + HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata, HAL_STATUS *error) { struct ath_hal_chip * const *pchip; @@ -64,7 +65,7 @@ ath_hal_attach(uint16_t devid, HAL_SOFTC sc, /* XXX don't have vendorid, assume atheros one works */ if (chip->probe(ATHEROS_VENDOR_ID, devid) == AH_NULL) continue; - ah = chip->attach(devid, sc, st, sh, error); + ah = chip->attach(devid, sc, st, sh, eepromdata, error); if (ah != AH_NULL) { /* copy back private state to public area */ ah->ah_devid = AH_PRIVATE(ah)->ah_devid; @@ -108,12 +109,16 @@ ath_hal_mac_name(struct ath_hal *ah) return "5416"; case AR_XSREV_VERSION_OWL_PCIE: return "5418"; + case AR_XSREV_VERSION_HOWL: + return "9130"; case AR_XSREV_VERSION_SOWL: return "9160"; case AR_XSREV_VERSION_MERLIN: return "9280"; case AR_XSREV_VERSION_KITE: return "9285"; + case AR_XSREV_VERSION_KIWI: + return "9287"; } return "????"; } @@ -197,9 +202,16 @@ HAL_BOOL ath_hal_wait(struct ath_hal *ah, u_int reg, uint32_t mask, uint32_t val) { #define AH_TIMEOUT 1000 + return ath_hal_waitfor(ah, reg, mask, val, AH_TIMEOUT); +#undef AH_TIMEOUT +} + +HAL_BOOL +ath_hal_waitfor(struct ath_hal *ah, u_int reg, uint32_t mask, uint32_t val, uint32_t timeout) +{ int i; - for (i = 0; i < AH_TIMEOUT; i++) { + for (i = 0; i < timeout; i++) { if ((OS_REG_READ(ah, reg) & mask) == val) return AH_TRUE; OS_DELAY(10); @@ -208,7 +220,6 @@ ath_hal_wait(struct ath_hal *ah, u_int reg, uint32_t mask, uint32_t val) "%s: timeout on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n", __func__, reg, OS_REG_READ(ah, reg), mask, val); return AH_FALSE; -#undef AH_TIMEOUT } /* @@ -228,6 +239,78 @@ ath_hal_reverseBits(uint32_t val, uint32_t n) return retval; } +/* 802.11n related timing definitions */ + +#define OFDM_PLCP_BITS 22 +#define HT_L_STF 8 +#define HT_L_LTF 8 +#define HT_L_SIG 4 +#define HT_SIG 8 +#define HT_STF 4 +#define HT_LTF(n) ((n) * 4) + +#define HT_RC_2_MCS(_rc) ((_rc) & 0xf) +#define HT_RC_2_STREAMS(_rc) ((((_rc) & 0x78) >> 3) + 1) +#define IS_HT_RATE(_rc) ( (_rc) & IEEE80211_RATE_MCS) + +/* + * Calculate the duration of a packet whether it is 11n or legacy. + */ +uint32_t +ath_hal_pkt_txtime(struct ath_hal *ah, const HAL_RATE_TABLE *rates, uint32_t frameLen, + uint16_t rateix, HAL_BOOL isht40, HAL_BOOL shortPreamble) +{ + uint8_t rc; + int numStreams; + + rc = rates->info[rateix].rateCode; + + /* Legacy rate? Return the old way */ + if (! IS_HT_RATE(rc)) + return ath_hal_computetxtime(ah, rates, frameLen, rateix, shortPreamble); + + /* 11n frame - extract out the number of spatial streams */ + numStreams = HT_RC_2_STREAMS(rc); + KASSERT(numStreams == 1 || numStreams == 2, ("number of spatial streams needs to be 1 or 2: MCS rate 0x%x!", rateix)); + + return ath_computedur_ht(frameLen, rc, numStreams, isht40, shortPreamble); +} + +/* + * Calculate the transmit duration of an 11n frame. + * This only works for MCS0->MCS15. + */ +uint32_t +ath_computedur_ht(uint32_t frameLen, uint16_t rate, int streams, HAL_BOOL isht40, + HAL_BOOL isShortGI) +{ + static const uint16_t ht20_bps[16] = { + 26, 52, 78, 104, 156, 208, 234, 260, + 52, 104, 156, 208, 312, 416, 468, 520 + }; + static const uint16_t ht40_bps[16] = { + 54, 108, 162, 216, 324, 432, 486, 540, + 108, 216, 324, 432, 648, 864, 972, 1080, + }; + uint32_t bitsPerSymbol, numBits, numSymbols, txTime; + + KASSERT(rate & IEEE80211_RATE_MCS, ("not mcs %d", rate)); + KASSERT((rate &~ IEEE80211_RATE_MCS) < 16, ("bad mcs 0x%x", rate)); + + if (isht40) + bitsPerSymbol = ht40_bps[rate & 0xf]; + else + bitsPerSymbol = ht20_bps[rate & 0xf]; + numBits = OFDM_PLCP_BITS + (frameLen << 3); + numSymbols = howmany(numBits, bitsPerSymbol); + if (isShortGI) + txTime = ((numSymbols * 18) + 4) / 5; /* 3.6us */ + else + txTime = numSymbols * 4; /* 4us */ + return txTime + HT_L_STF + HT_L_LTF + + HT_L_SIG + HT_SIG + HT_STF + HT_LTF(streams); +} + /* * Compute the time to transmit a frame of length frameLen bytes * using the specified rate, phy, and short preamble setting. @@ -240,6 +323,11 @@ ath_hal_computetxtime(struct ath_hal *ah, uint32_t bitsPerSymbol, numBits, numSymbols, phyTime, txTime; uint32_t kbps; + /* Warn if this function is called for 11n rates; it should not be! */ + if (IS_HT_RATE(rates->info[rateix].rateCode)) + ath_hal_printf(ah, "%s: MCS rate? (index %d; hwrate 0x%x)\n", + __func__, rateix, rates->info[rateix].rateCode); + kbps = rates->info[rateix].rateKbps; /* * index can be invalid duting dynamic Turbo transitions. @@ -336,6 +424,8 @@ ath_hal_chan2wmode(struct ath_hal *ah, const struct ieee80211_channel *chan) /* 11a Turbo 11b 11g 108g */ static const uint8_t CLOCK_RATE[] = { 40, 80, 22, 44, 88 }; +#define CLOCK_FAST_RATE_5GHZ_OFDM 44 + u_int ath_hal_mac_clks(struct ath_hal *ah, u_int usecs) { @@ -343,7 +433,12 @@ ath_hal_mac_clks(struct ath_hal *ah, u_int usecs) u_int clks; /* NB: ah_curchan may be null when called attach time */ - if (c != AH_NULL) { + /* XXX merlin and later specific workaround - 5ghz fast clock is 44 */ + if (c != AH_NULL && IS_5GHZ_FAST_CLOCK_EN(ah, c)) { + clks = usecs * CLOCK_FAST_RATE_5GHZ_OFDM; + if (IEEE80211_IS_CHAN_HT40(c)) + clks <<= 1; + } else if (c != AH_NULL) { clks = usecs * CLOCK_RATE[ath_hal_chan2wmode(ah, c)]; if (IEEE80211_IS_CHAN_HT40(c)) clks <<= 1; @@ -359,7 +454,12 @@ ath_hal_mac_usec(struct ath_hal *ah, u_int clks) u_int usec; /* NB: ah_curchan may be null when called attach time */ - if (c != AH_NULL) { + /* XXX merlin and later specific workaround - 5ghz fast clock is 44 */ + if (c != AH_NULL && IS_5GHZ_FAST_CLOCK_EN(ah, c)) { + usec = clks / CLOCK_FAST_RATE_5GHZ_OFDM; + if (IEEE80211_IS_CHAN_HT40(c)) + usec >>= 1; + } else if (c != AH_NULL) { usec = clks / CLOCK_RATE[ath_hal_chan2wmode(ah, c)]; if (IEEE80211_IS_CHAN_HT40(c)) usec >>= 1; @@ -422,6 +522,9 @@ ath_hal_getcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, case HAL_CAP_REG_DMN: /* regulatory domain */ *result = AH_PRIVATE(ah)->ah_currentRD; return HAL_OK; + case HAL_CAP_DFS_DMN: /* DFS Domain */ + *result = AH_PRIVATE(ah)->ah_dfsDomain; + return HAL_OK; case HAL_CAP_CIPHER: /* cipher handled in hardware */ case HAL_CAP_TKIP_MIC: /* handle TKIP MIC in hardware */ return HAL_ENOTSUPP; @@ -487,24 +590,75 @@ ath_hal_getcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, return HAL_ENOTSUPP; case HAL_CAP_11D: return HAL_OK; - case HAL_CAP_RXORN_FATAL: /* HAL_INT_RXORN treated as fatal */ - return AH_PRIVATE(ah)->ah_rxornIsFatal ? HAL_OK : HAL_ENOTSUPP; + case HAL_CAP_HT: return pCap->halHTSupport ? HAL_OK : HAL_ENOTSUPP; + case HAL_CAP_GTXTO: + return pCap->halGTTSupport ? HAL_OK : HAL_ENOTSUPP; + case HAL_CAP_FAST_CC: + return pCap->halFastCCSupport ? HAL_OK : HAL_ENOTSUPP; case HAL_CAP_TX_CHAINMASK: /* mask of TX chains supported */ *result = pCap->halTxChainMask; return HAL_OK; case HAL_CAP_RX_CHAINMASK: /* mask of RX chains supported */ *result = pCap->halRxChainMask; return HAL_OK; + case HAL_CAP_NUM_GPIO_PINS: + *result = pCap->halNumGpioPins; + return HAL_OK; + case HAL_CAP_CST: + return pCap->halCSTSupport ? HAL_OK : HAL_ENOTSUPP; + case HAL_CAP_RTS_AGGR_LIMIT: + *result = pCap->halRtsAggrLimit; + return HAL_OK; + case HAL_CAP_4ADDR_AGGR: + return pCap->hal4AddrAggrSupport ? HAL_OK : HAL_ENOTSUPP; + case HAL_CAP_EXT_CHAN_DFS: + return pCap->halExtChanDfsSupport ? HAL_OK : HAL_ENOTSUPP; + case HAL_CAP_COMBINED_RADAR_RSSI: + return pCap->halUseCombinedRadarRssi ? HAL_OK : HAL_ENOTSUPP; + case HAL_CAP_AUTO_SLEEP: + return pCap->halAutoSleepSupport ? HAL_OK : HAL_ENOTSUPP; + case HAL_CAP_MBSSID_AGGR_SUPPORT: + return pCap->halMbssidAggrSupport ? HAL_OK : HAL_ENOTSUPP; + case HAL_CAP_SPLIT_4KB_TRANS: /* hardware handles descriptors straddling 4k page boundary */ + return pCap->hal4kbSplitTransSupport ? HAL_OK : HAL_ENOTSUPP; + case HAL_CAP_REG_FLAG: + *result = AH_PRIVATE(ah)->ah_currentRDext; + return HAL_OK; + case HAL_CAP_BT_COEX: + return pCap->halBtCoexSupport ? HAL_OK : HAL_ENOTSUPP; + case HAL_CAP_HT20_SGI: + return pCap->halHTSGI20Support ? HAL_OK : HAL_ENOTSUPP; case HAL_CAP_RXTSTAMP_PREC: /* rx desc tstamp precision (bits) */ *result = pCap->halTstampPrecision; return HAL_OK; + case HAL_CAP_ENHANCED_DFS_SUPPORT: + return pCap->halEnhancedDfsSupport ? HAL_OK : HAL_ENOTSUPP; + + /* FreeBSD-specific entries for now */ + case HAL_CAP_RXORN_FATAL: /* HAL_INT_RXORN treated as fatal */ + return AH_PRIVATE(ah)->ah_rxornIsFatal ? HAL_OK : HAL_ENOTSUPP; case HAL_CAP_INTRMASK: /* mask of supported interrupts */ *result = pCap->halIntrMask; return HAL_OK; case HAL_CAP_BSSIDMATCH: /* hardware has disable bssid match */ return pCap->halBssidMatchSupport ? HAL_OK : HAL_ENOTSUPP; + case HAL_CAP_STREAMS: /* number of 11n spatial streams */ + switch (capability) { + case 0: /* TX */ + *result = pCap->halTxStreams; + return HAL_OK; + case 1: /* RX */ + *result = pCap->halRxStreams; + return HAL_OK; + default: + return HAL_ENOTSUPP; + } + case HAL_CAP_RXDESC_SELFLINK: /* hardware supports self-linked final RX descriptors correctly */ + return pCap->halHasRxSelfLinkedTail ? HAL_OK : HAL_ENOTSUPP; + case HAL_CAP_LONG_RXDESC_TSF: /* 32 bit TSF in RX descriptor? */ + return pCap->halHasLongRxDescTsf ? HAL_OK : HAL_ENOTSUPP; default: return HAL_EINVAL; } @@ -779,6 +933,80 @@ ath_hal_getChanNoise(struct ath_hal *ah, const struct ieee80211_channel *chan) return ichan->rawNoiseFloor + ichan->noiseFloorAdjust; } +/* + * Fetch the current setup of ctl/ext noise floor values. + * + * If the CHANNEL_MIMO_NF_VALID flag isn't set, the array is simply + * populated with values from NOISE_FLOOR[] + ath_hal_getNfAdjust(). + * + * The caller must supply ctl/ext NF arrays which are at least + * AH_MIMO_MAX_CHAINS entries long. + */ +int +ath_hal_get_mimo_chan_noise(struct ath_hal *ah, + const struct ieee80211_channel *chan, int16_t *nf_ctl, + int16_t *nf_ext) +{ +#ifdef AH_SUPPORT_AR5416 + HAL_CHANNEL_INTERNAL *ichan; + int i; + + ichan = ath_hal_checkchannel(ah, chan); + if (ichan == AH_NULL) { + HALDEBUG(ah, HAL_DEBUG_NFCAL, + "%s: invalid channel %u/0x%x; no mapping\n", + __func__, chan->ic_freq, chan->ic_flags); + for (i = 0; i < AH_MIMO_MAX_CHAINS; i++) { + nf_ctl[i] = nf_ext[i] = 0; + } + return 0; + } + + /* Return 0 if there's no valid MIMO values (yet) */ + if (! (ichan->privFlags & CHANNEL_MIMO_NF_VALID)) { + for (i = 0; i < AH_MIMO_MAX_CHAINS; i++) { + nf_ctl[i] = nf_ext[i] = 0; + } + return 0; + } + if (ichan->rawNoiseFloor == 0) { + WIRELESS_MODE mode = ath_hal_chan2wmode(ah, chan); + HALASSERT(mode < WIRELESS_MODE_MAX); + /* + * See the comment below - this could cause issues for + * stations which have a very low RSSI, below the + * 'normalised' NF values in NOISE_FLOOR[]. + */ + for (i = 0; i < AH_MIMO_MAX_CHAINS; i++) { + nf_ctl[i] = nf_ext[i] = NOISE_FLOOR[mode] + + ath_hal_getNfAdjust(ah, ichan); + } + return 1; + } else { + /* + * The value returned here from a MIMO radio is presumed to be + * "good enough" as a NF calculation. As RSSI values are calculated + * against this, an adjusted NF may be higher than the RSSI value + * returned from a vary weak station, resulting in an obscenely + * high signal strength calculation being returned. + * + * This should be re-evaluated at a later date, along with any + * signal strength calculations which are made. Quite likely the + * RSSI values will need to be adjusted to ensure the calculations + * don't "wrap" when RSSI is less than the "adjusted" NF value. + * ("Adjust" here is via ichan->noiseFloorAdjust.) + */ + for (i = 0; i < AH_MIMO_MAX_CHAINS; i++) { + nf_ctl[i] = ichan->noiseFloorCtl[i] + ath_hal_getNfAdjust(ah, ichan); + nf_ext[i] = ichan->noiseFloorExt[i] + ath_hal_getNfAdjust(ah, ichan); + } + return 1; + } +#else + return 0; +#endif /* AH_SUPPORT_AR5416 */ +} + /* * Process all valid raw noise floors into the dBm noise floor values. * Though our device has no reference for a dBm noise floor, we perform @@ -852,6 +1080,11 @@ ath_hal_ini_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia, for (r = 0; r < ia->rows; r++) { OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0), HAL_INI_VAL(ia, r, col)); + + /* Analog shift register delay seems needed for Merlin - PR kern/154220 */ + if (HAL_INI_VAL(ia, r, 0) >= 0x7800 && HAL_INI_VAL(ia, r, 0) < 0x7900) + OS_DELAY(100); + DMA_YIELD(regWr); } return regWr; @@ -879,3 +1112,149 @@ ath_hal_ini_bank_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia, } return regWr; } + +/* + * These are EEPROM board related routines which should likely live in + * a helper library of some sort. + */ + +/************************************************************** + * ath_ee_getLowerUppderIndex + * + * Return indices surrounding the value in sorted integer lists. + * Requirement: the input list must be monotonically increasing + * and populated up to the list size + * Returns: match is set if an index in the array matches exactly + * or a the target is before or after the range of the array. + */ +HAL_BOOL +ath_ee_getLowerUpperIndex(uint8_t target, uint8_t *pList, uint16_t listSize, + uint16_t *indexL, uint16_t *indexR) +{ + uint16_t i; + + /* + * Check first and last elements for beyond ordered array cases. + */ + if (target <= pList[0]) { + *indexL = *indexR = 0; + return AH_TRUE; + } + if (target >= pList[listSize-1]) { + *indexL = *indexR = (uint16_t)(listSize - 1); + return AH_TRUE; + } + + /* look for value being near or between 2 values in list */ + for (i = 0; i < listSize - 1; i++) { + /* + * If value is close to the current value of the list + * then target is not between values, it is one of the values + */ + if (pList[i] == target) { + *indexL = *indexR = i; + return AH_TRUE; + } + /* + * Look for value being between current value and next value + * if so return these 2 values + */ + if (target < pList[i + 1]) { + *indexL = i; + *indexR = (uint16_t)(i + 1); + return AH_FALSE; + } + } + HALASSERT(0); + *indexL = *indexR = 0; + return AH_FALSE; +} + +/************************************************************** + * ath_ee_FillVpdTable + * + * Fill the Vpdlist for indices Pmax-Pmin + * Note: pwrMin, pwrMax and Vpdlist are all in dBm * 4 + */ +HAL_BOOL +ath_ee_FillVpdTable(uint8_t pwrMin, uint8_t pwrMax, uint8_t *pPwrList, + uint8_t *pVpdList, uint16_t numIntercepts, uint8_t *pRetVpdList) +{ + uint16_t i, k; + uint8_t currPwr = pwrMin; + uint16_t idxL, idxR; + + HALASSERT(pwrMax > pwrMin); + for (i = 0; i <= (pwrMax - pwrMin) / 2; i++) { + ath_ee_getLowerUpperIndex(currPwr, pPwrList, numIntercepts, + &(idxL), &(idxR)); + if (idxR < 1) + idxR = 1; /* extrapolate below */ + if (idxL == numIntercepts - 1) + idxL = (uint16_t)(numIntercepts - 2); /* extrapolate above */ + if (pPwrList[idxL] == pPwrList[idxR]) + k = pVpdList[idxL]; + else + k = (uint16_t)( ((currPwr - pPwrList[idxL]) * pVpdList[idxR] + (pPwrList[idxR] - currPwr) * pVpdList[idxL]) / + (pPwrList[idxR] - pPwrList[idxL]) ); + HALASSERT(k < 256); + pRetVpdList[i] = (uint8_t)k; + currPwr += 2; /* half dB steps */ + } + + return AH_TRUE; +} + +/************************************************************************** + * ath_ee_interpolate + * + * Returns signed interpolated or the scaled up interpolated value + */ +int16_t +ath_ee_interpolate(uint16_t target, uint16_t srcLeft, uint16_t srcRight, + int16_t targetLeft, int16_t targetRight) +{ + int16_t rv; + + if (srcRight == srcLeft) { + rv = targetLeft; + } else { + rv = (int16_t)( ((target - srcLeft) * targetRight + + (srcRight - target) * targetLeft) / (srcRight - srcLeft) ); + } + return rv; +} + +/* + * Adjust the TSF. + */ +void +ath_hal_adjusttsf(struct ath_hal *ah, int32_t tsfdelta) +{ + /* XXX handle wrap/overflow */ + OS_REG_WRITE(ah, AR_TSF_L32, OS_REG_READ(ah, AR_TSF_L32) + tsfdelta); +} + +/* + * Enable or disable CCA. + */ +void +ath_hal_setcca(struct ath_hal *ah, int ena) +{ + /* + * NB: fill me in; this is not provided by default because disabling + * CCA in most locales violates regulatory. + */ +} + +/* + * Get CCA setting. + */ +int +ath_hal_getcca(struct ath_hal *ah) +{ + u_int32_t diag; + if (ath_hal_getcapability(ah, HAL_CAP_DIAG, 0, &diag) != HAL_OK) + return 1; + return ((diag & 0x500000) == 0); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah.h index 26288489a8..f4254c14fa 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah.h +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah.h @@ -30,6 +30,14 @@ #include "ah_osdep.h" +/* + * The maximum number of TX/RX chains supported. + * This is intended to be used by various statistics gathering operations + * (NF, RSSI, EVM). + */ +#define AH_MIMO_MAX_CHAINS 3 +#define AH_MIMO_MAX_EVM_PILOTS 6 + /* * __ahdecl is analogous to _cdecl; it defines the calling * convention used within the HAL. For most systems this @@ -101,16 +109,46 @@ typedef enum { HAL_CAP_TPC_ACK = 26, /* ack txpower with per-packet tpc */ HAL_CAP_TPC_CTS = 27, /* cts txpower with per-packet tpc */ HAL_CAP_11D = 28, /* 11d beacon support for changing cc */ - HAL_CAP_INTMIT = 29, /* interference mitigation */ - HAL_CAP_RXORN_FATAL = 30, /* HAL_INT_RXORN treated as fatal */ - HAL_CAP_HT = 31, /* hardware can support HT */ - HAL_CAP_TX_CHAINMASK = 32, /* mask of TX chains supported */ - HAL_CAP_RX_CHAINMASK = 33, /* mask of RX chains supported */ - HAL_CAP_RXTSTAMP_PREC = 34, /* rx desc tstamp precision (bits) */ - HAL_CAP_BB_HANG = 35, /* can baseband hang */ - HAL_CAP_MAC_HANG = 36, /* can MAC hang */ - HAL_CAP_INTRMASK = 37, /* bitmask of supported interrupts */ - HAL_CAP_BSSIDMATCH = 38, /* hardware has disable bssid match */ + + HAL_CAP_HT = 30, /* hardware can support HT */ + HAL_CAP_GTXTO = 31, /* hardware supports global tx timeout */ + HAL_CAP_FAST_CC = 32, /* hardware supports fast channel change */ + HAL_CAP_TX_CHAINMASK = 33, /* mask of TX chains supported */ + HAL_CAP_RX_CHAINMASK = 34, /* mask of RX chains supported */ + HAL_CAP_NUM_GPIO_PINS = 36, /* number of GPIO pins */ + + HAL_CAP_CST = 38, /* hardware supports carrier sense timeout */ + + HAL_CAP_RTS_AGGR_LIMIT = 42, /* aggregation limit with RTS */ + HAL_CAP_4ADDR_AGGR = 43, /* hardware is capable of 4addr aggregation */ + HAL_CAP_DFS_DMN = 44, /* current DFS domain */ + HAL_CAP_EXT_CHAN_DFS = 45, /* DFS support for extension channel */ + HAL_CAP_COMBINED_RADAR_RSSI = 46, /* Is combined RSSI for radar accurate */ + + HAL_CAP_AUTO_SLEEP = 48, /* hardware can go to network sleep + automatically after waking up to receive TIM */ + HAL_CAP_MBSSID_AGGR_SUPPORT = 49, /* Support for mBSSID Aggregation */ + HAL_CAP_SPLIT_4KB_TRANS = 50, /* hardware supports descriptors straddling a 4k page boundary */ + HAL_CAP_REG_FLAG = 51, /* Regulatory domain flags */ + + HAL_CAP_BT_COEX = 60, /* hardware is capable of bluetooth coexistence */ + + HAL_CAP_HT20_SGI = 96, /* hardware supports HT20 short GI */ + + HAL_CAP_RXTSTAMP_PREC = 100, /* rx desc tstamp precision (bits) */ + HAL_CAP_ENHANCED_DFS_SUPPORT = 117, /* hardware supports enhanced DFS */ + + /* The following are private to the FreeBSD HAL (224 onward) */ + + HAL_CAP_INTMIT = 229, /* interference mitigation */ + HAL_CAP_RXORN_FATAL = 230, /* HAL_INT_RXORN treated as fatal */ + HAL_CAP_BB_HANG = 235, /* can baseband hang */ + HAL_CAP_MAC_HANG = 236, /* can MAC hang */ + HAL_CAP_INTRMASK = 237, /* bitmask of supported interrupts */ + HAL_CAP_BSSIDMATCH = 238, /* hardware has disable bssid match */ + HAL_CAP_STREAMS = 239, /* how many 802.11n spatial streams are available */ + HAL_CAP_RXDESC_SELFLINK = 242, /* support a self-linked tail RX descriptor */ + HAL_CAP_LONG_RXDESC_TSF = 243, /* hardware supports 32bit TSF in RX descriptor */ } HAL_CAPABILITY_TYPE; /* @@ -139,6 +177,7 @@ typedef enum { HAL_TX_QUEUE_BEACON = 2, /* beacon xmit q */ HAL_TX_QUEUE_CAB = 3, /* "crap after beacon" xmit q */ HAL_TX_QUEUE_UAPSD = 4, /* u-apsd power save xmit q */ + HAL_TX_QUEUE_PSPOLL = 5, /* power save poll xmit q */ } HAL_TX_QUEUE; #define HAL_NUM_TX_QUEUES 10 /* max possible # of queues */ @@ -287,6 +326,10 @@ typedef enum { /* Rx Filter Frame Types */ typedef enum { + /* + * These bits correspond to AR_RX_FILTER for all chips. + * Not all bits are supported by all chips. + */ HAL_RX_FILTER_UCAST = 0x00000001, /* Allow unicast frames */ HAL_RX_FILTER_MCAST = 0x00000002, /* Allow multicast frames */ HAL_RX_FILTER_BCAST = 0x00000004, /* Allow broadcast frames */ @@ -295,9 +338,19 @@ typedef enum { HAL_RX_FILTER_PROM = 0x00000020, /* Promiscuous mode */ HAL_RX_FILTER_PROBEREQ = 0x00000080, /* Allow probe request frames */ HAL_RX_FILTER_PHYERR = 0x00000100, /* Allow phy errors */ - HAL_RX_FILTER_PHYRADAR = 0x00000200, /* Allow phy radar errors */ HAL_RX_FILTER_COMPBAR = 0x00000400, /* Allow compressed BAR */ - HAL_RX_FILTER_BSSID = 0x00000800, /* Disable BSSID match */ + HAL_RX_FILTER_COMP_BA = 0x00000800, /* Allow compressed blockack */ + HAL_RX_FILTER_PHYRADAR = 0x00002000, /* Allow phy radar errors */ + HAL_RX_FILTER_PSPOLL = 0x00004000, /* Allow PS-POLL frames */ + HAL_RX_FILTER_MCAST_BCAST_ALL = 0x00008000, + /* Allow all mcast/bcast frames */ + + /* + * Magic RX filter flags that aren't targetting hardware bits + * but instead the HAL sets individual bits - eg PHYERR will result + * in OFDM/CCK timing error frames being received. + */ + HAL_RX_FILTER_BSSID = 0x40000000, /* Disable BSSID match */ } HAL_RX_FILTER; typedef enum { @@ -324,6 +377,7 @@ typedef enum { HAL_INT_RXORN = 0x00000020, HAL_INT_TX = 0x00000040, /* Non-common mapping */ HAL_INT_TXDESC = 0x00000080, + HAL_INT_TIM_TIMER= 0x00000100, HAL_INT_TXURN = 0x00000800, HAL_INT_MIB = 0x00001000, HAL_INT_RXPHY = 0x00004000, @@ -592,6 +646,141 @@ struct ath_tx_status; struct ath_rx_status; struct ieee80211_channel; +/* + * This is a channel survey sample entry. + * + * The AR5212 ANI routines fill these samples. The ANI code then uses it + * when calculating listen time; it is also exported via a diagnostic + * API. + */ +typedef struct { + uint32_t seq_num; + uint32_t tx_busy; + uint32_t rx_busy; + uint32_t chan_busy; + uint32_t cycle_count; +} HAL_SURVEY_SAMPLE; + +/* + * This provides 3.2 seconds of sample space given an + * ANI time of 1/10th of a second. This may not be enough! + */ +#define CHANNEL_SURVEY_SAMPLE_COUNT 32 + +typedef struct { + HAL_SURVEY_SAMPLE samples[CHANNEL_SURVEY_SAMPLE_COUNT]; + uint32_t cur_sample; /* current sample in sequence */ + uint32_t cur_seq; /* current sequence number */ +} HAL_CHANNEL_SURVEY; + +/* + * ANI commands. + * + * These are used both internally and externally via the diagnostic + * API. + * + * Note that this is NOT the ANI commands being used via the INTMIT + * capability - that has a different mapping for some reason. + */ +typedef enum { + HAL_ANI_PRESENT = 0, /* is ANI support present */ + HAL_ANI_NOISE_IMMUNITY_LEVEL = 1, /* set level */ + HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION = 2, /* enable/disable */ + HAL_ANI_CCK_WEAK_SIGNAL_THR = 3, /* enable/disable */ + HAL_ANI_FIRSTEP_LEVEL = 4, /* set level */ + HAL_ANI_SPUR_IMMUNITY_LEVEL = 5, /* set level */ + HAL_ANI_MODE = 6, /* 0 => manual, 1 => auto (XXX do not change) */ + HAL_ANI_PHYERR_RESET = 7, /* reset phy error stats */ +} HAL_ANI_CMD; + +/* + * This is the layout of the ANI INTMIT capability. + * + * Notice that the command values differ to HAL_ANI_CMD. + */ +typedef enum { + HAL_CAP_INTMIT_PRESENT = 0, + HAL_CAP_INTMIT_ENABLE = 1, + HAL_CAP_INTMIT_NOISE_IMMUNITY_LEVEL = 2, + HAL_CAP_INTMIT_OFDM_WEAK_SIGNAL_LEVEL = 3, + HAL_CAP_INTMIT_CCK_WEAK_SIGNAL_THR = 4, + HAL_CAP_INTMIT_FIRSTEP_LEVEL = 5, + HAL_CAP_INTMIT_SPUR_IMMUNITY_LEVEL = 6 +} HAL_CAP_INTMIT_CMD; + +typedef struct { + int32_t pe_firpwr; /* FIR pwr out threshold */ + int32_t pe_rrssi; /* Radar rssi thresh */ + int32_t pe_height; /* Pulse height thresh */ + int32_t pe_prssi; /* Pulse rssi thresh */ + int32_t pe_inband; /* Inband thresh */ + + /* The following params are only for AR5413 and later */ + u_int32_t pe_relpwr; /* Relative power threshold in 0.5dB steps */ + u_int32_t pe_relstep; /* Pulse Relative step threshold in 0.5dB steps */ + u_int32_t pe_maxlen; /* Max length of radar sign in 0.8us units */ + int32_t pe_usefir128; /* Use the average in-band power measured over 128 cycles */ + int32_t pe_blockradar; /* + * Enable to block radar check if pkt detect is done via OFDM + * weak signal detect or pkt is detected immediately after tx + * to rx transition + */ + int32_t pe_enmaxrssi; /* + * Enable to use the max rssi instead of the last rssi during + * fine gain changes for radar detection + */ + int32_t pe_extchannel; /* Enable DFS on ext channel */ + int32_t pe_enabled; /* Whether radar detection is enabled */ +} HAL_PHYERR_PARAM; + +#define HAL_PHYERR_PARAM_NOVAL 65535 +#define HAL_PHYERR_PARAM_ENABLE 0x8000 /* Enable/Disable if applicable */ + +/* + * DFS operating mode flags. + */ +typedef enum { + HAL_DFS_UNINIT_DOMAIN = 0, /* Uninitialized dfs domain */ + HAL_DFS_FCC_DOMAIN = 1, /* FCC3 dfs domain */ + HAL_DFS_ETSI_DOMAIN = 2, /* ETSI dfs domain */ + HAL_DFS_MKK4_DOMAIN = 3, /* Japan dfs domain */ +} HAL_DFS_DOMAIN; + +/* + * Flag for setting QUIET period + */ +typedef enum { + HAL_QUIET_DISABLE = 0x0, + HAL_QUIET_ENABLE = 0x1, + HAL_QUIET_ADD_CURRENT_TSF = 0x2, /* add current TSF to next_start offset */ + HAL_QUIET_ADD_SWBA_RESP_TIME = 0x4, /* add beacon response time to next_start offset */ +} HAL_QUIET_FLAG; + +#define HAL_DFS_EVENT_PRICH 0x0000001 +#define HAL_DFS_EVENT_EXTCH 0x0000002 +#define HAL_DFS_EVENT_EXTEARLY 0x0000004 +#define HAL_DFS_EVENT_ISDC 0x0000008 + +struct hal_dfs_event { + uint64_t re_full_ts; /* 64-bit full timestamp from interrupt time */ + uint32_t re_ts; /* Original 15 bit recv timestamp */ + uint8_t re_rssi; /* rssi of radar event */ + uint8_t re_dur; /* duration of radar pulse */ + uint32_t re_flags; /* Flags (see above) */ +}; +typedef struct hal_dfs_event HAL_DFS_EVENT; + +typedef struct +{ + int ah_debug; /* only used if AH_DEBUG is defined */ + int ah_ar5416_biasadj; /* enable AR2133 radio specific bias fiddling */ + + /* NB: these are deprecated; they exist for now for compatibility */ + int ah_dma_beacon_response_time;/* in TU's */ + int ah_sw_beacon_response_time; /* in TU's */ + int ah_additional_swba_backoff; /* in TU's */ +} HAL_OPS_CONFIG; + /* * Hardware Access Layer (HAL) API. * @@ -618,6 +807,9 @@ struct ath_hal { uint16_t ah_analog5GhzRev;/* 5GHz radio revision */ uint16_t ah_analog2GhzRev;/* 2GHz radio revision */ + uint16_t *ah_eepromdata; /* eeprom buffer, if needed */ + + HAL_OPS_CONFIG ah_config; const HAL_RATE_TABLE *__ahdecl(*ah_getRateTable)(struct ath_hal *, u_int mode); void __ahdecl(*ah_detach)(struct ath_hal*); @@ -679,6 +871,8 @@ struct ath_hal { struct ath_desc *, struct ath_tx_status *); void __ahdecl(*ah_getTxIntrQueue)(struct ath_hal *, uint32_t *); void __ahdecl(*ah_reqTxIntrDesc)(struct ath_hal *, struct ath_desc*); + HAL_BOOL __ahdecl(*ah_getTxCompletionRates)(struct ath_hal *, + const struct ath_desc *ds, int *rates, int *tries); /* Receive Functions */ uint32_t __ahdecl(*ah_getRxDP)(struct ath_hal*); @@ -704,8 +898,13 @@ struct ath_hal { void __ahdecl(*ah_rxMonitor)(struct ath_hal *, const HAL_NODE_STATS *, const struct ieee80211_channel *); + void __ahdecl(*ah_aniPoll)(struct ath_hal *, + const struct ieee80211_channel *); void __ahdecl(*ah_procMibEvent)(struct ath_hal *, const HAL_NODE_STATS *); + void __ahdecl(*ah_rxAntCombDiversity)(struct ath_hal *, + struct ath_rx_status *, + unsigned long, int); /* Misc Functions */ HAL_STATUS __ahdecl(*ah_getCapability)(struct ath_hal *, @@ -757,6 +956,19 @@ struct ath_hal { u_int __ahdecl(*ah_getCTSTimeout)(struct ath_hal*); HAL_BOOL __ahdecl(*ah_setDecompMask)(struct ath_hal*, uint16_t, int); void __ahdecl(*ah_setCoverageClass)(struct ath_hal*, uint8_t, int); + HAL_STATUS __ahdecl(*ah_setQuiet)(struct ath_hal *ah, uint32_t period, + uint32_t duration, uint32_t nextStart, + HAL_QUIET_FLAG flag); + + /* DFS functions */ + void __ahdecl(*ah_enableDfs)(struct ath_hal *ah, + HAL_PHYERR_PARAM *pe); + void __ahdecl(*ah_getDfsThresh)(struct ath_hal *ah, + HAL_PHYERR_PARAM *pe); + HAL_BOOL __ahdecl(*ah_procRadarEvent)(struct ath_hal *ah, + struct ath_rx_status *rxs, uint64_t fulltsf, + const char *buf, HAL_DFS_EVENT *event); + HAL_BOOL __ahdecl(*ah_isFastClockEnabled)(struct ath_hal *ah); /* Key Cache Functions */ uint32_t __ahdecl(*ah_getKeyCacheSize)(struct ath_hal*); @@ -785,6 +997,33 @@ struct ath_hal { void __ahdecl(*ah_setStationBeaconTimers)(struct ath_hal*, const HAL_BEACON_STATE *); void __ahdecl(*ah_resetStationBeaconTimers)(struct ath_hal*); + uint64_t __ahdecl(*ah_getNextTBTT)(struct ath_hal *); + + /* 802.11n Functions */ + HAL_BOOL __ahdecl(*ah_chainTxDesc)(struct ath_hal *, + struct ath_desc *, u_int, u_int, HAL_PKT_TYPE, + u_int, HAL_CIPHER, uint8_t, u_int, HAL_BOOL, + HAL_BOOL); + HAL_BOOL __ahdecl(*ah_setupFirstTxDesc)(struct ath_hal *, + struct ath_desc *, u_int, u_int, u_int, + u_int, u_int, u_int, u_int, u_int); + HAL_BOOL __ahdecl(*ah_setupLastTxDesc)(struct ath_hal *, + struct ath_desc *, const struct ath_desc *); + void __ahdecl(*ah_set11nRateScenario)(struct ath_hal *, + struct ath_desc *, u_int, u_int, + HAL_11N_RATE_SERIES [], u_int, u_int); + void __ahdecl(*ah_set11nAggrMiddle)(struct ath_hal *, + struct ath_desc *, u_int); + void __ahdecl(*ah_clr11nAggr)(struct ath_hal *, + struct ath_desc *); + void __ahdecl(*ah_set11nBurstDuration)(struct ath_hal *, + struct ath_desc *, u_int); + uint32_t __ahdecl(*ah_get11nExtBusy)(struct ath_hal *); + void __ahdecl(*ah_set11nMac2040)(struct ath_hal *, + HAL_HT_MACMODE); + HAL_HT_RXCLEAR __ahdecl(*ah_get11nRxClear)(struct ath_hal *ah); + void __ahdecl(*ah_set11nRxClear)(struct ath_hal *, + HAL_HT_RXCLEAR); /* Interrupt functions */ HAL_BOOL __ahdecl(*ah_isInterruptPending)(struct ath_hal*); @@ -814,7 +1053,7 @@ extern const char *__ahdecl ath_hal_probe(uint16_t vendorid, uint16_t devid); * be returned if the status parameter is non-zero. */ extern struct ath_hal * __ahdecl ath_hal_attach(uint16_t devid, HAL_SOFTC, - HAL_BUS_TAG, HAL_BUS_HANDLE, HAL_STATUS* status); + HAL_BUS_TAG, HAL_BUS_HANDLE, uint16_t *eepromdata, HAL_STATUS* status); extern const char *ath_hal_mac_name(struct ath_hal *); extern const char *ath_hal_rf_name(struct ath_hal *); @@ -863,6 +1102,14 @@ extern HAL_STATUS __ahdecl ath_hal_set_channels(struct ath_hal *, struct ieee80211_channel *chans, int nchans, HAL_CTRY_CODE cc, HAL_REG_DOMAIN regDmn); +/* + * Fetch the ctl/ext noise floor values reported by a MIMO + * radio. Returns 1 for valid results, 0 for invalid channel. + */ +extern int __ahdecl ath_hal_get_mimo_chan_noise(struct ath_hal *ah, + const struct ieee80211_channel *chan, int16_t *nf_ctl, + int16_t *nf_ext); + /* * Calibrate noise floor data following a channel scan or similar. * This must be called prior retrieving noise floor data. @@ -875,9 +1122,38 @@ extern void __ahdecl ath_hal_process_noisefloor(struct ath_hal *ah); extern u_int __ahdecl ath_hal_getwirelessmodes(struct ath_hal*); /* - * Calculate the transmit duration of a frame. + * Calculate the packet TX time for a legacy or 11n frame + */ +extern uint32_t __ahdecl ath_hal_pkt_txtime(struct ath_hal *ah, + const HAL_RATE_TABLE *rates, uint32_t frameLen, + uint16_t rateix, HAL_BOOL isht40, HAL_BOOL shortPreamble); + +/* + * Calculate the duration of an 11n frame. + */ +extern uint32_t __ahdecl ath_computedur_ht(uint32_t frameLen, uint16_t rate, + int streams, HAL_BOOL isht40, HAL_BOOL isShortGI); + +/* + * Calculate the transmit duration of a legacy frame. */ extern uint16_t __ahdecl ath_hal_computetxtime(struct ath_hal *, const HAL_RATE_TABLE *rates, uint32_t frameLen, uint16_t rateix, HAL_BOOL shortPreamble); + +/* + * Adjust the TSF. + */ +extern void __ahdecl ath_hal_adjusttsf(struct ath_hal *ah, int32_t tsfdelta); + +/* + * Enable or disable CCA. + */ +void __ahdecl ath_hal_setcca(struct ath_hal *ah, int ena); + +/* + * Get CCA setting. + */ +int __ahdecl ath_hal_getcca(struct ath_hal *ah); + #endif /* _ATH_AH_H_ */ diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_debug.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_debug.h index e3b15ad1a7..f1678eb48e 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_debug.h +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_debug.h @@ -14,7 +14,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * $Id: ah_debug.h,v 1.1 2008/10/12 16:44:34 sam Exp $ + * $FreeBSD$ */ #ifndef _ATH_AH_DEBUG_H_ #define _ATH_AH_DEBUG_H_ @@ -42,8 +42,13 @@ enum { HAL_DEBUG_EEPROM = 0x00008000, HAL_DEBUG_BEACON = 0x00010000, /* beacon setup work */ HAL_DEBUG_POWER = 0x00020000, /* power management */ - HAL_DEBUG_INTERRUPT = 0x00000080, /* interrupt handling */ + HAL_DEBUG_GPIO = 0x00040000, /* GPIO debugging */ + HAL_DEBUG_INTERRUPT = 0x00080000, /* interrupt handling */ + HAL_DEBUG_DIVERSITY = 0x00100000, /* diversity debugging */ + HAL_DEBUG_DFS = 0x00200000, /* DFS debugging */ + HAL_DEBUG_HANG = 0x00400000, /* BB/MAC hang debugging */ + HAL_DEBUG_UNMASKABLE = 0xf0000000, /* always printed */ HAL_DEBUG_ANY = 0xffffffff }; #endif /* _ATH_AH_DEBUG_H_ */ diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_decode.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_decode.h index bd595aea8d..eb764af9ac 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_decode.h +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_decode.h @@ -14,7 +14,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * $Id: ah_decode.h,v 1.4 2008/11/10 04:08:00 sam Exp $ + * $FreeBSD$ */ #ifndef _ATH_AH_DECODE_H_ #define _ATH_AH_DECODE_H_ @@ -51,5 +51,15 @@ enum { AH_MARK_ANI_RESET, /* ar*AniReset, opmode */ AH_MARK_ANI_POLL, /* ar*AniReset, listen time */ AH_MARK_ANI_CONTROL, /* ar*AniReset, cmd */ + AH_MARK_RX_CTL, /* RX DMA control */ }; + +enum { + AH_MARK_RX_CTL_PCU_START, + AH_MARK_RX_CTL_PCU_STOP, + AH_MARK_RX_CTL_DMA_START, + AH_MARK_RX_CTL_DMA_STOP, + AH_MARK_RX_CTL_DMA_STOP_ERR, +}; + #endif /* _ATH_AH_DECODE_H_ */ diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_desc.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_desc.h index 919e247436..4651fc2d7c 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_desc.h +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_desc.h @@ -113,6 +113,8 @@ struct ath_rx_status { uint32_t rs_evm0; /* evm bytes */ uint32_t rs_evm1; uint32_t rs_evm2; + uint32_t rs_evm3; /* needed for ar9300 and later */ + uint32_t rs_evm4; /* needed for ar9300 and later */ #endif /* AH_SUPPORT_AR5416 */ }; @@ -142,7 +144,7 @@ enum { HAL_PHYERR_RADAR = 5, /* Radar detect */ HAL_PHYERR_SERVICE = 6, /* Illegal service */ HAL_PHYERR_TOR = 7, /* Transmit override receive */ - /* NB: these are specific to the 5212 */ + /* NB: these are specific to the 5212 and later */ HAL_PHYERR_OFDM_TIMING = 17, /* */ HAL_PHYERR_OFDM_SIGNAL_PARITY = 18, /* */ HAL_PHYERR_OFDM_RATE_ILLEGAL = 19, /* */ @@ -150,11 +152,18 @@ enum { HAL_PHYERR_OFDM_POWER_DROP = 21, /* */ HAL_PHYERR_OFDM_SERVICE = 22, /* */ HAL_PHYERR_OFDM_RESTART = 23, /* */ + HAL_PHYERR_FALSE_RADAR_EXT = 24, /* */ HAL_PHYERR_CCK_TIMING = 25, /* */ HAL_PHYERR_CCK_HEADER_CRC = 26, /* */ HAL_PHYERR_CCK_RATE_ILLEGAL = 27, /* */ HAL_PHYERR_CCK_SERVICE = 30, /* */ HAL_PHYERR_CCK_RESTART = 31, /* */ + HAL_PHYERR_CCK_LENGTH_ILLEGAL = 32, /* */ + HAL_PHYERR_CCK_POWER_DROP = 33, /* */ + /* AR5416 and later */ + HAL_PHYERR_HT_CRC_ERROR = 34, /* */ + HAL_PHYERR_HT_LENGTH_ILLEGAL = 35, /* */ + HAL_PHYERR_HT_RATE_ILLEGAL = 36, /* */ }; /* value found in rs_keyix to mark invalid entries */ diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_devid.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_devid.h index 0844c77361..c7a98dda4f 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_devid.h +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_devid.h @@ -14,7 +14,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * $Id: ah_devid.h,v 1.4 2008/10/06 18:32:46 sam Exp $ + * $FreeBSD$ */ #ifndef _DEV_ATH_DEVID_H_ @@ -74,10 +74,14 @@ /* AR5416 compatible devid's */ #define AR5416_DEVID_PCI 0x0023 /* AR5416 PCI (MB/CB) Owl */ #define AR5416_DEVID_PCIE 0x0024 /* AR5416 PCI-E (XB) Owl */ +#define AR5416_AR9130_DEVID 0x000b /* AR9130 SoC WiMAC */ #define AR9160_DEVID_PCI 0x0027 /* AR9160 PCI Sowl */ #define AR9280_DEVID_PCI 0x0029 /* AR9280 PCI Merlin */ #define AR9280_DEVID_PCIE 0x002a /* AR9280 PCI-E Merlin */ #define AR9285_DEVID_PCIE 0x002b /* AR9285 PCI-E Kite */ +#define AR2427_DEVID_PCIE 0x002c /* AR2427 PCI-E w/ 802.11n bonded out */ +#define AR9287_DEVID_PCI 0x002d /* AR9227 PCI Kiwi */ +#define AR9287_DEVID_PCIE 0x002e /* AR9287 PCI-E Kiwi */ #define AR_SUBVENDOR_ID_NOG 0x0e11 /* No 11G subvendor ID */ #define AR_SUBVENDOR_ID_NEW_A 0x7065 /* Update device to new RD */ diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_diagcodes.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_diagcodes.h new file mode 100644 index 0000000000..1e29b2cebe --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_diagcodes.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#ifndef _ATH_AH_DIAGCODES_H_ +#define _ATH_AH_DIAGCODES_H_ +/* + * Atheros Device Hardware Access Layer (HAL). + * + * Internal diagnostic API definitions. + */ + +/* + * Diagnostic interface. This is an open-ended interface that + * is opaque to applications. Diagnostic programs use this to + * retrieve internal data structures, etc. There is no guarantee + * that calling conventions for calls other than HAL_DIAG_REVS + * are stable between HAL releases; a diagnostic application must + * use the HAL revision information to deal with ABI/API differences. + * + * NB: do not renumber these, certain codes are publicly used. + */ +enum { + HAL_DIAG_REVS = 0, /* MAC/PHY/Radio revs */ + HAL_DIAG_EEPROM = 1, /* EEPROM contents */ + HAL_DIAG_EEPROM_EXP_11A = 2, /* EEPROM 5112 power exp for 11a */ + HAL_DIAG_EEPROM_EXP_11B = 3, /* EEPROM 5112 power exp for 11b */ + HAL_DIAG_EEPROM_EXP_11G = 4, /* EEPROM 5112 power exp for 11g */ + HAL_DIAG_ANI_CURRENT = 5, /* ANI current channel state */ + HAL_DIAG_ANI_OFDM = 6, /* ANI OFDM timing error stats */ + HAL_DIAG_ANI_CCK = 7, /* ANI CCK timing error stats */ + HAL_DIAG_ANI_STATS = 8, /* ANI statistics */ + HAL_DIAG_RFGAIN = 9, /* RfGain GAIN_VALUES */ + HAL_DIAG_RFGAIN_CURSTEP = 10, /* RfGain GAIN_OPTIMIZATION_STEP */ + HAL_DIAG_PCDAC = 11, /* PCDAC table */ + HAL_DIAG_TXRATES = 12, /* Transmit rate table */ + HAL_DIAG_REGS = 13, /* Registers */ + HAL_DIAG_ANI_CMD = 14, /* ANI issue command (XXX do not change!) */ + HAL_DIAG_SETKEY = 15, /* Set keycache backdoor */ + HAL_DIAG_RESETKEY = 16, /* Reset keycache backdoor */ + HAL_DIAG_EEREAD = 17, /* Read EEPROM word */ + HAL_DIAG_EEWRITE = 18, /* Write EEPROM word */ + /* 19-26 removed, do not reuse */ + HAL_DIAG_RDWRITE = 27, /* Write regulatory domain */ + HAL_DIAG_RDREAD = 28, /* Get regulatory domain */ + HAL_DIAG_FATALERR = 29, /* Read cached interrupt state */ + HAL_DIAG_11NCOMPAT = 30, /* 11n compatibility tweaks */ + HAL_DIAG_ANI_PARAMS = 31, /* ANI noise immunity parameters */ + HAL_DIAG_CHECK_HANGS = 32, /* check h/w hangs */ + HAL_DIAG_SETREGS = 33, /* write registers */ + HAL_DIAG_CHANSURVEY = 34, /* channel survey */ +}; + +#endif /* _ATH_AH_DIAGCODES_H_ */ diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_eeprom.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_eeprom.h index 0adfcd144d..b77fb6427c 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_eeprom.h +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_eeprom.h @@ -14,7 +14,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * $Id: ah_eeprom.h,v 1.11 2008/11/27 22:32:48 sam Exp $ + * $FreeBSD$ */ #ifndef _ATH_AH_EEPROM_H_ #define _ATH_AH_EEPROM_H_ @@ -94,11 +94,17 @@ enum { AR_EEP_RXMASK, /* uint8_t* */ AR_EEP_RXGAIN_TYPE, /* uint8_t* */ AR_EEP_TXGAIN_TYPE, /* uint8_t* */ + AR_EEP_DAC_HPWR_5G, /* uint8_t* */ AR_EEP_OL_PWRCTRL, /* use ath_hal_eepromGetFlag */ AR_EEP_FSTCLK_5G, /* use ath_hal_eepromGetFlag */ AR_EEP_ANTGAINMAX_5, /* int8_t* */ AR_EEP_ANTGAINMAX_2, /* int8_t* */ AR_EEP_WRITEPROTECT, /* use ath_hal_eepromGetFlag */ + AR_EEP_PWR_TABLE_OFFSET,/* int8_t* */ + AR_EEP_PWDCLKIND, /* uint8_t* */ + AR_EEP_TEMPSENSE_SLOPE, /* int8_t* */ + AR_EEP_TEMPSENSE_SLOPE_PAL_ON, /* int8_t* */ + AR_EEP_FRAC_N_5G, /* uint8_t* */ }; typedef struct { @@ -130,4 +136,5 @@ HAL_STATUS ath_hal_v1EepromAttach(struct ath_hal *ah); HAL_STATUS ath_hal_legacyEepromAttach(struct ath_hal *ah); HAL_STATUS ath_hal_v14EepromAttach(struct ath_hal *ah); HAL_STATUS ath_hal_v4kEepromAttach(struct ath_hal *ah); +HAL_STATUS ath_hal_9287EepromAttach(struct ath_hal *ah); #endif /* _ATH_AH_EEPROM_H_ */ diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_eeprom_9287.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_eeprom_9287.c new file mode 100644 index 0000000000..099fe34b2b --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_eeprom_9287.c @@ -0,0 +1,408 @@ +/* + * Copyright (c) 2008 Sam Leffler, Errno Consulting + * Copyright (c) 2010 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_eeprom_v14.h" +#include "ah_eeprom_9287.h" + +static HAL_STATUS +v9287EepromGet(struct ath_hal *ah, int param, void *val) +{ +#define CHAN_A_IDX 0 +#define CHAN_B_IDX 1 +#define IS_VERS(op, v) ((pBase->version & AR5416_EEP_VER_MINOR_MASK) op (v)) + HAL_EEPROM_9287 *ee = AH_PRIVATE(ah)->ah_eeprom; + const MODAL_EEP_9287_HEADER *pModal = &ee->ee_base.modalHeader; + const BASE_EEP_9287_HEADER *pBase = &ee->ee_base.baseEepHeader; + uint32_t sum; + uint8_t *macaddr; + int i; + + switch (param) { + case AR_EEP_NFTHRESH_2: + *(int16_t *)val = pModal->noiseFloorThreshCh[0]; + return HAL_OK; + case AR_EEP_MACADDR: /* Get MAC Address */ + sum = 0; + macaddr = val; + for (i = 0; i < 6; i++) { + macaddr[i] = pBase->macAddr[i]; + sum += pBase->macAddr[i]; + } + if (sum == 0 || sum == 0xffff*3) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad mac address %s\n", + __func__, ath_hal_ether_sprintf(macaddr)); + return HAL_EEBADMAC; + } + return HAL_OK; + case AR_EEP_REGDMN_0: + return pBase->regDmn[0]; + case AR_EEP_REGDMN_1: + return pBase->regDmn[1]; + case AR_EEP_OPCAP: + return pBase->deviceCap; + case AR_EEP_OPMODE: + return pBase->opCapFlags; + case AR_EEP_RFSILENT: + return pBase->rfSilent; + case AR_EEP_TXMASK: + return pBase->txMask; + case AR_EEP_RXMASK: + return pBase->rxMask; + case AR_EEP_OL_PWRCTRL: + HALASSERT(val == AH_NULL); + return pBase->openLoopPwrCntl ? HAL_OK : HAL_EIO; + case AR_EEP_AMODE: + return HAL_EIO; /* no 5GHz for Kiwi */ + case AR_EEP_BMODE: + case AR_EEP_GMODE: + HALASSERT(val == AH_NULL); + return pBase->opCapFlags & AR5416_OPFLAGS_11G ? + HAL_OK : HAL_EIO; + case AR_EEP_32KHZCRYSTAL: + case AR_EEP_COMPRESS: + case AR_EEP_FASTFRAME: /* XXX policy decision, h/w can do it */ + case AR_EEP_WRITEPROTECT: /* NB: no write protect bit */ + HALASSERT(val == AH_NULL); + /* fall thru... */ + case AR_EEP_MAXQCU: /* NB: not in opCapFlags */ + case AR_EEP_KCENTRIES: /* NB: not in opCapFlags */ + return HAL_EIO; + case AR_EEP_AES: + case AR_EEP_BURST: + case AR_EEP_RFKILL: + case AR_EEP_TURBO5DISABLE: + case AR_EEP_TURBO2DISABLE: + HALASSERT(val == AH_NULL); + return HAL_OK; + case AR_EEP_ANTGAINMAX_2: + *(int8_t *) val = ee->ee_antennaGainMax[1]; + return HAL_OK; + case AR_EEP_PWR_TABLE_OFFSET: + *(int8_t *) val = pBase->pwrTableOffset; + return HAL_OK; + case AR_EEP_TEMPSENSE_SLOPE: + if (IS_VERS(>=, AR9287_EEP_MINOR_VER_2)) + *(int8_t *)val = pBase->tempSensSlope; + else + *(int8_t *)val = 0; + return HAL_OK; + case AR_EEP_TEMPSENSE_SLOPE_PAL_ON: + if (IS_VERS(>=, AR9287_EEP_MINOR_VER_3)) + *(int8_t *)val = pBase->tempSensSlopePalOn; + else + *(int8_t *)val = 0; + return HAL_OK; + default: + HALASSERT(0); + return HAL_EINVAL; + } +#undef IS_VERS +#undef CHAN_A_IDX +#undef CHAN_B_IDX +} + +static HAL_STATUS +v9287EepromSet(struct ath_hal *ah, int param, int v) +{ + HAL_EEPROM_9287 *ee = AH_PRIVATE(ah)->ah_eeprom; + + switch (param) { + case AR_EEP_ANTGAINMAX_2: + ee->ee_antennaGainMax[1] = (int8_t) v; + return HAL_OK; + default: + return HAL_EINVAL; + } +} + +static HAL_BOOL +v9287EepromDiag(struct ath_hal *ah, int request, + const void *args, uint32_t argsize, void **result, uint32_t *resultsize) +{ + HAL_EEPROM_9287 *ee = AH_PRIVATE(ah)->ah_eeprom; + + switch (request) { + case HAL_DIAG_EEPROM: + *result = ee; + *resultsize = sizeof(HAL_EEPROM_9287); + return AH_TRUE; + } + return AH_FALSE; +} + +/* Do structure specific swaps if Eeprom format is non native to host */ +static void +eepromSwap(HAL_EEPROM_9287 *ee) +{ + uint32_t integer, i; + uint16_t word; + MODAL_EEP_9287_HEADER *pModal; + + /* convert Base Eep header */ + word = __bswap16(ee->ee_base.baseEepHeader.length); + ee->ee_base.baseEepHeader.length = word; + + word = __bswap16(ee->ee_base.baseEepHeader.checksum); + ee->ee_base.baseEepHeader.checksum = word; + + word = __bswap16(ee->ee_base.baseEepHeader.version); + ee->ee_base.baseEepHeader.version = word; + + word = __bswap16(ee->ee_base.baseEepHeader.regDmn[0]); + ee->ee_base.baseEepHeader.regDmn[0] = word; + + word = __bswap16(ee->ee_base.baseEepHeader.regDmn[1]); + ee->ee_base.baseEepHeader.regDmn[1] = word; + + word = __bswap16(ee->ee_base.baseEepHeader.rfSilent); + ee->ee_base.baseEepHeader.rfSilent = word; + + word = __bswap16(ee->ee_base.baseEepHeader.blueToothOptions); + ee->ee_base.baseEepHeader.blueToothOptions = word; + + word = __bswap16(ee->ee_base.baseEepHeader.deviceCap); + ee->ee_base.baseEepHeader.deviceCap = word; + + /* convert Modal Eep header */ + + /* only 2.4ghz here; so only one modal header entry */ + pModal = &ee->ee_base.modalHeader; + + /* XXX linux/ah_osdep.h only defines __bswap32 for BE */ + integer = __bswap32(pModal->antCtrlCommon); + pModal->antCtrlCommon = integer; + + for (i = 0; i < AR9287_MAX_CHAINS; i++) { + integer = __bswap32(pModal->antCtrlChain[i]); + pModal->antCtrlChain[i] = integer; + } + for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) { + word = __bswap16(pModal->spurChans[i].spurChan); + pModal->spurChans[i].spurChan = word; + } +} + +static uint16_t +v9287EepromGetSpurChan(struct ath_hal *ah, int ix, HAL_BOOL is2GHz) +{ + HAL_EEPROM_9287 *ee = AH_PRIVATE(ah)->ah_eeprom; + + HALASSERT(is2GHz == AH_TRUE); + if (is2GHz != AH_TRUE) + return 0; /* XXX ? */ + + HALASSERT(0 <= ix && ix < AR5416_EEPROM_MODAL_SPURS); + return ee->ee_base.modalHeader.spurChans[ix].spurChan; +} + +/************************************************************************** + * fbin2freq + * + * Get channel value from binary representation held in eeprom + * RETURNS: the frequency in MHz + */ +static uint16_t +fbin2freq(uint8_t fbin, HAL_BOOL is2GHz) +{ + /* + * Reserved value 0xFF provides an empty definition both as + * an fbin and as a frequency - do not convert + */ + if (fbin == AR5416_BCHAN_UNUSED) + return fbin; + return (uint16_t)((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin)); +} + + +/* + * Copy EEPROM Conformance Testing Limits contents + * into the allocated space + */ +/* USE CTLS from chain zero */ +#define CTL_CHAIN 0 + +static void +v9287EepromReadCTLInfo(struct ath_hal *ah, HAL_EEPROM_9287 *ee) +{ + RD_EDGES_POWER *rep = ee->ee_rdEdgesPower; + int i, j; + + HALASSERT(AR9287_NUM_CTLS <= sizeof(ee->ee_rdEdgesPower)/NUM_EDGES); + + for (i = 0; ee->ee_base.ctlIndex[i] != 0 && i < AR9287_NUM_CTLS; i++) { + for (j = 0; j < NUM_EDGES; j ++) { + /* XXX Confirm this is the right thing to do when an invalid channel is stored */ + if (ee->ee_base.ctlData[i].ctlEdges[CTL_CHAIN][j].bChannel == AR5416_BCHAN_UNUSED) { + rep[j].rdEdge = 0; + rep[j].twice_rdEdgePower = 0; + rep[j].flag = 0; + } else { + rep[j].rdEdge = fbin2freq( + ee->ee_base.ctlData[i].ctlEdges[CTL_CHAIN][j].bChannel, + (ee->ee_base.ctlIndex[i] & CTL_MODE_M) != CTL_11A); + rep[j].twice_rdEdgePower = MS(ee->ee_base.ctlData[i].ctlEdges[CTL_CHAIN][j].tPowerFlag, CAL_CTL_EDGES_POWER); + rep[j].flag = MS(ee->ee_base.ctlData[i].ctlEdges[CTL_CHAIN][j].tPowerFlag, CAL_CTL_EDGES_FLAG) != 0; + } + } + rep += NUM_EDGES; + } + ee->ee_numCtls = i; + HALDEBUG(ah, HAL_DEBUG_ATTACH | HAL_DEBUG_EEPROM, + "%s Numctls = %u\n",__func__,i); +} + +/* + * Reclaim any EEPROM-related storage. + */ +static void +v9287EepromDetach(struct ath_hal *ah) +{ + HAL_EEPROM_9287 *ee = AH_PRIVATE(ah)->ah_eeprom; + + ath_hal_free(ee); + AH_PRIVATE(ah)->ah_eeprom = AH_NULL; +} + +#define owl_get_eep_ver(_ee) \ + (((_ee)->ee_base.baseEepHeader.version >> 12) & 0xF) +#define owl_get_eep_rev(_ee) \ + (((_ee)->ee_base.baseEepHeader.version) & 0xFFF) + +HAL_STATUS +ath_hal_9287EepromAttach(struct ath_hal *ah) +{ +#define NW(a) (sizeof(a) / sizeof(uint16_t)) + HAL_EEPROM_9287 *ee = AH_PRIVATE(ah)->ah_eeprom; + uint16_t *eep_data, magic; + HAL_BOOL need_swap; + u_int w, off, len; + uint32_t sum; + + HALASSERT(ee == AH_NULL); + + /* + * Don't check magic if we're supplied with an EEPROM block, + * typically this is from Howl but it may also be from later + * boards w/ an embedded WMAC. + */ + if (ah->ah_eepromdata == NULL) { + if (!ath_hal_eepromRead(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s Error reading Eeprom MAGIC\n", __func__); + return HAL_EEREAD; + } + } + HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s Eeprom Magic = 0x%x\n", + __func__, magic); + if (magic != AR5416_EEPROM_MAGIC) { + HALDEBUG(ah, HAL_DEBUG_ANY, "Bad magic number\n"); + return HAL_EEMAGIC; + } + + ee = ath_hal_malloc(sizeof(HAL_EEPROM_9287)); + if (ee == AH_NULL) { + /* XXX message */ + return HAL_ENOMEM; + } + + eep_data = (uint16_t *) ee; + for (w = 0; w < NW(struct ar9287_eeprom); w++) { + off = AR9287_EEP_START_LOC + w; + if (!ath_hal_eepromRead(ah, off, &eep_data[w])) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s eeprom read error at offset 0x%x\n", + __func__, off); + return HAL_EEREAD; + } + } + /* Convert to eeprom native eeprom endian format */ + /* + * XXX this is likely incorrect but will do for now + * XXX to get embedded boards working. + */ + if (ah->ah_eepromdata == NULL && isBigEndian()) { + for (w = 0; w < NW(HAL_EEPROM_9287); w++) + eep_data[w] = __bswap16(eep_data[w]); + } + + /* + * At this point, we're in the native eeprom endian format + * Now, determine the eeprom endian by looking at byte 26?? + */ + need_swap = ((ee->ee_base.baseEepHeader.eepMisc & AR5416_EEPMISC_BIG_ENDIAN) != 0) ^ isBigEndian(); + if (need_swap) { + HALDEBUG(ah, HAL_DEBUG_ATTACH | HAL_DEBUG_EEPROM, + "Byte swap EEPROM contents.\n"); + len = __bswap16(ee->ee_base.baseEepHeader.length); + } else { + len = ee->ee_base.baseEepHeader.length; + } + len = AH_MIN(len, sizeof(HAL_EEPROM_9287)) / sizeof(uint16_t); + + /* Apply the checksum, done in native eeprom format */ + /* XXX - Need to check to make sure checksum calculation is done + * in the correct endian format. Right now, it seems it would + * cast the raw data to host format and do the calculation, which may + * not be correct as the calculation may need to be done in the native + * eeprom format + */ + sum = 0; + for (w = 0; w < len; w++) + sum ^= eep_data[w]; + /* Check CRC - Attach should fail on a bad checksum */ + if (sum != 0xffff) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "Bad EEPROM checksum 0x%x (Len=%u)\n", sum, len); + return HAL_EEBADSUM; + } + + if (need_swap) + eepromSwap(ee); /* byte swap multi-byte data */ + + /* swap words 0+2 so version is at the front */ + magic = eep_data[0]; + eep_data[0] = eep_data[2]; + eep_data[2] = magic; + + HALDEBUG(ah, HAL_DEBUG_ATTACH | HAL_DEBUG_EEPROM, + "%s Eeprom Version %u.%u\n", __func__, + owl_get_eep_ver(ee), owl_get_eep_rev(ee)); + + /* NB: must be after all byte swapping */ + if (owl_get_eep_ver(ee) != AR5416_EEP_VER) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "Bad EEPROM version 0x%x\n", owl_get_eep_ver(ee)); + return HAL_EEBADSUM; + } + + v9287EepromReadCTLInfo(ah, ee); /* Get CTLs */ + + AH_PRIVATE(ah)->ah_eeprom = ee; + AH_PRIVATE(ah)->ah_eeversion = ee->ee_base.baseEepHeader.version; + AH_PRIVATE(ah)->ah_eepromDetach = v9287EepromDetach; + AH_PRIVATE(ah)->ah_eepromGet = v9287EepromGet; + AH_PRIVATE(ah)->ah_eepromSet = v9287EepromSet; + AH_PRIVATE(ah)->ah_getSpurChan = v9287EepromGetSpurChan; + AH_PRIVATE(ah)->ah_eepromDiag = v9287EepromDiag; + return HAL_OK; +#undef NW +} diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_eeprom_9287.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_eeprom_9287.h new file mode 100644 index 0000000000..ff8080aa3a --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_eeprom_9287.h @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2008-2009 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ + +#ifndef __AH_EEPROM_9287_H__ +#define __AH_EEPROM_9287_H__ + +#define OLC_FOR_AR9287_10_LATER (AR_SREV_9287_11_OR_LATER(ah) && \ + ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) + +#define AR9287_EEP_VER 0xE +#define AR9287_EEP_VER_MINOR_MASK 0xFFF +#define AR9287_EEP_MINOR_VER_1 0x1 +#define AR9287_EEP_MINOR_VER_2 0x2 +#define AR9287_EEP_MINOR_VER_3 0x3 +#define AR9287_EEP_MINOR_VER AR9287_EEP_MINOR_VER_3 +#define AR9287_EEP_MINOR_VER_b AR9287_EEP_MINOR_VER +#define AR9287_EEP_NO_BACK_VER AR9287_EEP_MINOR_VER_1 + +#define AR9287_RDEXT_DEFAULT 0x1F + +#define AR9287_EEP_START_LOC 128 +#define AR9287_HTC_EEP_START_LOC 256 +#define AR9287_NUM_2G_CAL_PIERS 3 +#define AR9287_NUM_2G_CCK_TARGET_POWERS 3 +#define AR9287_NUM_2G_20_TARGET_POWERS 3 +#define AR9287_NUM_2G_40_TARGET_POWERS 3 +#define AR9287_NUM_CTLS 12 +#define AR9287_NUM_BAND_EDGES 4 +#define AR9287_PD_GAIN_ICEPTS 1 +#define AR9287_EEPMISC_BIG_ENDIAN 0x01 +#define AR9287_EEPMISC_WOW 0x02 +#define AR9287_MAX_CHAINS 2 +#define AR9287_ANT_16S 32 + +#define AR9287_DATA_SZ 32 + +#define AR9287_PWR_TABLE_OFFSET_DB -5 + +#define AR9287_CHECKSUM_LOCATION (AR9287_EEP_START_LOC + 1) + +struct base_eep_ar9287_header { + uint16_t version; /* Swapped w/ length; check ah_eeprom_v14.h */ + uint16_t checksum; + uint16_t length; + uint8_t opCapFlags; + uint8_t eepMisc; + uint16_t regDmn[2]; + uint8_t macAddr[6]; + uint8_t rxMask; + uint8_t txMask; + uint16_t rfSilent; + uint16_t blueToothOptions; + uint16_t deviceCap; + uint32_t binBuildNumber; + uint8_t deviceType; + uint8_t openLoopPwrCntl; + int8_t pwrTableOffset; + int8_t tempSensSlope; + int8_t tempSensSlopePalOn; + uint8_t futureBase[29]; +} __packed; + +struct modal_eep_ar9287_header { + uint32_t antCtrlChain[AR9287_MAX_CHAINS]; + uint32_t antCtrlCommon; + int8_t antennaGainCh[AR9287_MAX_CHAINS]; + uint8_t switchSettling; + uint8_t txRxAttenCh[AR9287_MAX_CHAINS]; + uint8_t rxTxMarginCh[AR9287_MAX_CHAINS]; + int8_t adcDesiredSize; + uint8_t txEndToXpaOff; + uint8_t txEndToRxOn; + uint8_t txFrameToXpaOn; + uint8_t thresh62; + int8_t noiseFloorThreshCh[AR9287_MAX_CHAINS]; + uint8_t xpdGain; + uint8_t xpd; + int8_t iqCalICh[AR9287_MAX_CHAINS]; + int8_t iqCalQCh[AR9287_MAX_CHAINS]; + uint8_t pdGainOverlap; + uint8_t xpaBiasLvl; + uint8_t txFrameToDataStart; + uint8_t txFrameToPaOn; + uint8_t ht40PowerIncForPdadc; + uint8_t bswAtten[AR9287_MAX_CHAINS]; + uint8_t bswMargin[AR9287_MAX_CHAINS]; + uint8_t swSettleHt40; + uint8_t version; + uint8_t db1; + uint8_t db2; + uint8_t ob_cck; + uint8_t ob_psk; + uint8_t ob_qam; + uint8_t ob_pal_off; + uint8_t futureModal[30]; + SPUR_CHAN spurChans[AR5416_EEPROM_MODAL_SPURS]; +} __packed; + +struct cal_data_op_loop_ar9287 { + uint8_t pwrPdg[2][5]; + uint8_t vpdPdg[2][5]; + uint8_t pcdac[2][5]; + uint8_t empty[2][5]; +} __packed; + +struct cal_data_per_freq_ar9287 { + uint8_t pwrPdg[AR5416_NUM_PD_GAINS][AR9287_PD_GAIN_ICEPTS]; + uint8_t vpdPdg[AR5416_NUM_PD_GAINS][AR9287_PD_GAIN_ICEPTS]; +} __packed; + +union cal_data_per_freq_ar9287_u { + struct cal_data_op_loop_ar9287 calDataOpen; + struct cal_data_per_freq_ar9287 calDataClose; +} __packed; + +struct cal_ctl_data_ar9287 { + CAL_CTL_EDGES ctlEdges[AR9287_MAX_CHAINS][AR9287_NUM_BAND_EDGES]; +} __packed; + +struct ar9287_eeprom { + struct base_eep_ar9287_header baseEepHeader; + uint8_t custData[AR9287_DATA_SZ]; + struct modal_eep_ar9287_header modalHeader; + uint8_t calFreqPier2G[AR9287_NUM_2G_CAL_PIERS]; + union cal_data_per_freq_ar9287_u + calPierData2G[AR9287_MAX_CHAINS][AR9287_NUM_2G_CAL_PIERS]; + CAL_TARGET_POWER_LEG + calTargetPowerCck[AR9287_NUM_2G_CCK_TARGET_POWERS]; + CAL_TARGET_POWER_LEG + calTargetPower2G[AR9287_NUM_2G_20_TARGET_POWERS]; + CAL_TARGET_POWER_HT + calTargetPower2GHT20[AR9287_NUM_2G_20_TARGET_POWERS]; + CAL_TARGET_POWER_HT + calTargetPower2GHT40[AR9287_NUM_2G_40_TARGET_POWERS]; + uint8_t ctlIndex[AR9287_NUM_CTLS]; + struct cal_ctl_data_ar9287 ctlData[AR9287_NUM_CTLS]; + uint8_t padding; +} __packed; + +typedef struct { + struct ar9287_eeprom ee_base; +#define NUM_EDGES 8 + uint16_t ee_numCtls; + RD_EDGES_POWER ee_rdEdgesPower[NUM_EDGES*AR9287_NUM_CTLS]; + /* XXX these are dynamically calculated for use by shared code */ + int8_t ee_antennaGainMax[2]; +} HAL_EEPROM_9287; + +typedef struct modal_eep_ar9287_header MODAL_EEP_9287_HEADER; +typedef struct base_eep_ar9287_header BASE_EEP_9287_HEADER; + + +#endif /* __AH_EEPROM_9287_H__ */ diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_eeprom_v1.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_eeprom_v1.c index 91f895c248..8b4664fc98 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_eeprom_v1.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_eeprom_v1.c @@ -14,7 +14,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * $Id: ah_eeprom_v1.c,v 1.1 2008/11/11 02:40:11 sam Exp $ + * $FreeBSD$ */ #include "opt_ah.h" @@ -68,7 +68,7 @@ v1EepromGet(struct ath_hal *ah, int param, void *val) } } -static HAL_BOOL +static HAL_STATUS v1EepromSet(struct ath_hal *ah, int param, int v) { return HAL_EINVAL; @@ -112,7 +112,7 @@ ath_hal_v1EepromAttach(struct ath_hal *ah) { HAL_EEPROM_v1 *ee = AH_PRIVATE(ah)->ah_eeprom; uint16_t athvals[AR_EEPROM_ATHEROS_MAX]; /* XXX off stack */ - uint16_t protect, version, eeval; + uint16_t protect, eeprom_version, eeval; uint32_t sum; int i, loc; @@ -138,18 +138,18 @@ ath_hal_v1EepromAttach(struct ath_hal *ah) HALDEBUG(ah, HAL_DEBUG_ATTACH, "EEPROM protect 0x%x\n", protect); /* XXX check proper access before continuing */ - if (!ath_hal_eepromRead(ah, AR_EEPROM_VERSION, &version)) { + if (!ath_hal_eepromRead(ah, AR_EEPROM_VERSION, &eeprom_version)) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unable to read EEPROM version\n", __func__); return HAL_EEREAD; } - if (((version>>12) & 0xf) != 1) { + if (((eeprom_version>>12) & 0xf) != 1) { /* * This code only groks the version 1 EEPROM layout. */ HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unsupported EEPROM version 0x%x found\n", - __func__, version); + __func__, eeprom_version); return HAL_EEVERSION; } @@ -183,7 +183,7 @@ ath_hal_v1EepromAttach(struct ath_hal *ah) return HAL_ENOMEM; } - ee->ee_version = version; + ee->ee_version = eeprom_version; ee->ee_protect = protect; ee->ee_antenna = athvals[2]; ee->ee_biasCurrents = athvals[3]; @@ -243,7 +243,7 @@ ath_hal_v1EepromAttach(struct ath_hal *ah) } AH_PRIVATE(ah)->ah_eeprom = ee; - AH_PRIVATE(ah)->ah_eeversion = version; + AH_PRIVATE(ah)->ah_eeversion = eeprom_version; AH_PRIVATE(ah)->ah_eepromDetach = v1EepromDetach; AH_PRIVATE(ah)->ah_eepromGet = v1EepromGet; AH_PRIVATE(ah)->ah_eepromSet = v1EepromSet; diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_eeprom_v1.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_eeprom_v1.h index 2c235896ea..22fce8a092 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_eeprom_v1.h +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_eeprom_v1.h @@ -14,7 +14,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * $Id: ah_eeprom_v1.h,v 1.1 2008/11/11 02:40:11 sam Exp $ + * $FreeBSD$ */ #ifndef _ATH_AH_EEPROM_V1_H_ #define _ATH_AH_EEPROM_V1_H_ diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_eeprom_v14.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_eeprom_v14.c index 8793d3ba73..37e973c169 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_eeprom_v14.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_eeprom_v14.c @@ -84,11 +84,25 @@ v14EepromGet(struct ath_hal *ah, int param, void *val) return IS_VERS(>=, AR5416_EEP_MINOR_VER_19) ? pBase->txGainType : AR5416_EEP_TXGAIN_ORIG; case AR_EEP_FSTCLK_5G: - return IS_VERS(>, AR5416_EEP_MINOR_VER_16) ? - pBase->fastClk5g : AH_TRUE; + /* 5ghz fastclock is always enabled for Merlin minor <= 16 */ + if (IS_VERS(<=, AR5416_EEP_MINOR_VER_16)) + return HAL_OK; + return pBase->fastClk5g ? HAL_OK : HAL_EIO; case AR_EEP_OL_PWRCTRL: HALASSERT(val == AH_NULL); return pBase->openLoopPwrCntl ? HAL_OK : HAL_EIO; + case AR_EEP_DAC_HPWR_5G: + if (IS_VERS(>=, AR5416_EEP_MINOR_VER_20)) { + *(uint8_t *) val = pBase->dacHiPwrMode_5G; + return HAL_OK; + } else + return HAL_EIO; + case AR_EEP_FRAC_N_5G: + if (IS_VERS(>=, AR5416_EEP_MINOR_VER_22)) { + *(uint8_t *) val = pBase->frac_n_5g; + } else + *(uint8_t *) val = 0; + return HAL_OK; case AR_EEP_AMODE: HALASSERT(val == AH_NULL); return pBase->opCapFlags & AR5416_OPFLAGS_11A ? @@ -120,6 +134,19 @@ v14EepromGet(struct ath_hal *ah, int param, void *val) case AR_EEP_ANTGAINMAX_5: *(int8_t *) val = ee->ee_antennaGainMax[0]; return HAL_OK; + case AR_EEP_PWR_TABLE_OFFSET: + if (IS_VERS(>=, AR5416_EEP_MINOR_VER_21)) + *(int8_t *) val = pBase->pwr_table_offset; + else + *(int8_t *) val = AR5416_PWR_TABLE_OFFSET_DB; + return HAL_OK; + case AR_EEP_PWDCLKIND: + if (IS_VERS(>=, AR5416_EEP_MINOR_VER_10)) { + *(uint8_t *) val = pBase->pwdclkind; + return HAL_OK; + } + return HAL_EIO; + default: HALASSERT(0); return HAL_EINVAL; @@ -129,7 +156,7 @@ v14EepromGet(struct ath_hal *ah, int param, void *val) #undef CHAN_B_IDX } -static HAL_BOOL +static HAL_STATUS v14EepromSet(struct ath_hal *ah, int param, int v) { HAL_EEPROM_v14 *ee = AH_PRIVATE(ah)->ah_eeprom; @@ -153,8 +180,8 @@ v14EepromDiag(struct ath_hal *ah, int request, switch (request) { case HAL_DIAG_EEPROM: - *result = &ee->ee_base; - *resultsize = sizeof(ee->ee_base); + *result = ee; + *resultsize = sizeof(HAL_EEPROM_v14); return AH_TRUE; } return AH_FALSE; @@ -205,7 +232,10 @@ eepromSwap(struct ar5416eeprom *ee) integer = __bswap32(pModal->antCtrlChain[i]); pModal->antCtrlChain[i] = integer; } - + for (i = 0; i < 3; i++) { + word = __bswap16(pModal->xpaBiasLvlFreq[i]); + pModal->xpaBiasLvlFreq[i] = word; + } for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) { word = __bswap16(pModal->spurChans[i].spurChan); pModal->spurChans[i].spurChan = word; @@ -294,6 +324,11 @@ v14EepromDetach(struct ath_hal *ah) #define owl_get_eep_rev(_ee) \ (((_ee)->ee_base.baseEepHeader.version) & 0xFFF) +/* + * Howl is (hopefully) a special case where the endian-ness of the EEPROM + * matches the native endian-ness; and that supplied EEPROMs don't have + * a magic value to check. + */ HAL_STATUS ath_hal_v14EepromAttach(struct ath_hal *ah) { @@ -306,16 +341,23 @@ ath_hal_v14EepromAttach(struct ath_hal *ah) HALASSERT(ee == AH_NULL); - if (!ath_hal_eepromRead(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) { - HALDEBUG(ah, HAL_DEBUG_ANY, - "%s Error reading Eeprom MAGIC\n", __func__); - return HAL_EEREAD; - } - HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s Eeprom Magic = 0x%x\n", - __func__, magic); - if (magic != AR5416_EEPROM_MAGIC) { - HALDEBUG(ah, HAL_DEBUG_ANY, "Bad magic number\n"); - return HAL_EEMAGIC; + /* + * Don't check magic if we're supplied with an EEPROM block, + * typically this is from Howl but it may also be from later + * boards w/ an embedded Merlin. + */ + if (ah->ah_eepromdata == NULL) { + if (!ath_hal_eepromRead(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s Error reading Eeprom MAGIC\n", __func__); + return HAL_EEREAD; + } + HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s Eeprom Magic = 0x%x\n", + __func__, magic); + if (magic != AR5416_EEPROM_MAGIC) { + HALDEBUG(ah, HAL_DEBUG_ANY, "Bad magic number\n"); + return HAL_EEMAGIC; + } } ee = ath_hal_malloc(sizeof(HAL_EEPROM_v14)); @@ -335,7 +377,8 @@ ath_hal_v14EepromAttach(struct ath_hal *ah) } } /* Convert to eeprom native eeprom endian format */ - if (isBigEndian()) { + /* XXX this is likely incorrect but will do for now to get howl/ap83 working. */ + if (ah->ah_eepromdata == NULL && isBigEndian()) { for (w = 0; w < NW(struct ar5416eeprom); w++) eep_data[w] = __bswap16(eep_data[w]); } diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_eeprom_v14.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_eeprom_v14.h index d2caa8087b..7b2c898ce6 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_eeprom_v14.h +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_eeprom_v14.h @@ -49,9 +49,13 @@ #define AR5416_EEP_MINOR_VER_3 0x3 #define AR5416_EEP_MINOR_VER_7 0x7 #define AR5416_EEP_MINOR_VER_9 0x9 +#define AR5416_EEP_MINOR_VER_10 0xa #define AR5416_EEP_MINOR_VER_16 0x10 #define AR5416_EEP_MINOR_VER_17 0x11 #define AR5416_EEP_MINOR_VER_19 0x13 +#define AR5416_EEP_MINOR_VER_20 0x14 +#define AR5416_EEP_MINOR_VER_21 0x15 +#define AR5416_EEP_MINOR_VER_22 0x16 // 16-bit offset location start of calibration struct #define AR5416_EEP_START_LOC 256 @@ -91,10 +95,10 @@ #define AR5416_OPFLAGS_11A 0x01 #define AR5416_OPFLAGS_11G 0x02 -#define AR5416_OPFLAGS_5G_HT40 0x04 -#define AR5416_OPFLAGS_2G_HT40 0x08 -#define AR5416_OPFLAGS_5G_HT20 0x10 -#define AR5416_OPFLAGS_2G_HT20 0x20 +#define AR5416_OPFLAGS_N_5G_HT40 0x04 /* If set, disable 5G HT40 */ +#define AR5416_OPFLAGS_N_2G_HT40 0x08 +#define AR5416_OPFLAGS_N_5G_HT20 0x10 +#define AR5416_OPFLAGS_N_2G_HT20 0x20 /* RF silent fields in EEPROM */ #define EEP_RFSILENT_ENABLED 0x0001 /* enabled/disabled */ @@ -138,6 +142,16 @@ typedef struct CalCtlEdges { #define CAL_CTL_EDGES_FLAG_S 6 } __packed CAL_CTL_EDGES; +/* + * These are the secondary regulatory domain flags + * for regDmn[1]. + */ +#define AR5416_REGDMN_EN_FCC_MID 0x01 /* 5.47 - 5.7GHz operation */ +#define AR5416_REGDMN_EN_JAP_MID 0x02 /* 5.47 - 5.7GHz operation */ +#define AR5416_REGDMN_EN_FCC_DFS_HT40 0x04 /* FCC HT40 + DFS operation */ +#define AR5416_REGDMN_EN_JAP_HT40 0x08 /* JP HT40 operation */ +#define AR5416_REGDMN_EN_JAP_DFS_HT40 0x10 /* JP HT40 + DFS operation */ + /* * NB: The format in EEPROM has words 0 and 2 swapped (i.e. version * and length are swapped). We reverse their position after reading @@ -165,13 +179,19 @@ typedef struct BaseEepHeader { uint8_t fastClk5g; uint8_t divChain; uint8_t rxGainType; - uint8_t dacHiPwrMode; /* use the DAC high power mode (MB91) */ + uint8_t dacHiPwrMode_5G;/* use the DAC high power mode (MB91) */ uint8_t openLoopPwrCntl;/* 1: use open loop power control, 0: use closed loop power control */ uint8_t dacLpMode; uint8_t txGainType; /* high power tx gain table support */ uint8_t rcChainMask; /* "1" if the card is an HB93 1x2 */ - uint8_t futureBase[24]; + uint8_t desiredScaleCCK; + uint8_t pwr_table_offset; + uint8_t frac_n_5g; /* + * bit 0: indicates that fracN synth + * mode applies to all 5G channels + */ + uint8_t futureBase[21]; } __packed BASE_EEP_HEADER; // 64 B typedef struct ModalEepHeader { @@ -210,14 +230,14 @@ typedef struct ModalEepHeader { uint8_t ob_ch1; // 1 -> ob and db become chain specific from AR9280 uint8_t db_ch1; // 1 uint8_t flagBits; // 1 -#define AR5416_EEP_FLAG_USEANT1 0x01 /* +1 configured antenna */ -#define AR5416_EEP_FLAG_FORCEXPAON 0x02 /* force XPA bit for 5G */ -#define AR5416_EEP_FLAG_LOCALBIAS 0x04 /* enable local bias */ -#define AR5416_EEP_FLAG_FEMBANDSELECT 0x08 /* FEM band select used */ -#define AR5416_EEP_FLAG_XLNABUFIN 0x10 -#define AR5416_EEP_FLAG_XLNAISEL 0x60 -#define AR5416_EEP_FLAG_XLNAISEL_S 5 -#define AR5416_EEP_FLAG_XLNABUFMODE 0x80 +#define AR5416_EEP_FLAG_USEANT1 0x80 /* +1 configured antenna */ +#define AR5416_EEP_FLAG_FORCEXPAON 0x40 /* force XPA bit for 5G */ +#define AR5416_EEP_FLAG_LOCALBIAS 0x20 /* enable local bias */ +#define AR5416_EEP_FLAG_FEMBANDSELECT 0x10 /* FEM band select used */ +#define AR5416_EEP_FLAG_XLNABUFIN 0x08 +#define AR5416_EEP_FLAG_XLNAISEL1 0x04 +#define AR5416_EEP_FLAG_XLNAISEL2 0x02 +#define AR5416_EEP_FLAG_XLNABUFMODE 0x01 uint8_t miscBits; // [0..1]: bb_tx_dac_scale_cck uint16_t xpaBiasLvlFreq[3]; // 3 uint8_t futureModal[6]; // 6 diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_eeprom_v3.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_eeprom_v3.c index 89a23c9f9f..3a7b0cc222 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_eeprom_v3.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_eeprom_v3.c @@ -1665,7 +1665,7 @@ legacyEepromGet(struct ath_hal *ah, int param, void *val) return HAL_EINVAL; } -static HAL_BOOL +static HAL_STATUS legacyEepromSet(struct ath_hal *ah, int param, int v) { HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_eeprom_v3.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_eeprom_v3.h index 9f30c72509..cde9a10af3 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_eeprom_v3.h +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_eeprom_v3.h @@ -14,7 +14,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * $Id: ah_eeprom_v3.h,v 1.2 2008/11/10 04:08:00 sam Exp $ + * $FreeBSD$ */ #ifndef _ATH_AH_EEPROM_V3_H_ #define _ATH_AH_EEPROM_V3_H_ diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_eeprom_v4k.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_eeprom_v4k.c index 03bb04c08a..927f08e394 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_eeprom_v4k.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_eeprom_v4k.c @@ -38,11 +38,8 @@ v4kEepromGet(struct ath_hal *ah, int param, void *val) int i; switch (param) { - case AR_EEP_NFTHRESH_5: - *(int16_t *)val = pModal[0].noiseFloorThreshCh[0]; - return HAL_OK; case AR_EEP_NFTHRESH_2: - *(int16_t *)val = pModal[1].noiseFloorThreshCh[0]; + *(int16_t *)val = pModal->noiseFloorThreshCh[0]; return HAL_OK; case AR_EEP_MACADDR: /* Get MAC Address */ sum = 0; @@ -67,14 +64,10 @@ v4kEepromGet(struct ath_hal *ah, int param, void *val) return pBase->opCapFlags; case AR_EEP_RFSILENT: return pBase->rfSilent; - case AR_EEP_OB_5: - return pModal[CHAN_A_IDX].ob; - case AR_EEP_DB_5: - return pModal[CHAN_A_IDX].db; case AR_EEP_OB_2: - return pModal[CHAN_B_IDX].ob; + return pModal->ob_0; case AR_EEP_DB_2: - return pModal[CHAN_B_IDX].db; + return pModal->db1_1; case AR_EEP_TXMASK: return pBase->txMask; case AR_EEP_RXMASK: @@ -82,13 +75,10 @@ v4kEepromGet(struct ath_hal *ah, int param, void *val) case AR_EEP_RXGAIN_TYPE: return AR5416_EEP_RXGAIN_ORIG; case AR_EEP_TXGAIN_TYPE: - return IS_VERS(>=, AR5416_EEP_MINOR_VER_19) ? - pBase->txGainType : AR5416_EEP_TXGAIN_ORIG; -#if 0 + return pBase->txGainType; case AR_EEP_OL_PWRCTRL: HALASSERT(val == AH_NULL); - return pBase->openLoopPwrCntl ? HAL_OK : HAL_EIO; -#endif + return HAL_EIO; case AR_EEP_AMODE: HALASSERT(val == AH_NULL); return pBase->opCapFlags & AR5416_OPFLAGS_11A ? @@ -110,15 +100,11 @@ v4kEepromGet(struct ath_hal *ah, int param, void *val) case AR_EEP_AES: case AR_EEP_BURST: case AR_EEP_RFKILL: - case AR_EEP_TURBO5DISABLE: case AR_EEP_TURBO2DISABLE: HALASSERT(val == AH_NULL); return HAL_OK; case AR_EEP_ANTGAINMAX_2: - *(int8_t *) val = ee->ee_antennaGainMax[1]; - return HAL_OK; - case AR_EEP_ANTGAINMAX_5: - *(int8_t *) val = ee->ee_antennaGainMax[0]; + *(int8_t *) val = ee->ee_antennaGainMax; return HAL_OK; default: HALASSERT(0); @@ -129,17 +115,14 @@ v4kEepromGet(struct ath_hal *ah, int param, void *val) #undef CHAN_B_IDX } -static HAL_BOOL +static HAL_STATUS v4kEepromSet(struct ath_hal *ah, int param, int v) { HAL_EEPROM_v4k *ee = AH_PRIVATE(ah)->ah_eeprom; switch (param) { case AR_EEP_ANTGAINMAX_2: - ee->ee_antennaGainMax[1] = (int8_t) v; - return HAL_OK; - case AR_EEP_ANTGAINMAX_5: - ee->ee_antennaGainMax[0] = (int8_t) v; + ee->ee_antennaGainMax = (int8_t) v; return HAL_OK; } return HAL_EINVAL; @@ -153,8 +136,8 @@ v4kEepromDiag(struct ath_hal *ah, int request, switch (request) { case HAL_DIAG_EEPROM: - *result = &ee->ee_base; - *resultsize = sizeof(ee->ee_base); + *result = ee; + *resultsize = sizeof(HAL_EEPROM_v4k); return AH_TRUE; } return AH_FALSE; @@ -252,7 +235,7 @@ v4kEepromReadCTLInfo(struct ath_hal *ah, HAL_EEPROM_v4k *ee) RD_EDGES_POWER *rep = ee->ee_rdEdgesPower; int i, j; - HALASSERT(AR5416_NUM_CTLS <= sizeof(ee->ee_rdEdgesPower)/NUM_EDGES); + HALASSERT(AR5416_4K_NUM_CTLS <= sizeof(ee->ee_rdEdgesPower)/NUM_EDGES); for (i = 0; ee->ee_base.ctlIndex[i] != 0 && i < AR5416_4K_NUM_CTLS; i++) { for (j = 0; j < NUM_EDGES; j ++) { @@ -304,11 +287,17 @@ ath_hal_v4kEepromAttach(struct ath_hal *ah) uint32_t sum; HALASSERT(ee == AH_NULL); - - if (!ath_hal_eepromRead(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) { - HALDEBUG(ah, HAL_DEBUG_ANY, - "%s Error reading Eeprom MAGIC\n", __func__); - return HAL_EEREAD; + /* + * Don't check magic if we're supplied with an EEPROM block, + * typically this is from Howl but it may also be from later + * boards w/ an embedded WMAC. + */ + if (ah->ah_eepromdata == NULL) { + if (!ath_hal_eepromRead(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s Error reading Eeprom MAGIC\n", __func__); + return HAL_EEREAD; + } } HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s Eeprom Magic = 0x%x\n", __func__, magic); @@ -334,7 +323,11 @@ ath_hal_v4kEepromAttach(struct ath_hal *ah) } } /* Convert to eeprom native eeprom endian format */ - if (isBigEndian()) { + /* + * XXX this is likely incorrect but will do for now + * XXX to get embedded boards working. + */ + if (ah->ah_eepromdata == NULL && isBigEndian()) { for (w = 0; w < NW(struct ar5416eeprom_4k); w++) eep_data[w] = __bswap16(eep_data[w]); } diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_eeprom_v4k.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_eeprom_v4k.h index fd0c69979a..3487de4724 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_eeprom_v4k.h +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_eeprom_v4k.h @@ -23,6 +23,14 @@ #include "ah_eeprom.h" #include "ah_eeprom_v14.h" +#if _BYTE_ORDER == _BIG_ENDIAN +#define __BIG_ENDIAN_BITFIELD +#endif + +#define AR9285_RDEXT_DEFAULT 0x1F + +#define AR5416_4K_EEP_PD_GAIN_BOUNDARY_DEFAULT 58 + #undef owl_eep_start_loc #ifdef __LINUX_ARM_ARCH__ /* AP71 */ #define owl_eep_start_loc 0 @@ -68,15 +76,15 @@ typedef struct BaseEepHeader4k { } __packed BASE_EEP4K_HEADER; // 32 B typedef struct ModalEepHeader4k { - uint32_t antCtrlChain[AR5416_4K_MAX_CHAINS]; // 12 + uint32_t antCtrlChain[AR5416_4K_MAX_CHAINS]; // 4 uint32_t antCtrlCommon; // 4 int8_t antennaGainCh[AR5416_4K_MAX_CHAINS]; // 1 uint8_t switchSettling; // 1 - uint8_t txRxAttenCh[AR5416_4K_MAX_CHAINS]; // 1 + uint8_t txRxAttenCh[AR5416_4K_MAX_CHAINS]; // 1 uint8_t rxTxMarginCh[AR5416_4K_MAX_CHAINS]; // 1 uint8_t adcDesiredSize; // 1 int8_t pgaDesiredSize; // 1 - uint8_t xlnaGainCh[AR5416_4K_MAX_CHAINS]; // 1 + uint8_t xlnaGainCh[AR5416_4K_MAX_CHAINS]; // 1 uint8_t txEndToXpaOff; // 1 uint8_t txEndToRxOn; // 1 uint8_t txFrameToXpaOn; // 1 @@ -86,14 +94,18 @@ typedef struct ModalEepHeader4k { uint8_t xpd; // 1 int8_t iqCalICh[AR5416_4K_MAX_CHAINS]; // 1 int8_t iqCalQCh[AR5416_4K_MAX_CHAINS]; // 1 + uint8_t pdGainOverlap; // 1 - uint8_t ob; // 1 - uint8_t db; // 1 - uint8_t xpaBiasLvl; // 1 -#if 0 - uint8_t pwrDecreaseFor2Chain; // 1 - uint8_t pwrDecreaseFor3Chain; // 1 -> 48 B + +#ifdef __BIG_ENDIAN_BITFIELD + uint8_t ob_1:4, ob_0:4; // 1 + uint8_t db1_1:4, db1_0:4; // 1 +#else + uint8_t ob_0:4, ob_1:4; + uint8_t db1_0:4, db1_1:4; #endif + + uint8_t xpaBiasLvl; // 1 uint8_t txFrameToDataStart; // 1 uint8_t txFrameToPaOn; // 1 uint8_t ht40PowerIncForPdadc; // 1 @@ -102,23 +114,38 @@ typedef struct ModalEepHeader4k { uint8_t swSettleHt40; // 1 uint8_t xatten2Db[AR5416_4K_MAX_CHAINS]; // 1 uint8_t xatten2Margin[AR5416_4K_MAX_CHAINS]; // 1 - uint8_t ob_ch1; // 1 -> ob and db become chain specific from AR9280 - uint8_t db_ch1; // 1 - uint8_t flagBits; // 1 -#define AR5416_EEP_FLAG_USEANT1 0x01 /* +1 configured antenna */ -#define AR5416_EEP_FLAG_FORCEXPAON 0x02 /* force XPA bit for 5G */ -#define AR5416_EEP_FLAG_LOCALBIAS 0x04 /* enable local bias */ -#define AR5416_EEP_FLAG_FEMBANDSELECT 0x08 /* FEM band select used */ -#define AR5416_EEP_FLAG_XLNABUFIN 0x10 -#define AR5416_EEP_FLAG_XLNAISEL 0x60 -#define AR5416_EEP_FLAG_XLNAISEL_S 5 -#define AR5416_EEP_FLAG_XLNABUFMODE 0x80 - uint8_t miscBits; // [0..1]: bb_tx_dac_scale_cck - uint16_t xpaBiasLvlFreq[3]; // 6 - uint8_t futureModal[2]; // 2 + +#ifdef __BIG_ENDIAN_BITFIELD + uint8_t db2_1:4, db2_0:4; // 1 +#else + uint8_t db2_0:4, db2_1:4; // 1 +#endif + + uint8_t version; // 1 + +#ifdef __BIG_ENDIAN_BITFIELD + uint8_t ob_3:4, ob_2:4; // 1 + uint8_t antdiv_ctl1:4, ob_4:4; // 1 + uint8_t db1_3:4, db1_2:4; // 1 + uint8_t antdiv_ctl2:4, db1_4:4; // 1 + uint8_t db2_2:4, db2_3:4; // 1 + uint8_t reserved:4, db2_4:4; // 1 +#else + uint8_t ob_2:4, ob_3:4; + uint8_t ob_4:4, antdiv_ctl1:4; + uint8_t db1_2:4, db1_3:4; + uint8_t db1_4:4, antdiv_ctl2:4; + uint8_t db2_2:4, db2_3:4; + uint8_t db2_4:4, reserved:4; +#endif + uint8_t tx_diversity; + uint8_t flc_pwr_thresh; + uint8_t bb_scale_smrt_antenna; +#define EEP_4K_BB_DESIRED_SCALE_MASK 0x1f + uint8_t futureModal[1]; SPUR_CHAN spurChans[AR5416_EEPROM_MODAL_SPURS]; // 20 B -} __packed MODAL_EEP4K_HEADER; // == 68 B +} __packed MODAL_EEP4K_HEADER; // == 68 B typedef struct CalCtlData4k { CAL_CTL_EDGES ctlEdges[AR5416_4K_MAX_CHAINS][AR5416_4K_NUM_BAND_EDGES]; @@ -150,6 +177,6 @@ typedef struct { uint16_t ee_numCtls; RD_EDGES_POWER ee_rdEdgesPower[NUM_EDGES*AR5416_4K_NUM_CTLS]; /* XXX these are dynamically calculated for use by shared code */ - int8_t ee_antennaGainMax[2]; + int8_t ee_antennaGainMax; } HAL_EEPROM_v4k; #endif /* _AH_EEPROM_V4K_H_ */ diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_internal.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_internal.h index 8f7ba65cb0..79184bd236 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_internal.h +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_internal.h @@ -28,6 +28,7 @@ #define AH_MAX(a,b) ((a)>(b)?(a):(b)) #include +#include "opt_ah.h" /* needed for AH_SUPPORT_AR5416 */ #ifndef NBBY #define NBBY 8 /* number of bits/byte */ @@ -80,7 +81,8 @@ struct ath_hal_chip { const char *name; const char *(*probe)(uint16_t vendorid, uint16_t devid); struct ath_hal *(*attach)(uint16_t devid, HAL_SOFTC, - HAL_BUS_TAG, HAL_BUS_HANDLE, HAL_STATUS *error); + HAL_BUS_TAG, HAL_BUS_HANDLE, uint16_t *eepromdata, + HAL_STATUS *error); }; #ifndef AH_CHIP #define AH_CHIP(_name, _probe, _attach) \ @@ -135,11 +137,16 @@ typedef struct { #define CHANNEL_IQVALID 0x01 /* IQ calibration valid */ #define CHANNEL_ANI_INIT 0x02 /* ANI state initialized */ #define CHANNEL_ANI_SETUP 0x04 /* ANI state setup */ +#define CHANNEL_MIMO_NF_VALID 0x04 /* Mimo NF values are valid */ uint8_t calValid; /* bitmask of cal types */ int8_t iCoff; int8_t qCoff; int16_t rawNoiseFloor; int16_t noiseFloorAdjust; +#ifdef AH_SUPPORT_AR5416 + int16_t noiseFloorCtl[AH_MIMO_MAX_CHAINS]; + int16_t noiseFloorExt[AH_MIMO_MAX_CHAINS]; +#endif /* AH_SUPPORT_AR5416 */ uint16_t mainSpur; /* cached spur value for this channel */ } HAL_CHANNEL_INTERNAL; @@ -177,6 +184,7 @@ typedef struct { halChanHalfRate : 1, halChanQuarterRate : 1, halHTSupport : 1, + halHTSGI20Support : 1, halRfSilentSupport : 1, halHwPhyCounterSupport : 1, halWowSupport : 1, @@ -190,11 +198,18 @@ typedef struct { halCSTSupport : 1, halRifsRxSupport : 1, halRifsTxSupport : 1, + hal4AddrAggrSupport : 1, halExtChanDfsSupport : 1, + halUseCombinedRadarRssi : 1, halForcePpmSupport : 1, halEnhancedPmSupport : 1, + halEnhancedDfsSupport : 1, halMbssidAggrSupport : 1, - halBssidMatchSupport : 1; + halBssidMatchSupport : 1, + hal4kbSplitTransSupport : 1, + halHasRxSelfLinkedTail : 1, + halSupportsFastClock5GHz : 1, /* Hardware supports 5ghz fast clock; check eeprom/channel before using */ + halHasLongRxDescTsf : 1; uint32_t halWirelessModes; uint16_t halTotalQueues; uint16_t halKeyCacheSize; @@ -208,6 +223,8 @@ typedef struct { uint8_t halNumAntCfg2GHz; uint8_t halNumAntCfg5GHz; uint32_t halIntrMask; + uint8_t halTxStreams; + uint8_t halRxStreams; } HAL_CAPABILITIES; struct regDomain; @@ -255,7 +272,7 @@ struct ath_hal_private { uint16_t ah_eeversion; /* EEPROM version */ void (*ah_eepromDetach)(struct ath_hal *); HAL_STATUS (*ah_eepromGet)(struct ath_hal *, int, void *); - HAL_BOOL (*ah_eepromSet)(struct ath_hal *, int, int); + HAL_STATUS (*ah_eepromSet)(struct ath_hal *, int, int); uint16_t (*ah_getSpurChan)(struct ath_hal *, int, HAL_BOOL); HAL_BOOL (*ah_eepromDiag)(struct ath_hal *, int request, const void *args, uint32_t argsize, @@ -286,6 +303,8 @@ struct ath_hal_private { * State for regulatory domain handling. */ HAL_REG_DOMAIN ah_currentRD; /* EEPROM regulatory domain */ + HAL_REG_DOMAIN ah_currentRDext; /* EEPROM extended regdomain flags */ + HAL_DFS_DOMAIN ah_dfsDomain; /* current DFS domain */ HAL_CHANNEL_INTERNAL ah_channels[AH_MAXCHAN]; /* private chan state */ u_int ah_nchan; /* valid items in ah_channels */ const struct regDomain *ah_rd2GHz; /* reg state for 2G band */ @@ -334,6 +353,8 @@ struct ath_hal_private { (_ah)->ah_configPCIE(_ah, _reset) #define ath_hal_disablePCIE(_ah) \ (_ah)->ah_disablePCIE(_ah) +#define ath_hal_setInterrupts(_ah, _mask) \ + (_ah)->ah_setInterrupts(_ah, _mask) #define ath_hal_eepromDetach(_ah) do { \ if (AH_PRIVATE(_ah)->ah_eepromDetach != AH_NULL) \ @@ -401,17 +422,6 @@ extern HAL_BOOL ath_hal_setTxQProps(struct ath_hal *ah, extern HAL_BOOL ath_hal_getTxQProps(struct ath_hal *ah, HAL_TXQ_INFO *qInfo, const HAL_TX_QUEUE_INFO *qi); -typedef enum { - HAL_ANI_PRESENT, /* is ANI support present */ - HAL_ANI_NOISE_IMMUNITY_LEVEL, /* set level */ - HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION, /* enable/disable */ - HAL_ANI_CCK_WEAK_SIGNAL_THR, /* enable/disable */ - HAL_ANI_FIRSTEP_LEVEL, /* set level */ - HAL_ANI_SPUR_IMMUNITY_LEVEL, /* set level */ - HAL_ANI_MODE = 6, /* 0 => manual, 1 => auto (XXX do not change) */ - HAL_ANI_PHYERR_RESET, /* reset phy error stats */ -} HAL_ANI_CMD; - #define HAL_SPUR_VAL_MASK 0x3FFF #define HAL_SPUR_CHAN_WIDTH 87 #define HAL_BIN_WIDTH_BASE_100HZ 3125 @@ -453,6 +463,8 @@ isBigEndian(void) */ #define SM(_v, _f) (((_v) << _f##_S) & (_f)) #define MS(_v, _f) (((_v) & (_f)) >> _f##_S) +#define OS_REG_RMW(_a, _r, _set, _clr) \ + OS_REG_WRITE(_a, _r, (OS_REG_READ(_a, _r) & ~(_clr)) | (_set)) #define OS_REG_RMW_FIELD(_a, _r, _f, _v) \ OS_REG_WRITE(_a, _r, \ (OS_REG_READ(_a, _r) &~ (_f)) | (((_v) << _f##_S) & (_f))) @@ -461,14 +473,15 @@ isBigEndian(void) #define OS_REG_CLR_BIT(_a, _r, _f) \ OS_REG_WRITE(_a, _r, OS_REG_READ(_a, _r) &~ (_f)) -/* system-configurable parameters */ -extern int ath_hal_dma_beacon_response_time; /* in TU's */ -extern int ath_hal_sw_beacon_response_time; /* in TU's */ -extern int ath_hal_additional_swba_backoff; /* in TU's */ +/* Analog register writes may require a delay between each one (eg Merlin?) */ +#define OS_A_REG_RMW_FIELD(_a, _r, _f, _v) \ + do { OS_REG_WRITE(_a, _r, (OS_REG_READ(_a, _r) &~ (_f)) | (((_v) << _f##_S) & (_f))) ; OS_DELAY(100); } while (0) /* wait for the register contents to have the specified value */ extern HAL_BOOL ath_hal_wait(struct ath_hal *, u_int reg, uint32_t mask, uint32_t val); +extern HAL_BOOL ath_hal_waitfor(struct ath_hal *, u_int reg, + uint32_t mask, uint32_t val, uint32_t timeout); /* return the first n bits in val reversed */ extern uint32_t ath_hal_reverseBits(uint32_t val, uint32_t n); @@ -487,11 +500,38 @@ extern void ath_hal_free(void *); /* common debugging interfaces */ #ifdef AH_DEBUG #include "ah_debug.h" -extern int ath_hal_debug; -extern void HALDEBUG(struct ath_hal *ah, u_int mask, const char* fmt, ...) +extern int ath_hal_debug; /* Global debug flags */ + +/* + * This is used for global debugging, when ahp doesn't yet have the + * related debugging state. For example, during probe/attach. + */ +#define HALDEBUG_G(_ah, __m, ...) \ + do { \ + if ((__m) == HAL_DEBUG_UNMASKABLE || \ + ath_hal_debug & (__m)) { \ + DO_HALDEBUG((_ah), (__m), __VA_ARGS__); \ + } \ + } while (0); + +/* + * This is used for local debugging, when ahp isn't NULL and + * thus may have debug flags set. + */ +#define HALDEBUG(_ah, __m, ...) \ + do { \ + if ((__m) == HAL_DEBUG_UNMASKABLE || \ + ath_hal_debug & (__m) || \ + (_ah)->ah_config.ah_debug & (__m)) { \ + DO_HALDEBUG((_ah), (__m), __VA_ARGS__); \ + } \ + } while(0); + +extern void DO_HALDEBUG(struct ath_hal *ah, u_int mask, const char* fmt, ...) __printflike(3,4); #else -#define HALDEBUG(_ah, __m, _fmt, ...) +#define HALDEBUG(_ah, __m, ...) +#define HALDEBUG_G(_ah, __m, ...) #endif /* AH_DEBUG */ /* @@ -587,45 +627,8 @@ extern HAL_BOOL ath_hal_setcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, uint32_t capability, uint32_t setting, HAL_STATUS *status); -/* - * Diagnostic interface. This is an open-ended interface that - * is opaque to applications. Diagnostic programs use this to - * retrieve internal data structures, etc. There is no guarantee - * that calling conventions for calls other than HAL_DIAG_REVS - * are stable between HAL releases; a diagnostic application must - * use the HAL revision information to deal with ABI/API differences. - * - * NB: do not renumber these, certain codes are publicly used. - */ -enum { - HAL_DIAG_REVS = 0, /* MAC/PHY/Radio revs */ - HAL_DIAG_EEPROM = 1, /* EEPROM contents */ - HAL_DIAG_EEPROM_EXP_11A = 2, /* EEPROM 5112 power exp for 11a */ - HAL_DIAG_EEPROM_EXP_11B = 3, /* EEPROM 5112 power exp for 11b */ - HAL_DIAG_EEPROM_EXP_11G = 4, /* EEPROM 5112 power exp for 11g */ - HAL_DIAG_ANI_CURRENT = 5, /* ANI current channel state */ - HAL_DIAG_ANI_OFDM = 6, /* ANI OFDM timing error stats */ - HAL_DIAG_ANI_CCK = 7, /* ANI CCK timing error stats */ - HAL_DIAG_ANI_STATS = 8, /* ANI statistics */ - HAL_DIAG_RFGAIN = 9, /* RfGain GAIN_VALUES */ - HAL_DIAG_RFGAIN_CURSTEP = 10, /* RfGain GAIN_OPTIMIZATION_STEP */ - HAL_DIAG_PCDAC = 11, /* PCDAC table */ - HAL_DIAG_TXRATES = 12, /* Transmit rate table */ - HAL_DIAG_REGS = 13, /* Registers */ - HAL_DIAG_ANI_CMD = 14, /* ANI issue command (XXX do not change!) */ - HAL_DIAG_SETKEY = 15, /* Set keycache backdoor */ - HAL_DIAG_RESETKEY = 16, /* Reset keycache backdoor */ - HAL_DIAG_EEREAD = 17, /* Read EEPROM word */ - HAL_DIAG_EEWRITE = 18, /* Write EEPROM word */ - /* 19-26 removed, do not reuse */ - HAL_DIAG_RDWRITE = 27, /* Write regulatory domain */ - HAL_DIAG_RDREAD = 28, /* Get regulatory domain */ - HAL_DIAG_FATALERR = 29, /* Read cached interrupt state */ - HAL_DIAG_11NCOMPAT = 30, /* 11n compatibility tweaks */ - HAL_DIAG_ANI_PARAMS = 31, /* ANI noise immunity parameters */ - HAL_DIAG_CHECK_HANGS = 32, /* check h/w hangs */ - HAL_DIAG_SETREGS = 33, /* write registers */ -}; +/* The diagnostic codes used to be internally defined here -adrian */ +#include "ah_diagcodes.h" enum { HAL_BB_HANG_DFS = 0x0001, @@ -801,4 +804,31 @@ extern int ath_hal_ini_bank_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia, #define TURBO_SYMBOL_TIME 4 #define WLAN_CTRL_FRAME_SIZE (2+2+6+4) /* ACK+FCS */ + +/* Generic EEPROM board value functions */ +extern HAL_BOOL ath_ee_getLowerUpperIndex(uint8_t target, uint8_t *pList, + uint16_t listSize, uint16_t *indexL, uint16_t *indexR); +extern HAL_BOOL ath_ee_FillVpdTable(uint8_t pwrMin, uint8_t pwrMax, + uint8_t *pPwrList, uint8_t *pVpdList, uint16_t numIntercepts, + uint8_t *pRetVpdList); +extern int16_t ath_ee_interpolate(uint16_t target, uint16_t srcLeft, + uint16_t srcRight, int16_t targetLeft, int16_t targetRight); + +/* Whether 5ghz fast clock is needed */ +/* + * The chipset (Merlin, AR9300/later) should set the capability flag below; + * this flag simply says that the hardware can do it, not that the EEPROM + * says it can. + * + * Merlin 2.0/2.1 chips with an EEPROM version > 16 do 5ghz fast clock + * if the relevant eeprom flag is set. + * Merlin 2.0/2.1 chips with an EEPROM version <= 16 do 5ghz fast clock + * by default. + */ +#define IS_5GHZ_FAST_CLOCK_EN(_ah, _c) \ + (IEEE80211_IS_CHAN_5GHZ(_c) && \ + AH_PRIVATE((_ah))->ah_caps.halSupportsFastClock5GHz && \ + ath_hal_eepromGetFlag((_ah), AR_EEP_FSTCLK_5G)) + + #endif /* _ATH_AH_INTERAL_H_ */ diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_regdomain.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_regdomain.c index 515c753a1f..7298c6bee8 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_regdomain.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_regdomain.c @@ -28,6 +28,8 @@ #include "ah_eeprom.h" #include "ah_devid.h" +#include "ah_regdomain.h" + /* * XXX this code needs a audit+review */ @@ -38,48 +40,6 @@ #define HAL_MODE_11A_TURBO HAL_MODE_108A #define HAL_MODE_11G_TURBO HAL_MODE_108G -/* - * BMLEN defines the size of the bitmask used to hold frequency - * band specifications. Note this must agree with the BM macro - * definition that's used to setup initializers. See also further - * comments below. - */ -#define BMLEN 2 /* 2 x 64 bits in each channel bitmask */ -typedef uint64_t chanbmask_t[BMLEN]; - -#define W0(_a) \ - (((_a) >= 0 && (_a) < 64 ? (((uint64_t) 1)<<(_a)) : (uint64_t) 0)) -#define W1(_a) \ - (((_a) > 63 && (_a) < 128 ? (((uint64_t) 1)<<((_a)-64)) : (uint64_t) 0)) -#define BM1(_fa) { W0(_fa), W1(_fa) } -#define BM2(_fa, _fb) { W0(_fa) | W0(_fb), W1(_fa) | W1(_fb) } -#define BM3(_fa, _fb, _fc) \ - { W0(_fa) | W0(_fb) | W0(_fc), W1(_fa) | W1(_fb) | W1(_fc) } -#define BM4(_fa, _fb, _fc, _fd) \ - { W0(_fa) | W0(_fb) | W0(_fc) | W0(_fd), \ - W1(_fa) | W1(_fb) | W1(_fc) | W1(_fd) } -#define BM5(_fa, _fb, _fc, _fd, _fe) \ - { W0(_fa) | W0(_fb) | W0(_fc) | W0(_fd) | W0(_fe), \ - W1(_fa) | W1(_fb) | W1(_fc) | W1(_fd) | W1(_fe) } -#define BM6(_fa, _fb, _fc, _fd, _fe, _ff) \ - { W0(_fa) | W0(_fb) | W0(_fc) | W0(_fd) | W0(_fe) | W0(_ff), \ - W1(_fa) | W1(_fb) | W1(_fc) | W1(_fd) | W1(_fe) | W1(_ff) } -#define BM7(_fa, _fb, _fc, _fd, _fe, _ff, _fg) \ - { W0(_fa) | W0(_fb) | W0(_fc) | W0(_fd) | W0(_fe) | W0(_ff) | \ - W0(_fg),\ - W1(_fa) | W1(_fb) | W1(_fc) | W1(_fd) | W1(_fe) | W1(_ff) | \ - W1(_fg) } -#define BM8(_fa, _fb, _fc, _fd, _fe, _ff, _fg, _fh) \ - { W0(_fa) | W0(_fb) | W0(_fc) | W0(_fd) | W0(_fe) | W0(_ff) | \ - W0(_fg) | W0(_fh) , \ - W1(_fa) | W1(_fb) | W1(_fc) | W1(_fd) | W1(_fe) | W1(_ff) | \ - W1(_fg) | W1(_fh) } -#define BM9(_fa, _fb, _fc, _fd, _fe, _ff, _fg, _fh, _fi) \ - { W0(_fa) | W0(_fb) | W0(_fc) | W0(_fd) | W0(_fe) | W0(_ff) | \ - W0(_fg) | W0(_fh) | W0(_fi) , \ - W1(_fa) | W1(_fb) | W1(_fc) | W1(_fd) | W1(_fe) | W1(_ff) | \ - W1(_fg) | W1(_fh) | W1(_fi) } - /* * Mask to check whether a domain is a multidomain or a single domain */ @@ -91,350 +51,16 @@ typedef uint64_t chanbmask_t[BMLEN]; * are the real unitary regdomains and are the only ones which have the * frequency bitmasks and flags set. */ -enum { - /* - * The following regulatory domain definitions are - * found in the EEPROM. Each regulatory domain - * can operate in either a 5GHz or 2.4GHz wireless mode or - * both 5GHz and 2.4GHz wireless modes. - * In general, the value holds no special - * meaning and is used to decode into either specific - * 2.4GHz or 5GHz wireless mode for that particular - * regulatory domain. - */ - NO_ENUMRD = 0x00, - NULL1_WORLD = 0x03, /* For 11b-only countries (no 11a allowed) */ - NULL1_ETSIB = 0x07, /* Israel */ - NULL1_ETSIC = 0x08, - FCC1_FCCA = 0x10, /* USA */ - FCC1_WORLD = 0x11, /* Hong Kong */ - FCC4_FCCA = 0x12, /* USA - Public Safety */ - FCC5_FCCB = 0x13, /* USA w/ 1/2 and 1/4 width channels */ - - FCC2_FCCA = 0x20, /* Canada */ - FCC2_WORLD = 0x21, /* Australia & HK */ - FCC2_ETSIC = 0x22, - FRANCE_RES = 0x31, /* Legacy France for OEM */ - FCC3_FCCA = 0x3A, /* USA & Canada w/5470 band, 11h, DFS enabled */ - FCC3_WORLD = 0x3B, /* USA & Canada w/5470 band, 11h, DFS enabled */ - - ETSI1_WORLD = 0x37, - ETSI3_ETSIA = 0x32, /* France (optional) */ - ETSI2_WORLD = 0x35, /* Hungary & others */ - ETSI3_WORLD = 0x36, /* France & others */ - ETSI4_WORLD = 0x30, - ETSI4_ETSIC = 0x38, - ETSI5_WORLD = 0x39, - ETSI6_WORLD = 0x34, /* Bulgaria */ - ETSI_RESERVED = 0x33, /* Reserved (Do not used) */ - - MKK1_MKKA = 0x40, /* Japan (JP1) */ - MKK1_MKKB = 0x41, /* Japan (JP0) */ - APL4_WORLD = 0x42, /* Singapore */ - MKK2_MKKA = 0x43, /* Japan with 4.9G channels */ - APL_RESERVED = 0x44, /* Reserved (Do not used) */ - APL2_WORLD = 0x45, /* Korea */ - APL2_APLC = 0x46, - APL3_WORLD = 0x47, - MKK1_FCCA = 0x48, /* Japan (JP1-1) */ - APL2_APLD = 0x49, /* Korea with 2.3G channels */ - MKK1_MKKA1 = 0x4A, /* Japan (JE1) */ - MKK1_MKKA2 = 0x4B, /* Japan (JE2) */ - MKK1_MKKC = 0x4C, /* Japan (MKK1_MKKA,except Ch14) */ - - APL3_FCCA = 0x50, - APL1_WORLD = 0x52, /* Latin America */ - APL1_FCCA = 0x53, - APL1_APLA = 0x54, - APL1_ETSIC = 0x55, - APL2_ETSIC = 0x56, /* Venezuela */ - APL5_WORLD = 0x58, /* Chile */ - APL6_WORLD = 0x5B, /* Singapore */ - APL7_FCCA = 0x5C, /* Taiwan 5.47 Band */ - APL8_WORLD = 0x5D, /* Malaysia 5GHz */ - APL9_WORLD = 0x5E, /* Korea 5GHz */ - - /* - * World mode SKUs - */ - WOR0_WORLD = 0x60, /* World0 (WO0 SKU) */ - WOR1_WORLD = 0x61, /* World1 (WO1 SKU) */ - WOR2_WORLD = 0x62, /* World2 (WO2 SKU) */ - WOR3_WORLD = 0x63, /* World3 (WO3 SKU) */ - WOR4_WORLD = 0x64, /* World4 (WO4 SKU) */ - WOR5_ETSIC = 0x65, /* World5 (WO5 SKU) */ - - WOR01_WORLD = 0x66, /* World0-1 (WW0-1 SKU) */ - WOR02_WORLD = 0x67, /* World0-2 (WW0-2 SKU) */ - EU1_WORLD = 0x68, /* Same as World0-2 (WW0-2 SKU), except active scan ch1-13. No ch14 */ - - WOR9_WORLD = 0x69, /* World9 (WO9 SKU) */ - WORA_WORLD = 0x6A, /* WorldA (WOA SKU) */ - WORB_WORLD = 0x6B, /* WorldB (WOB SKU) */ - - MKK3_MKKB = 0x80, /* Japan UNI-1 even + MKKB */ - MKK3_MKKA2 = 0x81, /* Japan UNI-1 even + MKKA2 */ - MKK3_MKKC = 0x82, /* Japan UNI-1 even + MKKC */ - - MKK4_MKKB = 0x83, /* Japan UNI-1 even + UNI-2 + MKKB */ - MKK4_MKKA2 = 0x84, /* Japan UNI-1 even + UNI-2 + MKKA2 */ - MKK4_MKKC = 0x85, /* Japan UNI-1 even + UNI-2 + MKKC */ - - MKK5_MKKB = 0x86, /* Japan UNI-1 even + UNI-2 + mid-band + MKKB */ - MKK5_MKKA2 = 0x87, /* Japan UNI-1 even + UNI-2 + mid-band + MKKA2 */ - MKK5_MKKC = 0x88, /* Japan UNI-1 even + UNI-2 + mid-band + MKKC */ - - MKK6_MKKB = 0x89, /* Japan UNI-1 even + UNI-1 odd MKKB */ - MKK6_MKKA2 = 0x8A, /* Japan UNI-1 even + UNI-1 odd + MKKA2 */ - MKK6_MKKC = 0x8B, /* Japan UNI-1 even + UNI-1 odd + MKKC */ - - MKK7_MKKB = 0x8C, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKB */ - MKK7_MKKA2 = 0x8D, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKA2 */ - MKK7_MKKC = 0x8E, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKC */ - - MKK8_MKKB = 0x8F, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKB */ - MKK8_MKKA2 = 0x90, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKA2 */ - MKK8_MKKC = 0x91, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKC */ - - /* Following definitions are used only by s/w to map old - * Japan SKUs. - */ - MKK3_MKKA = 0xF0, /* Japan UNI-1 even + MKKA */ - MKK3_MKKA1 = 0xF1, /* Japan UNI-1 even + MKKA1 */ - MKK3_FCCA = 0xF2, /* Japan UNI-1 even + FCCA */ - MKK4_MKKA = 0xF3, /* Japan UNI-1 even + UNI-2 + MKKA */ - MKK4_MKKA1 = 0xF4, /* Japan UNI-1 even + UNI-2 + MKKA1 */ - MKK4_FCCA = 0xF5, /* Japan UNI-1 even + UNI-2 + FCCA */ - MKK9_MKKA = 0xF6, /* Japan UNI-1 even + 4.9GHz */ - MKK10_MKKA = 0xF7, /* Japan UNI-1 even + UNI-2 + 4.9GHz */ - - /* - * Regulator domains ending in a number (e.g. APL1, - * MK1, ETSI4, etc) apply to 5GHz channel and power - * information. Regulator domains ending in a letter - * (e.g. APLA, FCCA, etc) apply to 2.4GHz channel and - * power information. - */ - APL1 = 0x0150, /* LAT & Asia */ - APL2 = 0x0250, /* LAT & Asia */ - APL3 = 0x0350, /* Taiwan */ - APL4 = 0x0450, /* Jordan */ - APL5 = 0x0550, /* Chile */ - APL6 = 0x0650, /* Singapore */ - APL8 = 0x0850, /* Malaysia */ - APL9 = 0x0950, /* Korea (South) ROC 3 */ - - ETSI1 = 0x0130, /* Europe & others */ - ETSI2 = 0x0230, /* Europe & others */ - ETSI3 = 0x0330, /* Europe & others */ - ETSI4 = 0x0430, /* Europe & others */ - ETSI5 = 0x0530, /* Europe & others */ - ETSI6 = 0x0630, /* Europe & others */ - ETSIA = 0x0A30, /* France */ - ETSIB = 0x0B30, /* Israel */ - ETSIC = 0x0C30, /* Latin America */ - - FCC1 = 0x0110, /* US & others */ - FCC2 = 0x0120, /* Canada, Australia & New Zealand */ - FCC3 = 0x0160, /* US w/new middle band & DFS */ - FCC4 = 0x0165, /* US Public Safety */ - FCC5 = 0x0166, /* US w/ 1/2 and 1/4 width channels */ - FCCA = 0x0A10, - FCCB = 0x0A11, /* US w/ 1/2 and 1/4 width channels */ - - APLD = 0x0D50, /* South Korea */ - - MKK1 = 0x0140, /* Japan (UNI-1 odd)*/ - MKK2 = 0x0240, /* Japan (4.9 GHz + UNI-1 odd) */ - MKK3 = 0x0340, /* Japan (UNI-1 even) */ - MKK4 = 0x0440, /* Japan (UNI-1 even + UNI-2) */ - MKK5 = 0x0540, /* Japan (UNI-1 even + UNI-2 + mid-band) */ - MKK6 = 0x0640, /* Japan (UNI-1 odd + UNI-1 even) */ - MKK7 = 0x0740, /* Japan (UNI-1 odd + UNI-1 even + UNI-2 */ - MKK8 = 0x0840, /* Japan (UNI-1 odd + UNI-1 even + UNI-2 + mid-band) */ - MKK9 = 0x0940, /* Japan (UNI-1 even + 4.9 GHZ) */ - MKK10 = 0x0B40, /* Japan (UNI-1 even + UNI-2 + 4.9 GHZ) */ - MKKA = 0x0A40, /* Japan */ - MKKC = 0x0A50, - - NULL1 = 0x0198, - WORLD = 0x0199, - DEBUG_REG_DMN = 0x01ff, -}; +#include "ah_regdomain/ah_rd_regenum.h" #define WORLD_SKU_MASK 0x00F0 #define WORLD_SKU_PREFIX 0x0060 -enum { /* conformance test limits */ - FCC = 0x10, - MKK = 0x40, - ETSI = 0x30, -}; - -/* - * The following are flags for different requirements per reg domain. - * These requirements are either inhereted from the reg domain pair or - * from the unitary reg domain if the reg domain pair flags value is 0 - */ -enum { - NO_REQ = 0x00000000, /* NB: must be zero */ - DISALLOW_ADHOC_11A = 0x00000001, /* adhoc not allowed in 5GHz */ - DISALLOW_ADHOC_11A_TURB = 0x00000002, /* not allowed w/ 5GHz turbo */ - NEED_NFC = 0x00000004, /* need noise floor check */ - ADHOC_PER_11D = 0x00000008, /* must receive 11d beacon */ - LIMIT_FRAME_4MS = 0x00000020, /* 4msec tx burst limit */ - NO_HOSTAP = 0x00000040, /* No HOSTAP mode opereation */ -}; - -/* - * The following describe the bit masks for different passive scan - * capability/requirements per regdomain. - */ -#define NO_PSCAN 0x0ULL /* NB: must be zero */ -#define PSCAN_FCC 0x0000000000000001ULL -#define PSCAN_FCC_T 0x0000000000000002ULL -#define PSCAN_ETSI 0x0000000000000004ULL -#define PSCAN_MKK1 0x0000000000000008ULL -#define PSCAN_MKK2 0x0000000000000010ULL -#define PSCAN_MKKA 0x0000000000000020ULL -#define PSCAN_MKKA_G 0x0000000000000040ULL -#define PSCAN_ETSIA 0x0000000000000080ULL -#define PSCAN_ETSIB 0x0000000000000100ULL -#define PSCAN_ETSIC 0x0000000000000200ULL -#define PSCAN_WWR 0x0000000000000400ULL -#define PSCAN_MKKA1 0x0000000000000800ULL -#define PSCAN_MKKA1_G 0x0000000000001000ULL -#define PSCAN_MKKA2 0x0000000000002000ULL -#define PSCAN_MKKA2_G 0x0000000000004000ULL -#define PSCAN_MKK3 0x0000000000008000ULL -#define PSCAN_DEFER 0x7FFFFFFFFFFFFFFFULL -#define IS_ECM_CHAN 0x8000000000000000ULL - /* * THE following table is the mapping of regdomain pairs specified by * an 8 bit regdomain value to the individual unitary reg domains */ -typedef struct regDomainPair { - HAL_REG_DOMAIN regDmnEnum; /* 16 bit reg domain pair */ - HAL_REG_DOMAIN regDmn5GHz; /* 5GHz reg domain */ - HAL_REG_DOMAIN regDmn2GHz; /* 2GHz reg domain */ - uint32_t flags5GHz; /* Requirements flags (AdHoc - disallow, noise floor cal needed, - etc) */ - uint32_t flags2GHz; /* Requirements flags (AdHoc - disallow, noise floor cal needed, - etc) */ - uint64_t pscanMask; /* Passive Scan flags which - can override unitary domain - passive scan flags. This - value is used as a mask on - the unitary flags*/ - uint16_t singleCC; /* Country code of single country if - a one-on-one mapping exists */ -} REG_DMN_PAIR_MAPPING; - -static REG_DMN_PAIR_MAPPING regDomainPairs[] = { - {NO_ENUMRD, DEBUG_REG_DMN, DEBUG_REG_DMN, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, - {NULL1_WORLD, NULL1, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, - {NULL1_ETSIB, NULL1, ETSIB, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, - {NULL1_ETSIC, NULL1, ETSIC, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, - - {FCC2_FCCA, FCC2, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, - {FCC2_WORLD, FCC2, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, - {FCC2_ETSIC, FCC2, ETSIC, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, - {FCC3_FCCA, FCC3, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, - {FCC3_WORLD, FCC3, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, - {FCC4_FCCA, FCC4, FCCA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, - {FCC5_FCCB, FCC5, FCCB, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, - - {ETSI1_WORLD, ETSI1, WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, - {ETSI2_WORLD, ETSI2, WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, - {ETSI3_WORLD, ETSI3, WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, - {ETSI4_WORLD, ETSI4, WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, - {ETSI5_WORLD, ETSI5, WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, - {ETSI6_WORLD, ETSI6, WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, - - {ETSI3_ETSIA, ETSI3, WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, - {FRANCE_RES, ETSI3, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, - - {FCC1_WORLD, FCC1, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, - {FCC1_FCCA, FCC1, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, - {APL1_WORLD, APL1, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, - {APL2_WORLD, APL2, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, - {APL3_WORLD, APL3, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, - {APL4_WORLD, APL4, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, - {APL5_WORLD, APL5, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, - {APL6_WORLD, APL6, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, - {APL8_WORLD, APL8, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, - {APL9_WORLD, APL9, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, - - {APL3_FCCA, APL3, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, - {APL1_ETSIC, APL1, ETSIC, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, - {APL2_ETSIC, APL2, ETSIC, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, - {APL2_APLD, APL2, APLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, - - {MKK1_MKKA, MKK1, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKKA, CTRY_JAPAN }, - {MKK1_MKKB, MKK1, MKKA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC| LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN1 }, - {MKK1_FCCA, MKK1, FCCA, DISALLOW_ADHOC_11A_TURB | NEED_NFC| LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1, CTRY_JAPAN2 }, - {MKK1_MKKA1, MKK1, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC| LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN4 }, - {MKK1_MKKA2, MKK1, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC| LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN5 }, - {MKK1_MKKC, MKK1, MKKC, DISALLOW_ADHOC_11A_TURB | NEED_NFC| LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1, CTRY_JAPAN6 }, - - /* MKK2 */ - {MKK2_MKKA, MKK2, MKKA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC| LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK2 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN3 }, - - /* MKK3 */ - {MKK3_MKKA, MKK3, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC , PSCAN_MKKA, CTRY_DEFAULT }, - {MKK3_MKKB, MKK3, MKKA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN7 }, - {MKK3_MKKA1, MKK3, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_DEFAULT }, - {MKK3_MKKA2,MKK3, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN8 }, - {MKK3_MKKC, MKK3, MKKC, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, NO_PSCAN, CTRY_JAPAN9 }, - {MKK3_FCCA, MKK3, FCCA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, NO_PSCAN, CTRY_DEFAULT }, - - /* MKK4 */ - {MKK4_MKKB, MKK4, MKKA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN10 }, - {MKK4_MKKA1, MKK4, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_DEFAULT }, - {MKK4_MKKA2, MKK4, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 |PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN11 }, - {MKK4_MKKC, MKK4, MKKC, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3, CTRY_JAPAN12 }, - {MKK4_FCCA, MKK4, FCCA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3, CTRY_DEFAULT }, - - /* MKK5 */ - {MKK5_MKKB, MKK5, MKKA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN13 }, - {MKK5_MKKA2,MKK5, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN14 }, - {MKK5_MKKC, MKK5, MKKC, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3, CTRY_JAPAN15 }, - - /* MKK6 */ - {MKK6_MKKB, MKK6, MKKA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN16 }, - {MKK6_MKKA2, MKK6, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN17 }, - {MKK6_MKKC, MKK6, MKKC, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1, CTRY_JAPAN18 }, - - /* MKK7 */ - {MKK7_MKKB, MKK7, MKKA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN19 }, - {MKK7_MKKA2, MKK7, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN20 }, - {MKK7_MKKC, MKK7, MKKC, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3, CTRY_JAPAN21 }, - - /* MKK8 */ - {MKK8_MKKB, MKK8, MKKA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN22 }, - {MKK8_MKKA2,MKK8, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN23 }, - {MKK8_MKKC, MKK8, MKKC, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3 , CTRY_JAPAN24 }, - - {MKK9_MKKA, MKK9, MKKA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_DEFAULT }, - {MKK10_MKKA, MKK10, MKKA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_DEFAULT }, - - /* These are super domains */ - {WOR0_WORLD, WOR0_WORLD, WOR0_WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, - {WOR1_WORLD, WOR1_WORLD, WOR1_WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, - {WOR2_WORLD, WOR2_WORLD, WOR2_WORLD, DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, - {WOR3_WORLD, WOR3_WORLD, WOR3_WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, - {WOR4_WORLD, WOR4_WORLD, WOR4_WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, - {WOR5_ETSIC, WOR5_ETSIC, WOR5_ETSIC, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, - {WOR01_WORLD, WOR01_WORLD, WOR01_WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, - {WOR02_WORLD, WOR02_WORLD, WOR02_WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, - {EU1_WORLD, EU1_WORLD, EU1_WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, - {WOR9_WORLD, WOR9_WORLD, WOR9_WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, - {WORA_WORLD, WORA_WORLD, WORA_WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, - {WORB_WORLD, WORB_WORLD, WORB_WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, -}; +#include "ah_regdomain/ah_rd_regmap.h" /* * The following tables are the master list for all different freqeuncy @@ -442,1281 +68,35 @@ static REG_DMN_PAIR_MAPPING regDomainPairs[] = { * for each band if it is used in ANY reg domain. */ -#define DEF_REGDMN FCC1_FCCA #define COUNTRY_ERD_FLAG 0x8000 #define WORLDWIDE_ROAMING_FLAG 0x4000 -typedef struct { - HAL_CTRY_CODE countryCode; - HAL_REG_DOMAIN regDmnEnum; -} COUNTRY_CODE_TO_ENUM_RD; - -static COUNTRY_CODE_TO_ENUM_RD allCountries[] = { - { CTRY_DEBUG, NO_ENUMRD }, - { CTRY_DEFAULT, DEF_REGDMN }, - { CTRY_ALBANIA, NULL1_WORLD }, - { CTRY_ALGERIA, NULL1_WORLD }, - { CTRY_ARGENTINA, APL3_WORLD }, - { CTRY_ARMENIA, ETSI4_WORLD }, - { CTRY_AUSTRALIA, FCC2_WORLD }, - { CTRY_AUSTRIA, ETSI1_WORLD }, - { CTRY_AZERBAIJAN, ETSI4_WORLD }, - { CTRY_BAHRAIN, APL6_WORLD }, - { CTRY_BELARUS, NULL1_WORLD }, - { CTRY_BELGIUM, ETSI1_WORLD }, - { CTRY_BELIZE, APL1_ETSIC }, - { CTRY_BOLIVIA, APL1_ETSIC }, - { CTRY_BRAZIL, FCC3_WORLD }, - { CTRY_BRUNEI_DARUSSALAM,APL1_WORLD }, - { CTRY_BULGARIA, ETSI6_WORLD }, - { CTRY_CANADA, FCC2_FCCA }, - { CTRY_CHILE, APL6_WORLD }, - { CTRY_CHINA, APL1_WORLD }, - { CTRY_COLOMBIA, FCC1_FCCA }, - { CTRY_COSTA_RICA, NULL1_WORLD }, - { CTRY_CROATIA, ETSI3_WORLD }, - { CTRY_CYPRUS, ETSI1_WORLD }, - { CTRY_CZECH, ETSI1_WORLD }, - { CTRY_DENMARK, ETSI1_WORLD }, - { CTRY_DOMINICAN_REPUBLIC,FCC1_FCCA }, - { CTRY_ECUADOR, NULL1_WORLD }, - { CTRY_EGYPT, ETSI3_WORLD }, - { CTRY_EL_SALVADOR, NULL1_WORLD }, - { CTRY_ESTONIA, ETSI1_WORLD }, - { CTRY_FINLAND, ETSI1_WORLD }, - { CTRY_FRANCE, ETSI1_WORLD }, - { CTRY_FRANCE2, ETSI3_WORLD }, - { CTRY_GEORGIA, ETSI4_WORLD }, - { CTRY_GERMANY, ETSI1_WORLD }, - { CTRY_GREECE, ETSI1_WORLD }, - { CTRY_GUATEMALA, FCC1_FCCA }, - { CTRY_HONDURAS, NULL1_WORLD }, - { CTRY_HONG_KONG, FCC2_WORLD }, - { CTRY_HUNGARY, ETSI1_WORLD }, - { CTRY_ICELAND, ETSI1_WORLD }, - { CTRY_INDIA, APL6_WORLD }, - { CTRY_INDONESIA, APL1_WORLD }, - { CTRY_IRAN, APL1_WORLD }, - { CTRY_IRELAND, ETSI1_WORLD }, - { CTRY_ISRAEL, NULL1_WORLD }, - { CTRY_ITALY, ETSI1_WORLD }, - { CTRY_JAPAN, MKK1_MKKA }, - { CTRY_JAPAN1, MKK1_MKKB }, - { CTRY_JAPAN2, MKK1_FCCA }, - { CTRY_JAPAN3, MKK2_MKKA }, - { CTRY_JAPAN4, MKK1_MKKA1 }, - { CTRY_JAPAN5, MKK1_MKKA2 }, - { CTRY_JAPAN6, MKK1_MKKC }, - - { CTRY_JAPAN7, MKK3_MKKB }, - { CTRY_JAPAN8, MKK3_MKKA2 }, - { CTRY_JAPAN9, MKK3_MKKC }, - - { CTRY_JAPAN10, MKK4_MKKB }, - { CTRY_JAPAN11, MKK4_MKKA2 }, - { CTRY_JAPAN12, MKK4_MKKC }, - - { CTRY_JAPAN13, MKK5_MKKB }, - { CTRY_JAPAN14, MKK5_MKKA2 }, - { CTRY_JAPAN15, MKK5_MKKC }, - - { CTRY_JAPAN16, MKK6_MKKB }, - { CTRY_JAPAN17, MKK6_MKKA2 }, - { CTRY_JAPAN18, MKK6_MKKC }, - - { CTRY_JAPAN19, MKK7_MKKB }, - { CTRY_JAPAN20, MKK7_MKKA2 }, - { CTRY_JAPAN21, MKK7_MKKC }, - - { CTRY_JAPAN22, MKK8_MKKB }, - { CTRY_JAPAN23, MKK8_MKKA2 }, - { CTRY_JAPAN24, MKK8_MKKC }, - - { CTRY_JORDAN, APL4_WORLD }, - { CTRY_KAZAKHSTAN, NULL1_WORLD }, - { CTRY_KOREA_NORTH, APL2_WORLD }, - { CTRY_KOREA_ROC, APL2_WORLD }, - { CTRY_KOREA_ROC2, APL2_WORLD }, - { CTRY_KOREA_ROC3, APL9_WORLD }, - { CTRY_KUWAIT, NULL1_WORLD }, - { CTRY_LATVIA, ETSI1_WORLD }, - { CTRY_LEBANON, NULL1_WORLD }, - { CTRY_LIECHTENSTEIN,ETSI1_WORLD }, - { CTRY_LITHUANIA, ETSI1_WORLD }, - { CTRY_LUXEMBOURG, ETSI1_WORLD }, - { CTRY_MACAU, FCC2_WORLD }, - { CTRY_MACEDONIA, NULL1_WORLD }, - { CTRY_MALAYSIA, APL8_WORLD }, - { CTRY_MALTA, ETSI1_WORLD }, - { CTRY_MEXICO, FCC1_FCCA }, - { CTRY_MONACO, ETSI4_WORLD }, - { CTRY_MOROCCO, NULL1_WORLD }, - { CTRY_NETHERLANDS, ETSI1_WORLD }, - { CTRY_NEW_ZEALAND, FCC2_ETSIC }, - { CTRY_NORWAY, ETSI1_WORLD }, - { CTRY_OMAN, APL6_WORLD }, - { CTRY_PAKISTAN, NULL1_WORLD }, - { CTRY_PANAMA, FCC1_FCCA }, - { CTRY_PERU, APL1_WORLD }, - { CTRY_PHILIPPINES, FCC3_WORLD }, - { CTRY_POLAND, ETSI1_WORLD }, - { CTRY_PORTUGAL, ETSI1_WORLD }, - { CTRY_PUERTO_RICO, FCC1_FCCA }, - { CTRY_QATAR, NULL1_WORLD }, - { CTRY_ROMANIA, NULL1_WORLD }, - { CTRY_RUSSIA, NULL1_WORLD }, - { CTRY_SAUDI_ARABIA,FCC2_WORLD }, - { CTRY_SINGAPORE, APL6_WORLD }, - { CTRY_SLOVAKIA, ETSI1_WORLD }, - { CTRY_SLOVENIA, ETSI1_WORLD }, - { CTRY_SOUTH_AFRICA,FCC3_WORLD }, - { CTRY_SPAIN, ETSI1_WORLD }, - { CTRY_SWEDEN, ETSI1_WORLD }, - { CTRY_SWITZERLAND, ETSI1_WORLD }, - { CTRY_SYRIA, NULL1_WORLD }, - { CTRY_TAIWAN, APL3_FCCA }, - { CTRY_THAILAND, FCC3_WORLD }, - { CTRY_TRINIDAD_Y_TOBAGO,ETSI4_WORLD }, - { CTRY_TUNISIA, ETSI3_WORLD }, - { CTRY_TURKEY, ETSI3_WORLD }, - { CTRY_UKRAINE, NULL1_WORLD }, - { CTRY_UAE, NULL1_WORLD }, - { CTRY_UNITED_KINGDOM, ETSI1_WORLD }, - { CTRY_UNITED_STATES, FCC1_FCCA }, - { CTRY_UNITED_STATES_FCC49,FCC4_FCCA }, - { CTRY_URUGUAY, FCC1_WORLD }, - { CTRY_UZBEKISTAN, FCC3_FCCA }, - { CTRY_VENEZUELA, APL2_ETSIC }, - { CTRY_VIET_NAM, NULL1_WORLD }, - { CTRY_ZIMBABWE, NULL1_WORLD } -}; - -/* Bit masks for DFS per regdomain */ -enum { - NO_DFS = 0x0000000000000000ULL, /* NB: must be zero */ - DFS_FCC3 = 0x0000000000000001ULL, - DFS_ETSI = 0x0000000000000002ULL, - DFS_MKK4 = 0x0000000000000004ULL, -}; - -#define AFTER(x) ((x)+1) +/* + * This table maps country ISO codes from net80211 into regulatory + * domains which the ath regulatory domain code understands. + */ +#include "ah_regdomain/ah_rd_ctry.h" /* - * Frequency band collections are defined using bitmasks. Each bit - * in a mask is the index of an entry in one of the following tables. - * Bitmasks are BMLEN*64 bits so if a table grows beyond that the bit - * vectors must be enlarged or the tables split somehow (e.g. split - * 1/2 and 1/4 rate channels into a separate table). + * The frequency band collections are a set of frequency ranges + * with shared properties - max tx power, max antenna gain, channel width, + * channel spacing, DFS requirements and passive scanning requirements. + * + * These are represented as entries in a frequency band bitmask. + * Each regulatory domain entry in ah_regdomain_domains.h uses one + * or more frequency band entries for each of the channel modes + * supported (11bg, 11a, half, quarter, turbo, etc.) * - * Beware of ordering; the indices are defined relative to the preceding - * entry so if things get off there will be confusion. A good way to - * check the indices is to collect them in a switch statement in a stub - * function so the compiler checks for duplicates. */ - -typedef struct { - uint16_t lowChannel; /* Low channel center in MHz */ - uint16_t highChannel; /* High Channel center in MHz */ - uint8_t powerDfs; /* Max power (dBm) for channel - range when using DFS */ - uint8_t antennaMax; /* Max allowed antenna gain */ - uint8_t channelBW; /* Bandwidth of the channel */ - uint8_t channelSep; /* Channel separation within - the band */ - uint64_t useDfs; /* Use DFS in the RegDomain - if corresponding bit is set */ - uint64_t usePassScan; /* Use Passive Scan in the RegDomain - if corresponding bit is set */ -} REG_DMN_FREQ_BAND; +#include "ah_regdomain/ah_rd_freqbands.h" /* - * 5GHz 11A channel tags + * This is the main regulatory database. It defines the supported + * set of features and requirements for each of the defined regulatory + * zones. It uses combinations of frequency ranges - represented in + * a bitmask - to determine the requirements and limitations needed. */ -static REG_DMN_FREQ_BAND regDmn5GhzFreq[] = { - { 4915, 4925, 23, 0, 10, 5, NO_DFS, PSCAN_MKK2 }, -#define F1_4915_4925 0 - { 4935, 4945, 23, 0, 10, 5, NO_DFS, PSCAN_MKK2 }, -#define F1_4935_4945 AFTER(F1_4915_4925) - { 4920, 4980, 23, 0, 20, 20, NO_DFS, PSCAN_MKK2 }, -#define F1_4920_4980 AFTER(F1_4935_4945) - { 4942, 4987, 27, 6, 5, 5, NO_DFS, PSCAN_FCC }, -#define F1_4942_4987 AFTER(F1_4920_4980) - { 4945, 4985, 30, 6, 10, 5, NO_DFS, PSCAN_FCC }, -#define F1_4945_4985 AFTER(F1_4942_4987) - { 4950, 4980, 33, 6, 20, 5, NO_DFS, PSCAN_FCC }, -#define F1_4950_4980 AFTER(F1_4945_4985) - { 5035, 5040, 23, 0, 10, 5, NO_DFS, PSCAN_MKK2 }, -#define F1_5035_5040 AFTER(F1_4950_4980) - { 5040, 5080, 23, 0, 20, 20, NO_DFS, PSCAN_MKK2 }, -#define F1_5040_5080 AFTER(F1_5035_5040) - { 5055, 5055, 23, 0, 10, 5, NO_DFS, PSCAN_MKK2 }, -#define F1_5055_5055 AFTER(F1_5040_5080) - - { 5120, 5240, 5, 6, 20, 20, NO_DFS, NO_PSCAN }, -#define F1_5120_5240 AFTER(F1_5055_5055) - { 5120, 5240, 5, 6, 10, 10, NO_DFS, NO_PSCAN }, -#define F2_5120_5240 AFTER(F1_5120_5240) - { 5120, 5240, 5, 6, 5, 5, NO_DFS, NO_PSCAN }, -#define F3_5120_5240 AFTER(F2_5120_5240) - - { 5170, 5230, 23, 0, 20, 20, NO_DFS, PSCAN_MKK1 | PSCAN_MKK2 }, -#define F1_5170_5230 AFTER(F3_5120_5240) - { 5170, 5230, 20, 0, 20, 20, NO_DFS, PSCAN_MKK1 | PSCAN_MKK2 }, -#define F2_5170_5230 AFTER(F1_5170_5230) - - { 5180, 5240, 15, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI }, -#define F1_5180_5240 AFTER(F2_5170_5230) - { 5180, 5240, 17, 6, 20, 20, NO_DFS, PSCAN_FCC }, -#define F2_5180_5240 AFTER(F1_5180_5240) - { 5180, 5240, 18, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI }, -#define F3_5180_5240 AFTER(F2_5180_5240) - { 5180, 5240, 20, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI }, -#define F4_5180_5240 AFTER(F3_5180_5240) - { 5180, 5240, 23, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI }, -#define F5_5180_5240 AFTER(F4_5180_5240) - { 5180, 5240, 23, 6, 20, 20, NO_DFS, PSCAN_FCC }, -#define F6_5180_5240 AFTER(F5_5180_5240) - { 5180, 5240, 17, 6, 20, 10, NO_DFS, PSCAN_FCC }, -#define F7_5180_5240 AFTER(F6_5180_5240) - { 5180, 5240, 17, 6, 20, 5, NO_DFS, PSCAN_FCC }, -#define F8_5180_5240 AFTER(F7_5180_5240) - { 5180, 5320, 20, 6, 20, 20, DFS_ETSI, PSCAN_ETSI }, - -#define F1_5180_5320 AFTER(F8_5180_5240) - { 5240, 5280, 23, 0, 20, 20, DFS_FCC3, PSCAN_FCC | PSCAN_ETSI }, - -#define F1_5240_5280 AFTER(F1_5180_5320) - { 5260, 5280, 23, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC | PSCAN_ETSI }, - -#define F1_5260_5280 AFTER(F1_5240_5280) - { 5260, 5320, 18, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC | PSCAN_ETSI }, - -#define F1_5260_5320 AFTER(F1_5260_5280) - { 5260, 5320, 20, 0, 20, 20, DFS_FCC3 | DFS_ETSI | DFS_MKK4, PSCAN_FCC | PSCAN_ETSI | PSCAN_MKK3 }, -#define F2_5260_5320 AFTER(F1_5260_5320) - - { 5260, 5320, 20, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC }, -#define F3_5260_5320 AFTER(F2_5260_5320) - { 5260, 5320, 23, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC }, -#define F4_5260_5320 AFTER(F3_5260_5320) - { 5260, 5320, 23, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC }, -#define F5_5260_5320 AFTER(F4_5260_5320) - { 5260, 5320, 30, 0, 20, 20, NO_DFS, NO_PSCAN }, -#define F6_5260_5320 AFTER(F5_5260_5320) - { 5260, 5320, 23, 6, 20, 10, DFS_FCC3 | DFS_ETSI, PSCAN_FCC }, -#define F7_5260_5320 AFTER(F6_5260_5320) - { 5260, 5320, 23, 6, 20, 5, DFS_FCC3 | DFS_ETSI, PSCAN_FCC }, -#define F8_5260_5320 AFTER(F7_5260_5320) - - { 5260, 5700, 5, 6, 20, 20, DFS_FCC3 | DFS_ETSI, NO_PSCAN }, -#define F1_5260_5700 AFTER(F8_5260_5320) - { 5260, 5700, 5, 6, 10, 10, DFS_FCC3 | DFS_ETSI, NO_PSCAN }, -#define F2_5260_5700 AFTER(F1_5260_5700) - { 5260, 5700, 5, 6, 5, 5, DFS_FCC3 | DFS_ETSI, NO_PSCAN }, -#define F3_5260_5700 AFTER(F2_5260_5700) - - { 5280, 5320, 17, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC }, -#define F1_5280_5320 AFTER(F3_5260_5700) - - { 5500, 5620, 30, 6, 20, 20, DFS_ETSI, PSCAN_ETSI }, -#define F1_5500_5620 AFTER(F1_5280_5320) - - { 5500, 5700, 20, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC }, -#define F1_5500_5700 AFTER(F1_5500_5620) - { 5500, 5700, 27, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC | PSCAN_ETSI }, -#define F2_5500_5700 AFTER(F1_5500_5700) - { 5500, 5700, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC | PSCAN_ETSI }, -#define F3_5500_5700 AFTER(F2_5500_5700) - { 5500, 5700, 23, 0, 20, 20, DFS_FCC3 | DFS_ETSI | DFS_MKK4, PSCAN_MKK3 | PSCAN_FCC }, -#define F4_5500_5700 AFTER(F3_5500_5700) - - { 5745, 5805, 23, 0, 20, 20, NO_DFS, NO_PSCAN }, -#define F1_5745_5805 AFTER(F4_5500_5700) - { 5745, 5805, 30, 6, 20, 20, NO_DFS, NO_PSCAN }, -#define F2_5745_5805 AFTER(F1_5745_5805) - { 5745, 5805, 30, 6, 20, 20, DFS_ETSI, PSCAN_ETSI }, -#define F3_5745_5805 AFTER(F2_5745_5805) - { 5745, 5825, 5, 6, 20, 20, NO_DFS, NO_PSCAN }, -#define F1_5745_5825 AFTER(F3_5745_5805) - { 5745, 5825, 17, 0, 20, 20, NO_DFS, NO_PSCAN }, -#define F2_5745_5825 AFTER(F1_5745_5825) - { 5745, 5825, 20, 0, 20, 20, NO_DFS, NO_PSCAN }, -#define F3_5745_5825 AFTER(F2_5745_5825) - { 5745, 5825, 30, 0, 20, 20, NO_DFS, NO_PSCAN }, -#define F4_5745_5825 AFTER(F3_5745_5825) - { 5745, 5825, 30, 6, 20, 20, NO_DFS, NO_PSCAN }, -#define F5_5745_5825 AFTER(F4_5745_5825) - { 5745, 5825, 30, 6, 20, 20, NO_DFS, NO_PSCAN }, -#define F6_5745_5825 AFTER(F5_5745_5825) - { 5745, 5825, 5, 6, 10, 10, NO_DFS, NO_PSCAN }, -#define F7_5745_5825 AFTER(F6_5745_5825) - { 5745, 5825, 5, 6, 5, 5, NO_DFS, NO_PSCAN }, -#define F8_5745_5825 AFTER(F7_5745_5825) - { 5745, 5825, 30, 6, 20, 10, NO_DFS, NO_PSCAN }, -#define F9_5745_5825 AFTER(F8_5745_5825) - { 5745, 5825, 30, 6, 20, 5, NO_DFS, NO_PSCAN }, -#define F10_5745_5825 AFTER(F9_5745_5825) - - /* - * Below are the world roaming channels - * All WWR domains have no power limit, instead use the card's CTL - * or max power settings. - */ - { 4920, 4980, 30, 0, 20, 20, NO_DFS, PSCAN_WWR }, -#define W1_4920_4980 AFTER(F10_5745_5825) - { 5040, 5080, 30, 0, 20, 20, NO_DFS, PSCAN_WWR }, -#define W1_5040_5080 AFTER(W1_4920_4980) - { 5170, 5230, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_WWR }, -#define W1_5170_5230 AFTER(W1_5040_5080) - { 5180, 5240, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_WWR }, -#define W1_5180_5240 AFTER(W1_5170_5230) - { 5260, 5320, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_WWR }, -#define W1_5260_5320 AFTER(W1_5180_5240) - { 5745, 5825, 30, 0, 20, 20, NO_DFS, PSCAN_WWR }, -#define W1_5745_5825 AFTER(W1_5260_5320) - { 5500, 5700, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_WWR }, -#define W1_5500_5700 AFTER(W1_5745_5825) - { 5260, 5320, 30, 0, 20, 20, NO_DFS, NO_PSCAN }, -#define W2_5260_5320 AFTER(W1_5500_5700) - { 5180, 5240, 30, 0, 20, 20, NO_DFS, NO_PSCAN }, -#define W2_5180_5240 AFTER(W2_5260_5320) - { 5825, 5825, 30, 0, 20, 20, NO_DFS, PSCAN_WWR }, -#define W2_5825_5825 AFTER(W2_5180_5240) -}; - -/* - * 5GHz Turbo (dynamic & static) tags - */ -static REG_DMN_FREQ_BAND regDmn5GhzTurboFreq[] = { - { 5130, 5210, 5, 6, 40, 40, NO_DFS, NO_PSCAN }, -#define T1_5130_5210 0 - { 5250, 5330, 5, 6, 40, 40, DFS_FCC3, NO_PSCAN }, -#define T1_5250_5330 AFTER(T1_5130_5210) - { 5370, 5490, 5, 6, 40, 40, NO_DFS, NO_PSCAN }, -#define T1_5370_5490 AFTER(T1_5250_5330) - { 5530, 5650, 5, 6, 40, 40, DFS_FCC3, NO_PSCAN }, -#define T1_5530_5650 AFTER(T1_5370_5490) - - { 5150, 5190, 5, 6, 40, 40, NO_DFS, NO_PSCAN }, -#define T1_5150_5190 AFTER(T1_5530_5650) - { 5230, 5310, 5, 6, 40, 40, DFS_FCC3, NO_PSCAN }, -#define T1_5230_5310 AFTER(T1_5150_5190) - { 5350, 5470, 5, 6, 40, 40, NO_DFS, NO_PSCAN }, -#define T1_5350_5470 AFTER(T1_5230_5310) - { 5510, 5670, 5, 6, 40, 40, DFS_FCC3, NO_PSCAN }, -#define T1_5510_5670 AFTER(T1_5350_5470) - - { 5200, 5240, 17, 6, 40, 40, NO_DFS, NO_PSCAN }, -#define T1_5200_5240 AFTER(T1_5510_5670) - { 5200, 5240, 23, 6, 40, 40, NO_DFS, NO_PSCAN }, -#define T2_5200_5240 AFTER(T1_5200_5240) - { 5210, 5210, 17, 6, 40, 40, NO_DFS, NO_PSCAN }, -#define T1_5210_5210 AFTER(T2_5200_5240) - { 5210, 5210, 23, 0, 40, 40, NO_DFS, NO_PSCAN }, -#define T2_5210_5210 AFTER(T1_5210_5210) - - { 5280, 5280, 23, 6, 40, 40, DFS_FCC3, PSCAN_FCC_T }, -#define T1_5280_5280 AFTER(T2_5210_5210) - { 5280, 5280, 20, 6, 40, 40, DFS_FCC3, PSCAN_FCC_T }, -#define T2_5280_5280 AFTER(T1_5280_5280) - { 5250, 5250, 17, 0, 40, 40, DFS_FCC3, PSCAN_FCC_T }, -#define T1_5250_5250 AFTER(T2_5280_5280) - { 5290, 5290, 20, 0, 40, 40, DFS_FCC3, PSCAN_FCC_T }, -#define T1_5290_5290 AFTER(T1_5250_5250) - { 5250, 5290, 20, 0, 40, 40, DFS_FCC3, PSCAN_FCC_T }, -#define T1_5250_5290 AFTER(T1_5290_5290) - { 5250, 5290, 23, 6, 40, 40, DFS_FCC3, PSCAN_FCC_T }, -#define T2_5250_5290 AFTER(T1_5250_5290) - - { 5540, 5660, 20, 6, 40, 40, DFS_FCC3, PSCAN_FCC_T }, -#define T1_5540_5660 AFTER(T2_5250_5290) - { 5760, 5800, 20, 0, 40, 40, NO_DFS, NO_PSCAN }, -#define T1_5760_5800 AFTER(T1_5540_5660) - { 5760, 5800, 30, 6, 40, 40, NO_DFS, NO_PSCAN }, -#define T2_5760_5800 AFTER(T1_5760_5800) - - { 5765, 5805, 30, 6, 40, 40, NO_DFS, NO_PSCAN }, -#define T1_5765_5805 AFTER(T2_5760_5800) - - /* - * Below are the WWR frequencies - */ - { 5210, 5250, 15, 0, 40, 40, DFS_FCC3 | DFS_ETSI, PSCAN_WWR }, -#define WT1_5210_5250 AFTER(T1_5765_5805) - { 5290, 5290, 18, 0, 40, 40, DFS_FCC3 | DFS_ETSI, PSCAN_WWR }, -#define WT1_5290_5290 AFTER(WT1_5210_5250) - { 5540, 5660, 20, 0, 40, 40, DFS_FCC3 | DFS_ETSI, PSCAN_WWR }, -#define WT1_5540_5660 AFTER(WT1_5290_5290) - { 5760, 5800, 20, 0, 40, 40, NO_DFS, PSCAN_WWR }, -#define WT1_5760_5800 AFTER(WT1_5540_5660) -}; - -/* - * 2GHz 11b channel tags - */ -static REG_DMN_FREQ_BAND regDmn2GhzFreq[] = { - { 2312, 2372, 5, 6, 20, 5, NO_DFS, NO_PSCAN }, -#define F1_2312_2372 0 - { 2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN }, -#define F2_2312_2372 AFTER(F1_2312_2372) - - { 2412, 2472, 5, 6, 20, 5, NO_DFS, NO_PSCAN }, -#define F1_2412_2472 AFTER(F2_2312_2372) - { 2412, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA }, -#define F2_2412_2472 AFTER(F1_2412_2472) - { 2412, 2472, 30, 0, 20, 5, NO_DFS, NO_PSCAN }, -#define F3_2412_2472 AFTER(F2_2412_2472) - - { 2412, 2462, 27, 6, 20, 5, NO_DFS, NO_PSCAN }, -#define F1_2412_2462 AFTER(F3_2412_2472) - { 2412, 2462, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA }, -#define F2_2412_2462 AFTER(F1_2412_2462) - - { 2432, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN }, -#define F1_2432_2442 AFTER(F2_2412_2462) - - { 2457, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN }, -#define F1_2457_2472 AFTER(F1_2432_2442) - - { 2467, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA2 | PSCAN_MKKA }, -#define F1_2467_2472 AFTER(F1_2457_2472) - - { 2484, 2484, 5, 6, 20, 5, NO_DFS, NO_PSCAN }, -#define F1_2484_2484 AFTER(F1_2467_2472) - { 2484, 2484, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA | PSCAN_MKKA1 | PSCAN_MKKA2 }, -#define F2_2484_2484 AFTER(F1_2484_2484) - - { 2512, 2732, 5, 6, 20, 5, NO_DFS, NO_PSCAN }, -#define F1_2512_2732 AFTER(F2_2484_2484) - - /* - * WWR have powers opened up to 20dBm. - * Limits should often come from CTL/Max powers - */ - { 2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN }, -#define W1_2312_2372 AFTER(F1_2512_2732) - { 2412, 2412, 20, 0, 20, 5, NO_DFS, NO_PSCAN }, -#define W1_2412_2412 AFTER(W1_2312_2372) - { 2417, 2432, 20, 0, 20, 5, NO_DFS, NO_PSCAN }, -#define W1_2417_2432 AFTER(W1_2412_2412) - { 2437, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN }, -#define W1_2437_2442 AFTER(W1_2417_2432) - { 2447, 2457, 20, 0, 20, 5, NO_DFS, NO_PSCAN }, -#define W1_2447_2457 AFTER(W1_2437_2442) - { 2462, 2462, 20, 0, 20, 5, NO_DFS, NO_PSCAN }, -#define W1_2462_2462 AFTER(W1_2447_2457) - { 2467, 2467, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN }, -#define W1_2467_2467 AFTER(W1_2462_2462) - { 2467, 2467, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN }, -#define W2_2467_2467 AFTER(W1_2467_2467) - { 2472, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN }, -#define W1_2472_2472 AFTER(W2_2467_2467) - { 2472, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN }, -#define W2_2472_2472 AFTER(W1_2472_2472) - { 2484, 2484, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN }, -#define W1_2484_2484 AFTER(W2_2472_2472) - { 2484, 2484, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN }, -#define W2_2484_2484 AFTER(W1_2484_2484) -}; - -/* - * 2GHz 11g channel tags - */ -static REG_DMN_FREQ_BAND regDmn2Ghz11gFreq[] = { - { 2312, 2372, 5, 6, 20, 5, NO_DFS, NO_PSCAN }, -#define G1_2312_2372 0 - { 2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN }, -#define G2_2312_2372 AFTER(G1_2312_2372) - { 2312, 2372, 5, 6, 10, 5, NO_DFS, NO_PSCAN }, -#define G3_2312_2372 AFTER(G2_2312_2372) - { 2312, 2372, 5, 6, 5, 5, NO_DFS, NO_PSCAN }, -#define G4_2312_2372 AFTER(G3_2312_2372) - - { 2412, 2472, 5, 6, 20, 5, NO_DFS, NO_PSCAN }, -#define G1_2412_2472 AFTER(G4_2312_2372) - { 2412, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA_G }, -#define G2_2412_2472 AFTER(G1_2412_2472) - { 2412, 2472, 30, 0, 20, 5, NO_DFS, NO_PSCAN }, -#define G3_2412_2472 AFTER(G2_2412_2472) - { 2412, 2472, 5, 6, 10, 5, NO_DFS, NO_PSCAN }, -#define G4_2412_2472 AFTER(G3_2412_2472) - { 2412, 2472, 5, 6, 5, 5, NO_DFS, NO_PSCAN }, -#define G5_2412_2472 AFTER(G4_2412_2472) - - { 2412, 2462, 27, 6, 20, 5, NO_DFS, NO_PSCAN }, -#define G1_2412_2462 AFTER(G5_2412_2472) - { 2412, 2462, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA_G }, -#define G2_2412_2462 AFTER(G1_2412_2462) - { 2412, 2462, 27, 6, 10, 5, NO_DFS, NO_PSCAN }, -#define G3_2412_2462 AFTER(G2_2412_2462) - { 2412, 2462, 27, 6, 5, 5, NO_DFS, NO_PSCAN }, -#define G4_2412_2462 AFTER(G3_2412_2462) - - { 2432, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN }, -#define G1_2432_2442 AFTER(G4_2412_2462) - - { 2457, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN }, -#define G1_2457_2472 AFTER(G1_2432_2442) - - { 2512, 2732, 5, 6, 20, 5, NO_DFS, NO_PSCAN }, -#define G1_2512_2732 AFTER(G1_2457_2472) - { 2512, 2732, 5, 6, 10, 5, NO_DFS, NO_PSCAN }, -#define G2_2512_2732 AFTER(G1_2512_2732) - { 2512, 2732, 5, 6, 5, 5, NO_DFS, NO_PSCAN }, -#define G3_2512_2732 AFTER(G2_2512_2732) - - { 2467, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA2 | PSCAN_MKKA }, -#define G1_2467_2472 AFTER(G3_2512_2732) - - /* - * WWR open up the power to 20dBm - */ - { 2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN }, -#define WG1_2312_2372 AFTER(G1_2467_2472) - { 2412, 2412, 20, 0, 20, 5, NO_DFS, NO_PSCAN }, -#define WG1_2412_2412 AFTER(WG1_2312_2372) - { 2417, 2432, 20, 0, 20, 5, NO_DFS, NO_PSCAN }, -#define WG1_2417_2432 AFTER(WG1_2412_2412) - { 2437, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN }, -#define WG1_2437_2442 AFTER(WG1_2417_2432) - { 2447, 2457, 20, 0, 20, 5, NO_DFS, NO_PSCAN }, -#define WG1_2447_2457 AFTER(WG1_2437_2442) - { 2462, 2462, 20, 0, 20, 5, NO_DFS, NO_PSCAN }, -#define WG1_2462_2462 AFTER(WG1_2447_2457) - { 2467, 2467, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN }, -#define WG1_2467_2467 AFTER(WG1_2462_2462) - { 2467, 2467, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN }, -#define WG2_2467_2467 AFTER(WG1_2467_2467) - { 2472, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN }, -#define WG1_2472_2472 AFTER(WG2_2467_2467) - { 2472, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN }, -#define WG2_2472_2472 AFTER(WG1_2472_2472) -}; - -/* - * 2GHz Dynamic turbo tags - */ -static REG_DMN_FREQ_BAND regDmn2Ghz11gTurboFreq[] = { - { 2312, 2372, 5, 6, 40, 40, NO_DFS, NO_PSCAN }, -#define T1_2312_2372 0 - { 2437, 2437, 5, 6, 40, 40, NO_DFS, NO_PSCAN }, -#define T1_2437_2437 AFTER(T1_2312_2372) - { 2437, 2437, 20, 6, 40, 40, NO_DFS, NO_PSCAN }, -#define T2_2437_2437 AFTER(T1_2437_2437) - { 2437, 2437, 18, 6, 40, 40, NO_DFS, PSCAN_WWR }, -#define T3_2437_2437 AFTER(T2_2437_2437) - { 2512, 2732, 5, 6, 40, 40, NO_DFS, NO_PSCAN }, -#define T1_2512_2732 AFTER(T3_2437_2437) -}; - -typedef struct regDomain { - uint16_t regDmnEnum; /* value from EnumRd table */ - uint8_t conformanceTestLimit; - uint32_t flags; /* Requirement flags (AdHoc disallow, - noise floor cal needed, etc) */ - uint64_t dfsMask; /* DFS bitmask for 5Ghz tables */ - uint64_t pscan; /* Bitmask for passive scan */ - chanbmask_t chan11a; /* 11a channels */ - chanbmask_t chan11a_turbo; /* 11a static turbo channels */ - chanbmask_t chan11a_dyn_turbo; /* 11a dynamic turbo channels */ - chanbmask_t chan11a_half; /* 11a 1/2 width channels */ - chanbmask_t chan11a_quarter; /* 11a 1/4 width channels */ - chanbmask_t chan11b; /* 11b channels */ - chanbmask_t chan11g; /* 11g channels */ - chanbmask_t chan11g_turbo; /* 11g dynamic turbo channels */ - chanbmask_t chan11g_half; /* 11g 1/2 width channels */ - chanbmask_t chan11g_quarter; /* 11g 1/4 width channels */ -} REG_DOMAIN; - -static REG_DOMAIN regDomains[] = { - - {.regDmnEnum = DEBUG_REG_DMN, - .conformanceTestLimit = FCC, - .dfsMask = DFS_FCC3, - .chan11a = BM4(F1_4950_4980, - F1_5120_5240, - F1_5260_5700, - F1_5745_5825), - .chan11a_half = BM4(F1_4945_4985, - F2_5120_5240, - F2_5260_5700, - F7_5745_5825), - .chan11a_quarter = BM4(F1_4942_4987, - F3_5120_5240, - F3_5260_5700, - F8_5745_5825), - .chan11a_turbo = BM8(T1_5130_5210, - T1_5250_5330, - T1_5370_5490, - T1_5530_5650, - T1_5150_5190, - T1_5230_5310, - T1_5350_5470, - T1_5510_5670), - .chan11a_dyn_turbo = BM4(T1_5200_5240, - T1_5280_5280, - T1_5540_5660, - T1_5765_5805), - .chan11b = BM4(F1_2312_2372, - F1_2412_2472, - F1_2484_2484, - F1_2512_2732), - .chan11g = BM3(G1_2312_2372, G1_2412_2472, G1_2512_2732), - .chan11g_turbo = BM3(T1_2312_2372, T1_2437_2437, T1_2512_2732), - .chan11g_half = BM3(G2_2312_2372, G4_2412_2472, G2_2512_2732), - .chan11g_quarter = BM3(G3_2312_2372, G5_2412_2472, G3_2512_2732), - }, - - {.regDmnEnum = APL1, - .conformanceTestLimit = FCC, - .chan11a = BM1(F4_5745_5825), - }, - - {.regDmnEnum = APL2, - .conformanceTestLimit = FCC, - .chan11a = BM1(F1_5745_5805), - }, - - {.regDmnEnum = APL3, - .conformanceTestLimit = FCC, - .chan11a = BM2(F1_5280_5320, F2_5745_5805), - }, - - {.regDmnEnum = APL4, - .conformanceTestLimit = FCC, - .chan11a = BM2(F4_5180_5240, F3_5745_5825), - }, - - {.regDmnEnum = APL5, - .conformanceTestLimit = FCC, - .chan11a = BM1(F2_5745_5825), - }, - - {.regDmnEnum = APL6, - .conformanceTestLimit = ETSI, - .dfsMask = DFS_ETSI, - .pscan = PSCAN_FCC_T | PSCAN_FCC, - .chan11a = BM3(F4_5180_5240, F2_5260_5320, F3_5745_5825), - .chan11a_turbo = BM3(T2_5210_5210, T1_5250_5290, T1_5760_5800), - }, - - {.regDmnEnum = APL8, - .conformanceTestLimit = ETSI, - .flags = DISALLOW_ADHOC_11A|DISALLOW_ADHOC_11A_TURB, - .chan11a = BM2(F6_5260_5320, F4_5745_5825), - }, - - {.regDmnEnum = APL9, - .conformanceTestLimit = ETSI, - .dfsMask = DFS_ETSI, - .pscan = PSCAN_ETSI, - .flags = DISALLOW_ADHOC_11A|DISALLOW_ADHOC_11A_TURB, - .chan11a = BM3(F1_5180_5320, F1_5500_5620, F3_5745_5805), - }, - - {.regDmnEnum = ETSI1, - .conformanceTestLimit = ETSI, - .dfsMask = DFS_ETSI, - .pscan = PSCAN_ETSI, - .flags = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, - .chan11a = BM3(W2_5180_5240, F2_5260_5320, F2_5500_5700), - }, - - {.regDmnEnum = ETSI2, - .conformanceTestLimit = ETSI, - .dfsMask = DFS_ETSI, - .pscan = PSCAN_ETSI, - .flags = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, - .chan11a = BM1(F3_5180_5240), - }, - - {.regDmnEnum = ETSI3, - .conformanceTestLimit = ETSI, - .dfsMask = DFS_ETSI, - .pscan = PSCAN_ETSI, - .flags = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, - .chan11a = BM2(W2_5180_5240, F2_5260_5320), - }, - - {.regDmnEnum = ETSI4, - .conformanceTestLimit = ETSI, - .dfsMask = DFS_ETSI, - .pscan = PSCAN_ETSI, - .flags = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, - .chan11a = BM2(F3_5180_5240, F1_5260_5320), - }, - - {.regDmnEnum = ETSI5, - .conformanceTestLimit = ETSI, - .dfsMask = DFS_ETSI, - .pscan = PSCAN_ETSI, - .flags = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, - .chan11a = BM1(F1_5180_5240), - }, - - {.regDmnEnum = ETSI6, - .conformanceTestLimit = ETSI, - .dfsMask = DFS_ETSI, - .pscan = PSCAN_ETSI, - .flags = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, - .chan11a = BM3(F5_5180_5240, F1_5260_5280, F3_5500_5700), - }, - - {.regDmnEnum = FCC1, - .conformanceTestLimit = FCC, - .chan11a = BM3(F2_5180_5240, F4_5260_5320, F5_5745_5825), - .chan11a_turbo = BM3(T1_5210_5210, T2_5250_5290, T2_5760_5800), - .chan11a_dyn_turbo = BM3(T1_5200_5240, T1_5280_5280, T1_5765_5805), - }, - - {.regDmnEnum = FCC2, - .conformanceTestLimit = FCC, - .chan11a = BM3(F6_5180_5240, F5_5260_5320, F6_5745_5825), - .chan11a_dyn_turbo = BM3(T2_5200_5240, T1_5280_5280, T1_5765_5805), - }, - - {.regDmnEnum = FCC3, - .conformanceTestLimit = FCC, - .dfsMask = DFS_FCC3, - .pscan = PSCAN_FCC | PSCAN_FCC_T, - .chan11a = BM4(F2_5180_5240, - F3_5260_5320, - F1_5500_5700, - F5_5745_5825), - .chan11a_turbo = BM4(T1_5210_5210, - T1_5250_5250, - T1_5290_5290, - T2_5760_5800), - .chan11a_dyn_turbo = BM3(T1_5200_5240, T2_5280_5280, T1_5540_5660), - }, - - {.regDmnEnum = FCC4, - .conformanceTestLimit = FCC, - .dfsMask = DFS_FCC3, - .pscan = PSCAN_FCC | PSCAN_FCC_T, - .chan11a = BM1(F1_4950_4980), - .chan11a_half = BM1(F1_4945_4985), - .chan11a_quarter = BM1(F1_4942_4987), - }, - - /* FCC1 w/ 1/2 and 1/4 width channels */ - {.regDmnEnum = FCC5, - .conformanceTestLimit = FCC, - .chan11a = BM3(F2_5180_5240, F4_5260_5320, F5_5745_5825), - .chan11a_turbo = BM3(T1_5210_5210, T2_5250_5290, T2_5760_5800), - .chan11a_dyn_turbo = BM3(T1_5200_5240, T1_5280_5280, T1_5765_5805), - .chan11a_half = BM3(F7_5180_5240, F7_5260_5320, F9_5745_5825), - .chan11a_quarter = BM3(F8_5180_5240, F8_5260_5320,F10_5745_5825), - }, - - {.regDmnEnum = MKK1, - .conformanceTestLimit = MKK, - .pscan = PSCAN_MKK1, - .flags = DISALLOW_ADHOC_11A_TURB, - .chan11a = BM1(F1_5170_5230), - }, - - {.regDmnEnum = MKK2, - .conformanceTestLimit = MKK, - .pscan = PSCAN_MKK2, - .flags = DISALLOW_ADHOC_11A_TURB, - .chan11a = BM3(F1_4920_4980, F1_5040_5080, F1_5170_5230), - .chan11a_half = BM4(F1_4915_4925, - F1_4935_4945, - F1_5035_5040, - F1_5055_5055), - }, - - /* UNI-1 even */ - {.regDmnEnum = MKK3, - .conformanceTestLimit = MKK, - .pscan = PSCAN_MKK3, - .flags = DISALLOW_ADHOC_11A_TURB, - .chan11a = BM1(F4_5180_5240), - }, - - /* UNI-1 even + UNI-2 */ - {.regDmnEnum = MKK4, - .conformanceTestLimit = MKK, - .dfsMask = DFS_MKK4, - .pscan = PSCAN_MKK3, - .flags = DISALLOW_ADHOC_11A_TURB, - .chan11a = BM2(F4_5180_5240, F2_5260_5320), - }, - - /* UNI-1 even + UNI-2 + mid-band */ - {.regDmnEnum = MKK5, - .conformanceTestLimit = MKK, - .dfsMask = DFS_MKK4, - .pscan = PSCAN_MKK3, - .flags = DISALLOW_ADHOC_11A_TURB, - .chan11a = BM3(F4_5180_5240, F2_5260_5320, F4_5500_5700), - }, - - /* UNI-1 odd + even */ - {.regDmnEnum = MKK6, - .conformanceTestLimit = MKK, - .pscan = PSCAN_MKK1, - .flags = DISALLOW_ADHOC_11A_TURB, - .chan11a = BM2(F2_5170_5230, F4_5180_5240), - }, - - /* UNI-1 odd + UNI-1 even + UNI-2 */ - {.regDmnEnum = MKK7, - .conformanceTestLimit = MKK, - .dfsMask = DFS_MKK4, - .pscan = PSCAN_MKK1 | PSCAN_MKK3, - .flags = DISALLOW_ADHOC_11A_TURB, - .chan11a = BM3(F1_5170_5230, F4_5180_5240, F2_5260_5320), - }, - - /* UNI-1 odd + UNI-1 even + UNI-2 + mid-band */ - {.regDmnEnum = MKK8, - .conformanceTestLimit = MKK, - .dfsMask = DFS_MKK4, - .pscan = PSCAN_MKK1 | PSCAN_MKK3, - .flags = DISALLOW_ADHOC_11A_TURB, - .chan11a = BM4(F1_5170_5230, - F4_5180_5240, - F2_5260_5320, - F4_5500_5700), - }, - - /* UNI-1 even + 4.9 GHZ */ - {.regDmnEnum = MKK9, - .conformanceTestLimit = MKK, - .pscan = PSCAN_MKK3, - .flags = DISALLOW_ADHOC_11A_TURB, - .chan11a = BM7(F1_4915_4925, - F1_4935_4945, - F1_4920_4980, - F1_5035_5040, - F1_5055_5055, - F1_5040_5080, - F4_5180_5240), - }, - - /* UNI-1 even + UNI-2 + 4.9 GHZ */ - {.regDmnEnum = MKK10, - .conformanceTestLimit = MKK, - .dfsMask = DFS_MKK4, - .pscan = PSCAN_MKK3, - .flags = DISALLOW_ADHOC_11A_TURB, - .chan11a = BM8(F1_4915_4925, - F1_4935_4945, - F1_4920_4980, - F1_5035_5040, - F1_5055_5055, - F1_5040_5080, - F4_5180_5240, - F2_5260_5320), - }, - - /* Defined here to use when 2G channels are authorised for country K2 */ - {.regDmnEnum = APLD, - .conformanceTestLimit = NO_CTL, - .chan11b = BM2(F2_2312_2372,F2_2412_2472), - .chan11g = BM2(G2_2312_2372,G2_2412_2472), - }, - - {.regDmnEnum = ETSIA, - .conformanceTestLimit = NO_CTL, - .pscan = PSCAN_ETSIA, - .flags = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, - .chan11b = BM1(F1_2457_2472), - .chan11g = BM1(G1_2457_2472), - .chan11g_turbo = BM1(T2_2437_2437) - }, - - {.regDmnEnum = ETSIB, - .conformanceTestLimit = ETSI, - .pscan = PSCAN_ETSIB, - .flags = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, - .chan11b = BM1(F1_2432_2442), - .chan11g = BM1(G1_2432_2442), - .chan11g_turbo = BM1(T2_2437_2437) - }, - - {.regDmnEnum = ETSIC, - .conformanceTestLimit = ETSI, - .pscan = PSCAN_ETSIC, - .flags = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, - .chan11b = BM1(F3_2412_2472), - .chan11g = BM1(G3_2412_2472), - .chan11g_turbo = BM1(T2_2437_2437) - }, - - {.regDmnEnum = FCCA, - .conformanceTestLimit = FCC, - .chan11b = BM1(F1_2412_2462), - .chan11g = BM1(G1_2412_2462), - .chan11g_turbo = BM1(T2_2437_2437), - }, - - /* FCCA w/ 1/2 and 1/4 width channels */ - {.regDmnEnum = FCCB, - .conformanceTestLimit = FCC, - .chan11b = BM1(F1_2412_2462), - .chan11g = BM1(G1_2412_2462), - .chan11g_turbo = BM1(T2_2437_2437), - .chan11g_half = BM1(G3_2412_2462), - .chan11g_quarter = BM1(G4_2412_2462), - }, - - {.regDmnEnum = MKKA, - .conformanceTestLimit = MKK, - .pscan = PSCAN_MKKA | PSCAN_MKKA_G - | PSCAN_MKKA1 | PSCAN_MKKA1_G - | PSCAN_MKKA2 | PSCAN_MKKA2_G, - .flags = DISALLOW_ADHOC_11A_TURB, - .chan11b = BM3(F2_2412_2462, F1_2467_2472, F2_2484_2484), - .chan11g = BM2(G2_2412_2462, G1_2467_2472), - .chan11g_turbo = BM1(T2_2437_2437) - }, - - {.regDmnEnum = MKKC, - .conformanceTestLimit = MKK, - .chan11b = BM1(F2_2412_2472), - .chan11g = BM1(G2_2412_2472), - .chan11g_turbo = BM1(T2_2437_2437) - }, - - {.regDmnEnum = WORLD, - .conformanceTestLimit = ETSI, - .chan11b = BM1(F2_2412_2472), - .chan11g = BM1(G2_2412_2472), - .chan11g_turbo = BM1(T2_2437_2437) - }, - - {.regDmnEnum = WOR0_WORLD, - .conformanceTestLimit = NO_CTL, - .dfsMask = DFS_FCC3 | DFS_ETSI, - .pscan = PSCAN_WWR, - .flags = ADHOC_PER_11D, - .chan11a = BM5(W1_5260_5320, - W1_5180_5240, - W1_5170_5230, - W1_5745_5825, - W1_5500_5700), - .chan11a_turbo = BM3(WT1_5210_5250, - WT1_5290_5290, - WT1_5760_5800), - .chan11b = BM8(W1_2412_2412, - W1_2437_2442, - W1_2462_2462, - W1_2472_2472, - W1_2417_2432, - W1_2447_2457, - W1_2467_2467, - W1_2484_2484), - .chan11g = BM7(WG1_2412_2412, - WG1_2437_2442, - WG1_2462_2462, - WG1_2472_2472, - WG1_2417_2432, - WG1_2447_2457, - WG1_2467_2467), - .chan11g_turbo = BM1(T3_2437_2437) - }, - - {.regDmnEnum = WOR01_WORLD, - .conformanceTestLimit = NO_CTL, - .dfsMask = DFS_FCC3 | DFS_ETSI, - .pscan = PSCAN_WWR, - .flags = ADHOC_PER_11D, - .chan11a = BM5(W1_5260_5320, - W1_5180_5240, - W1_5170_5230, - W1_5745_5825, - W1_5500_5700), - .chan11a_turbo = BM3(WT1_5210_5250, - WT1_5290_5290, - WT1_5760_5800), - .chan11b = BM5(W1_2412_2412, - W1_2437_2442, - W1_2462_2462, - W1_2417_2432, - W1_2447_2457), - .chan11g = BM5(WG1_2412_2412, - WG1_2437_2442, - WG1_2462_2462, - WG1_2417_2432, - WG1_2447_2457), - .chan11g_turbo = BM1(T3_2437_2437)}, - - {.regDmnEnum = WOR02_WORLD, - .conformanceTestLimit = NO_CTL, - .dfsMask = DFS_FCC3 | DFS_ETSI, - .pscan = PSCAN_WWR, - .flags = ADHOC_PER_11D, - .chan11a = BM5(W1_5260_5320, - W1_5180_5240, - W1_5170_5230, - W1_5745_5825, - W1_5500_5700), - .chan11a_turbo = BM3(WT1_5210_5250, - WT1_5290_5290, - WT1_5760_5800), - .chan11b = BM7(W1_2412_2412, - W1_2437_2442, - W1_2462_2462, - W1_2472_2472, - W1_2417_2432, - W1_2447_2457, - W1_2467_2467), - .chan11g = BM7(WG1_2412_2412, - WG1_2437_2442, - WG1_2462_2462, - WG1_2472_2472, - WG1_2417_2432, - WG1_2447_2457, - WG1_2467_2467), - .chan11g_turbo = BM1(T3_2437_2437)}, - - {.regDmnEnum = EU1_WORLD, - .conformanceTestLimit = NO_CTL, - .dfsMask = DFS_FCC3 | DFS_ETSI, - .pscan = PSCAN_WWR, - .flags = ADHOC_PER_11D, - .chan11a = BM5(W1_5260_5320, - W1_5180_5240, - W1_5170_5230, - W1_5745_5825, - W1_5500_5700), - .chan11a_turbo = BM3(WT1_5210_5250, - WT1_5290_5290, - WT1_5760_5800), - .chan11b = BM7(W1_2412_2412, - W1_2437_2442, - W1_2462_2462, - W2_2472_2472, - W1_2417_2432, - W1_2447_2457, - W2_2467_2467), - .chan11g = BM7(WG1_2412_2412, - WG1_2437_2442, - WG1_2462_2462, - WG2_2472_2472, - WG1_2417_2432, - WG1_2447_2457, - WG2_2467_2467), - .chan11g_turbo = BM1(T3_2437_2437)}, - - {.regDmnEnum = WOR1_WORLD, - .conformanceTestLimit = NO_CTL, - .dfsMask = DFS_FCC3 | DFS_ETSI, - .pscan = PSCAN_WWR, - .flags = DISALLOW_ADHOC_11A, - .chan11a = BM5(W1_5260_5320, - W1_5180_5240, - W1_5170_5230, - W1_5745_5825, - W1_5500_5700), - .chan11b = BM8(W1_2412_2412, - W1_2437_2442, - W1_2462_2462, - W1_2472_2472, - W1_2417_2432, - W1_2447_2457, - W1_2467_2467, - W1_2484_2484), - .chan11g = BM7(WG1_2412_2412, - WG1_2437_2442, - WG1_2462_2462, - WG1_2472_2472, - WG1_2417_2432, - WG1_2447_2457, - WG1_2467_2467), - .chan11g_turbo = BM1(T3_2437_2437) - }, - - {.regDmnEnum = WOR2_WORLD, - .conformanceTestLimit = NO_CTL, - .dfsMask = DFS_FCC3 | DFS_ETSI, - .pscan = PSCAN_WWR, - .flags = DISALLOW_ADHOC_11A, - .chan11a = BM5(W1_5260_5320, - W1_5180_5240, - W1_5170_5230, - W1_5745_5825, - W1_5500_5700), - .chan11a_turbo = BM3(WT1_5210_5250, - WT1_5290_5290, - WT1_5760_5800), - .chan11b = BM8(W1_2412_2412, - W1_2437_2442, - W1_2462_2462, - W1_2472_2472, - W1_2417_2432, - W1_2447_2457, - W1_2467_2467, - W1_2484_2484), - .chan11g = BM7(WG1_2412_2412, - WG1_2437_2442, - WG1_2462_2462, - WG1_2472_2472, - WG1_2417_2432, - WG1_2447_2457, - WG1_2467_2467), - .chan11g_turbo = BM1(T3_2437_2437)}, - - {.regDmnEnum = WOR3_WORLD, - .conformanceTestLimit = NO_CTL, - .dfsMask = DFS_FCC3 | DFS_ETSI, - .pscan = PSCAN_WWR, - .flags = ADHOC_PER_11D, - .chan11a = BM4(W1_5260_5320, - W1_5180_5240, - W1_5170_5230, - W1_5745_5825), - .chan11a_turbo = BM3(WT1_5210_5250, - WT1_5290_5290, - WT1_5760_5800), - .chan11b = BM7(W1_2412_2412, - W1_2437_2442, - W1_2462_2462, - W1_2472_2472, - W1_2417_2432, - W1_2447_2457, - W1_2467_2467), - .chan11g = BM7(WG1_2412_2412, - WG1_2437_2442, - WG1_2462_2462, - WG1_2472_2472, - WG1_2417_2432, - WG1_2447_2457, - WG1_2467_2467), - .chan11g_turbo = BM1(T3_2437_2437)}, - - {.regDmnEnum = WOR4_WORLD, - .conformanceTestLimit = NO_CTL, - .dfsMask = DFS_FCC3 | DFS_ETSI, - .pscan = PSCAN_WWR, - .flags = DISALLOW_ADHOC_11A, - .chan11a = BM4(W2_5260_5320, - W2_5180_5240, - F2_5745_5805, - W2_5825_5825), - .chan11a_turbo = BM3(WT1_5210_5250, - WT1_5290_5290, - WT1_5760_5800), - .chan11b = BM5(W1_2412_2412, - W1_2437_2442, - W1_2462_2462, - W1_2417_2432, - W1_2447_2457), - .chan11g = BM5(WG1_2412_2412, - WG1_2437_2442, - WG1_2462_2462, - WG1_2417_2432, - WG1_2447_2457), - .chan11g_turbo = BM1(T3_2437_2437)}, - - {.regDmnEnum = WOR5_ETSIC, - .conformanceTestLimit = NO_CTL, - .dfsMask = DFS_FCC3 | DFS_ETSI, - .pscan = PSCAN_WWR, - .flags = DISALLOW_ADHOC_11A, - .chan11a = BM3(W1_5260_5320, W2_5180_5240, F6_5745_5825), - .chan11b = BM7(W1_2412_2412, - W1_2437_2442, - W1_2462_2462, - W2_2472_2472, - W1_2417_2432, - W1_2447_2457, - W2_2467_2467), - .chan11g = BM7(WG1_2412_2412, - WG1_2437_2442, - WG1_2462_2462, - WG2_2472_2472, - WG1_2417_2432, - WG1_2447_2457, - WG2_2467_2467), - .chan11g_turbo = BM1(T3_2437_2437)}, - - {.regDmnEnum = WOR9_WORLD, - .conformanceTestLimit = NO_CTL, - .dfsMask = DFS_FCC3 | DFS_ETSI, - .pscan = PSCAN_WWR, - .flags = DISALLOW_ADHOC_11A, - .chan11a = BM4(W1_5260_5320, - W1_5180_5240, - W1_5745_5825, - W1_5500_5700), - .chan11a_turbo = BM3(WT1_5210_5250, - WT1_5290_5290, - WT1_5760_5800), - .chan11b = BM5(W1_2412_2412, - W1_2437_2442, - W1_2462_2462, - W1_2417_2432, - W1_2447_2457), - .chan11g = BM5(WG1_2412_2412, - WG1_2437_2442, - WG1_2462_2462, - WG1_2417_2432, - WG1_2447_2457), - .chan11g_turbo = BM1(T3_2437_2437)}, - - {.regDmnEnum = WORA_WORLD, - .conformanceTestLimit = NO_CTL, - .dfsMask = DFS_FCC3 | DFS_ETSI, - .pscan = PSCAN_WWR, - .flags = DISALLOW_ADHOC_11A, - .chan11a = BM4(W1_5260_5320, - W1_5180_5240, - W1_5745_5825, - W1_5500_5700), - .chan11b = BM7(W1_2412_2412, - W1_2437_2442, - W1_2462_2462, - W1_2472_2472, - W1_2417_2432, - W1_2447_2457, - W1_2467_2467), - .chan11g = BM7(WG1_2412_2412, - WG1_2437_2442, - WG1_2462_2462, - WG1_2472_2472, - WG1_2417_2432, - WG1_2447_2457, - WG1_2467_2467), - .chan11g_turbo = BM1(T3_2437_2437)}, - - {.regDmnEnum = WORB_WORLD, - .conformanceTestLimit = NO_CTL, - .dfsMask = DFS_FCC3 | DFS_ETSI, - .pscan = PSCAN_WWR, - .flags = DISALLOW_ADHOC_11A, - .chan11a = BM4(W1_5260_5320, - W1_5180_5240, - W1_5745_5825, - W1_5500_5700), - .chan11b = BM7(W1_2412_2412, - W1_2437_2442, - W1_2462_2462, - W1_2472_2472, - W1_2417_2432, - W1_2447_2457, - W1_2467_2467), - .chan11g = BM7(WG1_2412_2412, - WG1_2437_2442, - WG1_2462_2462, - WG1_2472_2472, - WG1_2417_2432, - WG1_2447_2457, - WG1_2467_2467), - .chan11g_turbo = BM1(T3_2437_2437)}, - - {.regDmnEnum = NULL1, - .conformanceTestLimit = NO_CTL, - } -}; - -struct cmode { - u_int mode; - u_int flags; -}; +#include "ah_regdomain/ah_rd_domains.h" static const struct cmode modes[] = { { HAL_MODE_TURBO, IEEE80211_CHAN_ST }, @@ -1745,6 +125,8 @@ static const struct cmode modes[] = { IEEE80211_CHAN_A | IEEE80211_CHAN_HT40D }, }; +static void ath_hal_update_dfsdomain(struct ath_hal *ah); + static OS_INLINE uint16_t getEepromRD(struct ath_hal *ah) { @@ -1787,7 +169,7 @@ isEepromValid(struct ath_hal *ah) if (regDomainPairs[i].regDmnEnum == rd) return AH_TRUE; } - HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, + HALDEBUG_G(ah, HAL_DEBUG_REGDOMAIN, "%s: invalid regulatory domain/country code 0x%x\n", __func__, rd); return AH_FALSE; } @@ -2146,6 +528,7 @@ getchannels(struct ath_hal *ah, "skip ecm channel\n"); continue; } +#if 0 if ((fband->useDfs & dfsMask) && (cm->flags & IEEE80211_CHAN_HT40)) { /* NB: DFS and HT40 don't mix */ @@ -2153,6 +536,7 @@ getchannels(struct ath_hal *ah, "skip HT40 chan, DFS required\n"); continue; } +#endif /* * Make sure that channel separation * meets the requirement. @@ -2229,7 +613,7 @@ ath_hal_mapgsm(int sku, int freq) return 1544 + freq; if (sku == SKU_SR9) return 3344 - freq; - HALDEBUG(AH_NULL, HAL_DEBUG_ANY, + HALDEBUG_G(AH_NULL, HAL_DEBUG_ANY, "%s: cannot map freq %u unknown gsm sku %u\n", __func__, freq, sku); return freq; @@ -2318,8 +702,12 @@ ath_hal_init_channels(struct ath_hal *ah, ah->ah_countryCode = country->countryCode; HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, "%s: cc %u\n", __func__, ah->ah_countryCode); + + /* Update current DFS domain */ + ath_hal_update_dfsdomain(ah); } else status = HAL_EINVAL; + return status; } @@ -2364,6 +752,11 @@ ath_hal_set_channels(struct ath_hal *ah, __func__, ah->ah_countryCode); } else status = HAL_EINVAL; + + if (status == HAL_OK) { + /* Update current DFS domain */ + (void) ath_hal_update_dfsdomain(ah); + } return status; } @@ -2429,6 +822,33 @@ ath_hal_getctl(struct ath_hal *ah, const struct ieee80211_channel *c) return ctl; } + +/* + * Update the current dfsDomain setting based on the given + * country code. + * + * Since FreeBSD/net80211 allows the channel set to change + * after the card has been setup (via ath_hal_init_channels()) + * this function method is needed to update ah_dfsDomain. + */ +void +ath_hal_update_dfsdomain(struct ath_hal *ah) +{ + const REG_DOMAIN *rd5GHz = AH_PRIVATE(ah)->ah_rd5GHz; + HAL_DFS_DOMAIN dfsDomain = HAL_DFS_UNINIT_DOMAIN; + + if (rd5GHz->dfsMask & DFS_FCC3) + dfsDomain = HAL_DFS_FCC_DOMAIN; + if (rd5GHz->dfsMask & DFS_ETSI) + dfsDomain = HAL_DFS_ETSI_DOMAIN; + if (rd5GHz->dfsMask & DFS_MKK4) + dfsDomain = HAL_DFS_MKK4_DOMAIN; + AH_PRIVATE(ah)->ah_dfsDomain = dfsDomain; + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, "%s ah_dfsDomain: %d\n", + __func__, AH_PRIVATE(ah)->ah_dfsDomain); +} + + /* * Return the max allowed antenna gain and apply any regulatory * domain specific changes. diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_regdomain.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_regdomain.h new file mode 100644 index 0000000000..e17e79a4e6 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_regdomain.h @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2005-2006 Atheros Communications, Inc. + * All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#ifndef __AH_REGDOMAIN_H__ +#define __AH_REGDOMAIN_H__ + +/* + * BMLEN defines the size of the bitmask used to hold frequency + * band specifications. Note this must agree with the BM macro + * definition that's used to setup initializers. See also further + * comments below. + */ +#define BMLEN 2 /* 2 x 64 bits in each channel bitmask */ +typedef uint64_t chanbmask_t[BMLEN]; + +/* + * The following describe the bit masks for different passive scan + * capability/requirements per regdomain. + */ +#define NO_PSCAN 0x0ULL /* NB: must be zero */ +#define PSCAN_FCC 0x0000000000000001ULL +#define PSCAN_FCC_T 0x0000000000000002ULL +#define PSCAN_ETSI 0x0000000000000004ULL +#define PSCAN_MKK1 0x0000000000000008ULL +#define PSCAN_MKK2 0x0000000000000010ULL +#define PSCAN_MKKA 0x0000000000000020ULL +#define PSCAN_MKKA_G 0x0000000000000040ULL +#define PSCAN_ETSIA 0x0000000000000080ULL +#define PSCAN_ETSIB 0x0000000000000100ULL +#define PSCAN_ETSIC 0x0000000000000200ULL +#define PSCAN_WWR 0x0000000000000400ULL +#define PSCAN_MKKA1 0x0000000000000800ULL +#define PSCAN_MKKA1_G 0x0000000000001000ULL +#define PSCAN_MKKA2 0x0000000000002000ULL +#define PSCAN_MKKA2_G 0x0000000000004000ULL +#define PSCAN_MKK3 0x0000000000008000ULL +#define PSCAN_DEFER 0x7FFFFFFFFFFFFFFFULL +#define IS_ECM_CHAN 0x8000000000000000ULL + +/* + * The following are flags for different requirements per reg domain. + * These requirements are either inhereted from the reg domain pair or + * from the unitary reg domain if the reg domain pair flags value is 0 + */ +enum { + NO_REQ = 0x00000000, /* NB: must be zero */ + DISALLOW_ADHOC_11A = 0x00000001, /* adhoc not allowed in 5GHz */ + DISALLOW_ADHOC_11A_TURB = 0x00000002, /* not allowed w/ 5GHz turbo */ + NEED_NFC = 0x00000004, /* need noise floor check */ + ADHOC_PER_11D = 0x00000008, /* must receive 11d beacon */ + LIMIT_FRAME_4MS = 0x00000020, /* 4msec tx burst limit */ + NO_HOSTAP = 0x00000040, /* No HOSTAP mode opereation */ +}; + +/* Bit masks for DFS per regdomain */ +enum { + NO_DFS = 0x0000000000000000ULL, /* NB: must be zero */ + DFS_FCC3 = 0x0000000000000001ULL, + DFS_ETSI = 0x0000000000000002ULL, + DFS_MKK4 = 0x0000000000000004ULL, +}; + +enum { /* conformance test limits */ + FCC = 0x10, + MKK = 0x40, + ETSI = 0x30, +}; + +/* + * THE following table is the mapping of regdomain pairs specified by + * an 8 bit regdomain value to the individual unitary reg domains + */ +typedef struct regDomainPair { + HAL_REG_DOMAIN regDmnEnum; /* 16 bit reg domain pair */ + HAL_REG_DOMAIN regDmn5GHz; /* 5GHz reg domain */ + HAL_REG_DOMAIN regDmn2GHz; /* 2GHz reg domain */ + uint32_t flags5GHz; /* Requirements flags (AdHoc + disallow, noise floor cal needed, + etc) */ + uint32_t flags2GHz; /* Requirements flags (AdHoc + disallow, noise floor cal needed, + etc) */ + uint64_t pscanMask; /* Passive Scan flags which + can override unitary domain + passive scan flags. This + value is used as a mask on + the unitary flags*/ + uint16_t singleCC; /* Country code of single country if + a one-on-one mapping exists */ +} REG_DMN_PAIR_MAPPING; + +typedef struct { + HAL_CTRY_CODE countryCode; + HAL_REG_DOMAIN regDmnEnum; +} COUNTRY_CODE_TO_ENUM_RD; + +/* + * Frequency band collections are defined using bitmasks. Each bit + * in a mask is the index of an entry in one of the following tables. + * Bitmasks are BMLEN*64 bits so if a table grows beyond that the bit + * vectors must be enlarged or the tables split somehow (e.g. split + * 1/2 and 1/4 rate channels into a separate table). + * + * Beware of ordering; the indices are defined relative to the preceding + * entry so if things get off there will be confusion. A good way to + * check the indices is to collect them in a switch statement in a stub + * function so the compiler checks for duplicates. + */ +typedef struct { + uint16_t lowChannel; /* Low channel center in MHz */ + uint16_t highChannel; /* High Channel center in MHz */ + uint8_t powerDfs; /* Max power (dBm) for channel + range when using DFS */ + uint8_t antennaMax; /* Max allowed antenna gain */ + uint8_t channelBW; /* Bandwidth of the channel */ + uint8_t channelSep; /* Channel separation within + the band */ + uint64_t useDfs; /* Use DFS in the RegDomain + if corresponding bit is set */ + uint64_t usePassScan; /* Use Passive Scan in the RegDomain + if corresponding bit is set */ +} REG_DMN_FREQ_BAND; + +typedef struct regDomain { + uint16_t regDmnEnum; /* value from EnumRd table */ + uint8_t conformanceTestLimit; + uint32_t flags; /* Requirement flags (AdHoc disallow, + noise floor cal needed, etc) */ + uint64_t dfsMask; /* DFS bitmask for 5Ghz tables */ + uint64_t pscan; /* Bitmask for passive scan */ + chanbmask_t chan11a; /* 11a channels */ + chanbmask_t chan11a_turbo; /* 11a static turbo channels */ + chanbmask_t chan11a_dyn_turbo; /* 11a dynamic turbo channels */ + chanbmask_t chan11a_half; /* 11a 1/2 width channels */ + chanbmask_t chan11a_quarter; /* 11a 1/4 width channels */ + chanbmask_t chan11b; /* 11b channels */ + chanbmask_t chan11g; /* 11g channels */ + chanbmask_t chan11g_turbo; /* 11g dynamic turbo channels */ + chanbmask_t chan11g_half; /* 11g 1/2 width channels */ + chanbmask_t chan11g_quarter; /* 11g 1/4 width channels */ +} REG_DOMAIN; + +struct cmode { + u_int mode; + u_int flags; +}; +#endif diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_regdomain/ah_rd_ctry.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_regdomain/ah_rd_ctry.h new file mode 100644 index 0000000000..af4824c3b5 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_regdomain/ah_rd_ctry.h @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2005-2011 Atheros Communications, Inc. + * All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ + +#ifndef __AH_REGDOMAIN_CTRY_H__ +#define __AH_REGDOMAIN_CTRY_H__ + +#define DEF_REGDMN FCC1_FCCA + +/* + * This table maps country ISO codes from net80211 into regulatory + * domains which the ath regulatory domain code understands. + */ +static COUNTRY_CODE_TO_ENUM_RD allCountries[] = { + { CTRY_DEBUG, NO_ENUMRD }, + { CTRY_DEFAULT, DEF_REGDMN }, + { CTRY_ALBANIA, NULL1_WORLD }, + { CTRY_ALGERIA, NULL1_WORLD }, + { CTRY_ARGENTINA, APL3_WORLD }, + { CTRY_ARMENIA, ETSI4_WORLD }, + { CTRY_AUSTRALIA, FCC3_WORLD }, + { CTRY_AUSTRIA, ETSI1_WORLD }, + { CTRY_AZERBAIJAN, ETSI4_WORLD }, + { CTRY_BAHRAIN, APL6_WORLD }, + { CTRY_BELARUS, NULL1_WORLD }, + { CTRY_BELGIUM, ETSI1_WORLD }, + { CTRY_BELIZE, APL1_ETSIC }, + { CTRY_BOLIVIA, APL1_ETSIC }, + { CTRY_BRAZIL, FCC3_WORLD }, + { CTRY_BRUNEI_DARUSSALAM,APL1_WORLD }, + { CTRY_BULGARIA, ETSI6_WORLD }, + { CTRY_CANADA, FCC2_FCCA }, + { CTRY_CHILE, APL6_WORLD }, + { CTRY_CHINA, APL1_WORLD }, + { CTRY_COLOMBIA, FCC1_FCCA }, + { CTRY_COSTA_RICA, NULL1_WORLD }, + { CTRY_CROATIA, ETSI3_WORLD }, + { CTRY_CYPRUS, ETSI1_WORLD }, + { CTRY_CZECH, ETSI1_WORLD }, + { CTRY_DENMARK, ETSI1_WORLD }, + { CTRY_DOMINICAN_REPUBLIC,FCC1_FCCA }, + { CTRY_ECUADOR, NULL1_WORLD }, + { CTRY_EGYPT, ETSI3_WORLD }, + { CTRY_EL_SALVADOR, NULL1_WORLD }, + { CTRY_ESTONIA, ETSI1_WORLD }, + { CTRY_FINLAND, ETSI1_WORLD }, + { CTRY_FRANCE, ETSI1_WORLD }, + { CTRY_FRANCE2, ETSI3_WORLD }, + { CTRY_GEORGIA, ETSI4_WORLD }, + { CTRY_GERMANY, ETSI1_WORLD }, + { CTRY_GREECE, ETSI1_WORLD }, + { CTRY_GUATEMALA, FCC1_FCCA }, + { CTRY_HONDURAS, NULL1_WORLD }, + { CTRY_HONG_KONG, FCC2_WORLD }, + { CTRY_HUNGARY, ETSI1_WORLD }, + { CTRY_ICELAND, ETSI1_WORLD }, + { CTRY_INDIA, APL6_WORLD }, + { CTRY_INDONESIA, APL1_WORLD }, + { CTRY_IRAN, APL1_WORLD }, + { CTRY_IRELAND, ETSI1_WORLD }, + { CTRY_ISRAEL, NULL1_WORLD }, + { CTRY_ITALY, ETSI1_WORLD }, + { CTRY_JAPAN, MKK1_MKKA }, + { CTRY_JAPAN1, MKK1_MKKB }, + { CTRY_JAPAN2, MKK1_FCCA }, + { CTRY_JAPAN3, MKK2_MKKA }, + { CTRY_JAPAN4, MKK1_MKKA1 }, + { CTRY_JAPAN5, MKK1_MKKA2 }, + { CTRY_JAPAN6, MKK1_MKKC }, + + { CTRY_JAPAN7, MKK3_MKKB }, + { CTRY_JAPAN8, MKK3_MKKA2 }, + { CTRY_JAPAN9, MKK3_MKKC }, + + { CTRY_JAPAN10, MKK4_MKKB }, + { CTRY_JAPAN11, MKK4_MKKA2 }, + { CTRY_JAPAN12, MKK4_MKKC }, + + { CTRY_JAPAN13, MKK5_MKKB }, + { CTRY_JAPAN14, MKK5_MKKA2 }, + { CTRY_JAPAN15, MKK5_MKKC }, + + { CTRY_JAPAN16, MKK6_MKKB }, + { CTRY_JAPAN17, MKK6_MKKA2 }, + { CTRY_JAPAN18, MKK6_MKKC }, + + { CTRY_JAPAN19, MKK7_MKKB }, + { CTRY_JAPAN20, MKK7_MKKA2 }, + { CTRY_JAPAN21, MKK7_MKKC }, + + { CTRY_JAPAN22, MKK8_MKKB }, + { CTRY_JAPAN23, MKK8_MKKA2 }, + { CTRY_JAPAN24, MKK8_MKKC }, + + { CTRY_JORDAN, APL4_WORLD }, + { CTRY_KAZAKHSTAN, NULL1_WORLD }, + { CTRY_KOREA_NORTH, APL2_WORLD }, + { CTRY_KOREA_ROC, APL2_WORLD }, + { CTRY_KOREA_ROC2, APL2_WORLD }, + { CTRY_KOREA_ROC3, APL9_WORLD }, + { CTRY_KUWAIT, NULL1_WORLD }, + { CTRY_LATVIA, ETSI1_WORLD }, + { CTRY_LEBANON, NULL1_WORLD }, + { CTRY_LIECHTENSTEIN,ETSI1_WORLD }, + { CTRY_LITHUANIA, ETSI1_WORLD }, + { CTRY_LUXEMBOURG, ETSI1_WORLD }, + { CTRY_MACAU, FCC2_WORLD }, + { CTRY_MACEDONIA, NULL1_WORLD }, + { CTRY_MALAYSIA, APL8_WORLD }, + { CTRY_MALTA, ETSI1_WORLD }, + { CTRY_MEXICO, FCC1_FCCA }, + { CTRY_MONACO, ETSI4_WORLD }, + { CTRY_MOROCCO, NULL1_WORLD }, + { CTRY_NETHERLANDS, ETSI1_WORLD }, + { CTRY_NEW_ZEALAND, FCC2_ETSIC }, + { CTRY_NORWAY, ETSI1_WORLD }, + { CTRY_OMAN, APL6_WORLD }, + { CTRY_PAKISTAN, NULL1_WORLD }, + { CTRY_PANAMA, FCC1_FCCA }, + { CTRY_PERU, APL1_WORLD }, + { CTRY_PHILIPPINES, FCC3_WORLD }, + { CTRY_POLAND, ETSI1_WORLD }, + { CTRY_PORTUGAL, ETSI1_WORLD }, + { CTRY_PUERTO_RICO, FCC1_FCCA }, + { CTRY_QATAR, NULL1_WORLD }, + { CTRY_ROMANIA, NULL1_WORLD }, + { CTRY_RUSSIA, NULL1_WORLD }, + { CTRY_SAUDI_ARABIA,FCC2_WORLD }, + { CTRY_SINGAPORE, APL6_WORLD }, + { CTRY_SLOVAKIA, ETSI1_WORLD }, + { CTRY_SLOVENIA, ETSI1_WORLD }, + { CTRY_SOUTH_AFRICA,FCC3_WORLD }, + { CTRY_SPAIN, ETSI1_WORLD }, + { CTRY_SWEDEN, ETSI1_WORLD }, + { CTRY_SWITZERLAND, ETSI1_WORLD }, + { CTRY_SYRIA, NULL1_WORLD }, + { CTRY_TAIWAN, APL3_FCCA }, + { CTRY_THAILAND, FCC3_WORLD }, + { CTRY_TRINIDAD_Y_TOBAGO,ETSI4_WORLD }, + { CTRY_TUNISIA, ETSI3_WORLD }, + { CTRY_TURKEY, ETSI3_WORLD }, + { CTRY_UKRAINE, NULL1_WORLD }, + { CTRY_UAE, NULL1_WORLD }, + { CTRY_UNITED_KINGDOM, ETSI1_WORLD }, + { CTRY_UNITED_STATES, FCC1_FCCA }, + { CTRY_UNITED_STATES_FCC49,FCC4_FCCA }, + { CTRY_URUGUAY, FCC1_WORLD }, + { CTRY_UZBEKISTAN, FCC3_FCCA }, + { CTRY_VENEZUELA, APL2_ETSIC }, + { CTRY_VIET_NAM, NULL1_WORLD }, + { CTRY_ZIMBABWE, NULL1_WORLD } +}; + +#endif diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_regdomain/ah_rd_domains.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_regdomain/ah_rd_domains.h new file mode 100644 index 0000000000..b8b8b2b8e9 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_regdomain/ah_rd_domains.h @@ -0,0 +1,749 @@ +/* + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2005-2006 Atheros Communications, Inc. + * All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ + +#ifndef __AH_REGDOMAIN_DOMAINS_H__ +#define __AH_REGDOMAIN_DOMAINS_H__ + +/* + * BMLEN defines the size of the bitmask used to hold frequency + * band specifications. Note this must agree with the BM macro + * definition that's used to setup initializers. See also further + * comments below. + */ +/* BMLEN is now defined in ah_regdomain.h */ +#define W0(_a) \ + (((_a) >= 0 && (_a) < 64 ? (((uint64_t) 1)<<(_a)) : (uint64_t) 0)) +#define W1(_a) \ + (((_a) > 63 && (_a) < 128 ? (((uint64_t) 1)<<((_a)-64)) : (uint64_t) 0)) +#define BM1(_fa) { W0(_fa), W1(_fa) } +#define BM2(_fa, _fb) { W0(_fa) | W0(_fb), W1(_fa) | W1(_fb) } +#define BM3(_fa, _fb, _fc) \ + { W0(_fa) | W0(_fb) | W0(_fc), W1(_fa) | W1(_fb) | W1(_fc) } +#define BM4(_fa, _fb, _fc, _fd) \ + { W0(_fa) | W0(_fb) | W0(_fc) | W0(_fd), \ + W1(_fa) | W1(_fb) | W1(_fc) | W1(_fd) } +#define BM5(_fa, _fb, _fc, _fd, _fe) \ + { W0(_fa) | W0(_fb) | W0(_fc) | W0(_fd) | W0(_fe), \ + W1(_fa) | W1(_fb) | W1(_fc) | W1(_fd) | W1(_fe) } +#define BM6(_fa, _fb, _fc, _fd, _fe, _ff) \ + { W0(_fa) | W0(_fb) | W0(_fc) | W0(_fd) | W0(_fe) | W0(_ff), \ + W1(_fa) | W1(_fb) | W1(_fc) | W1(_fd) | W1(_fe) | W1(_ff) } +#define BM7(_fa, _fb, _fc, _fd, _fe, _ff, _fg) \ + { W0(_fa) | W0(_fb) | W0(_fc) | W0(_fd) | W0(_fe) | W0(_ff) | \ + W0(_fg),\ + W1(_fa) | W1(_fb) | W1(_fc) | W1(_fd) | W1(_fe) | W1(_ff) | \ + W1(_fg) } +#define BM8(_fa, _fb, _fc, _fd, _fe, _ff, _fg, _fh) \ + { W0(_fa) | W0(_fb) | W0(_fc) | W0(_fd) | W0(_fe) | W0(_ff) | \ + W0(_fg) | W0(_fh) , \ + W1(_fa) | W1(_fb) | W1(_fc) | W1(_fd) | W1(_fe) | W1(_ff) | \ + W1(_fg) | W1(_fh) } +#define BM9(_fa, _fb, _fc, _fd, _fe, _ff, _fg, _fh, _fi) \ + { W0(_fa) | W0(_fb) | W0(_fc) | W0(_fd) | W0(_fe) | W0(_ff) | \ + W0(_fg) | W0(_fh) | W0(_fi) , \ + W1(_fa) | W1(_fb) | W1(_fc) | W1(_fd) | W1(_fe) | W1(_ff) | \ + W1(_fg) | W1(_fh) | W1(_fi) } + +static REG_DOMAIN regDomains[] = { + + {.regDmnEnum = DEBUG_REG_DMN, + .conformanceTestLimit = FCC, + .dfsMask = DFS_FCC3, + .chan11a = BM4(F1_4950_4980, + F1_5120_5240, + F1_5260_5700, + F1_5745_5825), + .chan11a_half = BM4(F1_4945_4985, + F2_5120_5240, + F2_5260_5700, + F7_5745_5825), + .chan11a_quarter = BM4(F1_4942_4987, + F3_5120_5240, + F3_5260_5700, + F8_5745_5825), + .chan11a_turbo = BM8(T1_5130_5210, + T1_5250_5330, + T1_5370_5490, + T1_5530_5650, + T1_5150_5190, + T1_5230_5310, + T1_5350_5470, + T1_5510_5670), + .chan11a_dyn_turbo = BM4(T1_5200_5240, + T1_5280_5280, + T1_5540_5660, + T1_5765_5805), + .chan11b = BM4(F1_2312_2372, + F1_2412_2472, + F1_2484_2484, + F1_2512_2732), + .chan11g = BM3(G1_2312_2372, G1_2412_2472, G1_2512_2732), + .chan11g_turbo = BM3(T1_2312_2372, T1_2437_2437, T1_2512_2732), + .chan11g_half = BM3(G2_2312_2372, G4_2412_2472, G2_2512_2732), + .chan11g_quarter = BM3(G3_2312_2372, G5_2412_2472, G3_2512_2732), + }, + + {.regDmnEnum = APL1, + .conformanceTestLimit = FCC, + .chan11a = BM1(F4_5745_5825), + }, + + {.regDmnEnum = APL2, + .conformanceTestLimit = FCC, + .chan11a = BM1(F1_5745_5805), + }, + + {.regDmnEnum = APL3, + .conformanceTestLimit = FCC, + .chan11a = BM2(F1_5280_5320, F2_5745_5805), + }, + + {.regDmnEnum = APL4, + .conformanceTestLimit = FCC, + .chan11a = BM2(F4_5180_5240, F3_5745_5825), + }, + + {.regDmnEnum = APL5, + .conformanceTestLimit = FCC, + .chan11a = BM1(F2_5745_5825), + }, + + {.regDmnEnum = APL6, + .conformanceTestLimit = ETSI, + .dfsMask = DFS_ETSI, + .pscan = PSCAN_FCC_T | PSCAN_FCC, + .chan11a = BM3(F4_5180_5240, F2_5260_5320, F3_5745_5825), + .chan11a_turbo = BM3(T2_5210_5210, T1_5250_5290, T1_5760_5800), + }, + + {.regDmnEnum = APL8, + .conformanceTestLimit = ETSI, + .flags = DISALLOW_ADHOC_11A|DISALLOW_ADHOC_11A_TURB, + .chan11a = BM2(F6_5260_5320, F4_5745_5825), + }, + + {.regDmnEnum = APL9, + .conformanceTestLimit = ETSI, + .dfsMask = DFS_ETSI, + .pscan = PSCAN_ETSI, + .flags = DISALLOW_ADHOC_11A|DISALLOW_ADHOC_11A_TURB, + .chan11a = BM3(F1_5180_5320, F1_5500_5620, F3_5745_5805), + }, + + {.regDmnEnum = ETSI1, + .conformanceTestLimit = ETSI, + .dfsMask = DFS_ETSI, + .pscan = PSCAN_ETSI, + .flags = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + .chan11a = BM3(W2_5180_5240, F2_5260_5320, F2_5500_5700), + }, + + {.regDmnEnum = ETSI2, + .conformanceTestLimit = ETSI, + .dfsMask = DFS_ETSI, + .pscan = PSCAN_ETSI, + .flags = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + .chan11a = BM1(F3_5180_5240), + }, + + {.regDmnEnum = ETSI3, + .conformanceTestLimit = ETSI, + .dfsMask = DFS_ETSI, + .pscan = PSCAN_ETSI, + .flags = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + .chan11a = BM2(W2_5180_5240, F2_5260_5320), + }, + + {.regDmnEnum = ETSI4, + .conformanceTestLimit = ETSI, + .dfsMask = DFS_ETSI, + .pscan = PSCAN_ETSI, + .flags = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + .chan11a = BM2(F3_5180_5240, F1_5260_5320), + }, + + {.regDmnEnum = ETSI5, + .conformanceTestLimit = ETSI, + .dfsMask = DFS_ETSI, + .pscan = PSCAN_ETSI, + .flags = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + .chan11a = BM1(F1_5180_5240), + }, + + {.regDmnEnum = ETSI6, + .conformanceTestLimit = ETSI, + .dfsMask = DFS_ETSI, + .pscan = PSCAN_ETSI, + .flags = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + .chan11a = BM3(F5_5180_5240, F1_5260_5280, F3_5500_5700), + }, + + {.regDmnEnum = FCC1, + .conformanceTestLimit = FCC, + .chan11a = BM3(F2_5180_5240, F4_5260_5320, F5_5745_5825), + .chan11a_turbo = BM3(T1_5210_5210, T2_5250_5290, T2_5760_5800), + .chan11a_dyn_turbo = BM3(T1_5200_5240, T1_5280_5280, T1_5765_5805), + }, + + {.regDmnEnum = FCC2, + .conformanceTestLimit = FCC, + .chan11a = BM3(F6_5180_5240, F5_5260_5320, F6_5745_5825), + .chan11a_dyn_turbo = BM3(T2_5200_5240, T1_5280_5280, T1_5765_5805), + }, + + {.regDmnEnum = FCC3, + .conformanceTestLimit = FCC, + .dfsMask = DFS_FCC3, + .pscan = PSCAN_FCC | PSCAN_FCC_T, + .chan11a = BM4(F2_5180_5240, + F3_5260_5320, + F1_5500_5700, + F5_5745_5825), + .chan11a_turbo = BM4(T1_5210_5210, + T1_5250_5250, + T1_5290_5290, + T2_5760_5800), + .chan11a_dyn_turbo = BM3(T1_5200_5240, T2_5280_5280, T1_5540_5660), + }, + + {.regDmnEnum = FCC4, + .conformanceTestLimit = FCC, + .dfsMask = DFS_FCC3, + .pscan = PSCAN_FCC | PSCAN_FCC_T, + .chan11a = BM1(F1_4950_4980), + .chan11a_half = BM1(F1_4945_4985), + .chan11a_quarter = BM1(F1_4942_4987), + }, + + /* FCC1 w/ 1/2 and 1/4 width channels */ + {.regDmnEnum = FCC5, + .conformanceTestLimit = FCC, + .chan11a = BM3(F2_5180_5240, F4_5260_5320, F5_5745_5825), + .chan11a_turbo = BM3(T1_5210_5210, T2_5250_5290, T2_5760_5800), + .chan11a_dyn_turbo = BM3(T1_5200_5240, T1_5280_5280, T1_5765_5805), + .chan11a_half = BM3(F7_5180_5240, F7_5260_5320, F9_5745_5825), + .chan11a_quarter = BM3(F8_5180_5240, F8_5260_5320,F10_5745_5825), + }, + + {.regDmnEnum = MKK1, + .conformanceTestLimit = MKK, + .pscan = PSCAN_MKK1, + .flags = DISALLOW_ADHOC_11A_TURB, + .chan11a = BM1(F1_5170_5230), + }, + + {.regDmnEnum = MKK2, + .conformanceTestLimit = MKK, + .pscan = PSCAN_MKK2, + .flags = DISALLOW_ADHOC_11A_TURB, + .chan11a = BM3(F1_4920_4980, F1_5040_5080, F1_5170_5230), + .chan11a_half = BM4(F1_4915_4925, + F1_4935_4945, + F1_5035_5040, + F1_5055_5055), + }, + + /* UNI-1 even */ + {.regDmnEnum = MKK3, + .conformanceTestLimit = MKK, + .pscan = PSCAN_MKK3, + .flags = DISALLOW_ADHOC_11A_TURB, + .chan11a = BM1(F4_5180_5240), + }, + + /* UNI-1 even + UNI-2 */ + {.regDmnEnum = MKK4, + .conformanceTestLimit = MKK, + .dfsMask = DFS_MKK4, + .pscan = PSCAN_MKK3, + .flags = DISALLOW_ADHOC_11A_TURB, + .chan11a = BM2(F4_5180_5240, F2_5260_5320), + }, + + /* UNI-1 even + UNI-2 + mid-band */ + {.regDmnEnum = MKK5, + .conformanceTestLimit = MKK, + .dfsMask = DFS_MKK4, + .pscan = PSCAN_MKK3, + .flags = DISALLOW_ADHOC_11A_TURB, + .chan11a = BM3(F4_5180_5240, F2_5260_5320, F4_5500_5700), + }, + + /* UNI-1 odd + even */ + {.regDmnEnum = MKK6, + .conformanceTestLimit = MKK, + .pscan = PSCAN_MKK1, + .flags = DISALLOW_ADHOC_11A_TURB, + .chan11a = BM2(F2_5170_5230, F4_5180_5240), + }, + + /* UNI-1 odd + UNI-1 even + UNI-2 */ + {.regDmnEnum = MKK7, + .conformanceTestLimit = MKK, + .dfsMask = DFS_MKK4, + .pscan = PSCAN_MKK1 | PSCAN_MKK3, + .flags = DISALLOW_ADHOC_11A_TURB, + .chan11a = BM3(F1_5170_5230, F4_5180_5240, F2_5260_5320), + }, + + /* UNI-1 odd + UNI-1 even + UNI-2 + mid-band */ + {.regDmnEnum = MKK8, + .conformanceTestLimit = MKK, + .dfsMask = DFS_MKK4, + .pscan = PSCAN_MKK1 | PSCAN_MKK3, + .flags = DISALLOW_ADHOC_11A_TURB, + .chan11a = BM4(F1_5170_5230, + F4_5180_5240, + F2_5260_5320, + F4_5500_5700), + }, + + /* UNI-1 even + 4.9 GHZ */ + {.regDmnEnum = MKK9, + .conformanceTestLimit = MKK, + .pscan = PSCAN_MKK3, + .flags = DISALLOW_ADHOC_11A_TURB, + .chan11a = BM7(F1_4915_4925, + F1_4935_4945, + F1_4920_4980, + F1_5035_5040, + F1_5055_5055, + F1_5040_5080, + F4_5180_5240), + }, + + /* UNI-1 even + UNI-2 + 4.9 GHZ */ + {.regDmnEnum = MKK10, + .conformanceTestLimit = MKK, + .dfsMask = DFS_MKK4, + .pscan = PSCAN_MKK3, + .flags = DISALLOW_ADHOC_11A_TURB, + .chan11a = BM8(F1_4915_4925, + F1_4935_4945, + F1_4920_4980, + F1_5035_5040, + F1_5055_5055, + F1_5040_5080, + F4_5180_5240, + F2_5260_5320), + }, + + /* Defined here to use when 2G channels are authorised for country K2 */ + {.regDmnEnum = APLD, + .conformanceTestLimit = NO_CTL, + .chan11b = BM2(F2_2312_2372,F2_2412_2472), + .chan11g = BM2(G2_2312_2372,G2_2412_2472), + }, + + {.regDmnEnum = ETSIA, + .conformanceTestLimit = NO_CTL, + .pscan = PSCAN_ETSIA, + .flags = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + .chan11b = BM1(F1_2457_2472), + .chan11g = BM1(G1_2457_2472), + .chan11g_turbo = BM1(T2_2437_2437) + }, + + {.regDmnEnum = ETSIB, + .conformanceTestLimit = ETSI, + .pscan = PSCAN_ETSIB, + .flags = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + .chan11b = BM1(F1_2432_2442), + .chan11g = BM1(G1_2432_2442), + .chan11g_turbo = BM1(T2_2437_2437) + }, + + {.regDmnEnum = ETSIC, + .conformanceTestLimit = ETSI, + .pscan = PSCAN_ETSIC, + .flags = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + .chan11b = BM1(F3_2412_2472), + .chan11g = BM1(G3_2412_2472), + .chan11g_turbo = BM1(T2_2437_2437) + }, + + {.regDmnEnum = FCCA, + .conformanceTestLimit = FCC, + .chan11b = BM1(F1_2412_2462), + .chan11g = BM1(G1_2412_2462), + .chan11g_turbo = BM1(T2_2437_2437), + }, + + /* FCCA w/ 1/2 and 1/4 width channels */ + {.regDmnEnum = FCCB, + .conformanceTestLimit = FCC, + .chan11b = BM1(F1_2412_2462), + .chan11g = BM1(G1_2412_2462), + .chan11g_turbo = BM1(T2_2437_2437), + .chan11g_half = BM1(G3_2412_2462), + .chan11g_quarter = BM1(G4_2412_2462), + }, + + {.regDmnEnum = MKKA, + .conformanceTestLimit = MKK, + .pscan = PSCAN_MKKA | PSCAN_MKKA_G + | PSCAN_MKKA1 | PSCAN_MKKA1_G + | PSCAN_MKKA2 | PSCAN_MKKA2_G, + .flags = DISALLOW_ADHOC_11A_TURB, + .chan11b = BM3(F2_2412_2462, F1_2467_2472, F2_2484_2484), + .chan11g = BM2(G2_2412_2462, G1_2467_2472), + .chan11g_turbo = BM1(T2_2437_2437) + }, + + {.regDmnEnum = MKKC, + .conformanceTestLimit = MKK, + .chan11b = BM1(F2_2412_2472), + .chan11g = BM1(G2_2412_2472), + .chan11g_turbo = BM1(T2_2437_2437) + }, + + {.regDmnEnum = WORLD, + .conformanceTestLimit = ETSI, + .chan11b = BM1(F2_2412_2472), + .chan11g = BM1(G2_2412_2472), + .chan11g_turbo = BM1(T2_2437_2437) + }, + + {.regDmnEnum = WOR0_WORLD, + .conformanceTestLimit = NO_CTL, + .dfsMask = DFS_FCC3 | DFS_ETSI, + .pscan = PSCAN_WWR, + .flags = ADHOC_PER_11D, + .chan11a = BM5(W1_5260_5320, + W1_5180_5240, + W1_5170_5230, + W1_5745_5825, + W1_5500_5700), + .chan11a_turbo = BM3(WT1_5210_5250, + WT1_5290_5290, + WT1_5760_5800), + .chan11b = BM8(W1_2412_2412, + W1_2437_2442, + W1_2462_2462, + W1_2472_2472, + W1_2417_2432, + W1_2447_2457, + W1_2467_2467, + W1_2484_2484), + .chan11g = BM7(WG1_2412_2412, + WG1_2437_2442, + WG1_2462_2462, + WG1_2472_2472, + WG1_2417_2432, + WG1_2447_2457, + WG1_2467_2467), + .chan11g_turbo = BM1(T3_2437_2437) + }, + + {.regDmnEnum = WOR01_WORLD, + .conformanceTestLimit = NO_CTL, + .dfsMask = DFS_FCC3 | DFS_ETSI, + .pscan = PSCAN_WWR, + .flags = ADHOC_PER_11D, + .chan11a = BM5(W1_5260_5320, + W1_5180_5240, + W1_5170_5230, + W1_5745_5825, + W1_5500_5700), + .chan11a_turbo = BM3(WT1_5210_5250, + WT1_5290_5290, + WT1_5760_5800), + .chan11b = BM5(W1_2412_2412, + W1_2437_2442, + W1_2462_2462, + W1_2417_2432, + W1_2447_2457), + .chan11g = BM5(WG1_2412_2412, + WG1_2437_2442, + WG1_2462_2462, + WG1_2417_2432, + WG1_2447_2457), + .chan11g_turbo = BM1(T3_2437_2437)}, + + {.regDmnEnum = WOR02_WORLD, + .conformanceTestLimit = NO_CTL, + .dfsMask = DFS_FCC3 | DFS_ETSI, + .pscan = PSCAN_WWR, + .flags = ADHOC_PER_11D, + .chan11a = BM5(W1_5260_5320, + W1_5180_5240, + W1_5170_5230, + W1_5745_5825, + W1_5500_5700), + .chan11a_turbo = BM3(WT1_5210_5250, + WT1_5290_5290, + WT1_5760_5800), + .chan11b = BM7(W1_2412_2412, + W1_2437_2442, + W1_2462_2462, + W1_2472_2472, + W1_2417_2432, + W1_2447_2457, + W1_2467_2467), + .chan11g = BM7(WG1_2412_2412, + WG1_2437_2442, + WG1_2462_2462, + WG1_2472_2472, + WG1_2417_2432, + WG1_2447_2457, + WG1_2467_2467), + .chan11g_turbo = BM1(T3_2437_2437)}, + + {.regDmnEnum = EU1_WORLD, + .conformanceTestLimit = NO_CTL, + .dfsMask = DFS_FCC3 | DFS_ETSI, + .pscan = PSCAN_WWR, + .flags = ADHOC_PER_11D, + .chan11a = BM5(W1_5260_5320, + W1_5180_5240, + W1_5170_5230, + W1_5745_5825, + W1_5500_5700), + .chan11a_turbo = BM3(WT1_5210_5250, + WT1_5290_5290, + WT1_5760_5800), + .chan11b = BM7(W1_2412_2412, + W1_2437_2442, + W1_2462_2462, + W2_2472_2472, + W1_2417_2432, + W1_2447_2457, + W2_2467_2467), + .chan11g = BM7(WG1_2412_2412, + WG1_2437_2442, + WG1_2462_2462, + WG2_2472_2472, + WG1_2417_2432, + WG1_2447_2457, + WG2_2467_2467), + .chan11g_turbo = BM1(T3_2437_2437)}, + + {.regDmnEnum = WOR1_WORLD, + .conformanceTestLimit = NO_CTL, + .dfsMask = DFS_FCC3 | DFS_ETSI, + .pscan = PSCAN_WWR, + .flags = DISALLOW_ADHOC_11A, + .chan11a = BM5(W1_5260_5320, + W1_5180_5240, + W1_5170_5230, + W1_5745_5825, + W1_5500_5700), + .chan11b = BM8(W1_2412_2412, + W1_2437_2442, + W1_2462_2462, + W1_2472_2472, + W1_2417_2432, + W1_2447_2457, + W1_2467_2467, + W1_2484_2484), + .chan11g = BM7(WG1_2412_2412, + WG1_2437_2442, + WG1_2462_2462, + WG1_2472_2472, + WG1_2417_2432, + WG1_2447_2457, + WG1_2467_2467), + .chan11g_turbo = BM1(T3_2437_2437) + }, + + {.regDmnEnum = WOR2_WORLD, + .conformanceTestLimit = NO_CTL, + .dfsMask = DFS_FCC3 | DFS_ETSI, + .pscan = PSCAN_WWR, + .flags = DISALLOW_ADHOC_11A, + .chan11a = BM5(W1_5260_5320, + W1_5180_5240, + W1_5170_5230, + W1_5745_5825, + W1_5500_5700), + .chan11a_turbo = BM3(WT1_5210_5250, + WT1_5290_5290, + WT1_5760_5800), + .chan11b = BM8(W1_2412_2412, + W1_2437_2442, + W1_2462_2462, + W1_2472_2472, + W1_2417_2432, + W1_2447_2457, + W1_2467_2467, + W1_2484_2484), + .chan11g = BM7(WG1_2412_2412, + WG1_2437_2442, + WG1_2462_2462, + WG1_2472_2472, + WG1_2417_2432, + WG1_2447_2457, + WG1_2467_2467), + .chan11g_turbo = BM1(T3_2437_2437)}, + + {.regDmnEnum = WOR3_WORLD, + .conformanceTestLimit = NO_CTL, + .dfsMask = DFS_FCC3 | DFS_ETSI, + .pscan = PSCAN_WWR, + .flags = ADHOC_PER_11D, + .chan11a = BM4(W1_5260_5320, + W1_5180_5240, + W1_5170_5230, + W1_5745_5825), + .chan11a_turbo = BM3(WT1_5210_5250, + WT1_5290_5290, + WT1_5760_5800), + .chan11b = BM7(W1_2412_2412, + W1_2437_2442, + W1_2462_2462, + W1_2472_2472, + W1_2417_2432, + W1_2447_2457, + W1_2467_2467), + .chan11g = BM7(WG1_2412_2412, + WG1_2437_2442, + WG1_2462_2462, + WG1_2472_2472, + WG1_2417_2432, + WG1_2447_2457, + WG1_2467_2467), + .chan11g_turbo = BM1(T3_2437_2437)}, + + {.regDmnEnum = WOR4_WORLD, + .conformanceTestLimit = NO_CTL, + .dfsMask = DFS_FCC3 | DFS_ETSI, + .pscan = PSCAN_WWR, + .flags = DISALLOW_ADHOC_11A, + .chan11a = BM4(W2_5260_5320, + W2_5180_5240, + F2_5745_5805, + W2_5825_5825), + .chan11a_turbo = BM3(WT1_5210_5250, + WT1_5290_5290, + WT1_5760_5800), + .chan11b = BM5(W1_2412_2412, + W1_2437_2442, + W1_2462_2462, + W1_2417_2432, + W1_2447_2457), + .chan11g = BM5(WG1_2412_2412, + WG1_2437_2442, + WG1_2462_2462, + WG1_2417_2432, + WG1_2447_2457), + .chan11g_turbo = BM1(T3_2437_2437)}, + + {.regDmnEnum = WOR5_ETSIC, + .conformanceTestLimit = NO_CTL, + .dfsMask = DFS_FCC3 | DFS_ETSI, + .pscan = PSCAN_WWR, + .flags = DISALLOW_ADHOC_11A, + .chan11a = BM3(W1_5260_5320, W2_5180_5240, F6_5745_5825), + .chan11b = BM7(W1_2412_2412, + W1_2437_2442, + W1_2462_2462, + W2_2472_2472, + W1_2417_2432, + W1_2447_2457, + W2_2467_2467), + .chan11g = BM7(WG1_2412_2412, + WG1_2437_2442, + WG1_2462_2462, + WG2_2472_2472, + WG1_2417_2432, + WG1_2447_2457, + WG2_2467_2467), + .chan11g_turbo = BM1(T3_2437_2437)}, + + {.regDmnEnum = WOR9_WORLD, + .conformanceTestLimit = NO_CTL, + .dfsMask = DFS_FCC3 | DFS_ETSI, + .pscan = PSCAN_WWR, + .flags = DISALLOW_ADHOC_11A, + .chan11a = BM4(W1_5260_5320, + W1_5180_5240, + W1_5745_5825, + W1_5500_5700), + .chan11a_turbo = BM3(WT1_5210_5250, + WT1_5290_5290, + WT1_5760_5800), + .chan11b = BM5(W1_2412_2412, + W1_2437_2442, + W1_2462_2462, + W1_2417_2432, + W1_2447_2457), + .chan11g = BM5(WG1_2412_2412, + WG1_2437_2442, + WG1_2462_2462, + WG1_2417_2432, + WG1_2447_2457), + .chan11g_turbo = BM1(T3_2437_2437)}, + + {.regDmnEnum = WORA_WORLD, + .conformanceTestLimit = NO_CTL, + .dfsMask = DFS_FCC3 | DFS_ETSI, + .pscan = PSCAN_WWR, + .flags = DISALLOW_ADHOC_11A, + .chan11a = BM4(W1_5260_5320, + W1_5180_5240, + W1_5745_5825, + W1_5500_5700), + .chan11b = BM7(W1_2412_2412, + W1_2437_2442, + W1_2462_2462, + W1_2472_2472, + W1_2417_2432, + W1_2447_2457, + W1_2467_2467), + .chan11g = BM7(WG1_2412_2412, + WG1_2437_2442, + WG1_2462_2462, + WG1_2472_2472, + WG1_2417_2432, + WG1_2447_2457, + WG1_2467_2467), + .chan11g_turbo = BM1(T3_2437_2437)}, + + {.regDmnEnum = WORB_WORLD, + .conformanceTestLimit = NO_CTL, + .dfsMask = DFS_FCC3 | DFS_ETSI, + .pscan = PSCAN_WWR, + .flags = DISALLOW_ADHOC_11A, + .chan11a = BM4(W1_5260_5320, + W1_5180_5240, + W1_5745_5825, + W1_5500_5700), + .chan11b = BM7(W1_2412_2412, + W1_2437_2442, + W1_2462_2462, + W1_2472_2472, + W1_2417_2432, + W1_2447_2457, + W1_2467_2467), + .chan11g = BM7(WG1_2412_2412, + WG1_2437_2442, + WG1_2462_2462, + WG1_2472_2472, + WG1_2417_2432, + WG1_2447_2457, + WG1_2467_2467), + .chan11g_turbo = BM1(T3_2437_2437)}, + + {.regDmnEnum = NULL1, + .conformanceTestLimit = NO_CTL, + } +}; + +#endif diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_regdomain/ah_rd_freqbands.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_regdomain/ah_rd_freqbands.h new file mode 100644 index 0000000000..79d418f3c7 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_regdomain/ah_rd_freqbands.h @@ -0,0 +1,419 @@ +/* + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2005-2006 Atheros Communications, Inc. + * All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ + +#ifndef __AH_REGDOMAIN_FREQBANDS_H__ +#define __AH_REGDOMAIN_FREQBANDS_H__ + +#define AFTER(x) ((x)+1) + +/* + * Frequency band collections are defined using bitmasks. Each bit + * in a mask is the index of an entry in one of the following tables. + * Bitmasks are BMLEN*64 bits so if a table grows beyond that the bit + * vectors must be enlarged or the tables split somehow (e.g. split + * 1/2 and 1/4 rate channels into a separate table). + * + * Beware of ordering; the indices are defined relative to the preceding + * entry so if things get off there will be confusion. A good way to + * check the indices is to collect them in a switch statement in a stub + * function so the compiler checks for duplicates. + */ + +/* + * 5GHz 11A channel tags + */ +static REG_DMN_FREQ_BAND regDmn5GhzFreq[] = { + { 4915, 4925, 23, 0, 10, 5, NO_DFS, PSCAN_MKK2 }, +#define F1_4915_4925 0 + { 4935, 4945, 23, 0, 10, 5, NO_DFS, PSCAN_MKK2 }, +#define F1_4935_4945 AFTER(F1_4915_4925) + { 4920, 4980, 23, 0, 20, 20, NO_DFS, PSCAN_MKK2 }, +#define F1_4920_4980 AFTER(F1_4935_4945) + { 4942, 4987, 27, 6, 5, 5, NO_DFS, PSCAN_FCC }, +#define F1_4942_4987 AFTER(F1_4920_4980) + { 4945, 4985, 30, 6, 10, 5, NO_DFS, PSCAN_FCC }, +#define F1_4945_4985 AFTER(F1_4942_4987) + { 4950, 4980, 33, 6, 20, 5, NO_DFS, PSCAN_FCC }, +#define F1_4950_4980 AFTER(F1_4945_4985) + { 5035, 5040, 23, 0, 10, 5, NO_DFS, PSCAN_MKK2 }, +#define F1_5035_5040 AFTER(F1_4950_4980) + { 5040, 5080, 23, 0, 20, 20, NO_DFS, PSCAN_MKK2 }, +#define F1_5040_5080 AFTER(F1_5035_5040) + { 5055, 5055, 23, 0, 10, 5, NO_DFS, PSCAN_MKK2 }, +#define F1_5055_5055 AFTER(F1_5040_5080) + + { 5120, 5240, 5, 6, 20, 20, NO_DFS, NO_PSCAN }, +#define F1_5120_5240 AFTER(F1_5055_5055) + { 5120, 5240, 5, 6, 10, 10, NO_DFS, NO_PSCAN }, +#define F2_5120_5240 AFTER(F1_5120_5240) + { 5120, 5240, 5, 6, 5, 5, NO_DFS, NO_PSCAN }, +#define F3_5120_5240 AFTER(F2_5120_5240) + + { 5170, 5230, 23, 0, 20, 20, NO_DFS, PSCAN_MKK1 | PSCAN_MKK2 }, +#define F1_5170_5230 AFTER(F3_5120_5240) + { 5170, 5230, 20, 0, 20, 20, NO_DFS, PSCAN_MKK1 | PSCAN_MKK2 }, +#define F2_5170_5230 AFTER(F1_5170_5230) + + { 5180, 5240, 15, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI }, +#define F1_5180_5240 AFTER(F2_5170_5230) + { 5180, 5240, 17, 6, 20, 20, NO_DFS, PSCAN_FCC }, +#define F2_5180_5240 AFTER(F1_5180_5240) + { 5180, 5240, 18, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI }, +#define F3_5180_5240 AFTER(F2_5180_5240) + { 5180, 5240, 20, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI }, +#define F4_5180_5240 AFTER(F3_5180_5240) + { 5180, 5240, 23, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI }, +#define F5_5180_5240 AFTER(F4_5180_5240) + { 5180, 5240, 23, 6, 20, 20, NO_DFS, PSCAN_FCC }, +#define F6_5180_5240 AFTER(F5_5180_5240) + { 5180, 5240, 17, 6, 20, 10, NO_DFS, PSCAN_FCC }, +#define F7_5180_5240 AFTER(F6_5180_5240) + { 5180, 5240, 17, 6, 20, 5, NO_DFS, PSCAN_FCC }, +#define F8_5180_5240 AFTER(F7_5180_5240) + { 5180, 5320, 20, 6, 20, 20, DFS_ETSI, PSCAN_ETSI }, + +#define F1_5180_5320 AFTER(F8_5180_5240) + { 5240, 5280, 23, 0, 20, 20, DFS_FCC3, PSCAN_FCC | PSCAN_ETSI }, + +#define F1_5240_5280 AFTER(F1_5180_5320) + { 5260, 5280, 23, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC | PSCAN_ETSI }, + +#define F1_5260_5280 AFTER(F1_5240_5280) + { 5260, 5320, 18, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC | PSCAN_ETSI }, + +#define F1_5260_5320 AFTER(F1_5260_5280) + { 5260, 5320, 20, 0, 20, 20, DFS_FCC3 | DFS_ETSI | DFS_MKK4, PSCAN_FCC | PSCAN_ETSI | PSCAN_MKK3 }, +#define F2_5260_5320 AFTER(F1_5260_5320) + + { 5260, 5320, 20, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC }, +#define F3_5260_5320 AFTER(F2_5260_5320) + { 5260, 5320, 23, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC }, +#define F4_5260_5320 AFTER(F3_5260_5320) + { 5260, 5320, 23, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC }, +#define F5_5260_5320 AFTER(F4_5260_5320) + { 5260, 5320, 30, 0, 20, 20, NO_DFS, NO_PSCAN }, +#define F6_5260_5320 AFTER(F5_5260_5320) + { 5260, 5320, 23, 6, 20, 10, DFS_FCC3 | DFS_ETSI, PSCAN_FCC }, +#define F7_5260_5320 AFTER(F6_5260_5320) + { 5260, 5320, 23, 6, 20, 5, DFS_FCC3 | DFS_ETSI, PSCAN_FCC }, +#define F8_5260_5320 AFTER(F7_5260_5320) + + { 5260, 5700, 5, 6, 20, 20, DFS_FCC3 | DFS_ETSI, NO_PSCAN }, +#define F1_5260_5700 AFTER(F8_5260_5320) + { 5260, 5700, 5, 6, 10, 10, DFS_FCC3 | DFS_ETSI, NO_PSCAN }, +#define F2_5260_5700 AFTER(F1_5260_5700) + { 5260, 5700, 5, 6, 5, 5, DFS_FCC3 | DFS_ETSI, NO_PSCAN }, +#define F3_5260_5700 AFTER(F2_5260_5700) + + { 5280, 5320, 17, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC }, +#define F1_5280_5320 AFTER(F3_5260_5700) + + { 5500, 5620, 30, 6, 20, 20, DFS_ETSI, PSCAN_ETSI }, +#define F1_5500_5620 AFTER(F1_5280_5320) + + { 5500, 5700, 20, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC }, +#define F1_5500_5700 AFTER(F1_5500_5620) + { 5500, 5700, 27, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC | PSCAN_ETSI }, +#define F2_5500_5700 AFTER(F1_5500_5700) + { 5500, 5700, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC | PSCAN_ETSI }, +#define F3_5500_5700 AFTER(F2_5500_5700) + { 5500, 5700, 23, 0, 20, 20, DFS_FCC3 | DFS_ETSI | DFS_MKK4, PSCAN_MKK3 | PSCAN_FCC }, +#define F4_5500_5700 AFTER(F3_5500_5700) + + { 5745, 5805, 23, 0, 20, 20, NO_DFS, NO_PSCAN }, +#define F1_5745_5805 AFTER(F4_5500_5700) + { 5745, 5805, 30, 6, 20, 20, NO_DFS, NO_PSCAN }, +#define F2_5745_5805 AFTER(F1_5745_5805) + { 5745, 5805, 30, 6, 20, 20, DFS_ETSI, PSCAN_ETSI }, +#define F3_5745_5805 AFTER(F2_5745_5805) + { 5745, 5825, 5, 6, 20, 20, NO_DFS, NO_PSCAN }, +#define F1_5745_5825 AFTER(F3_5745_5805) + { 5745, 5825, 17, 0, 20, 20, NO_DFS, NO_PSCAN }, +#define F2_5745_5825 AFTER(F1_5745_5825) + { 5745, 5825, 20, 0, 20, 20, NO_DFS, NO_PSCAN }, +#define F3_5745_5825 AFTER(F2_5745_5825) + { 5745, 5825, 30, 0, 20, 20, NO_DFS, NO_PSCAN }, +#define F4_5745_5825 AFTER(F3_5745_5825) + { 5745, 5825, 30, 6, 20, 20, NO_DFS, NO_PSCAN }, +#define F5_5745_5825 AFTER(F4_5745_5825) + { 5745, 5825, 30, 6, 20, 20, NO_DFS, NO_PSCAN }, +#define F6_5745_5825 AFTER(F5_5745_5825) + { 5745, 5825, 5, 6, 10, 10, NO_DFS, NO_PSCAN }, +#define F7_5745_5825 AFTER(F6_5745_5825) + { 5745, 5825, 5, 6, 5, 5, NO_DFS, NO_PSCAN }, +#define F8_5745_5825 AFTER(F7_5745_5825) + { 5745, 5825, 30, 6, 20, 10, NO_DFS, NO_PSCAN }, +#define F9_5745_5825 AFTER(F8_5745_5825) + { 5745, 5825, 30, 6, 20, 5, NO_DFS, NO_PSCAN }, +#define F10_5745_5825 AFTER(F9_5745_5825) + + /* + * Below are the world roaming channels + * All WWR domains have no power limit, instead use the card's CTL + * or max power settings. + */ + { 4920, 4980, 30, 0, 20, 20, NO_DFS, PSCAN_WWR }, +#define W1_4920_4980 AFTER(F10_5745_5825) + { 5040, 5080, 30, 0, 20, 20, NO_DFS, PSCAN_WWR }, +#define W1_5040_5080 AFTER(W1_4920_4980) + { 5170, 5230, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_WWR }, +#define W1_5170_5230 AFTER(W1_5040_5080) + { 5180, 5240, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_WWR }, +#define W1_5180_5240 AFTER(W1_5170_5230) + { 5260, 5320, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_WWR }, +#define W1_5260_5320 AFTER(W1_5180_5240) + { 5745, 5825, 30, 0, 20, 20, NO_DFS, PSCAN_WWR }, +#define W1_5745_5825 AFTER(W1_5260_5320) + { 5500, 5700, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_WWR }, +#define W1_5500_5700 AFTER(W1_5745_5825) + { 5260, 5320, 30, 0, 20, 20, NO_DFS, NO_PSCAN }, +#define W2_5260_5320 AFTER(W1_5500_5700) + { 5180, 5240, 30, 0, 20, 20, NO_DFS, NO_PSCAN }, +#define W2_5180_5240 AFTER(W2_5260_5320) + { 5825, 5825, 30, 0, 20, 20, NO_DFS, PSCAN_WWR }, +#define W2_5825_5825 AFTER(W2_5180_5240) +}; + +/* + * 5GHz Turbo (dynamic & static) tags + */ +static REG_DMN_FREQ_BAND regDmn5GhzTurboFreq[] = { + { 5130, 5210, 5, 6, 40, 40, NO_DFS, NO_PSCAN }, +#define T1_5130_5210 0 + { 5250, 5330, 5, 6, 40, 40, DFS_FCC3, NO_PSCAN }, +#define T1_5250_5330 AFTER(T1_5130_5210) + { 5370, 5490, 5, 6, 40, 40, NO_DFS, NO_PSCAN }, +#define T1_5370_5490 AFTER(T1_5250_5330) + { 5530, 5650, 5, 6, 40, 40, DFS_FCC3, NO_PSCAN }, +#define T1_5530_5650 AFTER(T1_5370_5490) + + { 5150, 5190, 5, 6, 40, 40, NO_DFS, NO_PSCAN }, +#define T1_5150_5190 AFTER(T1_5530_5650) + { 5230, 5310, 5, 6, 40, 40, DFS_FCC3, NO_PSCAN }, +#define T1_5230_5310 AFTER(T1_5150_5190) + { 5350, 5470, 5, 6, 40, 40, NO_DFS, NO_PSCAN }, +#define T1_5350_5470 AFTER(T1_5230_5310) + { 5510, 5670, 5, 6, 40, 40, DFS_FCC3, NO_PSCAN }, +#define T1_5510_5670 AFTER(T1_5350_5470) + + { 5200, 5240, 17, 6, 40, 40, NO_DFS, NO_PSCAN }, +#define T1_5200_5240 AFTER(T1_5510_5670) + { 5200, 5240, 23, 6, 40, 40, NO_DFS, NO_PSCAN }, +#define T2_5200_5240 AFTER(T1_5200_5240) + { 5210, 5210, 17, 6, 40, 40, NO_DFS, NO_PSCAN }, +#define T1_5210_5210 AFTER(T2_5200_5240) + { 5210, 5210, 23, 0, 40, 40, NO_DFS, NO_PSCAN }, +#define T2_5210_5210 AFTER(T1_5210_5210) + + { 5280, 5280, 23, 6, 40, 40, DFS_FCC3, PSCAN_FCC_T }, +#define T1_5280_5280 AFTER(T2_5210_5210) + { 5280, 5280, 20, 6, 40, 40, DFS_FCC3, PSCAN_FCC_T }, +#define T2_5280_5280 AFTER(T1_5280_5280) + { 5250, 5250, 17, 0, 40, 40, DFS_FCC3, PSCAN_FCC_T }, +#define T1_5250_5250 AFTER(T2_5280_5280) + { 5290, 5290, 20, 0, 40, 40, DFS_FCC3, PSCAN_FCC_T }, +#define T1_5290_5290 AFTER(T1_5250_5250) + { 5250, 5290, 20, 0, 40, 40, DFS_FCC3, PSCAN_FCC_T }, +#define T1_5250_5290 AFTER(T1_5290_5290) + { 5250, 5290, 23, 6, 40, 40, DFS_FCC3, PSCAN_FCC_T }, +#define T2_5250_5290 AFTER(T1_5250_5290) + + { 5540, 5660, 20, 6, 40, 40, DFS_FCC3, PSCAN_FCC_T }, +#define T1_5540_5660 AFTER(T2_5250_5290) + { 5760, 5800, 20, 0, 40, 40, NO_DFS, NO_PSCAN }, +#define T1_5760_5800 AFTER(T1_5540_5660) + { 5760, 5800, 30, 6, 40, 40, NO_DFS, NO_PSCAN }, +#define T2_5760_5800 AFTER(T1_5760_5800) + + { 5765, 5805, 30, 6, 40, 40, NO_DFS, NO_PSCAN }, +#define T1_5765_5805 AFTER(T2_5760_5800) + + /* + * Below are the WWR frequencies + */ + { 5210, 5250, 15, 0, 40, 40, DFS_FCC3 | DFS_ETSI, PSCAN_WWR }, +#define WT1_5210_5250 AFTER(T1_5765_5805) + { 5290, 5290, 18, 0, 40, 40, DFS_FCC3 | DFS_ETSI, PSCAN_WWR }, +#define WT1_5290_5290 AFTER(WT1_5210_5250) + { 5540, 5660, 20, 0, 40, 40, DFS_FCC3 | DFS_ETSI, PSCAN_WWR }, +#define WT1_5540_5660 AFTER(WT1_5290_5290) + { 5760, 5800, 20, 0, 40, 40, NO_DFS, PSCAN_WWR }, +#define WT1_5760_5800 AFTER(WT1_5540_5660) +}; + +/* + * 2GHz 11b channel tags + */ +static REG_DMN_FREQ_BAND regDmn2GhzFreq[] = { + { 2312, 2372, 5, 6, 20, 5, NO_DFS, NO_PSCAN }, +#define F1_2312_2372 0 + { 2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN }, +#define F2_2312_2372 AFTER(F1_2312_2372) + + { 2412, 2472, 5, 6, 20, 5, NO_DFS, NO_PSCAN }, +#define F1_2412_2472 AFTER(F2_2312_2372) + { 2412, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA }, +#define F2_2412_2472 AFTER(F1_2412_2472) + { 2412, 2472, 30, 0, 20, 5, NO_DFS, NO_PSCAN }, +#define F3_2412_2472 AFTER(F2_2412_2472) + + { 2412, 2462, 27, 6, 20, 5, NO_DFS, NO_PSCAN }, +#define F1_2412_2462 AFTER(F3_2412_2472) + { 2412, 2462, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA }, +#define F2_2412_2462 AFTER(F1_2412_2462) + + { 2432, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN }, +#define F1_2432_2442 AFTER(F2_2412_2462) + + { 2457, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN }, +#define F1_2457_2472 AFTER(F1_2432_2442) + + { 2467, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA2 | PSCAN_MKKA }, +#define F1_2467_2472 AFTER(F1_2457_2472) + + { 2484, 2484, 5, 6, 20, 5, NO_DFS, NO_PSCAN }, +#define F1_2484_2484 AFTER(F1_2467_2472) + { 2484, 2484, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA | PSCAN_MKKA1 | PSCAN_MKKA2 }, +#define F2_2484_2484 AFTER(F1_2484_2484) + + { 2512, 2732, 5, 6, 20, 5, NO_DFS, NO_PSCAN }, +#define F1_2512_2732 AFTER(F2_2484_2484) + + /* + * WWR have powers opened up to 20dBm. + * Limits should often come from CTL/Max powers + */ + { 2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN }, +#define W1_2312_2372 AFTER(F1_2512_2732) + { 2412, 2412, 20, 0, 20, 5, NO_DFS, NO_PSCAN }, +#define W1_2412_2412 AFTER(W1_2312_2372) + { 2417, 2432, 20, 0, 20, 5, NO_DFS, NO_PSCAN }, +#define W1_2417_2432 AFTER(W1_2412_2412) + { 2437, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN }, +#define W1_2437_2442 AFTER(W1_2417_2432) + { 2447, 2457, 20, 0, 20, 5, NO_DFS, NO_PSCAN }, +#define W1_2447_2457 AFTER(W1_2437_2442) + { 2462, 2462, 20, 0, 20, 5, NO_DFS, NO_PSCAN }, +#define W1_2462_2462 AFTER(W1_2447_2457) + { 2467, 2467, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN }, +#define W1_2467_2467 AFTER(W1_2462_2462) + { 2467, 2467, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN }, +#define W2_2467_2467 AFTER(W1_2467_2467) + { 2472, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN }, +#define W1_2472_2472 AFTER(W2_2467_2467) + { 2472, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN }, +#define W2_2472_2472 AFTER(W1_2472_2472) + { 2484, 2484, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN }, +#define W1_2484_2484 AFTER(W2_2472_2472) + { 2484, 2484, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN }, +#define W2_2484_2484 AFTER(W1_2484_2484) +}; + +/* + * 2GHz 11g channel tags + */ +static REG_DMN_FREQ_BAND regDmn2Ghz11gFreq[] = { + { 2312, 2372, 5, 6, 20, 5, NO_DFS, NO_PSCAN }, +#define G1_2312_2372 0 + { 2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN }, +#define G2_2312_2372 AFTER(G1_2312_2372) + { 2312, 2372, 5, 6, 10, 5, NO_DFS, NO_PSCAN }, +#define G3_2312_2372 AFTER(G2_2312_2372) + { 2312, 2372, 5, 6, 5, 5, NO_DFS, NO_PSCAN }, +#define G4_2312_2372 AFTER(G3_2312_2372) + + { 2412, 2472, 5, 6, 20, 5, NO_DFS, NO_PSCAN }, +#define G1_2412_2472 AFTER(G4_2312_2372) + { 2412, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA_G }, +#define G2_2412_2472 AFTER(G1_2412_2472) + { 2412, 2472, 30, 0, 20, 5, NO_DFS, NO_PSCAN }, +#define G3_2412_2472 AFTER(G2_2412_2472) + { 2412, 2472, 5, 6, 10, 5, NO_DFS, NO_PSCAN }, +#define G4_2412_2472 AFTER(G3_2412_2472) + { 2412, 2472, 5, 6, 5, 5, NO_DFS, NO_PSCAN }, +#define G5_2412_2472 AFTER(G4_2412_2472) + + { 2412, 2462, 27, 6, 20, 5, NO_DFS, NO_PSCAN }, +#define G1_2412_2462 AFTER(G5_2412_2472) + { 2412, 2462, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA_G }, +#define G2_2412_2462 AFTER(G1_2412_2462) + { 2412, 2462, 27, 6, 10, 5, NO_DFS, NO_PSCAN }, +#define G3_2412_2462 AFTER(G2_2412_2462) + { 2412, 2462, 27, 6, 5, 5, NO_DFS, NO_PSCAN }, +#define G4_2412_2462 AFTER(G3_2412_2462) + + { 2432, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN }, +#define G1_2432_2442 AFTER(G4_2412_2462) + + { 2457, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN }, +#define G1_2457_2472 AFTER(G1_2432_2442) + + { 2512, 2732, 5, 6, 20, 5, NO_DFS, NO_PSCAN }, +#define G1_2512_2732 AFTER(G1_2457_2472) + { 2512, 2732, 5, 6, 10, 5, NO_DFS, NO_PSCAN }, +#define G2_2512_2732 AFTER(G1_2512_2732) + { 2512, 2732, 5, 6, 5, 5, NO_DFS, NO_PSCAN }, +#define G3_2512_2732 AFTER(G2_2512_2732) + + { 2467, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA2 | PSCAN_MKKA }, +#define G1_2467_2472 AFTER(G3_2512_2732) + + /* + * WWR open up the power to 20dBm + */ + { 2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN }, +#define WG1_2312_2372 AFTER(G1_2467_2472) + { 2412, 2412, 20, 0, 20, 5, NO_DFS, NO_PSCAN }, +#define WG1_2412_2412 AFTER(WG1_2312_2372) + { 2417, 2432, 20, 0, 20, 5, NO_DFS, NO_PSCAN }, +#define WG1_2417_2432 AFTER(WG1_2412_2412) + { 2437, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN }, +#define WG1_2437_2442 AFTER(WG1_2417_2432) + { 2447, 2457, 20, 0, 20, 5, NO_DFS, NO_PSCAN }, +#define WG1_2447_2457 AFTER(WG1_2437_2442) + { 2462, 2462, 20, 0, 20, 5, NO_DFS, NO_PSCAN }, +#define WG1_2462_2462 AFTER(WG1_2447_2457) + { 2467, 2467, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN }, +#define WG1_2467_2467 AFTER(WG1_2462_2462) + { 2467, 2467, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN }, +#define WG2_2467_2467 AFTER(WG1_2467_2467) + { 2472, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN }, +#define WG1_2472_2472 AFTER(WG2_2467_2467) + { 2472, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN }, +#define WG2_2472_2472 AFTER(WG1_2472_2472) +}; + +/* + * 2GHz Dynamic turbo tags + */ +static REG_DMN_FREQ_BAND regDmn2Ghz11gTurboFreq[] = { + { 2312, 2372, 5, 6, 40, 40, NO_DFS, NO_PSCAN }, +#define T1_2312_2372 0 + { 2437, 2437, 5, 6, 40, 40, NO_DFS, NO_PSCAN }, +#define T1_2437_2437 AFTER(T1_2312_2372) + { 2437, 2437, 20, 6, 40, 40, NO_DFS, NO_PSCAN }, +#define T2_2437_2437 AFTER(T1_2437_2437) + { 2437, 2437, 18, 6, 40, 40, NO_DFS, PSCAN_WWR }, +#define T3_2437_2437 AFTER(T2_2437_2437) + { 2512, 2732, 5, 6, 40, 40, NO_DFS, NO_PSCAN }, +#define T1_2512_2732 AFTER(T3_2437_2437) +}; + +#endif diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_regdomain/ah_rd_regenum.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_regdomain/ah_rd_regenum.h new file mode 100644 index 0000000000..bc569cb00a --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_regdomain/ah_rd_regenum.h @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2005-2011 Atheros Communications, Inc. + * All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ + +#ifndef __AH_REGDOMAIN_REGENUM_H__ +#define __AH_REGDOMAIN_REGENUM_H__ + +/* + * Enumerated Regulatory Domain Information 8 bit values indicate that + * the regdomain is really a pair of unitary regdomains. 12 bit values + * are the real unitary regdomains and are the only ones which have the + * frequency bitmasks and flags set. + */ +enum { + /* + * The following regulatory domain definitions are + * found in the EEPROM. Each regulatory domain + * can operate in either a 5GHz or 2.4GHz wireless mode or + * both 5GHz and 2.4GHz wireless modes. + * In general, the value holds no special + * meaning and is used to decode into either specific + * 2.4GHz or 5GHz wireless mode for that particular + * regulatory domain. + */ + NO_ENUMRD = 0x00, + NULL1_WORLD = 0x03, /* For 11b-only countries (no 11a allowed) */ + NULL1_ETSIB = 0x07, /* Israel */ + NULL1_ETSIC = 0x08, + FCC1_FCCA = 0x10, /* USA */ + FCC1_WORLD = 0x11, /* Hong Kong */ + FCC4_FCCA = 0x12, /* USA - Public Safety */ + FCC5_FCCB = 0x13, /* USA w/ 1/2 and 1/4 width channels */ + FCC6_FCCA = 0x14, /* Canada for AP only */ + + FCC2_FCCA = 0x20, /* Canada */ + FCC2_WORLD = 0x21, /* Australia & HK */ + FCC2_ETSIC = 0x22, + FRANCE_RES = 0x31, /* Legacy France for OEM */ + FCC3_FCCA = 0x3A, /* USA & Canada w/5470 band, 11h, DFS enabled */ + FCC3_WORLD = 0x3B, /* USA & Canada w/5470 band, 11h, DFS enabled */ + + ETSI1_WORLD = 0x37, + ETSI3_ETSIA = 0x32, /* France (optional) */ + ETSI2_WORLD = 0x35, /* Hungary & others */ + ETSI3_WORLD = 0x36, /* France & others */ + ETSI4_WORLD = 0x30, + ETSI4_ETSIC = 0x38, + ETSI5_WORLD = 0x39, + ETSI6_WORLD = 0x34, /* Bulgaria */ + ETSI8_WORLD = 0x3D, /* Russia */ + ETSI9_WORLD = 0x3E, /* Ukraine */ + ETSI_RESERVED = 0x33, /* Reserved (Do not used) */ + + MKK1_MKKA = 0x40, /* Japan (JP1) */ + MKK1_MKKB = 0x41, /* Japan (JP0) */ + APL4_WORLD = 0x42, /* Singapore */ + MKK2_MKKA = 0x43, /* Japan with 4.9G channels */ + APL_RESERVED = 0x44, /* Reserved (Do not used) */ + APL2_WORLD = 0x45, /* Korea */ + APL2_APLC = 0x46, + APL3_WORLD = 0x47, + MKK1_FCCA = 0x48, /* Japan (JP1-1) */ + APL2_APLD = 0x49, /* Korea with 2.3G channels */ + MKK1_MKKA1 = 0x4A, /* Japan (JE1) */ + MKK1_MKKA2 = 0x4B, /* Japan (JE2) */ + MKK1_MKKC = 0x4C, /* Japan (MKK1_MKKA,except Ch14) */ + APL2_FCCA = 0x4D, /* Mobile customer */ + + APL3_FCCA = 0x50, + APL1_WORLD = 0x52, /* Latin America */ + APL1_FCCA = 0x53, + APL1_APLA = 0x54, + APL1_ETSIC = 0x55, + APL2_ETSIC = 0x56, /* Venezuela */ + APL5_WORLD = 0x58, /* Chile */ + APL6_WORLD = 0x5B, /* Singapore */ + APL7_FCCA = 0x5C, /* Taiwan 5.47 Band */ + APL8_WORLD = 0x5D, /* Malaysia 5GHz */ + APL9_WORLD = 0x5E, /* Korea 5GHz; before 11/2007; now APs only */ + APL10_WORLD = 0x5F, /* Korea 5GHz; After 11/2007; STAs only */ + + /* + * World mode SKUs + */ + WOR0_WORLD = 0x60, /* World0 (WO0 SKU) */ + WOR1_WORLD = 0x61, /* World1 (WO1 SKU) */ + WOR2_WORLD = 0x62, /* World2 (WO2 SKU) */ + WOR3_WORLD = 0x63, /* World3 (WO3 SKU) */ + WOR4_WORLD = 0x64, /* World4 (WO4 SKU) */ + WOR5_ETSIC = 0x65, /* World5 (WO5 SKU) */ + + WOR01_WORLD = 0x66, /* World0-1 (WW0-1 SKU) */ + WOR02_WORLD = 0x67, /* World0-2 (WW0-2 SKU) */ + EU1_WORLD = 0x68, /* Same as World0-2 (WW0-2 SKU), except active scan ch1-13. No ch14 */ + + WOR9_WORLD = 0x69, /* World9 (WO9 SKU) */ + WORA_WORLD = 0x6A, /* WorldA (WOA SKU) */ + WORB_WORLD = 0x6B, /* WorldB (WOB SKU) */ + WORC_WORLD = 0x6C, /* WorldC (WOC SKU) */ + + MKK3_MKKB = 0x80, /* Japan UNI-1 even + MKKB */ + MKK3_MKKA2 = 0x81, /* Japan UNI-1 even + MKKA2 */ + MKK3_MKKC = 0x82, /* Japan UNI-1 even + MKKC */ + + MKK4_MKKB = 0x83, /* Japan UNI-1 even + UNI-2 + MKKB */ + MKK4_MKKA2 = 0x84, /* Japan UNI-1 even + UNI-2 + MKKA2 */ + MKK4_MKKC = 0x85, /* Japan UNI-1 even + UNI-2 + MKKC */ + + MKK5_MKKB = 0x86, /* Japan UNI-1 even + UNI-2 + mid-band + MKKB */ + MKK5_MKKA2 = 0x87, /* Japan UNI-1 even + UNI-2 + mid-band + MKKA2 */ + MKK5_MKKC = 0x88, /* Japan UNI-1 even + UNI-2 + mid-band + MKKC */ + + MKK6_MKKB = 0x89, /* Japan UNI-1 even + UNI-1 odd MKKB */ + MKK6_MKKA2 = 0x8A, /* Japan UNI-1 even + UNI-1 odd + MKKA2 */ + MKK6_MKKC = 0x8B, /* Japan UNI-1 even + UNI-1 odd + MKKC */ + + MKK7_MKKB = 0x8C, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKB */ + MKK7_MKKA2 = 0x8D, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKA2 */ + MKK7_MKKC = 0x8E, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKC */ + + MKK8_MKKB = 0x8F, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKB */ + MKK8_MKKA2 = 0x90, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKA2 */ + MKK8_MKKC = 0x91, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKC */ + + MKK14_MKKA1 = 0x92, /* Japan UNI-1 even + UNI-1 odd + 4.9GHz + MKKA1 */ + MKK15_MKKA1 = 0x93, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + 4.9GHz + MKKA1 */ + + MKK10_FCCA = 0xD0, /* Japan UNI-1 even + UNI-2 + 4.9GHz + FCCA */ + MKK10_MKKA1 = 0xD1, /* Japan UNI-1 even + UNI-2 + 4.9GHz + MKKA1 */ + MKK10_MKKC = 0xD2, /* Japan UNI-1 even + UNI-2 + 4.9GHz + MKKC */ + MKK10_MKKA2 = 0xD3, /* Japan UNI-1 even + UNI-2 + 4.9GHz + MKKA2 */ + + MKK11_MKKA = 0xD4, /* Japan UNI-1 even + UNI-2 + mid-band + 4.9GHz + MKKA */ + MKK11_FCCA = 0xD5, /* Japan UNI-1 even + UNI-2 + mid-band + 4.9GHz + FCCA */ + MKK11_MKKA1 = 0xD6, /* Japan UNI-1 even + UNI-2 + mid-band + 4.9GHz + MKKA1 */ + MKK11_MKKC = 0xD7, /* Japan UNI-1 even + UNI-2 + mid-band + 4.9GHz + MKKC */ + MKK11_MKKA2 = 0xD8, /* Japan UNI-1 even + UNI-2 + mid-band + 4.9GHz + MKKA2 */ + + MKK12_MKKA = 0xD9, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + 4.9GHz + MKKA */ + MKK12_FCCA = 0xDA, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + 4.9GHz + FCCA */ + MKK12_MKKA1 = 0xDB, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + 4.9GHz + MKKA1 */ + MKK12_MKKC = 0xDC, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + 4.9GHz + MKKC */ + MKK12_MKKA2 = 0xDD, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + 4.9GHz + MKKA2 */ + + MKK13_MKKB = 0xDE, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKB + All passive + no adhoc */ + + /* + * Following definitions are used only by s/w to map old + * Japan SKUs. + */ + MKK3_MKKA = 0xF0, /* Japan UNI-1 even + MKKA */ + MKK3_MKKA1 = 0xF1, /* Japan UNI-1 even + MKKA1 */ + MKK3_FCCA = 0xF2, /* Japan UNI-1 even + FCCA */ + MKK4_MKKA = 0xF3, /* Japan UNI-1 even + UNI-2 + MKKA */ + MKK4_MKKA1 = 0xF4, /* Japan UNI-1 even + UNI-2 + MKKA1 */ + MKK4_FCCA = 0xF5, /* Japan UNI-1 even + UNI-2 + FCCA */ + MKK9_MKKA = 0xF6, /* Japan UNI-1 even + 4.9GHz */ + MKK10_MKKA = 0xF7, /* Japan UNI-1 even + UNI-2 + 4.9GHz */ + MKK6_MKKA1 = 0xF8, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKA1 */ + MKK6_FCCA = 0xF9, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + FCCA */ + MKK7_MKKA1 = 0xFA, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKA1 */ + MKK7_FCCA = 0xFB, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + FCCA */ + MKK9_FCCA = 0xFC, /* Japan UNI-1 even + 4.9GHz + FCCA */ + MKK9_MKKA1 = 0xFD, /* Japan UNI-1 even + 4.9GHz + MKKA1 */ + MKK9_MKKC = 0xFE, /* Japan UNI-1 even + 4.9GHz + MKKC */ + MKK9_MKKA2 = 0xFF, /* Japan UNI-1 even + 4.9GHz + MKKA2 */ + + /* + * Regulator domains ending in a number (e.g. APL1, + * MK1, ETSI4, etc) apply to 5GHz channel and power + * information. Regulator domains ending in a letter + * (e.g. APLA, FCCA, etc) apply to 2.4GHz channel and + * power information. + */ + APL1 = 0x0150, /* LAT & Asia */ + APL2 = 0x0250, /* LAT & Asia */ + APL3 = 0x0350, /* Taiwan */ + APL4 = 0x0450, /* Jordan */ + APL5 = 0x0550, /* Chile */ + APL6 = 0x0650, /* Singapore */ + APL7 = 0x0750, /* Taiwan, disable ch52 */ + APL8 = 0x0850, /* Malaysia */ + APL9 = 0x0950, /* Korea. Before 11/2007. Now used only by APs */ + APL10 = 0x1050, /* Korea. After 11/2007. For STAs only */ + + ETSI1 = 0x0130, /* Europe & others */ + ETSI2 = 0x0230, /* Europe & others */ + ETSI3 = 0x0330, /* Europe & others */ + ETSI4 = 0x0430, /* Europe & others */ + ETSI5 = 0x0530, /* Europe & others */ + ETSI6 = 0x0630, /* Europe & others */ + ETSI8 = 0x0830, /* Russia */ + ETSI9 = 0x0930, /* Ukraine */ + ETSIA = 0x0A30, /* France */ + ETSIB = 0x0B30, /* Israel */ + ETSIC = 0x0C30, /* Latin America */ + + FCC1 = 0x0110, /* US & others */ + FCC2 = 0x0120, /* Canada, Australia & New Zealand */ + FCC3 = 0x0160, /* US w/new middle band & DFS */ + FCC4 = 0x0165, /* US Public Safety */ + FCC5 = 0x0166, /* US w/ 1/2 and 1/4 width channels */ + FCC6 = 0x0610, /* Canada and Australia */ + FCCA = 0x0A10, + FCCB = 0x0A11, /* US w/ 1/2 and 1/4 width channels */ + + APLD = 0x0D50, /* South Korea */ + + MKK1 = 0x0140, /* Japan (UNI-1 odd)*/ + MKK2 = 0x0240, /* Japan (4.9 GHz + UNI-1 odd) */ + MKK3 = 0x0340, /* Japan (UNI-1 even) */ + MKK4 = 0x0440, /* Japan (UNI-1 even + UNI-2) */ + MKK5 = 0x0540, /* Japan (UNI-1 even + UNI-2 + mid-band) */ + MKK6 = 0x0640, /* Japan (UNI-1 odd + UNI-1 even) */ + MKK7 = 0x0740, /* Japan (UNI-1 odd + UNI-1 even + UNI-2 */ + MKK8 = 0x0840, /* Japan (UNI-1 odd + UNI-1 even + UNI-2 + mid-band) */ + MKK9 = 0x0940, /* Japan (UNI-1 even + 4.9 GHZ) */ + MKK10 = 0x0B40, /* Japan (UNI-1 even + UNI-2 + 4.9 GHZ) */ + MKK11 = 0x1140, /* Japan (UNI-1 even + UNI-2 + 4.9 GHZ) */ + MKK12 = 0x1240, /* Japan (UNI-1 even + UNI-2 + 4.9 GHZ) */ + MKK13 = 0x0C40, /* Same as MKK8 but all passive and no adhoc 11a */ + MKK14 = 0x1440, /* Japan UNI-1 even + UNI-1 odd + 4.9GHz */ + MKK15 = 0x1540, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + 4.9GHz */ + + MKKA = 0x0A40, /* Japan */ + MKKC = 0x0A50, + + NULL1 = 0x0198, + WORLD = 0x0199, + DEBUG_REG_DMN = 0x01ff, +}; + +#endif diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_regdomain/ah_rd_regmap.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_regdomain/ah_rd_regmap.h new file mode 100644 index 0000000000..b1b8edddd3 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_regdomain/ah_rd_regmap.h @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2005-2006 Atheros Communications, Inc. + * All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ + +#ifndef __AH_REGDOMAIN_REGMAP_H__ +#define __AH_REGDOMAIN_REGMAP_H__ + +/* + * THE following table is the mapping of regdomain pairs specified by + * an 8 bit regdomain value to the individual unitary reg domains + */ + +/* regdomain 5ghz 2ghz 5ghz 2ghz pscan mask single */ +/* enum regdomain regdomain flags flags country? */ +static REG_DMN_PAIR_MAPPING regDomainPairs[] = { + {NO_ENUMRD, DEBUG_REG_DMN, DEBUG_REG_DMN, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {NULL1_WORLD, NULL1, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {NULL1_ETSIB, NULL1, ETSIB, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {NULL1_ETSIC, NULL1, ETSIC, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + + {FCC2_FCCA, FCC2, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {FCC2_WORLD, FCC2, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {FCC2_ETSIC, FCC2, ETSIC, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {FCC3_FCCA, FCC3, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {FCC3_WORLD, FCC3, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {FCC4_FCCA, FCC4, FCCA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {FCC5_FCCB, FCC5, FCCB, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + + {ETSI1_WORLD, ETSI1, WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {ETSI2_WORLD, ETSI2, WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {ETSI3_WORLD, ETSI3, WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {ETSI4_WORLD, ETSI4, WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {ETSI5_WORLD, ETSI5, WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {ETSI6_WORLD, ETSI6, WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + + {ETSI3_ETSIA, ETSI3, WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {FRANCE_RES, ETSI3, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + + {FCC1_WORLD, FCC1, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {FCC1_FCCA, FCC1, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {APL1_WORLD, APL1, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {APL2_WORLD, APL2, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {APL3_WORLD, APL3, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {APL4_WORLD, APL4, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {APL5_WORLD, APL5, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {APL6_WORLD, APL6, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {APL8_WORLD, APL8, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {APL9_WORLD, APL9, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + + {APL3_FCCA, APL3, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {APL1_ETSIC, APL1, ETSIC, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {APL2_ETSIC, APL2, ETSIC, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {APL2_APLD, APL2, APLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + + {MKK1_MKKA, MKK1, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKKA, CTRY_JAPAN }, + {MKK1_MKKB, MKK1, MKKA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC| LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN1 }, + {MKK1_FCCA, MKK1, FCCA, DISALLOW_ADHOC_11A_TURB | NEED_NFC| LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1, CTRY_JAPAN2 }, + {MKK1_MKKA1, MKK1, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC| LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN4 }, + {MKK1_MKKA2, MKK1, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC| LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN5 }, + {MKK1_MKKC, MKK1, MKKC, DISALLOW_ADHOC_11A_TURB | NEED_NFC| LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1, CTRY_JAPAN6 }, + + /* MKK2 */ + {MKK2_MKKA, MKK2, MKKA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC| LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK2 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN3 }, + + /* MKK3 */ + {MKK3_MKKA, MKK3, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC , PSCAN_MKKA, CTRY_DEFAULT }, + {MKK3_MKKB, MKK3, MKKA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN7 }, + {MKK3_MKKA1, MKK3, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_DEFAULT }, + {MKK3_MKKA2,MKK3, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN8 }, + {MKK3_MKKC, MKK3, MKKC, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, NO_PSCAN, CTRY_JAPAN9 }, + {MKK3_FCCA, MKK3, FCCA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, NO_PSCAN, CTRY_DEFAULT }, + + /* MKK4 */ + {MKK4_MKKB, MKK4, MKKA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN10 }, + {MKK4_MKKA1, MKK4, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_DEFAULT }, + {MKK4_MKKA2, MKK4, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 |PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN11 }, + {MKK4_MKKC, MKK4, MKKC, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3, CTRY_JAPAN12 }, + {MKK4_FCCA, MKK4, FCCA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3, CTRY_DEFAULT }, + + /* MKK5 */ + {MKK5_MKKB, MKK5, MKKA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN13 }, + {MKK5_MKKA2,MKK5, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN14 }, + {MKK5_MKKC, MKK5, MKKC, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3, CTRY_JAPAN15 }, + + /* MKK6 */ + {MKK6_MKKB, MKK6, MKKA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN16 }, + {MKK6_MKKA2, MKK6, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN17 }, + {MKK6_MKKC, MKK6, MKKC, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1, CTRY_JAPAN18 }, + + /* MKK7 */ + {MKK7_MKKB, MKK7, MKKA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN19 }, + {MKK7_MKKA2, MKK7, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN20 }, + {MKK7_MKKC, MKK7, MKKC, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3, CTRY_JAPAN21 }, + + /* MKK8 */ + {MKK8_MKKB, MKK8, MKKA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN22 }, + {MKK8_MKKA2,MKK8, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN23 }, + {MKK8_MKKC, MKK8, MKKC, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3 , CTRY_JAPAN24 }, + + {MKK9_MKKA, MKK9, MKKA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_DEFAULT }, + {MKK10_MKKA, MKK10, MKKA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_DEFAULT }, + + /* These are super domains */ + {WOR0_WORLD, WOR0_WORLD, WOR0_WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {WOR1_WORLD, WOR1_WORLD, WOR1_WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {WOR2_WORLD, WOR2_WORLD, WOR2_WORLD, DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {WOR3_WORLD, WOR3_WORLD, WOR3_WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {WOR4_WORLD, WOR4_WORLD, WOR4_WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {WOR5_ETSIC, WOR5_ETSIC, WOR5_ETSIC, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {WOR01_WORLD, WOR01_WORLD, WOR01_WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {WOR02_WORLD, WOR02_WORLD, WOR02_WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {EU1_WORLD, EU1_WORLD, EU1_WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {WOR9_WORLD, WOR9_WORLD, WOR9_WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {WORA_WORLD, WORA_WORLD, WORA_WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {WORB_WORLD, WORB_WORLD, WORB_WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, +}; + +#endif diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_soc.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_soc.h index 50fbc62c45..ca75ae9a61 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_soc.h +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ah_soc.h @@ -14,7 +14,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * $Id: ah_soc.h,v 1.4 2008/11/10 04:08:00 sam Exp $ + * $FreeBSD$ */ #ifndef _ATH_AH_SOC_H_ #define _ATH_AH_SOC_H_ diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5210/ar5210.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5210/ar5210.h index 01c1fdcc1f..2471853156 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5210/ar5210.h +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5210/ar5210.h @@ -177,6 +177,8 @@ extern HAL_STATUS ar5210ProcTxDesc(struct ath_hal *, struct ath_desc *, struct ath_tx_status *); extern void ar5210GetTxIntrQueue(struct ath_hal *ah, uint32_t *); extern void ar5210IntrReqTxDesc(struct ath_hal *ah, struct ath_desc *); +extern HAL_BOOL ar5210GetTxCompletionRates(struct ath_hal *ah, + const struct ath_desc *, int *rates, int *tries); extern uint32_t ar5210GetRxDP(struct ath_hal *); extern void ar5210SetRxDP(struct ath_hal *, uint32_t rxdp); @@ -266,6 +268,7 @@ extern void ar5210BeaconInit(struct ath_hal *, uint32_t, uint32_t); extern void ar5210SetStaBeaconTimers(struct ath_hal *, const HAL_BEACON_STATE *); extern void ar5210ResetStaBeaconTimers(struct ath_hal *); +extern uint64_t ar5210GetNextTBTT(struct ath_hal *); extern HAL_BOOL ar5210IsInterruptPending(struct ath_hal *); extern HAL_BOOL ar5210GetPendingInterrupts(struct ath_hal *, HAL_INT *); @@ -275,7 +278,8 @@ extern HAL_INT ar5210SetInterrupts(struct ath_hal *, HAL_INT ints); extern const HAL_RATE_TABLE *ar5210GetRateTable(struct ath_hal *, u_int mode); extern HAL_BOOL ar5210AniControl(struct ath_hal *, HAL_ANI_CMD, int ); -extern void ar5210AniPoll(struct ath_hal *, const HAL_NODE_STATS *, +extern void ar5210AniPoll(struct ath_hal *, const struct ieee80211_channel *); +extern void ar5210RxMonitor(struct ath_hal *, const HAL_NODE_STATS *, const struct ieee80211_channel *); extern void ar5210MibEvent(struct ath_hal *, const HAL_NODE_STATS *); #endif /* _ATH_AR5210_H_ */ diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5210/ar5210_attach.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5210/ar5210_attach.c index 0a470ee69a..79c305511e 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5210/ar5210_attach.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5210/ar5210_attach.c @@ -73,6 +73,7 @@ static const struct ath_hal_private ar5210hal = {{ .ah_procTxDesc = ar5210ProcTxDesc, .ah_getTxIntrQueue = ar5210GetTxIntrQueue, .ah_reqTxIntrDesc = ar5210IntrReqTxDesc, + .ah_getTxCompletionRates = ar5210GetTxCompletionRates, /* RX Functions */ .ah_getRxDP = ar5210GetRxDP, @@ -88,7 +89,8 @@ static const struct ath_hal_private ar5210hal = {{ .ah_setRxFilter = ar5210SetRxFilter, .ah_setupRxDesc = ar5210SetupRxDesc, .ah_procRxDesc = ar5210ProcRxDesc, - .ah_rxMonitor = ar5210AniPoll, + .ah_rxMonitor = ar5210RxMonitor, + .ah_aniPoll = ar5210AniPoll, .ah_procMibEvent = ar5210MibEvent, /* Misc Functions */ @@ -146,6 +148,7 @@ static const struct ath_hal_private ar5210hal = {{ .ah_beaconInit = ar5210BeaconInit, .ah_setStationBeaconTimers = ar5210SetStaBeaconTimers, .ah_resetStationBeaconTimers = ar5210ResetStaBeaconTimers, + .ah_getNextTBTT = ar5210GetNextTBTT, /* Interrupt Functions */ .ah_isInterruptPending = ar5210IsInterruptPending, @@ -169,7 +172,7 @@ static HAL_BOOL ar5210FillCapabilityInfo(struct ath_hal *ah); */ static struct ath_hal * ar5210Attach(uint16_t devid, HAL_SOFTC sc, HAL_BUS_TAG st, HAL_BUS_HANDLE sh, - HAL_STATUS *status) + uint16_t *eepromdata, HAL_STATUS *status) { #define N(a) (sizeof(a)/sizeof(a[0])) struct ath_hal_5210 *ahp; @@ -179,14 +182,14 @@ ar5210Attach(uint16_t devid, HAL_SOFTC sc, HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS ecode; int i; - HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, + HALDEBUG_G(AH_NULL, HAL_DEBUG_ATTACH, "%s: devid 0x%x sc %p st %p sh %p\n", __func__, devid, sc, (void*) st, (void*) sh); /* NB: memory is returned zero'd */ ahp = ath_hal_malloc(sizeof (struct ath_hal_5210)); if (ahp == AH_NULL) { - HALDEBUG(AH_NULL, HAL_DEBUG_ANY, + HALDEBUG_G(AH_NULL, HAL_DEBUG_ANY, "%s: no memory for state block\n", __func__); ecode = HAL_ENOMEM; goto bad; @@ -375,6 +378,9 @@ ar5210FillCapabilityInfo(struct ath_hal *ah) | HAL_INT_FATAL ; + pCap->hal4kbSplitTransSupport = AH_TRUE; + pCap->halHasRxSelfLinkedTail = AH_TRUE; + ahpriv->ah_rxornIsFatal = AH_TRUE; return AH_TRUE; } diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5210/ar5210_beacon.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5210/ar5210_beacon.c index 680e2ded80..e12b039723 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5210/ar5210_beacon.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5210/ar5210_beacon.c @@ -14,7 +14,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * $Id: ar5210_beacon.c,v 1.4 2008/11/10 04:08:02 sam Exp $ + * $FreeBSD$ */ #include "opt_ah.h" @@ -26,6 +26,17 @@ #include "ar5210/ar5210reg.h" #include "ar5210/ar5210desc.h" +/* + * Return the hardware NextTBTT in TSF + */ +uint64_t +ar5210GetNextTBTT(struct ath_hal *ah) +{ +#define TU_TO_TSF(_tu) (((uint64_t)(_tu)) << 10) + return TU_TO_TSF(OS_REG_READ(ah, AR_TIMER0)); +#undef TU_TO_TSF +} + /* * Initialize all of the hardware registers used to send beacons. */ @@ -56,9 +67,9 @@ ar5210BeaconInit(struct ath_hal *ah, if (AH_PRIVATE(ah)->ah_opmode != HAL_M_STA) { bt.bt_nextdba = (next_beacon - - ath_hal_dma_beacon_response_time) << 3; /* 1/8 TU */ + ah->ah_config.ah_dma_beacon_response_time) << 3; /* 1/8 TU */ bt.bt_nextswba = (next_beacon - - ath_hal_sw_beacon_response_time) << 3; /* 1/8 TU */ + ah->ah_config.ah_sw_beacon_response_time) << 3; /* 1/8 TU */ /* * The SWBA interrupt is not used for beacons in ad hoc mode * as we don't yet support ATIMs. So since the beacon never diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5210/ar5210_keycache.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5210/ar5210_keycache.c index 9594ce3d94..87fb06706d 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5210/ar5210_keycache.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5210/ar5210_keycache.c @@ -14,7 +14,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * $Id: ar5210_keycache.c,v 1.4 2008/11/10 04:08:02 sam Exp $ + * $FreeBSD$ */ #include "opt_ah.h" diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5210/ar5210_misc.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5210/ar5210_misc.c index 7339f91c39..1c1573c4df 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5210/ar5210_misc.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5210/ar5210_misc.c @@ -561,11 +561,16 @@ ar5210AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param) } void -ar5210AniPoll(struct ath_hal *ah, const HAL_NODE_STATS *stats, +ar5210RxMonitor(struct ath_hal *ah, const HAL_NODE_STATS *stats, const struct ieee80211_channel *chan) { } +void +ar5210AniPoll(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ +} + void ar5210MibEvent(struct ath_hal *ah, const HAL_NODE_STATS *stats) { diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5210/ar5210_power.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5210/ar5210_power.c index c2771f2735..1c6909b559 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5210/ar5210_power.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5210/ar5210_power.c @@ -14,7 +14,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * $Id: ar5210_power.c,v 1.4 2008/11/10 04:08:02 sam Exp $ + * $FreeBSD$ */ #include "opt_ah.h" diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5210/ar5210_recv.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5210/ar5210_recv.c index 489c55ae28..bdb4d57cad 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5210/ar5210_recv.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5210/ar5210_recv.c @@ -14,7 +14,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * $Id: ar5210_recv.c,v 1.4 2008/11/10 04:08:02 sam Exp $ + * $FreeBSD$ */ #include "opt_ah.h" diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5210/ar5210_reset.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5210/ar5210_reset.c index 43e97ede3b..a798f84c98 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5210/ar5210_reset.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5210/ar5210_reset.c @@ -526,9 +526,10 @@ ar5210PerCalibrationN(struct ath_hal *ah, /* AGC calibration (this was added to make the NF threshold check work) */ OS_REG_WRITE(ah, AR_PHY_AGCCTL, OS_REG_READ(ah, AR_PHY_AGCCTL) | AR_PHY_AGC_CAL); - if (!ath_hal_wait(ah, AR_PHY_AGCCTL, AR_PHY_AGC_CAL, 0)) + if (!ath_hal_wait(ah, AR_PHY_AGCCTL, AR_PHY_AGC_CAL, 0)) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: AGC calibration timeout\n", __func__); + } /* Rewrite our AGC values we stored off earlier (return AGC to normal operation) */ OS_REG_WRITE(ah, 0x9858, reg9858); diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5210/ar5210_xmit.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5210/ar5210_xmit.c index 63cd9fd1a5..f7c6030681 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5210/ar5210_xmit.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5210/ar5210_xmit.c @@ -621,3 +621,12 @@ ar5210GetTxIntrQueue(struct ath_hal *ah, uint32_t *txqs) { return; } + +/* + * Retrieve the rate table from the given TX completion descriptor + */ +HAL_BOOL +ar5210GetTxCompletionRates(struct ath_hal *ah, const struct ath_desc *ds0, int *rates, int *tries) +{ + return AH_FALSE; +} diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5210/ar5210desc.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5210/ar5210desc.h index d7d382ccfa..5634480b80 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5210/ar5210desc.h +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5210/ar5210desc.h @@ -14,7 +14,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * $Id: ar5210desc.h,v 1.5 2008/11/10 04:08:02 sam Exp $ + * $FreeBSD$ */ #ifndef _DEV_ATH_AR5210DESC_H #define _DEV_ATH_AR5210DESC_H diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5210/ar5210phy.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5210/ar5210phy.h index 6211613d8e..4ab3025d95 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5210/ar5210phy.h +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5210/ar5210phy.h @@ -14,7 +14,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * $Id: ar5210phy.h,v 1.4 2008/11/10 01:19:37 sam Exp $ + * $FreeBSD$ */ #ifndef _DEV_ATH_AR5210PHY_H #define _DEV_ATH_AR5210PHY_H diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5210/ar5210reg.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5210/ar5210reg.h index dc49fcdd1d..894d9bbd85 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5210/ar5210reg.h +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5210/ar5210reg.h @@ -14,7 +14,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * $Id: ar5210reg.h,v 1.4 2008/11/10 01:19:37 sam Exp $ + * $FreeBSD$ */ #ifndef _DEV_ATH_AR5210REG_H #define _DEV_ATH_AR5210REG_H diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5210/ar5k_0007.ini b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5210/ar5k_0007.ini index b0285e9223..b536483b2c 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5210/ar5k_0007.ini +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5210/ar5k_0007.ini @@ -14,7 +14,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * $Id: ar5k_0007.ini,v 1.2 2008/11/10 01:19:37 sam Exp $ + * $FreeBSD$ */ /* crete register init */ diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5211/ar5211.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5211/ar5211.h index 223f95446e..51acd38862 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5211/ar5211.h +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5211/ar5211.h @@ -202,6 +202,8 @@ extern HAL_STATUS ar5211ProcTxDesc(struct ath_hal *, struct ath_desc *, struct ath_tx_status *); extern void ar5211GetTxIntrQueue(struct ath_hal *ah, uint32_t *); extern void ar5211IntrReqTxDesc(struct ath_hal *ah, struct ath_desc *); +extern HAL_BOOL ar5211GetTxCompletionRates(struct ath_hal *ah, + const struct ath_desc *ds0, int *rates, int *tries); extern uint32_t ar5211GetRxDP(struct ath_hal *); extern void ar5211SetRxDP(struct ath_hal *, uint32_t rxdp); @@ -294,6 +296,7 @@ extern void ar5211BeaconInit(struct ath_hal *, uint32_t, uint32_t); extern void ar5211SetStaBeaconTimers(struct ath_hal *, const HAL_BEACON_STATE *); extern void ar5211ResetStaBeaconTimers(struct ath_hal *); +extern uint64_t ar5211GetNextTBTT(struct ath_hal *); extern HAL_BOOL ar5211IsInterruptPending(struct ath_hal *); extern HAL_BOOL ar5211GetPendingInterrupts(struct ath_hal *, HAL_INT *); @@ -303,7 +306,8 @@ extern HAL_INT ar5211SetInterrupts(struct ath_hal *, HAL_INT ints); extern const HAL_RATE_TABLE *ar5211GetRateTable(struct ath_hal *, u_int mode); extern HAL_BOOL ar5211AniControl(struct ath_hal *, HAL_ANI_CMD, int ); -extern void ar5211AniPoll(struct ath_hal *, const HAL_NODE_STATS *, +extern void ar5211RxMonitor(struct ath_hal *, const HAL_NODE_STATS *, const struct ieee80211_channel *); +extern void ar5211AniPoll(struct ath_hal *, const struct ieee80211_channel *); extern void ar5211MibEvent(struct ath_hal *, const HAL_NODE_STATS *); #endif /* _ATH_AR5211_H_ */ diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5211/ar5211_attach.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5211/ar5211_attach.c index ec19751769..a0c42b2bf7 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5211/ar5211_attach.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5211/ar5211_attach.c @@ -73,6 +73,7 @@ static const struct ath_hal_private ar5211hal = {{ .ah_procTxDesc = ar5211ProcTxDesc, .ah_getTxIntrQueue = ar5211GetTxIntrQueue, .ah_reqTxIntrDesc = ar5211IntrReqTxDesc, + .ah_getTxCompletionRates = ar5211GetTxCompletionRates, /* RX Functions */ .ah_getRxDP = ar5211GetRxDP, @@ -88,7 +89,8 @@ static const struct ath_hal_private ar5211hal = {{ .ah_setRxFilter = ar5211SetRxFilter, .ah_setupRxDesc = ar5211SetupRxDesc, .ah_procRxDesc = ar5211ProcRxDesc, - .ah_rxMonitor = ar5211AniPoll, + .ah_rxMonitor = ar5211RxMonitor, + .ah_aniPoll = ar5211AniPoll, .ah_procMibEvent = ar5211MibEvent, /* Misc Functions */ @@ -146,6 +148,7 @@ static const struct ath_hal_private ar5211hal = {{ .ah_beaconInit = ar5211BeaconInit, .ah_setStationBeaconTimers = ar5211SetStaBeaconTimers, .ah_resetStationBeaconTimers = ar5211ResetStaBeaconTimers, + .ah_getNextTBTT = ar5211GetNextTBTT, /* Interrupt Functions */ .ah_isInterruptPending = ar5211IsInterruptPending, @@ -188,7 +191,8 @@ ar5211GetRadioRev(struct ath_hal *ah) */ static struct ath_hal * ar5211Attach(uint16_t devid, HAL_SOFTC sc, - HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status) + HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata, + HAL_STATUS *status) { #define N(a) (sizeof(a)/sizeof(a[0])) struct ath_hal_5211 *ahp; @@ -197,13 +201,13 @@ ar5211Attach(uint16_t devid, HAL_SOFTC sc, uint16_t eeval; HAL_STATUS ecode; - HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", + HALDEBUG_G(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", __func__, sc, (void*) st, (void*) sh); /* NB: memory is returned zero'd */ ahp = ath_hal_malloc(sizeof (struct ath_hal_5211)); if (ahp == AH_NULL) { - HALDEBUG(AH_NULL, HAL_DEBUG_ANY, + HALDEBUG_G(AH_NULL, HAL_DEBUG_ANY, "%s: cannot allocate memory for state block\n", __func__); ecode = HAL_ENOMEM; goto bad; @@ -506,6 +510,9 @@ ar5211FillCapabilityInfo(struct ath_hal *ah) | HAL_INT_TIM ; + pCap->hal4kbSplitTransSupport = AH_TRUE; + pCap->halHasRxSelfLinkedTail = AH_TRUE; + /* XXX might be ok w/ some chip revs */ ahpriv->ah_rxornIsFatal = AH_TRUE; return AH_TRUE; diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5211/ar5211_beacon.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5211/ar5211_beacon.c index 74207a322a..b2775d0376 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5211/ar5211_beacon.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5211/ar5211_beacon.c @@ -14,7 +14,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * $Id: ar5211_beacon.c,v 1.4 2008/11/10 04:08:02 sam Exp $ + * $FreeBSD$ */ #include "opt_ah.h" @@ -29,6 +29,17 @@ * Routines used to initialize and generated beacons for the AR5211/AR5311. */ +/* + * Return the hardware NextTBTT in TSF + */ +uint64_t +ar5211GetNextTBTT(struct ath_hal *ah) +{ +#define TU_TO_TSF(_tu) (((uint64_t)(_tu)) << 10) + return TU_TO_TSF(OS_REG_READ(ah, AR_TIMER0)); +#undef TU_TO_TSF +} + /* * Initialize all of the hardware registers used to send beacons. */ @@ -71,9 +82,9 @@ ar5211BeaconInit(struct ath_hal *ah, case HAL_M_IBSS: case HAL_M_HOSTAP: bt.bt_nextdba = (next_beacon - - ath_hal_dma_beacon_response_time) << 3; /* 1/8 TU */ + ah->ah_config.ah_dma_beacon_response_time) << 3; /* 1/8 TU */ bt.bt_nextswba = (next_beacon - - ath_hal_sw_beacon_response_time) << 3; /* 1/8 TU */ + ah->ah_config.ah_sw_beacon_response_time) << 3; /* 1/8 TU */ break; } /* diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5211/ar5211_keycache.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5211/ar5211_keycache.c index 61f579a452..3e0f922a4f 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5211/ar5211_keycache.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5211/ar5211_keycache.c @@ -14,7 +14,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * $Id: ar5211_keycache.c,v 1.4 2008/11/10 04:08:02 sam Exp $ + * $FreeBSD$ */ #include "opt_ah.h" diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5211/ar5211_misc.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5211/ar5211_misc.c index 33b9e21682..3b27062294 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5211/ar5211_misc.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5211/ar5211_misc.c @@ -564,7 +564,12 @@ ar5211AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param) } void -ar5211AniPoll(struct ath_hal *ah, const HAL_NODE_STATS *stats, +ar5211AniPoll(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ +} + +void +ar5211RxMonitor(struct ath_hal *ah, const HAL_NODE_STATS *stats, const struct ieee80211_channel *chan) { } diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5211/ar5211_power.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5211/ar5211_power.c index bcfcf7cccf..776cfb32b5 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5211/ar5211_power.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5211/ar5211_power.c @@ -14,7 +14,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * $Id: ar5211_power.c,v 1.4 2008/11/10 04:08:02 sam Exp $ + * $FreeBSD$ */ #include "opt_ah.h" diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5211/ar5211_recv.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5211/ar5211_recv.c index c5b0e183e3..733559e7a5 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5211/ar5211_recv.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5211/ar5211_recv.c @@ -14,7 +14,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * $Id: ar5211_recv.c,v 1.4 2008/11/10 04:08:02 sam Exp $ + * $FreeBSD$ */ #include "opt_ah.h" diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5211/ar5211_reset.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5211/ar5211_reset.c index 438bf5c8d7..d2501811a1 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5211/ar5211_reset.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5211/ar5211_reset.c @@ -46,7 +46,7 @@ typedef struct { } CHAN_INFO_2GHZ; #define CI_2GHZ_INDEX_CORRECTION 19 -const static CHAN_INFO_2GHZ chan2GHzData[] = { +static const CHAN_INFO_2GHZ chan2GHzData[] = { { 1, 0x46, 96 }, /* 2312 -19 */ { 1, 0x46, 97 }, /* 2317 -18 */ { 1, 0x46, 98 }, /* 2322 -17 */ @@ -926,9 +926,10 @@ ar5211IsNfGood(struct ath_hal *ah, struct ieee80211_channel *chan) if (!getNoiseFloorThresh(ah, chan, &nfThresh)) return AH_FALSE; - if (OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) + if (OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: NF did not complete in calibration window\n", __func__); + } nf = ar5211GetNoiseFloor(ah); if (nf > nfThresh) { HALDEBUG(ah, HAL_DEBUG_ANY, diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5211/ar5211_xmit.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5211/ar5211_xmit.c index 5d70564506..e1e7f73bf2 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5211/ar5211_xmit.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5211/ar5211_xmit.c @@ -345,8 +345,9 @@ ar5211ResetTxQueue(struct ath_hal *ah, u_int q) | AR_Q_MISC_CBR_INCR_DIS0 | AR_Q_MISC_RDYTIME_EXP_POLICY); value = (ahp->ah_beaconInterval - - (ath_hal_sw_beacon_response_time - ath_hal_dma_beacon_response_time) - - ath_hal_additional_swba_backoff) * 1024; + - (ah->ah_config.ah_sw_beacon_response_time + - ah->ah_config.ah_dma_beacon_response_time) + - ah->ah_config.ah_additional_swba_backoff) * 1024; OS_REG_WRITE(ah, AR_QRDYTIMECFG(q), value | AR_Q_RDYTIMECFG_EN); /* Configure DCU for CAB */ @@ -660,3 +661,13 @@ ar5211GetTxIntrQueue(struct ath_hal *ah, uint32_t *txqs) { return; } + +/* + * Retrieve the rate table from the given TX completion descriptor + */ +HAL_BOOL +ar5211GetTxCompletionRates(struct ath_hal *ah, const struct ath_desc *ds0, int *rates, int *tries) +{ + return AH_FALSE; +} + diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5211/ar5211desc.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5211/ar5211desc.h index 9fa6e29cf0..4528447dee 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5211/ar5211desc.h +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5211/ar5211desc.h @@ -14,7 +14,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * $Id: ar5211desc.h,v 1.5 2008/11/10 04:08:03 sam Exp $ + * $FreeBSD$ */ #ifndef _DEV_ATH_AR5211DESC_H #define _DEV_ATH_AR5211DESC_H diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5211/ar5211phy.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5211/ar5211phy.h index 8bd7051188..bf5b67e51a 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5211/ar5211phy.h +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5211/ar5211phy.h @@ -14,7 +14,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * $Id: ar5211phy.h,v 1.4 2008/11/10 01:19:38 sam Exp $ + * $FreeBSD$ */ #ifndef _DEV_ATH_AR5211PHY_H #define _DEV_ATH_AR5211PHY_H diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5211/ar5211reg.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5211/ar5211reg.h index babd565aad..647f20db45 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5211/ar5211reg.h +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5211/ar5211reg.h @@ -14,7 +14,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * $Id: ar5211reg.h,v 1.4 2008/11/10 01:19:38 sam Exp $ + * $FreeBSD$ */ #ifndef _DEV_ATH_AR5211REG_H #define _DEV_ATH_AR5211REG_H diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5211/boss.ini b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5211/boss.ini index a041c440ab..e054436d74 100755 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5211/boss.ini +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5211/boss.ini @@ -14,7 +14,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * $Id: boss.ini,v 1.3 2008/11/10 04:08:03 sam Exp $ + * $FreeBSD$ */ /* Auto Generated PCI Register Writes. Created: 09/12/02 */ diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5112.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5112.c index c1920b935f..10030682a2 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5112.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5112.c @@ -611,7 +611,7 @@ getFullPwrTable(uint16_t numPcdacs, uint16_t *pcdacs, int16_t *power, int16_t ma uint16_t idxR = 1; if (numPcdacs < 2) { - HALDEBUG(AH_NULL, HAL_DEBUG_ANY, + HALDEBUG_G(AH_NULL, HAL_DEBUG_ANY, "%s: at least 2 pcdac values needed [%d]\n", __func__, numPcdacs); return AH_FALSE; diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5212.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5212.h index ddd8420df4..40e718e467 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5212.h +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5212.h @@ -143,7 +143,7 @@ typedef struct RfHalFuncs { int16_t *minPower, int16_t *maxPower, const struct ieee80211_channel *, uint16_t *rfXpdGain); HAL_BOOL (*getChannelMaxMinPower)(struct ath_hal *ah, - const struct ieee80211_channel *, + const const struct ieee80211_channel *, int16_t *maxPow, int16_t *minPow); int16_t (*getNfAdjust)(struct ath_hal *, const HAL_CHANNEL_INTERNAL*); } RF_HAL_FUNCS; @@ -320,13 +320,19 @@ struct ath_hal_5212 { struct ar5212AniState *ah_curani; /* cached last reference */ struct ar5212AniState ah_ani[AH_MAXCHAN]; /* per-channel state */ + /* AR5416 uses some of the AR5212 ANI code; these are the ANI methods */ + HAL_BOOL (*ah_aniControl) (struct ath_hal *, HAL_ANI_CMD cmd, int param); + /* * Transmit power state. Note these are maintained * here so they can be retrieved by diagnostic tools. */ uint16_t *ah_pcdacTable; u_int ah_pcdacTableSize; - uint16_t ah_ratesArray[16]; + uint16_t ah_ratesArray[37]; + + uint8_t ah_txTrigLev; /* current Tx trigger level */ + uint8_t ah_maxTxTrigLev; /* max tx trigger level */ }; #define AH5212(_ah) ((struct ath_hal_5212 *)(_ah)) @@ -424,6 +430,7 @@ extern void ar5212BeaconInit(struct ath_hal *ah, extern void ar5212ResetStaBeaconTimers(struct ath_hal *ah); extern void ar5212SetStaBeaconTimers(struct ath_hal *ah, const HAL_BEACON_STATE *); +extern uint64_t ar5212GetNextTBTT(struct ath_hal *); extern HAL_BOOL ar5212IsInterruptPending(struct ath_hal *ah); extern HAL_BOOL ar5212GetPendingInterrupts(struct ath_hal *ah, HAL_INT *); @@ -459,6 +466,7 @@ extern void ar5212WriteAssocid(struct ath_hal *ah, const uint8_t *bssid, uint16_t assocId); extern uint32_t ar5212GetTsf32(struct ath_hal *ah); extern uint64_t ar5212GetTsf64(struct ath_hal *ah); +extern void ar5212SetTsf64(struct ath_hal *ah, uint64_t tsf64); extern void ar5212ResetTsf(struct ath_hal *ah); extern void ar5212SetBasicRate(struct ath_hal *ah, HAL_RATE_SET *pSet); extern uint32_t ar5212GetRandomSeed(struct ath_hal *ah); @@ -499,6 +507,8 @@ extern HAL_BOOL ar5212SetCapability(struct ath_hal *, HAL_CAPABILITY_TYPE, extern HAL_BOOL ar5212GetDiagState(struct ath_hal *ah, int request, const void *args, uint32_t argsize, void **result, uint32_t *resultsize); +extern HAL_STATUS ar5212SetQuiet(struct ath_hal *ah, uint32_t period, + uint32_t duration, uint32_t nextStart, HAL_QUIET_FLAG flag); extern HAL_BOOL ar5212SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode, int setChip); @@ -586,6 +596,8 @@ extern HAL_STATUS ar5212ProcTxDesc(struct ath_hal *ah, struct ath_desc *, struct ath_tx_status *); extern void ar5212GetTxIntrQueue(struct ath_hal *ah, uint32_t *); extern void ar5212IntrReqTxDesc(struct ath_hal *ah, struct ath_desc *); +extern HAL_BOOL ar5212GetTxCompletionRates(struct ath_hal *ah, + const struct ath_desc *ds0, int *rates, int *tries); extern const HAL_RATE_TABLE *ar5212GetRateTable(struct ath_hal *, u_int mode); @@ -601,8 +613,19 @@ struct ath_rx_status; extern void ar5212AniPhyErrReport(struct ath_hal *ah, const struct ath_rx_status *rs); extern void ar5212ProcessMibIntr(struct ath_hal *, const HAL_NODE_STATS *); -extern void ar5212AniPoll(struct ath_hal *, const HAL_NODE_STATS *, +extern void ar5212RxMonitor(struct ath_hal *, const HAL_NODE_STATS *, const struct ieee80211_channel *); +extern void ar5212AniPoll(struct ath_hal *, const struct ieee80211_channel *); extern void ar5212AniReset(struct ath_hal *, const struct ieee80211_channel *, HAL_OPMODE, int); + +extern HAL_BOOL ar5212IsNFCalInProgress(struct ath_hal *ah); +extern HAL_BOOL ar5212WaitNFCalComplete(struct ath_hal *ah, int i); +extern void ar5212EnableDfs(struct ath_hal *ah, HAL_PHYERR_PARAM *pe); +extern void ar5212GetDfsThresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe); +extern HAL_BOOL ar5212ProcessRadarEvent(struct ath_hal *ah, + struct ath_rx_status *rxs, uint64_t fulltsf, const char *buf, + HAL_DFS_EVENT *event); +extern HAL_BOOL ar5212IsFastClockEnabled(struct ath_hal *ah); + #endif /* _ATH_AR5212_H_ */ diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5212.ini b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5212.ini index d53dbe2e97..608f91f375 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5212.ini +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5212.ini @@ -14,7 +14,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * $Id: ar5212.ini,v 1.3 2008/11/10 04:08:03 sam Exp $ + * $FreeBSD$ */ /* Auto Generated PCI Register Writes. Created: 09/01/04 */ diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5212_ani.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5212_ani.c index 40b4879e1e..b101306a63 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5212_ani.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5212_ani.c @@ -222,7 +222,14 @@ ar5212AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param) typedef int TABLE[]; struct ath_hal_5212 *ahp = AH5212(ah); struct ar5212AniState *aniState = ahp->ah_curani; - const struct ar5212AniParams *params = aniState->params; + const struct ar5212AniParams *params = AH_NULL; + + /* + * This function may be called before there's a current + * channel (eg to disable ANI.) + */ + if (aniState != AH_NULL) + params = aniState->params; OS_MARK(ah, AH_MARK_ANI_CONTROL, cmd); @@ -343,8 +350,8 @@ ar5212AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param) ahp->ah_procPhyErr &= ~HAL_ANI_ENA; /* Turn off HW counters if we have them */ ar5212AniDetach(ah); - ar5212SetRxFilter(ah, - ar5212GetRxFilter(ah) &~ HAL_RX_FILTER_PHYERR); + ah->ah_setRxFilter(ah, + ah->ah_getRxFilter(ah) &~ HAL_RX_FILTER_PHYERR); } else { /* normal/auto mode */ /* don't mess with state if already enabled */ if (ahp->ah_procPhyErr & HAL_ANI_ENA) @@ -358,8 +365,8 @@ ar5212AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param) ahp->ah_curani->params: &ahp->ah_aniParams24 /*XXX*/); } else { - ar5212SetRxFilter(ah, - ar5212GetRxFilter(ah) | HAL_RX_FILTER_PHYERR); + ah->ah_setRxFilter(ah, + ah->ah_getRxFilter(ah) | HAL_RX_FILTER_PHYERR); } ahp->ah_procPhyErr |= HAL_ANI_ENA; } @@ -609,8 +616,20 @@ ar5212AniReset(struct ath_hal *ah, const struct ieee80211_channel *chan, /* * Turn off PHY error frame delivery while we futz with settings. */ - rxfilter = ar5212GetRxFilter(ah); - ar5212SetRxFilter(ah, rxfilter &~ HAL_RX_FILTER_PHYERR); + rxfilter = ah->ah_getRxFilter(ah); + ah->ah_setRxFilter(ah, rxfilter &~ HAL_RX_FILTER_PHYERR); + + /* + * If ANI is disabled at this point, don't set the default + * ANI parameter settings - leave the HAL settings there. + * This is (currently) needed for reliable radar detection. + */ + if (! ANI_ENA(ah)) { + HALDEBUG(ah, HAL_DEBUG_ANI, "%s: ANI disabled\n", + __func__); + goto finish; + } + /* * Automatic processing is done only in station mode right now. */ @@ -644,10 +663,15 @@ ar5212AniReset(struct ath_hal *ah, const struct ieee80211_channel *chan, ar5212AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, 0); ichan->privFlags |= CHANNEL_ANI_SETUP; } + /* + * In case the counters haven't yet been setup; set them up. + */ + enableAniMIBCounters(ah, ahp->ah_curani->params); ar5212AniRestart(ah, aniState); +finish: /* restore RX filter mask */ - ar5212SetRxFilter(ah, rxfilter); + ah->ah_setRxFilter(ah, rxfilter); } /* @@ -912,21 +936,26 @@ updateMIBStats(struct ath_hal *ah, struct ar5212AniState *aniState) aniState->cckPhyErrCount = cckPhyErrCnt; } +void +ar5212RxMonitor(struct ath_hal *ah, const HAL_NODE_STATS *stats, + const struct ieee80211_channel *chan) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + ahp->ah_stats.ast_nodestats.ns_avgbrssi = stats->ns_avgbrssi; +} + /* * Do periodic processing. This routine is called from the * driver's rx interrupt handler after processing frames. */ void -ar5212AniPoll(struct ath_hal *ah, const HAL_NODE_STATS *stats, - const struct ieee80211_channel *chan) +ar5212AniPoll(struct ath_hal *ah, const struct ieee80211_channel *chan) { struct ath_hal_5212 *ahp = AH5212(ah); struct ar5212AniState *aniState = ahp->ah_curani; const struct ar5212AniParams *params; int32_t listenTime; - ahp->ah_stats.ast_nodestats.ns_avgbrssi = stats->ns_avgbrssi; - /* XXX can aniState be null? */ if (aniState == AH_NULL) return; diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5212_attach.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5212_attach.c index ace6989747..eaceaba766 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5212_attach.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5212_attach.c @@ -69,6 +69,7 @@ static const struct ath_hal_private ar5212hal = {{ .ah_procTxDesc = ar5212ProcTxDesc, .ah_getTxIntrQueue = ar5212GetTxIntrQueue, .ah_reqTxIntrDesc = ar5212IntrReqTxDesc, + .ah_getTxCompletionRates = ar5212GetTxCompletionRates, /* RX Functions */ .ah_getRxDP = ar5212GetRxDP, @@ -84,7 +85,8 @@ static const struct ath_hal_private ar5212hal = {{ .ah_setRxFilter = ar5212SetRxFilter, .ah_setupRxDesc = ar5212SetupRxDesc, .ah_procRxDesc = ar5212ProcRxDesc, - .ah_rxMonitor = ar5212AniPoll, + .ah_rxMonitor = ar5212RxMonitor, + .ah_aniPoll = ar5212AniPoll, .ah_procMibEvent = ar5212ProcessMibIntr, /* Misc Functions */ @@ -125,6 +127,13 @@ static const struct ath_hal_private ar5212hal = {{ .ah_getCTSTimeout = ar5212GetCTSTimeout, .ah_setDecompMask = ar5212SetDecompMask, .ah_setCoverageClass = ar5212SetCoverageClass, + .ah_setQuiet = ar5212SetQuiet, + + /* DFS Functions */ + .ah_enableDfs = ar5212EnableDfs, + .ah_getDfsThresh = ar5212GetDfsThresh, + .ah_procRadarEvent = ar5212ProcessRadarEvent, + .ah_isFastClockEnabled = ar5212IsFastClockEnabled, /* Key Cache Functions */ .ah_getKeyCacheSize = ar5212GetKeyCacheSize, @@ -142,6 +151,7 @@ static const struct ath_hal_private ar5212hal = {{ .ah_beaconInit = ar5212BeaconInit, .ah_setStationBeaconTimers = ar5212SetStaBeaconTimers, .ah_resetStationBeaconTimers = ar5212ResetStaBeaconTimers, + .ah_getNextTBTT = ar5212GetNextTBTT, /* Interrupt Functions */ .ah_isInterruptPending = ar5212IsInterruptPending, @@ -201,6 +211,9 @@ ar5212AniSetup(struct ath_hal *ah) ar5212AniAttach(ah, &tmp, &tmp, AH_TRUE); } else ar5212AniAttach(ah, &aniparams, &aniparams, AH_TRUE); + + /* Set overridable ANI methods */ + AH5212(ah)->ah_aniControl = ar5212AniControl; } /* @@ -248,6 +261,9 @@ ar5212InitState(struct ath_hal_5212 *ahp, uint16_t devid, HAL_SOFTC sc, ahp->ah_acktimeout = (u_int) -1; ahp->ah_ctstimeout = (u_int) -1; ahp->ah_sifstime = (u_int) -1; + ahp->ah_txTrigLev = INIT_TX_FIFO_THRESHOLD, + ahp->ah_maxTxTrigLev = MAX_TX_FIFO_THRESHOLD, + OS_MEMCPY(&ahp->ah_bssidmask, defbssidmask, IEEE80211_ADDR_LEN); #undef N } @@ -291,7 +307,8 @@ ar5212IsMacSupported(uint8_t macVersion, uint8_t macRev) */ static struct ath_hal * ar5212Attach(uint16_t devid, HAL_SOFTC sc, - HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status) + HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata, + HAL_STATUS *status) { #define AH_EEPROM_PROTECT(ah) \ (AH_PRIVATE(ah)->ah_ispcie)? AR_EEPROM_PROTECT_PCIE : AR_EEPROM_PROTECT) @@ -302,13 +319,13 @@ ar5212Attach(uint16_t devid, HAL_SOFTC sc, uint16_t eeval; HAL_STATUS ecode; - HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", + HALDEBUG_G(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", __func__, sc, (void*) st, (void*) sh); /* NB: memory is returned zero'd */ ahp = ath_hal_malloc(sizeof (struct ath_hal_5212)); if (ahp == AH_NULL) { - HALDEBUG(AH_NULL, HAL_DEBUG_ANY, + HALDEBUG_G(AH_NULL, HAL_DEBUG_ANY, "%s: cannot allocate memory for state block\n", __func__); *status = HAL_ENOMEM; return AH_NULL; @@ -854,6 +871,9 @@ ar5212FillCapabilityInfo(struct ath_hal *ah) if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_GRIFFIN) pCap->halIntrMask &= ~HAL_INT_TBTT; + pCap->hal4kbSplitTransSupport = AH_TRUE; + pCap->halHasRxSelfLinkedTail = AH_TRUE; + return AH_TRUE; #undef IS_COBRA #undef IS_GRIFFIN_LITE diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5212_beacon.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5212_beacon.c index 2dbc0cb2c6..1b4b342bc4 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5212_beacon.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5212_beacon.c @@ -14,7 +14,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * $Id: ar5212_beacon.c,v 1.6 2008/11/10 04:08:03 sam Exp $ + * $FreeBSD$ */ #include "opt_ah.h" @@ -25,6 +25,17 @@ #include "ar5212/ar5212reg.h" #include "ar5212/ar5212desc.h" +/* + * Return the hardware NextTBTT in TSF + */ +uint64_t +ar5212GetNextTBTT(struct ath_hal *ah) +{ +#define TU_TO_TSF(_tu) (((uint64_t)(_tu)) << 10) + return TU_TO_TSF(OS_REG_READ(ah, AR_TIMER0)); +#undef TU_TO_TSF +} + /* * Initialize all of the hardware registers used to * send beacons. Note that for station operation the @@ -84,9 +95,9 @@ ar5212BeaconInit(struct ath_hal *ah, case HAL_M_HOSTAP: case HAL_M_IBSS: bt.bt_nextdba = (next_beacon - - ath_hal_dma_beacon_response_time) << 3; /* 1/8 TU */ + ah->ah_config.ah_dma_beacon_response_time) << 3; /* 1/8 TU */ bt.bt_nextswba = (next_beacon - - ath_hal_sw_beacon_response_time) << 3; /* 1/8 TU */ + ah->ah_config.ah_sw_beacon_response_time) << 3; /* 1/8 TU */ break; } /* diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5212_eeprom.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5212_eeprom.c index d2999fda48..f4b67715b4 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5212_eeprom.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5212_eeprom.c @@ -14,7 +14,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * $Id: ar5212_eeprom.c,v 1.6 2008/11/10 04:08:03 sam Exp $ + * $FreeBSD$ */ #include "opt_ah.h" diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5212_keycache.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5212_keycache.c index a1f2dbbf97..bf7db4942b 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5212_keycache.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5212_keycache.c @@ -14,7 +14,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * $Id: ar5212_keycache.c,v 1.4 2008/11/10 04:08:03 sam Exp $ + * $FreeBSD$ */ #include "opt_ah.h" @@ -99,11 +99,18 @@ ar5212ResetKeyCacheEntry(struct ath_hal *ah, uint16_t entry) /* * Sets the mac part of the specified key cache entry (and any * associated MIC entry) and mark them valid. + * + * Since mac[0] is shifted off and not presented to the hardware, + * it does double duty as a "don't use for unicast, use for multicast + * matching" flag. This interface should later be extended to + * explicitly do that rather than overloading a bit in the MAC + * address. */ HAL_BOOL ar5212SetKeyCacheEntryMac(struct ath_hal *ah, uint16_t entry, const uint8_t *mac) { uint32_t macHi, macLo; + uint32_t unicast_flag = AR_KEYTABLE_VALID; if (entry >= AH_PRIVATE(ah)->ah_caps.halKeyCacheSize) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: entry %u out of range\n", @@ -115,6 +122,16 @@ ar5212SetKeyCacheEntryMac(struct ath_hal *ah, uint16_t entry, const uint8_t *mac * the 4 MSBs, and MacHi is the 2 LSBs. */ if (mac != AH_NULL) { + /* + * AR_KEYTABLE_VALID indicates that the address is a unicast + * address, which must match the transmitter address for + * decrypting frames. + * Not setting this bit allows the hardware to use the key + * for multicast frame decryption. + */ + if (mac[0] & 0x01) + unicast_flag = 0; + macHi = (mac[5] << 8) | mac[4]; macLo = (mac[3] << 24)| (mac[2] << 16) | (mac[1] << 8) | mac[0]; @@ -125,7 +142,7 @@ ar5212SetKeyCacheEntryMac(struct ath_hal *ah, uint16_t entry, const uint8_t *mac macLo = macHi = 0; } OS_REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), macLo); - OS_REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), macHi | AR_KEYTABLE_VALID); + OS_REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), macHi | unicast_flag); return AH_TRUE; } diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5212_misc.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5212_misc.c index af9be75ea5..5bcde762a5 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5212_misc.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5212_misc.c @@ -21,9 +21,7 @@ #include "ah.h" #include "ah_internal.h" #include "ah_devid.h" -#ifdef AH_DEBUG #include "ah_desc.h" /* NB: for HAL_PHYERR* */ -#endif #include "ar5212/ar5212.h" #include "ar5212/ar5212reg.h" @@ -264,6 +262,13 @@ ar5212GetTsf32(struct ath_hal *ah) return OS_REG_READ(ah, AR_TSF_L32); } +void +ar5212SetTsf64(struct ath_hal *ah, uint64_t tsf64) +{ + OS_REG_WRITE(ah, AR_TSF_L32, tsf64 & 0xffffffff); + OS_REG_WRITE(ah, AR_TSF_U32, (tsf64 >> 32) & 0xffffffff); +} + /* * Reset the current hardware tsf for stamlme. */ @@ -451,7 +456,7 @@ ar5212SetSifsTime(struct ath_hal *ah, u_int us) } else { /* convert to system clocks */ OS_REG_WRITE(ah, AR_D_GBL_IFS_SIFS, ath_hal_mac_clks(ah, us-2)); - ahp->ah_slottime = us; + ahp->ah_sifstime = us; return AH_TRUE; } } @@ -627,6 +632,20 @@ ar5212SetCoverageClass(struct ath_hal *ah, uint8_t coverageclass, int now) } } +HAL_STATUS +ar5212SetQuiet(struct ath_hal *ah, uint32_t period, uint32_t duration, + uint32_t nextStart, HAL_QUIET_FLAG flag) +{ + OS_REG_WRITE(ah, AR_QUIET2, period | (duration << AR_QUIET2_QUIET_DUR_S)); + if (flag & HAL_QUIET_ENABLE) { + OS_REG_WRITE(ah, AR_QUIET1, nextStart | (1 << 16)); + } + else { + OS_REG_WRITE(ah, AR_QUIET1, nextStart); + } + return HAL_OK; +} + void ar5212SetPCUConfig(struct ath_hal *ah) { @@ -850,7 +869,7 @@ ar5212GetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, case HAL_CAP_MCAST_KEYSRCH: /* multicast frame keycache search */ switch (capability) { case 0: /* hardware capability */ - return HAL_OK; + return pCap->halMcastKeySrchSupport ? HAL_OK : HAL_ENXIO; case 1: return (ahp->ah_staId1Defaults & AR_STA_ID1_MCAST_KSRCH) ? HAL_OK : HAL_ENXIO; @@ -873,16 +892,16 @@ ar5212GetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, return HAL_OK; case HAL_CAP_INTMIT: /* interference mitigation */ switch (capability) { - case 0: /* hardware capability */ + case HAL_CAP_INTMIT_PRESENT: /* hardware capability */ return HAL_OK; - case 1: + case HAL_CAP_INTMIT_ENABLE: return (ahp->ah_procPhyErr & HAL_ANI_ENA) ? HAL_OK : HAL_ENXIO; - case 2: /* HAL_ANI_NOISE_IMMUNITY_LEVEL */ - case 3: /* HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION */ - case 4: /* HAL_ANI_CCK_WEAK_SIGNAL_THR */ - case 5: /* HAL_ANI_FIRSTEP_LEVEL */ - case 6: /* HAL_ANI_SPUR_IMMUNITY_LEVEL */ + case HAL_CAP_INTMIT_NOISE_IMMUNITY_LEVEL: + case HAL_CAP_INTMIT_OFDM_WEAK_SIGNAL_LEVEL: + case HAL_CAP_INTMIT_CCK_WEAK_SIGNAL_THR: + case HAL_CAP_INTMIT_FIRSTEP_LEVEL: + case HAL_CAP_INTMIT_SPUR_IMMUNITY_LEVEL: ani = ar5212AniGetCurrentState(ah); if (ani == AH_NULL) return HAL_ENXIO; @@ -927,7 +946,7 @@ ar5212SetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, else ahp->ah_miscMode |= AR_MISC_MODE_MIC_NEW_LOC_ENABLE; /* NB: write here so keys can be setup w/o a reset */ - OS_REG_WRITE(ah, AR_MISC_MODE, ahp->ah_miscMode); + OS_REG_WRITE(ah, AR_MISC_MODE, OS_REG_READ(ah, AR_MISC_MODE) | ahp->ah_miscMode); return AH_TRUE; case HAL_CAP_DIVERSITY: if (ahp->ah_phyPowerOn) { @@ -973,6 +992,8 @@ ar5212SetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, OS_REG_WRITE(ah, AR_TPC, ahp->ah_macTPC); return AH_TRUE; case HAL_CAP_INTMIT: { /* interference mitigation */ + /* This maps the public ANI commands to the internal ANI commands */ + /* Private: HAL_ANI_CMD; Public: HAL_CAP_INTMIT_CMD */ static const HAL_ANI_CMD cmds[] = { HAL_ANI_PRESENT, HAL_ANI_MODE, @@ -983,7 +1004,7 @@ ar5212SetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, HAL_ANI_SPUR_IMMUNITY_LEVEL, }; return capability < N(cmds) ? - ar5212AniControl(ah, cmds[capability], setting) : + AH5212(ah)->ah_aniControl(ah, cmds[capability], setting) : AH_FALSE; } case HAL_CAP_TSF_ADJUST: /* hardware has beacon tsf adjust */ @@ -1046,7 +1067,7 @@ ar5212GetDiagState(struct ath_hal *ah, int request, case HAL_DIAG_ANI_CMD: if (argsize != 2*sizeof(uint32_t)) return AH_FALSE; - ar5212AniControl(ah, ((const uint32_t *)args)[0], + AH5212(ah)->ah_aniControl(ah, ((const uint32_t *)args)[0], ((const uint32_t *)args)[1]); return AH_TRUE; case HAL_DIAG_ANI_PARAMS: @@ -1071,3 +1092,143 @@ ar5212GetDiagState(struct ath_hal *ah, int request, } return AH_FALSE; } + +/* + * Check whether there's an in-progress NF completion. + * + * Returns AH_TRUE if there's a in-progress NF calibration, AH_FALSE + * otherwise. + */ +HAL_BOOL +ar5212IsNFCalInProgress(struct ath_hal *ah) +{ + if (OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) + return AH_TRUE; + return AH_FALSE; +} + +/* + * Wait for an in-progress NF calibration to complete. + * + * The completion function waits "i" times 10uS. + * It returns AH_TRUE if the NF calibration completed (or was never + * in progress); AH_FALSE if it was still in progress after "i" checks. + */ +HAL_BOOL +ar5212WaitNFCalComplete(struct ath_hal *ah, int i) +{ + int j; + if (i <= 0) + i = 1; /* it should run at least once */ + for (j = 0; j < i; j++) { + if (! ar5212IsNFCalInProgress(ah)) + return AH_TRUE; + OS_DELAY(10); + } + return AH_FALSE; +} + +void +ar5212EnableDfs(struct ath_hal *ah, HAL_PHYERR_PARAM *pe) +{ + uint32_t val; + val = OS_REG_READ(ah, AR_PHY_RADAR_0); + + if (pe->pe_firpwr != HAL_PHYERR_PARAM_NOVAL) { + val &= ~AR_PHY_RADAR_0_FIRPWR; + val |= SM(pe->pe_firpwr, AR_PHY_RADAR_0_FIRPWR); + } + if (pe->pe_rrssi != HAL_PHYERR_PARAM_NOVAL) { + val &= ~AR_PHY_RADAR_0_RRSSI; + val |= SM(pe->pe_rrssi, AR_PHY_RADAR_0_RRSSI); + } + if (pe->pe_height != HAL_PHYERR_PARAM_NOVAL) { + val &= ~AR_PHY_RADAR_0_HEIGHT; + val |= SM(pe->pe_height, AR_PHY_RADAR_0_HEIGHT); + } + if (pe->pe_prssi != HAL_PHYERR_PARAM_NOVAL) { + val &= ~AR_PHY_RADAR_0_PRSSI; + val |= SM(pe->pe_prssi, AR_PHY_RADAR_0_PRSSI); + } + if (pe->pe_inband != HAL_PHYERR_PARAM_NOVAL) { + val &= ~AR_PHY_RADAR_0_INBAND; + val |= SM(pe->pe_inband, AR_PHY_RADAR_0_INBAND); + } + OS_REG_WRITE(ah, AR_PHY_RADAR_0, val | AR_PHY_RADAR_0_ENA); +} + +void +ar5212GetDfsThresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe) +{ + uint32_t val,temp; + + val = OS_REG_READ(ah, AR_PHY_RADAR_0); + + temp = MS(val,AR_PHY_RADAR_0_FIRPWR); + temp |= 0xFFFFFF80; + pe->pe_firpwr = temp; + pe->pe_rrssi = MS(val, AR_PHY_RADAR_0_RRSSI); + pe->pe_height = MS(val, AR_PHY_RADAR_0_HEIGHT); + pe->pe_prssi = MS(val, AR_PHY_RADAR_0_PRSSI); + pe->pe_inband = MS(val, AR_PHY_RADAR_0_INBAND); + + pe->pe_relpwr = 0; + pe->pe_relstep = 0; + pe->pe_maxlen = 0; + pe->pe_extchannel = AH_FALSE; +} + +/* + * Process the radar phy error and extract the pulse duration. + */ +HAL_BOOL +ar5212ProcessRadarEvent(struct ath_hal *ah, struct ath_rx_status *rxs, + uint64_t fulltsf, const char *buf, HAL_DFS_EVENT *event) +{ + uint8_t dur; + uint8_t rssi; + + /* Check whether the given phy error is a radar event */ + if ((rxs->rs_phyerr != HAL_PHYERR_RADAR) && + (rxs->rs_phyerr != HAL_PHYERR_FALSE_RADAR_EXT)) + return AH_FALSE; + + /* + * The first byte is the pulse width - if there's + * no data, simply set the duration to 0 + */ + if (rxs->rs_datalen >= 1) + /* The pulse width is byte 0 of the data */ + dur = ((uint8_t) buf[0]) & 0xff; + else + dur = 0; + + /* Pulse RSSI is the normal reported RSSI */ + rssi = (uint8_t) rxs->rs_rssi; + + /* 0 duration/rssi is not a valid radar event */ + if (dur == 0 && rssi == 0) + return AH_FALSE; + + HALDEBUG(ah, HAL_DEBUG_DFS, "%s: rssi=%d, dur=%d\n", + __func__, rssi, dur); + + /* Record the event */ + event->re_full_ts = fulltsf; + event->re_ts = rxs->rs_tstamp; + event->re_rssi = rssi; + event->re_dur = dur; + event->re_flags = HAL_DFS_EVENT_PRICH; + + return AH_TRUE; +} + +/* + * Return whether 5GHz fast-clock (44MHz) is enabled. + * It's always disabled for AR5212 series NICs. + */ +HAL_BOOL +ar5212IsFastClockEnabled(struct ath_hal *ah) +{ + return AH_FALSE; +} diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5212_recv.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5212_recv.c index eee18b037c..db4f93d430 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5212_recv.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5212_recv.c @@ -59,8 +59,10 @@ ar5212EnableReceive(struct ath_hal *ah) HAL_BOOL ar5212StopDmaReceive(struct ath_hal *ah) { + OS_MARK(ah, AH_MARK_RX_CTL, AH_MARK_RX_CTL_DMA_STOP); OS_REG_WRITE(ah, AR_CR, AR_CR_RXD); /* Set receive disable bit */ if (!ath_hal_wait(ah, AR_CR, AR_CR_RXE, 0)) { + OS_MARK(ah, AH_MARK_RX_CTL, AH_MARK_RX_CTL_DMA_STOP_ERR); #ifdef AH_DEBUG ath_hal_printf(ah, "%s: dma failed to stop in 10ms\n" "AR_CR=0x%08x\nAR_DIAG_SW=0x%08x\n", @@ -82,6 +84,7 @@ ar5212StartPcuReceive(struct ath_hal *ah) { struct ath_hal_private *ahp = AH_PRIVATE(ah); + OS_MARK(ah, AH_MARK_RX_CTL, AH_MARK_RX_CTL_PCU_START); OS_REG_WRITE(ah, AR_DIAG_SW, OS_REG_READ(ah, AR_DIAG_SW) &~ AR_DIAG_RX_DIS); ar5212EnableMibCounters(ah); @@ -95,6 +98,7 @@ ar5212StartPcuReceive(struct ath_hal *ah) void ar5212StopPcuReceive(struct ath_hal *ah) { + OS_MARK(ah, AH_MARK_RX_CTL, AH_MARK_RX_CTL_PCU_STOP); OS_REG_WRITE(ah, AR_DIAG_SW, OS_REG_READ(ah, AR_DIAG_SW) | AR_DIAG_RX_DIS); ar5212DisableMibCounters(ah); @@ -199,7 +203,7 @@ ar5212SetRxFilter(struct ath_hal *ah, uint32_t bits) ahp->ah_miscMode |= AR_MISC_MODE_BSSID_MATCH_FORCE; else ahp->ah_miscMode &= ~AR_MISC_MODE_BSSID_MATCH_FORCE; - OS_REG_WRITE(ah, AR_MISC_MODE, ahp->ah_miscMode); + OS_REG_WRITE(ah, AR_MISC_MODE, OS_REG_READ(ah, AR_MISC_MODE) | ahp->ah_miscMode); } } diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5212_reset.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5212_reset.c index fc937ea149..8e6341a04c 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5212_reset.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5212_reset.c @@ -283,6 +283,14 @@ ar5212Reset(struct ath_hal *ah, HAL_OPMODE opmode, regWrites = ath_hal_ini_write(ah, &ahp->ah_ini_modes, modesIndex, 0); regWrites = write_common(ah, &ahp->ah_ini_common, bChannelChange, regWrites); +#ifdef AH_RXCFG_SDMAMW_4BYTES + /* + * Nala doesn't work with 128 byte bursts on pb42(hydra) (ar71xx), + * use 4 instead. Enabling it on all platforms would hurt performance, + * so we only enable it on the ones that are affected by it. + */ + OS_REG_WRITE(ah, AR_RXCFG, 0); +#endif ahp->ah_rfHal->writeRegs(ah, modesIndex, freqIndex, regWrites); OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__); diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5212_xmit.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5212_xmit.c index ecdf34ebe4..3c6ddc0035 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5212_xmit.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5212_xmit.c @@ -48,16 +48,19 @@ ar5212UpdateTxTrigLevel(struct ath_hal *ah, HAL_BOOL bIncTrigLevel) uint32_t txcfg, curLevel, newLevel; HAL_INT omask; + if (ahp->ah_txTrigLev >= ahp->ah_maxTxTrigLev) + return AH_FALSE; + /* * Disable interrupts while futzing with the fifo level. */ - omask = ar5212SetInterrupts(ah, ahp->ah_maskReg &~ HAL_INT_GLOBAL); + omask = ath_hal_setInterrupts(ah, ahp->ah_maskReg &~ HAL_INT_GLOBAL); txcfg = OS_REG_READ(ah, AR_TXCFG); curLevel = MS(txcfg, AR_FTRIG); newLevel = curLevel; if (bIncTrigLevel) { /* increase the trigger level */ - if (curLevel < MAX_TX_FIFO_THRESHOLD) + if (curLevel < ahp->ah_maxTxTrigLev) newLevel++; } else if (curLevel > MIN_TX_FIFO_THRESHOLD) newLevel--; @@ -66,8 +69,10 @@ ar5212UpdateTxTrigLevel(struct ath_hal *ah, HAL_BOOL bIncTrigLevel) OS_REG_WRITE(ah, AR_TXCFG, (txcfg &~ AR_FTRIG) | SM(newLevel, AR_FTRIG)); + ahp->ah_txTrigLev = newLevel; + /* re-enable chip interrupts */ - ar5212SetInterrupts(ah, omask); + ath_hal_setInterrupts(ah, omask); return (newLevel != curLevel); } @@ -411,9 +416,9 @@ ar5212ResetTxQueue(struct ath_hal *ah, u_int q) * here solely for backwards compatibility. */ value = (ahp->ah_beaconInterval - - (ath_hal_sw_beacon_response_time - - ath_hal_dma_beacon_response_time) - - ath_hal_additional_swba_backoff) * 1024; + - (ah->ah_config.ah_sw_beacon_response_time - + ah->ah_config.ah_dma_beacon_response_time) + - ah->ah_config.ah_additional_swba_backoff) * 1024; OS_REG_WRITE(ah, AR_QRDYTIMECFG(q), value | AR_Q_RDYTIMECFG_ENA); } dmisc |= SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL, @@ -913,3 +918,24 @@ ar5212GetTxIntrQueue(struct ath_hal *ah, uint32_t *txqs) *txqs &= ahp->ah_intrTxqs; ahp->ah_intrTxqs &= ~(*txqs); } + +/* + * Retrieve the rate table from the given TX completion descriptor + */ +HAL_BOOL +ar5212GetTxCompletionRates(struct ath_hal *ah, const struct ath_desc *ds0, int *rates, int *tries) +{ + const struct ar5212_desc *ads = AR5212DESC_CONST(ds0); + + rates[0] = MS(ads->ds_ctl3, AR_XmitRate0); + rates[1] = MS(ads->ds_ctl3, AR_XmitRate1); + rates[2] = MS(ads->ds_ctl3, AR_XmitRate2); + rates[3] = MS(ads->ds_ctl3, AR_XmitRate3); + + tries[0] = MS(ads->ds_ctl2, AR_XmitDataTries0); + tries[1] = MS(ads->ds_ctl2, AR_XmitDataTries1); + tries[2] = MS(ads->ds_ctl2, AR_XmitDataTries2); + tries[3] = MS(ads->ds_ctl2, AR_XmitDataTries3); + + return AH_TRUE; +} diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5212desc.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5212desc.h index 9885c9fbae..c6af68b7b7 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5212desc.h +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5212desc.h @@ -14,7 +14,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * $Id: ar5212desc.h,v 1.4 2008/11/10 04:08:03 sam Exp $ + * $FreeBSD$ */ #ifndef _ATH_AR5212_DESC_H_ #define _ATH_AR5212_DESC_H_ diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5212phy.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5212phy.h index e040ec79b6..12cd3dfa29 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5212phy.h +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5212phy.h @@ -14,7 +14,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * $Id: ar5212phy.h,v 1.7 2008/11/19 21:23:01 sam Exp $ + * $FreeBSD$ */ #ifndef _DEV_ATH_AR5212PHY_H_ #define _DEV_ATH_AR5212PHY_H_ diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5212reg.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5212reg.h index f99b203e95..15c1a58f7d 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5212reg.h +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5212reg.h @@ -300,6 +300,7 @@ #define AR_QUIET1_NEXT_QUIET 0xffff #define AR_QUIET1_QUIET_ENABLE 0x10000 /* Enable Quiet time operation */ #define AR_QUIET1_QUIET_ACK_CTS_ENABLE 0x20000 /* Do we ack/cts during quiet period */ +#define AR_QUIET1_QUIET_ACK_CTS_ENABLE_S 17 #define AR_QUIET2 0x8100 /* More Quiet time programming */ #define AR_QUIET2_QUIET_PER_S 0 /* Periodicity of quiet period (TU) */ diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5311reg.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5311reg.h index efb8568636..b79370ebba 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5311reg.h +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5212/ar5311reg.h @@ -14,7 +14,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * $Id: ar5311reg.h,v 1.3 2008/10/06 18:32:50 sam Exp $ + * $FreeBSD$ */ #ifndef _DEV_ATH_AR5311REG_H_ #define _DEV_ATH_AR5311REG_H_ diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5312/ar5312_attach.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5312/ar5312_attach.c index 4af2d8951f..d1689d59fc 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5312/ar5312_attach.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5312/ar5312_attach.c @@ -61,7 +61,8 @@ ar5312AniSetup(struct ath_hal *ah) */ static struct ath_hal * ar5312Attach(uint16_t devid, HAL_SOFTC sc, - HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status) + HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata, + HAL_STATUS *status) { struct ath_hal_5212 *ahp = AH_NULL; struct ath_hal *ah; @@ -70,13 +71,13 @@ ar5312Attach(uint16_t devid, HAL_SOFTC sc, uint16_t eeval; HAL_STATUS ecode; - HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", + HALDEBUG_G(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", __func__, sc, st, (void*) sh); /* NB: memory is returned zero'd */ ahp = ath_hal_malloc(sizeof (struct ath_hal_5212)); if (ahp == AH_NULL) { - HALDEBUG(AH_NULL, HAL_DEBUG_ANY, + HALDEBUG_G(AH_NULL, HAL_DEBUG_ANY, "%s: cannot allocate memory for state block\n", __func__); *status = HAL_ENOMEM; return AH_NULL; diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5312/ar5312_eeprom.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5312/ar5312_eeprom.c index c14b8b2cdb..7a84232e0b 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5312/ar5312_eeprom.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5312/ar5312_eeprom.c @@ -14,7 +14,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * $Id: ar5312_eeprom.c,v 1.4 2008/11/10 04:08:04 sam Exp $ + * $FreeBSD$ */ #include "opt_ah.h" diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5312/ar5312_interrupts.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5312/ar5312_interrupts.c index c40191ed55..0a1545c075 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5312/ar5312_interrupts.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5312/ar5312_interrupts.c @@ -14,7 +14,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * $Id: ar5312_interrupts.c,v 1.2 2008/11/10 01:19:39 sam Exp $ + * $FreeBSD$ */ #include "opt_ah.h" diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5312/ar5312_misc.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5312/ar5312_misc.c index 79283186c5..3d85ece7d5 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5312/ar5312_misc.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5312/ar5312_misc.c @@ -14,7 +14,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * $Id: ar5312_misc.c,v 1.4 2008/11/22 07:40:15 sam Exp $ + * $FreeBSD$ */ #include "opt_ah.h" diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5312/ar5312_power.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5312/ar5312_power.c index 1cc4ed64a0..94a0f1c64b 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5312/ar5312_power.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5312/ar5312_power.c @@ -14,7 +14,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * $Id: ar5312_power.c,v 1.4 2008/11/10 04:08:04 sam Exp $ + * $FreeBSD$ */ #include "opt_ah.h" diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5312/ar5312phy.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5312/ar5312phy.h index 9f867c7526..fcb8564c77 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5312/ar5312phy.h +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5312/ar5312phy.h @@ -14,7 +14,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * $Id: ar5312phy.h,v 1.3 2008/10/06 18:32:50 sam Exp $ + * $FreeBSD$ */ #ifndef _DEV_ATH_AR5312PHY_H_ #define _DEV_ATH_AR5312PHY_H_ diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5312/ar5312reg.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5312/ar5312reg.h index ff79cd3f08..bdfeffa966 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5312/ar5312reg.h +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5312/ar5312reg.h @@ -14,7 +14,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * $Id: ar5312reg.h,v 1.4 2008/11/10 04:08:04 sam Exp $ + * $FreeBSD$ */ #ifndef _DEV_ATH_AR5312REG_H_ #define _DEV_ATH_AR5312REG_H_ diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar2133.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar2133.c index 44531787de..f25c108267 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar2133.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar2133.c @@ -57,6 +57,65 @@ ar2133WriteRegs(struct ath_hal *ah, u_int modesIndex, u_int freqIndex, freqIndex, writes); } +/* + * Fix on 2.4 GHz band for orientation sensitivity issue by increasing + * rf_pwd_icsyndiv. + * + * Theoretical Rules: + * if 2 GHz band + * if forceBiasAuto + * if synth_freq < 2412 + * bias = 0 + * else if 2412 <= synth_freq <= 2422 + * bias = 1 + * else // synth_freq > 2422 + * bias = 2 + * else if forceBias > 0 + * bias = forceBias & 7 + * else + * no change, use value from ini file + * else + * no change, invalid band + * + * 1st Mod: + * 2422 also uses value of 2 + * + * + * 2nd Mod: + * Less than 2412 uses value of 0, 2412 and above uses value of 2 + */ +static void +ar2133ForceBias(struct ath_hal *ah, uint16_t synth_freq) +{ + uint32_t tmp_reg; + int reg_writes = 0; + uint32_t new_bias = 0; + struct ar2133State *priv = AR2133(ah); + + /* XXX this is a bit of a silly check for 2.4ghz channels -adrian */ + if (synth_freq >= 3000) + return; + + if (synth_freq < 2412) + new_bias = 0; + else if (synth_freq < 2422) + new_bias = 1; + else + new_bias = 2; + + /* pre-reverse this field */ + tmp_reg = ath_hal_reverseBits(new_bias, 3); + + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: Force rf_pwd_icsyndiv to %1d on %4d\n", + __func__, new_bias, synth_freq); + + /* swizzle rf_pwd_icsyndiv */ + ar5416ModifyRfBuffer(priv->Bank6Data, tmp_reg, 3, 181, 3); + + /* write Bank 6 with new params */ + ath_hal_ini_bank_write(ah, &AH5416(ah)->ah_ini_bank6, priv->Bank6Data, reg_writes); +} + /* * Take the MHz channel value and set the Channel value * @@ -106,13 +165,13 @@ ar2133SetChannel(struct ath_hal *ah, const struct ieee80211_channel *chan) } } else if ((freq % 20) == 0 && freq >= 5120) { channelSel = ath_hal_reverseBits(((freq - 4800) / 20 << 2), 8); - if (AR_SREV_SOWL_10_OR_LATER(ah)) + if (AR_SREV_HOWL(ah) || AR_SREV_SOWL_10_OR_LATER(ah)) aModeRefSel = ath_hal_reverseBits(3, 2); else aModeRefSel = ath_hal_reverseBits(1, 2); } else if ((freq % 10) == 0) { channelSel = ath_hal_reverseBits(((freq - 4800) / 10 << 1), 8); - if (AR_SREV_SOWL_10_OR_LATER(ah)) + if (AR_SREV_HOWL(ah) || AR_SREV_SOWL_10_OR_LATER(ah)) aModeRefSel = ath_hal_reverseBits(2, 2); else aModeRefSel = ath_hal_reverseBits(1, 2); @@ -125,6 +184,10 @@ ar2133SetChannel(struct ath_hal *ah, const struct ieee80211_channel *chan) return AH_FALSE; } + /* Workaround for hw bug - AR5416 specific */ + if (AR_SREV_OWL(ah) && ah->ah_config.ah_ar5416_biasadj) + ar2133ForceBias(ah, freq); + reg32 = (channelSel << 8) | (aModeRefSel << 2) | (bModeSynth << 1) | (1 << 5) | 0x1; @@ -188,11 +251,19 @@ ar2133SetRfRegs(struct ath_hal *ah, const struct ieee80211_channel *chan, /* Only the 5 or 2 GHz OB/DB need to be set for a mode */ if (IEEE80211_IS_CHAN_2GHZ(chan)) { + HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: 2ghz: OB_2:%d, DB_2:%d\n", + __func__, + ath_hal_eepromGet(ah, AR_EEP_OB_2, AH_NULL), + ath_hal_eepromGet(ah, AR_EEP_DB_2, AH_NULL)); ar5416ModifyRfBuffer(priv->Bank6Data, ath_hal_eepromGet(ah, AR_EEP_OB_2, AH_NULL), 3, 197, 0); ar5416ModifyRfBuffer(priv->Bank6Data, ath_hal_eepromGet(ah, AR_EEP_DB_2, AH_NULL), 3, 194, 0); } else { + HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: 5ghz: OB_5:%d, DB_5:%d\n", + __func__, + ath_hal_eepromGet(ah, AR_EEP_OB_5, AH_NULL), + ath_hal_eepromGet(ah, AR_EEP_DB_5, AH_NULL)); ar5416ModifyRfBuffer(priv->Bank6Data, ath_hal_eepromGet(ah, AR_EEP_OB_5, AH_NULL), 3, 203, 0); ar5416ModifyRfBuffer(priv->Bank6Data, @@ -323,12 +394,29 @@ ar2133GetChannelMaxMinPower(struct ath_hal *ah, #endif } +/* + * The ordering of nfarray is thus: + * + * nfarray[0]: Chain 0 ctl + * nfarray[1]: Chain 1 ctl + * nfarray[2]: Chain 2 ctl + * nfarray[3]: Chain 0 ext + * nfarray[4]: Chain 1 ext + * nfarray[5]: Chain 2 ext + */ static void ar2133GetNoiseFloor(struct ath_hal *ah, int16_t nfarray[]) { struct ath_hal_5416 *ahp = AH5416(ah); int16_t nf; + /* + * Blank nf array - some chips may only + * have one or two RX chainmasks enabled. + */ + nfarray[0] = nfarray[1] = nfarray[2] = 0; + nfarray[3] = nfarray[4] = nfarray[5] = 0; + switch (ahp->ah_rx_chainmask) { case 0x7: nf = MS(OS_REG_READ(ah, AR_PHY_CH2_CCA), AR_PHY_CH2_MINCCA_PWR); @@ -336,7 +424,7 @@ ar2133GetNoiseFloor(struct ath_hal *ah, int16_t nfarray[]) nf = 0 - ((nf ^ 0x1ff) + 1); HALDEBUG(ah, HAL_DEBUG_NFCAL, "NF calibrated [ctl] [chain 2] is %d\n", nf); - nfarray[4] = nf; + nfarray[2] = nf; nf = MS(OS_REG_READ(ah, AR_PHY_CH2_EXT_CCA), AR_PHY_CH2_EXT_MINCCA_PWR); if (nf & 0x100) @@ -352,7 +440,7 @@ ar2133GetNoiseFloor(struct ath_hal *ah, int16_t nfarray[]) nf = 0 - ((nf ^ 0x1ff) + 1); HALDEBUG(ah, HAL_DEBUG_NFCAL, "NF calibrated [ctl] [chain 1] is %d\n", nf); - nfarray[2] = nf; + nfarray[1] = nf; nf = MS(OS_REG_READ(ah, AR_PHY_CH1_EXT_CCA), AR_PHY_CH1_EXT_MINCCA_PWR); @@ -360,7 +448,7 @@ ar2133GetNoiseFloor(struct ath_hal *ah, int16_t nfarray[]) nf = 0 - ((nf ^ 0x1ff) + 1); HALDEBUG(ah, HAL_DEBUG_NFCAL, "NF calibrated [ext] [chain 1] is %d\n", nf); - nfarray[3] = nf; + nfarray[4] = nf; /* fall thru... */ case 0x1: nf = MS(OS_REG_READ(ah, AR_PHY_CCA), AR_PHY_MINCCA_PWR); @@ -375,7 +463,7 @@ ar2133GetNoiseFloor(struct ath_hal *ah, int16_t nfarray[]) nf = 0 - ((nf ^ 0x1ff) + 1); HALDEBUG(ah, HAL_DEBUG_NFCAL, "NF calibrated [ext] [chain 0] is %d\n", nf); - nfarray[1] = nf; + nfarray[3] = nf; break; } diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416.h index 8d1484b60a..a0f5deead8 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416.h +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416.h @@ -37,6 +37,19 @@ typedef struct { uint16_t ext_center; } CHAN_CENTERS; +typedef enum Ar5416_Rates { + rate6mb, rate9mb, rate12mb, rate18mb, + rate24mb, rate36mb, rate48mb, rate54mb, + rate1l, rate2l, rate2s, rate5_5l, + rate5_5s, rate11l, rate11s, rateXr, + rateHt20_0, rateHt20_1, rateHt20_2, rateHt20_3, + rateHt20_4, rateHt20_5, rateHt20_6, rateHt20_7, + rateHt40_0, rateHt40_1, rateHt40_2, rateHt40_3, + rateHt40_4, rateHt40_5, rateHt40_6, rateHt40_7, + rateDupCck, rateDupOfdm, rateExtCck, rateExtOfdm, + Ar5416RateSize +} AR5416_RATES; + #define AR5416_DEFAULT_RXCHAINMASK 7 #define AR5416_DEFAULT_TXCHAINMASK 1 #define AR5416_MAX_RATE_POWER 63 @@ -49,6 +62,12 @@ typedef struct { #define AR5416_SPUR_RSSI_THRESH 40 +struct ar5416NfLimits { + int16_t max; + int16_t min; + int16_t nominal; +}; + struct ath_hal_5416 { struct ath_hal_5212 ah_5212; @@ -68,6 +87,26 @@ struct ath_hal_5416 { void (*ah_spurMitigate)(struct ath_hal *, const struct ieee80211_channel *); + /* calibration ops */ + HAL_BOOL (*ah_cal_initcal)(struct ath_hal *, + const struct ieee80211_channel *); + void (*ah_cal_pacal)(struct ath_hal *, + HAL_BOOL is_reset); + + /* optional open-loop tx power control related methods */ + void (*ah_olcInit)(struct ath_hal *); + void (*ah_olcTempCompensation)(struct ath_hal *); + + /* tx power control */ + HAL_BOOL (*ah_setPowerCalTable) (struct ath_hal *ah, + struct ar5416eeprom *pEepData, + const struct ieee80211_channel *chan, + int16_t *pTxPowerIndexOffset); + + /* baseband operations */ + void (*ah_initPLL) (struct ath_hal *ah, + const struct ieee80211_channel *chan); + u_int ah_globaltxtimeout; /* global tx timeout */ u_int ah_gpioMask; int ah_hangs; /* h/w hangs state */ @@ -81,7 +120,16 @@ struct ath_hal_5416 { uint32_t ah_rx_chainmask; uint32_t ah_tx_chainmask; + HAL_ANI_CMD ah_ani_function; + struct ar5416PerCal ah_cal; /* periodic calibration state */ + + struct ar5416NfLimits nf_2g; + struct ar5416NfLimits nf_5g; + + int initPDADC; + + int ah_need_an_top2_fixup; /* merlin or later chips that may need this workaround */ }; #define AH5416(_ah) ((struct ath_hal_5416 *)(_ah)) @@ -102,10 +150,6 @@ extern void ar5416Detach(struct ath_hal *ah); extern void ar5416AttachPCIE(struct ath_hal *ah); extern HAL_BOOL ar5416FillCapabilityInfo(struct ath_hal *ah); -#define IS_5GHZ_FAST_CLOCK_EN(_ah, _c) \ - (IEEE80211_IS_CHAN_5GHZ(_c) && \ - ath_hal_eepromGetFlag(ah, AR_EEP_FSTCLK_5G)) - extern void ar5416AniAttach(struct ath_hal *, const struct ar5212AniParams *, const struct ar5212AniParams *, HAL_BOOL ena); extern void ar5416AniDetach(struct ath_hal *); @@ -113,8 +157,9 @@ extern HAL_BOOL ar5416AniControl(struct ath_hal *, HAL_ANI_CMD cmd, int param); extern HAL_BOOL ar5416AniSetParams(struct ath_hal *, const struct ar5212AniParams *, const struct ar5212AniParams *); extern void ar5416ProcessMibIntr(struct ath_hal *, const HAL_NODE_STATS *); -extern void ar5416AniPoll(struct ath_hal *, const HAL_NODE_STATS *, +extern void ar5416RxMonitor(struct ath_hal *, const HAL_NODE_STATS *, const struct ieee80211_channel *); +extern void ar5416AniPoll(struct ath_hal *, const struct ieee80211_channel *); extern void ar5416AniReset(struct ath_hal *, const struct ieee80211_channel *, HAL_OPMODE, int); @@ -124,6 +169,7 @@ extern void ar5416BeaconInit(struct ath_hal *ah, extern void ar5416ResetStaBeaconTimers(struct ath_hal *ah); extern void ar5416SetStaBeaconTimers(struct ath_hal *ah, const HAL_BEACON_STATE *); +extern uint64_t ar5416GetNextTBTT(struct ath_hal *); extern HAL_BOOL ar5416EepromRead(struct ath_hal *, u_int off, uint16_t *data); extern HAL_BOOL ar5416EepromWrite(struct ath_hal *, u_int off, uint16_t data); @@ -141,6 +187,8 @@ extern void ar5416GpioSetIntr(struct ath_hal *ah, u_int, uint32_t ilevel); extern u_int ar5416GetWirelessModes(struct ath_hal *ah); extern void ar5416SetLedState(struct ath_hal *ah, HAL_LED_STATE state); +extern uint64_t ar5416GetTsf64(struct ath_hal *ah); +extern void ar5416SetTsf64(struct ath_hal *ah, uint64_t tsf64); extern void ar5416ResetTsf(struct ath_hal *ah); extern HAL_BOOL ar5416SetAntennaSwitch(struct ath_hal *, HAL_ANT_SETTING); extern HAL_BOOL ar5416SetDecompMask(struct ath_hal *, uint16_t, int); @@ -149,11 +197,21 @@ extern uint32_t ar5416Get11nExtBusy(struct ath_hal *ah); extern void ar5416Set11nMac2040(struct ath_hal *ah, HAL_HT_MACMODE mode); extern HAL_HT_RXCLEAR ar5416Get11nRxClear(struct ath_hal *ah); extern void ar5416Set11nRxClear(struct ath_hal *ah, HAL_HT_RXCLEAR rxclear); +extern HAL_STATUS ar5416SetQuiet(struct ath_hal *ah, uint32_t period, + uint32_t duration, uint32_t nextStart, HAL_QUIET_FLAG flag); extern HAL_STATUS ar5416GetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, uint32_t capability, uint32_t *result); extern HAL_BOOL ar5416GetDiagState(struct ath_hal *ah, int request, const void *args, uint32_t argsize, void **result, uint32_t *resultsize); +extern HAL_BOOL ar5416SetRifsDelay(struct ath_hal *ah, + const struct ieee80211_channel *chan, HAL_BOOL enable); +extern void ar5416EnableDfs(struct ath_hal *ah, HAL_PHYERR_PARAM *pe); +extern void ar5416GetDfsThresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe); +extern HAL_BOOL ar5416ProcessRadarEvent(struct ath_hal *ah, + struct ath_rx_status *rxs, uint64_t fulltsf, const char *buf, + HAL_DFS_EVENT *event); +extern HAL_BOOL ar5416IsFastClockEnabled(struct ath_hal *ah); extern HAL_BOOL ar5416SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode, int setChip); @@ -164,6 +222,8 @@ extern HAL_BOOL ar5416ResetKeyCacheEntry(struct ath_hal *ah, uint16_t entry); extern HAL_BOOL ar5416SetKeyCacheEntry(struct ath_hal *ah, uint16_t entry, const HAL_KEYVAL *k, const uint8_t *mac, int xorKey); +extern uint32_t ar5416GetRxFilter(struct ath_hal *ah); +extern void ar5416SetRxFilter(struct ath_hal *ah, uint32_t bits); extern void ar5416StartPcuReceive(struct ath_hal *ah); extern void ar5416StopPcuReceive(struct ath_hal *ah); extern HAL_BOOL ar5416SetupRxDesc(struct ath_hal *, @@ -180,6 +240,7 @@ extern HAL_RFGAIN ar5416GetRfgain(struct ath_hal *ah); extern HAL_BOOL ar5416Disable(struct ath_hal *ah); extern HAL_BOOL ar5416ChipReset(struct ath_hal *ah, const struct ieee80211_channel *); +extern int ar5416GetRegChainOffset(struct ath_hal *ah, int i); extern HAL_BOOL ar5416SetBoardValues(struct ath_hal *, const struct ieee80211_channel *); extern HAL_BOOL ar5416SetResetReg(struct ath_hal *, uint32_t type); @@ -190,6 +251,15 @@ extern HAL_BOOL ar5416GetChipPowerLimits(struct ath_hal *ah, struct ieee80211_channel *chan); extern void ar5416GetChannelCenters(struct ath_hal *, const struct ieee80211_channel *chan, CHAN_CENTERS *centers); +extern void ar5416SetRatesArrayFromTargetPower(struct ath_hal *ah, + const struct ieee80211_channel *chan, + int16_t *ratesArray, + const CAL_TARGET_POWER_LEG *targetPowerCck, + const CAL_TARGET_POWER_LEG *targetPowerCckExt, + const CAL_TARGET_POWER_LEG *targetPowerOfdm, + const CAL_TARGET_POWER_LEG *targetPowerOfdmExt, + const CAL_TARGET_POWER_HT *targetPowerHt20, + const CAL_TARGET_POWER_HT *targetPowerHt40); extern void ar5416GetTargetPowers(struct ath_hal *ah, const struct ieee80211_channel *chan, CAL_TARGET_POWER_HT *powInfo, @@ -200,7 +270,36 @@ extern void ar5416GetTargetPowersLeg(struct ath_hal *ah, CAL_TARGET_POWER_LEG *powInfo, uint16_t numChannels, CAL_TARGET_POWER_LEG *pNewPower, uint16_t numRates, HAL_BOOL isExtTarget); +extern void ar5416InitChainMasks(struct ath_hal *ah); +extern void ar5416RestoreChainMask(struct ath_hal *ah); +extern void ar5416EepromSetAddac(struct ath_hal *ah, + const struct ieee80211_channel *chan); +extern uint16_t ar5416GetMaxEdgePower(uint16_t freq, + CAL_CTL_EDGES *pRdEdgesPower, HAL_BOOL is2GHz); +extern void ar5416InitPLL(struct ath_hal *ah, + const struct ieee80211_channel *chan); +/* TX power setup related routines in ar5416_reset.c */ +extern void ar5416GetGainBoundariesAndPdadcs(struct ath_hal *ah, + const struct ieee80211_channel *chan, CAL_DATA_PER_FREQ *pRawDataSet, + uint8_t * bChans, uint16_t availPiers, + uint16_t tPdGainOverlap, int16_t *pMinCalPower, + uint16_t * pPdGainBoundaries, uint8_t * pPDADCValues, + uint16_t numXpdGains); +extern void ar5416SetGainBoundariesClosedLoop(struct ath_hal *ah, + int i, uint16_t pdGainOverlap_t2, + uint16_t gainBoundaries[]); +extern uint16_t ar5416GetXpdGainValues(struct ath_hal *ah, uint16_t xpdMask, + uint16_t xpdGainValues[]); +extern void ar5416WriteDetectorGainBiases(struct ath_hal *ah, + uint16_t numXpdGain, uint16_t xpdGainValues[]); +extern void ar5416WritePdadcValues(struct ath_hal *ah, int i, + uint8_t pdadcValues[]); +extern HAL_BOOL ar5416SetPowerCalTable(struct ath_hal *ah, + struct ar5416eeprom *pEepData, const struct ieee80211_channel *chan, + int16_t *pTxPowerIndexOffset); +extern void ar5416WriteTxPowerRateRegisters(struct ath_hal *ah, + const struct ieee80211_channel *chan, const int16_t ratesArray[]); extern HAL_BOOL ar5416StopTxDma(struct ath_hal *ah, u_int q); extern HAL_BOOL ar5416SetupTxDesc(struct ath_hal *ah, struct ath_desc *ds, @@ -218,6 +317,30 @@ extern HAL_BOOL ar5416FillTxDesc(struct ath_hal *ah, struct ath_desc *ds, const struct ath_desc *ds0); extern HAL_STATUS ar5416ProcTxDesc(struct ath_hal *ah, struct ath_desc *, struct ath_tx_status *); +extern HAL_BOOL ar5416GetTxCompletionRates(struct ath_hal *ah, + const struct ath_desc *ds0, int *rates, int *tries); + +extern HAL_BOOL ar5416ResetTxQueue(struct ath_hal *ah, u_int q); +extern int ar5416SetupTxQueue(struct ath_hal *ah, HAL_TX_QUEUE type, + const HAL_TXQ_INFO *qInfo); + +extern HAL_BOOL ar5416ChainTxDesc(struct ath_hal *ah, struct ath_desc *ds, + u_int pktLen, u_int hdrLen, HAL_PKT_TYPE type, u_int keyIx, + HAL_CIPHER cipher, uint8_t delims, u_int segLen, HAL_BOOL firstSeg, + HAL_BOOL lastSeg); +extern HAL_BOOL ar5416SetupFirstTxDesc(struct ath_hal *ah, struct ath_desc *ds, + u_int aggrLen, u_int flags, u_int txPower, u_int txRate0, u_int txTries0, + u_int antMode, u_int rtsctsRate, u_int rtsctsDuration); +extern HAL_BOOL ar5416SetupLastTxDesc(struct ath_hal *ah, struct ath_desc *ds, + const struct ath_desc *ds0); +extern HAL_BOOL ar5416SetGlobalTxTimeout(struct ath_hal *ah, u_int tu); +extern u_int ar5416GetGlobalTxTimeout(struct ath_hal *ah); +extern void ar5416Set11nRateScenario(struct ath_hal *ah, struct ath_desc *ds, + u_int durUpdateEn, u_int rtsctsRate, HAL_11N_RATE_SERIES series[], + u_int nseries, u_int flags); +extern void ar5416Set11nAggrMiddle(struct ath_hal *ah, struct ath_desc *ds, u_int numDelims); +extern void ar5416Clr11nAggr(struct ath_hal *ah, struct ath_desc *ds); +extern void ar5416Set11nBurstDuration(struct ath_hal *ah, struct ath_desc *ds, u_int burstDuration); extern const HAL_RATE_TABLE *ar5416GetRateTable(struct ath_hal *, u_int mode); #endif /* _ATH_AR5416_H_ */ diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416.ini b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416.ini index eee859e4e8..7f8c7934c0 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416.ini +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416.ini @@ -1,6 +1,6 @@ /* * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting - * Copyright (c) 2002-2008 Atheros Communications, Inc. + * Copyright (c) 2008-2009 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -24,29 +24,31 @@ static const uint32_t ar5416Modes[][6] = { { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 }, - { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801080, 0x08400840, 0x06e006e0 }, + { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 }, { 0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf }, + { 0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810 }, + { 0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a, 0x0000320a }, { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, - { 0x00009844, 0x1372161e, 0x13721c1e, 0x13721c30, 0x137216a4, 0x13721c25 }, + { 0x00009844, 0x1372161e, 0x1372161e, 0x137216a0, 0x137216a0, 0x137216a0 }, { 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, { 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, { 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, - { 0x00009850, 0x6c28b4e0, 0x6c28b4e0, 0x6d68b0de, 0x6d68b0de, 0x6c28b0de }, + { 0x00009850, 0x6c48b4e0, 0x6d48b4e0, 0x6d48b0de, 0x6c48b0de, 0x6c48b0de }, { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e }, - { 0x0000985c, 0x313a5d5e, 0x313a5d5e, 0x313a605e, 0x313a605e, 0x313a5d5e }, - { 0x00009860, 0x00049d10, 0x00049d10, 0x00049d20, 0x00049d20, 0x00049d10 }, - { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, + { 0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e, 0x31395d5e }, + { 0x00009860, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18 }, + { 0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, { 0x00009868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190 }, { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 }, - { 0x00009914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, 0x000007d0 }, - { 0x00009918, 0x000001b8, 0x00000370, 0x00000268, 0x00000134, 0x00000370 }, - { 0x00009924, 0xd0058a0b, 0xd0058a0b, 0xd0058a19, 0xd0058a13, 0xd0058a0b }, - { 0x00009944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020 }, + { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 }, + { 0x00009918, 0x000001b8, 0x00000370, 0x00000268, 0x00000134, 0x00000134 }, + { 0x00009924, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b }, + { 0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020 }, #ifdef TB243 { 0x00009960, 0x00000900, 0x00000900, 0x00009b40, 0x00009b40, 0x00012d80 }, { 0x0000a960, 0x00000900, 0x00000900, 0x00009b40, 0x00009b40, 0x00012d80 }, @@ -63,14 +65,16 @@ static const uint32_t ar5416Modes[][6] = { #endif #endif { 0x0000c9bc, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00 }, + { 0x00009964, 0x00000000, 0x00000000, 0x00001120, 0x00001120, 0x00001120 }, + { 0x000099bc, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00 }, { 0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be }, { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, - { 0x000099c8, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c }, + { 0x000099c8, 0x6af6532c, 0x6af6532c, 0x6af6532c, 0x6af6532c, 0x6af6532c }, { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a204, 0x00000440, 0x00000440, 0x00000440, 0x00000440, 0x00000440 }, + { 0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880 }, { 0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788 }, { 0x0000a20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 }, { 0x0000b20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 }, @@ -219,7 +223,6 @@ static const uint32_t ar5416Common[][2] = { { 0x00008110, 0x00000168 }, { 0x00008118, 0x000100aa }, { 0x0000811c, 0x00003210 }, - { 0x00008120, 0x08f04800 }, { 0x00008124, 0x00000000 }, { 0x00008128, 0x00000000 }, { 0x0000812c, 0x00000000 }, @@ -227,7 +230,7 @@ static const uint32_t ar5416Common[][2] = { { 0x00008134, 0x00000000 }, { 0x00008138, 0x00000000 }, { 0x0000813c, 0x00000000 }, - { 0x00008144, 0x00000000 }, + { 0x00008144, 0xffffffff }, { 0x00008168, 0x00000000 }, { 0x0000816c, 0x00000000 }, { 0x00008170, 0x32143320 }, @@ -235,7 +238,6 @@ static const uint32_t ar5416Common[][2] = { { 0x00008178, 0x00000100 }, { 0x0000817c, 0x00000000 }, { 0x000081c4, 0x00000000 }, - { 0x000081d0, 0x00003210 }, { 0x000081ec, 0x00000000 }, { 0x000081f0, 0x00000000 }, { 0x000081f4, 0x00000000 }, @@ -266,6 +268,7 @@ static const uint32_t ar5416Common[][2] = { { 0x00008258, 0x00000000 }, { 0x0000825c, 0x400000ff }, { 0x00008260, 0x00080922 }, + { 0x00008264, 0xa8000010 }, { 0x00008270, 0x00000000 }, { 0x00008274, 0x40000000 }, { 0x00008278, 0x003e4180 }, @@ -286,7 +289,7 @@ static const uint32_t ar5416Common[][2] = { { 0x0000832c, 0x00000007 }, { 0x00008330, 0x00000302 }, { 0x00008334, 0x00000e00 }, - { 0x00008338, 0x00000000 }, + { 0x00008338, 0x00070000 }, { 0x0000833c, 0x00000000 }, { 0x00008340, 0x000107ff }, { 0x00009808, 0x00000000 }, @@ -297,7 +300,7 @@ static const uint32_t ar5416Common[][2] = { { 0x0000982c, 0x0000a000 }, { 0x00009830, 0x00000000 }, { 0x0000983c, 0x00200400 }, - { 0x00009840, 0x206a016e }, + { 0x00009840, 0x206a002e }, { 0x0000984c, 0x1284233c }, { 0x00009854, 0x00000859 }, { 0x00009900, 0x00000000 }, @@ -319,7 +322,7 @@ static const uint32_t ar5416Common[][2] = { { 0x00009958, 0x00081fff }, { 0x0000c95c, 0x004b6a8e }, { 0x0000c968, 0x000003ce }, - { 0x00009970, 0x190c0514 }, + { 0x00009970, 0x190fb515 }, { 0x00009974, 0x00000000 }, { 0x00009978, 0x00000001 }, { 0x0000997c, 0x00000000 }, @@ -334,7 +337,7 @@ static const uint32_t ar5416Common[][2] = { { 0x000099a0, 0x00000000 }, { 0x000099a4, 0x00000001 }, { 0x000099a8, 0x001fff00 }, - { 0x000099ac, 0x000000c4 }, + { 0x000099ac, 0x00000000 }, { 0x000099b0, 0x03051000 }, { 0x000099dc, 0x00000000 }, { 0x000099e0, 0x00000200 }, @@ -426,9 +429,9 @@ static const uint32_t ar5416Common[][2] = { { 0x0000a25c, 0x0f0f0f01 }, { 0x0000a260, 0xdfa91f01 }, { 0x0000a268, 0x00000000 }, - { 0x0000a26c, 0x0ebae9c6 }, - { 0x0000b26c, 0x0ebae9c6 }, - { 0x0000c26c, 0x0ebae9c6 }, + { 0x0000a26c, 0x0e79e5c6 }, + { 0x0000b26c, 0x0e79e5c6 }, + { 0x0000c26c, 0x0e79e5c6 }, { 0x0000d270, 0x00820820 }, { 0x0000a278, 0x1ce739ce }, { 0x0000a27c, 0x051701ce }, @@ -441,15 +444,15 @@ static const uint32_t ar5416Common[][2] = { { 0x0000a350, 0x3fffffff }, { 0x0000a354, 0x0003ffff }, { 0x0000a358, 0x79a8aa1f }, - { 0x0000d35c, 0x066c420f }, - { 0x0000d360, 0x0f282207 }, - { 0x0000d364, 0x17601685 }, - { 0x0000d368, 0x1f801104 }, - { 0x0000d36c, 0x37a00c03 }, - { 0x0000d370, 0x3fc40883 }, - { 0x0000d374, 0x57c00803 }, - { 0x0000d378, 0x5fd80682 }, - { 0x0000d37c, 0x7fe00482 }, + { 0x0000d35c, 0x07ffffef }, + { 0x0000d360, 0x0fffffe7 }, + { 0x0000d364, 0x17ffffe5 }, + { 0x0000d368, 0x1fffffe4 }, + { 0x0000d36c, 0x37ffffe3 }, + { 0x0000d370, 0x3fffffe3 }, + { 0x0000d374, 0x57ffffe3 }, + { 0x0000d378, 0x5fffffe2 }, + { 0x0000d37c, 0x7fffffe2 }, { 0x0000d380, 0x7f3c7bba }, { 0x0000d384, 0xf3307ff0 }, { 0x0000a388, 0x08000000 }, @@ -625,8 +628,8 @@ static const uint32_t ar5416Bank6[][3] = { { 0x0000989c, 0x00dc0000, 0x00dc0000 }, { 0x0000989c, 0x00110000, 0x00110000 }, { 0x0000989c, 0x006100a8, 0x006100a8 }, - { 0x0000989c, 0x00421022, 0x00421022 }, - { 0x0000989c, 0x001400df, 0x001400df }, + { 0x0000989c, 0x00423022, 0x00423022 }, + { 0x0000989c, 0x201400df, 0x201400df }, { 0x0000989c, 0x00c40002, 0x00c40002 }, { 0x0000989c, 0x003000f2, 0x003000f2 }, { 0x0000989c, 0x00440016, 0x00440016 }, @@ -634,7 +637,7 @@ static const uint32_t ar5416Bank6[][3] = { { 0x0000989c, 0x0001805e, 0x0001805e }, { 0x0000989c, 0x0000c0ab, 0x0000c0ab }, { 0x0000989c, 0x000000e1, 0x000000e1 }, - { 0x0000989c, 0x00002081, 0x00002081 }, + { 0x0000989c, 0x00007081, 0x00007081 }, { 0x0000989c, 0x000000d4, 0x000000d4 }, { 0x000098d0, 0x0000000f, 0x0010000f }, }; @@ -648,43 +651,43 @@ static const uint32_t ar5416Bank7[][2] = { }; static const uint32_t ar5416Addac[][2] = { - {0x0989c, 0x00000000 }, - {0x0989c, 0x00000003 }, - {0x0989c, 0x00000000 }, - {0x0989c, 0x0000000c }, - {0x0989c, 0x00000000 }, - {0x0989c, 0x00000030 }, - {0x0989c, 0x00000000 }, - {0x0989c, 0x00000000 }, - {0x0989c, 0x00000000 }, - {0x0989c, 0x00000000 }, - {0x0989c, 0x00000000 }, - {0x0989c, 0x00000000 }, - {0x0989c, 0x00000000 }, - {0x0989c, 0x00000000 }, - {0x0989c, 0x00000000 }, - {0x0989c, 0x00000000 }, - {0x0989c, 0x00000000 }, - {0x0989c, 0x00000000 }, - {0x0989c, 0x00000060 }, - {0x0989c, 0x00000000 }, - {0x0989c, 0x00000000 }, - {0x0989c, 0x00000000 }, - {0x0989c, 0x00000000 }, - {0x0989c, 0x00000000 }, - {0x0989c, 0x00000000 }, - {0x0989c, 0x00000000 }, - {0x0989c, 0x00000000 }, - {0x0989c, 0x00000000 }, - {0x0989c, 0x00000000 }, - {0x0989c, 0x00000000 }, - {0x0989c, 0x00000000 }, - {0x0989c, 0x00000058 }, - {0x0989c, 0x00000000 }, - {0x0989c, 0x00000000 }, - {0x0989c, 0x00000000 }, - {0x0989c, 0x00000000 }, - {0x098c4, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000003 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x0000000c }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000030 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000060 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000058 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x000098c4, 0x00000000 }, }; /* hand-crafted from code that does explicit register writes */ diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416_ani.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416_ani.c index b10296c4e6..5af6b240b6 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416_ani.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416_ani.c @@ -156,6 +156,8 @@ ar5416AniAttach(struct ath_hal *ah, const struct ar5212AniParams *params24, /* * Cleanup any ANI state setup. + * + * This doesn't restore registers to their default settings! */ void ar5416AniDetach(struct ath_hal *ah) @@ -173,16 +175,60 @@ ar5416AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param) typedef int TABLE[]; struct ath_hal_5212 *ahp = AH5212(ah); struct ar5212AniState *aniState = ahp->ah_curani; - const struct ar5212AniParams *params = aniState->params; + const struct ar5212AniParams *params = AH_NULL; + + /* + * This function may be called before there's a current + * channel (eg to disable ANI.) + */ + if (aniState != AH_NULL) + params = aniState->params; OS_MARK(ah, AH_MARK_ANI_CONTROL, cmd); + /* These commands can't be disabled */ + if (cmd == HAL_ANI_PRESENT) + return AH_TRUE; + + if (cmd == HAL_ANI_MODE) { + if (param == 0) { + ahp->ah_procPhyErr &= ~HAL_ANI_ENA; + /* Turn off HW counters if we have them */ + ar5416AniDetach(ah); + } else { /* normal/auto mode */ + /* don't mess with state if already enabled */ + if (! (ahp->ah_procPhyErr & HAL_ANI_ENA)) { + /* Enable MIB Counters */ + /* + * XXX use 2.4ghz params if no channel is + * available + */ + enableAniMIBCounters(ah, + ahp->ah_curani != AH_NULL ? + ahp->ah_curani->params: + &ahp->ah_aniParams24); + ahp->ah_procPhyErr |= HAL_ANI_ENA; + } + } + return AH_TRUE; + } + + /* Check whether the particular function is enabled */ + if (((1 << cmd) & AH5416(ah)->ah_ani_function) == 0) { + HALDEBUG(ah, HAL_DEBUG_ANI, "%s: command %d disabled\n", + __func__, cmd); + HALDEBUG(ah, HAL_DEBUG_ANI, "%s: cmd %d; mask %x\n", __func__, cmd, AH5416(ah)->ah_ani_function); + return AH_FALSE; + } + + switch (cmd) { case HAL_ANI_NOISE_IMMUNITY_LEVEL: { u_int level = param; + HALDEBUG(ah, HAL_DEBUG_ANI, "%s: HAL_ANI_NOISE_IMMUNITY_LEVEL: set level = %d\n", __func__, level); if (level >= params->maxNoiseImmunityLevel) { - HALDEBUG(ah, HAL_DEBUG_ANY, + HALDEBUG(ah, HAL_DEBUG_ANI, "%s: immunity level out of range (%u > %u)\n", __func__, level, params->maxNoiseImmunityLevel); return AH_FALSE; @@ -213,6 +259,7 @@ ar5416AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param) static const TABLE m2CountThrLow = { 63, 48 }; u_int on = param ? 1 : 0; + HALDEBUG(ah, HAL_DEBUG_ANI, "%s: HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION: %s\n", __func__, on ? "enabled" : "disabled"); OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, AR_PHY_SFCORR_LOW_M1_THRESH_LOW, m1ThreshLow[on]); OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, @@ -253,6 +300,7 @@ ar5416AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param) static const TABLE weakSigThrCck = { 8, 6 }; u_int high = param ? 1 : 0; + HALDEBUG(ah, HAL_DEBUG_ANI, "%s: HAL_ANI_CCK_WEAK_SIGNAL_THR: %s\n", __func__, high ? "high" : "low"); OS_REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT, AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK, weakSigThrCck[high]); if (high) @@ -265,8 +313,9 @@ ar5416AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param) case HAL_ANI_FIRSTEP_LEVEL: { u_int level = param; + HALDEBUG(ah, HAL_DEBUG_ANI, "%s: HAL_ANI_FIRSTEP_LEVEL: level = %d\n", __func__, level); if (level >= params->maxFirstepLevel) { - HALDEBUG(ah, HAL_DEBUG_ANY, + HALDEBUG(ah, HAL_DEBUG_ANI, "%s: firstep level out of range (%u > %u)\n", __func__, level, params->maxFirstepLevel); return AH_FALSE; @@ -283,14 +332,21 @@ ar5416AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param) case HAL_ANI_SPUR_IMMUNITY_LEVEL: { u_int level = param; + HALDEBUG(ah, HAL_DEBUG_ANI, "%s: HAL_ANI_SPUR_IMMUNITY_LEVEL: level = %d\n", __func__, level); if (level >= params->maxSpurImmunityLevel) { - HALDEBUG(ah, HAL_DEBUG_ANY, + HALDEBUG(ah, HAL_DEBUG_ANI, "%s: spur immunity level out of range (%u > %u)\n", __func__, level, params->maxSpurImmunityLevel); return AH_FALSE; } OS_REG_RMW_FIELD(ah, AR_PHY_TIMING5, AR_PHY_TIMING5_CYCPWR_THR1, params->cycPwrThr1[level]); + + /* Only set the ext channel cycpwr_thr1 field for ht/40 */ + if (IEEE80211_IS_CHAN_HT40(AH_PRIVATE(ah)->ah_curchan)) + OS_REG_RMW_FIELD(ah, AR_PHY_EXT_CCA, + AR_PHY_EXT_TIMING5_CYCPWR_THR1, params->cycPwrThr1[level]); + if (level > aniState->spurImmunityLevel) ahp->ah_stats.ast_ani_spurup++; else if (level < aniState->spurImmunityLevel) @@ -298,27 +354,6 @@ ar5416AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param) aniState->spurImmunityLevel = level; break; } - case HAL_ANI_PRESENT: - break; - case HAL_ANI_MODE: - if (param == 0) { - ahp->ah_procPhyErr &= ~HAL_ANI_ENA; - /* Turn off HW counters if we have them */ - ar5416AniDetach(ah); - ar5212SetRxFilter(ah, - ar5212GetRxFilter(ah) &~ HAL_RX_FILTER_PHYERR); - } else { /* normal/auto mode */ - /* don't mess with state if already enabled */ - if (ahp->ah_procPhyErr & HAL_ANI_ENA) - break; - ar5212SetRxFilter(ah, - ar5212GetRxFilter(ah) &~ HAL_RX_FILTER_PHYERR); - /* Enable MIB Counters */ - enableAniMIBCounters(ah, ahp->ah_curani != AH_NULL ? - ahp->ah_curani->params: &ahp->ah_aniParams24 /*XXX*/); - ahp->ah_procPhyErr |= HAL_ANI_ENA; - } - break; #ifdef AH_PRIVATE_DIAG case HAL_ANI_PHYERR_RESET: ahp->ah_stats.ast_ani_ofdmerrs = 0; @@ -326,7 +361,7 @@ ar5416AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param) break; #endif /* AH_PRIVATE_DIAG */ default: - HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid cmd %u\n", + HALDEBUG(ah, HAL_DEBUG_ANI, "%s: invalid cmd %u\n", __func__, cmd); return AH_FALSE; } @@ -349,13 +384,15 @@ ar5416AniOfdmErrTrigger(struct ath_hal *ah) aniState = ahp->ah_curani; params = aniState->params; /* First, raise noise immunity level, up to max */ - if (aniState->noiseImmunityLevel+1 < params->maxNoiseImmunityLevel) { + if ((AH5416(ah)->ah_ani_function & (1 << HAL_ANI_NOISE_IMMUNITY_LEVEL)) && + (aniState->noiseImmunityLevel+1 < params->maxNoiseImmunityLevel)) { ar5416AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL, aniState->noiseImmunityLevel + 1); return; } /* then, raise spur immunity level, up to max */ - if (aniState->spurImmunityLevel+1 < params->maxSpurImmunityLevel) { + if ((AH5416(ah)->ah_ani_function & (1 << HAL_ANI_SPUR_IMMUNITY_LEVEL)) && + (aniState->spurImmunityLevel+1 < params->maxSpurImmunityLevel)) { ar5416AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL, aniState->spurImmunityLevel + 1); return; @@ -434,7 +471,8 @@ ar5416AniCckErrTrigger(struct ath_hal *ah) /* first, raise noise immunity level, up to max */ aniState = ahp->ah_curani; params = aniState->params; - if (aniState->noiseImmunityLevel+1 < params->maxNoiseImmunityLevel) { + if ((AH5416(ah)->ah_ani_function & (1 << HAL_ANI_NOISE_IMMUNITY_LEVEL) && + aniState->noiseImmunityLevel+1 < params->maxNoiseImmunityLevel)) { ar5416AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL, aniState->noiseImmunityLevel + 1); return; @@ -481,7 +519,7 @@ ar5416AniRestart(struct ath_hal *ah, struct ar5212AniState *aniState) OS_REG_WRITE(ah, AR_PHY_ERR_1, params->ofdmPhyErrBase); OS_REG_WRITE(ah, AR_PHY_ERR_2, params->cckPhyErrBase); OS_REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING); - OS_REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_CCK_TIMING); + OS_REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); /* Clear the mib counters and save them in the stats */ ar5212UpdateMibCounters(ah, &ahp->ah_mibStats); @@ -530,8 +568,21 @@ ar5416AniReset(struct ath_hal *ah, const struct ieee80211_channel *chan, /* * Turn off PHY error frame delivery while we futz with settings. */ - rxfilter = ar5212GetRxFilter(ah); - ar5212SetRxFilter(ah, rxfilter &~ HAL_RX_FILTER_PHYERR); + rxfilter = ah->ah_getRxFilter(ah); + ah->ah_setRxFilter(ah, rxfilter &~ HAL_RX_FILTER_PHYERR); + + /* + * If ANI is disabled at this point, don't set the default + * ANI parameter settings - leave the HAL settings there. + * This is (currently) needed for reliable radar detection. + */ + if (! ANI_ENA(ah)) { + HALDEBUG(ah, HAL_DEBUG_ANI, "%s: ANI disabled\n", + __func__); + goto finish; + } + + /* * Automatic processing is done only in station mode right now. */ @@ -565,10 +616,16 @@ ar5416AniReset(struct ath_hal *ah, const struct ieee80211_channel *chan, ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, 0); ichan->privFlags |= CHANNEL_ANI_SETUP; } + + /* + * In case the counters haven't yet been setup; set them up. + */ + enableAniMIBCounters(ah, aniState->params); ar5416AniRestart(ah, aniState); +finish: /* restore RX filter mask */ - ar5212SetRxFilter(ah, rxfilter); + ah->ah_setRxFilter(ah, rxfilter); } /* @@ -793,21 +850,26 @@ updateMIBStats(struct ath_hal *ah, struct ar5212AniState *aniState) aniState->cckPhyErrCount = cckPhyErrCnt; } +void +ar5416RxMonitor(struct ath_hal *ah, const HAL_NODE_STATS *stats, + const struct ieee80211_channel *chan) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + ahp->ah_stats.ast_nodestats.ns_avgbrssi = stats->ns_avgbrssi; +} + /* * Do periodic processing. This routine is called from the * driver's rx interrupt handler after processing frames. */ void -ar5416AniPoll(struct ath_hal *ah, const HAL_NODE_STATS *stats, - const struct ieee80211_channel *chan) +ar5416AniPoll(struct ath_hal *ah, const struct ieee80211_channel *chan) { struct ath_hal_5212 *ahp = AH5212(ah); struct ar5212AniState *aniState = ahp->ah_curani; const struct ar5212AniParams *params; int32_t listenTime; - ahp->ah_stats.ast_nodestats.ns_avgbrssi = stats->ns_avgbrssi; - /* XXX can aniState be null? */ if (aniState == AH_NULL) return; @@ -843,10 +905,16 @@ ar5416AniPoll(struct ath_hal *ah, const HAL_NODE_STATS *stats, /* check to see if need to raise immunity */ if (aniState->ofdmPhyErrCount > aniState->listenTime * params->ofdmTrigHigh / 1000) { + HALDEBUG(ah, HAL_DEBUG_ANI, + "%s: OFDM err %u listenTime %u\n", __func__, + aniState->ofdmPhyErrCount, aniState->listenTime); ar5416AniOfdmErrTrigger(ah); ar5416AniRestart(ah, aniState); } else if (aniState->cckPhyErrCount > aniState->listenTime * params->cckTrigHigh / 1000) { + HALDEBUG(ah, HAL_DEBUG_ANI, + "%s: CCK err %u listenTime %u\n", __func__, + aniState->ofdmPhyErrCount, aniState->listenTime); ar5416AniCckErrTrigger(ah); ar5416AniRestart(ah, aniState); } diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416_attach.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416_attach.c index a0bf7bdd62..12589f28ff 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416_attach.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416_attach.c @@ -57,8 +57,22 @@ ar5416AniSetup(struct ath_hal *ah) .rssiThrLow = 7, .period = 100, }; - /* NB: ANI is not enabled yet */ - ar5212AniAttach(ah, &aniparams, &aniparams, AH_FALSE); + /* NB: disable ANI noise immmunity for reliable RIFS rx */ + AH5416(ah)->ah_ani_function &= ~(1 << HAL_ANI_NOISE_IMMUNITY_LEVEL); + ar5416AniAttach(ah, &aniparams, &aniparams, AH_TRUE); +} + +/* + * AR5416 doesn't do OLC or temperature compensation. + */ +static void +ar5416olcInit(struct ath_hal *ah) +{ +} + +static void +ar5416olcTempCompensation(struct ath_hal *ah) +{ } /* @@ -98,16 +112,23 @@ ar5416InitState(struct ath_hal_5416 *ahp5416, uint16_t devid, HAL_SOFTC sc, ah->ah_setupXTxDesc = ar5416SetupXTxDesc; ah->ah_fillTxDesc = ar5416FillTxDesc; ah->ah_procTxDesc = ar5416ProcTxDesc; + ah->ah_getTxCompletionRates = ar5416GetTxCompletionRates; + ah->ah_setupTxQueue = ar5416SetupTxQueue; + ah->ah_resetTxQueue = ar5416ResetTxQueue; /* Receive Functions */ + ah->ah_getRxFilter = ar5416GetRxFilter; + ah->ah_setRxFilter = ar5416SetRxFilter; ah->ah_startPcuReceive = ar5416StartPcuReceive; ah->ah_stopPcuReceive = ar5416StopPcuReceive; ah->ah_setupRxDesc = ar5416SetupRxDesc; ah->ah_procRxDesc = ar5416ProcRxDesc; - ah->ah_rxMonitor = ar5416AniPoll, - ah->ah_procMibEvent = ar5416ProcessMibIntr, + ah->ah_rxMonitor = ar5416RxMonitor; + ah->ah_aniPoll = ar5416AniPoll; + ah->ah_procMibEvent = ar5416ProcessMibIntr; /* Misc Functions */ + ah->ah_getCapability = ar5416GetCapability; ah->ah_getDiagState = ar5416GetDiagState; ah->ah_setLedState = ar5416SetLedState; ah->ah_gpioCfgOutput = ar5416GpioCfgOutput; @@ -115,15 +136,23 @@ ar5416InitState(struct ath_hal_5416 *ahp5416, uint16_t devid, HAL_SOFTC sc, ah->ah_gpioGet = ar5416GpioGet; ah->ah_gpioSet = ar5416GpioSet; ah->ah_gpioSetIntr = ar5416GpioSetIntr; + ah->ah_getTsf64 = ar5416GetTsf64; ah->ah_resetTsf = ar5416ResetTsf; ah->ah_getRfGain = ar5416GetRfgain; ah->ah_setAntennaSwitch = ar5416SetAntennaSwitch; ah->ah_setDecompMask = ar5416SetDecompMask; ah->ah_setCoverageClass = ar5416SetCoverageClass; + ah->ah_setQuiet = ar5416SetQuiet; ah->ah_resetKeyCacheEntry = ar5416ResetKeyCacheEntry; ah->ah_setKeyCacheEntry = ar5416SetKeyCacheEntry; + /* DFS Functions */ + ah->ah_enableDfs = ar5416EnableDfs; + ah->ah_getDfsThresh = ar5416GetDfsThresh; + ah->ah_procRadarEvent = ar5416ProcessRadarEvent; + ah->ah_isFastClockEnabled = ar5416IsFastClockEnabled; + /* Power Management Functions */ ah->ah_setPowerMode = ar5416SetPowerMode; @@ -132,9 +161,9 @@ ar5416InitState(struct ath_hal_5416 *ahp5416, uint16_t devid, HAL_SOFTC sc, ah->ah_beaconInit = ar5416BeaconInit; ah->ah_setStationBeaconTimers = ar5416SetStaBeaconTimers; ah->ah_resetStationBeaconTimers = ar5416ResetStaBeaconTimers; + ah->ah_getNextTBTT = ar5416GetNextTBTT; - /* XXX 802.11n Functions */ -#if 0 + /* 802.11n Functions */ ah->ah_chainTxDesc = ar5416ChainTxDesc; ah->ah_setupFirstTxDesc = ar5416SetupFirstTxDesc; ah->ah_setupLastTxDesc = ar5416SetupLastTxDesc; @@ -146,7 +175,6 @@ ar5416InitState(struct ath_hal_5416 *ahp5416, uint16_t devid, HAL_SOFTC sc, ah->ah_set11nMac2040 = ar5416Set11nMac2040; ah->ah_get11nRxClear = ar5416Get11nRxClear; ah->ah_set11nRxClear = ar5416Set11nRxClear; -#endif /* Interrupt functions */ ah->ah_isInterruptPending = ar5416IsInterruptPending; @@ -160,13 +188,32 @@ ar5416InitState(struct ath_hal_5416 *ahp5416, uint16_t devid, HAL_SOFTC sc, #endif ahp->ah_priv.ah_getChipPowerLimits = ar5416GetChipPowerLimits; + /* Internal ops */ AH5416(ah)->ah_writeIni = ar5416WriteIni; AH5416(ah)->ah_spurMitigate = ar5416SpurMitigate; + + /* Internal baseband ops */ + AH5416(ah)->ah_initPLL = ar5416InitPLL; + + /* Internal calibration ops */ + AH5416(ah)->ah_cal_initcal = ar5416InitCalHardware; + + /* Internal TX power control related operations */ + AH5416(ah)->ah_olcInit = ar5416olcInit; + AH5416(ah)->ah_olcTempCompensation = ar5416olcTempCompensation; + AH5416(ah)->ah_setPowerCalTable = ar5416SetPowerCalTable; + /* * Start by setting all Owl devices to 2x2 */ AH5416(ah)->ah_rx_chainmask = AR5416_DEFAULT_RXCHAINMASK; AH5416(ah)->ah_tx_chainmask = AR5416_DEFAULT_TXCHAINMASK; + + /* Enable all ANI functions to begin with */ + AH5416(ah)->ah_ani_function = 0xffffffff; + + /* Set overridable ANI methods */ + AH5212(ah)->ah_aniControl = ar5416AniControl; } uint32_t @@ -189,7 +236,8 @@ ar5416GetRadioRev(struct ath_hal *ah) */ static struct ath_hal * ar5416Attach(uint16_t devid, HAL_SOFTC sc, - HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status) + HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata, + HAL_STATUS *status) { struct ath_hal_5416 *ahp5416; struct ath_hal_5212 *ahp; @@ -198,7 +246,7 @@ ar5416Attach(uint16_t devid, HAL_SOFTC sc, HAL_STATUS ecode; HAL_BOOL rfStatus; - HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", + HALDEBUG_G(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", __func__, sc, (void*) st, (void*) sh); /* NB: memory is returned zero'd */ @@ -207,7 +255,7 @@ ar5416Attach(uint16_t devid, HAL_SOFTC sc, sizeof(ar5416Addac) ); if (ahp5416 == AH_NULL) { - HALDEBUG(AH_NULL, HAL_DEBUG_ANY, + HALDEBUG_G(AH_NULL, HAL_DEBUG_ANY, "%s: cannot allocate memory for state block\n", __func__); *status = HAL_ENOMEM; return AH_NULL; @@ -247,7 +295,8 @@ ar5416Attach(uint16_t devid, HAL_SOFTC sc, HAL_INI_INIT(&AH5416(ah)->ah_ini_bank7, ar5416Bank7, 2); HAL_INI_INIT(&AH5416(ah)->ah_ini_addac, ar5416Addac, 2); - if (!IS_5416V2_2(ah)) { /* Owl 2.1/2.0 */ + if (! IS_5416V2_2(ah)) { /* Owl 2.1/2.0 */ + ath_hal_printf(ah, "[ath] Enabling CLKDRV workaround for AR5416 < v2.2\n"); struct ini { uint32_t *data; /* NB: !const */ int rows, cols; @@ -336,6 +385,8 @@ ar5416Attach(uint16_t devid, HAL_SOFTC sc, /* Read Reg Domain */ AH_PRIVATE(ah)->ah_currentRD = ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, AH_NULL); + AH_PRIVATE(ah)->ah_currentRDext = + ath_hal_eepromGet(ah, AR_EEP_REGDMN_1, AH_NULL); /* * ah_miscMode is populated by ar5416FillCapabilityInfo() @@ -344,7 +395,7 @@ ar5416Attach(uint16_t devid, HAL_SOFTC sc, * placed into hardware. */ if (ahp->ah_miscMode != 0) - OS_REG_WRITE(ah, AR_MISC_MODE, ahp->ah_miscMode); + OS_REG_WRITE(ah, AR_MISC_MODE, OS_REG_READ(ah, AR_MISC_MODE) | ahp->ah_miscMode); rfStatus = ar2133RfAttach(ah, &ecode); if (!rfStatus) { @@ -354,6 +405,14 @@ ar5416Attach(uint16_t devid, HAL_SOFTC sc, } ar5416AniSetup(ah); /* Anti Noise Immunity */ + + AH5416(ah)->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_5416_2GHZ; + AH5416(ah)->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_5416_2GHZ; + AH5416(ah)->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_5416_2GHZ; + AH5416(ah)->nf_5g.max = AR_PHY_CCA_MAX_GOOD_VAL_5416_5GHZ; + AH5416(ah)->nf_5g.min = AR_PHY_CCA_MIN_GOOD_VAL_5416_5GHZ; + AH5416(ah)->nf_5g.nominal = AR_PHY_CCA_NOM_VAL_5416_5GHZ; + ar5416InitNfHistBuff(AH5416(ah)->ah_cal.nfCalHist); HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__); @@ -375,6 +434,12 @@ ar5416Detach(struct ath_hal *ah) HALASSERT(ah != AH_NULL); HALASSERT(ah->ah_magic == AR5416_MAGIC); + /* Make sure that chip is awake before writing to it */ + if (! ar5416SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) + HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, + "%s: failed to wake up chip\n", + __func__); + ar5416AniDetach(ah); ar5212RfDetach(ah); ah->ah_disable(ah); @@ -435,10 +500,11 @@ ar5416WriteIni(struct ath_hal *ah, const struct ieee80211_channel *chan) * Write addac shifts */ OS_REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_EXTERNAL_RADIO); -#if 0 + /* NB: only required for Sowl */ - ar5416EepromSetAddac(ah, chan); -#endif + if (AR_SREV_SOWL(ah)) + ar5416EepromSetAddac(ah, chan); + regWrites = ath_hal_ini_write(ah, &AH5416(ah)->ah_ini_addac, 1, regWrites); OS_REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC); @@ -764,8 +830,9 @@ ar5416FillCapabilityInfo(struct ath_hal *ah) pCap->halPSPollBroken = AH_TRUE; /* XXX fixed in later revs? */ pCap->halVEOLSupport = AH_TRUE; pCap->halBssIdMaskSupport = AH_TRUE; - pCap->halMcastKeySrchSupport = AH_FALSE; + pCap->halMcastKeySrchSupport = AH_TRUE; /* Works on AR5416 and later */ pCap->halTsfAddSupport = AH_TRUE; + pCap->hal4AddrAggrSupport = AH_FALSE; /* Broken in Owl */ if (ath_hal_eepromGet(ah, AR_EEP_MAXQCU, &val) == HAL_OK) pCap->halTotalQueues = val; @@ -801,6 +868,9 @@ ar5416FillCapabilityInfo(struct ath_hal *ah) pCap->halWowMatchPatternExact = AH_FALSE; pCap->halBtCoexSupport = AH_FALSE; /* XXX need support */ pCap->halAutoSleepSupport = AH_FALSE; + pCap->hal4kbSplitTransSupport = AH_TRUE; + /* Disable this so Block-ACK works correctly */ + pCap->halHasRxSelfLinkedTail = AH_FALSE; #if 0 /* XXX not yet */ pCap->halNumAntCfg2GHz = ar5416GetNumAntConfig(ahp, HAL_FREQ_BAND_2GHZ); pCap->halNumAntCfg5GHz = ar5416GetNumAntConfig(ahp, HAL_FREQ_BAND_5GHZ); @@ -809,11 +879,19 @@ ar5416FillCapabilityInfo(struct ath_hal *ah) pCap->halTxChainMask = ath_hal_eepromGet(ah, AR_EEP_TXMASK, AH_NULL); /* XXX CB71 uses GPIO 0 to indicate 3 rx chains */ pCap->halRxChainMask = ath_hal_eepromGet(ah, AR_EEP_RXMASK, AH_NULL); + /* AR5416 may have 3 antennas but is a 2x2 stream device */ + pCap->halTxStreams = 2; + pCap->halRxStreams = 2; pCap->halRtsAggrLimit = 8*1024; /* Owl 2.0 limit */ - pCap->halMbssidAggrSupport = AH_TRUE; + pCap->halMbssidAggrSupport = AH_FALSE; /* Broken on Owl */ pCap->halForcePpmSupport = AH_TRUE; pCap->halEnhancedPmSupport = AH_TRUE; pCap->halBssidMatchSupport = AH_TRUE; + pCap->halGTTSupport = AH_TRUE; + pCap->halCSTSupport = AH_TRUE; + pCap->halEnhancedDfsSupport = AH_FALSE; + /* Hardware supports 32 bit TSF values in the RX descriptor */ + pCap->halHasLongRxDescTsf = AH_TRUE; if (ath_hal_eepromGetFlag(ah, AR_EEP_RFKILL) && ath_hal_eepromGet(ah, AR_EEP_RFSILENT, &ahpriv->ah_rfsilent) == HAL_OK) { diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416_beacon.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416_beacon.c index 358a0eed24..8b61e14658 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416_beacon.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416_beacon.c @@ -26,6 +26,16 @@ #include "ar5416/ar5416phy.h" #define TU_TO_USEC(_tu) ((_tu) << 10) +#define ONE_EIGHTH_TU_TO_USEC(_tu8) ((_tu8) << 7) + +/* + * Return the hardware NextTBTT in TSF + */ +uint64_t +ar5416GetNextTBTT(struct ath_hal *ah) +{ + return OS_REG_READ(ah, AR_NEXT_TBTT); +} /* * Initialize all of the hardware registers used to @@ -38,8 +48,8 @@ ar5416SetBeaconTimers(struct ath_hal *ah, const HAL_BEACON_TIMERS *bt) uint32_t bperiod; OS_REG_WRITE(ah, AR_NEXT_TBTT, TU_TO_USEC(bt->bt_nexttbtt)); - OS_REG_WRITE(ah, AR_NEXT_DBA, TU_TO_USEC(bt->bt_nextdba) >> 3); - OS_REG_WRITE(ah, AR_NEXT_SWBA, TU_TO_USEC(bt->bt_nextswba) >> 3); + OS_REG_WRITE(ah, AR_NEXT_DBA, ONE_EIGHTH_TU_TO_USEC(bt->bt_nextdba)); + OS_REG_WRITE(ah, AR_NEXT_SWBA, ONE_EIGHTH_TU_TO_USEC(bt->bt_nextswba)); OS_REG_WRITE(ah, AR_NEXT_NDP, TU_TO_USEC(bt->bt_nextatim)); bperiod = TU_TO_USEC(bt->bt_intval & HAL_BEACON_PERIOD); @@ -93,9 +103,9 @@ ar5416BeaconInit(struct ath_hal *ah, /* fall thru... */ case HAL_M_HOSTAP: bt.bt_nextdba = (next_beacon - - ath_hal_dma_beacon_response_time) << 3; /* 1/8 TU */ + ah->ah_config.ah_dma_beacon_response_time) << 3; /* 1/8 TU */ bt.bt_nextswba = (next_beacon - - ath_hal_sw_beacon_response_time) << 3; /* 1/8 TU */ + ah->ah_config.ah_sw_beacon_response_time) << 3; /* 1/8 TU */ bt.bt_flags |= AR_TIMER_MODE_TBTT | AR_TIMER_MODE_DBA | AR_TIMER_MODE_SWBA; @@ -144,7 +154,7 @@ ar5416SetStaBeaconTimers(struct ath_hal *ah, const HAL_BEACON_STATE *bs) /* NB: no cfp setting since h/w automatically takes care */ - OS_REG_WRITE(ah, AR_NEXT_TBTT, bs->bs_nexttbtt); + OS_REG_WRITE(ah, AR_NEXT_TBTT, TU_TO_USEC(bs->bs_nexttbtt)); /* * Start the beacon timers by setting the BEACON register @@ -221,15 +231,19 @@ ar5416SetStaBeaconTimers(struct ath_hal *ah, const HAL_BEACON_STATE *bs) OS_REG_WRITE(ah, AR_NEXT_TIM, TU_TO_USEC(nextTbtt - SLEEP_SLOP)); /* cab timeout is now in 1/8 TU */ - OS_REG_WRITE(ah, AR_SLEEP1, + OS_REG_WRITE(ah, AR5416_SLEEP1, SM((CAB_TIMEOUT_VAL << 3), AR5416_SLEEP1_CAB_TIMEOUT) - | AR_SLEEP1_ASSUME_DTIM); + | AR5416_SLEEP1_ASSUME_DTIM); + + /* XXX autosleep? Use min beacon timeout; check ath9k -adrian */ /* beacon timeout is now in 1/8 TU */ - OS_REG_WRITE(ah, AR_SLEEP2, + OS_REG_WRITE(ah, AR5416_SLEEP2, SM((BEACON_TIMEOUT_VAL << 3), AR5416_SLEEP2_BEACON_TIMEOUT)); - OS_REG_WRITE(ah, AR_TIM_PERIOD, beaconintval); - OS_REG_WRITE(ah, AR_DTIM_PERIOD, dtimperiod); + /* TIM_PERIOD and DTIM_PERIOD are now in uS. */ + OS_REG_WRITE(ah, AR_TIM_PERIOD, TU_TO_USEC(beaconintval)); + OS_REG_WRITE(ah, AR_DTIM_PERIOD, TU_TO_USEC(dtimperiod)); + OS_REG_SET_BIT(ah, AR_TIMER_MODE, AR_TIMER_MODE_TBTT | AR_TIMER_MODE_TIM | AR_TIMER_MODE_DTIM); HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: next DTIM %d\n", diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416_cal.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416_cal.c index 712f7e0568..d51417f499 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416_cal.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416_cal.c @@ -24,6 +24,8 @@ #include "ah_eeprom_v14.h" +#include "ar5212/ar5212.h" /* for NF cal related declarations */ + #include "ar5416/ar5416.h" #include "ar5416/ar5416reg.h" #include "ar5416/ar5416phy.h" @@ -35,9 +37,29 @@ static void ar5416StartNFCal(struct ath_hal *ah); static void ar5416LoadNF(struct ath_hal *ah, const struct ieee80211_channel *); static int16_t ar5416GetNf(struct ath_hal *, struct ieee80211_channel *); +static uint16_t ar5416GetDefaultNF(struct ath_hal *ah, const struct ieee80211_channel *chan); +static void ar5416SanitizeNF(struct ath_hal *ah, int16_t *nf); + /* * Determine if calibration is supported by device and channel flags */ + +/* + * ADC GAIN/DC offset calibration is for calibrating two ADCs that + * are acting as one by interleaving incoming symbols. This isn't + * relevant for 2.4GHz 20MHz wide modes because, as far as I can tell, + * the secondary ADC is never enabled. It is enabled however for + * 5GHz modes. + * + * It hasn't been confirmed whether doing this calibration is needed + * at all in the above modes and/or whether it's actually harmful. + * So for now, let's leave it enabled and just remember to get + * confirmation that it needs to be clarified. + * + * See US Patent No: US 7,541,952 B1: + * " Method and Apparatus for Offset and Gain Compensation for + * Analog-to-Digital Converters." + */ static OS_INLINE HAL_BOOL ar5416IsCalSupp(struct ath_hal *ah, const struct ieee80211_channel *chan, HAL_CAL_TYPE calType) @@ -50,9 +72,20 @@ ar5416IsCalSupp(struct ath_hal *ah, const struct ieee80211_channel *chan, return !IEEE80211_IS_CHAN_B(chan); case ADC_GAIN_CAL: case ADC_DC_CAL: - /* Run ADC Gain Cal for non-CCK & non 2GHz-HT20 only */ - return !IEEE80211_IS_CHAN_B(chan) && - !(IEEE80211_IS_CHAN_2GHZ(chan) && IEEE80211_IS_CHAN_HT20(chan)); + /* + * Run ADC Gain Cal for either 5ghz any or 2ghz HT40. + * + * Don't run ADC calibrations for 5ghz fast clock mode + * in HT20 - only one ADC is used. + */ + if (IEEE80211_IS_CHAN_HT20(chan) && + (IS_5GHZ_FAST_CLOCK_EN(ah, chan))) + return AH_FALSE; + if (IEEE80211_IS_CHAN_5GHZ(chan)) + return AH_TRUE; + if (IEEE80211_IS_CHAN_HT40(chan)) + return AH_TRUE; + return AH_FALSE; } return AH_FALSE; } @@ -161,45 +194,22 @@ ar5416RunInitCals(struct ath_hal *ah, int init_cal_count) } #endif + /* - * Initialize Calibration infrastructure. + * AGC calibration for the AR5416, AR9130, AR9160, AR9280. */ HAL_BOOL -ar5416InitCal(struct ath_hal *ah, const struct ieee80211_channel *chan) +ar5416InitCalHardware(struct ath_hal *ah, const struct ieee80211_channel *chan) { - struct ar5416PerCal *cal = &AH5416(ah)->ah_cal; - HAL_CHANNEL_INTERNAL *ichan; - - ichan = ath_hal_checkchannel(ah, chan); - HALASSERT(ichan != AH_NULL); if (AR_SREV_MERLIN_10_OR_LATER(ah)) { + /* Disable ADC */ + OS_REG_CLR_BIT(ah, AR_PHY_ADC_CTL, + AR_PHY_ADC_CTL_OFF_PWDADC); + /* Enable Rx Filter Cal */ - OS_REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); - - /* Clear the carrier leak cal bit */ - OS_REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); - - /* kick off the cal */ - OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL); - - /* Poll for offset calibration complete */ - if (!ath_hal_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0)) { - HALDEBUG(ah, HAL_DEBUG_ANY, - "%s: offset calibration failed to complete in 1ms; " - "noisy environment?\n", __func__); - return AH_FALSE; - } - - /* Set the cl cal bit and rerun the cal a 2nd time */ - /* Enable Rx Filter Cal */ - OS_REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); - OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, - AR_PHY_AGC_CONTROL_FLTR_CAL); - - OS_REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); } /* Calibrate the AGC */ @@ -213,6 +223,44 @@ ar5416InitCal(struct ath_hal *ah, const struct ieee80211_channel *chan) return AH_FALSE; } + if (AR_SREV_MERLIN_10_OR_LATER(ah)) { + /* Enable ADC */ + OS_REG_SET_BIT(ah, AR_PHY_ADC_CTL, + AR_PHY_ADC_CTL_OFF_PWDADC); + + /* Disable Rx Filter Cal */ + OS_REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, + AR_PHY_AGC_CONTROL_FLTR_CAL); + } + + return AH_TRUE; +} + +/* + * Initialize Calibration infrastructure. + */ +#define MAX_CAL_CHECK 32 +HAL_BOOL +ar5416InitCal(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + struct ar5416PerCal *cal = &AH5416(ah)->ah_cal; + HAL_CHANNEL_INTERNAL *ichan; + + ichan = ath_hal_checkchannel(ah, chan); + HALASSERT(ichan != AH_NULL); + + /* Do initial chipset-specific calibration */ + if (! AH5416(ah)->ah_cal_initcal(ah, chan)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: initial chipset calibration did " + "not complete in time; noisy environment?\n", __func__); + return AH_FALSE; + } + + /* If there's PA Cal, do it */ + if (AH5416(ah)->ah_cal_pacal) + AH5416(ah)->ah_cal_pacal(ah, AH_TRUE); + /* * Do NF calibration after DC offset and other CALs. * Per system engineers, noise floor value can sometimes be 20 dB @@ -221,13 +269,20 @@ ar5416InitCal(struct ath_hal *ah, const struct ieee80211_channel *chan) */ OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); + /* + * This may take a while to run; make sure subsequent + * calibration routines check that this has completed + * before reading the value and triggering a subsequent + * calibration. + */ + /* Initialize list pointers */ cal->cal_list = cal->cal_last = cal->cal_curr = AH_NULL; /* * Enable IQ, ADC Gain, ADC DC Offset Cals */ - if (AR_SREV_SOWL_10_OR_LATER(ah)) { + if (AR_SREV_HOWL(ah) || AR_SREV_SOWL_10_OR_LATER(ah)) { /* Setup all non-periodic, init time only calibrations */ /* XXX: Init DC Offset not working yet */ #if 0 @@ -273,6 +328,7 @@ ar5416InitCal(struct ath_hal *ah, const struct ieee80211_channel *chan) ichan->calValid = 0; return AH_TRUE; +#undef MAX_CAL_CHECK } /* @@ -391,11 +447,19 @@ ar5416PerCalibrationN(struct ath_hal *ah, struct ieee80211_channel *chan, struct ar5416PerCal *cal = &AH5416(ah)->ah_cal; HAL_CAL_LIST *currCal = cal->cal_curr; HAL_CHANNEL_INTERNAL *ichan; + int r; OS_MARK(ah, AH_MARK_PERCAL, chan->ic_freq); *isCalDone = AH_TRUE; + /* + * Since ath_hal calls the PerCal method with rxchainmask=0x1; + * override it with the current chainmask. The upper levels currently + * doesn't know about the chainmask. + */ + rxchainmask = AH5416(ah)->ah_rx_chainmask; + /* Invalid channel check */ ichan = ath_hal_checkchannel(ah, chan); if (ichan == AH_NULL) { @@ -429,21 +493,36 @@ ar5416PerCalibrationN(struct ath_hal *ah, struct ieee80211_channel *chan, /* Do NF cal only at longer intervals */ if (longcal) { + /* Do PA calibration if the chipset supports */ + if (AH5416(ah)->ah_cal_pacal) + AH5416(ah)->ah_cal_pacal(ah, AH_FALSE); + + /* Do open-loop temperature compensation if the chipset needs it */ + if (ath_hal_eepromGetFlag(ah, AR_EEP_OL_PWRCTRL)) + AH5416(ah)->ah_olcTempCompensation(ah); + /* * Get the value from the previous NF cal * and update the history buffer. */ - ar5416GetNf(ah, chan); + r = ar5416GetNf(ah, chan); + if (r == 0 || r == -1) { + /* NF calibration result isn't valid */ + HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "%s: NF calibration" + " didn't finish; delaying CCA\n", __func__); + } else { + /* + * NF calibration result is valid. + * + * Load the NF from history buffer of the current channel. + * NF is slow time-variant, so it is OK to use a + * historical value. + */ + ar5416LoadNF(ah, AH_PRIVATE(ah)->ah_curchan); - /* - * Load the NF from history buffer of the current channel. - * NF is slow time-variant, so it is OK to use a - * historical value. - */ - ar5416LoadNF(ah, AH_PRIVATE(ah)->ah_curchan); - - /* start NF calibration, without updating BB NF register*/ - ar5416StartNFCal(ah); + /* start NF calibration, without updating BB NF register*/ + ar5416StartNFCal(ah); + } } return AH_TRUE; } @@ -509,9 +588,10 @@ ar5416LoadNF(struct ath_hal *ah, const struct ieee80211_channel *chan) AR_PHY_CH2_EXT_CCA }; struct ar5212NfCalHist *h; - int i, j; + int i; int32_t val; uint8_t chainmask; + int16_t default_nf = ar5416GetDefaultNF(ah, chan); /* * Force NF calibration for all chains. @@ -519,8 +599,8 @@ ar5416LoadNF(struct ath_hal *ah, const struct ieee80211_channel *chan) if (AR_SREV_KITE(ah)) { /* Kite has only one chain */ chainmask = 0x9; - } else if (AR_SREV_MERLIN(ah)) { - /* Merlin has only two chains */ + } else if (AR_SREV_MERLIN(ah) || AR_SREV_KIWI(ah)) { + /* Merlin/Kiwi has only two chains */ chainmask = 0x1B; } else { chainmask = 0x3F; @@ -531,13 +611,30 @@ ar5416LoadNF(struct ath_hal *ah, const struct ieee80211_channel *chan) * so we can load below. */ h = AH5416(ah)->ah_cal.nfCalHist; - for (i = 0; i < AR5416_NUM_NF_READINGS; i ++) + HALDEBUG(ah, HAL_DEBUG_NFCAL, "CCA: "); + for (i = 0; i < AR5416_NUM_NF_READINGS; i ++) { + + /* Don't write to EXT radio CCA registers unless in HT/40 mode */ + /* XXX this check should really be cleaner! */ + if (i > 2 && !IEEE80211_IS_CHAN_HT40(chan)) + continue; + if (chainmask & (1 << i)) { + int16_t nf_val; + + if (h) + nf_val = h[i].privNF; + else + nf_val = default_nf; + val = OS_REG_READ(ah, ar5416_cca_regs[i]); val &= 0xFFFFFE00; - val |= (((uint32_t)(h[i].privNF) << 1) & 0x1ff); + val |= (((uint32_t) nf_val << 1) & 0x1ff); + HALDEBUG(ah, HAL_DEBUG_NFCAL, "[%d: %d]", i, nf_val); OS_REG_WRITE(ah, ar5416_cca_regs[i], val); } + } + HALDEBUG(ah, HAL_DEBUG_NFCAL, "\n"); /* Load software filtered NF value into baseband internal minCCApwr variable. */ OS_REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_ENABLE_NF); @@ -545,10 +642,20 @@ ar5416LoadNF(struct ath_hal *ah, const struct ieee80211_channel *chan) OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); /* Wait for load to complete, should be fast, a few 10s of us. */ - for (j = 0; j < 1000; j++) { - if ((OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) == 0) - break; - OS_DELAY(10); + if (! ar5212WaitNFCalComplete(ah, 1000)) { + /* + * We timed out waiting for the noisefloor to load, probably due to an + * in-progress rx. Simply return here and allow the load plenty of time + * to complete before the next calibration interval. We need to avoid + * trying to load -50 (which happens below) while the previous load is + * still in progress as this can cause rx deafness. Instead by returning + * here, the baseband nf cal will just be capped by our present + * noisefloor until the next calibration timer. + */ + HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "Timeout while waiting for " + "nf to load: AR_PHY_AGC_CONTROL=0x%x\n", + OS_REG_READ(ah, AR_PHY_AGC_CONTROL)); + return; } /* @@ -557,6 +664,12 @@ ar5416LoadNF(struct ath_hal *ah, const struct ieee80211_channel *chan) * of next noise floor calibration the baseband does. */ for (i = 0; i < AR5416_NUM_NF_READINGS; i ++) + + /* Don't write to EXT radio CCA registers unless in HT/40 mode */ + /* XXX this check should really be cleaner! */ + if (i > 2 && !IEEE80211_IS_CHAN_HT40(chan)) + continue; + if (chainmask & (1 << i)) { val = OS_REG_READ(ah, ar5416_cca_regs[i]); val &= 0xFFFFFE00; @@ -565,6 +678,11 @@ ar5416LoadNF(struct ath_hal *ah, const struct ieee80211_channel *chan) } } +/* + * This just initialises the "good" values for AR5416 which + * may not be right; it'lll be overridden by ar5416SanitizeNF() + * to nominal values. + */ void ar5416InitNfHistBuff(struct ar5212NfCalHist *h) { @@ -583,10 +701,12 @@ ar5416InitNfHistBuff(struct ar5212NfCalHist *h) * Update the noise floor buffer as a ring buffer */ static void -ar5416UpdateNFHistBuff(struct ar5212NfCalHist *h, int16_t *nfarray) +ar5416UpdateNFHistBuff(struct ath_hal *ah, struct ar5212NfCalHist *h, + int16_t *nfarray) { int i; + /* XXX TODO: don't record nfarray[] entries for inactive chains */ for (i = 0; i < AR5416_NUM_NF_READINGS; i ++) { h[i].nfCalBuffer[h[i].currIndex] = nfarray[i]; @@ -606,18 +726,68 @@ ar5416UpdateNFHistBuff(struct ar5212NfCalHist *h, int16_t *nfarray) } } +static uint16_t +ar5416GetDefaultNF(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + struct ar5416NfLimits *limit; + + if (!chan || IEEE80211_IS_CHAN_2GHZ(chan)) + limit = &AH5416(ah)->nf_2g; + else + limit = &AH5416(ah)->nf_5g; + + return limit->nominal; +} + +static void +ar5416SanitizeNF(struct ath_hal *ah, int16_t *nf) +{ + + struct ar5416NfLimits *limit; + int i; + + if (IEEE80211_IS_CHAN_2GHZ(AH_PRIVATE(ah)->ah_curchan)) + limit = &AH5416(ah)->nf_2g; + else + limit = &AH5416(ah)->nf_5g; + + for (i = 0; i < AR5416_NUM_NF_READINGS; i++) { + if (!nf[i]) + continue; + + if (nf[i] > limit->max) { + HALDEBUG(ah, HAL_DEBUG_NFCAL, + "NF[%d] (%d) > MAX (%d), correcting to MAX\n", + i, nf[i], limit->max); + nf[i] = limit->max; + } else if (nf[i] < limit->min) { + HALDEBUG(ah, HAL_DEBUG_NFCAL, + "NF[%d] (%d) < MIN (%d), correcting to NOM\n", + i, nf[i], limit->min); + nf[i] = limit->nominal; + } + } +} + + /* * Read the NF and check it against the noise floor threshhold + * + * Return 0 if the NF calibration hadn't finished, 0 if it was + * invalid, or > 0 for a valid NF reading. */ static int16_t ar5416GetNf(struct ath_hal *ah, struct ieee80211_channel *chan) { int16_t nf, nfThresh; + int i; + int retval = 0; - if (OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) { + if (ar5212IsNFCalInProgress(ah)) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: NF didn't complete in calibration window\n", __func__); nf = 0; + retval = -1; /* NF didn't finish */ } else { /* Finished NF cal, check against threshold */ int16_t nfarray[NUM_NOISEFLOOR_READINGS] = { 0 }; @@ -626,9 +796,10 @@ ar5416GetNf(struct ath_hal *ah, struct ieee80211_channel *chan) /* TODO - enhance for multiple chains and ext ch */ ath_hal_getNoiseFloor(ah, nfarray); nf = nfarray[0]; + ar5416SanitizeNF(ah, nfarray); if (ar5416GetEepromNoiseFloorThresh(ah, chan, &nfThresh)) { if (nf > nfThresh) { - HALDEBUG(ah, HAL_DEBUG_ANY, + HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "%s: noise floor failed detected; " "detected %d, threshold %d\n", __func__, nf, nfThresh); @@ -639,12 +810,22 @@ ar5416GetNf(struct ath_hal *ah, struct ieee80211_channel *chan) */ chan->ic_state |= IEEE80211_CHANSTATE_CWINT; nf = 0; + retval = 0; } } else { nf = 0; + retval = 0; } - ar5416UpdateNFHistBuff(AH5416(ah)->ah_cal.nfCalHist, nfarray); + /* Update MIMO channel statistics, regardless of validity or not (for now) */ + for (i = 0; i < 3; i++) { + ichan->noiseFloorCtl[i] = nfarray[i]; + ichan->noiseFloorExt[i] = nfarray[i + 3]; + } + ichan->privFlags |= CHANNEL_MIMO_NF_VALID; + + ar5416UpdateNFHistBuff(ah, AH5416(ah)->ah_cal.nfCalHist, nfarray); ichan->rawNoiseFloor = nf; + retval = nf; } - return nf; + return retval; } diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416_cal.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416_cal.h index e77f300b12..a4f19e592c 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416_cal.h +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416_cal.h @@ -102,6 +102,7 @@ struct ar5416PerCal { } \ } while (0) +HAL_BOOL ar5416InitCalHardware(struct ath_hal *ah, const struct ieee80211_channel *chan); HAL_BOOL ar5416InitCal(struct ath_hal *, const struct ieee80211_channel *); HAL_BOOL ar5416PerCalibration(struct ath_hal *, struct ieee80211_channel *, HAL_BOOL *isIQdone); diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416_cal_iq.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416_cal_iq.c index 82555b274c..939ba127ce 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416_cal_iq.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416_cal_iq.c @@ -115,7 +115,7 @@ ar5416IQCalibration(struct ath_hal *ah, uint8_t numChains) if (qCoff > 15) qCoff = 15; else if (qCoff <= -16) - qCoff = 16; + qCoff = -16; HALDEBUG(ah, HAL_DEBUG_PERCAL, " : iCoff = 0x%x qCoff = 0x%x\n", iCoff, qCoff); diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416_interrupts.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416_interrupts.c index 4b66d04fef..03d3544a89 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416_interrupts.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416_interrupts.c @@ -34,6 +34,10 @@ HAL_BOOL ar5416IsInterruptPending(struct ath_hal *ah) { uint32_t isr; + + if (AR_SREV_HOWL(ah)) + return AH_TRUE; + /* * Some platforms trigger our ISR before applying power to * the card, so make sure the INTPEND is really 1, not 0xffffffff. @@ -55,27 +59,34 @@ ar5416IsInterruptPending(struct ath_hal *ah) * values. The value returned is mapped to abstract the hw-specific bit * locations in the Interrupt Status Register. * + * (*masked) is cleared on initial call. + * * Returns: A hardware-abstracted bitmap of all non-masked-out * interrupts pending, as well as an unmasked value */ HAL_BOOL ar5416GetPendingInterrupts(struct ath_hal *ah, HAL_INT *masked) { - uint32_t isr, isr0, isr1, sync_cause; + uint32_t isr, isr0, isr1, sync_cause = 0; /* * Verify there's a mac interrupt and the RTC is on. */ - if ((OS_REG_READ(ah, AR_INTR_ASYNC_CAUSE) & AR_INTR_MAC_IRQ) && - (OS_REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M) == AR_RTC_STATUS_ON) - isr = OS_REG_READ(ah, AR_ISR); - else - isr = 0; - sync_cause = OS_REG_READ(ah, AR_INTR_SYNC_CAUSE); - sync_cause &= AR_INTR_SYNC_DEFAULT; - if (isr == 0 && sync_cause == 0) { + if (AR_SREV_HOWL(ah)) { *masked = 0; - return AH_FALSE; + isr = OS_REG_READ(ah, AR_ISR); + } else { + if ((OS_REG_READ(ah, AR_INTR_ASYNC_CAUSE) & AR_INTR_MAC_IRQ) && + (OS_REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M) == AR_RTC_STATUS_ON) + isr = OS_REG_READ(ah, AR_ISR); + else + isr = 0; + sync_cause = OS_REG_READ(ah, AR_INTR_SYNC_CAUSE); + sync_cause &= AR_INTR_SYNC_DEFAULT; + *masked = 0; + + if (isr == 0 && sync_cause == 0) + return AH_FALSE; } if (isr != 0) { @@ -120,8 +131,15 @@ ar5416GetPendingInterrupts(struct ath_hal *ah, HAL_INT *masked) ahp->ah_intrTxqs |= MS(isr1, AR_ISR_S1_QCU_TXEOL); } + if (AR_SREV_MERLIN(ah) || AR_SREV_KITE(ah)) { + uint32_t isr5; + isr5 = OS_REG_READ(ah, AR_ISR_S5_S); + if (isr5 & AR_ISR_S5_TIM_TIMER) + *masked |= HAL_INT_TIM_TIMER; + } + /* Interrupt Mitigation on AR5416 */ -#ifdef AR5416_INT_MITIGATION +#ifdef AH_AR5416_INTERRUPT_MITIGATION if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM)) *masked |= HAL_INT_RX; if (isr & (AR_ISR_TXMINTR | AR_ISR_TXINTM)) @@ -129,6 +147,10 @@ ar5416GetPendingInterrupts(struct ath_hal *ah, HAL_INT *masked) #endif *masked |= mask2; } + + if (AR_SREV_HOWL(ah)) + return AH_TRUE; + if (sync_cause != 0) { if (sync_cause & (AR_INTR_SYNC_HOST1_FATAL | AR_INTR_SYNC_HOST1_PERR)) { *masked |= HAL_INT_FATAL; @@ -177,16 +199,35 @@ ar5416SetInterrupts(struct ath_hal *ah, HAL_INT ints) OS_REG_WRITE(ah, AR_IER, AR_IER_DISABLE); (void) OS_REG_READ(ah, AR_IER); - OS_REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, 0); - (void) OS_REG_READ(ah, AR_INTR_ASYNC_ENABLE); + if (! AR_SREV_HOWL(ah)) { + OS_REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, 0); + (void) OS_REG_READ(ah, AR_INTR_ASYNC_ENABLE); - OS_REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0); - (void) OS_REG_READ(ah, AR_INTR_SYNC_ENABLE); + OS_REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0); + (void) OS_REG_READ(ah, AR_INTR_SYNC_ENABLE); + } } mask = ints & HAL_INT_COMMON; mask2 = 0; +#ifdef AH_AR5416_INTERRUPT_MITIGATION + /* + * Overwrite default mask if Interrupt mitigation + * is specified for AR5416 + */ + mask = ints & HAL_INT_COMMON; + if (ints & HAL_INT_TX) + mask |= AR_IMR_TXMINTR | AR_IMR_TXINTM; + if (ints & HAL_INT_RX) + mask |= AR_IMR_RXERR | AR_IMR_RXMINTR | AR_IMR_RXINTM; + if (ints & HAL_INT_TX) { + if (ahp->ah_txErrInterruptMask) + mask |= AR_IMR_TXERR; + if (ahp->ah_txEolInterruptMask) + mask |= AR_IMR_TXEOL; + } +#else if (ints & HAL_INT_TX) { if (ahp->ah_txOkInterruptMask) mask |= AR_IMR_TXOK; @@ -199,16 +240,6 @@ ar5416SetInterrupts(struct ath_hal *ah, HAL_INT ints) } if (ints & HAL_INT_RX) mask |= AR_IMR_RXOK | AR_IMR_RXERR | AR_IMR_RXDESC; -#ifdef AR5416_INT_MITIGATION - /* - * Overwrite default mask if Interrupt mitigation - * is specified for AR5416 - */ - mask = ints & HAL_INT_COMMON; - if (ints & HAL_INT_TX) - mask |= AR_IMR_TXMINTR | AR_IMR_TXINTM; - if (ints & HAL_INT_RX) - mask |= AR_IMR_RXERR | AR_IMR_RXMINTR | AR_IMR_RXINTM; #endif if (ints & (HAL_INT_BMISC)) { mask |= AR_IMR_BCNMISC; @@ -220,14 +251,20 @@ ar5416SetInterrupts(struct ath_hal *ah, HAL_INT ints) mask2 |= AR_IMR_S2_DTIMSYNC; if (ints & HAL_INT_CABEND) mask2 |= (AR_IMR_S2_CABEND ); - if (ints & HAL_INT_GTT) - mask2 |= AR_IMR_S2_GTT; if (ints & HAL_INT_CST) mask2 |= AR_IMR_S2_CST; if (ints & HAL_INT_TSFOOR) mask2 |= AR_IMR_S2_TSFOOR; } + if (ints & (HAL_INT_GTT | HAL_INT_CST)) { + mask |= AR_IMR_BCNMISC; + if (ints & HAL_INT_GTT) + mask2 |= AR_IMR_S2_GTT; + if (ints & HAL_INT_CST) + mask2 |= AR_IMR_S2_CST; + } + /* Write the new IMR and store off our SW copy. */ HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: new IMR 0x%x\n", __func__, mask); OS_REG_WRITE(ah, AR_IMR, mask); @@ -248,19 +285,21 @@ ar5416SetInterrupts(struct ath_hal *ah, HAL_INT ints) HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: enable IER\n", __func__); OS_REG_WRITE(ah, AR_IER, AR_IER_ENABLE); - mask = AR_INTR_MAC_IRQ; - if (ints & HAL_INT_GPIO) - mask |= SM(AH5416(ah)->ah_gpioMask, - AR_INTR_ASYNC_MASK_GPIO); - OS_REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, mask); - OS_REG_WRITE(ah, AR_INTR_ASYNC_MASK, mask); + if (! AR_SREV_HOWL(ah)) { + mask = AR_INTR_MAC_IRQ; + if (ints & HAL_INT_GPIO) + mask |= SM(AH5416(ah)->ah_gpioMask, + AR_INTR_ASYNC_MASK_GPIO); + OS_REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, mask); + OS_REG_WRITE(ah, AR_INTR_ASYNC_MASK, mask); - mask = AR_INTR_SYNC_DEFAULT; - if (ints & HAL_INT_GPIO) - mask |= SM(AH5416(ah)->ah_gpioMask, - AR_INTR_SYNC_MASK_GPIO); - OS_REG_WRITE(ah, AR_INTR_SYNC_ENABLE, mask); - OS_REG_WRITE(ah, AR_INTR_SYNC_MASK, mask); + mask = AR_INTR_SYNC_DEFAULT; + if (ints & HAL_INT_GPIO) + mask |= SM(AH5416(ah)->ah_gpioMask, + AR_INTR_SYNC_MASK_GPIO); + OS_REG_WRITE(ah, AR_INTR_SYNC_ENABLE, mask); + OS_REG_WRITE(ah, AR_INTR_SYNC_MASK, mask); + } } return omask; diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416_misc.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416_misc.c index ac6009bac8..7e61c84930 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416_misc.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416_misc.c @@ -40,14 +40,18 @@ u_int ar5416GetWirelessModes(struct ath_hal *ah) { u_int mode; + struct ath_hal_private *ahpriv = AH_PRIVATE(ah); + HAL_CAPABILITIES *pCap = &ahpriv->ah_caps; mode = ar5212GetWirelessModes(ah); - if (mode & HAL_MODE_11A) + + /* Only enable HT modes if the NIC supports HT */ + if (pCap->halHTSupport == AH_TRUE && (mode & HAL_MODE_11A)) mode |= HAL_MODE_11NA_HT20 | HAL_MODE_11NA_HT40PLUS | HAL_MODE_11NA_HT40MINUS ; - if (mode & HAL_MODE_11G) + if (pCap->halHTSupport == AH_TRUE && (mode & HAL_MODE_11G)) mode |= HAL_MODE_11NG_HT20 | HAL_MODE_11NG_HT40PLUS | HAL_MODE_11NG_HT40MINUS @@ -73,6 +77,9 @@ ar5416SetLedState(struct ath_hal *ah, HAL_LED_STATE state) }; uint32_t bits; + if (AR_SREV_HOWL(ah)) + return; + bits = OS_REG_READ(ah, AR_MAC_LED); bits = (bits &~ AR_MAC_LED_MODE) | SM(AR_MAC_LED_MODE_POWON, AR_MAC_LED_MODE) @@ -85,6 +92,41 @@ ar5416SetLedState(struct ath_hal *ah, HAL_LED_STATE state) OS_REG_WRITE(ah, AR_MAC_LED, bits); } +/* + * Get the current hardware tsf for stamlme + */ +uint64_t +ar5416GetTsf64(struct ath_hal *ah) +{ + uint32_t low1, low2, u32; + + /* sync multi-word read */ + low1 = OS_REG_READ(ah, AR_TSF_L32); + u32 = OS_REG_READ(ah, AR_TSF_U32); + low2 = OS_REG_READ(ah, AR_TSF_L32); + if (low2 < low1) { /* roll over */ + /* + * If we are not preempted this will work. If we are + * then we re-reading AR_TSF_U32 does no good as the + * low bits will be meaningless. Likewise reading + * L32, U32, U32, then comparing the last two reads + * to check for rollover doesn't help if preempted--so + * we take this approach as it costs one less PCI read + * which can be noticeable when doing things like + * timestamping packets in monitor mode. + */ + u32++; + } + return (((uint64_t) u32) << 32) | ((uint64_t) low2); +} + +void +ar5416SetTsf64(struct ath_hal *ah, uint64_t tsf64) +{ + OS_REG_WRITE(ah, AR_TSF_L32, tsf64 & 0xffffffff); + OS_REG_WRITE(ah, AR_TSF_U32, (tsf64 >> 32) & 0xffffffff); +} + /* * Reset the current hardware tsf for stamlme. */ @@ -120,6 +162,7 @@ ar5416SetDecompMask(struct ath_hal *ah, uint16_t keyidx, int en) void ar5416SetCoverageClass(struct ath_hal *ah, uint8_t coverageclass, int now) { + AH_PRIVATE(ah)->ah_coverageClass = coverageclass; } /* @@ -265,6 +308,35 @@ ar5416Set11nRxClear(struct ath_hal *ah, HAL_HT_RXCLEAR rxclear) } } +/* XXX shouldn't be here! */ +#define TU_TO_USEC(_tu) ((_tu) << 10) + +HAL_STATUS +ar5416SetQuiet(struct ath_hal *ah, uint32_t period, uint32_t duration, + uint32_t nextStart, HAL_QUIET_FLAG flag) +{ + uint32_t period_us = TU_TO_USEC(period); /* convert to us unit */ + uint32_t nextStart_us = TU_TO_USEC(nextStart); /* convert to us unit */ + if (flag & HAL_QUIET_ENABLE) { + if ((!nextStart) || (flag & HAL_QUIET_ADD_CURRENT_TSF)) { + /* Add the nextStart offset to the current TSF */ + nextStart_us += OS_REG_READ(ah, AR_TSF_L32); + } + if (flag & HAL_QUIET_ADD_SWBA_RESP_TIME) { + nextStart_us += ah->ah_config.ah_sw_beacon_response_time; + } + OS_REG_RMW_FIELD(ah, AR_QUIET1, AR_QUIET1_QUIET_ACK_CTS_ENABLE, 1); + OS_REG_WRITE(ah, AR_QUIET2, SM(duration, AR_QUIET2_QUIET_DUR)); + OS_REG_WRITE(ah, AR_QUIET_PERIOD, period_us); + OS_REG_WRITE(ah, AR_NEXT_QUIET, nextStart_us); + OS_REG_SET_BIT(ah, AR_TIMER_MODE, AR_TIMER_MODE_QUIET); + } else { + OS_REG_CLR_BIT(ah, AR_TIMER_MODE, AR_TIMER_MODE_QUIET); + } + return HAL_OK; +} +#undef TU_TO_USEC + HAL_STATUS ar5416GetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, uint32_t capability, uint32_t *result) @@ -273,9 +345,9 @@ ar5416GetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, case HAL_CAP_BB_HANG: switch (capability) { case HAL_BB_HANG_RIFS: - return AR_SREV_SOWL(ah) ? HAL_OK : HAL_ENOTSUPP; + return (AR_SREV_HOWL(ah) || AR_SREV_SOWL(ah)) ? HAL_OK : HAL_ENOTSUPP; case HAL_BB_HANG_DFS: - return AR_SREV_SOWL(ah) ? HAL_OK : HAL_ENOTSUPP; + return (AR_SREV_HOWL(ah) || AR_SREV_SOWL(ah)) ? HAL_OK : HAL_ENOTSUPP; case HAL_BB_HANG_RX_CLEAR: return AR_SREV_MERLIN(ah) ? HAL_OK : HAL_ENOTSUPP; } @@ -283,8 +355,10 @@ ar5416GetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, case HAL_CAP_MAC_HANG: return ((ah->ah_macVersion == AR_XSREV_VERSION_OWL_PCI) || (ah->ah_macVersion == AR_XSREV_VERSION_OWL_PCIE) || - AR_SREV_SOWL(ah)) ? + AR_SREV_HOWL(ah) || AR_SREV_SOWL(ah)) ? HAL_OK : HAL_ENOTSUPP; + case HAL_CAP_DIVERSITY: /* disable classic fast diversity */ + return HAL_ENXIO; default: break; } @@ -356,6 +430,59 @@ typedef struct { uint8_t qcu_complete_state; } hal_mac_hang_check_t; +HAL_BOOL +ar5416SetRifsDelay(struct ath_hal *ah, const struct ieee80211_channel *chan, + HAL_BOOL enable) +{ + uint32_t val; + HAL_BOOL is_chan_2g = AH_FALSE; + HAL_BOOL is_ht40 = AH_FALSE; + + if (chan) + is_chan_2g = IEEE80211_IS_CHAN_2GHZ(chan); + + if (chan) + is_ht40 = IEEE80211_IS_CHAN_HT40(chan); + + /* Only support disabling RIFS delay for now */ + HALASSERT(enable == AH_FALSE); + + if (enable == AH_TRUE) + return AH_FALSE; + + /* Change RIFS init delay to 0 */ + val = OS_REG_READ(ah, AR_PHY_HEAVY_CLIP_FACTOR_RIFS); + val &= ~AR_PHY_RIFS_INIT_DELAY; + OS_REG_WRITE(ah, AR_PHY_HEAVY_CLIP_FACTOR_RIFS, val); + + /* + * For Owl, RIFS RX parameters are controlled differently; + * it isn't enabled in the inivals by default. + * + * For Sowl/Howl, RIFS RX is enabled in the inivals by default; + * the following code sets them back to non-RIFS values. + * + * For > Sowl/Howl, RIFS RX can be left on by default and so + * this function shouldn't be called. + */ + if ((! AR_SREV_SOWL(ah)) && (! AR_SREV_HOWL(ah))) + return AH_TRUE; + + /* Reset search delay to default values */ + if (is_chan_2g) + if (is_ht40) + OS_REG_WRITE(ah, AR_PHY_SEARCH_START_DELAY, 0x268); + else + OS_REG_WRITE(ah, AR_PHY_SEARCH_START_DELAY, 0x134); + else + if (is_ht40) + OS_REG_WRITE(ah, AR_PHY_SEARCH_START_DELAY, 0x370); + else + OS_REG_WRITE(ah, AR_PHY_SEARCH_START_DELAY, 0x1b8); + + return AH_TRUE; +} + static HAL_BOOL ar5416CompareDbgHang(struct ath_hal *ah, const mac_dbg_regs_t *regs, const hal_mac_hang_check_t *check) @@ -435,12 +562,12 @@ ar5416DetectMacHang(struct ath_hal *ah) if (ar5416CompareDbgHang(ah, &mac_dbg, &hang_sig2)) return HAL_MAC_HANG_SIG2; - HALDEBUG(ah, HAL_DEBUG_ANY, "%s Found an unknown MAC hang signature " + HALDEBUG(ah, HAL_DEBUG_HANG, "%s Found an unknown MAC hang signature " "DMADBG_3=0x%x DMADBG_4=0x%x DMADBG_5=0x%x DMADBG_6=0x%x\n", __func__, mac_dbg.dma_dbg_3, mac_dbg.dma_dbg_4, mac_dbg.dma_dbg_5, mac_dbg.dma_dbg_6); - return HAL_MAC_HANG_UNKNOWN; + return 0; } /* @@ -484,16 +611,170 @@ ar5416DetectBBHang(struct ath_hal *ah) } for (i = 0; i < N(hang_list); i++) if ((hang_sig & hang_list[i].mask) == hang_list[i].val) { - HALDEBUG(ah, HAL_DEBUG_ANY, + HALDEBUG(ah, HAL_DEBUG_HANG, "%s BB hang, signature 0x%x, code 0x%x\n", __func__, hang_sig, hang_list[i].code); return hang_list[i].code; } - HALDEBUG(ah, HAL_DEBUG_ANY, "%s Found an unknown BB hang signature! " + HALDEBUG(ah, HAL_DEBUG_HANG, "%s Found an unknown BB hang signature! " "<0x806c>=0x%x\n", __func__, hang_sig); - return HAL_BB_HANG_UNKNOWN; + return 0; #undef N } #undef NUM_STATUS_READS + +/* + * Get the radar parameter values and return them in the pe + * structure + */ +void +ar5416GetDfsThresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe) +{ + uint32_t val, temp; + + val = OS_REG_READ(ah, AR_PHY_RADAR_0); + + temp = MS(val,AR_PHY_RADAR_0_FIRPWR); + temp |= 0xFFFFFF80; + pe->pe_firpwr = temp; + pe->pe_rrssi = MS(val, AR_PHY_RADAR_0_RRSSI); + pe->pe_height = MS(val, AR_PHY_RADAR_0_HEIGHT); + pe->pe_prssi = MS(val, AR_PHY_RADAR_0_PRSSI); + pe->pe_inband = MS(val, AR_PHY_RADAR_0_INBAND); + + val = OS_REG_READ(ah, AR_PHY_RADAR_1); + temp = val & AR_PHY_RADAR_1_RELPWR_ENA; + pe->pe_relpwr = MS(val, AR_PHY_RADAR_1_RELPWR_THRESH); + if (temp) + pe->pe_relpwr |= HAL_PHYERR_PARAM_ENABLE; + temp = val & AR_PHY_RADAR_1_RELSTEP_CHECK; + pe->pe_relstep = MS(val, AR_PHY_RADAR_1_RELSTEP_THRESH); + if (temp) + pe->pe_enabled = 1; + else + pe->pe_enabled = 0; + + pe->pe_maxlen = MS(val, AR_PHY_RADAR_1_MAXLEN); + pe->pe_extchannel = !! (OS_REG_READ(ah, AR_PHY_RADAR_EXT) & + AR_PHY_RADAR_EXT_ENA); + + pe->pe_usefir128 = !! (OS_REG_READ(ah, AR_PHY_RADAR_1) & + AR_PHY_RADAR_1_USE_FIR128); + pe->pe_blockradar = !! (OS_REG_READ(ah, AR_PHY_RADAR_1) & + AR_PHY_RADAR_1_BLOCK_CHECK); + pe->pe_enmaxrssi = !! (OS_REG_READ(ah, AR_PHY_RADAR_1) & + AR_PHY_RADAR_1_MAX_RRSSI); +} + +/* + * Enable radar detection and set the radar parameters per the + * values in pe + */ +void +ar5416EnableDfs(struct ath_hal *ah, HAL_PHYERR_PARAM *pe) +{ + uint32_t val; + + val = OS_REG_READ(ah, AR_PHY_RADAR_0); + + if (pe->pe_firpwr != HAL_PHYERR_PARAM_NOVAL) { + val &= ~AR_PHY_RADAR_0_FIRPWR; + val |= SM(pe->pe_firpwr, AR_PHY_RADAR_0_FIRPWR); + } + if (pe->pe_rrssi != HAL_PHYERR_PARAM_NOVAL) { + val &= ~AR_PHY_RADAR_0_RRSSI; + val |= SM(pe->pe_rrssi, AR_PHY_RADAR_0_RRSSI); + } + if (pe->pe_height != HAL_PHYERR_PARAM_NOVAL) { + val &= ~AR_PHY_RADAR_0_HEIGHT; + val |= SM(pe->pe_height, AR_PHY_RADAR_0_HEIGHT); + } + if (pe->pe_prssi != HAL_PHYERR_PARAM_NOVAL) { + val &= ~AR_PHY_RADAR_0_PRSSI; + val |= SM(pe->pe_prssi, AR_PHY_RADAR_0_PRSSI); + } + if (pe->pe_inband != HAL_PHYERR_PARAM_NOVAL) { + val &= ~AR_PHY_RADAR_0_INBAND; + val |= SM(pe->pe_inband, AR_PHY_RADAR_0_INBAND); + } + + /*Enable FFT data*/ + val |= AR_PHY_RADAR_0_FFT_ENA; + + OS_REG_WRITE(ah, AR_PHY_RADAR_0, val | AR_PHY_RADAR_0_ENA); + + if (pe->pe_usefir128 == 1) + OS_REG_CLR_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_USE_FIR128); + else if (pe->pe_usefir128 == 0) + OS_REG_SET_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_USE_FIR128); + + if (pe->pe_enmaxrssi == 1) + OS_REG_SET_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_MAX_RRSSI); + else if (pe->pe_enmaxrssi == 0) + OS_REG_CLR_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_MAX_RRSSI); + + if (pe->pe_blockradar == 1) + OS_REG_SET_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_BLOCK_CHECK); + else if (pe->pe_blockradar == 0) + OS_REG_CLR_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_BLOCK_CHECK); + + if (pe->pe_maxlen != HAL_PHYERR_PARAM_NOVAL) { + val = OS_REG_READ(ah, AR_PHY_RADAR_1); + val &= ~AR_PHY_RADAR_1_MAXLEN; + val |= SM(pe->pe_maxlen, AR_PHY_RADAR_1_MAXLEN); + OS_REG_WRITE(ah, AR_PHY_RADAR_1, val); + } + + /* + * Enable HT/40 if the upper layer asks; + * it should check the channel is HT/40 and HAL_CAP_EXT_CHAN_DFS + * is available. + */ + if (pe->pe_extchannel == 1) + OS_REG_SET_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA); + else if (pe->pe_extchannel == 0) + OS_REG_CLR_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA); + + if (pe->pe_relstep != HAL_PHYERR_PARAM_NOVAL) { + val = OS_REG_READ(ah, AR_PHY_RADAR_1); + val &= ~AR_PHY_RADAR_1_RELSTEP_THRESH; + val |= SM(pe->pe_relstep, AR_PHY_RADAR_1_RELSTEP_THRESH); + OS_REG_WRITE(ah, AR_PHY_RADAR_1, val); + } + if (pe->pe_relpwr != HAL_PHYERR_PARAM_NOVAL) { + val = OS_REG_READ(ah, AR_PHY_RADAR_1); + val &= ~AR_PHY_RADAR_1_RELPWR_THRESH; + val |= SM(pe->pe_relpwr, AR_PHY_RADAR_1_RELPWR_THRESH); + OS_REG_WRITE(ah, AR_PHY_RADAR_1, val); + } +} + +/* + * Extract the radar event information from the given phy error. + * + * Returns AH_TRUE if the phy error was actually a phy error, + * AH_FALSE if the phy error wasn't a phy error. + */ +HAL_BOOL +ar5416ProcessRadarEvent(struct ath_hal *ah, struct ath_rx_status *rxs, + uint64_t fulltsf, const char *buf, HAL_DFS_EVENT *event) +{ + /* + * For now, this isn't implemented. + */ + return AH_FALSE; +} + +/* + * Return whether fast-clock is currently enabled for this + * channel. + */ +HAL_BOOL +ar5416IsFastClockEnabled(struct ath_hal *ah) +{ + struct ath_hal_private *ahp = AH_PRIVATE(ah); + + return IS_5GHZ_FAST_CLOCK_EN(ah, ahp->ah_curchan); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416_phy.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416_phy.c index 0f99399f30..1cfd9644d2 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416_phy.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416_phy.c @@ -77,25 +77,25 @@ static HAL_RATE_TABLE ar5416_11na_table = { /* 12 Mb */ { AH_TRUE, OFDM, 12000, 0x0a, 0x00, (0x80|24), 2 }, /* 18 Mb */ { AH_TRUE, OFDM, 18000, 0x0e, 0x00, 36, 2 }, /* 24 Mb */ { AH_TRUE, OFDM, 24000, 0x09, 0x00, (0x80|48), 4 }, -/* 36 Mb */ { AH_TRUE, OFDM, 36000, 0x0d, 0x00, 72, 8 }, -/* 48 Mb */ { AH_TRUE, OFDM, 48000, 0x08, 0x00, 96, 8 }, -/* 54 Mb */ { AH_TRUE, OFDM, 54000, 0x0c, 0x00, 108, 8 }, -/* 6.5 Mb */ { AH_TRUE, HT, 6500, 0x80, 0x00, 0, 8 }, -/* 13 Mb */ { AH_TRUE, HT, 13000, 0x81, 0x00, 1, 8 }, -/*19.5 Mb */ { AH_TRUE, HT, 19500, 0x82, 0x00, 2, 8 }, -/* 26 Mb */ { AH_TRUE, HT, 26000, 0x83, 0x00, 3, 8 }, -/* 39 Mb */ { AH_TRUE, HT, 39000, 0x84, 0x00, 4, 8 }, -/* 52 Mb */ { AH_TRUE, HT, 52000, 0x85, 0x00, 5, 8 }, -/*58.5 Mb */ { AH_TRUE, HT, 58500, 0x86, 0x00, 6, 8 }, -/* 65 Mb */ { AH_TRUE, HT, 65000, 0x87, 0x00, 7, 8 }, -/* 13 Mb */ { AH_TRUE, HT, 13000, 0x88, 0x00, 8, 8 }, -/* 26 Mb */ { AH_TRUE, HT, 26000, 0x89, 0x00, 9, 8 }, -/* 39 Mb */ { AH_TRUE, HT, 39000, 0x8a, 0x00, 10, 8 }, -/* 52 Mb */ { AH_TRUE, HT, 52000, 0x8b, 0x00, 11, 8 }, -/* 78 Mb */ { AH_TRUE, HT, 78000, 0x8c, 0x00, 12, 8 }, -/* 104 Mb */ { AH_TRUE, HT, 104000, 0x8d, 0x00, 13, 8 }, -/* 117 Mb */ { AH_TRUE, HT, 117000, 0x8e, 0x00, 14, 8 }, -/* 130 Mb */ { AH_TRUE, HT, 130000, 0x8f, 0x00, 15, 8 }, +/* 36 Mb */ { AH_TRUE, OFDM, 36000, 0x0d, 0x00, 72, 4 }, +/* 48 Mb */ { AH_TRUE, OFDM, 48000, 0x08, 0x00, 96, 4 }, +/* 54 Mb */ { AH_TRUE, OFDM, 54000, 0x0c, 0x00, 108, 4 }, +/* 6.5 Mb */ { AH_TRUE, HT, 6500, 0x80, 0x00, 0, 4 }, +/* 13 Mb */ { AH_TRUE, HT, 13000, 0x81, 0x00, 1, 4 }, +/*19.5 Mb */ { AH_TRUE, HT, 19500, 0x82, 0x00, 2, 4 }, +/* 26 Mb */ { AH_TRUE, HT, 26000, 0x83, 0x00, 3, 4 }, +/* 39 Mb */ { AH_TRUE, HT, 39000, 0x84, 0x00, 4, 4 }, +/* 52 Mb */ { AH_TRUE, HT, 52000, 0x85, 0x00, 5, 4 }, +/*58.5 Mb */ { AH_TRUE, HT, 58500, 0x86, 0x00, 6, 4 }, +/* 65 Mb */ { AH_TRUE, HT, 65000, 0x87, 0x00, 7, 4 }, +/* 13 Mb */ { AH_TRUE, HT, 13000, 0x88, 0x00, 8, 4 }, +/* 26 Mb */ { AH_TRUE, HT, 26000, 0x89, 0x00, 9, 4 }, +/* 39 Mb */ { AH_TRUE, HT, 39000, 0x8a, 0x00, 10, 4 }, +/* 52 Mb */ { AH_TRUE, HT, 52000, 0x8b, 0x00, 11, 4 }, +/* 78 Mb */ { AH_TRUE, HT, 78000, 0x8c, 0x00, 12, 4 }, +/* 104 Mb */ { AH_TRUE, HT, 104000, 0x8d, 0x00, 13, 4 }, +/* 117 Mb */ { AH_TRUE, HT, 117000, 0x8e, 0x00, 14, 4 }, +/* 130 Mb */ { AH_TRUE, HT, 130000, 0x8f, 0x00, 15, 4 }, }, }; diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416_power.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416_power.c index c3b1285f37..2d8c7f9727 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416_power.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416_power.c @@ -52,8 +52,14 @@ ar5416SetPowerModeAwake(struct ath_hal *ah, int setChip) goto bad; } + if (AR_SREV_HOWL(ah)) + OS_REG_SET_BIT(ah, AR_RTC_RESET, AR_RTC_RESET_EN); + OS_REG_SET_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN); - OS_DELAY(50); /* Give chip the chance to awake */ + if (AR_SREV_HOWL(ah)) + OS_DELAY(10000); + else + OS_DELAY(50); /* Give chip the chance to awake */ for (i = POWER_UP_TIME / 50; i != 0; i--) { val = OS_REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M; @@ -88,9 +94,11 @@ ar5416SetPowerModeSleep(struct ath_hal *ah, int setChip) if (setChip) { /* Clear the RTC force wake bit to allow the mac to sleep */ OS_REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN); - OS_REG_WRITE(ah, AR_RC, AR_RC_AHB|AR_RC_HOSTIF); + if (! AR_SREV_HOWL(ah)) + OS_REG_WRITE(ah, AR_RC, AR_RC_AHB|AR_RC_HOSTIF); /* Shutdown chip. Active low */ - OS_REG_CLR_BIT(ah, AR_RTC_RESET, AR_RTC_RESET_EN); + if (! AR_SREV_OWL(ah)) + OS_REG_CLR_BIT(ah, AR_RTC_RESET, AR_RTC_RESET_EN); } } diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416_recv.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416_recv.c index 4a480aa91e..289da427eb 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416_recv.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416_recv.c @@ -26,6 +26,46 @@ #include "ar5416/ar5416reg.h" #include "ar5416/ar5416desc.h" +/* + * Get the receive filter. + */ +uint32_t +ar5416GetRxFilter(struct ath_hal *ah) +{ + uint32_t bits = OS_REG_READ(ah, AR_RX_FILTER); + uint32_t phybits = OS_REG_READ(ah, AR_PHY_ERR); + + if (phybits & AR_PHY_ERR_RADAR) + bits |= HAL_RX_FILTER_PHYRADAR; + if (phybits & (AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING)) + bits |= HAL_RX_FILTER_PHYERR; + return bits; +} + +/* + * Set the receive filter. + */ +void +ar5416SetRxFilter(struct ath_hal *ah, u_int32_t bits) +{ + uint32_t phybits; + + OS_REG_WRITE(ah, AR_RX_FILTER, (bits & 0xffff)); + phybits = 0; + if (bits & HAL_RX_FILTER_PHYRADAR) + phybits |= AR_PHY_ERR_RADAR; + if (bits & HAL_RX_FILTER_PHYERR) + phybits |= AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING; + OS_REG_WRITE(ah, AR_PHY_ERR, phybits); + if (phybits) { + OS_REG_WRITE(ah, AR_RXCFG, + OS_REG_READ(ah, AR_RXCFG) | AR_RXCFG_ZLFDMA); + } else { + OS_REG_WRITE(ah, AR_RXCFG, + OS_REG_READ(ah, AR_RXCFG) &~ AR_RXCFG_ZLFDMA); + } +} + /* * Start receive at the PCU engine */ @@ -67,6 +107,7 @@ ar5416SetupRxDesc(struct ath_hal *ah, struct ath_desc *ds, uint32_t size, u_int flags) { struct ar5416_desc *ads = AR5416DESC(ds); + HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; HALASSERT((size &~ AR_BufLen) == 0); @@ -77,6 +118,10 @@ ar5416SetupRxDesc(struct ath_hal *ah, struct ath_desc *ds, /* this should be enough */ ads->ds_rxstatus8 &= ~AR_RxDone; + /* clear the rest of the status fields */ + if (! pCap->halAutoSleepSupport) + OS_MEMZERO(&(ads->u), sizeof(ads->u)); + return AH_TRUE; } @@ -94,18 +139,9 @@ ar5416ProcRxDesc(struct ath_hal *ah, struct ath_desc *ds, struct ath_rx_status *rs) { struct ar5416_desc *ads = AR5416DESC(ds); - struct ar5416_desc *ands = AR5416DESC(nds); if ((ads->ds_rxstatus8 & AR_RxDone) == 0) return HAL_EINPROGRESS; - /* - * Given the use of a self-linked tail be very sure that the hw is - * done with this descriptor; the hw may have done this descriptor - * once and picked it up again...make sure the hw has moved on. - */ - if ((ands->ds_rxstatus8 & AR_RxDone) == 0 - && OS_REG_READ(ah, AR_RXDP) == pa) - return HAL_EINPROGRESS; rs->rs_status = 0; rs->rs_flags = 0; diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416_reset.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416_reset.c index 22ad3b7730..112d966954 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416_reset.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416_reset.c @@ -44,6 +44,8 @@ static void ar5416InitBB(struct ath_hal *ah, const struct ieee80211_channel *); static void ar5416InitIMR(struct ath_hal *ah, HAL_OPMODE opmode); static void ar5416InitQoS(struct ath_hal *ah); static void ar5416InitUserSettings(struct ath_hal *ah); +static void ar5416UpdateChainMasks(struct ath_hal *ah, HAL_BOOL is_ht); +static void ar5416OverrideIni(struct ath_hal *ah, const struct ieee80211_channel *); #if 0 static HAL_BOOL ar5416ChannelChange(struct ath_hal *, const struct ieee80211_channel *); @@ -52,34 +54,14 @@ static void ar5416SetDeltaSlope(struct ath_hal *, const struct ieee80211_channel static HAL_BOOL ar5416SetResetPowerOn(struct ath_hal *ah); static HAL_BOOL ar5416SetReset(struct ath_hal *ah, int type); -static void ar5416InitPLL(struct ath_hal *ah, const struct ieee80211_channel *chan); static HAL_BOOL ar5416SetPowerPerRateTable(struct ath_hal *ah, struct ar5416eeprom *pEepData, const struct ieee80211_channel *chan, int16_t *ratesArray, uint16_t cfgCtl, uint16_t AntennaReduction, uint16_t twiceMaxRegulatoryPower, uint16_t powerLimit); -static HAL_BOOL ar5416SetPowerCalTable(struct ath_hal *ah, - struct ar5416eeprom *pEepData, - const struct ieee80211_channel *chan, - int16_t *pTxPowerIndexOffset); -static uint16_t ar5416GetMaxEdgePower(uint16_t freq, - CAL_CTL_EDGES *pRdEdgesPower, HAL_BOOL is2GHz); - -static int16_t interpolate(uint16_t target, uint16_t srcLeft, - uint16_t srcRight, int16_t targetLeft, int16_t targetRight); static void ar5416Set11nRegs(struct ath_hal *ah, const struct ieee80211_channel *chan); -static void ar5416GetGainBoundariesAndPdadcs(struct ath_hal *ah, - const struct ieee80211_channel *chan, CAL_DATA_PER_FREQ *pRawDataSet, - uint8_t * bChans, uint16_t availPiers, - uint16_t tPdGainOverlap, int16_t *pMinCalPower, - uint16_t * pPdGainBoundaries, uint8_t * pPDADCValues, - uint16_t numXpdGains); -static HAL_BOOL getLowerUpperIndex(uint8_t target, uint8_t *pList, - uint16_t listSize, uint16_t *indexL, uint16_t *indexR); -static HAL_BOOL ar5416FillVpdTable(uint8_t pwrMin, uint8_t pwrMax, - uint8_t *pPwrList, uint8_t *pVpdList, - uint16_t numIntercepts, uint8_t *pRetVpdList); +static void ar5416MarkPhyInactive(struct ath_hal *ah); /* * Places the device in and out of reset and then places sane @@ -105,6 +87,7 @@ ar5416Reset(struct ath_hal *ah, HAL_OPMODE opmode, uint32_t powerVal, rssiThrReg; uint32_t ackTpcPow, ctsTpcPow, chirpTpcPow; int i; + uint64_t tsf = 0; OS_MARK(ah, AH_MARK_RESET, bChannelChange); @@ -161,55 +144,80 @@ ar5416Reset(struct ath_hal *ah, HAL_OPMODE opmode, (AR_MAC_LED_ASSOC | AR_MAC_LED_MODE | AR_MAC_LED_BLINK_THRESH_SEL | AR_MAC_LED_BLINK_SLOW); + /* For chips on which the RTC reset is done, save TSF before it gets cleared */ + if (AR_SREV_HOWL(ah) || + (AR_SREV_MERLIN(ah) && ath_hal_eepromGetFlag(ah, AR_EEP_OL_PWRCTRL))) + tsf = ar5416GetTsf64(ah); + + /* Mark PHY as inactive; marked active in ar5416InitBB() */ + ar5416MarkPhyInactive(ah); + if (!ar5416ChipReset(ah, chan)) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__); FAIL(HAL_EIO); } - /* Restore bmiss rssi & count thresholds */ - OS_REG_WRITE(ah, AR_RSSI_THR, rssiThrReg); + /* Restore TSF */ + if (tsf) + ar5416SetTsf64(ah, tsf); OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__); + if (AR_SREV_MERLIN_10_OR_LATER(ah)) + OS_REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE); AH5416(ah)->ah_writeIni(ah, chan); + if(AR_SREV_KIWI_13_OR_LATER(ah) ) { + /* Enable ASYNC FIFO */ + OS_REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3, + AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL); + OS_REG_SET_BIT(ah, AR_PHY_MODE, AR_PHY_MODE_ASYNCFIFO); + OS_REG_CLR_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3, + AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET); + OS_REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3, + AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET); + } + + /* Override ini values (that can be overriden in this fashion) */ + ar5416OverrideIni(ah, chan); + /* Setup 11n MAC/Phy mode registers */ ar5416Set11nRegs(ah, chan); OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__); + /* + * Some AR91xx SoC devices frequently fail to accept TSF writes + * right after the chip reset. When that happens, write a new + * value after the initvals have been applied, with an offset + * based on measured time difference + */ + if (AR_SREV_HOWL(ah) && (ar5416GetTsf64(ah) < tsf)) { + tsf += 1500; + ar5416SetTsf64(ah, tsf); + } + HALDEBUG(ah, HAL_DEBUG_RESET, ">>>2 %s: AR_PHY_DAG_CTRLCCK=0x%x\n", __func__, OS_REG_READ(ah,AR_PHY_DAG_CTRLCCK)); HALDEBUG(ah, HAL_DEBUG_RESET, ">>>2 %s: AR_PHY_ADC_CTL=0x%x\n", __func__, OS_REG_READ(ah,AR_PHY_ADC_CTL)); - /* Set the mute mask to the correct default */ - if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_2) - OS_REG_WRITE(ah, AR_SEQ_MASK, 0x0000000F); + /* + * Setup ah_tx_chainmask / ah_rx_chainmask before we fiddle + * with enabling the TX/RX radio chains. + */ + ar5416UpdateChainMasks(ah, IEEE80211_IS_CHAN_HT(chan)); + /* + * This routine swaps the analog chains - it should be done + * before any radio register twiddling is done. + */ + ar5416InitChainMasks(ah); - if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_3) { - /* Clear reg to alllow RX_CLEAR line debug */ - OS_REG_WRITE(ah, AR_PHY_BLUETOOTH, 0); + /* Setup the open-loop power calibration if required */ + if (ath_hal_eepromGetFlag(ah, AR_EEP_OL_PWRCTRL)) { + AH5416(ah)->ah_olcInit(ah); + AH5416(ah)->ah_olcTempCompensation(ah); } - if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_4) { -#ifdef notyet - /* Enable burst prefetch for the data queues */ - OS_REG_RMW_FIELD(ah, AR_D_FPCTL, ... ); - /* Enable double-buffering */ - OS_REG_CLR_BIT(ah, AR_TXCFG, AR_TXCFG_DBL_BUF_DIS); -#endif - } - - /* Set ADC/DAC select values */ - OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0e); - - if (AH5416(ah)->ah_rx_chainmask == 0x5 || - AH5416(ah)->ah_tx_chainmask == 0x5) - OS_REG_WRITE(ah, AR_PHY_ANALOG_SWAP, AR_PHY_SWAP_ALT_CHAIN); - /* Setup Chain Masks */ - OS_REG_WRITE(ah, AR_PHY_RX_CHAINMASK, AH5416(ah)->ah_rx_chainmask); - OS_REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, AH5416(ah)->ah_rx_chainmask); - OS_REG_WRITE(ah, AR_SELFGEN_MASK, AH5416(ah)->ah_tx_chainmask); /* Setup the transmit power values. */ if (!ah->ah_setTxPower(ah, chan, rfXpdGain)) { @@ -254,7 +262,18 @@ ar5416Reset(struct ath_hal *ah, HAL_OPMODE opmode, OS_REG_WRITE(ah, AR_BSSMSKU, LE_READ_2(ahp->ah_bssidmask + 4)); /* Restore previous led state */ - OS_REG_WRITE(ah, AR_MAC_LED, OS_REG_READ(ah, AR_MAC_LED) | saveLedState); + if (AR_SREV_HOWL(ah)) + OS_REG_WRITE(ah, AR_MAC_LED, + AR_MAC_LED_ASSOC_ACTIVE | AR_CFG_SCLK_32KHZ); + else + OS_REG_WRITE(ah, AR_MAC_LED, OS_REG_READ(ah, AR_MAC_LED) | + saveLedState); + + /* Start TSF2 for generic timer 8-15 */ +#ifdef NOTYET + if (AR_SREV_KIWI(ah)) + ar5416StartTsf2(ah); +#endif /* Restore previous antenna */ OS_REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna); @@ -268,6 +287,9 @@ ar5416Reset(struct ath_hal *ah, HAL_OPMODE opmode, OS_REG_WRITE(ah, AR_ISR, ~0); /* cleared on write */ + /* Restore bmiss rssi & count thresholds */ + OS_REG_WRITE(ah, AR_RSSI_THR, rssiThrReg); + if (!ar5212SetChannel(ah, chan)) FAIL(HAL_EIO); @@ -279,13 +301,49 @@ ar5416Reset(struct ath_hal *ah, HAL_OPMODE opmode, ahp->ah_intrTxqs = 0; for (i = 0; i < AH_PRIVATE(ah)->ah_caps.halTotalQueues; i++) - ar5212ResetTxQueue(ah, i); + ah->ah_resetTxQueue(ah, i); ar5416InitIMR(ah, opmode); ar5212SetCoverageClass(ah, AH_PRIVATE(ah)->ah_coverageClass, 1); ar5416InitQoS(ah); + /* This may override the AR_DIAG_SW register */ ar5416InitUserSettings(ah); + if (AR_SREV_KIWI_13_OR_LATER(ah)) { + /* + * Enable ASYNC FIFO + * + * If Async FIFO is enabled, the following counters change + * as MAC now runs at 117 Mhz instead of 88/44MHz when + * async FIFO is disabled. + * + * Overwrite the delay/timeouts initialized in ProcessIni() + * above. + */ + OS_REG_WRITE(ah, AR_D_GBL_IFS_SIFS, + AR_D_GBL_IFS_SIFS_ASYNC_FIFO_DUR); + OS_REG_WRITE(ah, AR_D_GBL_IFS_SLOT, + AR_D_GBL_IFS_SLOT_ASYNC_FIFO_DUR); + OS_REG_WRITE(ah, AR_D_GBL_IFS_EIFS, + AR_D_GBL_IFS_EIFS_ASYNC_FIFO_DUR); + + OS_REG_WRITE(ah, AR_TIME_OUT, + AR_TIME_OUT_ACK_CTS_ASYNC_FIFO_DUR); + OS_REG_WRITE(ah, AR_USEC, AR_USEC_ASYNC_FIFO_DUR); + + OS_REG_SET_BIT(ah, AR_MAC_PCU_LOGIC_ANALYZER, + AR_MAC_PCU_LOGIC_ANALYZER_DISBUG20768); + OS_REG_RMW_FIELD(ah, AR_AHB_MODE, AR_AHB_CUSTOM_BURST_EN, + AR_AHB_CUSTOM_BURST_ASYNC_FIFO_VAL); + } + + if (AR_SREV_KIWI_13_OR_LATER(ah)) { + /* Enable AGGWEP to accelerate encryption engine */ + OS_REG_SET_BIT(ah, AR_PCU_MISC_MODE2, + AR_PCU_MISC_MODE2_ENABLE_AGGWEP); + } + + /* * disable seq number generation in hw */ @@ -299,12 +357,14 @@ ar5416Reset(struct ath_hal *ah, HAL_OPMODE opmode, */ OS_REG_WRITE(ah, AR_OBS, 8); -#ifdef AR5416_INT_MITIGATION +#ifdef AH_AR5416_INTERRUPT_MITIGATION OS_REG_WRITE(ah, AR_MIRT, 0); + OS_REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, 500); OS_REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, 2000); -#endif - + OS_REG_RMW_FIELD(ah, AR_TIMT, AR_TIMT_LAST, 300); + OS_REG_RMW_FIELD(ah, AR_TIMT, AR_TIMT_FIRST, 750); +#endif ar5416InitBB(ah, chan); /* Setup compression registers */ @@ -325,11 +385,26 @@ ar5416Reset(struct ath_hal *ah, HAL_OPMODE opmode, if (!ar5416InitCal(ah, chan)) FAIL(HAL_ESELFTEST); + ar5416RestoreChainMask(ah); + AH_PRIVATE(ah)->ah_opmode = opmode; /* record operating mode */ if (bChannelChange && !IEEE80211_IS_CHAN_DFS(chan)) chan->ic_state &= ~IEEE80211_CHANSTATE_CWINT; + if (AR_SREV_HOWL(ah)) { + /* + * Enable the MBSSID block-ack fix for HOWL. + * This feature is only supported on Howl 1.4, but it is safe to + * set bit 22 of STA_ID1 on other Howl revisions (1.1, 1.2, 1.3), + * since bit 22 is unused in those Howl revisions. + */ + unsigned int reg; + reg = (OS_REG_READ(ah, AR_STA_ID1) | (1<<22)); + OS_REG_WRITE(ah,AR_STA_ID1, reg); + ath_hal_printf(ah, "MBSSID Set bit 22 of AR_STA_ID 0x%x\n", reg); + } + HALDEBUG(ah, HAL_DEBUG_RESET, "%s: done\n", __func__); OS_MARK(ah, AH_MARK_RESET_DONE, 0); @@ -391,7 +466,7 @@ ar5416ChannelChange(struct ath_hal *ah, const structu ieee80211_channel *chan) return AH_FALSE; /* Setup the transmit power values. */ - if (!ar5416SetTransmitPower(ah, chan, rfXpdGain)) { + if (!ah->ah_setTxPower(ah, chan, rfXpdGain)) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: error init'ing transmit power\n", __func__); return AH_FALSE; @@ -427,7 +502,7 @@ ar5416ChannelChange(struct ath_hal *ah, const structu ieee80211_channel *chan) chan->ic_state &= ~IEEE80211_CHANSTATE_CWINT; ichan->channel_time = 0; - ichan->tsf_last = ar5212GetTsf64(ah); + ichan->tsf_last = ar5416GetTsf64(ah); ar5212TxEnable(ah, AH_TRUE); return AH_TRUE; } @@ -436,6 +511,7 @@ ar5416ChannelChange(struct ath_hal *ah, const structu ieee80211_channel *chan) static void ar5416InitDMA(struct ath_hal *ah) { + struct ath_hal_5212 *ahp = AH5212(ah); /* * set AHB_MODE not to do cacheline prefetches @@ -454,7 +530,10 @@ ar5416InitDMA(struct ath_hal *ah) OS_REG_WRITE(ah, AR_RXCFG, (OS_REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_DMASZ_MASK) | AR_RXCFG_DMASZ_128B); - /* XXX restore TX trigger level */ + /* restore TX trigger level */ + OS_REG_WRITE(ah, AR_TXCFG, + (OS_REG_READ(ah, AR_TXCFG) &~ AR_FTRIG) | + SM(ahp->ah_txTrigLev, AR_FTRIG)); /* * Setup receive FIFO threshold to hold off TX activities @@ -465,7 +544,15 @@ ar5416InitDMA(struct ath_hal *ah) * reduce the number of usable entries in PCU TXBUF to avoid * wrap around. */ - OS_REG_WRITE(ah, AR_PCU_TXBUF_CTRL, AR_PCU_TXBUF_CTRL_USABLE_SIZE); + if (AR_SREV_KITE(ah)) + /* + * For AR9285 the number of Fifos are reduced to half. + * So set the usable tx buf size also to half to + * avoid data/delimiter underruns + */ + OS_REG_WRITE(ah, AR_PCU_TXBUF_CTRL, AR_9285_PCU_TXBUF_CTRL_USABLE_SIZE); + else + OS_REG_WRITE(ah, AR_PCU_TXBUF_CTRL, AR_PCU_TXBUF_CTRL_USABLE_SIZE); } static void @@ -488,7 +575,6 @@ ar5416InitBB(struct ath_hal *ah, const struct ieee80211_channel *chan) /* Turn on PLL on 5416 */ HALDEBUG(ah, HAL_DEBUG_RESET, "%s %s channel\n", __func__, IEEE80211_IS_CHAN_5GHZ(chan) ? "5GHz" : "2GHz"); - ar5416InitPLL(ah, chan); /* Activate the PHY (includes baseband activate and synthesizer on) */ OS_REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); @@ -523,15 +609,26 @@ ar5416InitIMR(struct ath_hal *ah, HAL_OPMODE opmode) | AR_IMR_RXERR | AR_IMR_RXORN | AR_IMR_BCNMISC; -#ifdef AR5416_INT_MITIGATION - ahp->ah_maskReg |= AR_IMR_TXINTM | AR_IMR_RXINTM +#ifdef AH_AR5416_INTERRUPT_MITIGATION + ahp->ah_maskReg |= AR_IMR_TXINTM | AR_IMR_RXINTM | AR_IMR_TXMINTR | AR_IMR_RXMINTR; #else - ahp->ah_maskReg |= AR_IMR_TXOK | AR_IMR_RXOK; + ahp->ah_maskReg |= AR_IMR_TXOK | AR_IMR_RXOK; #endif + if (opmode == HAL_M_HOSTAP) ahp->ah_maskReg |= AR_IMR_MIB; OS_REG_WRITE(ah, AR_IMR, ahp->ah_maskReg); + +#ifdef ADRIAN_NOTYET + /* This is straight from ath9k */ + if (! AR_SREV_HOWL(ah)) { + OS_REG_WRITE(ah, AR_INTR_SYNC_CAUSE, 0xFFFFFFFF); + OS_REG_WRITE(ah, AR_INTR_SYNC_ENABLE, AR_INTR_SYNC_DEFAULT); + OS_REG_WRITE(ah, AR_INTR_SYNC_MASK, 0); + } +#endif + /* Enable bus errors that are OR'd to set the HIUERR bit */ #if 0 OS_REG_WRITE(ah, AR_IMR_S2, @@ -569,7 +666,7 @@ ar5416InitUserSettings(struct ath_hal *ah) /* Restore user-specified settings */ if (ahp->ah_miscMode != 0) - OS_REG_WRITE(ah, AR_MISC_MODE, ahp->ah_miscMode); + OS_REG_WRITE(ah, AR_MISC_MODE, OS_REG_READ(ah, AR_MISC_MODE) | ahp->ah_miscMode); if (ahp->ah_sifstime != (u_int) -1) ar5212SetSifsTime(ah, ahp->ah_sifstime); if (ahp->ah_slottime != (u_int) -1) @@ -580,10 +677,31 @@ ar5416InitUserSettings(struct ath_hal *ah) ar5212SetCTSTimeout(ah, ahp->ah_ctstimeout); if (AH_PRIVATE(ah)->ah_diagreg != 0) OS_REG_WRITE(ah, AR_DIAG_SW, AH_PRIVATE(ah)->ah_diagreg); -#if 0 /* XXX Todo */ - if (ahp->ah_globaltxtimeout != (u_int) -1) - ar5416SetGlobalTxTimeout(ah, ahp->ah_globaltxtimeout); -#endif + if (AH5416(ah)->ah_globaltxtimeout != (u_int) -1) + ar5416SetGlobalTxTimeout(ah, AH5416(ah)->ah_globaltxtimeout); +} + +static void +ar5416SetRfMode(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + uint32_t rfMode; + + if (chan == AH_NULL) + return; + + /* treat channel B as channel G , no B mode suport in owl */ + rfMode = IEEE80211_IS_CHAN_CCK(chan) ? + AR_PHY_MODE_DYNAMIC : AR_PHY_MODE_OFDM; + + if (AR_SREV_MERLIN_20(ah) && IS_5GHZ_FAST_CLOCK_EN(ah, chan)) { + /* phy mode bits for 5GHz channels require Fast Clock */ + rfMode |= AR_PHY_MODE_DYNAMIC + | AR_PHY_MODE_DYN_CCK_DISABLE; + } else if (!AR_SREV_MERLIN_10_OR_LATER(ah)) { + rfMode |= IEEE80211_IS_CHAN_5GHZ(chan) ? + AR_PHY_MODE_RF5GHZ : AR_PHY_MODE_RF2GHZ; + } + OS_REG_WRITE(ah, AR_PHY_MODE, rfMode); } /* @@ -596,7 +714,7 @@ ar5416ChipReset(struct ath_hal *ah, const struct ieee80211_channel *chan) /* * Warm reset is optimistic. */ - if (AR_SREV_MERLIN_20_OR_LATER(ah) && + if (AR_SREV_MERLIN(ah) && ath_hal_eepromGetFlag(ah, AR_EEP_OL_PWRCTRL)) { if (!ar5416SetResetReg(ah, HAL_RESET_POWER_ON)) return AH_FALSE; @@ -609,7 +727,11 @@ ar5416ChipReset(struct ath_hal *ah, const struct ieee80211_channel *chan) if (!ar5416SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) return AH_FALSE; - ar5416InitPLL(ah, chan); +#ifdef notyet + ahp->ah_chipFullSleep = AH_FALSE; +#endif + + AH5416(ah)->ah_initPLL(ah, chan); /* * Perform warm reset before the mode/PLL/turbo registers @@ -617,22 +739,8 @@ ar5416ChipReset(struct ath_hal *ah, const struct ieee80211_channel *chan) * with an active radio can result in corrupted shifts to the * radio device. */ - if (chan != AH_NULL) { - uint32_t rfMode; + ar5416SetRfMode(ah, chan); - /* treat channel B as channel G , no B mode suport in owl */ - rfMode = IEEE80211_IS_CHAN_CCK(chan) ? - AR_PHY_MODE_DYNAMIC : AR_PHY_MODE_OFDM; - if (AR_SREV_MERLIN_20(ah) && IS_5GHZ_FAST_CLOCK_EN(ah, chan)) { - /* phy mode bits for 5GHz channels require Fast Clock */ - rfMode |= AR_PHY_MODE_DYNAMIC - | AR_PHY_MODE_DYN_CCK_DISABLE; - } else if (!AR_SREV_MERLIN_10_OR_LATER(ah)) { - rfMode |= IEEE80211_IS_CHAN_5GHZ(chan) ? - AR_PHY_MODE_RF5GHZ : AR_PHY_MODE_RF2GHZ; - } - OS_REG_WRITE(ah, AR_PHY_MODE, rfMode); - } return AH_TRUE; } @@ -730,7 +838,7 @@ ar5416SetTxPowerLimit(struct ath_hal *ah, uint32_t limit) uint16_t dummyXpdGains[2]; AH_PRIVATE(ah)->ah_powerLimit = AH_MIN(limit, MAX_RATE_POWER); - return ar5416SetTransmitPower(ah, AH_PRIVATE(ah)->ah_curchan, + return ah->ah_setTxPower(ah, AH_PRIVATE(ah)->ah_curchan, dummyXpdGains); } @@ -761,106 +869,25 @@ ar5416GetChipPowerLimits(struct ath_hal *ah, return AH_TRUE; } -/* XXX gag, this is sick */ -typedef enum Ar5416_Rates { - rate6mb, rate9mb, rate12mb, rate18mb, - rate24mb, rate36mb, rate48mb, rate54mb, - rate1l, rate2l, rate2s, rate5_5l, - rate5_5s, rate11l, rate11s, rateXr, - rateHt20_0, rateHt20_1, rateHt20_2, rateHt20_3, - rateHt20_4, rateHt20_5, rateHt20_6, rateHt20_7, - rateHt40_0, rateHt40_1, rateHt40_2, rateHt40_3, - rateHt40_4, rateHt40_5, rateHt40_6, rateHt40_7, - rateDupCck, rateDupOfdm, rateExtCck, rateExtOfdm, - Ar5416RateSize -} AR5416_RATES; - /************************************************************** - * ar5416SetTransmitPower + * ar5416WriteTxPowerRateRegisters * - * Set the transmit power in the baseband for the given - * operating channel and mode. + * Write the TX power rate registers from the raw values given + * in ratesArray[]. + * + * The CCK and HT40 rate registers are only written if needed. + * HT20 and 11g/11a OFDM rate registers are always written. + * + * The values written are raw values which should be written + * to the registers - so it's up to the caller to pre-adjust + * them (eg CCK power offset value, or Merlin TX power offset, + * etc.) */ -HAL_BOOL -ar5416SetTransmitPower(struct ath_hal *ah, - const struct ieee80211_channel *chan, uint16_t *rfXpdGain) +void +ar5416WriteTxPowerRateRegisters(struct ath_hal *ah, + const struct ieee80211_channel *chan, const int16_t ratesArray[]) { #define POW_SM(_r, _s) (((_r) & 0x3f) << (_s)) -#define N(a) (sizeof (a) / sizeof (a[0])) - - MODAL_EEP_HEADER *pModal; - struct ath_hal_5212 *ahp = AH5212(ah); - int16_t ratesArray[Ar5416RateSize]; - int16_t txPowerIndexOffset = 0; - uint8_t ht40PowerIncForPdadc = 2; - int i; - - uint16_t cfgCtl; - uint16_t powerLimit; - uint16_t twiceAntennaReduction; - uint16_t twiceMaxRegulatoryPower; - int16_t maxPower; - HAL_EEPROM_v14 *ee = AH_PRIVATE(ah)->ah_eeprom; - struct ar5416eeprom *pEepData = &ee->ee_base; - - HALASSERT(AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER14_1); - - /* Setup info for the actual eeprom */ - OS_MEMZERO(ratesArray, sizeof(ratesArray)); - cfgCtl = ath_hal_getctl(ah, chan); - powerLimit = chan->ic_maxregpower * 2; - twiceAntennaReduction = chan->ic_maxantgain; - twiceMaxRegulatoryPower = AH_MIN(MAX_RATE_POWER, AH_PRIVATE(ah)->ah_powerLimit); - pModal = &pEepData->modalHeader[IEEE80211_IS_CHAN_2GHZ(chan)]; - HALDEBUG(ah, HAL_DEBUG_RESET, "%s Channel=%u CfgCtl=%u\n", - __func__,chan->ic_freq, cfgCtl ); - - if (IS_EEP_MINOR_V2(ah)) { - ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc; - } - - if (!ar5416SetPowerPerRateTable(ah, pEepData, chan, - &ratesArray[0],cfgCtl, - twiceAntennaReduction, - twiceMaxRegulatoryPower, powerLimit)) { - HALDEBUG(ah, HAL_DEBUG_ANY, - "%s: unable to set tx power per rate table\n", __func__); - return AH_FALSE; - } - - if (!ar5416SetPowerCalTable(ah, pEepData, chan, &txPowerIndexOffset)) { - HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unable to set power table\n", - __func__); - return AH_FALSE; - } - - maxPower = AH_MAX(ratesArray[rate6mb], ratesArray[rateHt20_0]); - - if (IEEE80211_IS_CHAN_2GHZ(chan)) { - maxPower = AH_MAX(maxPower, ratesArray[rate1l]); - } - - if (IEEE80211_IS_CHAN_HT40(chan)) { - maxPower = AH_MAX(maxPower, ratesArray[rateHt40_0]); - } - - ahp->ah_tx6PowerInHalfDbm = maxPower; - AH_PRIVATE(ah)->ah_maxPowerLevel = maxPower; - ahp->ah_txPowerIndexOffset = txPowerIndexOffset; - - /* - * txPowerIndexOffset is set by the SetPowerTable() call - - * adjust the rate table (0 offset if rates EEPROM not loaded) - */ - for (i = 0; i < N(ratesArray); i++) { - ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]); - if (ratesArray[i] > AR5416_MAX_RATE_POWER) - ratesArray[i] = AR5416_MAX_RATE_POWER; - } - -#ifdef AH_EEPROM_DUMP - ar5416PrintPowerPerRate(ah, ratesArray); -#endif /* Write the OFDM power per rate set */ OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE1, @@ -912,18 +939,17 @@ ar5416SetTransmitPower(struct ath_hal *ah, if (IEEE80211_IS_CHAN_HT40(chan)) { /* Write the HT40 power per rate set */ - /* Correct PAR difference between HT40 and HT20/LEGACY */ OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE7, - POW_SM(ratesArray[rateHt40_3] + ht40PowerIncForPdadc, 24) - | POW_SM(ratesArray[rateHt40_2] + ht40PowerIncForPdadc, 16) - | POW_SM(ratesArray[rateHt40_1] + ht40PowerIncForPdadc, 8) - | POW_SM(ratesArray[rateHt40_0] + ht40PowerIncForPdadc, 0) + POW_SM(ratesArray[rateHt40_3], 24) + | POW_SM(ratesArray[rateHt40_2], 16) + | POW_SM(ratesArray[rateHt40_1], 8) + | POW_SM(ratesArray[rateHt40_0], 0) ); OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE8, - POW_SM(ratesArray[rateHt40_7] + ht40PowerIncForPdadc, 24) - | POW_SM(ratesArray[rateHt40_6] + ht40PowerIncForPdadc, 16) - | POW_SM(ratesArray[rateHt40_5] + ht40PowerIncForPdadc, 8) - | POW_SM(ratesArray[rateHt40_4] + ht40PowerIncForPdadc, 0) + POW_SM(ratesArray[rateHt40_7], 24) + | POW_SM(ratesArray[rateHt40_6], 16) + | POW_SM(ratesArray[rateHt40_5], 8) + | POW_SM(ratesArray[rateHt40_4], 0) ); /* Write the Dup/Ext 40 power per rate set */ OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE9, @@ -933,6 +959,177 @@ ar5416SetTransmitPower(struct ath_hal *ah, | POW_SM(ratesArray[rateDupCck], 0) ); } +} + + +/************************************************************** + * ar5416SetTransmitPower + * + * Set the transmit power in the baseband for the given + * operating channel and mode. + */ +HAL_BOOL +ar5416SetTransmitPower(struct ath_hal *ah, + const struct ieee80211_channel *chan, uint16_t *rfXpdGain) +{ +#define N(a) (sizeof (a) / sizeof (a[0])) + + MODAL_EEP_HEADER *pModal; + struct ath_hal_5212 *ahp = AH5212(ah); + int16_t ratesArray[Ar5416RateSize]; + int16_t txPowerIndexOffset = 0; + uint8_t ht40PowerIncForPdadc = 2; + int i; + + uint16_t cfgCtl; + uint16_t powerLimit; + uint16_t twiceAntennaReduction; + uint16_t twiceMaxRegulatoryPower; + int16_t maxPower; + HAL_EEPROM_v14 *ee = AH_PRIVATE(ah)->ah_eeprom; + struct ar5416eeprom *pEepData = &ee->ee_base; + + HALASSERT(AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER14_1); + + /* Setup info for the actual eeprom */ + OS_MEMZERO(ratesArray, sizeof(ratesArray)); + cfgCtl = ath_hal_getctl(ah, chan); + powerLimit = chan->ic_maxregpower * 2; + twiceAntennaReduction = chan->ic_maxantgain; + twiceMaxRegulatoryPower = AH_MIN(MAX_RATE_POWER, AH_PRIVATE(ah)->ah_powerLimit); + pModal = &pEepData->modalHeader[IEEE80211_IS_CHAN_2GHZ(chan)]; + HALDEBUG(ah, HAL_DEBUG_RESET, "%s Channel=%u CfgCtl=%u\n", + __func__,chan->ic_freq, cfgCtl ); + + if (IS_EEP_MINOR_V2(ah)) { + ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc; + } + + if (!ar5416SetPowerPerRateTable(ah, pEepData, chan, + &ratesArray[0],cfgCtl, + twiceAntennaReduction, + twiceMaxRegulatoryPower, powerLimit)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: unable to set tx power per rate table\n", __func__); + return AH_FALSE; + } + + if (!AH5416(ah)->ah_setPowerCalTable(ah, pEepData, chan, &txPowerIndexOffset)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unable to set power table\n", + __func__); + return AH_FALSE; + } + + maxPower = AH_MAX(ratesArray[rate6mb], ratesArray[rateHt20_0]); + + if (IEEE80211_IS_CHAN_2GHZ(chan)) { + maxPower = AH_MAX(maxPower, ratesArray[rate1l]); + } + + if (IEEE80211_IS_CHAN_HT40(chan)) { + maxPower = AH_MAX(maxPower, ratesArray[rateHt40_0]); + } + + ahp->ah_tx6PowerInHalfDbm = maxPower; + AH_PRIVATE(ah)->ah_maxPowerLevel = maxPower; + ahp->ah_txPowerIndexOffset = txPowerIndexOffset; + + /* + * txPowerIndexOffset is set by the SetPowerTable() call - + * adjust the rate table (0 offset if rates EEPROM not loaded) + */ + for (i = 0; i < N(ratesArray); i++) { + ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]); + if (ratesArray[i] > AR5416_MAX_RATE_POWER) + ratesArray[i] = AR5416_MAX_RATE_POWER; + } + +#ifdef AH_EEPROM_DUMP + /* + * Dump the rate array whilst it represents the intended dBm*2 + * values versus what's being adjusted before being programmed + * in. Keep this in mind if you code up this function and enable + * this debugging; the values won't necessarily be what's being + * programmed into the hardware. + */ + ar5416PrintPowerPerRate(ah, ratesArray); +#endif + + /* + * Merlin and later have a power offset, so subtract + * pwr_table_offset * 2 from each value. The default + * power offset is -5 dBm - ie, a register value of 0 + * equates to a TX power of -5 dBm. + */ + if (AR_SREV_MERLIN_20_OR_LATER(ah)) { + int8_t pwr_table_offset; + + (void) ath_hal_eepromGet(ah, AR_EEP_PWR_TABLE_OFFSET, + &pwr_table_offset); + /* Underflow power gets clamped at raw value 0 */ + /* Overflow power gets camped at AR5416_MAX_RATE_POWER */ + for (i = 0; i < N(ratesArray); i++) { + /* + * + pwr_table_offset is in dBm + * + ratesArray is in 1/2 dBm + */ + ratesArray[i] -= (pwr_table_offset * 2); + if (ratesArray[i] < 0) + ratesArray[i] = 0; + else if (ratesArray[i] > AR5416_MAX_RATE_POWER) + ratesArray[i] = AR5416_MAX_RATE_POWER; + } + } + + /* + * Adjust rates for OLC where needed + * + * The following CCK rates need adjusting when doing 2.4ghz + * CCK transmission. + * + * + rate2s, rate2l, rate1l, rate11s, rate11l, rate5_5s, rate5_5l + * + rateExtCck, rateDupCck + * + * They're adjusted here regardless. The hardware then gets + * programmed as needed. 5GHz operation doesn't program in CCK + * rates for legacy mode but they seem to be initialised for + * HT40 regardless of channel type. + */ + if (AR_SREV_MERLIN_20_OR_LATER(ah) && + ath_hal_eepromGetFlag(ah, AR_EEP_OL_PWRCTRL)) { + int adj[] = { + rate2s, rate2l, rate1l, rate11s, rate11l, + rate5_5s, rate5_5l, rateExtCck, rateDupCck + }; + int cck_ofdm_delta = 2; + int i; + for (i = 0; i < N(adj); i++) { + ratesArray[adj[i]] -= cck_ofdm_delta; + if (ratesArray[adj[i]] < 0) + ratesArray[adj[i]] = 0; + } + } + + /* + * Adjust the HT40 power to meet the correct target TX power + * for 40MHz mode, based on TX power curves that are established + * for 20MHz mode. + * + * XXX handle overflow/too high power level? + */ + if (IEEE80211_IS_CHAN_HT40(chan)) { + ratesArray[rateHt40_0] += ht40PowerIncForPdadc; + ratesArray[rateHt40_1] += ht40PowerIncForPdadc; + ratesArray[rateHt40_2] += ht40PowerIncForPdadc; + ratesArray[rateHt40_3] += ht40PowerIncForPdadc; + ratesArray[rateHt40_4] += ht40PowerIncForPdadc; + ratesArray[rateHt40_5] += ht40PowerIncForPdadc; + ratesArray[rateHt40_6] += ht40PowerIncForPdadc; + ratesArray[rateHt40_7] += ht40PowerIncForPdadc; + } + + /* Write the TX power rate registers */ + ar5416WriteTxPowerRateRegisters(ah, chan, ratesArray); /* Write the Power subtraction for dynamic chain changing, for per-packet powertx */ OS_REG_WRITE(ah, AR_PHY_POWER_TX_SUB, @@ -962,7 +1159,11 @@ ar5416Disable(struct ath_hal *ah) { if (!ar5212SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) return AH_FALSE; - return ar5416SetResetReg(ah, HAL_RESET_COLD); + if (! ar5416SetResetReg(ah, HAL_RESET_COLD)) + return AH_FALSE; + + AH5416(ah)->ah_initPLL(ah, AH_NULL); + return AH_TRUE; } /* @@ -974,7 +1175,11 @@ ar5416Disable(struct ath_hal *ah) HAL_BOOL ar5416PhyDisable(struct ath_hal *ah) { - return ar5416SetResetReg(ah, HAL_RESET_WARM); + if (! ar5416SetResetReg(ah, HAL_RESET_WARM)) + return AH_FALSE; + + AH5416(ah)->ah_initPLL(ah, AH_NULL); + return AH_TRUE; } /* @@ -1015,8 +1220,14 @@ ar5416SetResetPowerOn(struct ath_hal *ah) /* * RTC reset and clear */ + if (! AR_SREV_HOWL(ah)) + OS_REG_WRITE(ah, AR_RC, AR_RC_AHB); OS_REG_WRITE(ah, AR_RTC_RESET, 0); OS_DELAY(20); + + if (! AR_SREV_HOWL(ah)) + OS_REG_WRITE(ah, AR_RC, 0); + OS_REG_WRITE(ah, AR_RTC_RESET, 1); /* @@ -1034,6 +1245,18 @@ static HAL_BOOL ar5416SetReset(struct ath_hal *ah, int type) { uint32_t tmpReg, mask; + uint32_t rst_flags; + +#ifdef AH_SUPPORT_AR9130 /* Because of the AR9130 specific registers */ + if (AR_SREV_HOWL(ah)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "[ath] HOWL: Fiddling with derived clk!\n"); + uint32_t val = OS_REG_READ(ah, AR_RTC_DERIVED_CLK); + val &= ~AR_RTC_DERIVED_CLK_PERIOD; + val |= SM(1, AR_RTC_DERIVED_CLK_PERIOD); + OS_REG_WRITE(ah, AR_RTC_DERIVED_CLK, val); + (void) OS_REG_READ(ah, AR_RTC_DERIVED_CLK); + } +#endif /* AH_SUPPORT_AR9130 */ /* * Force wake @@ -1041,31 +1264,35 @@ ar5416SetReset(struct ath_hal *ah, int type) OS_REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT); - /* - * Reset AHB - */ - tmpReg = OS_REG_READ(ah, AR_INTR_SYNC_CAUSE); - if (tmpReg & (AR_INTR_SYNC_LOCAL_TIMEOUT|AR_INTR_SYNC_RADM_CPL_TIMEOUT)) { - OS_REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0); - OS_REG_WRITE(ah, AR_RC, AR_RC_AHB|AR_RC_HOSTIF); +#ifdef AH_SUPPORT_AR9130 + if (AR_SREV_HOWL(ah)) { + rst_flags = AR_RTC_RC_MAC_WARM | AR_RTC_RC_MAC_COLD | + AR_RTC_RC_COLD_RESET | AR_RTC_RC_WARM_RESET; } else { - OS_REG_WRITE(ah, AR_RC, AR_RC_AHB); +#endif /* AH_SUPPORT_AR9130 */ + /* + * Reset AHB + */ + tmpReg = OS_REG_READ(ah, AR_INTR_SYNC_CAUSE); + if (tmpReg & (AR_INTR_SYNC_LOCAL_TIMEOUT|AR_INTR_SYNC_RADM_CPL_TIMEOUT)) { + OS_REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0); + OS_REG_WRITE(ah, AR_RC, AR_RC_AHB|AR_RC_HOSTIF); + } else { + OS_REG_WRITE(ah, AR_RC, AR_RC_AHB); + } + rst_flags = AR_RTC_RC_MAC_WARM; + if (type == HAL_RESET_COLD) + rst_flags |= AR_RTC_RC_MAC_COLD; +#ifdef AH_SUPPORT_AR9130 } +#endif /* AH_SUPPORT_AR9130 */ - /* - * Set Mac(BB,Phy) Warm Reset - */ - switch (type) { - case HAL_RESET_WARM: - OS_REG_WRITE(ah, AR_RTC_RC, AR_RTC_RC_MAC_WARM); - break; - case HAL_RESET_COLD: - OS_REG_WRITE(ah, AR_RTC_RC, AR_RTC_RC_MAC_WARM|AR_RTC_RC_MAC_COLD); - break; - default: - HALASSERT(AH_FALSE); - break; - } + OS_REG_WRITE(ah, AR_RTC_RC, rst_flags); + + if (AR_SREV_HOWL(ah)) + OS_DELAY(10000); + else + OS_DELAY(100); /* * Clear resets and force wakeup @@ -1077,8 +1304,26 @@ ar5416SetReset(struct ath_hal *ah, int type) } /* Clear AHB reset */ - OS_REG_WRITE(ah, AR_RC, 0); + if (! AR_SREV_HOWL(ah)) + OS_REG_WRITE(ah, AR_RC, 0); + if (AR_SREV_HOWL(ah)) + OS_DELAY(50); + + if (AR_SREV_HOWL(ah)) { + uint32_t mask; + mask = OS_REG_READ(ah, AR_CFG); + if (mask & (AR_CFG_SWRB | AR_CFG_SWTB | AR_CFG_SWRG)) { + HALDEBUG(ah, HAL_DEBUG_RESET, + "CFG Byte Swap Set 0x%x\n", mask); + } else { + mask = + INIT_CONFIG_STATUS | AR_CFG_SWRB | AR_CFG_SWTB; + OS_REG_WRITE(ah, AR_CFG, mask); + HALDEBUG(ah, HAL_DEBUG_RESET, + "Setting CFG 0x%x\n", OS_REG_READ(ah, AR_CFG)); + } + } else { if (type == HAL_RESET_COLD) { if (isBigEndian()) { /* @@ -1095,69 +1340,102 @@ ar5416SetReset(struct ath_hal *ah, int type) } else OS_REG_WRITE(ah, AR_CFG, INIT_CONFIG_STATUS); } - - ar5416InitPLL(ah, AH_NULL); + } return AH_TRUE; } -#ifndef IS_5GHZ_FAST_CLOCK_EN -#define IS_5GHZ_FAST_CLOCK_EN(ah, chan) AH_FALSE -#endif +void +ar5416InitChainMasks(struct ath_hal *ah) +{ + int rx_chainmask = AH5416(ah)->ah_rx_chainmask; + /* Flip this for this chainmask regardless of chip */ + if (rx_chainmask == 0x5) + OS_REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, AR_PHY_SWAP_ALT_CHAIN); + + /* + * Workaround for OWL 1.0 calibration failure; enable multi-chain; + * then set true mask after calibration. + */ + if (IS_5416V1(ah) && (rx_chainmask == 0x5 || rx_chainmask == 0x3)) { + OS_REG_WRITE(ah, AR_PHY_RX_CHAINMASK, 0x7); + OS_REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, 0x7); + } else { + OS_REG_WRITE(ah, AR_PHY_RX_CHAINMASK, AH5416(ah)->ah_rx_chainmask); + OS_REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, AH5416(ah)->ah_rx_chainmask); + } + OS_REG_WRITE(ah, AR_SELFGEN_MASK, AH5416(ah)->ah_tx_chainmask); + + if (AH5416(ah)->ah_tx_chainmask == 0x5) + OS_REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, AR_PHY_SWAP_ALT_CHAIN); + + if (AR_SREV_HOWL(ah)) { + OS_REG_WRITE(ah, AR_PHY_ANALOG_SWAP, + OS_REG_READ(ah, AR_PHY_ANALOG_SWAP) | 0x00000001); + } +} + +/* + * Work-around for Owl 1.0 calibration failure. + * + * ar5416InitChainMasks sets the RX chainmask to 0x7 if it's Owl 1.0 + * due to init calibration failures. ar5416RestoreChainMask restores + * these registers to the correct setting. + */ +void +ar5416RestoreChainMask(struct ath_hal *ah) +{ + int rx_chainmask = AH5416(ah)->ah_rx_chainmask; + + if (IS_5416V1(ah) && (rx_chainmask == 0x5 || rx_chainmask == 0x3)) { + OS_REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask); + OS_REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask); + } +} + +/* + * Update the chainmask based on the current channel configuration. + * + * XXX ath9k checks bluetooth co-existence here + * XXX ath9k checks whether the current state is "off-channel". + * XXX ath9k sticks the hardware into 1x1 mode for legacy; + * we're going to leave multi-RX on for multi-path cancellation. + */ static void +ar5416UpdateChainMasks(struct ath_hal *ah, HAL_BOOL is_ht) +{ + struct ath_hal_private *ahpriv = AH_PRIVATE(ah); + HAL_CAPABILITIES *pCap = &ahpriv->ah_caps; + + if (is_ht) { + AH5416(ah)->ah_tx_chainmask = pCap->halTxChainMask; + } else { + AH5416(ah)->ah_tx_chainmask = 1; + } + AH5416(ah)->ah_rx_chainmask = pCap->halRxChainMask; + HALDEBUG(ah, HAL_DEBUG_RESET, "TX chainmask: 0x%x; RX chainmask: 0x%x\n", + AH5416(ah)->ah_tx_chainmask, + AH5416(ah)->ah_rx_chainmask); +} + +void ar5416InitPLL(struct ath_hal *ah, const struct ieee80211_channel *chan) { - uint32_t pll; + uint32_t pll = AR_RTC_PLL_REFDIV_5 | AR_RTC_PLL_DIV2; + if (chan != AH_NULL) { + if (IEEE80211_IS_CHAN_HALF(chan)) + pll |= SM(0x1, AR_RTC_PLL_CLKSEL); + else if (IEEE80211_IS_CHAN_QUARTER(chan)) + pll |= SM(0x2, AR_RTC_PLL_CLKSEL); - if (AR_SREV_MERLIN_20(ah) && - chan != AH_NULL && IEEE80211_IS_CHAN_5GHZ(chan)) { - /* - * PLL WAR for Merlin 2.0/2.1 - * When doing fast clock, set PLL to 0x142c - * Else, set PLL to 0x2850 to prevent reset-to-reset variation - */ - pll = IS_5GHZ_FAST_CLOCK_EN(ah, chan) ? 0x142c : 0x2850; - } else if (AR_SREV_MERLIN_10_OR_LATER(ah)) { - pll = SM(0x5, AR_RTC_SOWL_PLL_REFDIV); - if (chan != AH_NULL) { - if (IEEE80211_IS_CHAN_HALF(chan)) - pll |= SM(0x1, AR_RTC_SOWL_PLL_CLKSEL); - else if (IEEE80211_IS_CHAN_QUARTER(chan)) - pll |= SM(0x2, AR_RTC_SOWL_PLL_CLKSEL); - else if (IEEE80211_IS_CHAN_5GHZ(chan)) - pll |= SM(0x28, AR_RTC_SOWL_PLL_DIV); - else - pll |= SM(0x2c, AR_RTC_SOWL_PLL_DIV); - } else - pll |= SM(0x2c, AR_RTC_SOWL_PLL_DIV); - } else if (AR_SREV_SOWL_10_OR_LATER(ah)) { - pll = SM(0x5, AR_RTC_SOWL_PLL_REFDIV); - if (chan != AH_NULL) { - if (IEEE80211_IS_CHAN_HALF(chan)) - pll |= SM(0x1, AR_RTC_SOWL_PLL_CLKSEL); - else if (IEEE80211_IS_CHAN_QUARTER(chan)) - pll |= SM(0x2, AR_RTC_SOWL_PLL_CLKSEL); - else if (IEEE80211_IS_CHAN_5GHZ(chan)) - pll |= SM(0x50, AR_RTC_SOWL_PLL_DIV); - else - pll |= SM(0x58, AR_RTC_SOWL_PLL_DIV); - } else - pll |= SM(0x58, AR_RTC_SOWL_PLL_DIV); - } else { - pll = AR_RTC_PLL_REFDIV_5 | AR_RTC_PLL_DIV2; - if (chan != AH_NULL) { - if (IEEE80211_IS_CHAN_HALF(chan)) - pll |= SM(0x1, AR_RTC_PLL_CLKSEL); - else if (IEEE80211_IS_CHAN_QUARTER(chan)) - pll |= SM(0x2, AR_RTC_PLL_CLKSEL); - else if (IEEE80211_IS_CHAN_5GHZ(chan)) - pll |= SM(0xa, AR_RTC_PLL_DIV); - else - pll |= SM(0xb, AR_RTC_PLL_DIV); - } else + if (IEEE80211_IS_CHAN_5GHZ(chan)) + pll |= SM(0xa, AR_RTC_PLL_DIV); + else pll |= SM(0xb, AR_RTC_PLL_DIV); - } + } else + pll |= SM(0xb, AR_RTC_PLL_DIV); + OS_REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll); /* TODO: @@ -1169,6 +1447,82 @@ ar5416InitPLL(struct ath_hal *ah, const struct ieee80211_channel *chan) OS_REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_SLEEP_DERIVED_CLK); } +static void +ar5416SetDefGainValues(struct ath_hal *ah, + const MODAL_EEP_HEADER *pModal, + const struct ar5416eeprom *eep, + uint8_t txRxAttenLocal, int regChainOffset, int i) +{ + if (IS_EEP_MINOR_V3(ah)) { + txRxAttenLocal = pModal->txRxAttenCh[i]; + + if (AR_SREV_MERLIN_10_OR_LATER(ah)) { + OS_REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, + AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, + pModal->bswMargin[i]); + OS_REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, + AR_PHY_GAIN_2GHZ_XATTEN1_DB, + pModal->bswAtten[i]); + OS_REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, + AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN, + pModal->xatten2Margin[i]); + OS_REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, + AR_PHY_GAIN_2GHZ_XATTEN2_DB, + pModal->xatten2Db[i]); + } else { + OS_REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, + AR_PHY_GAIN_2GHZ_BSW_MARGIN, + pModal->bswMargin[i]); + OS_REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, + AR_PHY_GAIN_2GHZ_BSW_ATTEN, + pModal->bswAtten[i]); + } + } + + if (AR_SREV_MERLIN_10_OR_LATER(ah)) { + OS_REG_RMW_FIELD(ah, + AR_PHY_RXGAIN + regChainOffset, + AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal); + OS_REG_RMW_FIELD(ah, + AR_PHY_RXGAIN + regChainOffset, + AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[i]); + } else { + OS_REG_RMW_FIELD(ah, + AR_PHY_RXGAIN + regChainOffset, + AR_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal); + OS_REG_RMW_FIELD(ah, + AR_PHY_GAIN_2GHZ + regChainOffset, + AR_PHY_GAIN_2GHZ_RXTX_MARGIN, pModal->rxTxMarginCh[i]); + } +} + +/* + * Get the register chain offset for the given chain. + * + * Take into account the register chain swapping with AR5416 v2.0. + * + * XXX make sure that the reg chain swapping is only done for + * XXX AR5416 v2.0 or greater, and not later chips? + */ +int +ar5416GetRegChainOffset(struct ath_hal *ah, int i) +{ + int regChainOffset; + + if (AR_SREV_5416_V20_OR_LATER(ah) && + (AH5416(ah)->ah_rx_chainmask == 0x5 || + AH5416(ah)->ah_tx_chainmask == 0x5) && (i != 0)) { + /* Regs are swapped from chain 2 to 1 for 5416 2_0 with + * only chains 0 and 2 populated + */ + regChainOffset = (i == 1) ? 0x2000 : 0x1000; + } else { + regChainOffset = i * 0x1000; + } + + return regChainOffset; +} + /* * Read EEPROM header info and program the device for correct operation * given the channel value. @@ -1193,18 +1547,10 @@ ar5416SetBoardValues(struct ath_hal *ah, const struct ieee80211_channel *chan) if (AR_SREV_MERLIN(ah)) { if (i >= 2) break; } - if (AR_SREV_OWL_20_OR_LATER(ah) && - (AH5416(ah)->ah_rx_chainmask == 0x5 || - AH5416(ah)->ah_tx_chainmask == 0x5) && i != 0) { - /* Regs are swapped from chain 2 to 1 for 5416 2_0 with - * only chains 0 and 2 populated - */ - regChainOffset = (i == 1) ? 0x2000 : 0x1000; - } else { - regChainOffset = i * 0x1000; - } + regChainOffset = ar5416GetRegChainOffset(ah, i); OS_REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset, pModal->antCtrlChain[i]); + OS_REG_WRITE(ah, AR_PHY_TIMING_CTRL4 + regChainOffset, (OS_REG_READ(ah, AR_PHY_TIMING_CTRL4 + regChainOffset) & ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF | AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) | @@ -1212,32 +1558,50 @@ ar5416SetBoardValues(struct ath_hal *ah, const struct ieee80211_channel *chan) SM(pModal->iqCalQCh[i], AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF)); /* - * Large signal upgrade. - * XXX update + * Large signal upgrade, + * If 14.3 or later EEPROM, use + * txRxAttenLocal = pModal->txRxAttenCh[i] + * else txRxAttenLocal is fixed value above. */ - if ((i == 0) || AR_SREV_OWL_20_OR_LATER(ah)) { - OS_REG_WRITE(ah, AR_PHY_RXGAIN + regChainOffset, - (OS_REG_READ(ah, AR_PHY_RXGAIN + regChainOffset) & ~AR_PHY_RXGAIN_TXRX_ATTEN) | - SM(IS_EEP_MINOR_V3(ah) ? pModal->txRxAttenCh[i] : txRxAttenLocal, - AR_PHY_RXGAIN_TXRX_ATTEN)); + if ((i == 0) || AR_SREV_5416_V20_OR_LATER(ah)) + ar5416SetDefGainValues(ah, pModal, eep, txRxAttenLocal, regChainOffset, i); - OS_REG_WRITE(ah, AR_PHY_GAIN_2GHZ + regChainOffset, - (OS_REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) & ~AR_PHY_GAIN_2GHZ_RXTX_MARGIN) | - SM(pModal->rxTxMarginCh[i], AR_PHY_GAIN_2GHZ_RXTX_MARGIN)); - } } + if (AR_SREV_MERLIN_10_OR_LATER(ah)) { + if (IEEE80211_IS_CHAN_2GHZ(chan)) { + OS_A_REG_RMW_FIELD(ah, AR_AN_RF2G1_CH0, AR_AN_RF2G1_CH0_OB, pModal->ob); + OS_A_REG_RMW_FIELD(ah, AR_AN_RF2G1_CH0, AR_AN_RF2G1_CH0_DB, pModal->db); + OS_A_REG_RMW_FIELD(ah, AR_AN_RF2G1_CH1, AR_AN_RF2G1_CH1_OB, pModal->ob_ch1); + OS_A_REG_RMW_FIELD(ah, AR_AN_RF2G1_CH1, AR_AN_RF2G1_CH1_DB, pModal->db_ch1); + } else { + OS_A_REG_RMW_FIELD(ah, AR_AN_RF5G1_CH0, AR_AN_RF5G1_CH0_OB5, pModal->ob); + OS_A_REG_RMW_FIELD(ah, AR_AN_RF5G1_CH0, AR_AN_RF5G1_CH0_DB5, pModal->db); + OS_A_REG_RMW_FIELD(ah, AR_AN_RF5G1_CH1, AR_AN_RF5G1_CH1_OB5, pModal->ob_ch1); + OS_A_REG_RMW_FIELD(ah, AR_AN_RF5G1_CH1, AR_AN_RF5G1_CH1_DB5, pModal->db_ch1); + } + OS_A_REG_RMW_FIELD(ah, AR_AN_TOP2, AR_AN_TOP2_XPABIAS_LVL, pModal->xpaBiasLvl); + OS_A_REG_RMW_FIELD(ah, AR_AN_TOP2, AR_AN_TOP2_LOCALBIAS, + !!(pModal->flagBits & AR5416_EEP_FLAG_LOCALBIAS)); + OS_A_REG_RMW_FIELD(ah, AR_PHY_XPA_CFG, AR_PHY_FORCE_XPA_CFG, + !!(pModal->flagBits & AR5416_EEP_FLAG_FORCEXPAON)); + } + OS_REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH, pModal->switchSettling); OS_REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC, pModal->adcDesiredSize); - OS_REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_PGA, pModal->pgaDesiredSize); + + if (! AR_SREV_MERLIN_10_OR_LATER(ah)) + OS_REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_PGA, pModal->pgaDesiredSize); + OS_REG_WRITE(ah, AR_PHY_RF_CTL4, SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF) | SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAB_OFF) | SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAA_ON) | SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAB_ON)); - OS_REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON, pModal->txEndToRxOn); + OS_REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON, + pModal->txEndToRxOn); if (AR_SREV_MERLIN_10_OR_LATER(ah)) { OS_REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62, @@ -1247,46 +1611,44 @@ ar5416SetBoardValues(struct ath_hal *ah, const struct ieee80211_channel *chan) } else { OS_REG_RMW_FIELD(ah, AR_PHY_CCA, AR_PHY_CCA_THRESH62, pModal->thresh62); - OS_REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, AR_PHY_EXT_CCA_THRESH62, + OS_REG_RMW_FIELD(ah, AR_PHY_EXT_CCA, AR_PHY_EXT_CCA_THRESH62, pModal->thresh62); } /* Minor Version Specific application */ if (IS_EEP_MINOR_V2(ah)) { - OS_REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_FRAME_TO_DATA_START, pModal->txFrameToDataStart); - OS_REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_FRAME_TO_PA_ON, pModal->txFrameToPaOn); + OS_REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_FRAME_TO_DATA_START, + pModal->txFrameToDataStart); + OS_REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_FRAME_TO_PA_ON, + pModal->txFrameToPaOn); } - - if (IS_EEP_MINOR_V3(ah)) { - if (IEEE80211_IS_CHAN_HT40(chan)) { + + if (IS_EEP_MINOR_V3(ah) && IEEE80211_IS_CHAN_HT40(chan)) /* Overwrite switch settling with HT40 value */ - OS_REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH, pModal->swSettleHt40); - } - - if ((AR_SREV_OWL_20_OR_LATER(ah)) && - ( AH5416(ah)->ah_rx_chainmask == 0x5 || AH5416(ah)->ah_tx_chainmask == 0x5)){ - /* Reg Offsets are swapped for logical mapping */ - OS_REG_WRITE(ah, AR_PHY_GAIN_2GHZ + 0x1000, (OS_REG_READ(ah, AR_PHY_GAIN_2GHZ + 0x1000) & ~AR_PHY_GAIN_2GHZ_BSW_MARGIN) | - SM(pModal->bswMargin[2], AR_PHY_GAIN_2GHZ_BSW_MARGIN)); - OS_REG_WRITE(ah, AR_PHY_GAIN_2GHZ + 0x1000, (OS_REG_READ(ah, AR_PHY_GAIN_2GHZ + 0x1000) & ~AR_PHY_GAIN_2GHZ_BSW_ATTEN) | - SM(pModal->bswAtten[2], AR_PHY_GAIN_2GHZ_BSW_ATTEN)); - OS_REG_WRITE(ah, AR_PHY_GAIN_2GHZ + 0x2000, (OS_REG_READ(ah, AR_PHY_GAIN_2GHZ + 0x2000) & ~AR_PHY_GAIN_2GHZ_BSW_MARGIN) | - SM(pModal->bswMargin[1], AR_PHY_GAIN_2GHZ_BSW_MARGIN)); - OS_REG_WRITE(ah, AR_PHY_GAIN_2GHZ + 0x2000, (OS_REG_READ(ah, AR_PHY_GAIN_2GHZ + 0x2000) & ~AR_PHY_GAIN_2GHZ_BSW_ATTEN) | - SM(pModal->bswAtten[1], AR_PHY_GAIN_2GHZ_BSW_ATTEN)); - } else { - OS_REG_WRITE(ah, AR_PHY_GAIN_2GHZ + 0x1000, (OS_REG_READ(ah, AR_PHY_GAIN_2GHZ + 0x1000) & ~AR_PHY_GAIN_2GHZ_BSW_MARGIN) | - SM(pModal->bswMargin[1], AR_PHY_GAIN_2GHZ_BSW_MARGIN)); - OS_REG_WRITE(ah, AR_PHY_GAIN_2GHZ + 0x1000, (OS_REG_READ(ah, AR_PHY_GAIN_2GHZ + 0x1000) & ~AR_PHY_GAIN_2GHZ_BSW_ATTEN) | - SM(pModal->bswAtten[1], AR_PHY_GAIN_2GHZ_BSW_ATTEN)); - OS_REG_WRITE(ah, AR_PHY_GAIN_2GHZ + 0x2000, (OS_REG_READ(ah, AR_PHY_GAIN_2GHZ + 0x2000) & ~AR_PHY_GAIN_2GHZ_BSW_MARGIN) | - SM(pModal->bswMargin[2],AR_PHY_GAIN_2GHZ_BSW_MARGIN)); - OS_REG_WRITE(ah, AR_PHY_GAIN_2GHZ + 0x2000, (OS_REG_READ(ah, AR_PHY_GAIN_2GHZ + 0x2000) & ~AR_PHY_GAIN_2GHZ_BSW_ATTEN) | - SM(pModal->bswAtten[2], AR_PHY_GAIN_2GHZ_BSW_ATTEN)); + OS_REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH, + pModal->swSettleHt40); + + if (AR_SREV_MERLIN_20_OR_LATER(ah) && EEP_MINOR(ah) >= AR5416_EEP_MINOR_VER_19) + OS_REG_RMW_FIELD(ah, AR_PHY_CCK_TX_CTRL, AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK, pModal->miscBits); + + if (AR_SREV_MERLIN_20(ah) && EEP_MINOR(ah) >= AR5416_EEP_MINOR_VER_20) { + if (IEEE80211_IS_CHAN_2GHZ(chan)) + OS_A_REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, + eep->baseEepHeader.dacLpMode); + else if (eep->baseEepHeader.dacHiPwrMode_5G) + OS_A_REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, 0); + else + OS_A_REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, + eep->baseEepHeader.dacLpMode); + + OS_DELAY(100); + + OS_REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, AR_PHY_FRAME_CTL_TX_CLIP, + pModal->miscBits >> 2); + OS_REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL9, AR_PHY_TX_DESIRED_SCALE_CCK, + eep->baseEepHeader.desiredScaleCCK); } - OS_REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ, AR_PHY_GAIN_2GHZ_BSW_MARGIN, pModal->bswMargin[0]); - OS_REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ, AR_PHY_GAIN_2GHZ_BSW_ATTEN, pModal->bswAtten[0]); - } + return AH_TRUE; } @@ -1294,6 +1656,63 @@ ar5416SetBoardValues(struct ath_hal *ah, const struct ieee80211_channel *chan) * Helper functions common for AP/CB/XB */ +/* + * Set the target power array "ratesArray" from the + * given set of target powers. + * + * This is used by the various chipset/EEPROM TX power + * setup routines. + */ +void +ar5416SetRatesArrayFromTargetPower(struct ath_hal *ah, + const struct ieee80211_channel *chan, + int16_t *ratesArray, + const CAL_TARGET_POWER_LEG *targetPowerCck, + const CAL_TARGET_POWER_LEG *targetPowerCckExt, + const CAL_TARGET_POWER_LEG *targetPowerOfdm, + const CAL_TARGET_POWER_LEG *targetPowerOfdmExt, + const CAL_TARGET_POWER_HT *targetPowerHt20, + const CAL_TARGET_POWER_HT *targetPowerHt40) +{ +#define N(a) (sizeof(a)/sizeof(a[0])) + int i; + + /* Blank the rates array, to be consistent */ + for (i = 0; i < Ar5416RateSize; i++) + ratesArray[i] = 0; + + /* Set rates Array from collected data */ + ratesArray[rate6mb] = ratesArray[rate9mb] = ratesArray[rate12mb] = + ratesArray[rate18mb] = ratesArray[rate24mb] = targetPowerOfdm->tPow2x[0]; + ratesArray[rate36mb] = targetPowerOfdm->tPow2x[1]; + ratesArray[rate48mb] = targetPowerOfdm->tPow2x[2]; + ratesArray[rate54mb] = targetPowerOfdm->tPow2x[3]; + ratesArray[rateXr] = targetPowerOfdm->tPow2x[0]; + + for (i = 0; i < N(targetPowerHt20->tPow2x); i++) { + ratesArray[rateHt20_0 + i] = targetPowerHt20->tPow2x[i]; + } + + if (IEEE80211_IS_CHAN_2GHZ(chan)) { + ratesArray[rate1l] = targetPowerCck->tPow2x[0]; + ratesArray[rate2s] = ratesArray[rate2l] = targetPowerCck->tPow2x[1]; + ratesArray[rate5_5s] = ratesArray[rate5_5l] = targetPowerCck->tPow2x[2]; + ratesArray[rate11s] = ratesArray[rate11l] = targetPowerCck->tPow2x[3]; + } + if (IEEE80211_IS_CHAN_HT40(chan)) { + for (i = 0; i < N(targetPowerHt40->tPow2x); i++) { + ratesArray[rateHt40_0 + i] = targetPowerHt40->tPow2x[i]; + } + ratesArray[rateDupOfdm] = targetPowerHt40->tPow2x[0]; + ratesArray[rateDupCck] = targetPowerHt40->tPow2x[0]; + ratesArray[rateExtOfdm] = targetPowerOfdmExt->tPow2x[0]; + if (IEEE80211_IS_CHAN_2GHZ(chan)) { + ratesArray[rateExtCck] = targetPowerCckExt->tPow2x[0]; + } + } +#undef N +} + /* * ar5416SetPowerPerRateTable * @@ -1515,33 +1934,13 @@ ar5416SetPowerPerRateTable(struct ath_hal *ah, struct ar5416eeprom *pEepData, } /* end ctl mode checking */ /* Set rates Array from collected data */ - ratesArray[rate6mb] = ratesArray[rate9mb] = ratesArray[rate12mb] = ratesArray[rate18mb] = ratesArray[rate24mb] = targetPowerOfdm.tPow2x[0]; - ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1]; - ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2]; - ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3]; - ratesArray[rateXr] = targetPowerOfdm.tPow2x[0]; - - for (i = 0; i < N(targetPowerHt20.tPow2x); i++) { - ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i]; - } - - if (IEEE80211_IS_CHAN_2GHZ(chan)) { - ratesArray[rate1l] = targetPowerCck.tPow2x[0]; - ratesArray[rate2s] = ratesArray[rate2l] = targetPowerCck.tPow2x[1]; - ratesArray[rate5_5s] = ratesArray[rate5_5l] = targetPowerCck.tPow2x[2]; - ratesArray[rate11s] = ratesArray[rate11l] = targetPowerCck.tPow2x[3]; - } - if (IEEE80211_IS_CHAN_HT40(chan)) { - for (i = 0; i < N(targetPowerHt40.tPow2x); i++) { - ratesArray[rateHt40_0 + i] = targetPowerHt40.tPow2x[i]; - } - ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0]; - ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0]; - ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0]; - if (IEEE80211_IS_CHAN_2GHZ(chan)) { - ratesArray[rateExtCck] = targetPowerCckExt.tPow2x[0]; - } - } + ar5416SetRatesArrayFromTargetPower(ah, chan, ratesArray, + &targetPowerCck, + &targetPowerCckExt, + &targetPowerOfdm, + &targetPowerOfdmExt, + &targetPowerHt20, + &targetPowerHt40); return AH_TRUE; #undef EXT_ADDITIVE #undef CTL_11A_EXT @@ -1577,7 +1976,7 @@ fbin2freq(uint8_t fbin, HAL_BOOL is2GHz) * * Find the maximum conformance test limit for the given channel and CTL info */ -static uint16_t +uint16_t ar5416GetMaxEdgePower(uint16_t freq, CAL_CTL_EDGES *pRdEdgesPower, HAL_BOOL is2GHz) { uint16_t twiceMaxEdgePower = AR5416_MAX_RATE_POWER; @@ -1658,7 +2057,7 @@ ar5416GetTargetPowers(struct ath_hal *ah, const struct ieee80211_channel *chan, chi = fbin2freq(powInfo[lowIndex + 1].bChannel, IEEE80211_IS_CHAN_2GHZ(chan)); for (i = 0; i < numRates; i++) { - pNewPower->tPow2x[i] = (uint8_t)interpolate(freq, clo, chi, + pNewPower->tPow2x[i] = (uint8_t)ath_ee_interpolate(freq, clo, chi, powInfo[lowIndex].tPow2x[i], powInfo[lowIndex + 1].tPow2x[i]); } } @@ -1718,12 +2117,136 @@ ar5416GetTargetPowersLeg(struct ath_hal *ah, chi = fbin2freq(powInfo[lowIndex + 1].bChannel, IEEE80211_IS_CHAN_2GHZ(chan)); for (i = 0; i < numRates; i++) { - pNewPower->tPow2x[i] = (uint8_t)interpolate(freq, clo, chi, + pNewPower->tPow2x[i] = (uint8_t)ath_ee_interpolate(freq, clo, chi, powInfo[lowIndex].tPow2x[i], powInfo[lowIndex + 1].tPow2x[i]); } } } +/* + * Set the gain boundaries for the given radio chain. + * + * The gain boundaries tell the hardware at what point in the + * PDADC array to "switch over" from one PD gain setting + * to another. There's also a gain overlap between two + * PDADC array gain curves where there's valid PD values + * for 2 gain settings. + * + * The hardware uses the gain overlap and gain boundaries + * to determine which gain curve to use for the given + * target TX power. + */ +void +ar5416SetGainBoundariesClosedLoop(struct ath_hal *ah, int i, + uint16_t pdGainOverlap_t2, uint16_t gainBoundaries[]) +{ + int regChainOffset; + + regChainOffset = ar5416GetRegChainOffset(ah, i); + + HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: chain %d: gainOverlap_t2: %d," + " gainBoundaries: %d, %d, %d, %d\n", __func__, i, pdGainOverlap_t2, + gainBoundaries[0], gainBoundaries[1], gainBoundaries[2], + gainBoundaries[3]); + OS_REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset, + SM(pdGainOverlap_t2, AR_PHY_TPCRG5_PD_GAIN_OVERLAP) | + SM(gainBoundaries[0], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) | + SM(gainBoundaries[1], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) | + SM(gainBoundaries[2], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) | + SM(gainBoundaries[3], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4)); +} + +/* + * Get the gain values and the number of gain levels given + * in xpdMask. + * + * The EEPROM xpdMask determines which power detector gain + * levels were used during calibration. Each of these mask + * bits maps to a fixed gain level in hardware. + */ +uint16_t +ar5416GetXpdGainValues(struct ath_hal *ah, uint16_t xpdMask, + uint16_t xpdGainValues[]) +{ + int i; + uint16_t numXpdGain = 0; + + for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) { + if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) { + if (numXpdGain >= AR5416_NUM_PD_GAINS) { + HALASSERT(0); + break; + } + xpdGainValues[numXpdGain] = (uint16_t)(AR5416_PD_GAINS_IN_MASK - i); + numXpdGain++; + } + } + return numXpdGain; +} + +/* + * Write the detector gain and biases. + * + * There are four power detector gain levels. The xpdMask in the EEPROM + * determines which power detector gain levels have TX power calibration + * data associated with them. This function writes the number of + * PD gain levels and their values into the hardware. + * + * This is valid for all TX chains - the calibration data itself however + * will likely differ per-chain. + */ +void +ar5416WriteDetectorGainBiases(struct ath_hal *ah, uint16_t numXpdGain, + uint16_t xpdGainValues[]) +{ + HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: numXpdGain: %d," + " xpdGainValues: %d, %d, %d\n", __func__, numXpdGain, + xpdGainValues[0], xpdGainValues[1], xpdGainValues[2]); + + OS_REG_WRITE(ah, AR_PHY_TPCRG1, (OS_REG_READ(ah, AR_PHY_TPCRG1) & + ~(AR_PHY_TPCRG1_NUM_PD_GAIN | AR_PHY_TPCRG1_PD_GAIN_1 | + AR_PHY_TPCRG1_PD_GAIN_2 | AR_PHY_TPCRG1_PD_GAIN_3)) | + SM(numXpdGain - 1, AR_PHY_TPCRG1_NUM_PD_GAIN) | + SM(xpdGainValues[0], AR_PHY_TPCRG1_PD_GAIN_1 ) | + SM(xpdGainValues[1], AR_PHY_TPCRG1_PD_GAIN_2) | + SM(xpdGainValues[2], AR_PHY_TPCRG1_PD_GAIN_3)); +} + +/* + * Write the PDADC array to the given radio chain i. + * + * The 32 PDADC registers are written without any care about + * their contents - so if various chips treat values as "special", + * this routine will not care. + */ +void +ar5416WritePdadcValues(struct ath_hal *ah, int i, uint8_t pdadcValues[]) +{ + int regOffset, regChainOffset; + int j; + int reg32; + + regChainOffset = ar5416GetRegChainOffset(ah, i); + regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset; + + for (j = 0; j < 32; j++) { + reg32 = ((pdadcValues[4*j + 0] & 0xFF) << 0) | + ((pdadcValues[4*j + 1] & 0xFF) << 8) | + ((pdadcValues[4*j + 2] & 0xFF) << 16) | + ((pdadcValues[4*j + 3] & 0xFF) << 24) ; + OS_REG_WRITE(ah, regOffset, reg32); + HALDEBUG(ah, HAL_DEBUG_EEPROM, "PDADC: Chain %d |" + " PDADC %3d Value %3d | PDADC %3d Value %3d | PDADC %3d" + " Value %3d | PDADC %3d Value %3d |\n", + i, + 4*j, pdadcValues[4*j], + 4*j+1, pdadcValues[4*j + 1], + 4*j+2, pdadcValues[4*j + 2], + 4*j+3, pdadcValues[4*j + 3]); + regOffset += 4; + } +} + /************************************************************** * ar5416SetPowerCalTable * @@ -1731,7 +2254,7 @@ ar5416GetTargetPowersLeg(struct ath_hal *ah, * points as well as from the nearest pier(s) to get a power detector * linear voltage to power level table. */ -static HAL_BOOL +HAL_BOOL ar5416SetPowerCalTable(struct ath_hal *ah, struct ar5416eeprom *pEepData, const struct ieee80211_channel *chan, int16_t *pTxPowerIndexOffset) { @@ -1740,11 +2263,11 @@ ar5416SetPowerCalTable(struct ath_hal *ah, struct ar5416eeprom *pEepData, uint16_t pdGainOverlap_t2; static uint8_t pdadcValues[AR5416_NUM_PDADC_VALUES]; uint16_t gainBoundaries[AR5416_PD_GAINS_IN_MASK]; - uint16_t numPiers, i, j; + uint16_t numPiers, i; int16_t tMinCalPower; uint16_t numXpdGain, xpdMask; uint16_t xpdGainValues[AR5416_NUM_PD_GAINS]; - uint32_t reg32, regOffset, regChainOffset; + uint32_t regChainOffset; OS_MEMZERO(xpdGainValues, sizeof(xpdGainValues)); @@ -1764,36 +2287,14 @@ ar5416SetPowerCalTable(struct ath_hal *ah, struct ar5416eeprom *pEepData, numPiers = AR5416_NUM_5G_CAL_PIERS; } - numXpdGain = 0; /* Calculate the value of xpdgains from the xpdGain Mask */ - for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) { - if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) { - if (numXpdGain >= AR5416_NUM_PD_GAINS) { - HALASSERT(0); - break; - } - xpdGainValues[numXpdGain] = (uint16_t)(AR5416_PD_GAINS_IN_MASK - i); - numXpdGain++; - } - } + numXpdGain = ar5416GetXpdGainValues(ah, xpdMask, xpdGainValues); /* Write the detector gain biases and their number */ - OS_REG_WRITE(ah, AR_PHY_TPCRG1, (OS_REG_READ(ah, AR_PHY_TPCRG1) & - ~(AR_PHY_TPCRG1_NUM_PD_GAIN | AR_PHY_TPCRG1_PD_GAIN_1 | AR_PHY_TPCRG1_PD_GAIN_2 | AR_PHY_TPCRG1_PD_GAIN_3)) | - SM(numXpdGain - 1, AR_PHY_TPCRG1_NUM_PD_GAIN) | SM(xpdGainValues[0], AR_PHY_TPCRG1_PD_GAIN_1 ) | - SM(xpdGainValues[1], AR_PHY_TPCRG1_PD_GAIN_2) | SM(xpdGainValues[2], AR_PHY_TPCRG1_PD_GAIN_3)); + ar5416WriteDetectorGainBiases(ah, numXpdGain, xpdGainValues); for (i = 0; i < AR5416_MAX_CHAINS; i++) { - - if (AR_SREV_OWL_20_OR_LATER(ah) && - ( AH5416(ah)->ah_rx_chainmask == 0x5 || AH5416(ah)->ah_tx_chainmask == 0x5) && (i != 0)) { - /* Regs are swapped from chain 2 to 1 for 5416 2_0 with - * only chains 0 and 2 populated - */ - regChainOffset = (i == 1) ? 0x2000 : 0x1000; - } else { - regChainOffset = i * 0x1000; - } + regChainOffset = ar5416GetRegChainOffset(ah, i); if (pEepData->baseEepHeader.txMask & (1 << i)) { if (IEEE80211_IS_CHAN_2GHZ(chan)) { @@ -1802,47 +2303,20 @@ ar5416SetPowerCalTable(struct ath_hal *ah, struct ar5416eeprom *pEepData, pRawDataset = pEepData->calPierData5G[i]; } - ar5416GetGainBoundariesAndPdadcs(ah, chan, pRawDataset, + /* Fetch the gain boundaries and the PDADC values */ + ar5416GetGainBoundariesAndPdadcs(ah, chan, pRawDataset, pCalBChans, numPiers, pdGainOverlap_t2, &tMinCalPower, gainBoundaries, pdadcValues, numXpdGain); - if ((i == 0) || AR_SREV_OWL_20_OR_LATER(ah)) { - /* - * Note the pdadc table may not start at 0 dBm power, could be - * negative or greater than 0. Need to offset the power - * values by the amount of minPower for griffin - */ - - OS_REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset, - SM(pdGainOverlap_t2, AR_PHY_TPCRG5_PD_GAIN_OVERLAP) | - SM(gainBoundaries[0], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) | - SM(gainBoundaries[1], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) | - SM(gainBoundaries[2], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) | - SM(gainBoundaries[3], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4)); + if ((i == 0) || AR_SREV_5416_V20_OR_LATER(ah)) { + ar5416SetGainBoundariesClosedLoop(ah, i, pdGainOverlap_t2, + gainBoundaries); } /* Write the power values into the baseband power table */ - regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset; - - for (j = 0; j < 32; j++) { - reg32 = ((pdadcValues[4*j + 0] & 0xFF) << 0) | - ((pdadcValues[4*j + 1] & 0xFF) << 8) | - ((pdadcValues[4*j + 2] & 0xFF) << 16) | - ((pdadcValues[4*j + 3] & 0xFF) << 24) ; - OS_REG_WRITE(ah, regOffset, reg32); - -#ifdef PDADC_DUMP - ath_hal_printf(ah, "PDADC: Chain %d | PDADC %3d Value %3d | PDADC %3d Value %3d | PDADC %3d Value %3d | PDADC %3d Value %3d |\n", - i, - 4*j, pdadcValues[4*j], - 4*j+1, pdadcValues[4*j + 1], - 4*j+2, pdadcValues[4*j + 2], - 4*j+3, pdadcValues[4*j + 3]); -#endif - regOffset += 4; - } + ar5416WritePdadcValues(ah, i, pdadcValues); } } *pTxPowerIndexOffset = 0; @@ -1856,7 +2330,7 @@ ar5416SetPowerCalTable(struct ath_hal *ah, struct ar5416eeprom *pEepData, * Uses the data points read from EEPROM to reconstruct the pdadc power table * Called by ar5416SetPowerCalTable only. */ -static void +void ar5416GetGainBoundariesAndPdadcs(struct ath_hal *ah, const struct ieee80211_channel *chan, CAL_DATA_PER_FREQ *pRawDataSet, @@ -1898,15 +2372,15 @@ ar5416GetGainBoundariesAndPdadcs(struct ath_hal *ah, } /* Find pier indexes around the current channel */ - match = getLowerUpperIndex((uint8_t)FREQ2FBIN(centers.synth_center, IEEE80211_IS_CHAN_2GHZ(chan)), - bChans, numPiers, &idxL, &idxR); + match = ath_ee_getLowerUpperIndex((uint8_t)FREQ2FBIN(centers.synth_center, + IEEE80211_IS_CHAN_2GHZ(chan)), bChans, numPiers, &idxL, &idxR); if (match) { /* Directly fill both vpd tables from the matching index */ for (i = 0; i < numXpdGains; i++) { minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0]; maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4]; - ar5416FillVpdTable(minPwrT4[i], maxPwrT4[i], pRawDataSet[idxL].pwrPdg[i], + ath_ee_FillVpdTable(minPwrT4[i], maxPwrT4[i], pRawDataSet[idxL].pwrPdg[i], pRawDataSet[idxL].vpdPdg[i], AR5416_PD_GAIN_ICEPTS, vpdTableI[i]); } } else { @@ -1924,12 +2398,13 @@ ar5416GetGainBoundariesAndPdadcs(struct ath_hal *ah, HALASSERT(maxPwrT4[i] > minPwrT4[i]); /* Fill pier Vpds */ - ar5416FillVpdTable(minPwrT4[i], maxPwrT4[i], pPwrL, pVpdL, AR5416_PD_GAIN_ICEPTS, vpdTableL[i]); - ar5416FillVpdTable(minPwrT4[i], maxPwrT4[i], pPwrR, pVpdR, AR5416_PD_GAIN_ICEPTS, vpdTableR[i]); + ath_ee_FillVpdTable(minPwrT4[i], maxPwrT4[i], pPwrL, pVpdL, AR5416_PD_GAIN_ICEPTS, vpdTableL[i]); + ath_ee_FillVpdTable(minPwrT4[i], maxPwrT4[i], pPwrR, pVpdR, AR5416_PD_GAIN_ICEPTS, vpdTableR[i]); /* Interpolate the final vpd */ for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) { - vpdTableI[i][j] = (uint8_t)(interpolate((uint16_t)FREQ2FBIN(centers.synth_center, IEEE80211_IS_CHAN_2GHZ(chan)), + vpdTableI[i][j] = (uint8_t)(ath_ee_interpolate((uint16_t)FREQ2FBIN(centers.synth_center, + IEEE80211_IS_CHAN_2GHZ(chan)), bChans[idxL], bChans[idxR], vpdTableL[i][j], vpdTableR[i][j])); } } @@ -1947,7 +2422,7 @@ ar5416GetGainBoundariesAndPdadcs(struct ath_hal *ah, pPdGainBoundaries[i] = (uint16_t)AH_MIN(AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]); /* NB: only applies to owl 1.0 */ - if ((i == 0) && !AR_SREV_OWL_20_OR_LATER(ah) ) { + if ((i == 0) && !AR_SREV_5416_V20_OR_LATER(ah) ) { /* * fix the gain delta, but get a delta that can be applied to min to * keep the upper power values accurate, don't think max needs to @@ -1962,7 +2437,10 @@ ar5416GetGainBoundariesAndPdadcs(struct ath_hal *ah, /* Find starting index for this pdGain */ if (i == 0) { - ss = 0; /* for the first pdGain, start from index 0 */ + if (AR_SREV_MERLIN_10_OR_LATER(ah)) + ss = (int16_t)(0 - (minPwrT4[i] / 2)); + else + ss = 0; /* for the first pdGain, start from index 0 */ } else { /* need overlap entries extrapolated below. */ ss = (int16_t)((pPdGainBoundaries[i-1] - (minPwrT4[i] / 2)) - tPdGainOverlap + 1 + minDelta); @@ -1992,7 +2470,7 @@ ar5416GetGainBoundariesAndPdadcs(struct ath_hal *ah, * for last gain, pdGainBoundary == Pmax_t2, so will * have to extrapolate */ - if (tgtIndex > maxIndex) { /* need to extrapolate above */ + if (tgtIndex >= maxIndex) { /* need to extrapolate above */ while ((ss <= tgtIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) { tmpVal = (int16_t)((vpdTableI[i][sizeCurrVpdTable - 1] + (ss - maxIndex +1) * vpdStep)); @@ -2015,129 +2493,28 @@ ar5416GetGainBoundariesAndPdadcs(struct ath_hal *ah, return; } -/************************************************************** - * getLowerUppderIndex - * - * Return indices surrounding the value in sorted integer lists. - * Requirement: the input list must be monotonically increasing - * and populated up to the list size - * Returns: match is set if an index in the array matches exactly - * or a the target is before or after the range of the array. +/* + * The linux ath9k driver and (from what I've been told) the reference + * Atheros driver enables the 11n PHY by default whether or not it's + * configured. */ -HAL_BOOL -getLowerUpperIndex(uint8_t target, uint8_t *pList, uint16_t listSize, - uint16_t *indexL, uint16_t *indexR) -{ - uint16_t i; - - /* - * Check first and last elements for beyond ordered array cases. - */ - if (target <= pList[0]) { - *indexL = *indexR = 0; - return AH_TRUE; - } - if (target >= pList[listSize-1]) { - *indexL = *indexR = (uint16_t)(listSize - 1); - return AH_TRUE; - } - - /* look for value being near or between 2 values in list */ - for (i = 0; i < listSize - 1; i++) { - /* - * If value is close to the current value of the list - * then target is not between values, it is one of the values - */ - if (pList[i] == target) { - *indexL = *indexR = i; - return AH_TRUE; - } - /* - * Look for value being between current value and next value - * if so return these 2 values - */ - if (target < pList[i + 1]) { - *indexL = i; - *indexR = (uint16_t)(i + 1); - return AH_FALSE; - } - } - HALASSERT(0); - *indexL = *indexR = 0; - return AH_FALSE; -} - -/************************************************************** - * ar5416FillVpdTable - * - * Fill the Vpdlist for indices Pmax-Pmin - * Note: pwrMin, pwrMax and Vpdlist are all in dBm * 4 - */ -static HAL_BOOL -ar5416FillVpdTable(uint8_t pwrMin, uint8_t pwrMax, uint8_t *pPwrList, - uint8_t *pVpdList, uint16_t numIntercepts, uint8_t *pRetVpdList) -{ - uint16_t i, k; - uint8_t currPwr = pwrMin; - uint16_t idxL, idxR; - - HALASSERT(pwrMax > pwrMin); - for (i = 0; i <= (pwrMax - pwrMin) / 2; i++) { - getLowerUpperIndex(currPwr, pPwrList, numIntercepts, - &(idxL), &(idxR)); - if (idxR < 1) - idxR = 1; /* extrapolate below */ - if (idxL == numIntercepts - 1) - idxL = (uint16_t)(numIntercepts - 2); /* extrapolate above */ - if (pPwrList[idxL] == pPwrList[idxR]) - k = pVpdList[idxL]; - else - k = (uint16_t)( ((currPwr - pPwrList[idxL]) * pVpdList[idxR] + (pPwrList[idxR] - currPwr) * pVpdList[idxL]) / - (pPwrList[idxR] - pPwrList[idxL]) ); - HALASSERT(k < 256); - pRetVpdList[i] = (uint8_t)k; - currPwr += 2; /* half dB steps */ - } - - return AH_TRUE; -} - -/************************************************************************** - * interpolate - * - * Returns signed interpolated or the scaled up interpolated value - */ -static int16_t -interpolate(uint16_t target, uint16_t srcLeft, uint16_t srcRight, - int16_t targetLeft, int16_t targetRight) -{ - int16_t rv; - - if (srcRight == srcLeft) { - rv = targetLeft; - } else { - rv = (int16_t)( ((target - srcLeft) * targetRight + - (srcRight - target) * targetLeft) / (srcRight - srcLeft) ); - } - return rv; -} - static void ar5416Set11nRegs(struct ath_hal *ah, const struct ieee80211_channel *chan) { uint32_t phymode; + uint32_t enableDacFifo = 0; HAL_HT_MACMODE macmode; /* MAC - 20/40 mode */ - if (!IEEE80211_IS_CHAN_HT(chan)) - return; + if (AR_SREV_KITE_10_OR_LATER(ah)) + enableDacFifo = (OS_REG_READ(ah, AR_PHY_TURBO) & AR_PHY_FC_ENABLE_DAC_FIFO); /* Enable 11n HT, 20 MHz */ phymode = AR_PHY_FC_HT_EN | AR_PHY_FC_SHORT_GI_40 - | AR_PHY_FC_SINGLE_HT_LTF1 | AR_PHY_FC_WALSH; + | AR_PHY_FC_SINGLE_HT_LTF1 | AR_PHY_FC_WALSH | enableDacFifo; /* Configure baseband for dynamic 20/40 operation */ if (IEEE80211_IS_CHAN_HT40(chan)) { - phymode |= AR_PHY_FC_DYN2040_EN | AR_PHY_FC_SHORT_GI_40; + phymode |= AR_PHY_FC_DYN2040_EN; /* Configure control (primary) channel at +-10MHz */ if (IEEE80211_IS_CHAN_HT40U(chan)) @@ -2161,7 +2538,7 @@ ar5416Set11nRegs(struct ath_hal *ah, const struct ieee80211_channel *chan) /* carrier sense timeout */ OS_REG_SET_BIT(ah, AR_GTTM, AR_GTTM_CST_USEC); - OS_REG_WRITE(ah, AR_CST, 1 << AR_CST_TIMEOUT_LIMIT_S); + OS_REG_WRITE(ah, AR_CST, 0xF << AR_CST_TIMEOUT_LIMIT_S); } void @@ -2188,3 +2565,125 @@ ar5416GetChannelCenters(struct ath_hal *ah, centers->ext_center = freq; } } + +/* + * Override the INI vals being programmed. + */ +static void +ar5416OverrideIni(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + uint32_t val; + + /* + * Set the RX_ABORT and RX_DIS and clear if off only after + * RXE is set for MAC. This prevents frames with corrupted + * descriptor status. + */ + OS_REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); + + if (AR_SREV_MERLIN_10_OR_LATER(ah)) { + val = OS_REG_READ(ah, AR_PCU_MISC_MODE2); + val &= (~AR_PCU_MISC_MODE2_ADHOC_MCAST_KEYID_ENABLE); + if (!AR_SREV_9271(ah)) + val &= ~AR_PCU_MISC_MODE2_HWWAR1; + + if (AR_SREV_KIWI_11_OR_LATER(ah)) + val = val & (~AR_PCU_MISC_MODE2_HWWAR2); + + OS_REG_WRITE(ah, AR_PCU_MISC_MODE2, val); + } + + /* + * Disable RIFS search on some chips to avoid baseband + * hang issues. + */ + if (AR_SREV_HOWL(ah) || AR_SREV_SOWL(ah)) + (void) ar5416SetRifsDelay(ah, chan, AH_FALSE); + + if (!AR_SREV_5416_V20_OR_LATER(ah) || AR_SREV_MERLIN(ah)) + return; + + /* + * Disable BB clock gating + * Necessary to avoid issues on AR5416 2.0 + */ + OS_REG_WRITE(ah, 0x9800 + (651 << 2), 0x11); +} + +struct ini { + uint32_t *data; /* NB: !const */ + int rows, cols; +}; + +/* + * Override XPA bias level based on operating frequency. + * This is a v14 EEPROM specific thing for the AR9160. + */ +void +ar5416EepromSetAddac(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ +#define XPA_LVL_FREQ(cnt) (pModal->xpaBiasLvlFreq[cnt]) + MODAL_EEP_HEADER *pModal; + HAL_EEPROM_v14 *ee = AH_PRIVATE(ah)->ah_eeprom; + struct ar5416eeprom *eep = &ee->ee_base; + uint8_t biaslevel; + + if (! AR_SREV_SOWL(ah)) + return; + + if (EEP_MINOR(ah) < AR5416_EEP_MINOR_VER_7) + return; + + pModal = &(eep->modalHeader[IEEE80211_IS_CHAN_2GHZ(chan)]); + + if (pModal->xpaBiasLvl != 0xff) + biaslevel = pModal->xpaBiasLvl; + else { + uint16_t resetFreqBin, freqBin, freqCount = 0; + CHAN_CENTERS centers; + + ar5416GetChannelCenters(ah, chan, ¢ers); + + resetFreqBin = FREQ2FBIN(centers.synth_center, IEEE80211_IS_CHAN_2GHZ(chan)); + freqBin = XPA_LVL_FREQ(0) & 0xff; + biaslevel = (uint8_t) (XPA_LVL_FREQ(0) >> 14); + + freqCount++; + + while (freqCount < 3) { + if (XPA_LVL_FREQ(freqCount) == 0x0) + break; + + freqBin = XPA_LVL_FREQ(freqCount) & 0xff; + if (resetFreqBin >= freqBin) + biaslevel = (uint8_t)(XPA_LVL_FREQ(freqCount) >> 14); + else + break; + freqCount++; + } + } + + HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: overriding XPA bias level = %d\n", + __func__, biaslevel); + + /* + * This is a dirty workaround for the const initval data, + * which will upset multiple AR9160's on the same board. + * + * The HAL should likely just have a private copy of the addac + * data per instance. + */ + if (IEEE80211_IS_CHAN_2GHZ(chan)) + HAL_INI_VAL((struct ini *) &AH5416(ah)->ah_ini_addac, 7, 1) = + (HAL_INI_VAL(&AH5416(ah)->ah_ini_addac, 7, 1) & (~0x18)) | biaslevel << 3; + else + HAL_INI_VAL((struct ini *) &AH5416(ah)->ah_ini_addac, 6, 1) = + (HAL_INI_VAL(&AH5416(ah)->ah_ini_addac, 6, 1) & (~0xc0)) | biaslevel << 6; +#undef XPA_LVL_FREQ +} + +static void +ar5416MarkPhyInactive(struct ath_hal *ah) +{ + OS_REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416_xmit.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416_xmit.c index 47277a18b4..20791e8a5a 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416_xmit.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416_xmit.c @@ -149,8 +149,10 @@ ar5416StopTxDma(struct ath_hal *ah, u_int q) #define VALID_TX_RATES \ ((1<<0x0b)|(1<<0x0f)|(1<<0x0a)|(1<<0x0e)|(1<<0x09)|(1<<0x0d)|\ (1<<0x08)|(1<<0x0c)|(1<<0x1b)|(1<<0x1a)|(1<<0x1e)|(1<<0x19)|\ - (1<<0x1d)|(1<<0x18)|(1<<0x1c)) -#define isValidTxRate(_r) ((1<<(_r)) & VALID_TX_RATES) + (1<<0x1d)|(1<<0x18)|(1<<0x1c)|(1<<0x01)|(1<<0x02)|(1<<0x03)|\ + (1<<0x04)|(1<<0x05)|(1<<0x06)|(1<<0x07)|(1<<0x00)) +/* NB: accept HT rates */ +#define isValidTxRate(_r) ((1<<((_r) & 0x7f)) & VALID_TX_RATES) HAL_BOOL ar5416SetupTxDesc(struct ath_hal *ah, struct ath_desc *ds, @@ -206,10 +208,11 @@ ar5416SetupTxDesc(struct ath_hal *ah, struct ath_desc *ds, | SM(ahp->ah_tx_chainmask, AR_ChainSel2) | SM(ahp->ah_tx_chainmask, AR_ChainSel3) ; - ads->ds_ctl8 = 0; - ads->ds_ctl9 = (txPower << 24); /* XXX? */ - ads->ds_ctl10 = (txPower << 24); /* XXX? */ - ads->ds_ctl11 = (txPower << 24); /* XXX? */ + ads->ds_ctl8 = SM(0, AR_AntCtl0); + ads->ds_ctl9 = SM(0, AR_AntCtl1) | SM(txPower, AR_XmitPower1); + ads->ds_ctl10 = SM(0, AR_AntCtl2) | SM(txPower, AR_XmitPower2); + ads->ds_ctl11 = SM(0, AR_AntCtl3) | SM(txPower, AR_XmitPower3); + if (keyIx != HAL_TXKEYIX_INVALID) { /* XXX validate key index */ ads->ds_ctl1 |= SM(keyIx, AR_DestIdx); @@ -227,9 +230,20 @@ ar5416SetupTxDesc(struct ath_hal *ah, struct ath_desc *ds, ads->ds_ctl0 |= (flags & HAL_TXDESC_CTSENA ? AR_CTSEnable : 0) | (flags & HAL_TXDESC_RTSENA ? AR_RTSEnable : 0) ; - ads->ds_ctl2 |= SM(rtsctsDuration, AR_BurstDur); ads->ds_ctl7 |= (rtsctsRate << AR_RTSCTSRate_S); } + + /* + * Set the TX antenna to 0 for Kite + * To preserve existing behaviour, also set the TPC bits to 0; + * when TPC is enabled these should be filled in appropriately. + */ + if (AR_SREV_KITE(ah)) { + ads->ds_ctl8 = SM(0, AR_AntCtl0); + ads->ds_ctl9 = SM(0, AR_AntCtl1) | SM(0, AR_XmitPower1); + ads->ds_ctl10 = SM(0, AR_AntCtl2) | SM(0, AR_XmitPower2); + ads->ds_ctl11 = SM(0, AR_AntCtl3) | SM(0, AR_XmitPower3); + } return AH_TRUE; #undef RTSCTS } @@ -304,8 +318,6 @@ ar5416FillTxDesc(struct ath_hal *ah, struct ath_desc *ds, return AH_TRUE; } -#if 0 - HAL_BOOL ar5416ChainTxDesc(struct ath_hal *ah, struct ath_desc *ds, u_int pktLen, @@ -320,6 +332,7 @@ ar5416ChainTxDesc(struct ath_hal *ah, struct ath_desc *ds, { struct ar5416_desc *ads = AR5416DESC(ds); uint32_t *ds_txstatus = AR5416_DS_TXSTATUS(ah,ads); + struct ath_hal_5416 *ahp = AH5416(ah); int isaggr = 0; @@ -335,7 +348,7 @@ ar5416ChainTxDesc(struct ath_hal *ah, struct ath_desc *ds, } if (!firstSeg) { - ath_hal_memzero(ds->ds_hw, AR5416_DESC_TX_CTL_SZ); + OS_MEMZERO(ds->ds_hw, AR5416_DESC_TX_CTL_SZ); } ads->ds_ctl0 = (pktLen & AR_FrameLen); @@ -349,7 +362,7 @@ ar5416ChainTxDesc(struct ath_hal *ah, struct ath_desc *ds, ads->ds_ctl0 |= AR_DestIdxValid; } - ads->ds_ctl6 = SM(keyType[cipher], AR_EncrType); + ads->ds_ctl6 = SM(ahp->ah_keytype[cipher], AR_EncrType); if (isaggr) { ads->ds_ctl6 |= SM(delims, AR_PadDelim); } @@ -403,10 +416,10 @@ ar5416SetupFirstTxDesc(struct ath_hal *ah, struct ath_desc *ds, | SM(AH5416(ah)->ah_tx_chainmask, AR_ChainSel3); /* NB: no V1 WAR */ - ads->ds_ctl8 = 0; - ads->ds_ctl9 = (txPower << 24); - ads->ds_ctl10 = (txPower << 24); - ads->ds_ctl11 = (txPower << 24); + ads->ds_ctl8 = SM(0, AR_AntCtl0); + ads->ds_ctl9 = SM(0, AR_AntCtl1) | SM(txPower, AR_XmitPower1); + ads->ds_ctl10 = SM(0, AR_AntCtl2) | SM(txPower, AR_XmitPower2); + ads->ds_ctl11 = SM(0, AR_AntCtl3) | SM(txPower, AR_XmitPower3); ads->ds_ctl6 &= ~(0xffff); ads->ds_ctl6 |= SM(aggrLen, AR_AggrLen); @@ -415,7 +428,18 @@ ar5416SetupFirstTxDesc(struct ath_hal *ah, struct ath_desc *ds, /* XXX validate rtsctsDuration */ ads->ds_ctl0 |= (flags & HAL_TXDESC_CTSENA ? AR_CTSEnable : 0) | (flags & HAL_TXDESC_RTSENA ? AR_RTSEnable : 0); - ads->ds_ctl2 |= SM(rtsctsDuration, AR_BurstDur); + } + + /* + * Set the TX antenna to 0 for Kite + * To preserve existing behaviour, also set the TPC bits to 0; + * when TPC is enabled these should be filled in appropriately. + */ + if (AR_SREV_KITE(ah)) { + ads->ds_ctl8 = SM(0, AR_AntCtl0); + ads->ds_ctl9 = SM(0, AR_AntCtl1) | SM(0, AR_XmitPower1); + ads->ds_ctl10 = SM(0, AR_AntCtl2) | SM(0, AR_XmitPower2); + ads->ds_ctl11 = SM(0, AR_AntCtl3) | SM(0, AR_XmitPower3); } return AH_TRUE; @@ -442,7 +466,6 @@ ar5416SetupLastTxDesc(struct ath_hal *ah, struct ath_desc *ds, return AH_TRUE; } -#endif /* 0 */ #ifdef AH_NEED_DESC_SWAP /* Swap transmit descriptor */ @@ -574,7 +597,6 @@ ar5416ProcTxDesc(struct ath_hal *ah, return HAL_OK; } -#if 0 HAL_BOOL ar5416SetGlobalTxTimeout(struct ath_hal *ah, u_int tu) { @@ -601,13 +623,49 @@ ar5416GetGlobalTxTimeout(struct ath_hal *ah) void ar5416Set11nRateScenario(struct ath_hal *ah, struct ath_desc *ds, u_int durUpdateEn, u_int rtsctsRate, - HAL_11N_RATE_SERIES series[], u_int nseries) + HAL_11N_RATE_SERIES series[], u_int nseries, u_int flags) { struct ar5416_desc *ads = AR5416DESC(ds); + uint32_t ds_ctl0; HALASSERT(nseries == 4); (void)nseries; + /* + * XXX since the upper layers doesn't know the current chainmask + * XXX setup, just override its decisions here. + * XXX The upper layers need to be taught this! + */ + if (series[0].Tries != 0) + series[0].ChSel = AH5416(ah)->ah_tx_chainmask; + if (series[1].Tries != 0) + series[1].ChSel = AH5416(ah)->ah_tx_chainmask; + if (series[2].Tries != 0) + series[2].ChSel = AH5416(ah)->ah_tx_chainmask; + if (series[3].Tries != 0) + series[3].ChSel = AH5416(ah)->ah_tx_chainmask; + + /* + * Only one of RTS and CTS enable must be set. + * If a frame has both set, just do RTS protection - + * that's enough to satisfy legacy protection. + */ + if (flags & (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA)) { + ds_ctl0 = ads->ds_ctl0; + + if (flags & HAL_TXDESC_RTSENA) { + ds_ctl0 &= ~AR_CTSEnable; + ds_ctl0 |= AR_RTSEnable; + } else { + ds_ctl0 &= ~AR_RTSEnable; + ds_ctl0 |= AR_CTSEnable; + } + + ads->ds_ctl0 = ds_ctl0; + } else { + ads->ds_ctl0 = + (ads->ds_ctl0 & ~(AR_RTSEnable | AR_CTSEnable)); + } ads->ds_ctl2 = set11nTries(series, 0) | set11nTries(series, 1) @@ -631,27 +689,6 @@ ar5416Set11nRateScenario(struct ath_hal *ah, struct ath_desc *ds, | set11nRateFlags(series, 2) | set11nRateFlags(series, 3) | SM(rtsctsRate, AR_RTSCTSRate); - - /* - * Enable RTSCTS if any of the series is flagged for RTSCTS, - * but only if CTS is not enabled. - */ - /* - * FIXME : the entire RTS/CTS handling should be moved to this - * function (by passing the global RTS/CTS flags to this function). - * currently it is split between this function and the - * setupFiirstDescriptor. with this current implementation there - * is an implicit assumption that setupFirstDescriptor is called - * before this function. - */ - if (((series[0].RateFlags & HAL_RATESERIES_RTS_CTS) || - (series[1].RateFlags & HAL_RATESERIES_RTS_CTS) || - (series[2].RateFlags & HAL_RATESERIES_RTS_CTS) || - (series[3].RateFlags & HAL_RATESERIES_RTS_CTS) ) && - (ads->ds_ctl0 & AR_CTSEnable) == 0) { - ads->ds_ctl0 |= AR_RTSEnable; - ads->ds_ctl0 &= ~AR_CTSEnable; - } } void @@ -692,4 +729,380 @@ ar5416Set11nBurstDuration(struct ath_hal *ah, struct ath_desc *ds, ads->ds_ctl2 &= ~AR_BurstDur; ads->ds_ctl2 |= SM(burstDuration, AR_BurstDur); } -#endif + +/* + * Retrieve the rate table from the given TX completion descriptor + */ +HAL_BOOL +ar5416GetTxCompletionRates(struct ath_hal *ah, const struct ath_desc *ds0, int *rates, int *tries) +{ + const struct ar5416_desc *ads = AR5416DESC_CONST(ds0); + + rates[0] = MS(ads->ds_ctl3, AR_XmitRate0); + rates[1] = MS(ads->ds_ctl3, AR_XmitRate1); + rates[2] = MS(ads->ds_ctl3, AR_XmitRate2); + rates[3] = MS(ads->ds_ctl3, AR_XmitRate3); + + tries[0] = MS(ads->ds_ctl2, AR_XmitDataTries0); + tries[1] = MS(ads->ds_ctl2, AR_XmitDataTries1); + tries[2] = MS(ads->ds_ctl2, AR_XmitDataTries2); + tries[3] = MS(ads->ds_ctl2, AR_XmitDataTries3); + + return AH_TRUE; +} + + +/* + * TX queue management routines - AR5416 and later chipsets + */ + +/* + * Allocate and initialize a tx DCU/QCU combination. + */ +int +ar5416SetupTxQueue(struct ath_hal *ah, HAL_TX_QUEUE type, + const HAL_TXQ_INFO *qInfo) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + HAL_TX_QUEUE_INFO *qi; + HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; + int q, defqflags; + + /* by default enable OK+ERR+DESC+URN interrupts */ + defqflags = HAL_TXQ_TXOKINT_ENABLE + | HAL_TXQ_TXERRINT_ENABLE + | HAL_TXQ_TXDESCINT_ENABLE + | HAL_TXQ_TXURNINT_ENABLE; + /* XXX move queue assignment to driver */ + switch (type) { + case HAL_TX_QUEUE_BEACON: + q = pCap->halTotalQueues-1; /* highest priority */ + defqflags |= HAL_TXQ_DBA_GATED + | HAL_TXQ_CBR_DIS_QEMPTY + | HAL_TXQ_ARB_LOCKOUT_GLOBAL + | HAL_TXQ_BACKOFF_DISABLE; + break; + case HAL_TX_QUEUE_CAB: + q = pCap->halTotalQueues-2; /* next highest priority */ + defqflags |= HAL_TXQ_DBA_GATED + | HAL_TXQ_CBR_DIS_QEMPTY + | HAL_TXQ_CBR_DIS_BEMPTY + | HAL_TXQ_ARB_LOCKOUT_GLOBAL + | HAL_TXQ_BACKOFF_DISABLE; + break; + case HAL_TX_QUEUE_PSPOLL: + q = 1; /* lowest priority */ + defqflags |= HAL_TXQ_DBA_GATED + | HAL_TXQ_CBR_DIS_QEMPTY + | HAL_TXQ_CBR_DIS_BEMPTY + | HAL_TXQ_ARB_LOCKOUT_GLOBAL + | HAL_TXQ_BACKOFF_DISABLE; + break; + case HAL_TX_QUEUE_UAPSD: + q = pCap->halTotalQueues-3; /* nextest highest priority */ + if (ahp->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: no available UAPSD tx queue\n", __func__); + return -1; + } + break; + case HAL_TX_QUEUE_DATA: + for (q = 0; q < pCap->halTotalQueues; q++) + if (ahp->ah_txq[q].tqi_type == HAL_TX_QUEUE_INACTIVE) + break; + if (q == pCap->halTotalQueues) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: no available tx queue\n", __func__); + return -1; + } + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: bad tx queue type %u\n", __func__, type); + return -1; + } + + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: queue %u\n", __func__, q); + + qi = &ahp->ah_txq[q]; + if (qi->tqi_type != HAL_TX_QUEUE_INACTIVE) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: tx queue %u already active\n", + __func__, q); + return -1; + } + OS_MEMZERO(qi, sizeof(HAL_TX_QUEUE_INFO)); + qi->tqi_type = type; + if (qInfo == AH_NULL) { + qi->tqi_qflags = defqflags; + qi->tqi_aifs = INIT_AIFS; + qi->tqi_cwmin = HAL_TXQ_USEDEFAULT; /* NB: do at reset */ + qi->tqi_cwmax = INIT_CWMAX; + qi->tqi_shretry = INIT_SH_RETRY; + qi->tqi_lgretry = INIT_LG_RETRY; + qi->tqi_physCompBuf = 0; + } else { + qi->tqi_physCompBuf = qInfo->tqi_compBuf; + (void) ar5212SetTxQueueProps(ah, q, qInfo); + } + /* NB: must be followed by ar5212ResetTxQueue */ + return q; +} + +/* + * Update the h/w interrupt registers to reflect a tx q's configuration. + */ +static void +setTxQInterrupts(struct ath_hal *ah, HAL_TX_QUEUE_INFO *qi) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, + "%s: tx ok 0x%x err 0x%x desc 0x%x eol 0x%x urn 0x%x\n", __func__, + ahp->ah_txOkInterruptMask, ahp->ah_txErrInterruptMask, + ahp->ah_txDescInterruptMask, ahp->ah_txEolInterruptMask, + ahp->ah_txUrnInterruptMask); + + OS_REG_WRITE(ah, AR_IMR_S0, + SM(ahp->ah_txOkInterruptMask, AR_IMR_S0_QCU_TXOK) + | SM(ahp->ah_txDescInterruptMask, AR_IMR_S0_QCU_TXDESC) + ); + OS_REG_WRITE(ah, AR_IMR_S1, + SM(ahp->ah_txErrInterruptMask, AR_IMR_S1_QCU_TXERR) + | SM(ahp->ah_txEolInterruptMask, AR_IMR_S1_QCU_TXEOL) + ); + OS_REG_RMW_FIELD(ah, AR_IMR_S2, + AR_IMR_S2_QCU_TXURN, ahp->ah_txUrnInterruptMask); +} + +/* + * Set the retry, aifs, cwmin/max, readyTime regs for specified queue + * Assumes: + * phwChannel has been set to point to the current channel + */ +HAL_BOOL +ar5416ResetTxQueue(struct ath_hal *ah, u_int q) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; + const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan; + HAL_TX_QUEUE_INFO *qi; + uint32_t cwMin, chanCwMin, value, qmisc, dmisc; + + if (q >= pCap->halTotalQueues) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n", + __func__, q); + return AH_FALSE; + } + qi = &ahp->ah_txq[q]; + if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) { + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: inactive queue %u\n", + __func__, q); + return AH_TRUE; /* XXX??? */ + } + + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: reset queue %u\n", __func__, q); + + if (qi->tqi_cwmin == HAL_TXQ_USEDEFAULT) { + /* + * Select cwmin according to channel type. + * NB: chan can be NULL during attach + */ + if (chan && IEEE80211_IS_CHAN_B(chan)) + chanCwMin = INIT_CWMIN_11B; + else + chanCwMin = INIT_CWMIN; + /* make sure that the CWmin is of the form (2^n - 1) */ + for (cwMin = 1; cwMin < chanCwMin; cwMin = (cwMin << 1) | 1) + ; + } else + cwMin = qi->tqi_cwmin; + + /* set cwMin/Max and AIFS values */ + OS_REG_WRITE(ah, AR_DLCL_IFS(q), + SM(cwMin, AR_D_LCL_IFS_CWMIN) + | SM(qi->tqi_cwmax, AR_D_LCL_IFS_CWMAX) + | SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS)); + + /* Set retry limit values */ + OS_REG_WRITE(ah, AR_DRETRY_LIMIT(q), + SM(INIT_SSH_RETRY, AR_D_RETRY_LIMIT_STA_SH) + | SM(INIT_SLG_RETRY, AR_D_RETRY_LIMIT_STA_LG) + | SM(qi->tqi_lgretry, AR_D_RETRY_LIMIT_FR_LG) + | SM(qi->tqi_shretry, AR_D_RETRY_LIMIT_FR_SH) + ); + + /* NB: always enable early termination on the QCU */ + qmisc = AR_Q_MISC_DCU_EARLY_TERM_REQ + | SM(AR_Q_MISC_FSP_ASAP, AR_Q_MISC_FSP); + + /* NB: always enable DCU to wait for next fragment from QCU */ + dmisc = AR_D_MISC_FRAG_WAIT_EN; + + /* Enable exponential backoff window */ + dmisc |= AR_D_MISC_BKOFF_PERSISTENCE; + + /* + * The chip reset default is to use a DCU backoff threshold of 0x2. + * Restore this when programming the DCU MISC register. + */ + dmisc |= 0x2; + + /* multiqueue support */ + if (qi->tqi_cbrPeriod) { + OS_REG_WRITE(ah, AR_QCBRCFG(q), + SM(qi->tqi_cbrPeriod,AR_Q_CBRCFG_CBR_INTERVAL) + | SM(qi->tqi_cbrOverflowLimit, AR_Q_CBRCFG_CBR_OVF_THRESH)); + qmisc = (qmisc &~ AR_Q_MISC_FSP) | AR_Q_MISC_FSP_CBR; + if (qi->tqi_cbrOverflowLimit) + qmisc |= AR_Q_MISC_CBR_EXP_CNTR_LIMIT; + } + if (qi->tqi_readyTime) { + OS_REG_WRITE(ah, AR_QRDYTIMECFG(q), + SM(qi->tqi_readyTime, AR_Q_RDYTIMECFG_INT) + | AR_Q_RDYTIMECFG_ENA); + } + + OS_REG_WRITE(ah, AR_DCHNTIME(q), + SM(qi->tqi_burstTime, AR_D_CHNTIME_DUR) + | (qi->tqi_burstTime ? AR_D_CHNTIME_EN : 0)); + + if (qi->tqi_readyTime && + (qi->tqi_qflags & HAL_TXQ_RDYTIME_EXP_POLICY_ENABLE)) + qmisc |= AR_Q_MISC_RDYTIME_EXP_POLICY; + if (qi->tqi_qflags & HAL_TXQ_DBA_GATED) + qmisc = (qmisc &~ AR_Q_MISC_FSP) | AR_Q_MISC_FSP_DBA_GATED; + if (MS(qmisc, AR_Q_MISC_FSP) != AR_Q_MISC_FSP_ASAP) { + /* + * These are meangingful only when not scheduled asap. + */ + if (qi->tqi_qflags & HAL_TXQ_CBR_DIS_BEMPTY) + qmisc |= AR_Q_MISC_CBR_INCR_DIS0; + else + qmisc &= ~AR_Q_MISC_CBR_INCR_DIS0; + if (qi->tqi_qflags & HAL_TXQ_CBR_DIS_QEMPTY) + qmisc |= AR_Q_MISC_CBR_INCR_DIS1; + else + qmisc &= ~AR_Q_MISC_CBR_INCR_DIS1; + } + + if (qi->tqi_qflags & HAL_TXQ_BACKOFF_DISABLE) + dmisc |= AR_D_MISC_POST_FR_BKOFF_DIS; + if (qi->tqi_qflags & HAL_TXQ_FRAG_BURST_BACKOFF_ENABLE) + dmisc |= AR_D_MISC_FRAG_BKOFF_EN; + if (qi->tqi_qflags & HAL_TXQ_ARB_LOCKOUT_GLOBAL) + dmisc |= SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL, + AR_D_MISC_ARB_LOCKOUT_CNTRL); + else if (qi->tqi_qflags & HAL_TXQ_ARB_LOCKOUT_INTRA) + dmisc |= SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_INTRA_FR, + AR_D_MISC_ARB_LOCKOUT_CNTRL); + if (qi->tqi_qflags & HAL_TXQ_IGNORE_VIRTCOL) + dmisc |= SM(AR_D_MISC_VIR_COL_HANDLING_IGNORE, + AR_D_MISC_VIR_COL_HANDLING); + if (qi->tqi_qflags & HAL_TXQ_SEQNUM_INC_DIS) + dmisc |= AR_D_MISC_SEQ_NUM_INCR_DIS; + + /* + * Fillin type-dependent bits. Most of this can be + * removed by specifying the queue parameters in the + * driver; it's here for backwards compatibility. + */ + switch (qi->tqi_type) { + case HAL_TX_QUEUE_BEACON: /* beacon frames */ + qmisc |= AR_Q_MISC_FSP_DBA_GATED + | AR_Q_MISC_BEACON_USE + | AR_Q_MISC_CBR_INCR_DIS1; + + dmisc |= SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL, + AR_D_MISC_ARB_LOCKOUT_CNTRL) + | AR_D_MISC_BEACON_USE + | AR_D_MISC_POST_FR_BKOFF_DIS; + break; + case HAL_TX_QUEUE_CAB: /* CAB frames */ + /* + * No longer Enable AR_Q_MISC_RDYTIME_EXP_POLICY, + * There is an issue with the CAB Queue + * not properly refreshing the Tx descriptor if + * the TXE clear setting is used. + */ + qmisc |= AR_Q_MISC_FSP_DBA_GATED + | AR_Q_MISC_CBR_INCR_DIS1 + | AR_Q_MISC_CBR_INCR_DIS0; + + if (!qi->tqi_readyTime) { + /* + * NB: don't set default ready time if driver + * has explicitly specified something. This is + * here solely for backwards compatibility. + */ + value = (ahp->ah_beaconInterval + - (ah->ah_config.ah_sw_beacon_response_time - + ah->ah_config.ah_dma_beacon_response_time) + - ah->ah_config.ah_additional_swba_backoff) * 1024; + OS_REG_WRITE(ah, AR_QRDYTIMECFG(q), value | AR_Q_RDYTIMECFG_ENA); + } + dmisc |= SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL, + AR_D_MISC_ARB_LOCKOUT_CNTRL); + break; + case HAL_TX_QUEUE_PSPOLL: + qmisc |= AR_Q_MISC_CBR_INCR_DIS1; + break; + case HAL_TX_QUEUE_UAPSD: + dmisc |= AR_D_MISC_POST_FR_BKOFF_DIS; + break; + default: /* NB: silence compiler */ + break; + } + + OS_REG_WRITE(ah, AR_QMISC(q), qmisc); + OS_REG_WRITE(ah, AR_DMISC(q), dmisc); + + /* Setup compression scratchpad buffer */ + /* + * XXX: calling this asynchronously to queue operation can + * cause unexpected behavior!!! + */ + if (qi->tqi_physCompBuf) { + HALASSERT(qi->tqi_type == HAL_TX_QUEUE_DATA || + qi->tqi_type == HAL_TX_QUEUE_UAPSD); + OS_REG_WRITE(ah, AR_Q_CBBS, (80 + 2*q)); + OS_REG_WRITE(ah, AR_Q_CBBA, qi->tqi_physCompBuf); + OS_REG_WRITE(ah, AR_Q_CBC, HAL_COMP_BUF_MAX_SIZE/1024); + OS_REG_WRITE(ah, AR_Q0_MISC + 4*q, + OS_REG_READ(ah, AR_Q0_MISC + 4*q) + | AR_Q_MISC_QCU_COMP_EN); + } + + /* + * Always update the secondary interrupt mask registers - this + * could be a new queue getting enabled in a running system or + * hw getting re-initialized during a reset! + * + * Since we don't differentiate between tx interrupts corresponding + * to individual queues - secondary tx mask regs are always unmasked; + * tx interrupts are enabled/disabled for all queues collectively + * using the primary mask reg + */ + if (qi->tqi_qflags & HAL_TXQ_TXOKINT_ENABLE) + ahp->ah_txOkInterruptMask |= 1 << q; + else + ahp->ah_txOkInterruptMask &= ~(1 << q); + if (qi->tqi_qflags & HAL_TXQ_TXERRINT_ENABLE) + ahp->ah_txErrInterruptMask |= 1 << q; + else + ahp->ah_txErrInterruptMask &= ~(1 << q); + if (qi->tqi_qflags & HAL_TXQ_TXDESCINT_ENABLE) + ahp->ah_txDescInterruptMask |= 1 << q; + else + ahp->ah_txDescInterruptMask &= ~(1 << q); + if (qi->tqi_qflags & HAL_TXQ_TXEOLINT_ENABLE) + ahp->ah_txEolInterruptMask |= 1 << q; + else + ahp->ah_txEolInterruptMask &= ~(1 << q); + if (qi->tqi_qflags & HAL_TXQ_TXURNINT_ENABLE) + ahp->ah_txUrnInterruptMask |= 1 << q; + else + ahp->ah_txUrnInterruptMask &= ~(1 << q); + setTxQInterrupts(ah, qi); + + return AH_TRUE; +} diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416desc.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416desc.h index e52ded6355..105c5d6080 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416desc.h +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416desc.h @@ -205,6 +205,29 @@ struct ar5416_desc { #define AR_STBC2 0x40000000 #define AR_STBC3 0x80000000 +/* ds_ctl8 */ +#define AR_AntCtl0 0x00ffffff +#define AR_AntCtl0_S 0 +/* Xmit 0 TPC is AR_XmitPower in ctl0 */ + +/* ds_ctl9 */ +#define AR_AntCtl1 0x00ffffff +#define AR_AntCtl1_S 0 +#define AR_XmitPower1 0xff000000 +#define AR_XmitPower1_S 24 + +/* ds_ctl10 */ +#define AR_AntCtl2 0x00ffffff +#define AR_AntCtl2_S 0 +#define AR_XmitPower2 0xff000000 +#define AR_XmitPower2_S 24 + +/* ds_ctl11 */ +#define AR_AntCtl3 0x00ffffff +#define AR_AntCtl3_S 0 +#define AR_XmitPower3 0xff000000 +#define AR_XmitPower3_S 24 + /************* * TX Status * *************/ @@ -387,11 +410,11 @@ struct ar5416_desc { #define RXSTATUS_OFFSET(ah) 4 #define RXSTATUS_NUMWORDS(ah) 9 #define RXSTATUS_RATE(ah, ads) \ - (AR_SREV_OWL_20_OR_LATER(ah) ? \ + (AR_SREV_5416_V20_OR_LATER(ah) ? \ MS((ads)->ds_rxstatus0, AR_RxRate) : \ ((ads)->ds_rxstatus3 >> 2) & 0xFF) #define RXSTATUS_DUPLICATE(ah, ads) \ - (AR_SREV_OWL_20_OR_LATER(ah) ? \ + (AR_SREV_5416_V20_OR_LATER(ah) ? \ MS((ads)->ds_rxstatus3, AR_Parallel40) : \ ((ads)->ds_rxstatus3 >> 10) & 0x1) #endif /* _ATH_AR5416_DESC_H_ */ diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416phy.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416phy.h index d5185b6ffd..d7a5e0b22b 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416phy.h +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416phy.h @@ -21,6 +21,25 @@ #include "ar5212/ar5212phy.h" +/* For AR_PHY_RADAR0 */ +#define AR_PHY_RADAR_0_FFT_ENA 0x80000000 + +#define AR_PHY_RADAR_EXT 0x9940 +#define AR_PHY_RADAR_EXT_ENA 0x00004000 + +#define AR_PHY_RADAR_1 0x9958 +#define AR_PHY_RADAR_1_RELPWR_ENA 0x00800000 +#define AR_PHY_RADAR_1_USE_FIR128 0x00400000 +#define AR_PHY_RADAR_1_RELPWR_THRESH 0x003F0000 +#define AR_PHY_RADAR_1_RELPWR_THRESH_S 16 +#define AR_PHY_RADAR_1_BLOCK_CHECK 0x00008000 +#define AR_PHY_RADAR_1_MAX_RRSSI 0x00004000 +#define AR_PHY_RADAR_1_RELSTEP_CHECK 0x00002000 +#define AR_PHY_RADAR_1_RELSTEP_THRESH 0x00001F00 +#define AR_PHY_RADAR_1_RELSTEP_THRESH_S 8 +#define AR_PHY_RADAR_1_MAXLEN 0x000000FF +#define AR_PHY_RADAR_1_MAXLEN_S 0 + #define AR_PHY_CHIP_ID_REV_0 0x80 /* 5416 Rev 0 (owl 1.0) BB */ #define AR_PHY_CHIP_ID_REV_1 0x81 /* 5416 Rev 1 (owl 2.0) BB */ @@ -93,6 +112,8 @@ #define AR9280_PHY_RXGAIN_TXRX_MARGIN 0x001FC000 #define AR9280_PHY_RXGAIN_TXRX_MARGIN_S 14 +#define AR_PHY_SEARCH_START_DELAY 0x9918 /* search start delay */ + #define AR_PHY_EXT_CCA 0x99bc #define AR_PHY_EXT_CCA_CYCPWR_THR1 0x0000FE00 #define AR_PHY_EXT_CCA_CYCPWR_THR1_S 9 @@ -100,6 +121,13 @@ #define AR_PHY_EXT_MINCCA_PWR_S 23 #define AR_PHY_EXT_CCA_THRESH62 0x007F0000 #define AR_PHY_EXT_CCA_THRESH62_S 16 +/* + * This duplicates AR_PHY_EXT_CCA_CYCPWR_THR1; it reads more like + * an ANI register this way. + */ +#define AR_PHY_EXT_TIMING5_CYCPWR_THR1 0x0000FE00 +#define AR_PHY_EXT_TIMING5_CYCPWR_THR1_S 9 + #define AR9280_PHY_EXT_MINCCA_PWR 0x01FF0000 #define AR9280_PHY_EXT_MINCCA_PWR_S 16 @@ -111,6 +139,9 @@ #define AR_PHY_HEAVY_CLIP_ENABLE 0x99E0 +#define AR_PHY_HEAVY_CLIP_FACTOR_RIFS 0x99ec +#define AR_PHY_RIFS_INIT_DELAY 0x03ff0000 + #define AR_PHY_M_SLEEP 0x99f0 /* sleep control registers */ #define AR_PHY_REFCLKDLY 0x99f4 #define AR_PHY_REFCLKPD 0x99f8 @@ -266,4 +297,29 @@ #define AR_PHY_CL_CAL_CTL 0xA358 /* carrier leak cal control */ #define AR_PHY_CL_CAL_ENABLE 0x00000002 #define AR_PHY_PARALLEL_CAL_ENABLE 0x00000001 + +/* empirically determined "good" CCA value ranges from atheros */ +#define AR_PHY_CCA_NOM_VAL_5416_2GHZ -90 +#define AR_PHY_CCA_NOM_VAL_5416_5GHZ -100 +#define AR_PHY_CCA_MIN_GOOD_VAL_5416_2GHZ -100 +#define AR_PHY_CCA_MIN_GOOD_VAL_5416_5GHZ -110 +#define AR_PHY_CCA_MAX_GOOD_VAL_5416_2GHZ -80 +#define AR_PHY_CCA_MAX_GOOD_VAL_5416_5GHZ -90 + +/* ar9280 specific? */ +#define AR_PHY_XPA_CFG 0xA3D8 +#define AR_PHY_FORCE_XPA_CFG 0x000000001 +#define AR_PHY_FORCE_XPA_CFG_S 0 + +#define AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK 0x0000000C +#define AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK_S 2 + +#define AR_PHY_TX_PWRCTRL9 0xa27C +#define AR_PHY_TX_DESIRED_SCALE_CCK 0x00007C00 +#define AR_PHY_TX_DESIRED_SCALE_CCK_S 10 +#define AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL 0x80000000 +#define AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL_S 31 + +#define AR_PHY_MODE_ASYNCFIFO 0x80 /* Enable async fifo */ + #endif /* _DEV_ATH_AR5416PHY_H_ */ diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416reg.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416reg.h index cab34ccd7f..c18c26f90f 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416reg.h +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar5416reg.h @@ -40,6 +40,7 @@ #define AR_INTR_ASYNC_MASK 0x4030 /* asynchronous interrupt mask */ #define AR_INTR_SYNC_MASK 0x4034 /* synchronous interrupt mask */ #define AR_INTR_ASYNC_CAUSE 0x4038 /* check pending interrupts */ +#define AR_INTR_ASYNC_CAUSE_CLR 0x4038 /* clear pending interrupts */ #define AR_INTR_ASYNC_ENABLE 0x403c /* enable interrupts */ #define AR5416_PCIE_SERDES 0x4040 #define AR5416_PCIE_SERDES2 0x4044 @@ -54,37 +55,38 @@ #define AR_GPIO_OUTPUT_MUX3 0x4068 #define AR_EEPROM_STATUS_DATA 0x407c #define AR_OBS 0x4080 -#define AR_RTC_RC 0x7000 /* reset control */ -#define AR_RTC_PLL_CONTROL 0x7014 -#define AR_RTC_RESET 0x7040 /* RTC reset register */ -#define AR_RTC_STATUS 0x7044 /* system sleep status */ -#define AR_RTC_SLEEP_CLK 0x7048 -#define AR_RTC_FORCE_WAKE 0x704c /* control MAC force wake */ -#define AR_RTC_INTR_CAUSE 0x7050 /* RTC interrupt cause/clear */ -#define AR_RTC_INTR_ENABLE 0x7054 /* RTC interrupt enable */ -#define AR_RTC_INTR_MASK 0x7058 /* RTC interrupt mask */ -/* AR9280: rf long shift registers */ -#define AR_AN_RF2G1_CH0 0x7810 -#define AR_AN_RF5G1_CH0 0x7818 -#define AR_AN_RF2G1_CH1 0x7834 -#define AR_AN_RF5G1_CH1 0x783C -#define AR_AN_TOP2 0x7894 -#define AR_AN_SYNTH9 0x7868 -#define AR9285_AN_RF2G1 0x7820 -#define AR9285_AN_RF2G2 0x7824 -#define AR9285_AN_RF2G3 0x7828 -#define AR9285_AN_RF2G4 0x782C -#define AR9285_AN_RF2G6 0x7834 -#define AR9285_AN_RF2G7 0x7838 -#define AR9285_AN_RF2G8 0x783C -#define AR9285_AN_RF2G9 0x7840 -#define AR9285_AN_RXTXBB1 0x7854 -#define AR9285_AN_TOP2 0x7868 -#define AR9285_AN_TOP3 0x786c -#define AR9285_AN_TOP4 0x7870 -#define AR9285_AN_TOP4_DEFAULT 0x10142c00 + +#ifdef AH_SUPPORT_AR9130 +#define AR_RTC_BASE 0x20000 +#else +#define AR_RTC_BASE 0x7000 +#endif /* AH_SUPPORT_AR9130 */ + +#define AR_RTC_RC AR_RTC_BASE + 0x00 /* reset control */ +#define AR_RTC_PLL_CONTROL AR_RTC_BASE + 0x14 +#define AR_RTC_RESET AR_RTC_BASE + 0x40 /* RTC reset register */ +#define AR_RTC_STATUS AR_RTC_BASE + 0x44 /* system sleep status */ +#define AR_RTC_SLEEP_CLK AR_RTC_BASE + 0x48 +#define AR_RTC_FORCE_WAKE AR_RTC_BASE + 0x4c /* control MAC force wake */ +#define AR_RTC_INTR_CAUSE AR_RTC_BASE + 0x50 /* RTC interrupt cause/clear */ +#define AR_RTC_INTR_ENABLE AR_RTC_BASE + 0x54 /* RTC interrupt enable */ +#define AR_RTC_INTR_MASK AR_RTC_BASE + 0x58 /* RTC interrupt mask */ + +#ifdef AH_SUPPORT_AR9130 +/* RTC_DERIVED_* - only for AR9130 */ +#define AR_RTC_DERIVED_CLK (AR_RTC_BASE + 0x0038) +#define AR_RTC_DERIVED_CLK_PERIOD 0x0000fffe +#define AR_RTC_DERIVED_CLK_PERIOD_S 1 +#endif /* AH_SUPPORT_AR9130 */ #define AR_RESET_TSF 0x8020 + +/* + * AR_SLEEP1 / AR_SLEEP2 are in the same place as in + * AR5212, however the fields have changed. + */ +#define AR5416_SLEEP1 0x80d4 +#define AR5416_SLEEP2 0x80d8 #define AR_RXFIFO_CFG 0x8114 #define AR_PHY_ERR_1 0x812c #define AR_PHY_ERR_MASK_1 0x8130 /* mask for AR_PHY_ERR_1 */ @@ -127,6 +129,7 @@ #define AR_EXTRCCNT 0x8328 /* extension channel rx clear count */ #define AR_SELFGEN_MASK 0x832c /* rx and cal chain masks */ #define AR_PCU_TXBUF_CTRL 0x8340 +#define AR_PCU_MISC_MODE2 0x8344 /* DMA & PCI Registers in PCI space (usable during sleep)*/ #define AR_RC_AHB 0x00000001 /* AHB reset */ @@ -183,6 +186,12 @@ #define AR_RXCFG_DMASZ_512B 7 /* MAC Led registers */ +#define AR_CFG_SCLK_RATE_IND 0x00000003 /* sleep clock indication */ +#define AR_CFG_SCLK_RATE_IND_S 0 +#define AR_CFG_SCLK_32MHZ 0x00000000 /* Sleep clock rate */ +#define AR_CFG_SCLK_4MHZ 0x00000001 /* Sleep clock rate */ +#define AR_CFG_SCLK_1MHZ 0x00000002 /* Sleep clock rate */ +#define AR_CFG_SCLK_32KHZ 0x00000003 /* Sleep clock rate */ #define AR_MAC_LED_BLINK_SLOW 0x00000008 /* LED slowest blink rate mode */ #define AR_MAC_LED_BLINK_THRESH_SEL 0x00000070 /* LED blink threshold select */ #define AR_MAC_LED_MODE 0x00000380 /* LED mode select */ @@ -218,6 +227,10 @@ #define AR_AHB_PAGE_SIZE_1K 0x00000000 /* set page-size as 1k */ #define AR_AHB_PAGE_SIZE_2K 0x00000008 /* set page-size as 2k */ #define AR_AHB_PAGE_SIZE_4K 0x00000010 /* set page-size as 4k */ +/* Kiwi */ +#define AR_AHB_CUSTOM_BURST_EN 0x000000C0 /* set Custom Burst Mode */ +#define AR_AHB_CUSTOM_BURST_EN_S 6 /* set Custom Burst Mode */ +#define AR_AHB_CUSTOM_BURST_ASYNC_FIFO_VAL 3 /* set both bits in Async FIFO mode */ /* MAC PCU Registers */ #define AR_STA_ID1_PRESERVE_SEQNUM 0x20000000 /* Don't replace seq num */ @@ -244,6 +257,10 @@ #define AR_ISR_S2_GTT 0x00800000 /* Global transmit timeout */ #define AR_ISR_S2_TSFOOR 0x40000000 /* RX TSF out of range */ +#define AR_ISR_S5 0x0098 +#define AR_ISR_S5_S 0x00d8 +#define AR_ISR_S5_TIM_TIMER 0x00000010 + #define AR_INTR_SPURIOUS 0xffffffff #define AR_INTR_RTC_IRQ 0x00000001 /* rtc in shutdown state */ #define AR_INTR_MAC_IRQ 0x00000002 /* pending mac interrupt */ @@ -308,6 +325,10 @@ #define AR_RTC_RC_M 0x00000003 #define AR_RTC_RC_MAC_WARM 0x00000001 #define AR_RTC_RC_MAC_COLD 0x00000002 +#ifdef AH_SUPPORT_AR9130 +#define AR_RTC_RC_COLD_RESET 0x00000004 +#define AR_RTC_RC_WARM_RESET 0x00000008 +#endif /* AH_SUPPORT_AR9130 */ #define AR_RTC_PLL_DIV 0x0000001f #define AR_RTC_PLL_DIV_S 0 #define AR_RTC_PLL_DIV2 0x00000020 @@ -323,7 +344,11 @@ #define AR_RTC_RESET_EN 0x00000001 /* Reset RTC bit */ #define AR_RTC_PM_STATUS_M 0x0000000f /* Pwr Mgmt Status */ +#ifdef AH_SUPPORT_AR9130 +#define AR_RTC_STATUS_M 0x0000000f /* RTC Status */ +#else #define AR_RTC_STATUS_M 0x0000003f /* RTC Status */ +#endif /* AH_SUPPORT_AR9130 */ #define AR_RTC_STATUS_SHUTDOWN 0x00000001 #define AR_RTC_STATUS_ON 0x00000002 #define AR_RTC_STATUS_SLEEP 0x00000004 @@ -340,6 +365,13 @@ #define AR_RTC_PLL_CLKSEL_S 8 /* AR9280: rf long shift registers */ +#define AR_AN_RF2G1_CH0 0x7810 +#define AR_AN_RF5G1_CH0 0x7818 +#define AR_AN_RF2G1_CH1 0x7834 +#define AR_AN_RF5G1_CH1 0x783C +#define AR_AN_TOP2 0x7894 +#define AR_AN_SYNTH9 0x7868 + #define AR_AN_RF2G1_CH0_OB 0x03800000 #define AR_AN_RF2G1_CH0_OB_S 23 #define AR_AN_RF2G1_CH0_DB 0x1C000000 @@ -360,6 +392,10 @@ #define AR_AN_RF5G1_CH1_DB5 0x00380000 #define AR_AN_RF5G1_CH1_DB5_S 19 +#define AR_AN_TOP1 0x7890 +#define AR_AN_TOP1_DACIPMODE 0x00040000 +#define AR_AN_TOP1_DACIPMODE_S 18 + #define AR_AN_TOP2_XPABIAS_LVL 0xC0000000 #define AR_AN_TOP2_XPABIAS_LVL_S 30 #define AR_AN_TOP2_LOCALBIAS 0x00200000 @@ -370,86 +406,11 @@ #define AR_AN_SYNTH9_REFDIVA 0xf8000000 #define AR_AN_SYNTH9_REFDIVA_S 27 -/* AR9285 Analog registers */ -#define AR9285_AN_RF2G1_ENPACAL 0x00000800 -#define AR9285_AN_RF2G1_ENPACAL_S 11 -#define AR9285_AN_RF2G1_PDPADRV1 0x02000000 -#define AR9285_AN_RF2G1_PDPADRV1_S 25 -#define AR9285_AN_RF2G1_PDPADRV2 0x01000000 -#define AR9285_AN_RF2G1_PDPADRV2_S 24 -#define AR9285_AN_RF2G1_PDPAOUT 0x00800000 -#define AR9285_AN_RF2G1_PDPAOUT_S 23 - -#define AR9285_AN_RF2G2_OFFCAL 0x00001000 -#define AR9285_AN_RF2G2_OFFCAL_S 12 - -#define AR9285_AN_RF2G3_PDVCCOMP 0x02000000 -#define AR9285_AN_RF2G3_PDVCCOMP_S 25 -#define AR9285_AN_RF2G3_OB_0 0x00E00000 -#define AR9285_AN_RF2G3_OB_0_S 21 -#define AR9285_AN_RF2G3_OB_1 0x001C0000 -#define AR9285_AN_RF2G3_OB_1_S 18 -#define AR9285_AN_RF2G3_OB_2 0x00038000 -#define AR9285_AN_RF2G3_OB_2_S 15 -#define AR9285_AN_RF2G3_OB_3 0x00007000 -#define AR9285_AN_RF2G3_OB_3_S 12 -#define AR9285_AN_RF2G3_OB_4 0x00000E00 -#define AR9285_AN_RF2G3_OB_4_S 9 - -#define AR9285_AN_RF2G3_DB1_0 0x000001C0 -#define AR9285_AN_RF2G3_DB1_0_S 6 -#define AR9285_AN_RF2G3_DB1_1 0x00000038 -#define AR9285_AN_RF2G3_DB1_1_S 3 -#define AR9285_AN_RF2G3_DB1_2 0x00000007 -#define AR9285_AN_RF2G3_DB1_2_S 0 - -#define AR9285_AN_RF2G4_DB1_3 0xE0000000 -#define AR9285_AN_RF2G4_DB1_3_S 29 -#define AR9285_AN_RF2G4_DB1_4 0x1C000000 -#define AR9285_AN_RF2G4_DB1_4_S 26 - -#define AR9285_AN_RF2G4_DB2_0 0x03800000 -#define AR9285_AN_RF2G4_DB2_0_S 23 -#define AR9285_AN_RF2G4_DB2_1 0x00700000 -#define AR9285_AN_RF2G4_DB2_1_S 20 -#define AR9285_AN_RF2G4_DB2_2 0x000E0000 -#define AR9285_AN_RF2G4_DB2_2_S 17 -#define AR9285_AN_RF2G4_DB2_3 0x0001C000 -#define AR9285_AN_RF2G4_DB2_3_S 14 -#define AR9285_AN_RF2G4_DB2_4 0x00003800 -#define AR9285_AN_RF2G4_DB2_4_S 11 - -#define AR9285_AN_RF2G6_CCOMP 0x00007800 -#define AR9285_AN_RF2G6_CCOMP_S 11 -#define AR9285_AN_RF2G6_OFFS 0x03f00000 -#define AR9285_AN_RF2G6_OFFS_S 20 - #define AR9271_AN_RF2G6_OFFS 0x07f00000 #define AR9271_AN_RF2G6_OFFS_S 20 -#define AR9285_AN_RF2G7_PWDDB 0x00000002 -#define AR9285_AN_RF2G7_PWDDB_S 1 -#define AR9285_AN_RF2G7_PADRVGN2TAB0 0xE0000000 -#define AR9285_AN_RF2G7_PADRVGN2TAB0_S 29 - -#define AR9285_AN_RF2G8_PADRVGN2TAB0 0x0001C000 -#define AR9285_AN_RF2G8_PADRVGN2TAB0_S 14 - -#define AR9285_AN_RXTXBB1_PDRXTXBB1 0x00000020 -#define AR9285_AN_RXTXBB1_PDRXTXBB1_S 5 -#define AR9285_AN_RXTXBB1_PDV2I 0x00000080 -#define AR9285_AN_RXTXBB1_PDV2I_S 7 -#define AR9285_AN_RXTXBB1_PDDACIF 0x00000100 -#define AR9285_AN_RXTXBB1_PDDACIF_S 8 -#define AR9285_AN_RXTXBB1_SPARE9 0x00000001 -#define AR9285_AN_RXTXBB1_SPARE9_S 0 - -#define AR9285_AN_TOP3_XPABIAS_LVL 0x0000000C -#define AR9285_AN_TOP3_XPABIAS_LVL_S 2 -#define AR9285_AN_TOP3_PWDDAC 0x00800000 -#define AR9285_AN_TOP3_PWDDAC_S 23 - /* Sleep control */ +#define AR5416_SLEEP1_ASSUME_DTIM 0x00080000 #define AR5416_SLEEP1_CAB_TIMEOUT 0xFFE00000 /* Cab timeout (TU) */ #define AR5416_SLEEP1_CAB_TIMEOUT_S 22 @@ -495,6 +456,31 @@ #define AR_PCU_CLEAR_VMF 0x01000000 /* clear vmf mode (fast cc)*/ #define AR_PCU_CLEAR_BA_VALID 0x04000000 /* clear ba state */ +#define AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE 0x00000002 +#define AR_PCU_MISC_MODE2_NO_CRYPTO_FOR_NON_DATA_PKT 0x00000004 +/* + * This bit enables the Multicast search based on both MAC Address and Key ID. + * If bit is 0, then Multicast search is based on MAC address only. + * For Merlin and above only. + */ +#define AR_PCU_MISC_MODE2_ADHOC_MCAST_KEYID_ENABLE 0x00000040 +#define AR_PCU_MISC_MODE2_ENABLE_AGGWEP 0x00020000 /* Kiwi or later? */ +#define AR_PCU_MISC_MODE2_HWWAR1 0x00100000 +#define AR_PCU_MISC_MODE2_HWWAR2 0x02000000 + +/* For Kiwi */ +#define AR_MAC_PCU_ASYNC_FIFO_REG3 0x8358 +#define AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL 0x00000400 +#define AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET 0x80000000 + +/* TSF2. For Kiwi only */ +#define AR_TSF2_L32 0x8390 +#define AR_TSF2_U32 0x8394 + +/* MAC Direct Connect Control. For Kiwi only */ +#define AR_DIRECT_CONNECT 0x83A0 +#define AR_DC_AP_STA_EN 0x00000001 + /* GPIO Interrupt */ #define AR_INTR_GPIO 0x3FF00000 /* gpio interrupted */ #define AR_INTR_GPIO_S 20 @@ -521,12 +507,25 @@ #define AR_GPIO_INTR_POL_VAL 0x1FFF #define AR_GPIO_INTR_POL_VAL_S 0 +#define AR_GPIO_JTAG_DISABLE 0x00020000 + #define AR_2040_JOINED_RX_CLEAR 0x00000001 /* use ctl + ext rx_clear for cca */ #define AR_PCU_TXBUF_CTRL_SIZE_MASK 0x7FF #define AR_PCU_TXBUF_CTRL_USABLE_SIZE 0x700 #define AR_9285_PCU_TXBUF_CTRL_USABLE_SIZE 0x380 +/* IFS, SIFS, slot, etc for Async FIFO mode (Kiwi) */ +#define AR_D_GBL_IFS_SIFS_ASYNC_FIFO_DUR 0x000003AB +#define AR_TIME_OUT_ACK_CTS_ASYNC_FIFO_DUR 0x16001D56 +#define AR_USEC_ASYNC_FIFO_DUR 0x12e00074 +#define AR_D_GBL_IFS_SLOT_ASYNC_FIFO_DUR 0x00000420 +#define AR_D_GBL_IFS_EIFS_ASYNC_FIFO_DUR 0x0000A5EB + +/* Used by Kiwi Async FIFO */ +#define AR_MAC_PCU_LOGIC_ANALYZER 0x8264 +#define AR_MAC_PCU_LOGIC_ANALYZER_DISBUG20768 0x20000000 + /* Eeprom defines */ #define AR_EEPROM_STATUS_DATA_VAL 0x0000ffff #define AR_EEPROM_STATUS_DATA_VAL_S 0 @@ -535,6 +534,17 @@ #define AR_EEPROM_STATUS_DATA_PROT_ACCESS 0x00040000 #define AR_EEPROM_STATUS_DATA_ABSENT_ACCESS 0x00080000 +/* + * AR5212 defines the MAC revision mask as 0xF, but both ath9k and + * the Atheros HAL define it as 0x7. + * + * What this means however is AR5416 silicon revisions have + * changed. The below macros are for what is contained in the + * lower four bits; if the lower three bits are taken into account + * the revisions become 1.0 => 0x0, 2.0 => 0x1, 2.2 => 0x2. + */ + +/* These are the legacy revisions, with a four bit AR_SREV_REVISION mask */ #define AR_SREV_REVISION_OWL_10 0x08 #define AR_SREV_REVISION_OWL_20 0x09 #define AR_SREV_REVISION_OWL_22 0x0a @@ -545,9 +555,13 @@ #define AR_RAD2122_SREV_MAJOR 0xf0 /* Fowl: 2+5G/2x2 */ /* Test macro for owl 1.0 */ -#define IS_5416V1(_ah) ((_ah)->ah_macRev == AR_SREV_REVISION_OWL_10) -#define IS_5416V2(_ah) ((_ah)->ah_macRev >= AR_SREV_REVISION_OWL_20) -#define IS_5416V2_2(_ah) ((_ah)->ah_macRev == AR_SREV_REVISION_OWL_22) +#define IS_5416V1(_ah) (AR_SREV_OWL((_ah)) && AH_PRIVATE((_ah))->ah_macRev == AR_SREV_REVISION_OWL_10) +#define IS_5416V2(_ah) (AR_SREV_OWL((_ah)) && AH_PRIVATE((_ah))->ah_macRev >= AR_SREV_REVISION_OWL_20) +#define IS_5416V2_2(_ah) (AR_SREV_OWL((_ah)) && AH_PRIVATE((_ah))->ah_macRev == AR_SREV_REVISION_OWL_22) + +/* Misc; compatibility with Atheros HAL */ +#define AR_SREV_5416_V20_OR_LATER(_ah) (AR_SREV_HOWL((_ah)) || AR_SREV_OWL_20_OR_LATER(_ah)) +#define AR_SREV_5416_V22_OR_LATER(_ah) (AR_SREV_HOWL((_ah)) || AR_SREV_OWL_22_OR_LATER(_ah)) /* Expanded Mac Silicon Rev (16 bits starting with Sowl) */ #define AR_XSREV_ID 0xFFFFFFFF /* Chip ID */ @@ -564,10 +578,22 @@ #define AR_XSREV_VERSION_OWL_PCI 0x0D #define AR_XSREV_VERSION_OWL_PCIE 0x0C + + +/* + * These are from ath9k/Atheros and assume an AR_SREV version mask + * of 0x07, rather than 0x0F which is being used in the FreeBSD HAL. + * Thus, don't use these values as they're incorrect here; use + * AR_SREV_REVISION_OWL_{10,20,22}. + */ +#if 0 #define AR_XSREV_REVISION_OWL_10 0 /* Owl 1.0 */ #define AR_XSREV_REVISION_OWL_20 1 /* Owl 2.0/2.1 */ #define AR_XSREV_REVISION_OWL_22 2 /* Owl 2.2 */ -#define AR_XSREV_VERSION_SOWL 0x40 +#endif + +#define AR_XSREV_VERSION_HOWL 0x14 /* Howl (AR9130) */ +#define AR_XSREV_VERSION_SOWL 0x40 /* Sowl (AR9160) */ #define AR_XSREV_REVISION_SOWL_10 0 /* Sowl 1.0 */ #define AR_XSREV_REVISION_SOWL_11 1 /* Sowl 1.1 */ #define AR_XSREV_VERSION_MERLIN 0x80 /* Merlin Version */ @@ -578,47 +604,118 @@ #define AR_XSREV_REVISION_KITE_10 0 /* Kite 1.0 */ #define AR_XSREV_REVISION_KITE_11 1 /* Kite 1.1 */ #define AR_XSREV_REVISION_KITE_12 2 /* Kite 1.2 */ +#define AR_XSREV_VERSION_KIWI 0x180 /* Kiwi (AR9287) */ +#define AR_XSREV_REVISION_KIWI_10 0 +#define AR_XSREV_REVISION_KIWI_11 1 +#define AR_XSREV_REVISION_KIWI_12 2 +#define AR_XSREV_REVISION_KIWI_13 3 + +/* Owl (AR5416) */ +#define AR_SREV_OWL(_ah) \ + ((AH_PRIVATE((_ah))->ah_macVersion == AR_XSREV_VERSION_OWL_PCI) || \ + (AH_PRIVATE((_ah))->ah_macVersion == AR_XSREV_VERSION_OWL_PCIE)) #define AR_SREV_OWL_20_OR_LATER(_ah) \ - (AH_PRIVATE((_ah))->ah_macVersion >= AR_XSREV_VERSION_SOWL || \ - AH_PRIVATE((_ah))->ah_macRev >= AR_XSREV_REVISION_OWL_20) + ((AR_SREV_OWL(_ah) && \ + AH_PRIVATE((_ah))->ah_macRev >= AR_SREV_REVISION_OWL_20) || \ + AH_PRIVATE((_ah))->ah_macVersion >= AR_XSREV_VERSION_HOWL) + #define AR_SREV_OWL_22_OR_LATER(_ah) \ - (AH_PRIVATE((_ah))->ah_macVersion >= AR_XSREV_VERSION_SOWL || \ - AH_PRIVATE((_ah))->ah_macRev >= AR_XSREV_REVISION_OWL_22) + ((AR_SREV_OWL(_ah) && \ + AH_PRIVATE((_ah))->ah_macRev >= AR_SREV_REVISION_OWL_22) || \ + AH_PRIVATE((_ah))->ah_macVersion >= AR_XSREV_VERSION_HOWL) + +/* Howl (AR9130) */ + +#define AR_SREV_HOWL(_ah) \ + (AH_PRIVATE((_ah))->ah_macVersion == AR_XSREV_VERSION_HOWL) + +#define AR_SREV_9100(_ah) AR_SREV_HOWL(_ah) + +/* Sowl (AR9160) */ #define AR_SREV_SOWL(_ah) \ (AH_PRIVATE((_ah))->ah_macVersion == AR_XSREV_VERSION_SOWL) + #define AR_SREV_SOWL_10_OR_LATER(_ah) \ (AH_PRIVATE((_ah))->ah_macVersion >= AR_XSREV_VERSION_SOWL) + #define AR_SREV_SOWL_11(_ah) \ (AR_SREV_SOWL(_ah) && \ AH_PRIVATE((_ah))->ah_macRev == AR_XSREV_REVISION_SOWL_11) +/* Merlin (AR9280) */ + #define AR_SREV_MERLIN(_ah) \ (AH_PRIVATE((_ah))->ah_macVersion == AR_XSREV_VERSION_MERLIN) + #define AR_SREV_MERLIN_10_OR_LATER(_ah) \ (AH_PRIVATE((_ah))->ah_macVersion >= AR_XSREV_VERSION_MERLIN) + #define AR_SREV_MERLIN_20(_ah) \ (AR_SREV_MERLIN(_ah) && \ - AH_PRIVATE((_ah))->ah_macRev == AR_XSREV_REVISION_MERLIN_20) + AH_PRIVATE((_ah))->ah_macRev >= AR_XSREV_REVISION_MERLIN_20) + #define AR_SREV_MERLIN_20_OR_LATER(_ah) \ - (AR_SREV_MERLIN_20(_ah) || \ - AH_PRIVATE((_ah))->ah_macVersion > AR_XSREV_VERSION_MERLIN) + ((AH_PRIVATE((_ah))->ah_macVersion > AR_XSREV_VERSION_MERLIN) || \ + (AR_SREV_MERLIN((_ah)) && \ + AH_PRIVATE((_ah))->ah_macRev >= AR_XSREV_REVISION_MERLIN_20)) + +/* Kite (AR9285) */ #define AR_SREV_KITE(_ah) \ (AH_PRIVATE((_ah))->ah_macVersion == AR_XSREV_VERSION_KITE) + #define AR_SREV_KITE_10_OR_LATER(_ah) \ (AH_PRIVATE((_ah))->ah_macVersion >= AR_XSREV_VERSION_KITE) + #define AR_SREV_KITE_11(_ah) \ (AR_SREV_KITE(ah) && \ AH_PRIVATE((_ah))->ah_macRev == AR_XSREV_REVISION_KITE_11) + #define AR_SREV_KITE_11_OR_LATER(_ah) \ - (AR_SREV_KITE_11(_ah) || \ - AH_PRIVATE((_ah))->ah_macRev >= AR_XSREV_REVISION_KITE_11) + ((AH_PRIVATE((_ah))->ah_macVersion > AR_XSREV_VERSION_KITE) || \ + (AR_SREV_KITE((_ah)) && \ + AH_PRIVATE((_ah))->ah_macRev >= AR_XSREV_REVISION_KITE_11)) + #define AR_SREV_KITE_12(_ah) \ (AR_SREV_KITE(ah) && \ AH_PRIVATE((_ah))->ah_macRev == AR_XSREV_REVISION_KITE_12) + #define AR_SREV_KITE_12_OR_LATER(_ah) \ - (AR_SREV_KITE_12(_ah) || \ - AH_PRIVATE((_ah))->ah_macRev >= AR_XSREV_REVISION_KITE_12) + ((AH_PRIVATE((_ah))->ah_macVersion > AR_XSREV_VERSION_KITE) || \ + (AR_SREV_KITE((_ah)) && \ + AH_PRIVATE((_ah))->ah_macRev >= AR_XSREV_REVISION_KITE_12)) + +#define AR_SREV_9285E_20(_ah) \ + (AR_SREV_KITE_12_OR_LATER(_ah) && \ + ((OS_REG_READ(_ah, AR_AN_SYNTH9) & 0x7) == 0x1)) + +#define AR_SREV_KIWI(_ah) \ + (AH_PRIVATE((_ah))->ah_macVersion == AR_XSREV_VERSION_KIWI) + +#define AR_SREV_KIWI_11_OR_LATER(_ah) \ + (AR_SREV_KIWI(_ah) && \ + AH_PRIVATE((_ah))->ah_macRev >= AR_XSREV_REVISION_KIWI_11) + +#define AR_SREV_KIWI_11(_ah) \ + (AR_SREV_KIWI(_ah) && \ + AH_PRIVATE((_ah))->ah_macRev == AR_XSREV_REVISION_KIWI_11) + +#define AR_SREV_KIWI_12(_ah) \ + (AR_SREV_KIWI(_ah) && \ + AH_PRIVATE((_ah))->ah_macRev == AR_XSREV_REVISION_KIWI_12) + +#define AR_SREV_KIWI_12_OR_LATER(_ah) \ + (AR_SREV_KIWI(_ah) && \ + AH_PRIVATE((_ah))->ah_macRev >= AR_XSREV_REVISION_KIWI_12) + +#define AR_SREV_KIWI_13_OR_LATER(_ah) \ + (AR_SREV_KIWI(_ah) && \ + AH_PRIVATE((_ah))->ah_macRev >= AR_XSREV_REVISION_KIWI_13) + + +/* Not yet implemented chips */ +#define AR_SREV_9271(_ah) 0 + #endif /* _DEV_ATH_AR5416REG_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9001/ar9130.ini b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9001/ar9130.ini new file mode 100644 index 0000000000..0bd9f8e0a8 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9001/ar9130.ini @@ -0,0 +1,669 @@ +/* + * Copyright (c) 2010 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ + +static const uint32_t ar5416Modes_9100[][6] = { + { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, + { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, + { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, + { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 }, + { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 }, + { 0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf }, + { 0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810 }, + { 0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a, 0x0000320a }, + { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, + { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, + { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, + { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, + { 0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0 }, + { 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, + { 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, + { 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, + { 0x00009850, 0x6c48b4e2, 0x6d48b4e2, 0x6d48b0e2, 0x6c48b0e2, 0x6c48b0e2 }, + { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e }, + { 0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e, 0x31395d5e }, + { 0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18 }, + { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, + { 0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0 }, + { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 }, + { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 }, + { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 }, + { 0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d }, + { 0x00009940, 0x00750604, 0x00754604, 0xfff81204, 0xfff81204, 0xfff81204 }, + { 0x00009944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020 }, + { 0x00009954, 0x5f3ca3de, 0x5f3ca3de, 0xe250a51e, 0xe250a51e, 0xe250a51e }, + { 0x00009958, 0x2108ecff, 0x2108ecff, 0x3388ffff, 0x3388ffff, 0x3388ffff }, + { 0x00009960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0 }, + { 0x0000a960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0 }, + { 0x0000b960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0 }, + { 0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, 0x00001120 }, + { 0x0000c9bc, 0x001a0600, 0x001a0600, 0x001a1000, 0x001a0c00, 0x001a0c00 }, + { 0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be }, + { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, + { 0x000099c8, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329 }, + { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, + { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, + { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880 }, + { 0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788 }, + { 0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, + { 0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, + { 0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, + { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, + { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, + { 0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa }, + { 0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 }, + { 0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402 }, + { 0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06 }, + { 0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b }, + { 0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b }, + { 0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a }, + { 0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf }, + { 0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f }, + { 0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f }, + { 0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f }, + { 0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, +}; + +static const uint32_t ar5416Common_9100[][2] = { + /* Addr allmodes */ + { 0x0000000c, 0x00000000 }, + { 0x00000030, 0x00020015 }, + { 0x00000034, 0x00000005 }, + { 0x00000040, 0x00000000 }, + { 0x00000044, 0x00000008 }, + { 0x00000048, 0x00000008 }, + { 0x0000004c, 0x00000010 }, + { 0x00000050, 0x00000000 }, + { 0x00000054, 0x0000001f }, + { 0x00000800, 0x00000000 }, + { 0x00000804, 0x00000000 }, + { 0x00000808, 0x00000000 }, + { 0x0000080c, 0x00000000 }, + { 0x00000810, 0x00000000 }, + { 0x00000814, 0x00000000 }, + { 0x00000818, 0x00000000 }, + { 0x0000081c, 0x00000000 }, + { 0x00000820, 0x00000000 }, + { 0x00000824, 0x00000000 }, + { 0x00001040, 0x002ffc0f }, + { 0x00001044, 0x002ffc0f }, + { 0x00001048, 0x002ffc0f }, + { 0x0000104c, 0x002ffc0f }, + { 0x00001050, 0x002ffc0f }, + { 0x00001054, 0x002ffc0f }, + { 0x00001058, 0x002ffc0f }, + { 0x0000105c, 0x002ffc0f }, + { 0x00001060, 0x002ffc0f }, + { 0x00001064, 0x002ffc0f }, + { 0x00001230, 0x00000000 }, + { 0x00001270, 0x00000000 }, + { 0x00001038, 0x00000000 }, + { 0x00001078, 0x00000000 }, + { 0x000010b8, 0x00000000 }, + { 0x000010f8, 0x00000000 }, + { 0x00001138, 0x00000000 }, + { 0x00001178, 0x00000000 }, + { 0x000011b8, 0x00000000 }, + { 0x000011f8, 0x00000000 }, + { 0x00001238, 0x00000000 }, + { 0x00001278, 0x00000000 }, + { 0x000012b8, 0x00000000 }, + { 0x000012f8, 0x00000000 }, + { 0x00001338, 0x00000000 }, + { 0x00001378, 0x00000000 }, + { 0x000013b8, 0x00000000 }, + { 0x000013f8, 0x00000000 }, + { 0x00001438, 0x00000000 }, + { 0x00001478, 0x00000000 }, + { 0x000014b8, 0x00000000 }, + { 0x000014f8, 0x00000000 }, + { 0x00001538, 0x00000000 }, + { 0x00001578, 0x00000000 }, + { 0x000015b8, 0x00000000 }, + { 0x000015f8, 0x00000000 }, + { 0x00001638, 0x00000000 }, + { 0x00001678, 0x00000000 }, + { 0x000016b8, 0x00000000 }, + { 0x000016f8, 0x00000000 }, + { 0x00001738, 0x00000000 }, + { 0x00001778, 0x00000000 }, + { 0x000017b8, 0x00000000 }, + { 0x000017f8, 0x00000000 }, + { 0x0000103c, 0x00000000 }, + { 0x0000107c, 0x00000000 }, + { 0x000010bc, 0x00000000 }, + { 0x000010fc, 0x00000000 }, + { 0x0000113c, 0x00000000 }, + { 0x0000117c, 0x00000000 }, + { 0x000011bc, 0x00000000 }, + { 0x000011fc, 0x00000000 }, + { 0x0000123c, 0x00000000 }, + { 0x0000127c, 0x00000000 }, + { 0x000012bc, 0x00000000 }, + { 0x000012fc, 0x00000000 }, + { 0x0000133c, 0x00000000 }, + { 0x0000137c, 0x00000000 }, + { 0x000013bc, 0x00000000 }, + { 0x000013fc, 0x00000000 }, + { 0x0000143c, 0x00000000 }, + { 0x0000147c, 0x00000000 }, + { 0x00020010, 0x00000003 }, + { 0x00020038, 0x000004c2 }, + { 0x00008004, 0x00000000 }, + { 0x00008008, 0x00000000 }, + { 0x0000800c, 0x00000000 }, + { 0x00008018, 0x00000700 }, + { 0x00008020, 0x00000000 }, + { 0x00008038, 0x00000000 }, + { 0x0000803c, 0x00000000 }, + { 0x00008048, 0x40000000 }, + { 0x00008054, 0x00004000 }, + { 0x00008058, 0x00000000 }, + { 0x0000805c, 0x000fc78f }, + { 0x00008060, 0x0000000f }, + { 0x00008064, 0x00000000 }, + { 0x000080c0, 0x2a82301a }, + { 0x000080c4, 0x05dc01e0 }, + { 0x000080c8, 0x1f402710 }, + { 0x000080cc, 0x01f40000 }, + { 0x000080d0, 0x00001e00 }, + { 0x000080d4, 0x00000000 }, + { 0x000080d8, 0x00400000 }, + { 0x000080e0, 0xffffffff }, + { 0x000080e4, 0x0000ffff }, + { 0x000080e8, 0x003f3f3f }, + { 0x000080ec, 0x00000000 }, + { 0x000080f0, 0x00000000 }, + { 0x000080f4, 0x00000000 }, + { 0x000080f8, 0x00000000 }, + { 0x000080fc, 0x00020000 }, + { 0x00008100, 0x00020000 }, + { 0x00008104, 0x00000001 }, + { 0x00008108, 0x00000052 }, + { 0x0000810c, 0x00000000 }, + { 0x00008110, 0x00000168 }, + { 0x00008118, 0x000100aa }, + { 0x0000811c, 0x00003210 }, + { 0x00008120, 0x08f04800 }, + { 0x00008124, 0x00000000 }, + { 0x00008128, 0x00000000 }, + { 0x0000812c, 0x00000000 }, + { 0x00008130, 0x00000000 }, + { 0x00008134, 0x00000000 }, + { 0x00008138, 0x00000000 }, + { 0x0000813c, 0x00000000 }, + { 0x00008144, 0x00000000 }, + { 0x00008168, 0x00000000 }, + { 0x0000816c, 0x00000000 }, + { 0x00008170, 0x32143320 }, + { 0x00008174, 0xfaa4fa50 }, + { 0x00008178, 0x00000100 }, + { 0x0000817c, 0x00000000 }, + { 0x000081c4, 0x00000000 }, + { 0x000081d0, 0x00003210 }, + { 0x000081ec, 0x00000000 }, + { 0x000081f0, 0x00000000 }, + { 0x000081f4, 0x00000000 }, + { 0x000081f8, 0x00000000 }, + { 0x000081fc, 0x00000000 }, + { 0x00008200, 0x00000000 }, + { 0x00008204, 0x00000000 }, + { 0x00008208, 0x00000000 }, + { 0x0000820c, 0x00000000 }, + { 0x00008210, 0x00000000 }, + { 0x00008214, 0x00000000 }, + { 0x00008218, 0x00000000 }, + { 0x0000821c, 0x00000000 }, + { 0x00008220, 0x00000000 }, + { 0x00008224, 0x00000000 }, + { 0x00008228, 0x00000000 }, + { 0x0000822c, 0x00000000 }, + { 0x00008230, 0x00000000 }, + { 0x00008234, 0x00000000 }, + { 0x00008238, 0x00000000 }, + { 0x0000823c, 0x00000000 }, + { 0x00008240, 0x00100000 }, + { 0x00008244, 0x0010f400 }, + { 0x00008248, 0x00000100 }, + { 0x0000824c, 0x0001e800 }, + { 0x00008250, 0x00000000 }, + { 0x00008254, 0x00000000 }, + { 0x00008258, 0x00000000 }, + { 0x0000825c, 0x400000ff }, + { 0x00008260, 0x00080922 }, + { 0x00008270, 0x00000000 }, + { 0x00008274, 0x40000000 }, + { 0x00008278, 0x003e4180 }, + { 0x0000827c, 0x00000000 }, + { 0x00008284, 0x0000002c }, + { 0x00008288, 0x0000002c }, + { 0x0000828c, 0x00000000 }, + { 0x00008294, 0x00000000 }, + { 0x00008298, 0x00000000 }, + { 0x00008300, 0x00000000 }, + { 0x00008304, 0x00000000 }, + { 0x00008308, 0x00000000 }, + { 0x0000830c, 0x00000000 }, + { 0x00008310, 0x00000000 }, + { 0x00008314, 0x00000000 }, + { 0x00008318, 0x00000000 }, + { 0x00008328, 0x00000000 }, + { 0x0000832c, 0x00000007 }, + { 0x00008330, 0x00000302 }, + { 0x00008334, 0x00000e00 }, + { 0x00008338, 0x00000000 }, + { 0x0000833c, 0x00000000 }, + { 0x00008340, 0x000107ff }, + { 0x00009808, 0x00000000 }, + { 0x0000980c, 0xad848e19 }, + { 0x00009810, 0x7d14e000 }, + { 0x00009814, 0x9c0a9f6b }, + { 0x0000981c, 0x00000000 }, + { 0x0000982c, 0x0000a000 }, + { 0x00009830, 0x00000000 }, + { 0x0000983c, 0x00200400 }, + { 0x00009840, 0x206a01ae }, + { 0x0000984c, 0x1284233c }, + { 0x00009854, 0x00000859 }, + { 0x00009900, 0x00000000 }, + { 0x00009904, 0x00000000 }, + { 0x00009908, 0x00000000 }, + { 0x0000990c, 0x00000000 }, + { 0x0000991c, 0x10000fff }, + { 0x00009920, 0x05100000 }, + { 0x0000a920, 0x05100000 }, + { 0x0000b920, 0x05100000 }, + { 0x00009928, 0x00000001 }, + { 0x0000992c, 0x00000004 }, + { 0x00009934, 0x1e1f2022 }, + { 0x00009938, 0x0a0b0c0d }, + { 0x0000993c, 0x00000000 }, + { 0x00009948, 0x9280b212 }, + { 0x0000994c, 0x00020028 }, + { 0x0000c95c, 0x004b6a8e }, + { 0x0000c968, 0x000003ce }, + { 0x00009970, 0x190fb515 }, + { 0x00009974, 0x00000000 }, + { 0x00009978, 0x00000001 }, + { 0x0000997c, 0x00000000 }, + { 0x00009980, 0x00000000 }, + { 0x00009984, 0x00000000 }, + { 0x00009988, 0x00000000 }, + { 0x0000998c, 0x00000000 }, + { 0x00009990, 0x00000000 }, + { 0x00009994, 0x00000000 }, + { 0x00009998, 0x00000000 }, + { 0x0000999c, 0x00000000 }, + { 0x000099a0, 0x00000000 }, + { 0x000099a4, 0x00000001 }, + { 0x000099a8, 0x201fff00 }, + { 0x000099ac, 0x006f0000 }, + { 0x000099b0, 0x03051000 }, + { 0x000099dc, 0x00000000 }, + { 0x000099e0, 0x00000200 }, + { 0x000099e4, 0xaaaaaaaa }, + { 0x000099e8, 0x3c466478 }, + { 0x000099ec, 0x0cc80caa }, + { 0x000099fc, 0x00001042 }, + { 0x00009b00, 0x00000000 }, + { 0x00009b04, 0x00000001 }, + { 0x00009b08, 0x00000002 }, + { 0x00009b0c, 0x00000003 }, + { 0x00009b10, 0x00000004 }, + { 0x00009b14, 0x00000005 }, + { 0x00009b18, 0x00000008 }, + { 0x00009b1c, 0x00000009 }, + { 0x00009b20, 0x0000000a }, + { 0x00009b24, 0x0000000b }, + { 0x00009b28, 0x0000000c }, + { 0x00009b2c, 0x0000000d }, + { 0x00009b30, 0x00000010 }, + { 0x00009b34, 0x00000011 }, + { 0x00009b38, 0x00000012 }, + { 0x00009b3c, 0x00000013 }, + { 0x00009b40, 0x00000014 }, + { 0x00009b44, 0x00000015 }, + { 0x00009b48, 0x00000018 }, + { 0x00009b4c, 0x00000019 }, + { 0x00009b50, 0x0000001a }, + { 0x00009b54, 0x0000001b }, + { 0x00009b58, 0x0000001c }, + { 0x00009b5c, 0x0000001d }, + { 0x00009b60, 0x00000020 }, + { 0x00009b64, 0x00000021 }, + { 0x00009b68, 0x00000022 }, + { 0x00009b6c, 0x00000023 }, + { 0x00009b70, 0x00000024 }, + { 0x00009b74, 0x00000025 }, + { 0x00009b78, 0x00000028 }, + { 0x00009b7c, 0x00000029 }, + { 0x00009b80, 0x0000002a }, + { 0x00009b84, 0x0000002b }, + { 0x00009b88, 0x0000002c }, + { 0x00009b8c, 0x0000002d }, + { 0x00009b90, 0x00000030 }, + { 0x00009b94, 0x00000031 }, + { 0x00009b98, 0x00000032 }, + { 0x00009b9c, 0x00000033 }, + { 0x00009ba0, 0x00000034 }, + { 0x00009ba4, 0x00000035 }, + { 0x00009ba8, 0x00000035 }, + { 0x00009bac, 0x00000035 }, + { 0x00009bb0, 0x00000035 }, + { 0x00009bb4, 0x00000035 }, + { 0x00009bb8, 0x00000035 }, + { 0x00009bbc, 0x00000035 }, + { 0x00009bc0, 0x00000035 }, + { 0x00009bc4, 0x00000035 }, + { 0x00009bc8, 0x00000035 }, + { 0x00009bcc, 0x00000035 }, + { 0x00009bd0, 0x00000035 }, + { 0x00009bd4, 0x00000035 }, + { 0x00009bd8, 0x00000035 }, + { 0x00009bdc, 0x00000035 }, + { 0x00009be0, 0x00000035 }, + { 0x00009be4, 0x00000035 }, + { 0x00009be8, 0x00000035 }, + { 0x00009bec, 0x00000035 }, + { 0x00009bf0, 0x00000035 }, + { 0x00009bf4, 0x00000035 }, + { 0x00009bf8, 0x00000010 }, + { 0x00009bfc, 0x0000001a }, + { 0x0000a210, 0x40806333 }, + { 0x0000a214, 0x00106c10 }, + { 0x0000a218, 0x009c4060 }, + { 0x0000a220, 0x018830c6 }, + { 0x0000a224, 0x00000400 }, + { 0x0000a228, 0x001a0bb5 }, + { 0x0000a22c, 0x00000000 }, + { 0x0000a234, 0x20202020 }, + { 0x0000a238, 0x20202020 }, + { 0x0000a23c, 0x13c889af }, + { 0x0000a240, 0x38490a20 }, + { 0x0000a244, 0x00007bb6 }, + { 0x0000a248, 0x0fff3ffc }, + { 0x0000a24c, 0x00000001 }, + { 0x0000a250, 0x0000e000 }, + { 0x0000a254, 0x00000000 }, + { 0x0000a258, 0x0cc75380 }, + { 0x0000a25c, 0x0f0f0f01 }, + { 0x0000a260, 0xdfa91f01 }, + { 0x0000a268, 0x00000001 }, + { 0x0000a26c, 0x0ebae9c6 }, + { 0x0000b26c, 0x0ebae9c6 }, + { 0x0000c26c, 0x0ebae9c6 }, + { 0x0000d270, 0x00820820 }, + { 0x0000a278, 0x1ce739ce }, + { 0x0000a27c, 0x050701ce }, + { 0x0000a338, 0x00000000 }, + { 0x0000a33c, 0x00000000 }, + { 0x0000a340, 0x00000000 }, + { 0x0000a344, 0x00000000 }, + { 0x0000a348, 0x3fffffff }, + { 0x0000a34c, 0x3fffffff }, + { 0x0000a350, 0x3fffffff }, + { 0x0000a354, 0x0003ffff }, + { 0x0000a358, 0x79a8aa33 }, + { 0x0000d35c, 0x07ffffef }, + { 0x0000d360, 0x0fffffe7 }, + { 0x0000d364, 0x17ffffe5 }, + { 0x0000d368, 0x1fffffe4 }, + { 0x0000d36c, 0x37ffffe3 }, + { 0x0000d370, 0x3fffffe3 }, + { 0x0000d374, 0x57ffffe3 }, + { 0x0000d378, 0x5fffffe2 }, + { 0x0000d37c, 0x7fffffe2 }, + { 0x0000d380, 0x7f3c7bba }, + { 0x0000d384, 0xf3307ff0 }, + { 0x0000a388, 0x0c000000 }, + { 0x0000a38c, 0x20202020 }, + { 0x0000a390, 0x20202020 }, + { 0x0000a394, 0x1ce739ce }, + { 0x0000a398, 0x000001ce }, + { 0x0000a39c, 0x00000001 }, + { 0x0000a3a0, 0x00000000 }, + { 0x0000a3a4, 0x00000000 }, + { 0x0000a3a8, 0x00000000 }, + { 0x0000a3ac, 0x00000000 }, + { 0x0000a3b0, 0x00000000 }, + { 0x0000a3b4, 0x00000000 }, + { 0x0000a3b8, 0x00000000 }, + { 0x0000a3bc, 0x00000000 }, + { 0x0000a3c0, 0x00000000 }, + { 0x0000a3c4, 0x00000000 }, + { 0x0000a3c8, 0x00000246 }, + { 0x0000a3cc, 0x20202020 }, + { 0x0000a3d0, 0x20202020 }, + { 0x0000a3d4, 0x20202020 }, + { 0x0000a3dc, 0x1ce739ce }, + { 0x0000a3e0, 0x000001ce }, +}; + +static const uint32_t ar5416Bank0_9100[][2] = { + /* Addr allmodes */ + { 0x000098b0, 0x1e5795e5 }, + { 0x000098e0, 0x02008020 }, +}; + +static const uint32_t ar5416BB_RfGain_9100[][3] = { + /* Addr 5G_HT20 5G_HT40 */ + { 0x00009a00, 0x00000000, 0x00000000 }, + { 0x00009a04, 0x00000040, 0x00000040 }, + { 0x00009a08, 0x00000080, 0x00000080 }, + { 0x00009a0c, 0x000001a1, 0x00000141 }, + { 0x00009a10, 0x000001e1, 0x00000181 }, + { 0x00009a14, 0x00000021, 0x000001c1 }, + { 0x00009a18, 0x00000061, 0x00000001 }, + { 0x00009a1c, 0x00000168, 0x00000041 }, + { 0x00009a20, 0x000001a8, 0x000001a8 }, + { 0x00009a24, 0x000001e8, 0x000001e8 }, + { 0x00009a28, 0x00000028, 0x00000028 }, + { 0x00009a2c, 0x00000068, 0x00000068 }, + { 0x00009a30, 0x00000189, 0x000000a8 }, + { 0x00009a34, 0x000001c9, 0x00000169 }, + { 0x00009a38, 0x00000009, 0x000001a9 }, + { 0x00009a3c, 0x00000049, 0x000001e9 }, + { 0x00009a40, 0x00000089, 0x00000029 }, + { 0x00009a44, 0x00000170, 0x00000069 }, + { 0x00009a48, 0x000001b0, 0x00000190 }, + { 0x00009a4c, 0x000001f0, 0x000001d0 }, + { 0x00009a50, 0x00000030, 0x00000010 }, + { 0x00009a54, 0x00000070, 0x00000050 }, + { 0x00009a58, 0x00000191, 0x00000090 }, + { 0x00009a5c, 0x000001d1, 0x00000151 }, + { 0x00009a60, 0x00000011, 0x00000191 }, + { 0x00009a64, 0x00000051, 0x000001d1 }, + { 0x00009a68, 0x00000091, 0x00000011 }, + { 0x00009a6c, 0x000001b8, 0x00000051 }, + { 0x00009a70, 0x000001f8, 0x00000198 }, + { 0x00009a74, 0x00000038, 0x000001d8 }, + { 0x00009a78, 0x00000078, 0x00000018 }, + { 0x00009a7c, 0x00000199, 0x00000058 }, + { 0x00009a80, 0x000001d9, 0x00000098 }, + { 0x00009a84, 0x00000019, 0x00000159 }, + { 0x00009a88, 0x00000059, 0x00000199 }, + { 0x00009a8c, 0x00000099, 0x000001d9 }, + { 0x00009a90, 0x000000d9, 0x00000019 }, + { 0x00009a94, 0x000000f9, 0x00000059 }, + { 0x00009a98, 0x000000f9, 0x00000099 }, + { 0x00009a9c, 0x000000f9, 0x000000d9 }, + { 0x00009aa0, 0x000000f9, 0x000000f9 }, + { 0x00009aa4, 0x000000f9, 0x000000f9 }, + { 0x00009aa8, 0x000000f9, 0x000000f9 }, + { 0x00009aac, 0x000000f9, 0x000000f9 }, + { 0x00009ab0, 0x000000f9, 0x000000f9 }, + { 0x00009ab4, 0x000000f9, 0x000000f9 }, + { 0x00009ab8, 0x000000f9, 0x000000f9 }, + { 0x00009abc, 0x000000f9, 0x000000f9 }, + { 0x00009ac0, 0x000000f9, 0x000000f9 }, + { 0x00009ac4, 0x000000f9, 0x000000f9 }, + { 0x00009ac8, 0x000000f9, 0x000000f9 }, + { 0x00009acc, 0x000000f9, 0x000000f9 }, + { 0x00009ad0, 0x000000f9, 0x000000f9 }, + { 0x00009ad4, 0x000000f9, 0x000000f9 }, + { 0x00009ad8, 0x000000f9, 0x000000f9 }, + { 0x00009adc, 0x000000f9, 0x000000f9 }, + { 0x00009ae0, 0x000000f9, 0x000000f9 }, + { 0x00009ae4, 0x000000f9, 0x000000f9 }, + { 0x00009ae8, 0x000000f9, 0x000000f9 }, + { 0x00009aec, 0x000000f9, 0x000000f9 }, + { 0x00009af0, 0x000000f9, 0x000000f9 }, + { 0x00009af4, 0x000000f9, 0x000000f9 }, + { 0x00009af8, 0x000000f9, 0x000000f9 }, + { 0x00009afc, 0x000000f9, 0x000000f9 }, +}; + +static const uint32_t ar5416Bank1_9100[][2] = { + /* Addr allmodes */ + { 0x000098b0, 0x02108421 }, + { 0x000098ec, 0x00000008 }, +}; + +static const uint32_t ar5416Bank2_9100[][2] = { + /* Addr allmodes */ + { 0x000098b0, 0x0e73ff17 }, + { 0x000098e0, 0x00000420 }, +}; + +static const uint32_t ar5416Bank3_9100[][3] = { + /* Addr 5G_HT20 5G_HT40 */ + { 0x000098f0, 0x01400018, 0x01c00018 }, +}; + +static const uint32_t ar5416Bank6_9100[][3] = { + /* Addr 5G_HT20 5G_HT40 */ + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00e00000, 0x00e00000 }, + { 0x0000989c, 0x005e0000, 0x005e0000 }, + { 0x0000989c, 0x00120000, 0x00120000 }, + { 0x0000989c, 0x00620000, 0x00620000 }, + { 0x0000989c, 0x00020000, 0x00020000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x005f0000, 0x005f0000 }, + { 0x0000989c, 0x00870000, 0x00870000 }, + { 0x0000989c, 0x00f90000, 0x00f90000 }, + { 0x0000989c, 0x007b0000, 0x007b0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00f50000, 0x00f50000 }, + { 0x0000989c, 0x00dc0000, 0x00dc0000 }, + { 0x0000989c, 0x00110000, 0x00110000 }, + { 0x0000989c, 0x006100a8, 0x006100a8 }, + { 0x0000989c, 0x004210a2, 0x004210a2 }, + { 0x0000989c, 0x0014000f, 0x0014000f }, + { 0x0000989c, 0x00c40002, 0x00c40002 }, + { 0x0000989c, 0x003000f2, 0x003000f2 }, + { 0x0000989c, 0x00440016, 0x00440016 }, + { 0x0000989c, 0x00410040, 0x00410040 }, + { 0x0000989c, 0x000180d6, 0x000180d6 }, + { 0x0000989c, 0x0000c0aa, 0x0000c0aa }, + { 0x0000989c, 0x000000b1, 0x000000b1 }, + { 0x0000989c, 0x00002000, 0x00002000 }, + { 0x0000989c, 0x000000d4, 0x000000d4 }, + { 0x000098d0, 0x0000000f, 0x0010000f }, +}; + +static const uint32_t ar5416Bank6TPC_9100[][3] = { + /* Addr 5G_HT20 5G_HT40 */ + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00e00000, 0x00e00000 }, + { 0x0000989c, 0x005e0000, 0x005e0000 }, + { 0x0000989c, 0x00120000, 0x00120000 }, + { 0x0000989c, 0x00620000, 0x00620000 }, + { 0x0000989c, 0x00020000, 0x00020000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x40ff0000, 0x40ff0000 }, + { 0x0000989c, 0x005f0000, 0x005f0000 }, + { 0x0000989c, 0x00870000, 0x00870000 }, + { 0x0000989c, 0x00f90000, 0x00f90000 }, + { 0x0000989c, 0x007b0000, 0x007b0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00f50000, 0x00f50000 }, + { 0x0000989c, 0x00dc0000, 0x00dc0000 }, + { 0x0000989c, 0x00110000, 0x00110000 }, + { 0x0000989c, 0x006100a8, 0x006100a8 }, + { 0x0000989c, 0x00423022, 0x00423022 }, + { 0x0000989c, 0x2014008f, 0x2014008f }, + { 0x0000989c, 0x00c40002, 0x00c40002 }, + { 0x0000989c, 0x003000f2, 0x003000f2 }, + { 0x0000989c, 0x00440016, 0x00440016 }, + { 0x0000989c, 0x00410040, 0x00410040 }, + { 0x0000989c, 0x0001805e, 0x0001805e }, + { 0x0000989c, 0x0000c0ab, 0x0000c0ab }, + { 0x0000989c, 0x000000e1, 0x000000e1 }, + { 0x0000989c, 0x00007080, 0x00007080 }, + { 0x0000989c, 0x000000d4, 0x000000d4 }, + { 0x000098d0, 0x0000000f, 0x0010000f }, +}; + +static const uint32_t ar5416Bank7_9100[][2] = { + /* Addr allmodes */ + { 0x0000989c, 0x00000500 }, + { 0x0000989c, 0x00000800 }, + { 0x000098cc, 0x0000000e }, +}; + +static const uint32_t ar5416Addac_9100[][2] = { + /* Addr allmodes */ + { 0x0000989c, 0x00000000 }, + { 0x0000989c, 0x00000000 }, + { 0x0000989c, 0x00000000 }, + { 0x0000989c, 0x00000000 }, + { 0x0000989c, 0x00000000 }, + { 0x0000989c, 0x00000000 }, + { 0x0000989c, 0x00000000 }, + { 0x0000989c, 0x00000010 }, + { 0x0000989c, 0x00000000 }, + { 0x0000989c, 0x00000000 }, + { 0x0000989c, 0x00000000 }, + { 0x0000989c, 0x00000000 }, + { 0x0000989c, 0x00000000 }, + { 0x0000989c, 0x00000000 }, + { 0x0000989c, 0x00000000 }, + { 0x0000989c, 0x00000000 }, + { 0x0000989c, 0x00000000 }, + { 0x0000989c, 0x00000000 }, + { 0x0000989c, 0x00000000 }, + { 0x0000989c, 0x00000000 }, + { 0x0000989c, 0x00000000 }, + { 0x0000989c, 0x000000c0 }, + { 0x0000989c, 0x00000015 }, + { 0x0000989c, 0x00000000 }, + { 0x0000989c, 0x00000000 }, + { 0x0000989c, 0x00000000 }, + { 0x0000989c, 0x00000000 }, + { 0x0000989c, 0x00000000 }, + { 0x0000989c, 0x00000000 }, + { 0x0000989c, 0x00000000 }, + { 0x0000989c, 0x00000000 }, + { 0x000098cc, 0x00000000 }, +}; diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9001/ar9130_attach.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9001/ar9130_attach.c new file mode 100644 index 0000000000..518ed85fe8 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9001/ar9130_attach.c @@ -0,0 +1,312 @@ +/* + * Copyright (c) 2011 Adrian Chadd, Xenion Pty Ltd + * Copyright (c) 2008 Sam Leffler, Errno Consulting + * Copyright (c) 2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" + +#include "ar5416/ar5416.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" + +#include "ar9001/ar9130reg.h" +#include "ar9001/ar9130_phy.h" +#include "ar9001/ar9130_eeprom.h" + +#include "ar9001/ar9130.ini" + +static const HAL_PERCAL_DATA ar9130_iq_cal = { /* multi sample */ + .calName = "IQ", .calType = IQ_MISMATCH_CAL, + .calNumSamples = MAX_CAL_SAMPLES, + .calCountMax = PER_MIN_LOG_COUNT, + .calCollect = ar5416IQCalCollect, + .calPostProc = ar5416IQCalibration +}; +static const HAL_PERCAL_DATA ar9130_adc_gain_cal = { /* multi sample */ + .calName = "ADC Gain", .calType = ADC_GAIN_CAL, + .calNumSamples = MAX_CAL_SAMPLES, + .calCountMax = PER_MIN_LOG_COUNT, + .calCollect = ar5416AdcGainCalCollect, + .calPostProc = ar5416AdcGainCalibration +}; +static const HAL_PERCAL_DATA ar9130_adc_dc_cal = { /* multi sample */ + .calName = "ADC DC", .calType = ADC_DC_CAL, + .calNumSamples = MAX_CAL_SAMPLES, + .calCountMax = PER_MIN_LOG_COUNT, + .calCollect = ar5416AdcDcCalCollect, + .calPostProc = ar5416AdcDcCalibration +}; +static const HAL_PERCAL_DATA ar9130_adc_init_dc_cal = { + .calName = "ADC Init DC", .calType = ADC_DC_INIT_CAL, + .calNumSamples = MIN_CAL_SAMPLES, + .calCountMax = INIT_LOG_COUNT, + .calCollect = ar5416AdcDcCalCollect, + .calPostProc = ar5416AdcDcCalibration +}; + +static HAL_BOOL ar9130FillCapabilityInfo(struct ath_hal *ah); + +/* + * Attach for an AR9130 part. + */ +static struct ath_hal * +ar9130Attach(uint16_t devid, HAL_SOFTC sc, + HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata, HAL_STATUS *status) +{ + struct ath_hal_5416 *ahp5416; + struct ath_hal_5212 *ahp; + struct ath_hal *ah; + uint32_t val; + HAL_STATUS ecode; + HAL_BOOL rfStatus; + + HALDEBUG_G(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", + __func__, sc, (void*) st, (void*) sh); + + /* NB: memory is returned zero'd */ + ahp5416 = ath_hal_malloc(sizeof (struct ath_hal_5416)); + if (ahp5416 == AH_NULL) { + HALDEBUG_G(AH_NULL, HAL_DEBUG_ANY, + "%s: cannot allocate memory for state block\n", __func__); + *status = HAL_ENOMEM; + return AH_NULL; + } + ar5416InitState(ahp5416, devid, sc, st, sh, status); + ahp = &ahp5416->ah_5212; + ah = &ahp->ah_priv.h; + + /* XXX override with 9100 specific state */ + AH5416(ah)->ah_initPLL = ar9130InitPLL; + /* XXX should force chainmasks to 0x7, as per ath9k calibration bugs */ + + /* override 5416 methods for our needs */ + + AH5416(ah)->ah_cal.iqCalData.calData = &ar9130_iq_cal; + AH5416(ah)->ah_cal.adcGainCalData.calData = &ar9130_adc_gain_cal; + AH5416(ah)->ah_cal.adcDcCalData.calData = &ar9130_adc_dc_cal; + AH5416(ah)->ah_cal.adcDcCalInitData.calData = &ar9130_adc_init_dc_cal; + AH5416(ah)->ah_cal.suppCals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL; + + /* + * This was hard-set because the initial ath9k port of this + * code kept their runtime conditional register #defines. + * AR_SREV and the RTC registers have shifted for Howl; + * they detected this and changed the values at runtime. + * The current port doesn't yet do this; it may do at a + * later stage, so this is set early so any routines which + * manipulate the registers have ah_macVersion set to base + * the above decision upon. + */ + AH_PRIVATE((ah))->ah_macVersion = AR_XSREV_VERSION_HOWL; + + /* + * Use the "local" EEPROM data given to us by the higher layers. + * This is a private copy out of system flash. The Linux ath9k + * commit for the initial AR9130 support mentions MMIO flash + * access is "unreliable." -adrian + */ + AH_PRIVATE((ah))->ah_eepromRead = ar9130EepromRead; + AH_PRIVATE((ah))->ah_eepromWrite = NULL; + ah->ah_eepromdata = eepromdata; + + if (!ar5416SetResetReg(ah, HAL_RESET_POWER_ON)) { + /* reset chip */ + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't reset chip\n", + __func__); + ecode = HAL_EIO; + goto bad; + } + + if (!ar5416SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't wakeup chip\n", + __func__); + ecode = HAL_EIO; + goto bad; + } + /* Read Revisions from Chips before taking out of reset */ + val = OS_REG_READ(ah, AR_SREV_CHIP_HOWL) & AR_SREV_CHIP_HOWL_ID; + + /* XXX are these values even valid for the mac/radio revision? -adrian */ + HALDEBUG(ah, HAL_DEBUG_ATTACH, + "%s: ID 0x%x VERSION 0x%x TYPE 0x%x REVISION 0x%x\n", + __func__, MS(val, AR_XSREV_ID), MS(val, AR_XSREV_VERSION), + MS(val, AR_XSREV_TYPE), MS(val, AR_XSREV_REVISION)); + AH_PRIVATE(ah)->ah_macRev = MS(val, AR_XSREV_REVISION); + AH_PRIVATE(ah)->ah_ispcie = 0; + + /* setup common ini data; rf backends handle remainder */ + HAL_INI_INIT(&ahp->ah_ini_modes, ar5416Modes_9100, 6); + HAL_INI_INIT(&ahp->ah_ini_common, ar5416Common_9100, 2); + + HAL_INI_INIT(&AH5416(ah)->ah_ini_bb_rfgain, ar5416BB_RfGain_9100, 3); + HAL_INI_INIT(&AH5416(ah)->ah_ini_bank0, ar5416Bank0_9100, 2); + HAL_INI_INIT(&AH5416(ah)->ah_ini_bank1, ar5416Bank1_9100, 2); + HAL_INI_INIT(&AH5416(ah)->ah_ini_bank2, ar5416Bank2_9100, 2); + HAL_INI_INIT(&AH5416(ah)->ah_ini_bank3, ar5416Bank3_9100, 3); + HAL_INI_INIT(&AH5416(ah)->ah_ini_bank6, ar5416Bank6TPC_9100, 3); + HAL_INI_INIT(&AH5416(ah)->ah_ini_bank7, ar5416Bank7_9100, 2); + HAL_INI_INIT(&AH5416(ah)->ah_ini_addac, ar5416Addac_9100, 2); + + ecode = ath_hal_v14EepromAttach(ah); + if (ecode != HAL_OK) + goto bad; + + if (!ar5416ChipReset(ah, AH_NULL)) { /* reset chip */ + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__); + ecode = HAL_EIO; + goto bad; + } + + AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIP_ID); + + if (!ar5212ChipTest(ah)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: hardware self-test failed\n", + __func__); + ecode = HAL_ESELFTEST; + goto bad; + } + + /* + * Set correct Baseband to analog shift + * setting to access analog chips. + */ + OS_REG_WRITE(ah, AR_PHY(0), 0x00000007); + + /* Read Radio Chip Rev Extract */ + AH_PRIVATE(ah)->ah_analog5GhzRev = ar5416GetRadioRev(ah); + switch (AH_PRIVATE(ah)->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) { + case AR_RAD2133_SREV_MAJOR: /* Sowl: 2G/3x3 */ + case AR_RAD5133_SREV_MAJOR: /* Sowl: 2+5G/3x3 */ + break; + default: + if (AH_PRIVATE(ah)->ah_analog5GhzRev == 0) { + AH_PRIVATE(ah)->ah_analog5GhzRev = + AR_RAD5133_SREV_MAJOR; + break; + } +#ifdef AH_DEBUG + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: 5G Radio Chip Rev 0x%02X is not supported by " + "this driver\n", __func__, + AH_PRIVATE(ah)->ah_analog5GhzRev); + ecode = HAL_ENOTSUPP; + goto bad; +#endif + } + rfStatus = ar2133RfAttach(ah, &ecode); + if (!rfStatus) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RF setup failed, status %u\n", + __func__, ecode); + goto bad; + } + + /* + * Got everything we need now to setup the capabilities. + */ + if (!ar9130FillCapabilityInfo(ah)) { + ecode = HAL_EEREAD; + goto bad; + } + + ecode = ath_hal_eepromGet(ah, AR_EEP_MACADDR, ahp->ah_macaddr); + if (ecode != HAL_OK) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: error getting mac address from EEPROM\n", __func__); + goto bad; + } + /* XXX How about the serial number ? */ + /* Read Reg Domain */ + AH_PRIVATE(ah)->ah_currentRD = + ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, AH_NULL); + AH_PRIVATE(ah)->ah_currentRDext = + ath_hal_eepromGet(ah, AR_EEP_REGDMN_1, AH_NULL); + + + /* + * ah_miscMode is populated by ar5416FillCapabilityInfo() + * starting from griffin. Set here to make sure that + * AR_MISC_MODE_MIC_NEW_LOC_ENABLE is set before a GTK is + * placed into hardware. + */ + if (ahp->ah_miscMode != 0) + OS_REG_WRITE(ah, AR_MISC_MODE, ahp->ah_miscMode); + + /* XXX no ANI for AR9130 */ + AH5416(ah)->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_5416_2GHZ; + AH5416(ah)->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_5416_2GHZ; + AH5416(ah)->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_5416_2GHZ; + AH5416(ah)->nf_5g.max = AR_PHY_CCA_MAX_GOOD_VAL_5416_5GHZ; + AH5416(ah)->nf_5g.min = AR_PHY_CCA_MIN_GOOD_VAL_5416_5GHZ; + AH5416(ah)->nf_5g.nominal = AR_PHY_CCA_NOM_VAL_5416_5GHZ; + + ar5416InitNfHistBuff(AH5416(ah)->ah_cal.nfCalHist); + + HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__); + + return ah; +bad: + if (ahp) + ar5416Detach((struct ath_hal *) ahp); + if (status) + *status = ecode; + return AH_NULL; +} + +/* + * Fill all software cached or static hardware state information. + * Return failure if capabilities are to come from EEPROM and + * cannot be read. + */ +static HAL_BOOL +ar9130FillCapabilityInfo(struct ath_hal *ah) +{ + HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; + + HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: begin\n", __func__); + if (!ar5416FillCapabilityInfo(ah)) + return AH_FALSE; + HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: fill'ed; now setting\n", __func__); + pCap->halCSTSupport = AH_TRUE; + pCap->halRifsRxSupport = AH_TRUE; + pCap->halRifsTxSupport = AH_TRUE; + pCap->halRtsAggrLimit = 64*1024; /* 802.11n max */ + pCap->halExtChanDfsSupport = AH_TRUE; + pCap->halUseCombinedRadarRssi = AH_TRUE; + pCap->halAutoSleepSupport = AH_FALSE; /* XXX? */ + /* + * MBSSID aggregation is broken in Howl v1.1, v1.2, v1.3 + * and works fine in v1.4. + * XXX todo, enable it for v1.4. + */ + pCap->halMbssidAggrSupport = AH_FALSE; + pCap->hal4AddrAggrSupport = AH_TRUE; + + return AH_TRUE; +} + +static const char* +ar9130Probe(uint16_t vendorid, uint16_t devid) +{ + if (vendorid == ATHEROS_VENDOR_ID && devid == AR5416_AR9130_DEVID) + return "Atheros 9130"; + return AH_NULL; +} +AH_CHIP(AR9130, ar9130Probe, ar9130Attach); diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9001/ar9130_eeprom.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9001/ar9130_eeprom.c new file mode 100644 index 0000000000..465e1739a9 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9001/ar9130_eeprom.c @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2011 Adrian Chadd, Xenion Pty Ltd + * Copyright (c) 2010 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar9001/ar9130_eeprom.h" + +/* XXX this shouldn't be done here */ +/* This is in 16 bit words; not bytes -adrian */ +#define ATH_DATA_EEPROM_SIZE 2048 + +HAL_BOOL +ar9130EepromRead(struct ath_hal *ah, u_int off, uint16_t *data) +{ + if (ah->ah_eepromdata == AH_NULL) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: no eeprom data!\n", __func__); + return AH_FALSE; + } + if (off > ATH_DATA_EEPROM_SIZE) { + HALDEBUG(ah, HAL_DEBUG_ANY, "ar9130EepromRead: offset %x > %x\n", off, ATH_DATA_EEPROM_SIZE); + return AH_FALSE; + } + (*data) = ah->ah_eepromdata[off]; + return AH_TRUE; +} diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9001/ar9130_eeprom.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9001/ar9130_eeprom.h new file mode 100644 index 0000000000..54556f6e14 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9001/ar9130_eeprom.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2010 Adrian Chadd, Xenion Pty Ltd + * Copyright (c) 2010 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#ifndef __AR9130_EEPROM_H__ +#define __AR9130_EEPROM_H__ + +extern HAL_BOOL ar9130EepromRead(struct ath_hal *ah, u_int off, uint16_t *data); + +#endif diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9001/ar9130_phy.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9001/ar9130_phy.c new file mode 100644 index 0000000000..61ee0a2341 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9001/ar9130_phy.c @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2011 Adrian Chadd, Xenion Pty Ltd + * Copyright (c) 2010 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" + +#include "ar5416/ar5416.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" +#include "ar9001/ar9130_phy.h" + +void +ar9130InitPLL(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + + uint32_t pll; + + if (chan && IEEE80211_IS_CHAN_5GHZ(chan)) + pll = 0x1450; + else + pll = 0x1458; + + OS_REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll); + OS_DELAY(RTC_PLL_SETTLE_DELAY); + OS_REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_SLEEP_DERIVED_CLK); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9001/ar9130_phy.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9001/ar9130_phy.h new file mode 100644 index 0000000000..516df9277f --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9001/ar9130_phy.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2010 Adrian Chadd, Xenion Pty Ltd + * Copyright (c) 2008 Sam Leffler, Errno Consulting + * Copyright (c) 2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#ifndef __AR9130_PHY_H__ +#define __AR9130_PHY_H__ + +extern void ar9130InitPLL(struct ath_hal *ah, const struct ieee80211_channel *chan); + +#endif diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9001/ar9130reg.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9001/ar9130reg.h new file mode 100644 index 0000000000..c289c32e2c --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9001/ar9130reg.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2010 Adrian Chadd, Xenion Pty Ltd + * Copyright (c) 2008 Sam Leffler, Errno Consulting + * Copyright (c) 2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#ifndef __AR9130REG_H__ +#define __AR9130REG_H__ + +/* AR9130 shifts these registers */ +#define AR_SREV_CHIP_HOWL 0x0600 +#define AR_SREV_CHIP_HOWL_ID 0x00000FFF + +#endif /* __AR9130REG_H__ */ diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar9160.ini b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9001/ar9160.ini old mode 100755 new mode 100644 similarity index 97% rename from src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar9160.ini rename to src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9001/ar9160.ini index 275aa48454..963b0006e0 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar9160.ini +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9001/ar9160.ini @@ -1,6 +1,6 @@ /* * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting - * Copyright (c) 2002-2008 Atheros Communications, Inc. + * Copyright (c) 2002-2009 Atheros Communications, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -19,6 +19,7 @@ /* Auto Generated PCI Register Writes. Created: 05/22/08 */ static const uint32_t ar9160Modes[][6] = { + /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, @@ -35,22 +36,24 @@ static const uint32_t ar9160Modes[][6] = { { 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, { 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, { 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, - { 0x00009850, 0x6d48b4e2, 0x6d48b4e2, 0x6d48b0e2, 0x6d48b0e2, 0x6d48b0e2 }, + { 0x00009850, 0x6c48b4e2, 0x6c48b4e2, 0x6c48b0e2, 0x6c48b0e2, 0x6c48b0e2 }, { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e }, - { 0x0000985c, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e }, + { 0x0000985c, 0x31395d5e, 0x31395d5e, 0x31395d5e, 0x31395d5e, 0x31395d5e }, { 0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18 }, + { 0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, { 0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0 }, { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 }, - { 0x00009914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, 0x000007d0 }, + { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 }, { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 }, { 0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d }, - { 0x00009944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020 }, + { 0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020 }, { 0x00009960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 }, { 0x0000a960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 }, { 0x0000b960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 }, { 0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, 0x00001120 }, { 0x0000c968, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce, 0x000003ce }, + { 0x000099bc, 0x001a0600, 0x001a0600, 0x001a0c00, 0x001a0c00, 0x001a0c00 }, { 0x0000c9bc, 0x001a0600, 0x001a0600, 0x001a0c00, 0x001a0c00, 0x001a0c00 }, { 0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be }, { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, @@ -212,7 +215,7 @@ static const uint32_t ar9160Common[][2] = { { 0x00008134, 0x00000000 }, { 0x00008138, 0x00000000 }, { 0x0000813c, 0x00000000 }, - { 0x00008144, 0x00000000 }, + { 0x00008144, 0xffffffff }, { 0x00008168, 0x00000000 }, { 0x0000816c, 0x00000000 }, { 0x00008170, 0x32143320 }, @@ -271,7 +274,7 @@ static const uint32_t ar9160Common[][2] = { { 0x0000832c, 0x00000007 }, { 0x00008330, 0x00000302 }, { 0x00008334, 0x00000e00 }, - { 0x00008338, 0x00000000 }, + { 0x00008338, 0x00ff0000 }, { 0x0000833c, 0x00000000 }, { 0x00008340, 0x000107ff }, { 0x00009808, 0x00000000 }, @@ -326,6 +329,7 @@ static const uint32_t ar9160Common[][2] = { { 0x000099e4, 0xaaaaaaaa }, { 0x000099e8, 0x3c466478 }, { 0x000099ec, 0x0cc80caa }, + { 0x000099f0, 0x00000000 }, /* XXX adrian's addition: AR_PHY_CALMODE == 0 */ { 0x000099fc, 0x00001042 }, { 0x00009b00, 0x00000000 }, { 0x00009b04, 0x00000001 }, @@ -405,7 +409,7 @@ static const uint32_t ar9160Common[][2] = { { 0x0000a244, 0x00007bb6 }, { 0x0000a248, 0x0fff3ffc }, { 0x0000a24c, 0x00000001 }, - { 0x0000a250, 0x0000a000 }, + { 0x0000a250, 0x0000e000 }, { 0x0000a254, 0x00000000 }, { 0x0000a258, 0x0cc75380 }, { 0x0000a25c, 0x0f0f0f01 }, @@ -425,7 +429,7 @@ static const uint32_t ar9160Common[][2] = { { 0x0000a34c, 0x3fffffff }, { 0x0000a350, 0x3fffffff }, { 0x0000a354, 0x0003ffff }, - { 0x0000a358, 0x79a8aa33 }, + { 0x0000a358, 0x79bfaa03 }, { 0x0000d35c, 0x07ffffef }, { 0x0000d360, 0x0fffffe7 }, { 0x0000d364, 0x17ffffe5 }, diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar9160_attach.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9001/ar9160_attach.c similarity index 82% rename from src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar9160_attach.c rename to src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9001/ar9160_attach.c index 96dca803e3..2234eb35bf 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar9160_attach.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9001/ar9160_attach.c @@ -26,7 +26,7 @@ #include "ar5416/ar5416reg.h" #include "ar5416/ar5416phy.h" -#include "ar5416/ar9160.ini" +#include "ar9001/ar9160.ini" static const HAL_PERCAL_DATA ar9160_iq_cal = { /* multi sample */ .calName = "IQ", .calType = IQ_MISMATCH_CAL, @@ -80,8 +80,32 @@ ar9160AniSetup(struct ath_hal *ah) .rssiThrLow = 7, .period = 100, }; - /* NB: ANI is not enabled yet */ - ar5212AniAttach(ah, &aniparams, &aniparams, AH_FALSE); + + /* NB: disable ANI noise immmunity for reliable RIFS rx */ + AH5416(ah)->ah_ani_function &= ~(1 << HAL_ANI_NOISE_IMMUNITY_LEVEL); + ar5416AniAttach(ah, &aniparams, &aniparams, AH_TRUE); +} + +static void +ar9160InitPLL(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + uint32_t pll = SM(0x5, AR_RTC_SOWL_PLL_REFDIV); + if (chan != AH_NULL) { + if (IEEE80211_IS_CHAN_HALF(chan)) + pll |= SM(0x1, AR_RTC_SOWL_PLL_CLKSEL); + else if (IEEE80211_IS_CHAN_QUARTER(chan)) + pll |= SM(0x2, AR_RTC_SOWL_PLL_CLKSEL); + + if (IEEE80211_IS_CHAN_5GHZ(chan)) + pll |= SM(0x50, AR_RTC_SOWL_PLL_DIV); + else + pll |= SM(0x58, AR_RTC_SOWL_PLL_DIV); + } else + pll |= SM(0x58, AR_RTC_SOWL_PLL_DIV); + + OS_REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll); + OS_DELAY(RTC_PLL_SETTLE_DELAY); + OS_REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_SLEEP_DERIVED_CLK); } /* @@ -89,7 +113,8 @@ ar9160AniSetup(struct ath_hal *ah) */ static struct ath_hal * ar9160Attach(uint16_t devid, HAL_SOFTC sc, - HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status) + HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata, + HAL_STATUS *status) { struct ath_hal_5416 *ahp5416; struct ath_hal_5212 *ahp; @@ -98,13 +123,13 @@ ar9160Attach(uint16_t devid, HAL_SOFTC sc, HAL_STATUS ecode; HAL_BOOL rfStatus; - HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", + HALDEBUG_G(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", __func__, sc, (void*) st, (void*) sh); /* NB: memory is returned zero'd */ ahp5416 = ath_hal_malloc(sizeof (struct ath_hal_5416)); if (ahp5416 == AH_NULL) { - HALDEBUG(AH_NULL, HAL_DEBUG_ANY, + HALDEBUG_G(AH_NULL, HAL_DEBUG_ANY, "%s: cannot allocate memory for state block\n", __func__); *status = HAL_ENOMEM; return AH_NULL; @@ -115,6 +140,7 @@ ar9160Attach(uint16_t devid, HAL_SOFTC sc, /* XXX override with 9160 specific state */ /* override 5416 methods for our needs */ + AH5416(ah)->ah_initPLL = ar9160InitPLL; AH5416(ah)->ah_cal.iqCalData.calData = &ar9160_iq_cal; AH5416(ah)->ah_cal.adcGainCalData.calData = &ar9160_adc_gain_cal; @@ -238,6 +264,8 @@ ar9160Attach(uint16_t devid, HAL_SOFTC sc, /* Read Reg Domain */ AH_PRIVATE(ah)->ah_currentRD = ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, AH_NULL); + AH_PRIVATE(ah)->ah_currentRDext = + ath_hal_eepromGet(ah, AR_EEP_REGDMN_1, AH_NULL); /* * ah_miscMode is populated by ar5416FillCapabilityInfo() @@ -246,9 +274,18 @@ ar9160Attach(uint16_t devid, HAL_SOFTC sc, * placed into hardware. */ if (ahp->ah_miscMode != 0) - OS_REG_WRITE(ah, AR_MISC_MODE, ahp->ah_miscMode); + OS_REG_WRITE(ah, AR_MISC_MODE, OS_REG_READ(ah, AR_MISC_MODE) | ahp->ah_miscMode); ar9160AniSetup(ah); /* Anti Noise Immunity */ + + /* This just uses the AR5416 NF values */ + AH5416(ah)->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_5416_2GHZ; + AH5416(ah)->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_5416_2GHZ; + AH5416(ah)->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_5416_2GHZ; + AH5416(ah)->nf_5g.max = AR_PHY_CCA_MAX_GOOD_VAL_5416_5GHZ; + AH5416(ah)->nf_5g.min = AR_PHY_CCA_MIN_GOOD_VAL_5416_5GHZ; + AH5416(ah)->nf_5g.nominal = AR_PHY_CCA_NOM_VAL_5416_5GHZ; + ar5416InitNfHistBuff(AH5416(ah)->ah_cal.nfCalHist); HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__); @@ -279,7 +316,15 @@ ar9160FillCapabilityInfo(struct ath_hal *ah) pCap->halRifsTxSupport = AH_TRUE; pCap->halRtsAggrLimit = 64*1024; /* 802.11n max */ pCap->halExtChanDfsSupport = AH_TRUE; + pCap->halUseCombinedRadarRssi = AH_TRUE; pCap->halAutoSleepSupport = AH_FALSE; /* XXX? */ + pCap->halMbssidAggrSupport = AH_TRUE; + pCap->hal4AddrAggrSupport = AH_TRUE; + + /* AR9160 is a 2x2 stream device */ + pCap->halTxStreams = 2; + pCap->halRxStreams = 2; + return AH_TRUE; } diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9002phy.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9002phy.h new file mode 100644 index 0000000000..3d837cfcf5 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9002phy.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2010-2011 Adrian Chadd, Xenion Pty Ltd. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ +#ifndef __ATH_AR9002PHY_H__ +#define __ATH_AR9002PHY_H__ + +#define AR_PHY_TX_PWRCTRL4 0xa264 +#define AR_PHY_TX_PWRCTRL_PD_AVG_VALID 0x00000001 +#define AR_PHY_TX_PWRCTRL_PD_AVG_VALID_S 0 +#define AR_PHY_TX_PWRCTRL_PD_AVG_OUT 0x000001FE +#define AR_PHY_TX_PWRCTRL_PD_AVG_OUT_S 1 + +#define AR_PHY_TX_PWRCTRL6_0 0xa270 +#define AR_PHY_TX_PWRCTRL6_1 0xb270 +#define AR_PHY_TX_PWRCTRL_ERR_EST_MODE 0x03000000 +#define AR_PHY_TX_PWRCTRL_ERR_EST_MODE_S 24 + +#define AR_PHY_TX_PWRCTRL7 0xa274 +#define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN 0x01F80000 +#define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN_S 19 + +#define AR_PHY_TX_PWRCTRL8 0xa278 +#define AR_PHY_TX_PWRCTRL10 0xa394 + +#define AR_PHY_TX_GAIN_TBL1 0xa300 +#define AR_PHY_TX_GAIN 0x0007F000 +#define AR_PHY_TX_GAIN_S 12 + +#define AR_PHY_CH0_TX_PWRCTRL11 0xa398 +#define AR_PHY_CH1_TX_PWRCTRL11 0xb398 +#define AR_PHY_CH0_TX_PWRCTRL12 0xa3dc +#define AR_PHY_CH0_TX_PWRCTRL13 0xa3e0 + +#endif diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar9280.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9280.c similarity index 94% rename from src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar9280.c rename to src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9280.c index 72720f7f24..99fd1d790d 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar9280.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9280.c @@ -26,7 +26,7 @@ #include "ah_eeprom_v14.h" -#include "ar5416/ar9280.h" +#include "ar9002/ar9280.h" #include "ar5416/ar5416reg.h" #include "ar5416/ar5416phy.h" @@ -76,6 +76,7 @@ ar9280SetChannel(struct ath_hal *ah, const struct ieee80211_channel *chan) uint32_t freq, ndiv, channelSel = 0, channelFrac = 0, reg32 = 0; CHAN_CENTERS centers; uint32_t refDivA = 24; + uint8_t frac_n_5g; OS_MARK(ah, AH_MARK_SETCHANNEL, chan->ic_freq); @@ -85,6 +86,9 @@ ar9280SetChannel(struct ath_hal *ah, const struct ieee80211_channel *chan) reg32 = OS_REG_READ(ah, AR_PHY_SYNTH_CONTROL); reg32 &= 0xc0000000; + if (ath_hal_eepromGet(ah, AR_EEP_FRAC_N_5G, &frac_n_5g) != HAL_OK) + frac_n_5g = 0; + if (freq < 4800) { /* 2 GHz, fractional mode */ uint32_t txctl; @@ -106,11 +110,16 @@ ar9280SetChannel(struct ath_hal *ah, const struct ieee80211_channel *chan) bMode = 0; fracMode = 0; - if ((freq % 20) == 0) { - aModeRefSel = 3; - } else if ((freq % 10) == 0) { - aModeRefSel = 2; - } else { + switch (frac_n_5g) { + case 0: + if ((freq % 20) == 0) { + aModeRefSel = 3; + } else if ((freq % 10) == 0) { + aModeRefSel = 2; + } + if (aModeRefSel) break; + case 1: + default: aModeRefSel = 0; /* Enable 2G (fractional) mode for channels which are 5MHz spaced */ fracMode = 1; @@ -118,9 +127,10 @@ ar9280SetChannel(struct ath_hal *ah, const struct ieee80211_channel *chan) channelSel = (freq * 0x8000)/15; /* RefDivA setting */ - OS_REG_RMW_FIELD(ah, AR_AN_SYNTH9, + OS_A_REG_RMW_FIELD(ah, AR_AN_SYNTH9, AR_AN_SYNTH9_REFDIVA, refDivA); } + if (!fracMode) { ndiv = (freq * (refDivA >> aModeRefSel))/60; channelSel = ndiv & 0x1ff; @@ -265,6 +275,16 @@ ar9280GetChannelMaxMinPower(struct ath_hal *ah, #endif } +/* + * The ordering of nfarray is thus: + * + * nfarray[0]: Chain 0 ctl + * nfarray[1]: Chain 1 ctl + * nfarray[2]: Chain 2 ctl + * nfarray[3]: Chain 0 ext + * nfarray[4]: Chain 1 ext + * nfarray[5]: Chain 2 ext + */ static void ar9280GetNoiseFloor(struct ath_hal *ah, int16_t nfarray[]) { @@ -297,6 +317,11 @@ ar9280GetNoiseFloor(struct ath_hal *ah, int16_t nfarray[]) HALDEBUG(ah, HAL_DEBUG_NFCAL, "NF calibrated [ext] [chain 1] is %d\n", nf); nfarray[4] = nf; + + /* Chain 2 - invalid */ + nfarray[2] = 0; + nfarray[5] = 0; + } /* diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar9280.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9280.h similarity index 70% rename from src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar9280.h rename to src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9280.h index 59039f0157..e383918abb 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar9280.h +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9280.h @@ -20,12 +20,23 @@ #include "ar5416/ar5416.h" +/* + * This is a chip thing, but it's used here as part of the + * ath_hal_9280 struct; so it's convienent to locate the + * define here. + */ +#define AR9280_TX_GAIN_TABLE_SIZE 22 + struct ath_hal_9280 { struct ath_hal_5416 ah_5416; HAL_INI_ARRAY ah_ini_xmodes; HAL_INI_ARRAY ah_ini_rxgain; HAL_INI_ARRAY ah_ini_txgain; + + int PDADCdelta; + + uint32_t originalGain[AR9280_TX_GAIN_TABLE_SIZE]; }; #define AH9280(_ah) ((struct ath_hal_9280 *)(_ah)) @@ -34,6 +45,13 @@ struct ath_hal_9280 { #define AR9280_DEFAULT_TXCHAINMASK 1 #define AR9285_DEFAULT_TXCHAINMASK 1 +#define AR_PHY_CCA_NOM_VAL_9280_2GHZ -112 +#define AR_PHY_CCA_NOM_VAL_9280_5GHZ -112 +#define AR_PHY_CCA_MIN_GOOD_VAL_9280_2GHZ -127 +#define AR_PHY_CCA_MIN_GOOD_VAL_9280_5GHZ -122 +#define AR_PHY_CCA_MAX_GOOD_VAL_9280_2GHZ -97 +#define AR_PHY_CCA_MAX_GOOD_VAL_9280_5GHZ -102 + HAL_BOOL ar9280RfAttach(struct ath_hal *, HAL_STATUS *); struct ath_hal; @@ -41,5 +59,6 @@ struct ath_hal; HAL_BOOL ar9280SetAntennaSwitch(struct ath_hal *, HAL_ANT_SETTING); void ar9280SpurMitigate(struct ath_hal *, const struct ieee80211_channel *); - +void ar9280InitPLL(struct ath_hal *ah, + const struct ieee80211_channel *chan); #endif /* _ATH_AR9280_H_ */ diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar9280_attach.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9280_attach.c similarity index 78% rename from src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar9280_attach.c rename to src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9280_attach.c index 8436482b11..4f4b8baf2b 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar9280_attach.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9280_attach.c @@ -24,12 +24,13 @@ #include "ah_eeprom_v14.h" /* XXX for tx/rx gain */ -#include "ar5416/ar9280.h" +#include "ar9002/ar9280.h" #include "ar5416/ar5416reg.h" #include "ar5416/ar5416phy.h" -#include "ar5416/ar9280v1.ini" -#include "ar5416/ar9280v2.ini" +#include "ar9002/ar9280v1.ini" +#include "ar9002/ar9280v2.ini" +#include "ar9002/ar9280_olc.h" static const HAL_PERCAL_DATA ar9280_iq_cal = { /* single sample */ .calName = "IQ", .calType = IQ_MISMATCH_CAL, @@ -41,14 +42,14 @@ static const HAL_PERCAL_DATA ar9280_iq_cal = { /* single sample */ static const HAL_PERCAL_DATA ar9280_adc_gain_cal = { /* single sample */ .calName = "ADC Gain", .calType = ADC_GAIN_CAL, .calNumSamples = MIN_CAL_SAMPLES, - .calCountMax = PER_MIN_LOG_COUNT, + .calCountMax = PER_MAX_LOG_COUNT, .calCollect = ar5416AdcGainCalCollect, .calPostProc = ar5416AdcGainCalibration }; static const HAL_PERCAL_DATA ar9280_adc_dc_cal = { /* single sample */ .calName = "ADC DC", .calType = ADC_DC_CAL, .calNumSamples = MIN_CAL_SAMPLES, - .calCountMax = PER_MIN_LOG_COUNT, + .calCountMax = PER_MAX_LOG_COUNT, .calCollect = ar5416AdcDcCalCollect, .calPostProc = ar5416AdcDcCalibration }; @@ -68,16 +69,80 @@ static void ar9280WriteIni(struct ath_hal *ah, static void ar9280AniSetup(struct ath_hal *ah) { - /* NB: disable ANI for reliable RIFS rx */ - ar5212AniAttach(ah, AH_NULL, AH_NULL, AH_FALSE); + /* + * These are the parameters from the AR5416 ANI code; + * they likely need quite a bit of adjustment for the + * AR9280. + */ + static const struct ar5212AniParams aniparams = { + .maxNoiseImmunityLevel = 4, /* levels 0..4 */ + .totalSizeDesired = { -55, -55, -55, -55, -62 }, + .coarseHigh = { -14, -14, -14, -14, -12 }, + .coarseLow = { -64, -64, -64, -64, -70 }, + .firpwr = { -78, -78, -78, -78, -80 }, + .maxSpurImmunityLevel = 2, + .cycPwrThr1 = { 2, 4, 6 }, + .maxFirstepLevel = 2, /* levels 0..2 */ + .firstep = { 0, 4, 8 }, + .ofdmTrigHigh = 500, + .ofdmTrigLow = 200, + .cckTrigHigh = 200, + .cckTrigLow = 100, + .rssiThrHigh = 40, + .rssiThrLow = 7, + .period = 100, + }; + /* NB: disable ANI noise immmunity for reliable RIFS rx */ + AH5416(ah)->ah_ani_function &= ~(1 << HAL_ANI_NOISE_IMMUNITY_LEVEL); + + /* NB: ANI is not enabled yet */ + ar5416AniAttach(ah, &aniparams, &aniparams, AH_TRUE); } +void +ar9280InitPLL(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + uint32_t pll = SM(0x5, AR_RTC_SOWL_PLL_REFDIV); + + if (AR_SREV_MERLIN_20(ah) && + chan != AH_NULL && IEEE80211_IS_CHAN_5GHZ(chan)) { + /* + * PLL WAR for Merlin 2.0/2.1 + * When doing fast clock, set PLL to 0x142c + * Else, set PLL to 0x2850 to prevent reset-to-reset variation + */ + pll = IS_5GHZ_FAST_CLOCK_EN(ah, chan) ? 0x142c : 0x2850; + } else if (AR_SREV_MERLIN_10_OR_LATER(ah)) { + pll = SM(0x5, AR_RTC_SOWL_PLL_REFDIV); + if (chan != AH_NULL) { + if (IEEE80211_IS_CHAN_HALF(chan)) + pll |= SM(0x1, AR_RTC_SOWL_PLL_CLKSEL); + else if (IEEE80211_IS_CHAN_QUARTER(chan)) + pll |= SM(0x2, AR_RTC_SOWL_PLL_CLKSEL); + if (IEEE80211_IS_CHAN_5GHZ(chan)) + pll |= SM(0x28, AR_RTC_SOWL_PLL_DIV); + else + pll |= SM(0x2c, AR_RTC_SOWL_PLL_DIV); + } else + pll |= SM(0x2c, AR_RTC_SOWL_PLL_DIV); + } + + OS_REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll); + OS_DELAY(RTC_PLL_SETTLE_DELAY); + OS_REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_SLEEP_DERIVED_CLK); +} + +/* XXX shouldn't be here! */ +#define EEP_MINOR(_ah) \ + (AH_PRIVATE(_ah)->ah_eeversion & AR5416_EEP_VER_MINOR_MASK) + /* * Attach for an AR9280 part. */ static struct ath_hal * ar9280Attach(uint16_t devid, HAL_SOFTC sc, - HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status) + HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata, + HAL_STATUS *status) { struct ath_hal_9280 *ahp9280; struct ath_hal_5212 *ahp; @@ -85,14 +150,16 @@ ar9280Attach(uint16_t devid, HAL_SOFTC sc, uint32_t val; HAL_STATUS ecode; HAL_BOOL rfStatus; + int8_t pwr_table_offset; + uint8_t pwr; - HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", + HALDEBUG_G(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", __func__, sc, (void*) st, (void*) sh); /* NB: memory is returned zero'd */ ahp9280 = ath_hal_malloc(sizeof (struct ath_hal_9280)); if (ahp9280 == AH_NULL) { - HALDEBUG(AH_NULL, HAL_DEBUG_ANY, + HALDEBUG_G(AH_NULL, HAL_DEBUG_ANY, "%s: cannot allocate memory for state block\n", __func__); *status = HAL_ENOMEM; return AH_NULL; @@ -104,6 +171,8 @@ ar9280Attach(uint16_t devid, HAL_SOFTC sc, /* XXX override with 9280 specific state */ /* override 5416 methods for our needs */ + AH5416(ah)->ah_initPLL = ar9280InitPLL; + ah->ah_setAntennaSwitch = ar9280SetAntennaSwitch; ah->ah_configPCIE = ar9280ConfigPCIE; @@ -115,6 +184,10 @@ ar9280Attach(uint16_t devid, HAL_SOFTC sc, AH5416(ah)->ah_spurMitigate = ar9280SpurMitigate; AH5416(ah)->ah_writeIni = ar9280WriteIni; + AH5416(ah)->ah_olcInit = ar9280olcInit; + AH5416(ah)->ah_olcTempCompensation = ar9280olcTemperatureCompensation; + AH5416(ah)->ah_setPowerCalTable = ar9280SetPowerCalTable; + AH5416(ah)->ah_rx_chainmask = AR9280_DEFAULT_RXCHAINMASK; AH5416(ah)->ah_tx_chainmask = AR9280_DEFAULT_TXCHAINMASK; @@ -213,7 +286,31 @@ ar9280Attach(uint16_t devid, HAL_SOFTC sc, goto bad; } - if (AR_SREV_MERLIN_20_OR_LATER(ah)) { + /* Enable fixup for AR_AN_TOP2 if necessary */ + /* + * The v14 EEPROM layer returns HAL_EIO if PWDCLKIND isn't supported + * by the EEPROM version. + * + * ath9k checks the EEPROM minor version is >= 0x0a here, instead of + * the abstracted EEPROM access layer. + */ + ecode = ath_hal_eepromGet(ah, AR_EEP_PWDCLKIND, &pwr); + if (AR_SREV_MERLIN_20_OR_LATER(ah) && ecode == HAL_OK && pwr == 0) { + printf("[ath] enabling AN_TOP2_FIXUP\n"); + AH5416(ah)->ah_need_an_top2_fixup = 1; + } + + /* + * Check whether the power table offset isn't the default. + * This can occur with eeprom minor V21 or greater on Merlin. + */ + (void) ath_hal_eepromGet(ah, AR_EEP_PWR_TABLE_OFFSET, &pwr_table_offset); + if (pwr_table_offset != AR5416_PWR_TABLE_OFFSET_DB) + ath_hal_printf(ah, "[ath]: default pwr offset: %d dBm != EEPROM pwr offset: %d dBm; curves will be adjusted.\n", + AR5416_PWR_TABLE_OFFSET_DB, (int) pwr_table_offset); + + /* XXX check for >= minor ver 17 */ + if (AR_SREV_MERLIN_20(ah)) { /* setup rxgain table */ switch (ath_hal_eepromGet(ah, AR_EEP_RXGAIN_TYPE, AH_NULL)) { case AR5416_EEP_RXGAIN_13dB_BACKOFF: @@ -233,7 +330,9 @@ ar9280Attach(uint16_t devid, HAL_SOFTC sc, goto bad; /* XXX ? try to continue */ } } - if (AR_SREV_MERLIN_20_OR_LATER(ah)) { + + /* XXX check for >= minor ver 19 */ + if (AR_SREV_MERLIN_20(ah)) { /* setp txgain table */ switch (ath_hal_eepromGet(ah, AR_EEP_TXGAIN_TYPE, AH_NULL)) { case AR5416_EEP_TXGAIN_HIGH_POWER: @@ -268,6 +367,8 @@ ar9280Attach(uint16_t devid, HAL_SOFTC sc, /* Read Reg Domain */ AH_PRIVATE(ah)->ah_currentRD = ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, AH_NULL); + AH_PRIVATE(ah)->ah_currentRDext = + ath_hal_eepromGet(ah, AR_EEP_REGDMN_1, AH_NULL); /* * ah_miscMode is populated by ar5416FillCapabilityInfo() @@ -276,9 +377,18 @@ ar9280Attach(uint16_t devid, HAL_SOFTC sc, * placed into hardware. */ if (ahp->ah_miscMode != 0) - OS_REG_WRITE(ah, AR_MISC_MODE, ahp->ah_miscMode); + OS_REG_WRITE(ah, AR_MISC_MODE, OS_REG_READ(ah, AR_MISC_MODE) | ahp->ah_miscMode); ar9280AniSetup(ah); /* Anti Noise Immunity */ + + /* Setup noise floor min/max/nominal values */ + AH5416(ah)->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9280_2GHZ; + AH5416(ah)->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_9280_2GHZ; + AH5416(ah)->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9280_2GHZ; + AH5416(ah)->nf_5g.max = AR_PHY_CCA_MAX_GOOD_VAL_9280_5GHZ; + AH5416(ah)->nf_5g.min = AR_PHY_CCA_MIN_GOOD_VAL_9280_5GHZ; + AH5416(ah)->nf_5g.nominal = AR_PHY_CCA_NOM_VAL_9280_5GHZ; + ar5416InitNfHistBuff(AH5416(ah)->ah_cal.nfCalHist); HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__); @@ -308,6 +418,8 @@ ar9280WriteIni(struct ath_hal *ah, const struct ieee80211_channel *chan) { u_int modesIndex, freqIndex; int regWrites = 0; + int i; + const HAL_INI_ARRAY *ia; /* Setup the indices for the next set of register array writes */ /* XXX Ignore 11n dynamic mode on the AR5416 for the moment */ @@ -332,10 +444,33 @@ ar9280WriteIni(struct ath_hal *ah, const struct ieee80211_channel *chan) OS_REG_WRITE(ah, AR_PHY(0), 0x00000007); OS_REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC); - /* XXX Merlin ini fixups */ - /* XXX Merlin 100us delay for shift registers */ + /* + * This is unwound because at the moment, there's a requirement + * for Merlin (and later, perhaps) to have a specific bit fixed + * in the AR_AN_TOP2 register before writing it. + */ + ia = &AH5212(ah)->ah_ini_modes; +#if 0 regWrites = ath_hal_ini_write(ah, &AH5212(ah)->ah_ini_modes, modesIndex, regWrites); +#endif + HALASSERT(modesIndex < ia->cols); + for (i = 0; i < ia->rows; i++) { + uint32_t reg = HAL_INI_VAL(ia, i, 0); + uint32_t val = HAL_INI_VAL(ia, i, modesIndex); + + if (reg == AR_AN_TOP2 && AH5416(ah)->ah_need_an_top2_fixup) + val &= ~AR_AN_TOP2_PWDCLKIND; + + OS_REG_WRITE(ah, reg, val); + + /* Analog shift register delay seems needed for Merlin - PR kern/154220 */ + if (reg >= 0x7800 && reg < 0x7900) + OS_DELAY(100); + + DMA_YIELD(regWrites); + } + if (AR_SREV_MERLIN_20_OR_LATER(ah)) { regWrites = ath_hal_ini_write(ah, &AH9280(ah)->ah_ini_rxgain, modesIndex, regWrites); @@ -674,30 +809,54 @@ ar9280FillCapabilityInfo(struct ath_hal *ah) #if 0 pCap->halWowMatchPatternDword = AH_TRUE; #endif + /* AR9280 is a 2x2 stream device */ + pCap->halTxStreams = 2; + pCap->halRxStreams = 2; + pCap->halCSTSupport = AH_TRUE; pCap->halRifsRxSupport = AH_TRUE; pCap->halRifsTxSupport = AH_TRUE; pCap->halRtsAggrLimit = 64*1024; /* 802.11n max */ pCap->halExtChanDfsSupport = AH_TRUE; + pCap->halUseCombinedRadarRssi = AH_TRUE; #if 0 /* XXX bluetooth */ pCap->halBtCoexSupport = AH_TRUE; #endif pCap->halAutoSleepSupport = AH_FALSE; /* XXX? */ -#if 0 pCap->hal4kbSplitTransSupport = AH_FALSE; -#endif + /* Disable this so Block-ACK works correctly */ + pCap->halHasRxSelfLinkedTail = AH_FALSE; + pCap->halMbssidAggrSupport = AH_TRUE; + pCap->hal4AddrAggrSupport = AH_TRUE; + + if (AR_SREV_MERLIN_20(ah)) { + pCap->halPSPollBroken = AH_FALSE; + /* + * This just enables the support; it doesn't + * state 5ghz fast clock will always be used. + */ + pCap->halSupportsFastClock5GHz = AH_TRUE; + } pCap->halRxStbcSupport = 1; pCap->halTxStbcSupport = 1; + pCap->halEnhancedDfsSupport = AH_TRUE; return AH_TRUE; } +/* + * This has been disabled - having the HAL flip chainmasks on/off + * when attempting to implement 11n disrupts things. For now, just + * leave this flipped off and worry about implementing TX diversity + * for legacy and MCS0-7 when 11n is fully functioning. + */ HAL_BOOL ar9280SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING settings) { #define ANTENNA0_CHAINMASK 0x1 #define ANTENNA1_CHAINMASK 0x2 +#if 0 struct ath_hal_5416 *ahp = AH5416(ah); /* Antenna selection is done by setting the tx/rx chainmasks approp. */ @@ -716,10 +875,15 @@ ar9280SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING settings) case HAL_ANT_VARIABLE: /* Restore original chainmask settings */ /* XXX */ - ahp->ah_tx_chainmask = AR5416_DEFAULT_TXCHAINMASK; - ahp->ah_rx_chainmask = AR5416_DEFAULT_RXCHAINMASK; + ahp->ah_tx_chainmask = AR9280_DEFAULT_TXCHAINMASK; + ahp->ah_rx_chainmask = AR9280_DEFAULT_RXCHAINMASK; break; } + + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: settings=%d, tx/rx chainmask=%d/%d\n", + __func__, settings, ahp->ah_tx_chainmask, ahp->ah_rx_chainmask); + +#endif return AH_TRUE; #undef ANTENNA0_CHAINMASK #undef ANTENNA1_CHAINMASK diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9280_olc.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9280_olc.c new file mode 100644 index 0000000000..361930bf4b --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9280_olc.c @@ -0,0 +1,408 @@ +/* + * Copyright (c) 2011 Adrian Chadd, Xenion Pty Ltd. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ah_eeprom_v14.h" + +#include "ar9002/ar9280.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" +#include "ar9002/ar9002phy.h" + +#include "ar9002/ar9280_olc.h" + +void +ar9280olcInit(struct ath_hal *ah) +{ + uint32_t i; + + /* Only do OLC if it's enabled for this chipset */ + if (! ath_hal_eepromGetFlag(ah, AR_EEP_OL_PWRCTRL)) + return; + + HALDEBUG(ah, HAL_DEBUG_RESET, "%s: Setting up TX gain tables.\n", __func__); + + for (i = 0; i < AR9280_TX_GAIN_TABLE_SIZE; i++) + AH9280(ah)->originalGain[i] = MS(OS_REG_READ(ah, + AR_PHY_TX_GAIN_TBL1 + i * 4), AR_PHY_TX_GAIN); + + AH9280(ah)->PDADCdelta = 0; +} + +void +ar9280olcGetTxGainIndex(struct ath_hal *ah, + const struct ieee80211_channel *chan, + struct calDataPerFreqOpLoop *rawDatasetOpLoop, + uint8_t *calChans, uint16_t availPiers, uint8_t *pwr, uint8_t *pcdacIdx) +{ + uint8_t pcdac, i = 0; + uint16_t idxL = 0, idxR = 0, numPiers; + HAL_BOOL match; + CHAN_CENTERS centers; + + ar5416GetChannelCenters(ah, chan, ¢ers); + + for (numPiers = 0; numPiers < availPiers; numPiers++) + if (calChans[numPiers] == AR5416_BCHAN_UNUSED) + break; + + match = ath_ee_getLowerUpperIndex((uint8_t)FREQ2FBIN(centers.synth_center, + IEEE80211_IS_CHAN_2GHZ(chan)), calChans, numPiers, + &idxL, &idxR); + if (match) { + pcdac = rawDatasetOpLoop[idxL].pcdac[0][0]; + *pwr = rawDatasetOpLoop[idxL].pwrPdg[0][0]; + } else { + pcdac = rawDatasetOpLoop[idxR].pcdac[0][0]; + *pwr = (rawDatasetOpLoop[idxL].pwrPdg[0][0] + + rawDatasetOpLoop[idxR].pwrPdg[0][0])/2; + } + while (pcdac > AH9280(ah)->originalGain[i] && + i < (AR9280_TX_GAIN_TABLE_SIZE - 1)) + i++; + + *pcdacIdx = i; +} + +/* + * XXX txPower here is likely not the target txPower in the traditional + * XXX sense, but is set by a call to ar9280olcGetTxGainIndex(). + * XXX Thus, be careful if you're trying to use this routine yourself. + */ +void +ar9280olcGetPDADCs(struct ath_hal *ah, uint32_t initTxGain, int txPower, + uint8_t *pPDADCValues) +{ + uint32_t i; + uint32_t offset; + + OS_REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL6_0, AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3); + OS_REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL6_1, AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3); + + OS_REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL7, AR_PHY_TX_PWRCTRL_INIT_TX_GAIN, initTxGain); + + offset = txPower; + for (i = 0; i < AR5416_NUM_PDADC_VALUES; i++) + if (i < offset) + pPDADCValues[i] = 0x0; + else + pPDADCValues[i] = 0xFF; +} + +/* + * Run temperature compensation calibration. + * + * The TX gain table is adjusted depending upon the difference + * between the initial PDADC value and the currently read + * average TX power sample value. This value is only valid if + * frames have been transmitted, so currPDADC will be 0 if + * no frames have yet been transmitted. + */ +void +ar9280olcTemperatureCompensation(struct ath_hal *ah) +{ + uint32_t rddata, i; + int delta, currPDADC, regval; + uint8_t hpwr_5g = 0; + + if (! ath_hal_eepromGetFlag(ah, AR_EEP_OL_PWRCTRL)) + return; + + rddata = OS_REG_READ(ah, AR_PHY_TX_PWRCTRL4); + currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT); + + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "%s: called: initPDADC=%d, currPDADC=%d\n", + __func__, AH5416(ah)->initPDADC, currPDADC); + + if (AH5416(ah)->initPDADC == 0 || currPDADC == 0) + return; + + (void) (ath_hal_eepromGet(ah, AR_EEP_DAC_HPWR_5G, &hpwr_5g)); + + if (hpwr_5g) + delta = (currPDADC - AH5416(ah)->initPDADC + 4) / 8; + else + delta = (currPDADC - AH5416(ah)->initPDADC + 5) / 10; + + HALDEBUG(ah, HAL_DEBUG_PERCAL, "%s: delta=%d, PDADCdelta=%d\n", + __func__, delta, AH9280(ah)->PDADCdelta); + + if (delta != AH9280(ah)->PDADCdelta) { + AH9280(ah)->PDADCdelta = delta; + for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) { + regval = AH9280(ah)->originalGain[i] - delta; + if (regval < 0) + regval = 0; + + OS_REG_RMW_FIELD(ah, + AR_PHY_TX_GAIN_TBL1 + i * 4, + AR_PHY_TX_GAIN, regval); + } + } +} + + +static int16_t +ar9280ChangeGainBoundarySettings(struct ath_hal *ah, uint16_t *gb, + uint16_t numXpdGain, uint16_t pdGainOverlap_t2, int8_t pwr_table_offset, + int16_t *diff) +{ + uint16_t k; + + /* Prior to writing the boundaries or the pdadc vs. power table + * into the chip registers the default starting point on the pdadc + * vs. power table needs to be checked and the curve boundaries + * adjusted accordingly + */ + if (AR_SREV_MERLIN_20_OR_LATER(ah)) { + uint16_t gb_limit; + + if (AR5416_PWR_TABLE_OFFSET_DB != pwr_table_offset) { + /* get the difference in dB */ + *diff = (uint16_t)(pwr_table_offset - AR5416_PWR_TABLE_OFFSET_DB); + /* get the number of half dB steps */ + *diff *= 2; + /* change the original gain boundary settings + * by the number of half dB steps + */ + for (k = 0; k < numXpdGain; k++) + gb[k] = (uint16_t)(gb[k] - *diff); + } + /* Because of a hardware limitation, ensure the gain boundary + * is not larger than (63 - overlap) + */ + gb_limit = (uint16_t)(AR5416_MAX_RATE_POWER - pdGainOverlap_t2); + + for (k = 0; k < numXpdGain; k++) + gb[k] = (uint16_t)min(gb_limit, gb[k]); + } + + return *diff; +} + +static void +ar9280AdjustPDADCValues(struct ath_hal *ah, int8_t pwr_table_offset, + int16_t diff, uint8_t *pdadcValues) +{ +#define NUM_PDADC(diff) (AR5416_NUM_PDADC_VALUES - diff) + uint16_t k; + + /* If this is a board that has a pwrTableOffset that differs from + * the default AR5416_PWR_TABLE_OFFSET_DB then the start of the + * pdadc vs pwr table needs to be adjusted prior to writing to the + * chip. + */ + if (AR_SREV_MERLIN_20_OR_LATER(ah)) { + if (AR5416_PWR_TABLE_OFFSET_DB != pwr_table_offset) { + /* shift the table to start at the new offset */ + for (k = 0; k < (uint16_t)NUM_PDADC(diff); k++ ) { + pdadcValues[k] = pdadcValues[k + diff]; + } + + /* fill the back of the table */ + for (k = (uint16_t)NUM_PDADC(diff); k < NUM_PDADC(0); k++) { + pdadcValues[k] = pdadcValues[NUM_PDADC(diff)]; + } + } + } +#undef NUM_PDADC +} +/* + * This effectively disables the gain boundaries leaving it + * to the open-loop TX power control. + */ +static void +ar9280SetGainBoundariesOpenLoop(struct ath_hal *ah, int i, + uint16_t pdGainOverlap_t2, uint16_t gainBoundaries[]) +{ + int regChainOffset; + + regChainOffset = ar5416GetRegChainOffset(ah, i); + + /* These are unused for OLC */ + (void) pdGainOverlap_t2; + (void) gainBoundaries; + + HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: chain %d: writing closed loop values\n", + __func__, i); + + OS_REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset, + SM(0x6, AR_PHY_TPCRG5_PD_GAIN_OVERLAP) | + SM(0x38, AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) | + SM(0x38, AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) | + SM(0x38, AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) | + SM(0x38, AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4)); +} + +/* Eeprom versioning macros. Returns true if the version is equal or newer than the ver specified */ +/* XXX shouldn't be here! */ +#define EEP_MINOR(_ah) \ + (AH_PRIVATE(_ah)->ah_eeversion & AR5416_EEP_VER_MINOR_MASK) +#define IS_EEP_MINOR_V2(_ah) (EEP_MINOR(_ah) >= AR5416_EEP_MINOR_VER_2) +#define IS_EEP_MINOR_V3(_ah) (EEP_MINOR(_ah) >= AR5416_EEP_MINOR_VER_3) + +/************************************************************** + * ar9280SetPowerCalTable + * + * Pull the PDADC piers from cal data and interpolate them across the given + * points as well as from the nearest pier(s) to get a power detector + * linear voltage to power level table. + * + * Handle OLC for Merlin where required. + */ +HAL_BOOL +ar9280SetPowerCalTable(struct ath_hal *ah, struct ar5416eeprom *pEepData, + const struct ieee80211_channel *chan, int16_t *pTxPowerIndexOffset) +{ + CAL_DATA_PER_FREQ *pRawDataset; + uint8_t *pCalBChans = AH_NULL; + uint16_t pdGainOverlap_t2; + static uint8_t pdadcValues[AR5416_NUM_PDADC_VALUES]; + uint16_t gainBoundaries[AR5416_PD_GAINS_IN_MASK]; + uint16_t numPiers, i; + int16_t tMinCalPower; + uint16_t numXpdGain, xpdMask; + uint16_t xpdGainValues[AR5416_NUM_PD_GAINS]; + uint32_t regChainOffset; + int8_t pwr_table_offset; + + OS_MEMZERO(xpdGainValues, sizeof(xpdGainValues)); + + xpdMask = pEepData->modalHeader[IEEE80211_IS_CHAN_2GHZ(chan)].xpdGain; + + (void) ath_hal_eepromGet(ah, AR_EEP_PWR_TABLE_OFFSET, &pwr_table_offset); + + + if (IS_EEP_MINOR_V2(ah)) { + pdGainOverlap_t2 = pEepData->modalHeader[IEEE80211_IS_CHAN_2GHZ(chan)].pdGainOverlap; + } else { + pdGainOverlap_t2 = (uint16_t)(MS(OS_REG_READ(ah, AR_PHY_TPCRG5), AR_PHY_TPCRG5_PD_GAIN_OVERLAP)); + } + + if (IEEE80211_IS_CHAN_2GHZ(chan)) { + pCalBChans = pEepData->calFreqPier2G; + numPiers = AR5416_NUM_2G_CAL_PIERS; + } else { + pCalBChans = pEepData->calFreqPier5G; + numPiers = AR5416_NUM_5G_CAL_PIERS; + } + + /* If OLC is being done, set the init PDADC value appropriately */ + if (IEEE80211_IS_CHAN_2GHZ(chan) && AR_SREV_MERLIN_20_OR_LATER(ah) && + ath_hal_eepromGetFlag(ah, AR_EEP_OL_PWRCTRL)) { + struct calDataPerFreq *pRawDataset = pEepData->calPierData2G[0]; + AH5416(ah)->initPDADC = ((struct calDataPerFreqOpLoop *) pRawDataset)->vpdPdg[0][0]; + } else { + /* + * XXX ath9k doesn't clear this for 5ghz mode if + * it were set in 2ghz mode before! + * The Merlin OLC temperature compensation code + * uses this to calculate the PDADC delta during + * calibration ; 0 here effectively stops the + * temperature compensation calibration from + * occuring. + */ + AH5416(ah)->initPDADC = 0; + } + + /* Calculate the value of xpdgains from the xpdGain Mask */ + numXpdGain = ar5416GetXpdGainValues(ah, xpdMask, xpdGainValues); + + /* Write the detector gain biases and their number */ + ar5416WriteDetectorGainBiases(ah, numXpdGain, xpdGainValues); + + for (i = 0; i < AR5416_MAX_CHAINS; i++) { + regChainOffset = ar5416GetRegChainOffset(ah, i); + if (pEepData->baseEepHeader.txMask & (1 << i)) { + uint16_t diff; + + if (IEEE80211_IS_CHAN_2GHZ(chan)) { + pRawDataset = pEepData->calPierData2G[i]; + } else { + pRawDataset = pEepData->calPierData5G[i]; + } + + /* Fetch the gain boundaries and the PDADC values */ + if (AR_SREV_MERLIN_20_OR_LATER(ah) && + ath_hal_eepromGetFlag(ah, AR_EEP_OL_PWRCTRL)) { + uint8_t pcdacIdx; + uint8_t txPower; + + ar9280olcGetTxGainIndex(ah, chan, + (struct calDataPerFreqOpLoop *) pRawDataset, + pCalBChans, numPiers, &txPower, &pcdacIdx); + ar9280olcGetPDADCs(ah, pcdacIdx, txPower / 2, pdadcValues); + } else { + ar5416GetGainBoundariesAndPdadcs(ah, chan, + pRawDataset, pCalBChans, numPiers, + pdGainOverlap_t2, &tMinCalPower, + gainBoundaries, pdadcValues, numXpdGain); + } + + /* + * Prior to writing the boundaries or the pdadc vs. power table + * into the chip registers the default starting point on the pdadc + * vs. power table needs to be checked and the curve boundaries + * adjusted accordingly + */ + diff = ar9280ChangeGainBoundarySettings(ah, + gainBoundaries, numXpdGain, pdGainOverlap_t2, + pwr_table_offset, &diff); + + if ((i == 0) || AR_SREV_5416_V20_OR_LATER(ah)) { + /* Set gain boundaries for either open- or closed-loop TPC */ + if (AR_SREV_MERLIN_20_OR_LATER(ah) && + ath_hal_eepromGetFlag(ah, AR_EEP_OL_PWRCTRL)) + ar9280SetGainBoundariesOpenLoop(ah, + i, pdGainOverlap_t2, + gainBoundaries); + else + ar5416SetGainBoundariesClosedLoop(ah, + i, pdGainOverlap_t2, + gainBoundaries); + } + + /* + * If this is a board that has a pwrTableOffset that differs from + * the default AR5416_PWR_TABLE_OFFSET_DB then the start of the + * pdadc vs pwr table needs to be adjusted prior to writing to the + * chip. + */ + ar9280AdjustPDADCValues(ah, pwr_table_offset, diff, pdadcValues); + + /* Write the power values into the baseband power table */ + ar5416WritePdadcValues(ah, i, pdadcValues); + } + } + *pTxPowerIndexOffset = 0; + + return AH_TRUE; +} diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9280_olc.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9280_olc.h new file mode 100644 index 0000000000..e08639c0ca --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9280_olc.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2010-2011 Adrian Chadd, Xenion Pty Ltd. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef __ATH_AR9280_OLC_H__ +#define __ATH_AR9280_OLC_H__ + +extern void ar9280olcInit(struct ath_hal *ah); + +/* OLC TX power control */ +extern void ar9280olcGetPDADCs(struct ath_hal *ah, uint32_t initTxGain, + int txPower, uint8_t *pPDADCValues); +extern void ar9280olcGetTxGainIndex(struct ath_hal *ah, + const struct ieee80211_channel *chan, + struct calDataPerFreqOpLoop *rawDatasetOpLoop, + uint8_t *calChans, uint16_t availPiers, uint8_t *pwr, uint8_t *pcdacIdx); +extern void ar9280GetGainBoundariesAndPdadcs(struct ath_hal *ah, + const struct ieee80211_channel *chan, CAL_DATA_PER_FREQ *pRawDataSet, + uint8_t * bChans, uint16_t availPiers, + uint16_t tPdGainOverlap, int16_t *pMinCalPower, + uint16_t * pPdGainBoundaries, uint8_t * pPDADCValues, + uint16_t numXpdGains); +extern HAL_BOOL ar9280SetPowerCalTable(struct ath_hal *ah, + struct ar5416eeprom *pEepData, const struct ieee80211_channel *chan, + int16_t *pTxPowerIndexOffset); + +/* OLC calibration */ +extern void ar9280olcTemperatureCompensation(struct ath_hal *ah); + +#endif diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar9280v1.ini b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9280v1.ini similarity index 100% rename from src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar9280v1.ini rename to src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9280v1.ini diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar9280v2.ini b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9280v2.ini similarity index 81% rename from src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar9280v2.ini rename to src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9280v2.ini index aa8e524840..60286ec0a5 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar9280v2.ini +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9280v2.ini @@ -1,6 +1,5 @@ /* - * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting - * Copyright (c) 2002-2008 Atheros Communications, Inc. + * Copyright (c) 2010 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -16,7 +15,6 @@ * * $FreeBSD$ */ -/* Auto Generated PCI Register Writes. Created: 10/15/08 */ static const uint32_t ar9280Modes_v2[][6] = { /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ @@ -26,51 +24,50 @@ static const uint32_t ar9280Modes_v2[][6] = { { 0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008 }, { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 }, { 0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f }, + { 0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810 }, + { 0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a, 0x0000320a }, { 0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880 }, { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, - { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009824, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e }, { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, { 0x00009840, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e, 0x206a012e }, { 0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0 }, - { 0x00009850, 0x6c4000e2, 0x6c4000e2, 0x6d4000e2, 0x6c4000e2, 0x6c4000e2 }, + { 0x00009850, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2, 0x6c4000e2 }, { 0x00009858, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e }, - { 0x0000985c, 0x31395d5e, 0x31395d5e, 0x3139605e, 0x31395d5e, 0x31395d5e }, + { 0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e, 0x31395d5e }, { 0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18 }, { 0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, { 0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 }, { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 }, { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 }, - { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 }, + { 0x00009918, 0x0000000a, 0x00000014, 0x00000268, 0x0000000b, 0x00000016 }, { 0x00009924, 0xd00a8a0b, 0xd00a8a0b, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d }, { 0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1010, 0xffbc1010, 0xffbc1010 }, { 0x00009960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 }, { 0x0000a960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 }, { 0x00009964, 0x00000210, 0x00000210, 0x00000210, 0x00000210, 0x00000210 }, + { 0x0000c968, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce, 0x000003ce }, { 0x000099b8, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c }, { 0x000099bc, 0x00000a00, 0x00000a00, 0x00000c00, 0x00000c00, 0x00000c00 }, { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 }, - { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, - { 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329 }, - { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, - { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, - { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, { 0x0000a204, 0x00000444, 0x00000444, 0x00000444, 0x00000444, 0x00000444 }, { 0x0000a20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019, 0x0001f019 }, { 0x0000b20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019, 0x0001f019 }, { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, + { 0x0000a23c, 0x13c88000, 0x13c88000, 0x13c88001, 0x13c88000, 0x13c88000 }, { 0x0000a250, 0x001ff000, 0x001ff000, 0x0004a000, 0x0004a000, 0x0004a000 }, - { 0x0000a274, 0x0a19c652, 0x0a19c652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652 }, { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e }, + { 0x0000a388, 0x0c000000, 0x0c000000, 0x08000000, 0x0c000000, 0x0c000000 }, { 0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, { 0x00007894, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000 }, }; static const uint32_t ar9280Common_v2[][2] = { + /* Addr allmodes */ { 0x0000000c, 0x00000000 }, { 0x00000030, 0x00020015 }, { 0x00000034, 0x00000005 }, @@ -196,7 +193,6 @@ static const uint32_t ar9280Common_v2[][2] = { { 0x00008110, 0x00000168 }, { 0x00008118, 0x000100aa }, { 0x0000811c, 0x00003210 }, - { 0x00008120, 0x08f04800 }, { 0x00008124, 0x00000000 }, { 0x00008128, 0x00000000 }, { 0x0000812c, 0x00000000 }, @@ -212,7 +208,6 @@ static const uint32_t ar9280Common_v2[][2] = { { 0x00008178, 0x00000100 }, { 0x0000817c, 0x00000000 }, { 0x000081c0, 0x00000000 }, - { 0x000081d0, 0x00003210 }, { 0x000081ec, 0x00000000 }, { 0x000081f0, 0x00000000 }, { 0x000081f4, 0x00000000 }, @@ -243,7 +238,7 @@ static const uint32_t ar9280Common_v2[][2] = { { 0x00008258, 0x00000000 }, { 0x0000825c, 0x400000ff }, { 0x00008260, 0x00080922 }, - { 0x00008264, 0xa8a00010 }, + { 0x00008264, 0x88a00010 }, { 0x00008270, 0x00000000 }, { 0x00008274, 0x40000000 }, { 0x00008278, 0x003e4180 }, @@ -263,7 +258,7 @@ static const uint32_t ar9280Common_v2[][2] = { { 0x00008338, 0x00ff0000 }, { 0x0000833c, 0x00000000 }, { 0x00008340, 0x000107ff }, - { 0x00008344, 0x00581043 }, + { 0x00008344, 0x00481043 }, { 0x00009808, 0x00000000 }, { 0x0000980c, 0xafa68e30 }, { 0x00009810, 0xfd14e000 }, @@ -294,8 +289,7 @@ static const uint32_t ar9280Common_v2[][2] = { { 0x00009958, 0x2108ecff }, { 0x00009940, 0x14750604 }, { 0x0000c95c, 0x004b6a8e }, - { 0x00009968, 0x000003ce }, - { 0x00009970, 0x190fb515 }, + { 0x00009970, 0x190fb514 }, { 0x00009974, 0x00000000 }, { 0x00009978, 0x00000001 }, { 0x0000997c, 0x00000000 }, @@ -313,6 +307,12 @@ static const uint32_t ar9280Common_v2[][2] = { { 0x000099ac, 0x006f0000 }, { 0x000099b0, 0x03051000 }, { 0x000099b4, 0x00000820 }, + { 0x000099c4, 0x06336f77 }, + { 0x000099c8, 0x6af6532f }, + { 0x000099cc, 0x08f186c8 }, + { 0x000099d0, 0x00046384 }, + { 0x000099d4, 0x00000000 }, + { 0x000099d8, 0x00000000 }, { 0x000099dc, 0x00000000 }, { 0x000099e0, 0x00000000 }, { 0x000099e4, 0xaaaaaaaa }, @@ -330,7 +330,6 @@ static const uint32_t ar9280Common_v2[][2] = { { 0x0000a22c, 0x233f7180 }, { 0x0000a234, 0x20202020 }, { 0x0000a238, 0x20202020 }, - { 0x0000a23c, 0x13c88000 }, { 0x0000a240, 0x38490a20 }, { 0x0000a244, 0x00007bb6 }, { 0x0000a248, 0x0fff3ffc }, @@ -340,8 +339,8 @@ static const uint32_t ar9280Common_v2[][2] = { { 0x0000a25c, 0x0f0f0f01 }, { 0x0000a260, 0xdfa91f01 }, { 0x0000a268, 0x00000000 }, - { 0x0000a26c, 0x0ebae9c6 }, - { 0x0000b26c, 0x0ebae9c6 }, + { 0x0000a26c, 0x0e79e5c6 }, + { 0x0000b26c, 0x0e79e5c6 }, { 0x0000d270, 0x00820820 }, { 0x0000a278, 0x1ce739ce }, { 0x0000d35c, 0x07ffffef }, @@ -355,7 +354,6 @@ static const uint32_t ar9280Common_v2[][2] = { { 0x0000d37c, 0x7fffffe2 }, { 0x0000d380, 0x7f3c7bba }, { 0x0000d384, 0xf3307ff0 }, - { 0x0000a388, 0x0c000000 }, { 0x0000a38c, 0x20202020 }, { 0x0000a390, 0x20202020 }, { 0x0000a394, 0x1ce739ce }, @@ -379,23 +377,18 @@ static const uint32_t ar9280Common_v2[][2] = { { 0x0000a3e0, 0x000001ce }, { 0x0000a3e4, 0x00000000 }, { 0x0000a3e8, 0x18c43433 }, - { 0x0000a3ec, 0x00f70081 }, { 0x00007800, 0x00040000 }, { 0x00007804, 0xdb005012 }, { 0x00007808, 0x04924914 }, { 0x0000780c, 0x21084210 }, { 0x00007810, 0x6d801300 }, { 0x00007818, 0x07e41000 }, - { 0x0000781c, 0x00392000 }, - { 0x00007820, 0x92592480 }, { 0x00007824, 0x00040000 }, { 0x00007828, 0xdb005012 }, { 0x0000782c, 0x04924914 }, { 0x00007830, 0x21084210 }, { 0x00007834, 0x6d801300 }, { 0x0000783c, 0x07e40000 }, - { 0x00007840, 0x00392000 }, - { 0x00007844, 0x92592480 }, { 0x00007848, 0x00100000 }, { 0x0000784c, 0x773f0567 }, { 0x00007850, 0x54214514 }, @@ -418,7 +411,7 @@ static const uint32_t ar9280Common_v2[][2] = { }; static const uint32_t ar9280Modes_fast_clock_v2[][3] = { - /* Address 5G-HT20 5G-HT40 */ + /* Addr 5G_HT20 5G_HT40 */ { 0x00001030, 0x00000268, 0x000004d0 }, { 0x00001070, 0x0000018c, 0x00000318 }, { 0x000010b0, 0x00000fd0, 0x00001fa0 }, @@ -426,13 +419,12 @@ static const uint32_t ar9280Modes_fast_clock_v2[][3] = { { 0x0000801c, 0x148ec02b, 0x148ec057 }, { 0x00008318, 0x000044c0, 0x00008980 }, { 0x00009820, 0x02020200, 0x02020200 }, - { 0x00009824, 0x00000f0f, 0x00000f0f }, + { 0x00009824, 0x01000f0f, 0x01000f0f }, { 0x00009828, 0x0b020001, 0x0b020001 }, { 0x00009834, 0x00000f0f, 0x00000f0f }, { 0x00009844, 0x03721821, 0x03721821 }, { 0x00009914, 0x00000898, 0x00001130 }, { 0x00009918, 0x0000000b, 0x00000016 }, - { 0x00009944, 0xdfbc1210, 0xdfbc1210 }, }; static const uint32_t ar9280Modes_backoff_23db_rxgain_v2[][6] = { @@ -486,96 +478,96 @@ static const uint32_t ar9280Modes_backoff_23db_rxgain_v2[][6] = { { 0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08 }, { 0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c }, { 0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b10, 0x00008b10, 0x00008b10 }, - { 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b14, 0x00008b14, 0x00008b14 }, - { 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b01, 0x00008b01, 0x00008b01 }, - { 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b05, 0x00008b05, 0x00008b05 }, - { 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b09, 0x00008b09, 0x00008b09 }, - { 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008b0d, 0x00008b0d, 0x00008b0d }, - { 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008b11, 0x00008b11, 0x00008b11 }, - { 0x00009adc, 0x0000b390, 0x0000b390, 0x00008b15, 0x00008b15, 0x00008b15 }, - { 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008b02, 0x00008b02, 0x00008b02 }, - { 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008b06, 0x00008b06, 0x00008b06 }, - { 0x00009ae8, 0x0000b780, 0x0000b780, 0x00008b0a, 0x00008b0a, 0x00008b0a }, - { 0x00009aec, 0x0000b784, 0x0000b784, 0x00008b0e, 0x00008b0e, 0x00008b0e }, - { 0x00009af0, 0x0000b788, 0x0000b788, 0x00008b12, 0x00008b12, 0x00008b12 }, - { 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00008b16, 0x00008b16, 0x00008b16 }, - { 0x00009af8, 0x0000b790, 0x0000b790, 0x00008b03, 0x00008b03, 0x00008b03 }, - { 0x00009afc, 0x0000b794, 0x0000b794, 0x00008b07, 0x00008b07, 0x00008b07 }, - { 0x00009b00, 0x0000b798, 0x0000b798, 0x00008b0b, 0x00008b0b, 0x00008b0b }, - { 0x00009b04, 0x0000d784, 0x0000d784, 0x00008b0f, 0x00008b0f, 0x00008b0f }, - { 0x00009b08, 0x0000d788, 0x0000d788, 0x00008b13, 0x00008b13, 0x00008b13 }, - { 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00008b17, 0x00008b17, 0x00008b17 }, - { 0x00009b10, 0x0000d790, 0x0000d790, 0x00008b23, 0x00008b23, 0x00008b23 }, - { 0x00009b14, 0x0000f780, 0x0000f780, 0x00008b27, 0x00008b27, 0x00008b27 }, - { 0x00009b18, 0x0000f784, 0x0000f784, 0x00008b2b, 0x00008b2b, 0x00008b2b }, - { 0x00009b1c, 0x0000f788, 0x0000f788, 0x00008b2f, 0x00008b2f, 0x00008b2f }, - { 0x00009b20, 0x0000f78c, 0x0000f78c, 0x00008b33, 0x00008b33, 0x00008b33 }, - { 0x00009b24, 0x0000f790, 0x0000f790, 0x00008b37, 0x00008b37, 0x00008b37 }, - { 0x00009b28, 0x0000f794, 0x0000f794, 0x00008b43, 0x00008b43, 0x00008b43 }, - { 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x00008b47, 0x00008b47, 0x00008b47 }, - { 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x00008b4b, 0x00008b4b, 0x00008b4b }, - { 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x00008b4f, 0x00008b4f, 0x00008b4f }, - { 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x00008b53, 0x00008b53, 0x00008b53 }, - { 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x00008b57, 0x00008b57, 0x00008b57 }, - { 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b98, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bac, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009be0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009be4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009be8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bec, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009848, 0x00001066, 0x00001066, 0x00001050, 0x00001050, 0x00001050 }, - { 0x0000a848, 0x00001066, 0x00001066, 0x00001050, 0x00001050, 0x00001050 }, + { 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b80, 0x00008b80, 0x00008b80 }, + { 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b84, 0x00008b84, 0x00008b84 }, + { 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b88, 0x00008b88, 0x00008b88 }, + { 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b8c, 0x00008b8c, 0x00008b8c }, + { 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008b90, 0x00008b90, 0x00008b90 }, + { 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008b94, 0x00008b94, 0x00008b94 }, + { 0x00009adc, 0x0000b390, 0x0000b390, 0x00008b98, 0x00008b98, 0x00008b98 }, + { 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008ba4, 0x00008ba4, 0x00008ba4 }, + { 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008ba8, 0x00008ba8, 0x00008ba8 }, + { 0x00009ae8, 0x0000b780, 0x0000b780, 0x00008bac, 0x00008bac, 0x00008bac }, + { 0x00009aec, 0x0000b784, 0x0000b784, 0x00008bb0, 0x00008bb0, 0x00008bb0 }, + { 0x00009af0, 0x0000b788, 0x0000b788, 0x00008bb4, 0x00008bb4, 0x00008bb4 }, + { 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00008ba1, 0x00008ba1, 0x00008ba1 }, + { 0x00009af8, 0x0000b790, 0x0000b790, 0x00008ba5, 0x00008ba5, 0x00008ba5 }, + { 0x00009afc, 0x0000b794, 0x0000b794, 0x00008ba9, 0x00008ba9, 0x00008ba9 }, + { 0x00009b00, 0x0000b798, 0x0000b798, 0x00008bad, 0x00008bad, 0x00008bad }, + { 0x00009b04, 0x0000d784, 0x0000d784, 0x00008bb1, 0x00008bb1, 0x00008bb1 }, + { 0x00009b08, 0x0000d788, 0x0000d788, 0x00008bb5, 0x00008bb5, 0x00008bb5 }, + { 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00008ba2, 0x00008ba2, 0x00008ba2 }, + { 0x00009b10, 0x0000d790, 0x0000d790, 0x00008ba6, 0x00008ba6, 0x00008ba6 }, + { 0x00009b14, 0x0000f780, 0x0000f780, 0x00008baa, 0x00008baa, 0x00008baa }, + { 0x00009b18, 0x0000f784, 0x0000f784, 0x00008bae, 0x00008bae, 0x00008bae }, + { 0x00009b1c, 0x0000f788, 0x0000f788, 0x00008bb2, 0x00008bb2, 0x00008bb2 }, + { 0x00009b20, 0x0000f78c, 0x0000f78c, 0x00008bb6, 0x00008bb6, 0x00008bb6 }, + { 0x00009b24, 0x0000f790, 0x0000f790, 0x00008ba3, 0x00008ba3, 0x00008ba3 }, + { 0x00009b28, 0x0000f794, 0x0000f794, 0x00008ba7, 0x00008ba7, 0x00008ba7 }, + { 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x00008bab, 0x00008bab, 0x00008bab }, + { 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x00008baf, 0x00008baf, 0x00008baf }, + { 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x00008bb3, 0x00008bb3, 0x00008bb3 }, + { 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x00008bb7, 0x00008bb7, 0x00008bb7 }, + { 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x00008bc3, 0x00008bc3, 0x00008bc3 }, + { 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x00008bc7, 0x00008bc7, 0x00008bc7 }, + { 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x00008bcb, 0x00008bcb, 0x00008bcb }, + { 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x00008bcf, 0x00008bcf, 0x00008bcf }, + { 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x00008bd3, 0x00008bd3, 0x00008bd3 }, + { 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x00008bd7, 0x00008bd7, 0x00008bd7 }, + { 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009b98, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009bac, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009be0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009be4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009be8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009bec, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009848, 0x00001066, 0x00001066, 0x00001055, 0x00001055, 0x00001055 }, + { 0x0000a848, 0x00001066, 0x00001066, 0x00001055, 0x00001055, 0x00001055 }, }; static const uint32_t ar9280Modes_original_rxgain_v2[][6] = { /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ - { 0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290, 0x00000290 }, - { 0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300, 0x00000300 }, - { 0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304, 0x00000304 }, - { 0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308, 0x00000308 }, - { 0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c, 0x0000030c }, + { 0x00009a00, 0x00008184, 0x00008184, 0x00008000, 0x00008000, 0x00008000 }, + { 0x00009a04, 0x00008188, 0x00008188, 0x00008000, 0x00008000, 0x00008000 }, + { 0x00009a08, 0x0000818c, 0x0000818c, 0x00008000, 0x00008000, 0x00008000 }, + { 0x00009a0c, 0x00008190, 0x00008190, 0x00008000, 0x00008000, 0x00008000 }, + { 0x00009a10, 0x00008194, 0x00008194, 0x00008000, 0x00008000, 0x00008000 }, { 0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000, 0x00008000 }, { 0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004, 0x00008004 }, { 0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008, 0x00008008 }, @@ -839,6 +831,8 @@ static const uint32_t ar9280Modes_backoff_13db_rxgain_v2[][6] = { static const uint32_t ar9280Modes_high_power_tx_gain_v2[][6] = { /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ + { 0x0000a274, 0x0a19e652, 0x0a19e652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652 }, + { 0x0000a27c, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce }, { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, { 0x0000a304, 0x00003002, 0x00003002, 0x00004002, 0x00004002, 0x00004002 }, { 0x0000a308, 0x00006004, 0x00006004, 0x00007008, 0x00007008, 0x00007008 }, @@ -848,26 +842,32 @@ static const uint32_t ar9280Modes_high_power_tx_gain_v2[][6] = { { 0x0000a318, 0x0001504a, 0x0001504a, 0x0001820a, 0x0001820a, 0x0001820a }, { 0x0000a31c, 0x0001904c, 0x0001904c, 0x0001b211, 0x0001b211, 0x0001b211 }, { 0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213, 0x0001e213 }, - { 0x0000a324, 0x00020092, 0x00020092, 0x00022411, 0x00022411, 0x00022411 }, - { 0x0000a328, 0x0002410a, 0x0002410a, 0x00025413, 0x00025413, 0x00025413 }, - { 0x0000a32c, 0x0002710c, 0x0002710c, 0x00029811, 0x00029811, 0x00029811 }, - { 0x0000a330, 0x0002b18b, 0x0002b18b, 0x0002c813, 0x0002c813, 0x0002c813 }, - { 0x0000a334, 0x0002e1cc, 0x0002e1cc, 0x00030a14, 0x00030a14, 0x00030a14 }, - { 0x0000a338, 0x000321ec, 0x000321ec, 0x00035a50, 0x00035a50, 0x00035a50 }, - { 0x0000a33c, 0x000321ec, 0x000321ec, 0x00039c4c, 0x00039c4c, 0x00039c4c }, - { 0x0000a340, 0x000321ec, 0x000321ec, 0x0003de8a, 0x0003de8a, 0x0003de8a }, - { 0x0000a344, 0x000321ec, 0x000321ec, 0x00042e92, 0x00042e92, 0x00042e92 }, - { 0x0000a348, 0x000321ec, 0x000321ec, 0x00046ed2, 0x00046ed2, 0x00046ed2 }, - { 0x0000a34c, 0x000321ec, 0x000321ec, 0x0004bed5, 0x0004bed5, 0x0004bed5 }, - { 0x0000a350, 0x000321ec, 0x000321ec, 0x0004ff54, 0x0004ff54, 0x0004ff54 }, - { 0x0000a354, 0x000321ec, 0x000321ec, 0x00053fd5, 0x00053fd5, 0x00053fd5 }, + { 0x0000a324, 0x00021092, 0x00021092, 0x00022411, 0x00022411, 0x00022411 }, + { 0x0000a328, 0x0002510a, 0x0002510a, 0x00025413, 0x00025413, 0x00025413 }, + { 0x0000a32c, 0x0002910c, 0x0002910c, 0x00029811, 0x00029811, 0x00029811 }, + { 0x0000a330, 0x0002c18b, 0x0002c18b, 0x0002c813, 0x0002c813, 0x0002c813 }, + { 0x0000a334, 0x0002f1cc, 0x0002f1cc, 0x00030a14, 0x00030a14, 0x00030a14 }, + { 0x0000a338, 0x000321eb, 0x000321eb, 0x00035a50, 0x00035a50, 0x00035a50 }, + { 0x0000a33c, 0x000341ec, 0x000341ec, 0x00039c4c, 0x00039c4c, 0x00039c4c }, + { 0x0000a340, 0x000341ec, 0x000341ec, 0x0003de8a, 0x0003de8a, 0x0003de8a }, + { 0x0000a344, 0x000341ec, 0x000341ec, 0x00042e92, 0x00042e92, 0x00042e92 }, + { 0x0000a348, 0x000341ec, 0x000341ec, 0x00046ed2, 0x00046ed2, 0x00046ed2 }, + { 0x0000a34c, 0x000341ec, 0x000341ec, 0x0004bed5, 0x0004bed5, 0x0004bed5 }, + { 0x0000a350, 0x000341ec, 0x000341ec, 0x0004ff54, 0x0004ff54, 0x0004ff54 }, + { 0x0000a354, 0x000341ec, 0x000341ec, 0x00055fd5, 0x00055fd5, 0x00055fd5 }, + { 0x0000a3ec, 0x00f70081, 0x00f70081, 0x00f70081, 0x00f70081, 0x00f70081 }, { 0x00007814, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff }, { 0x00007838, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff }, - { 0x0000a27c, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce }, + { 0x0000781c, 0x00172000, 0x00172000, 0x00172000, 0x00172000, 0x00172000 }, + { 0x00007840, 0x00172000, 0x00172000, 0x00172000, 0x00172000, 0x00172000 }, + { 0x00007820, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480 }, + { 0x00007844, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480 }, }; static const uint32_t ar9280Modes_original_tx_gain_v2[][6] = { /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ + { 0x0000a274, 0x0a19c652, 0x0a19c652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652 }, + { 0x0000a27c, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce }, { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, { 0x0000a304, 0x00003002, 0x00003002, 0x00003002, 0x00003002, 0x00003002 }, { 0x0000a308, 0x00006004, 0x00006004, 0x00008009, 0x00008009, 0x00008009 }, @@ -890,14 +890,17 @@ static const uint32_t ar9280Modes_original_tx_gain_v2[][6] = { { 0x0000a34c, 0x000321ec, 0x000321ec, 0x00046e8a, 0x00046e8a, 0x00046e8a }, { 0x0000a350, 0x000321ec, 0x000321ec, 0x00049ec9, 0x00049ec9, 0x00049ec9 }, { 0x0000a354, 0x000321ec, 0x000321ec, 0x0004bf42, 0x0004bf42, 0x0004bf42 }, + { 0x0000a3ec, 0x00f70081, 0x00f70081, 0x00f70081, 0x00f70081, 0x00f70081 }, { 0x00007814, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff }, { 0x00007838, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff }, - { 0x0000a27c, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce }, + { 0x0000781c, 0x00392000, 0x00392000, 0x00392000, 0x00392000, 0x00392000 }, + { 0x00007840, 0x00392000, 0x00392000, 0x00392000, 0x00392000, 0x00392000 }, + { 0x00007820, 0x92592480, 0x92592480, 0x92592480, 0x92592480, 0x92592480 }, + { 0x00007844, 0x92592480, 0x92592480, 0x92592480, 0x92592480, 0x92592480 }, }; -/* Auto generated PCI-E PHY config for Merlin with CLKREQ de-asserted in L1 mode. */ -/* In L1 mode, deassert CLKREQ, power consumption will be lower than leaving CLKREQ asserted. */ -static const uint32_t ar9280PciePhy_clkreq_off_L1_v2[][2] = { +static const uint32_t ar9280PciePhy_clkreq_off_L1_merlin[][2] = { + /* Addr allmodes */ {0x00004040, 0x9248fd00 }, {0x00004040, 0x24924924 }, {0x00004040, 0xa8000019 }, @@ -910,9 +913,8 @@ static const uint32_t ar9280PciePhy_clkreq_off_L1_v2[][2] = { {0x00004044, 0x00000000 }, }; -/* Auto generated PCI-E PHY config for Merlin with CLKREQ always asserted in L1 mode */ -/* In L1 mode leave CLKREQ asserted, power consumption will be little high. */ static const uint32_t ar9280PciePhy_clkreq_always_on_L1_v2[][2] = { + /* Addr allmodes */ {0x00004040, 0x9248fd00 }, {0x00004040, 0x24924924 }, {0x00004040, 0xa8000019 }, @@ -925,17 +927,3 @@ static const uint32_t ar9280PciePhy_clkreq_always_on_L1_v2[][2] = { {0x00004044, 0x00000000 }, }; -/* Auto generated PCI-E PHY config for Merlin with WOW */ -static const uint32_t ar9280PciePhy_AWOW_merlin[][2] = { - {0x00004040, 0x9248fd00 }, - {0x00004040, 0x24924924 }, - {0x00004040, 0xa8000019 }, - {0x00004040, 0x13160820 }, - {0x00004040, 0xe5980560 }, - {0x00004040, 0xc01ddffd }, - {0x00004040, 0x1aaabe41 }, - {0x00004040, 0xbe105554 }, - {0x00004040, 0x00043007 }, - {0x00004044, 0x00000000 }, -}; - diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar9285.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9285.c similarity index 83% rename from src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar9285.c rename to src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9285.c index 800c92fa1b..f1851ccc91 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar9285.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9285.c @@ -23,11 +23,21 @@ #include "ah_eeprom_v14.h" -#include "ar5416/ar9280.h" -#include "ar5416/ar9285.h" +#include "ar9002/ar9280.h" +#include "ar9002/ar9285.h" #include "ar5416/ar5416reg.h" #include "ar5416/ar5416phy.h" +/* + * The ordering of nfarray is thus: + * + * nfarray[0]: Chain 0 ctl + * nfarray[1]: Chain 1 ctl + * nfarray[2]: Chain 2 ctl + * nfarray[3]: Chain 0 ext + * nfarray[4]: Chain 1 ext + * nfarray[5]: Chain 2 ext + */ static void ar9285GetNoiseFloor(struct ath_hal *ah, int16_t nfarray[]) { @@ -40,7 +50,6 @@ ar9285GetNoiseFloor(struct ath_hal *ah, int16_t nfarray[]) "NF calibrated [ctl] [chain 0] is %d\n", nf); nfarray[0] = nf; - nfarray[1] = 0; nf = MS(OS_REG_READ(ah, AR_PHY_EXT_CCA), AR9280_PHY_EXT_MINCCA_PWR); if (nf & 0x100) @@ -49,7 +58,13 @@ ar9285GetNoiseFloor(struct ath_hal *ah, int16_t nfarray[]) "NF calibrated [ext] [chain 0] is %d\n", nf); nfarray[3] = nf; + /* Chain 1 - invalid */ + nfarray[1] = 0; nfarray[4] = 0; + + /* Chain 2 - invalid */ + nfarray[2] = 0; + nfarray[5] = 0; } HAL_BOOL diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar9285.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9285.h similarity index 55% rename from src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar9285.h rename to src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9285.h index 1ee058bf31..3f6b48143c 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar9285.h +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9285.h @@ -20,17 +20,63 @@ #include "ar5416/ar5416.h" +enum ar9285_ant_div_comb_lna_conf { + ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2 = 0, + ATH_ANT_DIV_COMB_LNA2 = 1, + ATH_ANT_DIV_COMB_LNA1 = 2, + ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2 = 3, +}; + +struct ar9285_ant_comb { + uint16_t count; + uint16_t total_pkt_count; + HAL_BOOL scan; + HAL_BOOL scan_not_start; + int main_total_rssi; + int alt_total_rssi; + int alt_recv_cnt; + int main_recv_cnt; + int rssi_lna1; + int rssi_lna2; + int rssi_add; + int rssi_sub; + int rssi_first; + int rssi_second; + int rssi_third; + HAL_BOOL alt_good; + int quick_scan_cnt; + int main_conf; + enum ar9285_ant_div_comb_lna_conf first_quick_scan_conf; + enum ar9285_ant_div_comb_lna_conf second_quick_scan_conf; + int first_bias; + int second_bias; + HAL_BOOL first_ratio; + HAL_BOOL second_ratio; + unsigned long scan_start_time; +}; + struct ath_hal_9285 { struct ath_hal_5416 ah_5416; HAL_INI_ARRAY ah_ini_txgain; HAL_INI_ARRAY ah_ini_rxgain; + + struct ar9285_ant_comb ant_comb; /* Kite Antenna comb/diversity */ + + struct { + int32_t prev_offset; /* Previous value of PA offset value */ + int8_t max_skipcount; /* Max No. of times PACAL can be skipped */ + int8_t skipcount; /* No. of times the PACAL to be skipped */ + } pacal_info; }; #define AH9285(_ah) ((struct ath_hal_9285 *)(_ah)) #define AR9285_DEFAULT_RXCHAINMASK 1 #define AR9285_DEFAULT_TXCHAINMASK 1 +#define AR_PHY_CCA_NOM_VAL_9285_2GHZ -118 +#define AR_PHY_CCA_MIN_GOOD_VAL_9285_2GHZ -127 +#define AR_PHY_CCA_MAX_GOOD_VAL_9285_2GHZ -108 HAL_BOOL ar9285SetAntennaSwitch(struct ath_hal *, HAL_ANT_SETTING); HAL_BOOL ar9285RfAttach(struct ath_hal *, HAL_STATUS *); diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar9285.ini b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9285.ini similarity index 100% rename from src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar9285.ini rename to src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9285.ini diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar9285_attach.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9285_attach.c similarity index 72% rename from src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar9285_attach.c rename to src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9285_attach.c index a639652021..02c7b9892a 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar9285_attach.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9285_attach.c @@ -24,14 +24,18 @@ #include "ah_eeprom_v4k.h" /* XXX for tx/rx gain */ -#include "ar5416/ar9280.h" -#include "ar5416/ar9285.h" +#include "ar9002/ar9280.h" +#include "ar9002/ar9285.h" #include "ar5416/ar5416reg.h" #include "ar5416/ar5416phy.h" -#include "ar5416/ar9285.ini" -#include "ar5416/ar9285v2.ini" -#include "ar5416/ar9280v2.ini" /* XXX ini for tx/rx gain */ +#include "ar9002/ar9285.ini" +#include "ar9002/ar9285v2.ini" +#include "ar9002/ar9280v2.ini" /* XXX ini for tx/rx gain */ + +#include "ar9002/ar9285_cal.h" +#include "ar9002/ar9285_phy.h" +#include "ar9002/ar9285_diversity.h" static const HAL_PERCAL_DATA ar9280_iq_cal = { /* single sample */ .calName = "IQ", .calType = IQ_MISMATCH_CAL, @@ -70,8 +74,33 @@ static void ar9285WriteIni(struct ath_hal *ah, static void ar9285AniSetup(struct ath_hal *ah) { - /* NB: disable ANI for reliable RIFS rx */ - ar5212AniAttach(ah, AH_NULL, AH_NULL, AH_FALSE); + /* + * These are the parameters from the AR5416 ANI code; + * they likely need quite a bit of adjustment for the + * AR9285. + */ + static const struct ar5212AniParams aniparams = { + .maxNoiseImmunityLevel = 4, /* levels 0..4 */ + .totalSizeDesired = { -55, -55, -55, -55, -62 }, + .coarseHigh = { -14, -14, -14, -14, -12 }, + .coarseLow = { -64, -64, -64, -64, -70 }, + .firpwr = { -78, -78, -78, -78, -80 }, + .maxSpurImmunityLevel = 2, + .cycPwrThr1 = { 2, 4, 6 }, + .maxFirstepLevel = 2, /* levels 0..2 */ + .firstep = { 0, 4, 8 }, + .ofdmTrigHigh = 500, + .ofdmTrigLow = 200, + .cckTrigHigh = 200, + .cckTrigLow = 100, + .rssiThrHigh = 40, + .rssiThrLow = 7, + .period = 100, + }; + /* NB: disable ANI noise immmunity for reliable RIFS rx */ + AH5416(ah)->ah_ani_function &= ~(1 << HAL_ANI_NOISE_IMMUNITY_LEVEL); + + ar5416AniAttach(ah, &aniparams, &aniparams, AH_TRUE); } /* @@ -79,7 +108,8 @@ ar9285AniSetup(struct ath_hal *ah) */ static struct ath_hal * ar9285Attach(uint16_t devid, HAL_SOFTC sc, - HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status) + HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata, + HAL_STATUS *status) { struct ath_hal_9285 *ahp9285; struct ath_hal_5212 *ahp; @@ -88,13 +118,13 @@ ar9285Attach(uint16_t devid, HAL_SOFTC sc, HAL_STATUS ecode; HAL_BOOL rfStatus; - HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", + HALDEBUG_G(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", __func__, sc, (void*) st, (void*) sh); /* NB: memory is returned zero'd */ ahp9285 = ath_hal_malloc(sizeof (struct ath_hal_9285)); if (ahp9285 == AH_NULL) { - HALDEBUG(AH_NULL, HAL_DEBUG_ANY, + HALDEBUG_G(AH_NULL, HAL_DEBUG_ANY, "%s: cannot allocate memory for state block\n", __func__); *status = HAL_ENOMEM; return AH_NULL; @@ -106,6 +136,8 @@ ar9285Attach(uint16_t devid, HAL_SOFTC sc, /* XXX override with 9285 specific state */ /* override 5416 methods for our needs */ + AH5416(ah)->ah_initPLL = ar9280InitPLL; + ah->ah_setAntennaSwitch = ar9285SetAntennaSwitch; ah->ah_configPCIE = ar9285ConfigPCIE; ah->ah_setTxPower = ar9285SetTransmitPower; @@ -121,6 +153,8 @@ ar9285Attach(uint16_t devid, HAL_SOFTC sc, AH5416(ah)->ah_writeIni = ar9285WriteIni; AH5416(ah)->ah_rx_chainmask = AR9285_DEFAULT_RXCHAINMASK; AH5416(ah)->ah_tx_chainmask = AR9285_DEFAULT_TXCHAINMASK; + + ahp->ah_maxTxTrigLev = MAX_TX_FIFO_THRESHOLD >> 1; if (!ar5416SetResetReg(ah, HAL_RESET_POWER_ON)) { /* reset chip */ @@ -162,6 +196,12 @@ ar9285Attach(uint16_t devid, HAL_SOFTC sc, } ar5416AttachPCIE(ah); + /* Attach methods that require MAC version/revision info */ + if (AR_SREV_KITE_12_OR_LATER(ah)) + AH5416(ah)->ah_cal_initcal = ar9285InitCalHardware; + if (AR_SREV_KITE_11_OR_LATER(ah)) + AH5416(ah)->ah_cal_pacal = ar9002_hw_pa_cal; + ecode = ath_hal_v4kEepromAttach(ah); if (ecode != HAL_OK) goto bad; @@ -218,15 +258,27 @@ ar9285Attach(uint16_t devid, HAL_SOFTC sc, HAL_INI_INIT(&ahp9285->ah_ini_rxgain, ar9280Modes_original_rxgain_v2, 6); + + if (AR_SREV_9285E_20(ah)) + ath_hal_printf(ah, "[ath] AR9285E_20 detected; using XE TX gain tables\n"); + /* setup txgain table */ switch (ath_hal_eepromGet(ah, AR_EEP_TXGAIN_TYPE, AH_NULL)) { case AR5416_EEP_TXGAIN_HIGH_POWER: - HAL_INI_INIT(&ahp9285->ah_ini_txgain, - ar9285Modes_high_power_tx_gain_v2, 6); + if (AR_SREV_9285E_20(ah)) + HAL_INI_INIT(&ahp9285->ah_ini_txgain, + ar9285Modes_XE2_0_high_power, 6); + else + HAL_INI_INIT(&ahp9285->ah_ini_txgain, + ar9285Modes_high_power_tx_gain_v2, 6); break; case AR5416_EEP_TXGAIN_ORIG: - HAL_INI_INIT(&ahp9285->ah_ini_txgain, - ar9285Modes_original_tx_gain_v2, 6); + if (AR_SREV_9285E_20(ah)) + HAL_INI_INIT(&ahp9285->ah_ini_txgain, + ar9285Modes_XE2_0_normal_power, 6); + else + HAL_INI_INIT(&ahp9285->ah_ini_txgain, + ar9285Modes_original_tx_gain_v2, 6); break; default: HALASSERT(AH_FALSE); @@ -241,6 +293,16 @@ ar9285Attach(uint16_t devid, HAL_SOFTC sc, goto bad; } + /* Print out whether the EEPROM settings enable AR9285 diversity */ + if (ar9285_check_div_comb(ah)) { + ath_hal_printf(ah, "[ath] Enabling diversity for Kite\n"); + ah->ah_rxAntCombDiversity = ar9285_ant_comb_scan; + } + + /* Disable 11n for the AR2427 */ + if (devid == AR2427_DEVID_PCIE) + AH_PRIVATE(ah)->ah_caps.halHTSupport = AH_FALSE; + ecode = ath_hal_eepromGet(ah, AR_EEP_MACADDR, ahp->ah_macaddr); if (ecode != HAL_OK) { HALDEBUG(ah, HAL_DEBUG_ANY, @@ -251,6 +313,11 @@ ar9285Attach(uint16_t devid, HAL_SOFTC sc, /* Read Reg Domain */ AH_PRIVATE(ah)->ah_currentRD = ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, AH_NULL); + /* + * For Kite and later chipsets, the following bits are not + * programmed in EEPROM and so are set as enabled always. + */ + AH_PRIVATE(ah)->ah_currentRDext = AR9285_RDEXT_DEFAULT; /* * ah_miscMode is populated by ar5416FillCapabilityInfo() @@ -259,9 +326,16 @@ ar9285Attach(uint16_t devid, HAL_SOFTC sc, * placed into hardware. */ if (ahp->ah_miscMode != 0) - OS_REG_WRITE(ah, AR_MISC_MODE, ahp->ah_miscMode); + OS_REG_WRITE(ah, AR_MISC_MODE, OS_REG_READ(ah, AR_MISC_MODE) | ahp->ah_miscMode); ar9285AniSetup(ah); /* Anti Noise Immunity */ + + /* Setup noise floor min/max/nominal values */ + AH5416(ah)->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9285_2GHZ; + AH5416(ah)->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_9285_2GHZ; + AH5416(ah)->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9285_2GHZ; + /* XXX no 5ghz values? */ + ar5416InitNfHistBuff(AH5416(ah)->ah_cal.nfCalHist); HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__); @@ -313,7 +387,6 @@ ar9285WriteIni(struct ath_hal *ah, const struct ieee80211_channel *chan) } regWrites = ath_hal_ini_write(ah, &AH5212(ah)->ah_ini_common, 1, regWrites); - } /* @@ -334,62 +407,45 @@ ar9285FillCapabilityInfo(struct ath_hal *ah) #if 0 pCap->halWowMatchPatternDword = AH_TRUE; #endif + /* AR9285 has 2 antennas but is a 1x1 stream device */ + pCap->halTxStreams = 1; + pCap->halRxStreams = 1; + pCap->halCSTSupport = AH_TRUE; pCap->halRifsRxSupport = AH_TRUE; pCap->halRifsTxSupport = AH_TRUE; pCap->halRtsAggrLimit = 64*1024; /* 802.11n max */ pCap->halExtChanDfsSupport = AH_TRUE; + pCap->halUseCombinedRadarRssi = AH_TRUE; #if 0 /* XXX bluetooth */ pCap->halBtCoexSupport = AH_TRUE; #endif pCap->halAutoSleepSupport = AH_FALSE; /* XXX? */ -#if 0 pCap->hal4kbSplitTransSupport = AH_FALSE; -#endif + /* Disable this so Block-ACK works correctly */ + pCap->halHasRxSelfLinkedTail = AH_FALSE; + pCap->halMbssidAggrSupport = AH_TRUE; + pCap->hal4AddrAggrSupport = AH_TRUE; + + if (AR_SREV_KITE_12_OR_LATER(ah)) + pCap->halPSPollBroken = AH_FALSE; + + /* Only RX STBC supported */ pCap->halRxStbcSupport = 1; - pCap->halTxStbcSupport = 1; + pCap->halTxStbcSupport = 0; return AH_TRUE; } -HAL_BOOL -ar9285SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING settings) -{ -#define ANTENNA0_CHAINMASK 0x1 -#define ANTENNA1_CHAINMASK 0x2 - struct ath_hal_5416 *ahp = AH5416(ah); - - /* Antenna selection is done by setting the tx/rx chainmasks approp. */ - switch (settings) { - case HAL_ANT_FIXED_A: - /* Enable first antenna only */ - ahp->ah_tx_chainmask = ANTENNA0_CHAINMASK; - ahp->ah_rx_chainmask = ANTENNA0_CHAINMASK; - break; - case HAL_ANT_FIXED_B: - /* Enable second antenna only, after checking capability */ - if (AH_PRIVATE(ah)->ah_caps.halTxChainMask > ANTENNA1_CHAINMASK) - ahp->ah_tx_chainmask = ANTENNA1_CHAINMASK; - ahp->ah_rx_chainmask = ANTENNA1_CHAINMASK; - break; - case HAL_ANT_VARIABLE: - /* Restore original chainmask settings */ - /* XXX */ - ahp->ah_tx_chainmask = AR5416_DEFAULT_TXCHAINMASK; - ahp->ah_rx_chainmask = AR5416_DEFAULT_RXCHAINMASK; - break; - } - return AH_TRUE; -#undef ANTENNA0_CHAINMASK -#undef ANTENNA1_CHAINMASK -} - static const char* ar9285Probe(uint16_t vendorid, uint16_t devid) { if (vendorid == ATHEROS_VENDOR_ID && devid == AR9285_DEVID_PCIE) return "Atheros 9285"; + if (vendorid == ATHEROS_VENDOR_ID && (devid == AR2427_DEVID_PCIE)) + return "Atheros 2427"; + return AH_NULL; } AH_CHIP(AR9285, ar9285Probe, ar9285Attach); diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9285_cal.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9285_cal.c new file mode 100644 index 0000000000..a743e21ef1 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9285_cal.c @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2008-2010 Atheros Communications Inc. + * Copyright (c) 2011 Adrian Chadd, Xenion Pty Ltd. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" +#include "ah.h" +#include "ah_internal.h" + +#include "ah_eeprom_v4k.h" + +#include "ar9002/ar9285.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" +#include "ar9002/ar9002phy.h" +#include "ar9002/ar9285phy.h" +#include "ar9002/ar9285an.h" + +#include "ar9002/ar9285_cal.h" + +#define AR9285_CLCAL_REDO_THRESH 1 +#define MAX_PACAL_SKIPCOUNT 8 + +#define N(a) (sizeof (a) / sizeof (a[0])) + +static void +ar9285_hw_pa_cal(struct ath_hal *ah, HAL_BOOL is_reset) +{ + uint32_t regVal; + int i, offset, offs_6_1, offs_0; + uint32_t ccomp_org, reg_field; + uint32_t regList[][2] = { + { 0x786c, 0 }, + { 0x7854, 0 }, + { 0x7820, 0 }, + { 0x7824, 0 }, + { 0x7868, 0 }, + { 0x783c, 0 }, + { 0x7838, 0 }, + }; + + /* PA CAL is not needed for high power solution */ + if (ath_hal_eepromGet(ah, AR_EEP_TXGAIN_TYPE, AH_NULL) == + AR5416_EEP_TXGAIN_HIGH_POWER) + return; + + HALDEBUG(ah, HAL_DEBUG_PERCAL, "Running PA Calibration\n"); + + for (i = 0; i < N(regList); i++) + regList[i][1] = OS_REG_READ(ah, regList[i][0]); + + regVal = OS_REG_READ(ah, 0x7834); + regVal &= (~(0x1)); + OS_REG_WRITE(ah, 0x7834, regVal); + regVal = OS_REG_READ(ah, 0x9808); + regVal |= (0x1 << 27); + OS_REG_WRITE(ah, 0x9808, regVal); + + OS_REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1); + OS_REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1); + OS_REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1); + OS_REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1); + OS_REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0); + OS_REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0); + OS_REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0); + OS_REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 0); + OS_REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2, 0); + OS_REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0); + OS_REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7); + OS_REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0); + ccomp_org = MS(OS_REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_CCOMP); + OS_REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, 0xf); + + OS_REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0); + OS_DELAY(30); + OS_REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, 0); + OS_REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 0); + + for (i = 6; i > 0; i--) { + regVal = OS_REG_READ(ah, 0x7834); + regVal |= (1 << (19 + i)); + OS_REG_WRITE(ah, 0x7834, regVal); + OS_DELAY(1); + regVal = OS_REG_READ(ah, 0x7834); + regVal &= (~(0x1 << (19 + i))); + reg_field = MS(OS_REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9); + regVal |= (reg_field << (19 + i)); + OS_REG_WRITE(ah, 0x7834, regVal); + } + + OS_REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 1); + OS_DELAY(1); + reg_field = MS(OS_REG_READ(ah, AR9285_AN_RF2G9), AR9285_AN_RXTXBB1_SPARE9); + OS_REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, reg_field); + offs_6_1 = MS(OS_REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_OFFS); + offs_0 = MS(OS_REG_READ(ah, AR9285_AN_RF2G3), AR9285_AN_RF2G3_PDVCCOMP); + + offset = (offs_6_1<<1) | offs_0; + offset = offset - 0; + offs_6_1 = offset>>1; + offs_0 = offset & 1; + + if ((!is_reset) && (AH9285(ah)->pacal_info.prev_offset == offset)) { + if (AH9285(ah)->pacal_info.max_skipcount < MAX_PACAL_SKIPCOUNT) + AH9285(ah)->pacal_info.max_skipcount = + 2 * AH9285(ah)->pacal_info.max_skipcount; + AH9285(ah)->pacal_info.skipcount = AH9285(ah)->pacal_info.max_skipcount; + } else { + AH9285(ah)->pacal_info.max_skipcount = 1; + AH9285(ah)->pacal_info.skipcount = 0; + AH9285(ah)->pacal_info.prev_offset = offset; + } + + OS_REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, offs_6_1); + OS_REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, offs_0); + + regVal = OS_REG_READ(ah, 0x7834); + regVal |= 0x1; + OS_REG_WRITE(ah, 0x7834, regVal); + regVal = OS_REG_READ(ah, 0x9808); + regVal &= (~(0x1 << 27)); + OS_REG_WRITE(ah, 0x9808, regVal); + + for (i = 0; i < N(regList); i++) + OS_REG_WRITE(ah, regList[i][0], regList[i][1]); + + OS_REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, ccomp_org); +} + +void +ar9002_hw_pa_cal(struct ath_hal *ah, HAL_BOOL is_reset) +{ + if (AR_SREV_KITE_11_OR_LATER(ah)) { + if (is_reset || !AH9285(ah)->pacal_info.skipcount) + ar9285_hw_pa_cal(ah, is_reset); + else + AH9285(ah)->pacal_info.skipcount--; + } +} + +/* Carrier leakage Calibration fix */ +static HAL_BOOL +ar9285_hw_cl_cal(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + OS_REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); + if (IEEE80211_IS_CHAN_HT20(chan)) { + OS_REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE); + OS_REG_SET_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN); + OS_REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, + AR_PHY_AGC_CONTROL_FLTR_CAL); + OS_REG_CLR_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE); + OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL); + if (!ath_hal_wait(ah, AR_PHY_AGC_CONTROL, + AR_PHY_AGC_CONTROL_CAL, 0)) { + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "offset calibration failed to complete in 1ms; noisy environment?\n"); + return AH_FALSE; + } + OS_REG_CLR_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN); + OS_REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE); + OS_REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); + } + OS_REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); + OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); + OS_REG_SET_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE); + OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL); + if (!ath_hal_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, + 0)) { + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "offset calibration failed to complete in 1ms; noisy environment?\n"); + return AH_FALSE; + } + + OS_REG_SET_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); + OS_REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); + OS_REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); + + return AH_TRUE; +} + +static HAL_BOOL +ar9285_hw_clc(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + int i; + uint32_t txgain_max; + uint32_t clc_gain, gain_mask = 0, clc_num = 0; + uint32_t reg_clc_I0, reg_clc_Q0; + uint32_t i0_num = 0; + uint32_t q0_num = 0; + uint32_t total_num = 0; + uint32_t reg_rf2g5_org; + HAL_BOOL retv = AH_TRUE; + + if (!(ar9285_hw_cl_cal(ah, chan))) + return AH_FALSE; + + txgain_max = MS(OS_REG_READ(ah, AR_PHY_TX_PWRCTRL7), + AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX); + + for (i = 0; i < (txgain_max+1); i++) { + clc_gain = (OS_REG_READ(ah, (AR_PHY_TX_GAIN_TBL1+(i<<2))) & + AR_PHY_TX_GAIN_CLC) >> AR_PHY_TX_GAIN_CLC_S; + if (!(gain_mask & (1 << clc_gain))) { + gain_mask |= (1 << clc_gain); + clc_num++; + } + } + + for (i = 0; i < clc_num; i++) { + reg_clc_I0 = (OS_REG_READ(ah, (AR_PHY_CLC_TBL1 + (i << 2))) + & AR_PHY_CLC_I0) >> AR_PHY_CLC_I0_S; + reg_clc_Q0 = (OS_REG_READ(ah, (AR_PHY_CLC_TBL1 + (i << 2))) + & AR_PHY_CLC_Q0) >> AR_PHY_CLC_Q0_S; + if (reg_clc_I0 == 0) + i0_num++; + + if (reg_clc_Q0 == 0) + q0_num++; + } + total_num = i0_num + q0_num; + if (total_num > AR9285_CLCAL_REDO_THRESH) { + reg_rf2g5_org = OS_REG_READ(ah, AR9285_RF2G5); + if (AR_SREV_9285E_20(ah)) { + OS_REG_WRITE(ah, AR9285_RF2G5, + (reg_rf2g5_org & AR9285_RF2G5_IC50TX) | + AR9285_RF2G5_IC50TX_XE_SET); + } else { + OS_REG_WRITE(ah, AR9285_RF2G5, + (reg_rf2g5_org & AR9285_RF2G5_IC50TX) | + AR9285_RF2G5_IC50TX_SET); + } + retv = ar9285_hw_cl_cal(ah, chan); + OS_REG_WRITE(ah, AR9285_RF2G5, reg_rf2g5_org); + } + return retv; +} + +HAL_BOOL +ar9285InitCalHardware(struct ath_hal *ah, + const struct ieee80211_channel *chan) +{ + if (AR_SREV_KITE(ah) && AR_SREV_KITE_10_OR_LATER(ah) && + (! ar9285_hw_clc(ah, chan))) + return AH_FALSE; + + return AH_TRUE; +} diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9285_cal.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9285_cal.h new file mode 100644 index 0000000000..c6ecc4190d --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9285_cal.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2008-2010 Atheros Communications Inc. + * Copyright (c) 2011 Adrian Chadd, Xenion Pty Ltd. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ +#ifndef __AR9285_CAL_H__ +#define __AR9285_CAL_H__ + +extern void ar9002_hw_pa_cal(struct ath_hal *ah, HAL_BOOL is_reset); +extern HAL_BOOL ar9285InitCalHardware(struct ath_hal *ah, const struct ieee80211_channel *chan); + +#endif diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9285_diversity.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9285_diversity.c new file mode 100644 index 0000000000..84c7682aa3 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9285_diversity.c @@ -0,0 +1,751 @@ +/* + * Copyright (c) 2008-2010 Atheros Communications Inc. + * Copyright (c) 2011 Adrian Chadd, Xenion Pty Ltd. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_desc.h" +#include "ah_internal.h" +#include "ah_eeprom_v4k.h" + +#include "ar9002/ar9280.h" +#include "ar9002/ar9285_diversity.h" +#include "ar9002/ar9285.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" +#include "ar9002/ar9285phy.h" +#include "ar9002/ar9285_phy.h" + + +/* Linux compability macros */ +/* + * XXX these don't handle rounding, underflow, overflow, wrapping! + */ +#define msecs_to_jiffies(a) ( (a) * hz / 1000 ) +#define time_after(a, b) ( (long) (b) - (long) (a) < 0 ) + +static HAL_BOOL +ath_is_alt_ant_ratio_better(int alt_ratio, int maxdelta, int mindelta, + int main_rssi_avg, int alt_rssi_avg, int pkt_count) +{ + return (((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) && + (alt_rssi_avg > main_rssi_avg + maxdelta)) || + (alt_rssi_avg > main_rssi_avg + mindelta)) && (pkt_count > 50); +} + +static void +ath_lnaconf_alt_good_scan(struct ar9285_ant_comb *antcomb, + struct ar9285_antcomb_conf ant_conf, int main_rssi_avg) +{ + antcomb->quick_scan_cnt = 0; + + if (ant_conf.main_lna_conf == ATH_ANT_DIV_COMB_LNA2) + antcomb->rssi_lna2 = main_rssi_avg; + else if (ant_conf.main_lna_conf == ATH_ANT_DIV_COMB_LNA1) + antcomb->rssi_lna1 = main_rssi_avg; + + switch ((ant_conf.main_lna_conf << 4) | ant_conf.alt_lna_conf) { + case (0x10): /* LNA2 A-B */ + antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; + antcomb->first_quick_scan_conf = + ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; + antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA1; + break; + case (0x20): /* LNA1 A-B */ + antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; + antcomb->first_quick_scan_conf = + ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; + antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA2; + break; + case (0x21): /* LNA1 LNA2 */ + antcomb->main_conf = ATH_ANT_DIV_COMB_LNA2; + antcomb->first_quick_scan_conf = + ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; + antcomb->second_quick_scan_conf = + ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; + break; + case (0x12): /* LNA2 LNA1 */ + antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1; + antcomb->first_quick_scan_conf = + ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; + antcomb->second_quick_scan_conf = + ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; + break; + case (0x13): /* LNA2 A+B */ + antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; + antcomb->first_quick_scan_conf = + ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; + antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA1; + break; + case (0x23): /* LNA1 A+B */ + antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; + antcomb->first_quick_scan_conf = + ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; + antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA2; + break; + default: + break; + } +} + +static void +ath_select_ant_div_from_quick_scan(struct ar9285_ant_comb *antcomb, + struct ar9285_antcomb_conf *div_ant_conf, int main_rssi_avg, + int alt_rssi_avg, int alt_ratio) +{ + /* alt_good */ + switch (antcomb->quick_scan_cnt) { + case 0: + /* set alt to main, and alt to first conf */ + div_ant_conf->main_lna_conf = antcomb->main_conf; + div_ant_conf->alt_lna_conf = antcomb->first_quick_scan_conf; + break; + case 1: + /* set alt to main, and alt to first conf */ + div_ant_conf->main_lna_conf = antcomb->main_conf; + div_ant_conf->alt_lna_conf = antcomb->second_quick_scan_conf; + antcomb->rssi_first = main_rssi_avg; + antcomb->rssi_second = alt_rssi_avg; + + if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) { + /* main is LNA1 */ + if (ath_is_alt_ant_ratio_better(alt_ratio, + ATH_ANT_DIV_COMB_LNA1_DELTA_HI, + ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, + main_rssi_avg, alt_rssi_avg, + antcomb->total_pkt_count)) + antcomb->first_ratio = AH_TRUE; + else + antcomb->first_ratio = AH_FALSE; + } else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2) { + if (ath_is_alt_ant_ratio_better(alt_ratio, + ATH_ANT_DIV_COMB_LNA1_DELTA_MID, + ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, + main_rssi_avg, alt_rssi_avg, + antcomb->total_pkt_count)) + antcomb->first_ratio = AH_TRUE; + else + antcomb->first_ratio = AH_FALSE; + } else { + if ((((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) && + (alt_rssi_avg > main_rssi_avg + + ATH_ANT_DIV_COMB_LNA1_DELTA_HI)) || + (alt_rssi_avg > main_rssi_avg)) && + (antcomb->total_pkt_count > 50)) + antcomb->first_ratio = AH_TRUE; + else + antcomb->first_ratio = AH_FALSE; + } + break; + case 2: + antcomb->alt_good = AH_FALSE; + antcomb->scan_not_start = AH_FALSE; + antcomb->scan = AH_FALSE; + antcomb->rssi_first = main_rssi_avg; + antcomb->rssi_third = alt_rssi_avg; + + if (antcomb->second_quick_scan_conf == ATH_ANT_DIV_COMB_LNA1) + antcomb->rssi_lna1 = alt_rssi_avg; + else if (antcomb->second_quick_scan_conf == + ATH_ANT_DIV_COMB_LNA2) + antcomb->rssi_lna2 = alt_rssi_avg; + else if (antcomb->second_quick_scan_conf == + ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2) { + if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2) + antcomb->rssi_lna2 = main_rssi_avg; + else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) + antcomb->rssi_lna1 = main_rssi_avg; + } + + if (antcomb->rssi_lna2 > antcomb->rssi_lna1 + + ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA) + div_ant_conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA2; + else + div_ant_conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA1; + + if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) { + if (ath_is_alt_ant_ratio_better(alt_ratio, + ATH_ANT_DIV_COMB_LNA1_DELTA_HI, + ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, + main_rssi_avg, alt_rssi_avg, + antcomb->total_pkt_count)) + antcomb->second_ratio = AH_TRUE; + else + antcomb->second_ratio = AH_FALSE; + } else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2) { + if (ath_is_alt_ant_ratio_better(alt_ratio, + ATH_ANT_DIV_COMB_LNA1_DELTA_MID, + ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, + main_rssi_avg, alt_rssi_avg, + antcomb->total_pkt_count)) + antcomb->second_ratio = AH_TRUE; + else + antcomb->second_ratio = AH_FALSE; + } else { + if ((((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) && + (alt_rssi_avg > main_rssi_avg + + ATH_ANT_DIV_COMB_LNA1_DELTA_HI)) || + (alt_rssi_avg > main_rssi_avg)) && + (antcomb->total_pkt_count > 50)) + antcomb->second_ratio = AH_TRUE; + else + antcomb->second_ratio = AH_FALSE; + } + + /* set alt to the conf with maximun ratio */ + if (antcomb->first_ratio && antcomb->second_ratio) { + if (antcomb->rssi_second > antcomb->rssi_third) { + /* first alt*/ + if ((antcomb->first_quick_scan_conf == + ATH_ANT_DIV_COMB_LNA1) || + (antcomb->first_quick_scan_conf == + ATH_ANT_DIV_COMB_LNA2)) + /* Set alt LNA1 or LNA2*/ + if (div_ant_conf->main_lna_conf == + ATH_ANT_DIV_COMB_LNA2) + div_ant_conf->alt_lna_conf = + ATH_ANT_DIV_COMB_LNA1; + else + div_ant_conf->alt_lna_conf = + ATH_ANT_DIV_COMB_LNA2; + else + /* Set alt to A+B or A-B */ + div_ant_conf->alt_lna_conf = + antcomb->first_quick_scan_conf; + } else if ((antcomb->second_quick_scan_conf == + ATH_ANT_DIV_COMB_LNA1) || + (antcomb->second_quick_scan_conf == + ATH_ANT_DIV_COMB_LNA2)) { + /* Set alt LNA1 or LNA2 */ + if (div_ant_conf->main_lna_conf == + ATH_ANT_DIV_COMB_LNA2) + div_ant_conf->alt_lna_conf = + ATH_ANT_DIV_COMB_LNA1; + else + div_ant_conf->alt_lna_conf = + ATH_ANT_DIV_COMB_LNA2; + } else { + /* Set alt to A+B or A-B */ + div_ant_conf->alt_lna_conf = + antcomb->second_quick_scan_conf; + } + } else if (antcomb->first_ratio) { + /* first alt */ + if ((antcomb->first_quick_scan_conf == + ATH_ANT_DIV_COMB_LNA1) || + (antcomb->first_quick_scan_conf == + ATH_ANT_DIV_COMB_LNA2)) + /* Set alt LNA1 or LNA2 */ + if (div_ant_conf->main_lna_conf == + ATH_ANT_DIV_COMB_LNA2) + div_ant_conf->alt_lna_conf = + ATH_ANT_DIV_COMB_LNA1; + else + div_ant_conf->alt_lna_conf = + ATH_ANT_DIV_COMB_LNA2; + else + /* Set alt to A+B or A-B */ + div_ant_conf->alt_lna_conf = + antcomb->first_quick_scan_conf; + } else if (antcomb->second_ratio) { + /* second alt */ + if ((antcomb->second_quick_scan_conf == + ATH_ANT_DIV_COMB_LNA1) || + (antcomb->second_quick_scan_conf == + ATH_ANT_DIV_COMB_LNA2)) + /* Set alt LNA1 or LNA2 */ + if (div_ant_conf->main_lna_conf == + ATH_ANT_DIV_COMB_LNA2) + div_ant_conf->alt_lna_conf = + ATH_ANT_DIV_COMB_LNA1; + else + div_ant_conf->alt_lna_conf = + ATH_ANT_DIV_COMB_LNA2; + else + /* Set alt to A+B or A-B */ + div_ant_conf->alt_lna_conf = + antcomb->second_quick_scan_conf; + } else { + /* main is largest */ + if ((antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) || + (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2)) + /* Set alt LNA1 or LNA2 */ + if (div_ant_conf->main_lna_conf == + ATH_ANT_DIV_COMB_LNA2) + div_ant_conf->alt_lna_conf = + ATH_ANT_DIV_COMB_LNA1; + else + div_ant_conf->alt_lna_conf = + ATH_ANT_DIV_COMB_LNA2; + else + /* Set alt to A+B or A-B */ + div_ant_conf->alt_lna_conf = antcomb->main_conf; + } + break; + default: + break; + } +} + +static void +ath_ant_div_conf_fast_divbias(struct ar9285_antcomb_conf *ant_conf) +{ + /* Adjust the fast_div_bias based on main and alt lna conf */ + switch ((ant_conf->main_lna_conf << 4) | ant_conf->alt_lna_conf) { + case (0x01): /* A-B LNA2 */ + ant_conf->fast_div_bias = 0x3b; + break; + case (0x02): /* A-B LNA1 */ + ant_conf->fast_div_bias = 0x3d; + break; + case (0x03): /* A-B A+B */ + ant_conf->fast_div_bias = 0x1; + break; + case (0x10): /* LNA2 A-B */ + ant_conf->fast_div_bias = 0x7; + break; + case (0x12): /* LNA2 LNA1 */ + ant_conf->fast_div_bias = 0x2; + break; + case (0x13): /* LNA2 A+B */ + ant_conf->fast_div_bias = 0x7; + break; + case (0x20): /* LNA1 A-B */ + ant_conf->fast_div_bias = 0x6; + break; + case (0x21): /* LNA1 LNA2 */ + ant_conf->fast_div_bias = 0x0; + break; + case (0x23): /* LNA1 A+B */ + ant_conf->fast_div_bias = 0x6; + break; + case (0x30): /* A+B A-B */ + ant_conf->fast_div_bias = 0x1; + break; + case (0x31): /* A+B LNA2 */ + ant_conf->fast_div_bias = 0x3b; + break; + case (0x32): /* A+B LNA1 */ + ant_conf->fast_div_bias = 0x3d; + break; + default: + break; + } +} + +/* Antenna diversity and combining */ +void +ar9285_ant_comb_scan(struct ath_hal *ah, struct ath_rx_status *rs, + unsigned long ticks, int hz) +{ + struct ar9285_antcomb_conf div_ant_conf; + struct ar9285_ant_comb *antcomb = &AH9285(ah)->ant_comb; + int alt_ratio = 0, alt_rssi_avg = 0, main_rssi_avg = 0, curr_alt_set; + int curr_main_set, curr_bias; + int main_rssi = rs->rs_rssi_ctl[0]; + int alt_rssi = rs->rs_rssi_ctl[1]; + int rx_ant_conf, main_ant_conf, alt_ant_conf; + HAL_BOOL short_scan = AH_FALSE; + + rx_ant_conf = (rs->rs_rssi_ctl[2] >> 4) & ATH_ANT_RX_MASK; + main_ant_conf = (rs->rs_rssi_ctl[2] >> 2) & ATH_ANT_RX_MASK; + alt_ant_conf = (rs->rs_rssi_ctl[2] >> 0) & ATH_ANT_RX_MASK; + +#if 0 + HALDEBUG(ah, HAL_DEBUG_DIVERSITY, "%s: RSSI %d/%d, conf %x/%x, rxconf %x, LNA: %d; ANT: %d; FastDiv: %d\n", + __func__, main_rssi, alt_rssi, main_ant_conf,alt_ant_conf, rx_ant_conf, + !!(rs->rs_rssi_ctl[2] & 0x80), !!(rs->rs_rssi_ctl[2] & 0x40), !!(rs->rs_rssi_ext[2] & 0x40)); +#endif + + if (! ar9285_check_div_comb(ah)) + return; + + if (AH5212(ah)->ah_diversity == AH_FALSE) + return; + +#if 0 + HALDEBUG(ah, HAL_DEBUG_DIVERSITY, "%s: main: %d, alt: %d, rx_ant_conf: %x, main_ant_conf: %x\n", + __func__, main_rssi, alt_rssi, rx_ant_conf, main_ant_conf); +#endif + + /* Record packet only when alt_rssi is positive */ + if (main_rssi > 0 && alt_rssi > 0) { + antcomb->total_pkt_count++; + antcomb->main_total_rssi += main_rssi; + antcomb->alt_total_rssi += alt_rssi; + if (main_ant_conf == rx_ant_conf) + antcomb->main_recv_cnt++; + else + antcomb->alt_recv_cnt++; + } + + /* Short scan check */ + if (antcomb->scan && antcomb->alt_good) { + if (time_after(ticks, antcomb->scan_start_time + + msecs_to_jiffies(ATH_ANT_DIV_COMB_SHORT_SCAN_INTR))) + short_scan = AH_TRUE; + else + if (antcomb->total_pkt_count == + ATH_ANT_DIV_COMB_SHORT_SCAN_PKTCOUNT) { + alt_ratio = ((antcomb->alt_recv_cnt * 100) / + antcomb->total_pkt_count); + if (alt_ratio < ATH_ANT_DIV_COMB_ALT_ANT_RATIO) + short_scan = AH_TRUE; + } + } + + if (((antcomb->total_pkt_count < ATH_ANT_DIV_COMB_MAX_PKTCOUNT) || + rs->rs_moreaggr) && !short_scan) + return; + + if (antcomb->total_pkt_count) { + alt_ratio = ((antcomb->alt_recv_cnt * 100) / + antcomb->total_pkt_count); + main_rssi_avg = (antcomb->main_total_rssi / + antcomb->total_pkt_count); + alt_rssi_avg = (antcomb->alt_total_rssi / + antcomb->total_pkt_count); + } + + ar9285_antdiv_comb_conf_get(ah, &div_ant_conf); + curr_alt_set = div_ant_conf.alt_lna_conf; + curr_main_set = div_ant_conf.main_lna_conf; + curr_bias = div_ant_conf.fast_div_bias; + + antcomb->count++; + + if (antcomb->count == ATH_ANT_DIV_COMB_MAX_COUNT) { + if (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO) { + ath_lnaconf_alt_good_scan(antcomb, div_ant_conf, + main_rssi_avg); + antcomb->alt_good = AH_TRUE; + } else { + antcomb->alt_good = AH_FALSE; + } + + antcomb->count = 0; + antcomb->scan = AH_TRUE; + antcomb->scan_not_start = AH_TRUE; + } + + if (!antcomb->scan) { + if (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO) { + if (curr_alt_set == ATH_ANT_DIV_COMB_LNA2) { + /* Switch main and alt LNA */ + div_ant_conf.main_lna_conf = + ATH_ANT_DIV_COMB_LNA2; + div_ant_conf.alt_lna_conf = + ATH_ANT_DIV_COMB_LNA1; + } else if (curr_alt_set == ATH_ANT_DIV_COMB_LNA1) { + div_ant_conf.main_lna_conf = + ATH_ANT_DIV_COMB_LNA1; + div_ant_conf.alt_lna_conf = + ATH_ANT_DIV_COMB_LNA2; + } + + goto div_comb_done; + } else if ((curr_alt_set != ATH_ANT_DIV_COMB_LNA1) && + (curr_alt_set != ATH_ANT_DIV_COMB_LNA2)) { + /* Set alt to another LNA */ + if (curr_main_set == ATH_ANT_DIV_COMB_LNA2) + div_ant_conf.alt_lna_conf = + ATH_ANT_DIV_COMB_LNA1; + else if (curr_main_set == ATH_ANT_DIV_COMB_LNA1) + div_ant_conf.alt_lna_conf = + ATH_ANT_DIV_COMB_LNA2; + + goto div_comb_done; + } + + if ((alt_rssi_avg < (main_rssi_avg + + ATH_ANT_DIV_COMB_LNA1_LNA2_DELTA))) + goto div_comb_done; + } + + if (!antcomb->scan_not_start) { + switch (curr_alt_set) { + case ATH_ANT_DIV_COMB_LNA2: + antcomb->rssi_lna2 = alt_rssi_avg; + antcomb->rssi_lna1 = main_rssi_avg; + antcomb->scan = AH_TRUE; + /* set to A+B */ + div_ant_conf.main_lna_conf = + ATH_ANT_DIV_COMB_LNA1; + div_ant_conf.alt_lna_conf = + ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; + break; + case ATH_ANT_DIV_COMB_LNA1: + antcomb->rssi_lna1 = alt_rssi_avg; + antcomb->rssi_lna2 = main_rssi_avg; + antcomb->scan = AH_TRUE; + /* set to A+B */ + div_ant_conf.main_lna_conf = ATH_ANT_DIV_COMB_LNA2; + div_ant_conf.alt_lna_conf = + ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; + break; + case ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2: + antcomb->rssi_add = alt_rssi_avg; + antcomb->scan = AH_TRUE; + /* set to A-B */ + div_ant_conf.alt_lna_conf = + ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; + break; + case ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2: + antcomb->rssi_sub = alt_rssi_avg; + antcomb->scan = AH_FALSE; + if (antcomb->rssi_lna2 > + (antcomb->rssi_lna1 + + ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA)) { + /* use LNA2 as main LNA */ + if ((antcomb->rssi_add > antcomb->rssi_lna1) && + (antcomb->rssi_add > antcomb->rssi_sub)) { + /* set to A+B */ + div_ant_conf.main_lna_conf = + ATH_ANT_DIV_COMB_LNA2; + div_ant_conf.alt_lna_conf = + ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; + } else if (antcomb->rssi_sub > + antcomb->rssi_lna1) { + /* set to A-B */ + div_ant_conf.main_lna_conf = + ATH_ANT_DIV_COMB_LNA2; + div_ant_conf.alt_lna_conf = + ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; + } else { + /* set to LNA1 */ + div_ant_conf.main_lna_conf = + ATH_ANT_DIV_COMB_LNA2; + div_ant_conf.alt_lna_conf = + ATH_ANT_DIV_COMB_LNA1; + } + } else { + /* use LNA1 as main LNA */ + if ((antcomb->rssi_add > antcomb->rssi_lna2) && + (antcomb->rssi_add > antcomb->rssi_sub)) { + /* set to A+B */ + div_ant_conf.main_lna_conf = + ATH_ANT_DIV_COMB_LNA1; + div_ant_conf.alt_lna_conf = + ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; + } else if (antcomb->rssi_sub > + antcomb->rssi_lna1) { + /* set to A-B */ + div_ant_conf.main_lna_conf = + ATH_ANT_DIV_COMB_LNA1; + div_ant_conf.alt_lna_conf = + ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; + } else { + /* set to LNA2 */ + div_ant_conf.main_lna_conf = + ATH_ANT_DIV_COMB_LNA1; + div_ant_conf.alt_lna_conf = + ATH_ANT_DIV_COMB_LNA2; + } + } + break; + default: + break; + } + } else { + if (!antcomb->alt_good) { + antcomb->scan_not_start = AH_FALSE; + /* Set alt to another LNA */ + if (curr_main_set == ATH_ANT_DIV_COMB_LNA2) { + div_ant_conf.main_lna_conf = + ATH_ANT_DIV_COMB_LNA2; + div_ant_conf.alt_lna_conf = + ATH_ANT_DIV_COMB_LNA1; + } else if (curr_main_set == ATH_ANT_DIV_COMB_LNA1) { + div_ant_conf.main_lna_conf = + ATH_ANT_DIV_COMB_LNA1; + div_ant_conf.alt_lna_conf = + ATH_ANT_DIV_COMB_LNA2; + } + goto div_comb_done; + } + } + + ath_select_ant_div_from_quick_scan(antcomb, &div_ant_conf, + main_rssi_avg, alt_rssi_avg, + alt_ratio); + + antcomb->quick_scan_cnt++; + +div_comb_done: + ath_ant_div_conf_fast_divbias(&div_ant_conf); + + ar9285_antdiv_comb_conf_set(ah, &div_ant_conf); + + HALDEBUG(ah, HAL_DEBUG_DIVERSITY, "%s: total_pkt_count=%d\n", + __func__, antcomb->total_pkt_count); + + HALDEBUG(ah, HAL_DEBUG_DIVERSITY, "%s: main_total_rssi=%d\n", + __func__, antcomb->main_total_rssi); + HALDEBUG(ah, HAL_DEBUG_DIVERSITY, "%s: alt_total_rssi=%d\n", + __func__, antcomb->alt_total_rssi); + + HALDEBUG(ah, HAL_DEBUG_DIVERSITY, "%s: main_rssi_avg=%d\n", + __func__, main_rssi_avg); + HALDEBUG(ah, HAL_DEBUG_DIVERSITY, "%s: alt_alt_rssi_avg=%d\n", + __func__, alt_rssi_avg); + + HALDEBUG(ah, HAL_DEBUG_DIVERSITY, "%s: main_recv_cnt=%d\n", + __func__, antcomb->main_recv_cnt); + HALDEBUG(ah, HAL_DEBUG_DIVERSITY, "%s: alt_recv_cnt=%d\n", + __func__, antcomb->alt_recv_cnt); + +// if (curr_alt_set != div_ant_conf.alt_lna_conf) + HALDEBUG(ah, HAL_DEBUG_DIVERSITY, "%s: lna_conf: %x -> %x\n", + __func__, curr_alt_set, div_ant_conf.alt_lna_conf); +// if (curr_main_set != div_ant_conf.main_lna_conf) + HALDEBUG(ah, HAL_DEBUG_DIVERSITY, "%s: main_lna_conf: %x -> %x\n", + __func__, curr_main_set, div_ant_conf.main_lna_conf); +// if (curr_bias != div_ant_conf.fast_div_bias) + HALDEBUG(ah, HAL_DEBUG_DIVERSITY, "%s: fast_div_bias: %x -> %x\n", + __func__, curr_bias, div_ant_conf.fast_div_bias); + + antcomb->scan_start_time = ticks; + antcomb->total_pkt_count = 0; + antcomb->main_total_rssi = 0; + antcomb->alt_total_rssi = 0; + antcomb->main_recv_cnt = 0; + antcomb->alt_recv_cnt = 0; +} + +/* + * Set the antenna switch to control RX antenna diversity. + * + * If a fixed configuration is used, the LNA and div bias + * settings are fixed and the antenna diversity scanning routine + * is disabled. + * + * If a variable configuration is used, a default is programmed + * in and sampling commences per RXed packet. + * + * Since this is called from ar9285SetBoardValues() to setup + * diversity, it means that after a reset or scan, any current + * software diversity combining settings will be lost and won't + * re-appear until after the first successful sample run. + * Please keep this in mind if you're seeing weird performance + * that happens to relate to scan/diversity timing. + */ +HAL_BOOL +ar9285SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING settings) +{ + int regVal; + const HAL_EEPROM_v4k *ee = AH_PRIVATE(ah)->ah_eeprom; + const MODAL_EEP4K_HEADER *pModal = &ee->ee_base.modalHeader; + uint8_t ant_div_control1, ant_div_control2; + + if (pModal->version < 3) { + HALDEBUG(ah, HAL_DEBUG_DIVERSITY, "%s: not supported\n", + __func__); + return AH_FALSE; /* Can't do diversity */ + } + + /* Store settings */ + AH5212(ah)->ah_antControl = settings; + AH5212(ah)->ah_diversity = (settings == HAL_ANT_VARIABLE); + + /* XXX don't fiddle if the PHY is in sleep mode or ! chan */ + + /* Begin setting the relevant registers */ + + ant_div_control1 = pModal->antdiv_ctl1; + ant_div_control2 = pModal->antdiv_ctl2; + + regVal = OS_REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL); + regVal &= (~(AR_PHY_9285_ANT_DIV_CTL_ALL)); + + /* enable antenna diversity only if diversityControl == HAL_ANT_VARIABLE */ + if (settings == HAL_ANT_VARIABLE) + regVal |= SM(ant_div_control1, AR_PHY_9285_ANT_DIV_CTL); + + if (settings == HAL_ANT_VARIABLE) { + HALDEBUG(ah, HAL_DEBUG_DIVERSITY, "%s: HAL_ANT_VARIABLE\n", + __func__); + regVal |= SM(ant_div_control2, AR_PHY_9285_ANT_DIV_ALT_LNACONF); + regVal |= SM((ant_div_control2 >> 2), AR_PHY_9285_ANT_DIV_MAIN_LNACONF); + regVal |= SM((ant_div_control1 >> 1), AR_PHY_9285_ANT_DIV_ALT_GAINTB); + regVal |= SM((ant_div_control1 >> 2), AR_PHY_9285_ANT_DIV_MAIN_GAINTB); + } else { + if (settings == HAL_ANT_FIXED_A) { + /* Diversity disabled, RX = LNA1 */ + HALDEBUG(ah, HAL_DEBUG_DIVERSITY, "%s: HAL_ANT_FIXED_A\n", + __func__); + regVal |= SM(ATH_ANT_DIV_COMB_LNA2, AR_PHY_9285_ANT_DIV_ALT_LNACONF); + regVal |= SM(ATH_ANT_DIV_COMB_LNA1, AR_PHY_9285_ANT_DIV_MAIN_LNACONF); + regVal |= SM(AR_PHY_9285_ANT_DIV_GAINTB_0, AR_PHY_9285_ANT_DIV_ALT_GAINTB); + regVal |= SM(AR_PHY_9285_ANT_DIV_GAINTB_1, AR_PHY_9285_ANT_DIV_MAIN_GAINTB); + } + else if (settings == HAL_ANT_FIXED_B) { + /* Diversity disabled, RX = LNA2 */ + HALDEBUG(ah, HAL_DEBUG_DIVERSITY, "%s: HAL_ANT_FIXED_B\n", + __func__); + regVal |= SM(ATH_ANT_DIV_COMB_LNA1, AR_PHY_9285_ANT_DIV_ALT_LNACONF); + regVal |= SM(ATH_ANT_DIV_COMB_LNA2, AR_PHY_9285_ANT_DIV_MAIN_LNACONF); + regVal |= SM(AR_PHY_9285_ANT_DIV_GAINTB_1, AR_PHY_9285_ANT_DIV_ALT_GAINTB); + regVal |= SM(AR_PHY_9285_ANT_DIV_GAINTB_0, AR_PHY_9285_ANT_DIV_MAIN_GAINTB); + } + } + + OS_REG_WRITE(ah, AR_PHY_MULTICHAIN_GAIN_CTL, regVal); + regVal = OS_REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL); + regVal = OS_REG_READ(ah, AR_PHY_CCK_DETECT); + regVal &= (~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV); + if (settings == HAL_ANT_VARIABLE) + regVal |= SM((ant_div_control1 >> 3), AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV); + + OS_REG_WRITE(ah, AR_PHY_CCK_DETECT, regVal); + regVal = OS_REG_READ(ah, AR_PHY_CCK_DETECT); + + /* + * If Diversity combining is available and the diversity setting + * is to allow variable diversity, enable it by default. + * + * This will be eventually overridden by the software antenna + * diversity logic. + * + * Note that yes, this following section overrides the above + * settings for the LNA configuration and fast-bias. + */ + if (ar9285_check_div_comb(ah) && AH5212(ah)->ah_diversity == AH_TRUE) { + // If support DivComb, set MAIN to LNA1 and ALT to LNA2 at the first beginning + HALDEBUG(ah, HAL_DEBUG_DIVERSITY, + "%s: Enable initial settings for combined diversity\n", + __func__); + regVal = OS_REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL); + regVal &= (~(AR_PHY_9285_ANT_DIV_MAIN_LNACONF | AR_PHY_9285_ANT_DIV_ALT_LNACONF)); + regVal |= (ATH_ANT_DIV_COMB_LNA1 << AR_PHY_9285_ANT_DIV_MAIN_LNACONF_S); + regVal |= (ATH_ANT_DIV_COMB_LNA2 << AR_PHY_9285_ANT_DIV_ALT_LNACONF_S); + regVal &= (~(AR_PHY_9285_FAST_DIV_BIAS)); + regVal |= (0 << AR_PHY_9285_FAST_DIV_BIAS_S); + OS_REG_WRITE(ah, AR_PHY_MULTICHAIN_GAIN_CTL, regVal); + } + + return AH_TRUE; +} diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9285_diversity.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9285_diversity.h new file mode 100644 index 0000000000..220db1e812 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9285_diversity.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2008-2010 Atheros Communications Inc. + * Copyright (c) 2011 Adrian Chadd, Xenion Pty Ltd. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ +#ifndef __AR9285_DIVERSITY_H__ +#define __AR9285_DIVERSITY_H__ + +/* Antenna diversity/combining */ +#define ATH_ANT_RX_CURRENT_SHIFT 4 +#define ATH_ANT_RX_MAIN_SHIFT 2 +#define ATH_ANT_RX_MASK 0x3 + +#define ATH_ANT_DIV_COMB_SHORT_SCAN_INTR 50 +#define ATH_ANT_DIV_COMB_SHORT_SCAN_PKTCOUNT 0x100 +#define ATH_ANT_DIV_COMB_MAX_PKTCOUNT 0x200 +#define ATH_ANT_DIV_COMB_INIT_COUNT 95 +#define ATH_ANT_DIV_COMB_MAX_COUNT 100 +#define ATH_ANT_DIV_COMB_ALT_ANT_RATIO 30 +#define ATH_ANT_DIV_COMB_ALT_ANT_RATIO2 20 + +#define ATH_ANT_DIV_COMB_LNA1_LNA2_DELTA -3 +#define ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA -1 +#define ATH_ANT_DIV_COMB_LNA1_DELTA_HI -4 +#define ATH_ANT_DIV_COMB_LNA1_DELTA_MID -2 +#define ATH_ANT_DIV_COMB_LNA1_DELTA_LOW 2 + +extern void ar9285_ant_comb_scan(struct ath_hal *ah, struct ath_rx_status *rs, + unsigned long ticks, int hz); + +#endif diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9285_phy.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9285_phy.c new file mode 100644 index 0000000000..e4e73d47f0 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9285_phy.c @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2008-2010 Atheros Communications Inc. + * Copyright (c) 2010-2011 Adrian Chadd, Xenion Pty Ltd. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" +#include "ah_eeprom_v4k.h" + +#include "ar9002/ar9280.h" +#include "ar9002/ar9285.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" +#include "ar9002/ar9285phy.h" +#include "ar9002/ar9285_phy.h" + +void +ar9285_antdiv_comb_conf_get(struct ath_hal *ah, + struct ar9285_antcomb_conf *antconf) +{ + uint32_t regval; + + regval = OS_REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL); + antconf->main_lna_conf = (regval & AR_PHY_9285_ANT_DIV_MAIN_LNACONF) >> + AR_PHY_9285_ANT_DIV_MAIN_LNACONF_S; + antconf->alt_lna_conf = (regval & AR_PHY_9285_ANT_DIV_ALT_LNACONF) >> + AR_PHY_9285_ANT_DIV_ALT_LNACONF_S; + antconf->fast_div_bias = (regval & AR_PHY_9285_FAST_DIV_BIAS) >> + AR_PHY_9285_FAST_DIV_BIAS_S; +} + +void +ar9285_antdiv_comb_conf_set(struct ath_hal *ah, + struct ar9285_antcomb_conf *antconf) +{ + uint32_t regval; + + regval = OS_REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL); + regval &= ~(AR_PHY_9285_ANT_DIV_MAIN_LNACONF | + AR_PHY_9285_ANT_DIV_ALT_LNACONF | + AR_PHY_9285_FAST_DIV_BIAS); + regval |= ((antconf->main_lna_conf << AR_PHY_9285_ANT_DIV_MAIN_LNACONF_S) + & AR_PHY_9285_ANT_DIV_MAIN_LNACONF); + regval |= ((antconf->alt_lna_conf << AR_PHY_9285_ANT_DIV_ALT_LNACONF_S) + & AR_PHY_9285_ANT_DIV_ALT_LNACONF); + regval |= ((antconf->fast_div_bias << AR_PHY_9285_FAST_DIV_BIAS_S) + & AR_PHY_9285_FAST_DIV_BIAS); + + OS_REG_WRITE(ah, AR_PHY_MULTICHAIN_GAIN_CTL, regval); +} + +/* + * Check whether combined + fast antenna diversity should be enabled. + * + * This enables software-driven RX antenna diversity based on RX + * RSSI + antenna config packet sampling. + */ +HAL_BOOL +ar9285_check_div_comb(struct ath_hal *ah) +{ + uint8_t ant_div_ctl1; + HAL_EEPROM_v4k *ee = AH_PRIVATE(ah)->ah_eeprom; + const MODAL_EEP4K_HEADER *pModal = &ee->ee_base.modalHeader; + + /* For now, simply disable this until it's better debugged. -adrian */ + return AH_FALSE; + + if (! AR_SREV_KITE(ah)) + return AH_FALSE; + + if (pModal->version < 3) + return AH_FALSE; + + ant_div_ctl1 = pModal->antdiv_ctl1; + if ((ant_div_ctl1 & 0x1) && ((ant_div_ctl1 >> 3) & 0x1)) + return AH_TRUE; + + return AH_FALSE; +} diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9285_phy.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9285_phy.h new file mode 100644 index 0000000000..b2367185f1 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9285_phy.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2008-2010 Atheros Communications Inc. + * Copyright (c) 2010-2011 Adrian Chadd, Xenion Pty Ltd. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ +#ifndef __AR9285_PHY_H__ +#define __AR9285_PHY_H__ + +/* + * Manipulate AR9285 antenna diversity configuration + */ +struct ar9285_antcomb_conf { + uint8_t main_lna_conf; + uint8_t alt_lna_conf; + uint8_t fast_div_bias; +}; + +extern void ar9285_antdiv_comb_conf_set(struct ath_hal *ah, + struct ar9285_antcomb_conf *antconf); +extern void ar9285_antdiv_comb_conf_get(struct ath_hal *ah, + struct ar9285_antcomb_conf *antconf); +extern HAL_BOOL ar9285_check_div_comb(struct ath_hal *ah); + +#endif diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar9285_reset.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9285_reset.c similarity index 52% rename from src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar9285_reset.c rename to src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9285_reset.c index 8c2de10c3c..1a0c77be26 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar9285_reset.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9285_reset.c @@ -31,10 +31,13 @@ #include "ah_eeprom_v14.h" #include "ah_eeprom_v4k.h" -#include "ar5416/ar9285.h" +#include "ar9002/ar9285.h" #include "ar5416/ar5416.h" #include "ar5416/ar5416reg.h" #include "ar5416/ar5416phy.h" +#include "ar9002/ar9002phy.h" +#include "ar9002/ar9285phy.h" +#include "ar9002/ar9285an.h" /* Eeprom versioning macros. Returns true if the version is equal or newer than the ver specified */ #define EEP_MINOR(_ah) \ @@ -57,33 +60,12 @@ static HAL_BOOL ar9285SetPowerCalTable(struct ath_hal *ah, struct ar5416eeprom_4k *pEepData, const struct ieee80211_channel *chan, int16_t *pTxPowerIndexOffset); -static int16_t interpolate(uint16_t target, uint16_t srcLeft, - uint16_t srcRight, int16_t targetLeft, int16_t targetRight); -static HAL_BOOL ar9285FillVpdTable(uint8_t, uint8_t, uint8_t *, uint8_t *, - uint16_t, uint8_t *); static void ar9285GetGainBoundariesAndPdadcs(struct ath_hal *ah, const struct ieee80211_channel *chan, CAL_DATA_PER_FREQ_4K *pRawDataSet, uint8_t * bChans, uint16_t availPiers, uint16_t tPdGainOverlap, int16_t *pMinCalPower, uint16_t * pPdGainBoundaries, uint8_t * pPDADCValues, uint16_t numXpdGains); -static HAL_BOOL getLowerUpperIndex(uint8_t target, uint8_t *pList, - uint16_t listSize, uint16_t *indexL, uint16_t *indexR); -static uint16_t ar9285GetMaxEdgePower(uint16_t, CAL_CTL_EDGES *); - -/* XXX gag, this is sick */ -typedef enum Ar5416_Rates { - rate6mb, rate9mb, rate12mb, rate18mb, - rate24mb, rate36mb, rate48mb, rate54mb, - rate1l, rate2l, rate2s, rate5_5l, - rate5_5s, rate11l, rate11s, rateXr, - rateHt20_0, rateHt20_1, rateHt20_2, rateHt20_3, - rateHt20_4, rateHt20_5, rateHt20_6, rateHt20_7, - rateHt40_0, rateHt40_1, rateHt40_2, rateHt40_3, - rateHt40_4, rateHt40_5, rateHt40_6, rateHt40_7, - rateDupCck, rateDupOfdm, rateExtCck, rateExtOfdm, - Ar5416RateSize -} AR5416_RATES; HAL_BOOL ar9285SetTransmitPower(struct ath_hal *ah, @@ -155,198 +137,245 @@ ar9285SetTransmitPower(struct ath_hal *ah, */ for (i = 0; i < N(ratesArray); i++) { ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]); + /* -5 dBm offset for Merlin and later; this includes Kite */ + ratesArray[i] -= AR5416_PWR_TABLE_OFFSET_DB * 2; if (ratesArray[i] > AR5416_MAX_RATE_POWER) ratesArray[i] = AR5416_MAX_RATE_POWER; - ratesArray[i] -= AR5416_PWR_TABLE_OFFSET_DB * 2; + if (ratesArray[i] < 0) + ratesArray[i] = 0; } #ifdef AH_EEPROM_DUMP ar5416PrintPowerPerRate(ah, ratesArray); #endif - /* Write the OFDM power per rate set */ - OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE1, - POW_SM(ratesArray[rate18mb], 24) - | POW_SM(ratesArray[rate12mb], 16) - | POW_SM(ratesArray[rate9mb], 8) - | POW_SM(ratesArray[rate6mb], 0) - ); - OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE2, - POW_SM(ratesArray[rate54mb], 24) - | POW_SM(ratesArray[rate48mb], 16) - | POW_SM(ratesArray[rate36mb], 8) - | POW_SM(ratesArray[rate24mb], 0) - ); - - /* Write the CCK power per rate set */ - OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE3, - POW_SM(ratesArray[rate2s], 24) - | POW_SM(ratesArray[rate2l], 16) - | POW_SM(ratesArray[rateXr], 8) /* XR target power */ - | POW_SM(ratesArray[rate1l], 0) - ); - OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE4, - POW_SM(ratesArray[rate11s], 24) - | POW_SM(ratesArray[rate11l], 16) - | POW_SM(ratesArray[rate5_5s], 8) - | POW_SM(ratesArray[rate5_5l], 0) - ); - HALDEBUG(ah, HAL_DEBUG_RESET, - "%s AR_PHY_POWER_TX_RATE3=0x%x AR_PHY_POWER_TX_RATE4=0x%x\n", - __func__, OS_REG_READ(ah,AR_PHY_POWER_TX_RATE3), - OS_REG_READ(ah,AR_PHY_POWER_TX_RATE4)); - - /* Write the HT20 power per rate set */ - OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE5, - POW_SM(ratesArray[rateHt20_3], 24) - | POW_SM(ratesArray[rateHt20_2], 16) - | POW_SM(ratesArray[rateHt20_1], 8) - | POW_SM(ratesArray[rateHt20_0], 0) - ); - OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE6, - POW_SM(ratesArray[rateHt20_7], 24) - | POW_SM(ratesArray[rateHt20_6], 16) - | POW_SM(ratesArray[rateHt20_5], 8) - | POW_SM(ratesArray[rateHt20_4], 0) - ); - + /* + * Adjust the HT40 power to meet the correct target TX power + * for 40MHz mode, based on TX power curves that are established + * for 20MHz mode. + * + * XXX handle overflow/too high power level? + */ if (IEEE80211_IS_CHAN_HT40(chan)) { - /* Write the HT40 power per rate set */ - /* Correct PAR difference between HT40 and HT20/LEGACY */ - OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE7, - POW_SM(ratesArray[rateHt40_3] + ht40PowerIncForPdadc, 24) - | POW_SM(ratesArray[rateHt40_2] + ht40PowerIncForPdadc, 16) - | POW_SM(ratesArray[rateHt40_1] + ht40PowerIncForPdadc, 8) - | POW_SM(ratesArray[rateHt40_0] + ht40PowerIncForPdadc, 0) - ); - OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE8, - POW_SM(ratesArray[rateHt40_7] + ht40PowerIncForPdadc, 24) - | POW_SM(ratesArray[rateHt40_6] + ht40PowerIncForPdadc, 16) - | POW_SM(ratesArray[rateHt40_5] + ht40PowerIncForPdadc, 8) - | POW_SM(ratesArray[rateHt40_4] + ht40PowerIncForPdadc, 0) - ); - /* Write the Dup/Ext 40 power per rate set */ - OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE9, - POW_SM(ratesArray[rateExtOfdm], 24) - | POW_SM(ratesArray[rateExtCck], 16) - | POW_SM(ratesArray[rateDupOfdm], 8) - | POW_SM(ratesArray[rateDupCck], 0) - ); + ratesArray[rateHt40_0] += ht40PowerIncForPdadc; + ratesArray[rateHt40_1] += ht40PowerIncForPdadc; + ratesArray[rateHt40_2] += ht40PowerIncForPdadc; + ratesArray[rateHt40_3] += ht40PowerIncForPdadc; + ratesArray[rateHt40_4] += ht40PowerIncForPdadc; + ratesArray[rateHt40_5] += ht40PowerIncForPdadc; + ratesArray[rateHt40_6] += ht40PowerIncForPdadc; + ratesArray[rateHt40_7] += ht40PowerIncForPdadc; } + /* Write the TX power rate registers */ + ar5416WriteTxPowerRateRegisters(ah, chan, ratesArray); + return AH_TRUE; #undef POW_SM #undef N } +static void +ar9285SetBoardGain(struct ath_hal *ah, const MODAL_EEP4K_HEADER *pModal, + const struct ar5416eeprom_4k *eep, uint8_t txRxAttenLocal) +{ + OS_REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0, + pModal->antCtrlChain[0]); + + OS_REG_WRITE(ah, AR_PHY_TIMING_CTRL4_CHAIN(0), + (OS_REG_READ(ah, AR_PHY_TIMING_CTRL4_CHAIN(0)) & + ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF | + AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) | + SM(pModal->iqCalICh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) | + SM(pModal->iqCalQCh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF)); + + if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= + AR5416_EEP_MINOR_VER_3) { + txRxAttenLocal = pModal->txRxAttenCh[0]; + + OS_REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ, + AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, pModal->bswMargin[0]); + OS_REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ, + AR_PHY_GAIN_2GHZ_XATTEN1_DB, pModal->bswAtten[0]); + OS_REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ, + AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN, pModal->xatten2Margin[0]); + OS_REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ, + AR_PHY_GAIN_2GHZ_XATTEN2_DB, pModal->xatten2Db[0]); + + /* Set the block 1 value to block 0 value */ + OS_REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000, + AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, + pModal->bswMargin[0]); + OS_REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000, + AR_PHY_GAIN_2GHZ_XATTEN1_DB, pModal->bswAtten[0]); + OS_REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000, + AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN, + pModal->xatten2Margin[0]); + OS_REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000, + AR_PHY_GAIN_2GHZ_XATTEN2_DB, pModal->xatten2Db[0]); + } + + OS_REG_RMW_FIELD(ah, AR_PHY_RXGAIN, + AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal); + OS_REG_RMW_FIELD(ah, AR_PHY_RXGAIN, + AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]); + + OS_REG_RMW_FIELD(ah, AR_PHY_RXGAIN + 0x1000, + AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal); + OS_REG_RMW_FIELD(ah, AR_PHY_RXGAIN + 0x1000, + AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]); +} + +/* + * Read EEPROM header info and program the device for correct operation + * given the channel value. + */ HAL_BOOL ar9285SetBoardValues(struct ath_hal *ah, const struct ieee80211_channel *chan) { - const HAL_EEPROM_v4k *ee = AH_PRIVATE(ah)->ah_eeprom; - const struct ar5416eeprom_4k *eep = &ee->ee_base; - const MODAL_EEP4K_HEADER *pModal; - int i, regChainOffset; - uint8_t txRxAttenLocal; /* workaround for eeprom versions <= 14.2 */ + const HAL_EEPROM_v4k *ee = AH_PRIVATE(ah)->ah_eeprom; + const struct ar5416eeprom_4k *eep = &ee->ee_base; + const MODAL_EEP4K_HEADER *pModal; + uint8_t txRxAttenLocal; + uint8_t ob[5], db1[5], db2[5]; - HALASSERT(AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER14_1); - pModal = &eep->modalHeader; + pModal = &eep->modalHeader; + txRxAttenLocal = 23; - /* NB: workaround for eeprom versions <= 14.2 */ - txRxAttenLocal = 23; + OS_REG_WRITE(ah, AR_PHY_SWITCH_COM, pModal->antCtrlCommon); - OS_REG_WRITE(ah, AR_PHY_SWITCH_COM, pModal->antCtrlCommon); - for (i = 0; i < AR5416_4K_MAX_CHAINS; i++) { - if (AR_SREV_MERLIN(ah)) { - if (i >= 2) break; - } - if (AR_SREV_OWL_20_OR_LATER(ah) && - (AH5416(ah)->ah_rx_chainmask == 0x5 || - AH5416(ah)->ah_tx_chainmask == 0x5) && i != 0) { - /* Regs are swapped from chain 2 to 1 for 5416 2_0 with - * only chains 0 and 2 populated - */ - regChainOffset = (i == 1) ? 0x2000 : 0x1000; - } else { - regChainOffset = i * 0x1000; - } + /* Single chain for 4K EEPROM*/ + ar9285SetBoardGain(ah, pModal, eep, txRxAttenLocal); - OS_REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset, pModal->antCtrlChain[i]); - OS_REG_WRITE(ah, AR_PHY_TIMING_CTRL4 + regChainOffset, - (OS_REG_READ(ah, AR_PHY_TIMING_CTRL4 + regChainOffset) & - ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF | AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) | - SM(pModal->iqCalICh[i], AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) | - SM(pModal->iqCalQCh[i], AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF)); + /* Initialize Ant Diversity settings if supported */ + (void) ar9285SetAntennaSwitch(ah, AH5212(ah)->ah_antControl); - /* - * Large signal upgrade. - * XXX update - */ + /* Configure TX power calibration */ + if (pModal->version >= 2) { + ob[0] = pModal->ob_0; + ob[1] = pModal->ob_1; + ob[2] = pModal->ob_2; + ob[3] = pModal->ob_3; + ob[4] = pModal->ob_4; - if ((i == 0) || AR_SREV_OWL_20_OR_LATER(ah)) { - OS_REG_WRITE(ah, AR_PHY_RXGAIN + regChainOffset, - (OS_REG_READ(ah, AR_PHY_RXGAIN + regChainOffset) & ~AR_PHY_RXGAIN_TXRX_ATTEN) | - SM(IS_EEP_MINOR_V3(ah) ? pModal->txRxAttenCh[i] : txRxAttenLocal, - AR_PHY_RXGAIN_TXRX_ATTEN)); + db1[0] = pModal->db1_0; + db1[1] = pModal->db1_1; + db1[2] = pModal->db1_2; + db1[3] = pModal->db1_3; + db1[4] = pModal->db1_4; - OS_REG_WRITE(ah, AR_PHY_GAIN_2GHZ + regChainOffset, - (OS_REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) & ~AR_PHY_GAIN_2GHZ_RXTX_MARGIN) | - SM(pModal->rxTxMarginCh[i], AR_PHY_GAIN_2GHZ_RXTX_MARGIN)); - } - } + db2[0] = pModal->db2_0; + db2[1] = pModal->db2_1; + db2[2] = pModal->db2_2; + db2[3] = pModal->db2_3; + db2[4] = pModal->db2_4; + } else if (pModal->version == 1) { + ob[0] = pModal->ob_0; + ob[1] = ob[2] = ob[3] = ob[4] = pModal->ob_1; + db1[0] = pModal->db1_0; + db1[1] = db1[2] = db1[3] = db1[4] = pModal->db1_1; + db2[0] = pModal->db2_0; + db2[1] = db2[2] = db2[3] = db2[4] = pModal->db2_1; + } else { + int i; - OS_REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH, pModal->switchSettling); - OS_REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC, pModal->adcDesiredSize); - OS_REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_PGA, pModal->pgaDesiredSize); - OS_REG_WRITE(ah, AR_PHY_RF_CTL4, - SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF) - | SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAB_OFF) - | SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAA_ON) - | SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAB_ON)); - - OS_REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON, pModal->txEndToRxOn); - - OS_REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62, - pModal->thresh62); - OS_REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, AR_PHY_EXT_CCA0_THRESH62, - pModal->thresh62); - - /* Minor Version Specific application */ - if (IS_EEP_MINOR_V2(ah)) { - OS_REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_FRAME_TO_DATA_START, pModal->txFrameToDataStart); - OS_REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_FRAME_TO_PA_ON, pModal->txFrameToPaOn); - } - - if (IS_EEP_MINOR_V3(ah)) { - if (IEEE80211_IS_CHAN_HT40(chan)) { - /* Overwrite switch settling with HT40 value */ - OS_REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH, pModal->swSettleHt40); + for (i = 0; i < 5; i++) { + ob[i] = pModal->ob_0; + db1[i] = pModal->db1_0; + db2[i] = pModal->db1_0; + } } - - if ((AR_SREV_OWL_20_OR_LATER(ah)) && - ( AH5416(ah)->ah_rx_chainmask == 0x5 || AH5416(ah)->ah_tx_chainmask == 0x5)){ - /* Reg Offsets are swapped for logical mapping */ - OS_REG_WRITE(ah, AR_PHY_GAIN_2GHZ + 0x1000, (OS_REG_READ(ah, AR_PHY_GAIN_2GHZ + 0x1000) & ~AR_PHY_GAIN_2GHZ_BSW_MARGIN) | - SM(pModal->bswMargin[2], AR_PHY_GAIN_2GHZ_BSW_MARGIN)); - OS_REG_WRITE(ah, AR_PHY_GAIN_2GHZ + 0x1000, (OS_REG_READ(ah, AR_PHY_GAIN_2GHZ + 0x1000) & ~AR_PHY_GAIN_2GHZ_BSW_ATTEN) | - SM(pModal->bswAtten[2], AR_PHY_GAIN_2GHZ_BSW_ATTEN)); - OS_REG_WRITE(ah, AR_PHY_GAIN_2GHZ + 0x2000, (OS_REG_READ(ah, AR_PHY_GAIN_2GHZ + 0x2000) & ~AR_PHY_GAIN_2GHZ_BSW_MARGIN) | - SM(pModal->bswMargin[1], AR_PHY_GAIN_2GHZ_BSW_MARGIN)); - OS_REG_WRITE(ah, AR_PHY_GAIN_2GHZ + 0x2000, (OS_REG_READ(ah, AR_PHY_GAIN_2GHZ + 0x2000) & ~AR_PHY_GAIN_2GHZ_BSW_ATTEN) | - SM(pModal->bswAtten[1], AR_PHY_GAIN_2GHZ_BSW_ATTEN)); - } else { - OS_REG_WRITE(ah, AR_PHY_GAIN_2GHZ + 0x1000, (OS_REG_READ(ah, AR_PHY_GAIN_2GHZ + 0x1000) & ~AR_PHY_GAIN_2GHZ_BSW_MARGIN) | - SM(pModal->bswMargin[1], AR_PHY_GAIN_2GHZ_BSW_MARGIN)); - OS_REG_WRITE(ah, AR_PHY_GAIN_2GHZ + 0x1000, (OS_REG_READ(ah, AR_PHY_GAIN_2GHZ + 0x1000) & ~AR_PHY_GAIN_2GHZ_BSW_ATTEN) | - SM(pModal->bswAtten[1], AR_PHY_GAIN_2GHZ_BSW_ATTEN)); - OS_REG_WRITE(ah, AR_PHY_GAIN_2GHZ + 0x2000, (OS_REG_READ(ah, AR_PHY_GAIN_2GHZ + 0x2000) & ~AR_PHY_GAIN_2GHZ_BSW_MARGIN) | - SM(pModal->bswMargin[2],AR_PHY_GAIN_2GHZ_BSW_MARGIN)); - OS_REG_WRITE(ah, AR_PHY_GAIN_2GHZ + 0x2000, (OS_REG_READ(ah, AR_PHY_GAIN_2GHZ + 0x2000) & ~AR_PHY_GAIN_2GHZ_BSW_ATTEN) | - SM(pModal->bswAtten[2], AR_PHY_GAIN_2GHZ_BSW_ATTEN)); - } - OS_REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ, AR_PHY_GAIN_2GHZ_BSW_MARGIN, pModal->bswMargin[0]); - OS_REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ, AR_PHY_GAIN_2GHZ_BSW_ATTEN, pModal->bswAtten[0]); - } - return AH_TRUE; + + OS_A_REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_OB_0, ob[0]); + OS_A_REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_OB_1, ob[1]); + OS_A_REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_OB_2, ob[2]); + OS_A_REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_OB_3, ob[3]); + OS_A_REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_OB_4, ob[4]); + + OS_A_REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_DB1_0, db1[0]); + OS_A_REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_DB1_1, db1[1]); + OS_A_REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_DB1_2, db1[2]); + OS_A_REG_RMW_FIELD(ah, AR9285_AN_RF2G4, AR9285_AN_RF2G4_DB1_3, db1[3]); + OS_A_REG_RMW_FIELD(ah, AR9285_AN_RF2G4, AR9285_AN_RF2G4_DB1_4, db1[4]); + + OS_A_REG_RMW_FIELD(ah, AR9285_AN_RF2G4, AR9285_AN_RF2G4_DB2_0, db2[0]); + OS_A_REG_RMW_FIELD(ah, AR9285_AN_RF2G4, AR9285_AN_RF2G4_DB2_1, db2[1]); + OS_A_REG_RMW_FIELD(ah, AR9285_AN_RF2G4, AR9285_AN_RF2G4_DB2_2, db2[2]); + OS_A_REG_RMW_FIELD(ah, AR9285_AN_RF2G4, AR9285_AN_RF2G4_DB2_3, db2[3]); + OS_A_REG_RMW_FIELD(ah, AR9285_AN_RF2G4, AR9285_AN_RF2G4_DB2_4, db2[4]); + + OS_REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH, + pModal->switchSettling); + OS_REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC, + pModal->adcDesiredSize); + + OS_REG_WRITE(ah, AR_PHY_RF_CTL4, + SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF) | + SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAB_OFF) | + SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAA_ON) | + SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAB_ON)); + + OS_REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON, + pModal->txEndToRxOn); + + OS_REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62, + pModal->thresh62); + OS_REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, AR_PHY_EXT_CCA0_THRESH62, + pModal->thresh62); + + if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= + AR5416_EEP_MINOR_VER_2) { + OS_REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_FRAME_TO_DATA_START, + pModal->txFrameToDataStart); + OS_REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_FRAME_TO_PA_ON, + pModal->txFrameToPaOn); + } + + if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= + AR5416_EEP_MINOR_VER_3) { + if (IEEE80211_IS_CHAN_HT40(chan)) + OS_REG_RMW_FIELD(ah, AR_PHY_SETTLING, + AR_PHY_SETTLING_SWITCH, pModal->swSettleHt40); + } + + /* + * Program the CCK TX gain factor appropriately if needed. + * The AR9285/AR9271 has a non-constant PA tx gain behaviour + * for CCK versus OFDM rates; other chips deal with this + * differently. + * + * The mask/shift/multiply hackery is done so place the same + * value (bb_desired_scale) into multiple 5-bit fields. + * For example, AR_PHY_TX_PWRCTRL9 has bb_desired_scale written + * to three fields: (0..4), (5..9) and (10..14). + */ + if (AR_SREV_9271(ah) || AR_SREV_KITE(ah)) { + uint8_t bb_desired_scale = (pModal->bb_scale_smrt_antenna & EEP_4K_BB_DESIRED_SCALE_MASK); + if ((eep->baseEepHeader.txGainType == 0) && (bb_desired_scale != 0)) { + ath_hal_printf(ah, "[ath]: adjusting cck tx gain factor\n"); + uint32_t pwrctrl, mask, clr; + + mask = (1<<0) | (1<<5) | (1<<10) | (1<<15) | (1<<20) | (1<<25); + pwrctrl = mask * bb_desired_scale; + clr = mask * 0x1f; + OS_REG_RMW(ah, AR_PHY_TX_PWRCTRL8, pwrctrl, clr); + OS_REG_RMW(ah, AR_PHY_TX_PWRCTRL10, pwrctrl, clr); + OS_REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL12, pwrctrl, clr); + + mask = (1<<0) | (1<<5) | (1<<15); + pwrctrl = mask * bb_desired_scale; + clr = mask * 0x1f; + OS_REG_RMW(ah, AR_PHY_TX_PWRCTRL9, pwrctrl, clr); + + mask = (1<<0) | (1<<5); + pwrctrl = mask * bb_desired_scale; + clr = mask * 0x1f; + OS_REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL11, pwrctrl, clr); + OS_REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL13, pwrctrl, clr); + } + } + + return AH_TRUE; } /* @@ -453,9 +482,9 @@ ar9285SetPowerPerRateTable(struct ath_hal *ah, struct ar5416eeprom_4k *pEepData, (((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))) { rep = &(pEepData->ctlData[i]); - twiceMinEdgePower = ar9285GetMaxEdgePower(freq, + twiceMinEdgePower = ar5416GetMaxEdgePower(freq, rep->ctlEdges[ - owl_get_ntxchains(AH5416(ah)->ah_tx_chainmask) - 1]); + owl_get_ntxchains(AH5416(ah)->ah_tx_chainmask) - 1], AH_TRUE); if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) { /* Find the minimum of all CTL edge powers that apply to this channel */ twiceMaxEdgePower = AH_MIN(twiceMaxEdgePower, twiceMinEdgePower); @@ -504,32 +533,15 @@ ar9285SetPowerPerRateTable(struct ath_hal *ah, struct ar5416eeprom_4k *pEepData, } } /* end ctl mode checking */ - /* Set rates Array from collected data */ - ratesArray[rate6mb] = ratesArray[rate9mb] = ratesArray[rate12mb] = ratesArray[rate18mb] = ratesArray[rate24mb] = targetPowerOfdm.tPow2x[0]; - ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1]; - ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2]; - ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3]; - ratesArray[rateXr] = targetPowerOfdm.tPow2x[0]; + /* Set rates Array from collected data */ + ar5416SetRatesArrayFromTargetPower(ah, chan, ratesArray, + &targetPowerCck, + &targetPowerCckExt, + &targetPowerOfdm, + &targetPowerOfdmExt, + &targetPowerHt20, + &targetPowerHt40); - for (i = 0; i < N(targetPowerHt20.tPow2x); i++) { - ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i]; - } - - ratesArray[rate1l] = targetPowerCck.tPow2x[0]; - ratesArray[rate2s] = ratesArray[rate2l] = targetPowerCck.tPow2x[1]; - ratesArray[rate5_5s] = ratesArray[rate5_5l] = targetPowerCck.tPow2x[2]; - ratesArray[rate11s] = ratesArray[rate11l] = targetPowerCck.tPow2x[3]; - if (IEEE80211_IS_CHAN_HT40(chan)) { - for (i = 0; i < N(targetPowerHt40.tPow2x); i++) { - ratesArray[rateHt40_0 + i] = targetPowerHt40.tPow2x[i]; - } - ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0]; - ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0]; - ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0]; - if (IEEE80211_IS_CHAN_2GHZ(chan)) { - ratesArray[rateExtCck] = targetPowerCckExt.tPow2x[0]; - } - } return AH_TRUE; #undef EXT_ADDITIVE #undef CTL_11G_EXT @@ -538,58 +550,6 @@ ar9285SetPowerPerRateTable(struct ath_hal *ah, struct ar5416eeprom_4k *pEepData, #undef N } -/************************************************************************** - * fbin2freq - * - * Get channel value from binary representation held in eeprom - * RETURNS: the frequency in MHz - */ -static uint16_t -fbin2freq(uint8_t fbin) -{ - /* - * Reserved value 0xFF provides an empty definition both as - * an fbin and as a frequency - do not convert - */ - if (fbin == AR5416_BCHAN_UNUSED) { - return fbin; - } - - return (uint16_t)(2300 + fbin); -} - -/* - * XXX almost the same as ar5416GetMaxEdgePower. - */ -static uint16_t -ar9285GetMaxEdgePower(uint16_t freq, CAL_CTL_EDGES *pRdEdgesPower) -{ - uint16_t twiceMaxEdgePower = AR5416_MAX_RATE_POWER; - int i; - - /* Get the edge power */ - for (i = 0; (i < AR5416_NUM_BAND_EDGES) && (pRdEdgesPower[i].bChannel != AR5416_BCHAN_UNUSED) ; i++) { - /* - * If there's an exact channel match or an inband flag set - * on the lower channel use the given rdEdgePower - */ - if (freq == fbin2freq(pRdEdgesPower[i].bChannel)) { - twiceMaxEdgePower = MS(pRdEdgesPower[i].tPowerFlag, CAL_CTL_EDGES_POWER); - break; - } else if ((i > 0) && (freq < fbin2freq(pRdEdgesPower[i].bChannel))) { - if (fbin2freq(pRdEdgesPower[i - 1].bChannel) < freq && (pRdEdgesPower[i - 1].tPowerFlag & CAL_CTL_EDGES_FLAG) != 0) { - twiceMaxEdgePower = MS(pRdEdgesPower[i - 1].tPowerFlag, CAL_CTL_EDGES_POWER); - } - /* Leave loop - no more affecting edges possible in this monotonic increasing list */ - break; - } - } - HALASSERT(twiceMaxEdgePower > 0); - return twiceMaxEdgePower; -} - - - static HAL_BOOL ar9285SetPowerCalTable(struct ath_hal *ah, struct ar5416eeprom_4k *pEepData, const struct ieee80211_channel *chan, int16_t *pTxPowerIndexOffset) @@ -599,11 +559,11 @@ ar9285SetPowerCalTable(struct ath_hal *ah, struct ar5416eeprom_4k *pEepData, uint16_t pdGainOverlap_t2; static uint8_t pdadcValues[AR5416_NUM_PDADC_VALUES]; uint16_t gainBoundaries[AR5416_PD_GAINS_IN_MASK]; - uint16_t numPiers, i, j; + uint16_t numPiers, i; int16_t tMinCalPower; uint16_t numXpdGain, xpdMask; - uint16_t xpdGainValues[AR5416_4K_NUM_PD_GAINS]; - uint32_t reg32, regOffset, regChainOffset; + uint16_t xpdGainValues[4]; /* v4k eeprom has 2; the other two stay 0 */ + uint32_t regChainOffset; OS_MEMZERO(xpdGainValues, sizeof(xpdGainValues)); @@ -618,6 +578,7 @@ ar9285SetPowerCalTable(struct ath_hal *ah, struct ar5416eeprom_4k *pEepData, pCalBChans = pEepData->calFreqPier2G; numPiers = AR5416_4K_NUM_2G_CAL_PIERS; numXpdGain = 0; + /* Calculate the value of xpdgains from the xpdGain Mask */ for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) { if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) { @@ -631,23 +592,10 @@ ar9285SetPowerCalTable(struct ath_hal *ah, struct ar5416eeprom_4k *pEepData, } /* Write the detector gain biases and their number */ - OS_REG_WRITE(ah, AR_PHY_TPCRG1, (OS_REG_READ(ah, AR_PHY_TPCRG1) & - ~(AR_PHY_TPCRG1_NUM_PD_GAIN | AR_PHY_TPCRG1_PD_GAIN_1 | AR_PHY_TPCRG1_PD_GAIN_2 | AR_PHY_TPCRG1_PD_GAIN_3)) | - SM(numXpdGain - 1, AR_PHY_TPCRG1_NUM_PD_GAIN) | SM(xpdGainValues[0], AR_PHY_TPCRG1_PD_GAIN_1 ) | - SM(xpdGainValues[1], AR_PHY_TPCRG1_PD_GAIN_2) | SM(xpdGainValues[2], AR_PHY_TPCRG1_PD_GAIN_3)); + ar5416WriteDetectorGainBiases(ah, numXpdGain, xpdGainValues); for (i = 0; i < AR5416_MAX_CHAINS; i++) { - - if (AR_SREV_OWL_20_OR_LATER(ah) && - ( AH5416(ah)->ah_rx_chainmask == 0x5 || AH5416(ah)->ah_tx_chainmask == 0x5) && (i != 0)) { - /* Regs are swapped from chain 2 to 1 for 5416 2_0 with - * only chains 0 and 2 populated - */ - regChainOffset = (i == 1) ? 0x2000 : 0x1000; - } else { - regChainOffset = i * 0x1000; - } - + regChainOffset = ar5416GetRegChainOffset(ah, i); if (pEepData->baseEepHeader.txMask & (1 << i)) { pRawDataset = pEepData->calPierData2G[i]; @@ -657,41 +605,17 @@ ar9285SetPowerCalTable(struct ath_hal *ah, struct ar5416eeprom_4k *pEepData, &tMinCalPower, gainBoundaries, pdadcValues, numXpdGain); - if ((i == 0) || AR_SREV_OWL_20_OR_LATER(ah)) { + if ((i == 0) || AR_SREV_5416_V20_OR_LATER(ah)) { /* * Note the pdadc table may not start at 0 dBm power, could be * negative or greater than 0. Need to offset the power * values by the amount of minPower for griffin */ - - OS_REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset, - SM(pdGainOverlap_t2, AR_PHY_TPCRG5_PD_GAIN_OVERLAP) | - SM(gainBoundaries[0], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) | - SM(gainBoundaries[1], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) | - SM(gainBoundaries[2], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) | - SM(gainBoundaries[3], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4)); + ar5416SetGainBoundariesClosedLoop(ah, i, pdGainOverlap_t2, gainBoundaries); } /* Write the power values into the baseband power table */ - regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset; - - for (j = 0; j < 32; j++) { - reg32 = ((pdadcValues[4*j + 0] & 0xFF) << 0) | - ((pdadcValues[4*j + 1] & 0xFF) << 8) | - ((pdadcValues[4*j + 2] & 0xFF) << 16) | - ((pdadcValues[4*j + 3] & 0xFF) << 24) ; - OS_REG_WRITE(ah, regOffset, reg32); - -#ifdef PDADC_DUMP - ath_hal_printf(ah, "PDADC: Chain %d | PDADC %3d Value %3d | PDADC %3d Value %3d | PDADC %3d Value %3d | PDADC %3d Value %3d |\n", - i, - 4*j, pdadcValues[4*j], - 4*j+1, pdadcValues[4*j + 1], - 4*j+2, pdadcValues[4*j + 2], - 4*j+3, pdadcValues[4*j + 3]); -#endif - regOffset += 4; - } + ar5416WritePdadcValues(ah, i, pdadcValues); } } *pTxPowerIndexOffset = 0; @@ -741,15 +665,15 @@ ar9285GetGainBoundariesAndPdadcs(struct ath_hal *ah, } /* Find pier indexes around the current channel */ - match = getLowerUpperIndex((uint8_t)FREQ2FBIN(centers.synth_center, IEEE80211_IS_CHAN_2GHZ(chan)), - bChans, numPiers, &idxL, &idxR); + match = ath_ee_getLowerUpperIndex((uint8_t)FREQ2FBIN(centers.synth_center, + IEEE80211_IS_CHAN_2GHZ(chan)), bChans, numPiers, &idxL, &idxR); if (match) { /* Directly fill both vpd tables from the matching index */ for (i = 0; i < numXpdGains; i++) { minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0]; maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4]; - ar9285FillVpdTable(minPwrT4[i], maxPwrT4[i], + ath_ee_FillVpdTable(minPwrT4[i], maxPwrT4[i], pRawDataSet[idxL].pwrPdg[i], pRawDataSet[idxL].vpdPdg[i], AR5416_PD_GAIN_ICEPTS, vpdTableI[i]); @@ -769,14 +693,15 @@ ar9285GetGainBoundariesAndPdadcs(struct ath_hal *ah, HALASSERT(maxPwrT4[i] > minPwrT4[i]); /* Fill pier Vpds */ - ar9285FillVpdTable(minPwrT4[i], maxPwrT4[i], pPwrL, pVpdL, + ath_ee_FillVpdTable(minPwrT4[i], maxPwrT4[i], pPwrL, pVpdL, AR5416_PD_GAIN_ICEPTS, vpdTableL[i]); - ar9285FillVpdTable(minPwrT4[i], maxPwrT4[i], pPwrR, pVpdR, + ath_ee_FillVpdTable(minPwrT4[i], maxPwrT4[i], pPwrR, pVpdR, AR5416_PD_GAIN_ICEPTS, vpdTableR[i]); /* Interpolate the final vpd */ for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) { - vpdTableI[i][j] = (uint8_t)(interpolate((uint16_t)FREQ2FBIN(centers.synth_center, IEEE80211_IS_CHAN_2GHZ(chan)), + vpdTableI[i][j] = (uint8_t)(ath_ee_interpolate((uint16_t)FREQ2FBIN(centers.synth_center, + IEEE80211_IS_CHAN_2GHZ(chan)), bChans[idxL], bChans[idxR], vpdTableL[i][j], vpdTableR[i][j])); } } @@ -794,7 +719,7 @@ ar9285GetGainBoundariesAndPdadcs(struct ath_hal *ah, pPdGainBoundaries[i] = (uint16_t)AH_MIN(AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]); /* NB: only applies to owl 1.0 */ - if ((i == 0) && !AR_SREV_OWL_20_OR_LATER(ah) ) { + if ((i == 0) && !AR_SREV_5416_V20_OR_LATER(ah) ) { /* * fix the gain delta, but get a delta that can be applied to min to * keep the upper power values accurate, don't think max needs to @@ -809,7 +734,10 @@ ar9285GetGainBoundariesAndPdadcs(struct ath_hal *ah, /* Find starting index for this pdGain */ if (i == 0) { - ss = 0; /* for the first pdGain, start from index 0 */ + if (AR_SREV_MERLIN_20_OR_LATER(ah)) + ss = (int16_t)(0 - (minPwrT4[i] / 2)); + else + ss = 0; /* for the first pdGain, start from index 0 */ } else { /* need overlap entries extrapolated below. */ ss = (int16_t)((pPdGainBoundaries[i-1] - (minPwrT4[i] / 2)) - tPdGainOverlap + 1 + minDelta); @@ -839,7 +767,7 @@ ar9285GetGainBoundariesAndPdadcs(struct ath_hal *ah, * for last gain, pdGainBoundary == Pmax_t2, so will * have to extrapolate */ - if (tgtIndex > maxIndex) { /* need to extrapolate above */ + if (tgtIndex >= maxIndex) { /* need to extrapolate above */ while ((ss <= tgtIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) { tmpVal = (int16_t)((vpdTableI[i][sizeCurrVpdTable - 1] + (ss - maxIndex +1) * vpdStep)); @@ -851,7 +779,7 @@ ar9285GetGainBoundariesAndPdadcs(struct ath_hal *ah, /* Fill out pdGainBoundaries - only up to 2 allowed here, but hardware allows up to 4 */ while (i < AR5416_PD_GAINS_IN_MASK) { - pPdGainBoundaries[i] = pPdGainBoundaries[i-1]; + pPdGainBoundaries[i] = AR5416_4K_EEP_PD_GAIN_BOUNDARY_DEFAULT; i++; } @@ -861,91 +789,3 @@ ar9285GetGainBoundariesAndPdadcs(struct ath_hal *ah, } return; } -/* - * XXX same as ar5416FillVpdTable - */ -static HAL_BOOL -ar9285FillVpdTable(uint8_t pwrMin, uint8_t pwrMax, uint8_t *pPwrList, - uint8_t *pVpdList, uint16_t numIntercepts, uint8_t *pRetVpdList) -{ - uint16_t i, k; - uint8_t currPwr = pwrMin; - uint16_t idxL, idxR; - - HALASSERT(pwrMax > pwrMin); - for (i = 0; i <= (pwrMax - pwrMin) / 2; i++) { - getLowerUpperIndex(currPwr, pPwrList, numIntercepts, - &(idxL), &(idxR)); - if (idxR < 1) - idxR = 1; /* extrapolate below */ - if (idxL == numIntercepts - 1) - idxL = (uint16_t)(numIntercepts - 2); /* extrapolate above */ - if (pPwrList[idxL] == pPwrList[idxR]) - k = pVpdList[idxL]; - else - k = (uint16_t)( ((currPwr - pPwrList[idxL]) * pVpdList[idxR] + (pPwrList[idxR] - currPwr) * pVpdList[idxL]) / - (pPwrList[idxR] - pPwrList[idxL]) ); - HALASSERT(k < 256); - pRetVpdList[i] = (uint8_t)k; - currPwr += 2; /* half dB steps */ - } - - return AH_TRUE; -} -static int16_t -interpolate(uint16_t target, uint16_t srcLeft, uint16_t srcRight, - int16_t targetLeft, int16_t targetRight) -{ - int16_t rv; - - if (srcRight == srcLeft) { - rv = targetLeft; - } else { - rv = (int16_t)( ((target - srcLeft) * targetRight + - (srcRight - target) * targetLeft) / (srcRight - srcLeft) ); - } - return rv; -} - -HAL_BOOL -getLowerUpperIndex(uint8_t target, uint8_t *pList, uint16_t listSize, - uint16_t *indexL, uint16_t *indexR) -{ - uint16_t i; - - /* - * Check first and last elements for beyond ordered array cases. - */ - if (target <= pList[0]) { - *indexL = *indexR = 0; - return AH_TRUE; - } - if (target >= pList[listSize-1]) { - *indexL = *indexR = (uint16_t)(listSize - 1); - return AH_TRUE; - } - - /* look for value being near or between 2 values in list */ - for (i = 0; i < listSize - 1; i++) { - /* - * If value is close to the current value of the list - * then target is not between values, it is one of the values - */ - if (pList[i] == target) { - *indexL = *indexR = i; - return AH_TRUE; - } - /* - * Look for value being between current value and next value - * if so return these 2 values - */ - if (target < pList[i + 1]) { - *indexL = i; - *indexR = (uint16_t)(i + 1); - return AH_FALSE; - } - } - HALASSERT(0); - *indexL = *indexR = 0; - return AH_FALSE; -} diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9285an.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9285an.h new file mode 100644 index 0000000000..3b80938e3a --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9285an.h @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2008-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ + +#ifndef __AR9285_AN_H__ +#define __AR9285_AN_H__ + +/* AR9285 Analog register definitions */ + +#define AR9285_AN_RF2G1 0x7820 + +#define AR9285_AN_RF2G1_ENPACAL 0x00000800 +#define AR9285_AN_RF2G1_ENPACAL_S 11 +#define AR9285_AN_RF2G1_PDPADRV1 0x02000000 +#define AR9285_AN_RF2G1_PDPADRV1_S 25 +#define AR9285_AN_RF2G1_PDPADRV2 0x01000000 +#define AR9285_AN_RF2G1_PDPADRV2_S 24 +#define AR9285_AN_RF2G1_PDPAOUT 0x00800000 +#define AR9285_AN_RF2G1_PDPAOUT_S 23 + +#define AR9285_AN_RF2G2 0x7824 + +#define AR9285_AN_RF2G2_OFFCAL 0x00001000 +#define AR9285_AN_RF2G2_OFFCAL_S 12 + +#define AR9285_AN_RF2G3 0x7828 + +#define AR9285_AN_RF2G3_PDVCCOMP 0x02000000 +#define AR9285_AN_RF2G3_PDVCCOMP_S 25 +#define AR9285_AN_RF2G3_OB_0 0x00E00000 +#define AR9285_AN_RF2G3_OB_0_S 21 +#define AR9285_AN_RF2G3_OB_1 0x001C0000 +#define AR9285_AN_RF2G3_OB_1_S 18 +#define AR9285_AN_RF2G3_OB_2 0x00038000 +#define AR9285_AN_RF2G3_OB_2_S 15 +#define AR9285_AN_RF2G3_OB_3 0x00007000 +#define AR9285_AN_RF2G3_OB_3_S 12 +#define AR9285_AN_RF2G3_OB_4 0x00000E00 +#define AR9285_AN_RF2G3_OB_4_S 9 +#define AR9285_AN_RF2G3_DB1_0 0x000001C0 +#define AR9285_AN_RF2G3_DB1_0_S 6 +#define AR9285_AN_RF2G3_DB1_1 0x00000038 +#define AR9285_AN_RF2G3_DB1_1_S 3 +#define AR9285_AN_RF2G3_DB1_2 0x00000007 +#define AR9285_AN_RF2G3_DB1_2_S 0 + +#define AR9285_AN_RF2G4 0x782C + +#define AR9285_AN_RF2G4_DB1_3 0xE0000000 +#define AR9285_AN_RF2G4_DB1_3_S 29 +#define AR9285_AN_RF2G4_DB1_4 0x1C000000 +#define AR9285_AN_RF2G4_DB1_4_S 26 + +#define AR9285_AN_RF2G4_DB2_0 0x03800000 +#define AR9285_AN_RF2G4_DB2_0_S 23 +#define AR9285_AN_RF2G4_DB2_1 0x00700000 +#define AR9285_AN_RF2G4_DB2_1_S 20 +#define AR9285_AN_RF2G4_DB2_2 0x000E0000 +#define AR9285_AN_RF2G4_DB2_2_S 17 +#define AR9285_AN_RF2G4_DB2_3 0x0001C000 +#define AR9285_AN_RF2G4_DB2_3_S 14 +#define AR9285_AN_RF2G4_DB2_4 0x00003800 +#define AR9285_AN_RF2G4_DB2_4_S 11 + +#define AR9285_AN_RF2G6 0x7834 + +#define AR9285_AN_RF2G6_CCOMP 0x00007800 +#define AR9285_AN_RF2G6_CCOMP_S 11 +#define AR9285_AN_RF2G6_OFFS 0x03f00000 +#define AR9285_AN_RF2G6_OFFS_S 20 + +#define AR9285_AN_RF2G7 0x7838 + +#define AR9285_AN_RF2G7_PWDDB 0x00000002 +#define AR9285_AN_RF2G7_PWDDB_S 1 +#define AR9285_AN_RF2G7_PADRVGN2TAB0 0xE0000000 +#define AR9285_AN_RF2G7_PADRVGN2TAB0_S 29 + +#define AR9285_AN_RF2G8 0x783C + +#define AR9285_AN_RF2G8_PADRVGN2TAB0 0x0001C000 +#define AR9285_AN_RF2G8_PADRVGN2TAB0_S 14 + +#define AR9285_AN_RF2G9 0x7840 + +#define AR9285_AN_RXTXBB1 0x7854 + +#define AR9285_AN_RXTXBB1_PDRXTXBB1 0x00000020 +#define AR9285_AN_RXTXBB1_PDRXTXBB1_S 5 +#define AR9285_AN_RXTXBB1_PDV2I 0x00000080 +#define AR9285_AN_RXTXBB1_PDV2I_S 7 +#define AR9285_AN_RXTXBB1_PDDACIF 0x00000100 +#define AR9285_AN_RXTXBB1_PDDACIF_S 8 +#define AR9285_AN_RXTXBB1_SPARE9 0x00000001 +#define AR9285_AN_RXTXBB1_SPARE9_S 0 + +#define AR9285_AN_TOP2 0x7868 + +#define AR9285_AN_TOP3 0x786c + +#define AR9285_AN_TOP3_XPABIAS_LVL 0x0000000C +#define AR9285_AN_TOP3_XPABIAS_LVL_S 2 +#define AR9285_AN_TOP3_PWDDAC 0x00800000 +#define AR9285_AN_TOP3_PWDDAC_S 23 + +#define AR9285_AN_TOP4 0x7870 +#define AR9285_AN_TOP4_DEFAULT 0x10142c00 + +#endif /* __AR9285_AN_H__ */ diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9285phy.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9285phy.h new file mode 100644 index 0000000000..f823053652 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9285phy.h @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2008-2010 Atheros Communications Inc. + * Copyright (c) 2010-2011 Adrian Chadd, Xenion Pty Ltd. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ +#ifndef __ATH_AR9285PHY_H__ +#define __ATH_AR9285PHY_H__ + +#define AR9285_AN_RF2G1 0x7820 +#define AR9285_AN_RF2G1_ENPACAL 0x00000800 +#define AR9285_AN_RF2G1_ENPACAL_S 11 +#define AR9285_AN_RF2G1_PDPADRV1 0x02000000 +#define AR9285_AN_RF2G1_PDPADRV1_S 25 +#define AR9285_AN_RF2G1_PDPADRV2 0x01000000 +#define AR9285_AN_RF2G1_PDPADRV2_S 24 +#define AR9285_AN_RF2G1_PDPAOUT 0x00800000 +#define AR9285_AN_RF2G1_PDPAOUT_S 23 + +#define AR9285_AN_RF2G2 0x7824 +#define AR9285_AN_RF2G2_OFFCAL 0x00001000 +#define AR9285_AN_RF2G2_OFFCAL_S 12 + +#define AR9285_AN_RF2G3 0x7828 +#define AR9285_AN_RF2G3_PDVCCOMP 0x02000000 +#define AR9285_AN_RF2G3_PDVCCOMP_S 25 +#define AR9285_AN_RF2G3_OB_0 0x00E00000 +#define AR9285_AN_RF2G3_OB_0_S 21 +#define AR9285_AN_RF2G3_OB_1 0x001C0000 +#define AR9285_AN_RF2G3_OB_1_S 18 +#define AR9285_AN_RF2G3_OB_2 0x00038000 +#define AR9285_AN_RF2G3_OB_2_S 15 +#define AR9285_AN_RF2G3_OB_3 0x00007000 +#define AR9285_AN_RF2G3_OB_3_S 12 +#define AR9285_AN_RF2G3_OB_4 0x00000E00 +#define AR9285_AN_RF2G3_OB_4_S 9 + +#define AR9285_AN_RF2G3_DB1_0 0x000001C0 +#define AR9285_AN_RF2G3_DB1_0_S 6 +#define AR9285_AN_RF2G3_DB1_1 0x00000038 +#define AR9285_AN_RF2G3_DB1_1_S 3 +#define AR9285_AN_RF2G3_DB1_2 0x00000007 +#define AR9285_AN_RF2G3_DB1_2_S 0 + +#define AR9285_AN_RF2G4 0x782C +#define AR9285_AN_RF2G4_DB1_3 0xE0000000 +#define AR9285_AN_RF2G4_DB1_3_S 29 +#define AR9285_AN_RF2G4_DB1_4 0x1C000000 +#define AR9285_AN_RF2G4_DB1_4_S 26 + +#define AR9285_AN_RF2G4_DB2_0 0x03800000 +#define AR9285_AN_RF2G4_DB2_0_S 23 +#define AR9285_AN_RF2G4_DB2_1 0x00700000 +#define AR9285_AN_RF2G4_DB2_1_S 20 +#define AR9285_AN_RF2G4_DB2_2 0x000E0000 +#define AR9285_AN_RF2G4_DB2_2_S 17 +#define AR9285_AN_RF2G4_DB2_3 0x0001C000 +#define AR9285_AN_RF2G4_DB2_3_S 14 +#define AR9285_AN_RF2G4_DB2_4 0x00003800 +#define AR9285_AN_RF2G4_DB2_4_S 11 + +#define AR9285_RF2G5 0x7830 +#define AR9285_RF2G5_IC50TX 0xfffff8ff +#define AR9285_RF2G5_IC50TX_SET 0x00000400 +#define AR9285_RF2G5_IC50TX_XE_SET 0x00000500 +#define AR9285_RF2G5_IC50TX_CLEAR 0x00000700 +#define AR9285_RF2G5_IC50TX_CLEAR_S 8 + +#define AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX 0x0007E000 +#define AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX_S 13 +#define AR_PHY_TX_GAIN_CLC 0x0000001E +#define AR_PHY_TX_GAIN_CLC_S 1 +#define AR_PHY_TX_GAIN 0x0007F000 +#define AR_PHY_TX_GAIN_S 12 + +#define AR_PHY_CLC_TBL1 0xa35c +#define AR_PHY_CLC_I0 0x07ff0000 +#define AR_PHY_CLC_I0_S 16 +#define AR_PHY_CLC_Q0 0x0000ffd0 +#define AR_PHY_CLC_Q0_S 5 + +#define AR_PHY_MULTICHAIN_GAIN_CTL 0x99ac +#define AR_PHY_9285_FAST_DIV_BIAS 0x00007E00 +#define AR_PHY_9285_FAST_DIV_BIAS_S 9 +#define AR_PHY_9285_ANT_DIV_CTL_ALL 0x7f000000 +#define AR_PHY_9285_ANT_DIV_CTL 0x01000000 +#define AR_PHY_9285_ANT_DIV_CTL_S 24 +#define AR_PHY_9285_ANT_DIV_ALT_LNACONF 0x06000000 +#define AR_PHY_9285_ANT_DIV_ALT_LNACONF_S 25 +#define AR_PHY_9285_ANT_DIV_MAIN_LNACONF 0x18000000 +#define AR_PHY_9285_ANT_DIV_MAIN_LNACONF_S 27 +#define AR_PHY_9285_ANT_DIV_ALT_GAINTB 0x20000000 +#define AR_PHY_9285_ANT_DIV_ALT_GAINTB_S 29 +#define AR_PHY_9285_ANT_DIV_MAIN_GAINTB 0x40000000 +#define AR_PHY_9285_ANT_DIV_MAIN_GAINTB_S 30 +#define AR_PHY_9285_ANT_DIV_LNA1 2 +#define AR_PHY_9285_ANT_DIV_LNA2 1 +#define AR_PHY_9285_ANT_DIV_LNA1_PLUS_LNA2 3 +#define AR_PHY_9285_ANT_DIV_LNA1_MINUS_LNA2 0 +#define AR_PHY_9285_ANT_DIV_GAINTB_0 0 +#define AR_PHY_9285_ANT_DIV_GAINTB_1 1 + +/* for AR_PHY_CCK_DETECT */ +#define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME 0x00001FC0 +#define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME_S 6 +#define AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV 0x2000 +#define AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV_S 13 + +#endif diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar9285v2.ini b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9285v2.ini similarity index 84% rename from src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar9285v2.ini rename to src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9285v2.ini index 2a9de1dba4..9126dc4fc8 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar5416/ar9285v2.ini +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9285v2.ini @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2010 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -16,7 +16,6 @@ * $FreeBSD$ */ -/* AR9285 v1_2 PCI Register Writes. Created: 04/13/09 */ static const u_int32_t ar9285Modes_v2[][6] = { /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, @@ -78,7 +77,7 @@ static const u_int32_t ar9285Modes_v2[][6] = { { 0x00009a44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000 }, { 0x00009a48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000 }, { 0x00009a4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000 }, - { 0x00009a50, 0x00000000, 0x00000000, 0x00058220, 0x00058220, 0x00000000 }, + { 0x00009a50, 0x00000000, 0x00000000, 0x00058224, 0x00058224, 0x00000000 }, { 0x00009a54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000 }, { 0x00009a58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000 }, { 0x00009a5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000 }, @@ -92,8 +91,8 @@ static const u_int32_t ar9285Modes_v2[][6] = { { 0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 }, { 0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 }, { 0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 }, - { 0x00009a88, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 }, - { 0x00009a8c, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, + { 0x00009a88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00, 0x00000000 }, + { 0x00009a8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 }, { 0x00009a90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, { 0x00009a94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000 }, { 0x00009a98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000 }, @@ -206,7 +205,7 @@ static const u_int32_t ar9285Modes_v2[][6] = { { 0x0000aa44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000 }, { 0x0000aa48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000 }, { 0x0000aa4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000 }, - { 0x0000aa50, 0x00000000, 0x00000000, 0x00058220, 0x00058220, 0x00000000 }, + { 0x0000aa50, 0x00000000, 0x00000000, 0x00058224, 0x00058224, 0x00000000 }, { 0x0000aa54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000 }, { 0x0000aa58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000 }, { 0x0000aa5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000 }, @@ -220,8 +219,8 @@ static const u_int32_t ar9285Modes_v2[][6] = { { 0x0000aa7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 }, { 0x0000aa80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 }, { 0x0000aa84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 }, - { 0x0000aa88, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 }, - { 0x0000aa8c, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, + { 0x0000aa88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00, 0x00000000 }, + { 0x0000aa8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 }, { 0x0000aa90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, { 0x0000aa94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000 }, { 0x0000aa98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000 }, @@ -324,6 +323,7 @@ static const u_int32_t ar9285Modes_v2[][6] = { }; static const u_int32_t ar9285Common_v2[][2] = { + /* Addr allmodes */ { 0x0000000c, 0x00000000 }, { 0x00000030, 0x00020045 }, { 0x00000034, 0x00000005 }, @@ -625,17 +625,12 @@ static const u_int32_t ar9285Common_v2[][2] = { { 0x00007808, 0x54214514 }, { 0x0000780c, 0x02025830 }, { 0x00007810, 0x71c0d388 }, - { 0x00007814, 0x924934a8 }, { 0x0000781c, 0x00000000 }, { 0x00007824, 0x00d86fff }, - { 0x00007828, 0x26d2491b }, { 0x0000782c, 0x6e36d97b }, - { 0x00007830, 0xedb6d96e }, { 0x00007834, 0x71400087 }, - { 0x0000783c, 0x0001fffe }, - { 0x00007840, 0xffeb1a20 }, { 0x00007844, 0x000c0db6 }, - { 0x00007848, 0x6db61b6f }, + { 0x00007848, 0x6db6246f }, { 0x0000784c, 0x6d9b66db }, { 0x00007850, 0x6d8c6dba }, { 0x00007854, 0x00040000 }, @@ -671,7 +666,12 @@ static const u_int32_t ar9285Modes_high_power_tx_gain_v2[][6] = { { 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, { 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, { 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x00007814, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8 }, + { 0x00007828, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b }, + { 0x00007830, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e }, { 0x00007838, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803 }, + { 0x0000783c, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe }, + { 0x00007840, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20 }, { 0x0000786c, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe }, { 0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00 }, { 0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a216652, 0x0a216652, 0x0a22a652 }, @@ -707,7 +707,12 @@ static const u_int32_t ar9285Modes_original_tx_gain_v2[][6] = { { 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, { 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, { 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x00007814, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8 }, + { 0x00007828, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b }, + { 0x00007830, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e }, { 0x00007838, 0xfac68801, 0xfac68801, 0xfac68801, 0xfac68801, 0xfac68801 }, + { 0x0000783c, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe }, + { 0x00007840, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20 }, { 0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4 }, { 0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04 }, { 0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a21a652, 0x0a21a652, 0x0a22a652 }, @@ -719,7 +724,90 @@ static const u_int32_t ar9285Modes_original_tx_gain_v2[][6] = { { 0x0000a3e0, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c }, }; +static const u_int32_t ar9285Modes_XE2_0_normal_power[][6] = { + /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ + { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200, 0x00000000 }, + { 0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208, 0x00000000 }, + { 0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608, 0x00000000 }, + { 0x0000a310, 0x00000000, 0x00000000, 0x00022618, 0x00022618, 0x00000000 }, + { 0x0000a314, 0x00000000, 0x00000000, 0x0002a6c9, 0x0002a6c9, 0x00000000 }, + { 0x0000a318, 0x00000000, 0x00000000, 0x00031710, 0x00031710, 0x00000000 }, + { 0x0000a31c, 0x00000000, 0x00000000, 0x00035718, 0x00035718, 0x00000000 }, + { 0x0000a320, 0x00000000, 0x00000000, 0x00038758, 0x00038758, 0x00000000 }, + { 0x0000a324, 0x00000000, 0x00000000, 0x0003c75a, 0x0003c75a, 0x00000000 }, + { 0x0000a328, 0x00000000, 0x00000000, 0x0004075c, 0x0004075c, 0x00000000 }, + { 0x0000a32c, 0x00000000, 0x00000000, 0x0004475e, 0x0004475e, 0x00000000 }, + { 0x0000a330, 0x00000000, 0x00000000, 0x0004679f, 0x0004679f, 0x00000000 }, + { 0x0000a334, 0x00000000, 0x00000000, 0x000487df, 0x000487df, 0x00000000 }, + { 0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000 }, + { 0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000 }, + { 0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x00007814, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8 }, + { 0x00007828, 0x4ad2491b, 0x4ad2491b, 0x2ad2491b, 0x4ad2491b, 0x4ad2491b }, + { 0x00007830, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6dbae }, + { 0x00007838, 0xdac71441, 0xdac71441, 0xdac71441, 0xdac71441, 0xdac71441 }, + { 0x0000783c, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe }, + { 0x00007840, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c }, + { 0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4 }, + { 0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04 }, + { 0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a21a652, 0x0a21a652, 0x0a22a652 }, + { 0x0000a278, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c }, + { 0x0000a27c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c }, + { 0x0000a394, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c }, + { 0x0000a398, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c }, + { 0x0000a3dc, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c }, + { 0x0000a3e0, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c }, +}; + +static const u_int32_t ar9285Modes_XE2_0_high_power[][6] = { + /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ + { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a304, 0x00000000, 0x00000000, 0x00006200, 0x00006200, 0x00000000 }, + { 0x0000a308, 0x00000000, 0x00000000, 0x00008201, 0x00008201, 0x00000000 }, + { 0x0000a30c, 0x00000000, 0x00000000, 0x0000b240, 0x0000b240, 0x00000000 }, + { 0x0000a310, 0x00000000, 0x00000000, 0x0000d241, 0x0000d241, 0x00000000 }, + { 0x0000a314, 0x00000000, 0x00000000, 0x0000f600, 0x0000f600, 0x00000000 }, + { 0x0000a318, 0x00000000, 0x00000000, 0x00012800, 0x00012800, 0x00000000 }, + { 0x0000a31c, 0x00000000, 0x00000000, 0x00016802, 0x00016802, 0x00000000 }, + { 0x0000a320, 0x00000000, 0x00000000, 0x0001b805, 0x0001b805, 0x00000000 }, + { 0x0000a324, 0x00000000, 0x00000000, 0x00021a80, 0x00021a80, 0x00000000 }, + { 0x0000a328, 0x00000000, 0x00000000, 0x00028b00, 0x00028b00, 0x00000000 }, + { 0x0000a32c, 0x00000000, 0x00000000, 0x0002ab40, 0x0002ab40, 0x00000000 }, + { 0x0000a330, 0x00000000, 0x00000000, 0x0002cd80, 0x0002cd80, 0x00000000 }, + { 0x0000a334, 0x00000000, 0x00000000, 0x00033d82, 0x00033d82, 0x00000000 }, + { 0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000 }, + { 0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000 }, + { 0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x00007814, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8 }, + { 0x00007828, 0x4ad2491b, 0x4ad2491b, 0x2ad2491b, 0x4ad2491b, 0x4ad2491b }, + { 0x00007830, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e }, + { 0x00007838, 0xdac71443, 0xdac71443, 0xdac71443, 0xdac71443, 0xdac71443 }, + { 0x0000783c, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe }, + { 0x00007840, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c }, + { 0x0000786c, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe }, + { 0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00 }, + { 0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a216652, 0x0a216652, 0x0a22a652 }, + { 0x0000a278, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7 }, + { 0x0000a27c, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7 }, + { 0x0000a394, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7 }, + { 0x0000a398, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7 }, + { 0x0000a3dc, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7 }, + { 0x0000a3e0, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7 }, +}; + static const u_int32_t ar9285PciePhy_clkreq_always_on_L1_v2[][2] = { + /* Addr allmodes */ {0x00004040, 0x9248fd00 }, {0x00004040, 0x24924924 }, {0x00004040, 0xa8000019 }, @@ -733,6 +821,7 @@ static const u_int32_t ar9285PciePhy_clkreq_always_on_L1_v2[][2] = { }; static const u_int32_t ar9285PciePhy_clkreq_off_L1_v2[][2] = { + /* Addr allmodes */ {0x00004040, 0x9248fd00 }, {0x00004040, 0x24924924 }, {0x00004040, 0xa8000019 }, diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9287.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9287.c new file mode 100644 index 0000000000..9b874b36bd --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9287.c @@ -0,0 +1,392 @@ +/* + * Copyright (c) 2008-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +/* + * NB: Merlin and later have a simpler RF backend. + */ +#include "ah.h" +#include "ah_internal.h" + +#include "ah_eeprom_v14.h" + +#include "ar9002/ar9287.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" + +#define N(a) (sizeof(a)/sizeof(a[0])) + +struct ar9287State { + RF_HAL_FUNCS base; /* public state, must be first */ + uint16_t pcdacTable[1]; /* XXX */ +}; +#define AR9287(ah) ((struct ar9287State *) AH5212(ah)->ah_rfHal) + +static HAL_BOOL ar9287GetChannelMaxMinPower(struct ath_hal *, + const struct ieee80211_channel *, int16_t *maxPow,int16_t *minPow); +int16_t ar9287GetNfAdjust(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *c); + +static void +ar9287WriteRegs(struct ath_hal *ah, u_int modesIndex, u_int freqIndex, + int writes) +{ + (void) ath_hal_ini_write(ah, &AH5416(ah)->ah_ini_bb_rfgain, + freqIndex, writes); +} + +/* + * Take the MHz channel value and set the Channel value + * + * ASSUMES: Writes enabled to analog bus + * + * Actual Expression, + * + * For 2GHz channel, + * Channel Frequency = (3/4) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^17) + * (freq_ref = 40MHz) + * + * For 5GHz channel, + * Channel Frequency = (3/2) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^10) + * (freq_ref = 40MHz/(24>>amodeRefSel)) + * + * For 5GHz channels which are 5MHz spaced, + * Channel Frequency = (3/2) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^17) + * (freq_ref = 40MHz) + */ +static HAL_BOOL +ar9287SetChannel(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + uint16_t bMode, fracMode, aModeRefSel = 0; + uint32_t freq, ndiv, channelSel = 0, channelFrac = 0, reg32 = 0; + CHAN_CENTERS centers; + uint32_t refDivA = 24; + + OS_MARK(ah, AH_MARK_SETCHANNEL, chan->ic_freq); + + ar5416GetChannelCenters(ah, chan, ¢ers); + freq = centers.synth_center; + + reg32 = OS_REG_READ(ah, AR_PHY_SYNTH_CONTROL); + reg32 &= 0xc0000000; + + if (freq < 4800) { /* 2 GHz, fractional mode */ + uint32_t txctl; + int regWrites = 0; + + bMode = 1; + fracMode = 1; + aModeRefSel = 0; + channelSel = (freq * 0x10000)/15; + + if (AR_SREV_KIWI_11_OR_LATER(ah)) { + if (freq == 2484) { + ath_hal_ini_write(ah, + &AH9287(ah)->ah_ini_cckFirJapan2484, 1, + regWrites); + } else { + ath_hal_ini_write(ah, + &AH9287(ah)->ah_ini_cckFirNormal, 1, + regWrites); + } + } + + txctl = OS_REG_READ(ah, AR_PHY_CCK_TX_CTRL); + if (freq == 2484) { + /* Enable channel spreading for channel 14 */ + OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, + txctl | AR_PHY_CCK_TX_CTRL_JAPAN); + } else { + OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, + txctl &~ AR_PHY_CCK_TX_CTRL_JAPAN); + } + } else { + bMode = 0; + fracMode = 0; + + if ((freq % 20) == 0) { + aModeRefSel = 3; + } else if ((freq % 10) == 0) { + aModeRefSel = 2; + } else { + aModeRefSel = 0; + /* + * Enable 2G (fractional) mode for channels which + * are 5MHz spaced + */ + fracMode = 1; + refDivA = 1; + channelSel = (freq * 0x8000)/15; + + /* RefDivA setting */ + OS_A_REG_RMW_FIELD(ah, AR_AN_SYNTH9, + AR_AN_SYNTH9_REFDIVA, refDivA); + } + if (!fracMode) { + ndiv = (freq * (refDivA >> aModeRefSel))/60; + channelSel = ndiv & 0x1ff; + channelFrac = (ndiv & 0xfffffe00) * 2; + channelSel = (channelSel << 17) | channelFrac; + } + } + + reg32 = reg32 | (bMode << 29) | (fracMode << 28) | + (aModeRefSel << 26) | (channelSel); + + OS_REG_WRITE(ah, AR_PHY_SYNTH_CONTROL, reg32); + + AH_PRIVATE(ah)->ah_curchan = chan; + + return AH_TRUE; +} + +/* + * Return a reference to the requested RF Bank. + */ +static uint32_t * +ar9287GetRfBank(struct ath_hal *ah, int bank) +{ + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown RF Bank %d requested\n", + __func__, bank); + return AH_NULL; +} + +/* + * Reads EEPROM header info from device structure and programs + * all rf registers + */ +static HAL_BOOL +ar9287SetRfRegs(struct ath_hal *ah, const struct ieee80211_channel *chan, + uint16_t modesIndex, uint16_t *rfXpdGain) +{ + return AH_TRUE; /* nothing to do */ +} + +/* + * Read the transmit power levels from the structures taken from EEPROM + * Interpolate read transmit power values for this channel + * Organize the transmit power values into a table for writing into the hardware + */ + +static HAL_BOOL +ar9287SetPowerTable(struct ath_hal *ah, int16_t *pPowerMin, int16_t *pPowerMax, + const struct ieee80211_channel *chan, uint16_t *rfXpdGain) +{ + return AH_TRUE; +} + +#if 0 +static int16_t +ar9287GetMinPower(struct ath_hal *ah, EXPN_DATA_PER_CHANNEL_5112 *data) +{ + int i, minIndex; + int16_t minGain,minPwr,minPcdac,retVal; + + /* Assume NUM_POINTS_XPD0 > 0 */ + minGain = data->pDataPerXPD[0].xpd_gain; + for (minIndex=0,i=1; ipDataPerXPD[i].xpd_gain < minGain) { + minIndex = i; + minGain = data->pDataPerXPD[i].xpd_gain; + } + } + minPwr = data->pDataPerXPD[minIndex].pwr_t4[0]; + minPcdac = data->pDataPerXPD[minIndex].pcdac[0]; + for (i=1; ipDataPerXPD[minIndex].pwr_t4[i] < minPwr) { + minPwr = data->pDataPerXPD[minIndex].pwr_t4[i]; + minPcdac = data->pDataPerXPD[minIndex].pcdac[i]; + } + } + retVal = minPwr - (minPcdac*2); + return(retVal); +} +#endif + +static HAL_BOOL +ar9287GetChannelMaxMinPower(struct ath_hal *ah, + const struct ieee80211_channel *chan, + int16_t *maxPow, int16_t *minPow) +{ +#if 0 + struct ath_hal_5212 *ahp = AH5212(ah); + int numChannels=0,i,last; + int totalD, totalF,totalMin; + EXPN_DATA_PER_CHANNEL_5112 *data=AH_NULL; + EEPROM_POWER_EXPN_5112 *powerArray=AH_NULL; + + *maxPow = 0; + if (IS_CHAN_A(chan)) { + powerArray = ahp->ah_modePowerArray5112; + data = powerArray[headerInfo11A].pDataPerChannel; + numChannels = powerArray[headerInfo11A].numChannels; + } else if (IS_CHAN_G(chan) || IS_CHAN_108G(chan)) { + /* XXX - is this correct? Should we also use the same power for turbo G? */ + powerArray = ahp->ah_modePowerArray5112; + data = powerArray[headerInfo11G].pDataPerChannel; + numChannels = powerArray[headerInfo11G].numChannels; + } else if (IS_CHAN_B(chan)) { + powerArray = ahp->ah_modePowerArray5112; + data = powerArray[headerInfo11B].pDataPerChannel; + numChannels = powerArray[headerInfo11B].numChannels; + } else { + return (AH_TRUE); + } + /* Make sure the channel is in the range of the TP values + * (freq piers) + */ + if ((numChannels < 1) || + (chan->channel < data[0].channelValue) || + (chan->channel > data[numChannels-1].channelValue)) + return(AH_FALSE); + + /* Linearly interpolate the power value now */ + for (last=0,i=0; + (ichannel > data[i].channelValue); + last=i++); + totalD = data[i].channelValue - data[last].channelValue; + if (totalD > 0) { + totalF = data[i].maxPower_t4 - data[last].maxPower_t4; + *maxPow = (int8_t) ((totalF*(chan->channel-data[last].channelValue) + data[last].maxPower_t4*totalD)/totalD); + + totalMin = ar9287GetMinPower(ah,&data[i]) - ar9287GetMinPower(ah, &data[last]); + *minPow = (int8_t) ((totalMin*(chan->channel-data[last].channelValue) + ar9287GetMinPower(ah, &data[last])*totalD)/totalD); + return (AH_TRUE); + } else { + if (chan->channel == data[i].channelValue) { + *maxPow = data[i].maxPower_t4; + *minPow = ar9287GetMinPower(ah, &data[i]); + return(AH_TRUE); + } else + return(AH_FALSE); + } +#else + *maxPow = *minPow = 0; + return AH_FALSE; +#endif +} + +/* + * The ordering of nfarray is thus: + * + * nfarray[0]: Chain 0 ctl + * nfarray[1]: Chain 1 ctl + * nfarray[2]: Chain 2 ctl + * nfarray[3]: Chain 0 ext + * nfarray[4]: Chain 1 ext + * nfarray[5]: Chain 2 ext + */ +static void +ar9287GetNoiseFloor(struct ath_hal *ah, int16_t nfarray[]) +{ + int16_t nf; + + nf = MS(OS_REG_READ(ah, AR_PHY_CCA), AR9280_PHY_MINCCA_PWR); + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + HALDEBUG(ah, HAL_DEBUG_NFCAL, + "NF calibrated [ctl] [chain 0] is %d\n", nf); + nfarray[0] = nf; + + nf = MS(OS_REG_READ(ah, AR_PHY_CH1_CCA), AR9280_PHY_CH1_MINCCA_PWR); + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + HALDEBUG(ah, HAL_DEBUG_NFCAL, + "NF calibrated [ctl] [chain 1] is %d\n", nf); + nfarray[1] = nf; + + nf = MS(OS_REG_READ(ah, AR_PHY_EXT_CCA), AR9280_PHY_EXT_MINCCA_PWR); + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + HALDEBUG(ah, HAL_DEBUG_NFCAL, + "NF calibrated [ext] [chain 0] is %d\n", nf); + nfarray[3] = nf; + + nf = MS(OS_REG_READ(ah, AR_PHY_CH1_EXT_CCA), AR9280_PHY_CH1_EXT_MINCCA_PWR); + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + HALDEBUG(ah, HAL_DEBUG_NFCAL, + "NF calibrated [ext] [chain 1] is %d\n", nf); + nfarray[4] = nf; + + /* Chain 2 - invalid */ + nfarray[2] = 0; + nfarray[5] = 0; + +} + +/* + * Adjust NF based on statistical values for 5GHz frequencies. + * Stubbed:Not used by Fowl + */ +int16_t +ar9287GetNfAdjust(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *c) +{ + return 0; +} + +/* + * Free memory for analog bank scratch buffers + */ +static void +ar9287RfDetach(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + HALASSERT(ahp->ah_rfHal != AH_NULL); + ath_hal_free(ahp->ah_rfHal); + ahp->ah_rfHal = AH_NULL; +} + +HAL_BOOL +ar9287RfAttach(struct ath_hal *ah, HAL_STATUS *status) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + struct ar9287State *priv; + + HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: attach AR9280 radio\n", __func__); + + HALASSERT(ahp->ah_rfHal == AH_NULL); + priv = ath_hal_malloc(sizeof(struct ar9287State)); + if (priv == AH_NULL) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: cannot allocate private state\n", __func__); + *status = HAL_ENOMEM; /* XXX */ + return AH_FALSE; + } + priv->base.rfDetach = ar9287RfDetach; + priv->base.writeRegs = ar9287WriteRegs; + priv->base.getRfBank = ar9287GetRfBank; + priv->base.setChannel = ar9287SetChannel; + priv->base.setRfRegs = ar9287SetRfRegs; + priv->base.setPowerTable = ar9287SetPowerTable; + priv->base.getChannelMaxMinPower = ar9287GetChannelMaxMinPower; + priv->base.getNfAdjust = ar9287GetNfAdjust; + + ahp->ah_pcdacTable = priv->pcdacTable; + ahp->ah_pcdacTableSize = sizeof(priv->pcdacTable); + ahp->ah_rfHal = &priv->base; + /* + * Set noise floor adjust method; we arrange a + * direct call instead of thunking. + */ + AH_PRIVATE(ah)->ah_getNfAdjust = priv->base.getNfAdjust; + AH_PRIVATE(ah)->ah_getNoiseFloor = ar9287GetNoiseFloor; + + return AH_TRUE; +} diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9287.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9287.h new file mode 100644 index 0000000000..90d25ed28f --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9287.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2010 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ + +#ifndef _ATH_AR9287_H_ +#define _ATH_AR9287_H_ + +#include "ar5416/ar5416.h" + +/* + * This is a chip thing, but it's used here as part of the + * ath_hal_9287 struct; so it's convienent to locate the + * define here. + */ +#define AR9287_TX_GAIN_TABLE_SIZE 22 + +struct ath_hal_9287 { + struct ath_hal_5416 ah_5416; + + HAL_INI_ARRAY ah_ini_xmodes; + HAL_INI_ARRAY ah_ini_rxgain; + HAL_INI_ARRAY ah_ini_txgain; + + HAL_INI_ARRAY ah_ini_cckFirNormal; + HAL_INI_ARRAY ah_ini_cckFirJapan2484; + + int PDADCdelta; + + uint32_t originalGain[AR9287_TX_GAIN_TABLE_SIZE]; +}; +#define AH9287(_ah) ((struct ath_hal_9287 *)(_ah)) + +#define AR9287_DEFAULT_RXCHAINMASK 3 +#define AR9285_DEFAULT_RXCHAINMASK 1 +#define AR9287_DEFAULT_TXCHAINMASK 3 +#define AR9285_DEFAULT_TXCHAINMASK 1 + +#define AR_PHY_CCA_NOM_VAL_9287_2GHZ -112 +#define AR_PHY_CCA_NOM_VAL_9287_5GHZ -112 +#define AR_PHY_CCA_MIN_GOOD_VAL_9287_2GHZ -127 +#define AR_PHY_CCA_MIN_GOOD_VAL_9287_5GHZ -122 +#define AR_PHY_CCA_MAX_GOOD_VAL_9287_2GHZ -97 +#define AR_PHY_CCA_MAX_GOOD_VAL_9287_5GHZ -102 + +extern HAL_BOOL ar9287RfAttach(struct ath_hal *, HAL_STATUS *); +extern HAL_BOOL ar9287SetAntennaSwitch(struct ath_hal *, HAL_ANT_SETTING); + +#endif /* _ATH_AR9287_H_ */ diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9287.ini b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9287.ini new file mode 100644 index 0000000000..7f4ca05190 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9287.ini @@ -0,0 +1,783 @@ +/* + * Copyright (c) 2010 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ + +static const uint32_t ar9287Modes_9287_1_1[][6] = { + {0x00001030, 0x00000000, 0x00000000, 0x000002c0, 0x00000160, 0x000001e0}, + {0x00001070, 0x00000000, 0x00000000, 0x00000318, 0x0000018c, 0x000001e0}, + {0x000010b0, 0x00000000, 0x00000000, 0x00007c70, 0x00003e38, 0x00001180}, + {0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008}, + {0x00008014, 0x00000000, 0x00000000, 0x10801600, 0x08400b00, 0x06e006e0}, + {0x0000801c, 0x00000000, 0x00000000, 0x12e00057, 0x12e0002b, 0x0988004f}, + {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810}, + {0x000081d0, 0x00003200, 0x00003200, 0x0000320a, 0x0000320a, 0x0000320a}, + {0x00008318, 0x00000000, 0x00000000, 0x00006880, 0x00003440, 0x00006880}, + {0x00009804, 0x00000000, 0x00000000, 0x000003c4, 0x00000300, 0x00000303}, + {0x00009820, 0x00000000, 0x00000000, 0x02020200, 0x02020200, 0x02020200}, + {0x00009824, 0x00000000, 0x00000000, 0x01000e0e, 0x01000e0e, 0x01000e0e}, + {0x00009828, 0x00000000, 0x00000000, 0x3a020001, 0x3a020001, 0x3a020001}, + {0x00009834, 0x00000000, 0x00000000, 0x00000e0e, 0x00000e0e, 0x00000e0e}, + {0x00009838, 0x00000003, 0x00000003, 0x00000007, 0x00000007, 0x00000007}, + {0x00009840, 0x206a002e, 0x206a002e, 0x206a012e, 0x206a012e, 0x206a012e}, + {0x00009844, 0x03720000, 0x03720000, 0x037216a0, 0x037216a0, 0x037216a0}, + {0x00009850, 0x60000000, 0x60000000, 0x6d4000e2, 0x6c4000e2, 0x6c4000e2}, + {0x00009858, 0x7c000d00, 0x7c000d00, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e}, + {0x0000985c, 0x3100005e, 0x3100005e, 0x3139605e, 0x31395d5e, 0x31395d5e}, + {0x00009860, 0x00058d00, 0x00058d00, 0x00058d20, 0x00058d20, 0x00058d18}, + {0x00009864, 0x00000e00, 0x00000e00, 0x0001ce00, 0x0001ce00, 0x0001ce00}, + {0x00009868, 0x000040c0, 0x000040c0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0}, + {0x0000986c, 0x00000080, 0x00000080, 0x06903881, 0x06903881, 0x06903881}, + {0x00009914, 0x00000000, 0x00000000, 0x00001130, 0x00000898, 0x000007d0}, + {0x00009918, 0x00000000, 0x00000000, 0x00000016, 0x0000000b, 0x00000016}, + {0x00009924, 0xd00a8a01, 0xd00a8a01, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d}, + {0x00009944, 0xefbc0000, 0xefbc0000, 0xefbc1010, 0xefbc1010, 0xefbc1010}, + {0x00009960, 0x00000000, 0x00000000, 0x00000010, 0x00000010, 0x00000010}, + {0x0000a960, 0x00000000, 0x00000000, 0x00000010, 0x00000010, 0x00000010}, + {0x00009964, 0x00000000, 0x00000000, 0x00000210, 0x00000210, 0x00000210}, + {0x0000c968, 0x00000200, 0x00000200, 0x000003ce, 0x000003ce, 0x000003ce}, + {0x000099b8, 0x00000000, 0x00000000, 0x0000001c, 0x0000001c, 0x0000001c}, + {0x000099bc, 0x00000000, 0x00000000, 0x00000c00, 0x00000c00, 0x00000c00}, + {0x000099c0, 0x00000000, 0x00000000, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, + {0x0000a204, 0x00000440, 0x00000440, 0x00000444, 0x00000444, 0x00000444}, + {0x0000a20c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000b20c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a21c, 0x1803800a, 0x1803800a, 0x1883800a, 0x1883800a, 0x1883800a}, + {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000}, + {0x0000a250, 0x00000000, 0x00000000, 0x0004a000, 0x0004a000, 0x0004a000}, + {0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e}, + {0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +}; + +static const uint32_t ar9287Common_9287_1_1[][2] = { + /* Addr allmodes */ + {0x0000000c, 0x00000000}, + {0x00000030, 0x00020015}, + {0x00000034, 0x00000005}, + {0x00000040, 0x00000000}, + {0x00000044, 0x00000008}, + {0x00000048, 0x00000008}, + {0x0000004c, 0x00000010}, + {0x00000050, 0x00000000}, + {0x00000054, 0x0000001f}, + {0x00000800, 0x00000000}, + {0x00000804, 0x00000000}, + {0x00000808, 0x00000000}, + {0x0000080c, 0x00000000}, + {0x00000810, 0x00000000}, + {0x00000814, 0x00000000}, + {0x00000818, 0x00000000}, + {0x0000081c, 0x00000000}, + {0x00000820, 0x00000000}, + {0x00000824, 0x00000000}, + {0x00001040, 0x002ffc0f}, + {0x00001044, 0x002ffc0f}, + {0x00001048, 0x002ffc0f}, + {0x0000104c, 0x002ffc0f}, + {0x00001050, 0x002ffc0f}, + {0x00001054, 0x002ffc0f}, + {0x00001058, 0x002ffc0f}, + {0x0000105c, 0x002ffc0f}, + {0x00001060, 0x002ffc0f}, + {0x00001064, 0x002ffc0f}, + {0x00001230, 0x00000000}, + {0x00001270, 0x00000000}, + {0x00001038, 0x00000000}, + {0x00001078, 0x00000000}, + {0x000010b8, 0x00000000}, + {0x000010f8, 0x00000000}, + {0x00001138, 0x00000000}, + {0x00001178, 0x00000000}, + {0x000011b8, 0x00000000}, + {0x000011f8, 0x00000000}, + {0x00001238, 0x00000000}, + {0x00001278, 0x00000000}, + {0x000012b8, 0x00000000}, + {0x000012f8, 0x00000000}, + {0x00001338, 0x00000000}, + {0x00001378, 0x00000000}, + {0x000013b8, 0x00000000}, + {0x000013f8, 0x00000000}, + {0x00001438, 0x00000000}, + {0x00001478, 0x00000000}, + {0x000014b8, 0x00000000}, + {0x000014f8, 0x00000000}, + {0x00001538, 0x00000000}, + {0x00001578, 0x00000000}, + {0x000015b8, 0x00000000}, + {0x000015f8, 0x00000000}, + {0x00001638, 0x00000000}, + {0x00001678, 0x00000000}, + {0x000016b8, 0x00000000}, + {0x000016f8, 0x00000000}, + {0x00001738, 0x00000000}, + {0x00001778, 0x00000000}, + {0x000017b8, 0x00000000}, + {0x000017f8, 0x00000000}, + {0x0000103c, 0x00000000}, + {0x0000107c, 0x00000000}, + {0x000010bc, 0x00000000}, + {0x000010fc, 0x00000000}, + {0x0000113c, 0x00000000}, + {0x0000117c, 0x00000000}, + {0x000011bc, 0x00000000}, + {0x000011fc, 0x00000000}, + {0x0000123c, 0x00000000}, + {0x0000127c, 0x00000000}, + {0x000012bc, 0x00000000}, + {0x000012fc, 0x00000000}, + {0x0000133c, 0x00000000}, + {0x0000137c, 0x00000000}, + {0x000013bc, 0x00000000}, + {0x000013fc, 0x00000000}, + {0x0000143c, 0x00000000}, + {0x0000147c, 0x00000000}, + {0x00004030, 0x00000002}, + {0x0000403c, 0x00000002}, + {0x00004024, 0x0000001f}, + {0x00004060, 0x00000000}, + {0x00004064, 0x00000000}, + {0x00007010, 0x00000033}, + {0x00007020, 0x00000000}, + {0x00007034, 0x00000002}, + {0x00007038, 0x000004c2}, + {0x00008004, 0x00000000}, + {0x00008008, 0x00000000}, + {0x0000800c, 0x00000000}, + {0x00008018, 0x00000700}, + {0x00008020, 0x00000000}, + {0x00008038, 0x00000000}, + {0x0000803c, 0x00000000}, + {0x00008048, 0x40000000}, + {0x00008054, 0x00000000}, + {0x00008058, 0x00000000}, + {0x0000805c, 0x000fc78f}, + {0x00008060, 0x0000000f}, + {0x00008064, 0x00000000}, + {0x00008070, 0x00000000}, + {0x000080c0, 0x2a80001a}, + {0x000080c4, 0x05dc01e0}, + {0x000080c8, 0x1f402710}, + {0x000080cc, 0x01f40000}, + {0x000080d0, 0x00001e00}, + {0x000080d4, 0x00000000}, + {0x000080d8, 0x00400000}, + {0x000080e0, 0xffffffff}, + {0x000080e4, 0x0000ffff}, + {0x000080e8, 0x003f3f3f}, + {0x000080ec, 0x00000000}, + {0x000080f0, 0x00000000}, + {0x000080f4, 0x00000000}, + {0x000080f8, 0x00000000}, + {0x000080fc, 0x00020000}, + {0x00008100, 0x00020000}, + {0x00008104, 0x00000001}, + {0x00008108, 0x00000052}, + {0x0000810c, 0x00000000}, + {0x00008110, 0x00000168}, + {0x00008118, 0x000100aa}, + {0x0000811c, 0x00003210}, + {0x00008124, 0x00000000}, + {0x00008128, 0x00000000}, + {0x0000812c, 0x00000000}, + {0x00008130, 0x00000000}, + {0x00008134, 0x00000000}, + {0x00008138, 0x00000000}, + {0x0000813c, 0x00000000}, + {0x00008144, 0xffffffff}, + {0x00008168, 0x00000000}, + {0x0000816c, 0x00000000}, + {0x00008170, 0x18487320}, + {0x00008174, 0xfaa4fa50}, + {0x00008178, 0x00000100}, + {0x0000817c, 0x00000000}, + {0x000081c0, 0x00000000}, + {0x000081c4, 0x00000000}, + {0x000081d4, 0x00000000}, + {0x000081ec, 0x00000000}, + {0x000081f0, 0x00000000}, + {0x000081f4, 0x00000000}, + {0x000081f8, 0x00000000}, + {0x000081fc, 0x00000000}, + {0x00008200, 0x00000000}, + {0x00008204, 0x00000000}, + {0x00008208, 0x00000000}, + {0x0000820c, 0x00000000}, + {0x00008210, 0x00000000}, + {0x00008214, 0x00000000}, + {0x00008218, 0x00000000}, + {0x0000821c, 0x00000000}, + {0x00008220, 0x00000000}, + {0x00008224, 0x00000000}, + {0x00008228, 0x00000000}, + {0x0000822c, 0x00000000}, + {0x00008230, 0x00000000}, + {0x00008234, 0x00000000}, + {0x00008238, 0x00000000}, + {0x0000823c, 0x00000000}, + {0x00008240, 0x00100000}, + {0x00008244, 0x0010f400}, + {0x00008248, 0x00000100}, + {0x0000824c, 0x0001e800}, + {0x00008250, 0x00000000}, + {0x00008254, 0x00000000}, + {0x00008258, 0x00000000}, + {0x0000825c, 0x400000ff}, + {0x00008260, 0x00080922}, + {0x00008264, 0x88a00010}, + {0x00008270, 0x00000000}, + {0x00008274, 0x40000000}, + {0x00008278, 0x003e4180}, + {0x0000827c, 0x00000000}, + {0x00008284, 0x0000002c}, + {0x00008288, 0x0000002c}, + {0x0000828c, 0x000000ff}, + {0x00008294, 0x00000000}, + {0x00008298, 0x00000000}, + {0x0000829c, 0x00000000}, + {0x00008300, 0x00000040}, + {0x00008314, 0x00000000}, + {0x00008328, 0x00000000}, + {0x0000832c, 0x00000007}, + {0x00008330, 0x00000302}, + {0x00008334, 0x00000e00}, + {0x00008338, 0x00ff0000}, + {0x0000833c, 0x00000000}, + {0x00008340, 0x000107ff}, + {0x00008344, 0x01c81043}, + {0x00008360, 0xffffffff}, + {0x00008364, 0xffffffff}, + {0x00008368, 0x00000000}, + {0x00008370, 0x00000000}, + {0x00008374, 0x000000ff}, + {0x00008378, 0x00000000}, + {0x0000837c, 0x00000000}, + {0x00008380, 0xffffffff}, + {0x00008384, 0xffffffff}, + {0x00008390, 0x0fffffff}, + {0x00008394, 0x0fffffff}, + {0x00008398, 0x00000000}, + {0x0000839c, 0x00000000}, + {0x000083a0, 0x00000000}, + {0x00009808, 0x00000000}, + {0x0000980c, 0xafe68e30}, + {0x00009810, 0xfd14e000}, + {0x00009814, 0x9c0a9f6b}, + {0x0000981c, 0x00000000}, + {0x0000982c, 0x0000a000}, + {0x00009830, 0x00000000}, + {0x0000983c, 0x00200400}, + {0x0000984c, 0x0040233c}, + {0x0000a84c, 0x0040233c}, + {0x00009854, 0x00000044}, + {0x00009900, 0x00000000}, + {0x00009904, 0x00000000}, + {0x00009908, 0x00000000}, + {0x0000990c, 0x00000000}, + {0x00009910, 0x10002310}, + {0x0000991c, 0x10000fff}, + {0x00009920, 0x04900000}, + {0x0000a920, 0x04900000}, + {0x00009928, 0x00000001}, + {0x0000992c, 0x00000004}, + {0x00009930, 0x00000000}, + {0x0000a930, 0x00000000}, + {0x00009934, 0x1e1f2022}, + {0x00009938, 0x0a0b0c0d}, + {0x0000993c, 0x00000000}, + {0x00009948, 0x9280c00a}, + {0x0000994c, 0x00020028}, + {0x00009954, 0x5f3ca3de}, + {0x00009958, 0x0108ecff}, + {0x00009940, 0x14750604}, + {0x0000c95c, 0x004b6a8e}, + {0x00009970, 0x990bb514}, + {0x00009974, 0x00000000}, + {0x00009978, 0x00000001}, + {0x0000997c, 0x00000000}, + {0x000099a0, 0x00000000}, + {0x000099a4, 0x00000001}, + {0x000099a8, 0x201fff00}, + {0x000099ac, 0x0c6f0000}, + {0x000099b0, 0x03051000}, + {0x000099b4, 0x00000820}, + {0x000099c4, 0x06336f77}, + {0x000099c8, 0x6af6532f}, + {0x000099cc, 0x08f186c8}, + {0x000099d0, 0x00046384}, + {0x000099dc, 0x00000000}, + {0x000099e0, 0x00000000}, + {0x000099e4, 0xaaaaaaaa}, + {0x000099e8, 0x3c466478}, + {0x000099ec, 0x0cc80caa}, + {0x000099f0, 0x00000000}, + {0x000099fc, 0x00001042}, + {0x0000a208, 0x803e4788}, + {0x0000a210, 0x4080a333}, + {0x0000a214, 0x40206c10}, + {0x0000a218, 0x009c4060}, + {0x0000a220, 0x01834061}, + {0x0000a224, 0x00000400}, + {0x0000a228, 0x000003b5}, + {0x0000a22c, 0x233f7180}, + {0x0000a234, 0x20202020}, + {0x0000a238, 0x20202020}, + {0x0000a23c, 0x13c889af}, + {0x0000a240, 0x38490a20}, + {0x0000a244, 0x00000000}, + {0x0000a248, 0xfffffffc}, + {0x0000a24c, 0x00000000}, + {0x0000a254, 0x00000000}, + {0x0000a258, 0x0cdbd380}, + {0x0000a25c, 0x0f0f0f01}, + {0x0000a260, 0xdfa91f01}, + {0x0000a264, 0x00418a11}, + {0x0000b264, 0x00418a11}, + {0x0000a268, 0x00000000}, + {0x0000a26c, 0x0e79e5c6}, + {0x0000b26c, 0x0e79e5c6}, + {0x0000d270, 0x00820820}, + {0x0000a278, 0x1ce739ce}, + {0x0000a27c, 0x050701ce}, + {0x0000d35c, 0x07ffffef}, + {0x0000d360, 0x0fffffe7}, + {0x0000d364, 0x17ffffe5}, + {0x0000d368, 0x1fffffe4}, + {0x0000d36c, 0x37ffffe3}, + {0x0000d370, 0x3fffffe3}, + {0x0000d374, 0x57ffffe3}, + {0x0000d378, 0x5fffffe2}, + {0x0000d37c, 0x7fffffe2}, + {0x0000d380, 0x7f3c7bba}, + {0x0000d384, 0xf3307ff0}, + {0x0000a388, 0x0c000000}, + {0x0000a38c, 0x20202020}, + {0x0000a390, 0x20202020}, + {0x0000a394, 0x1ce739ce}, + {0x0000a398, 0x000001ce}, + {0x0000b398, 0x000001ce}, + {0x0000a39c, 0x00000001}, + {0x0000a3c8, 0x00000246}, + {0x0000a3cc, 0x20202020}, + {0x0000a3d0, 0x20202020}, + {0x0000a3d4, 0x20202020}, + {0x0000a3dc, 0x1ce739ce}, + {0x0000a3e0, 0x000001ce}, + {0x0000a3e4, 0x00000000}, + {0x0000a3e8, 0x18c43433}, + {0x0000a3ec, 0x00f70081}, + {0x0000a3f0, 0x01036a1e}, + {0x0000a3f4, 0x00000000}, + {0x0000b3f4, 0x00000000}, + {0x0000a7d8, 0x000003f1}, + {0x00007800, 0x00000800}, + {0x00007804, 0x6c35ffd2}, + {0x00007808, 0x6db6c000}, + {0x0000780c, 0x6db6cb30}, + {0x00007810, 0x6db6cb6c}, + {0x00007814, 0x0501e200}, + {0x00007818, 0x0094128d}, + {0x0000781c, 0x976ee392}, + {0x00007820, 0xf75ff6fc}, + {0x00007824, 0x00040000}, + {0x00007828, 0xdb003012}, + {0x0000782c, 0x04924914}, + {0x00007830, 0x21084210}, + {0x00007834, 0x00140000}, + {0x00007838, 0x0e4548d8}, + {0x0000783c, 0x54214514}, + {0x00007840, 0x02025830}, + {0x00007844, 0x71c0d388}, + {0x00007848, 0x934934a8}, + {0x00007850, 0x00000000}, + {0x00007854, 0x00000800}, + {0x00007858, 0x6c35ffd2}, + {0x0000785c, 0x6db6c000}, + {0x00007860, 0x6db6cb30}, + {0x00007864, 0x6db6cb6c}, + {0x00007868, 0x0501e200}, + {0x0000786c, 0x0094128d}, + {0x00007870, 0x976ee392}, + {0x00007874, 0xf75ff6fc}, + {0x00007878, 0x00040000}, + {0x0000787c, 0xdb003012}, + {0x00007880, 0x04924914}, + {0x00007884, 0x21084210}, + {0x00007888, 0x001b6db0}, + {0x0000788c, 0x00376b63}, + {0x00007890, 0x06db6db6}, + {0x00007894, 0x006d8000}, + {0x00007898, 0x48100000}, + {0x0000789c, 0x00000000}, + {0x000078a0, 0x08000000}, + {0x000078a4, 0x0007ffd8}, + {0x000078a8, 0x0007ffd8}, + {0x000078ac, 0x001c0020}, + {0x000078b0, 0x00060aeb}, + {0x000078b4, 0x40008080}, + {0x000078b8, 0x2a850160}, +}; + +static const uint32_t ar9287Common_normal_cck_fir_coeff_9287_1_1[][2] = { + /* Addr allmodes */ + {0x0000a1f4, 0x00fffeff}, + {0x0000a1f8, 0x00f5f9ff}, + {0x0000a1fc, 0xb79f6427}, +}; + +static const uint32_t ar9287Common_japan_2484_cck_fir_coeff_9287_1_1[][2] = { + /* Addr allmodes */ + {0x0000a1f4, 0x00000000}, + {0x0000a1f8, 0xefff0301}, + {0x0000a1fc, 0xca9228ee}, +}; + +static const uint32_t ar9287Modes_tx_gain_9287_1_1[][6] = { + {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a304, 0x00000000, 0x00000000, 0x00004002, 0x00004002, 0x00004002}, + {0x0000a308, 0x00000000, 0x00000000, 0x00008004, 0x00008004, 0x00008004}, + {0x0000a30c, 0x00000000, 0x00000000, 0x0000c00a, 0x0000c00a, 0x0000c00a}, + {0x0000a310, 0x00000000, 0x00000000, 0x0001000c, 0x0001000c, 0x0001000c}, + {0x0000a314, 0x00000000, 0x00000000, 0x0001420b, 0x0001420b, 0x0001420b}, + {0x0000a318, 0x00000000, 0x00000000, 0x0001824a, 0x0001824a, 0x0001824a}, + {0x0000a31c, 0x00000000, 0x00000000, 0x0001c44a, 0x0001c44a, 0x0001c44a}, + {0x0000a320, 0x00000000, 0x00000000, 0x0002064a, 0x0002064a, 0x0002064a}, + {0x0000a324, 0x00000000, 0x00000000, 0x0002484a, 0x0002484a, 0x0002484a}, + {0x0000a328, 0x00000000, 0x00000000, 0x00028a4a, 0x00028a4a, 0x00028a4a}, + {0x0000a32c, 0x00000000, 0x00000000, 0x0002cc4a, 0x0002cc4a, 0x0002cc4a}, + {0x0000a330, 0x00000000, 0x00000000, 0x00030e4a, 0x00030e4a, 0x00030e4a}, + {0x0000a334, 0x00000000, 0x00000000, 0x00034e8a, 0x00034e8a, 0x00034e8a}, + {0x0000a338, 0x00000000, 0x00000000, 0x00038e8c, 0x00038e8c, 0x00038e8c}, + {0x0000a33c, 0x00000000, 0x00000000, 0x0003cecc, 0x0003cecc, 0x0003cecc}, + {0x0000a340, 0x00000000, 0x00000000, 0x00040ed4, 0x00040ed4, 0x00040ed4}, + {0x0000a344, 0x00000000, 0x00000000, 0x00044edc, 0x00044edc, 0x00044edc}, + {0x0000a348, 0x00000000, 0x00000000, 0x00048ede, 0x00048ede, 0x00048ede}, + {0x0000a34c, 0x00000000, 0x00000000, 0x0004cf1e, 0x0004cf1e, 0x0004cf1e}, + {0x0000a350, 0x00000000, 0x00000000, 0x00050f5e, 0x00050f5e, 0x00050f5e}, + {0x0000a354, 0x00000000, 0x00000000, 0x00054f9e, 0x00054f9e, 0x00054f9e}, + {0x0000a780, 0x00000000, 0x00000000, 0x00000062, 0x00000062, 0x00000062}, + {0x0000a784, 0x00000000, 0x00000000, 0x00004064, 0x00004064, 0x00004064}, + {0x0000a788, 0x00000000, 0x00000000, 0x000080a4, 0x000080a4, 0x000080a4}, + {0x0000a78c, 0x00000000, 0x00000000, 0x0000c0aa, 0x0000c0aa, 0x0000c0aa}, + {0x0000a790, 0x00000000, 0x00000000, 0x000100ac, 0x000100ac, 0x000100ac}, + {0x0000a794, 0x00000000, 0x00000000, 0x000140b4, 0x000140b4, 0x000140b4}, + {0x0000a798, 0x00000000, 0x00000000, 0x000180f4, 0x000180f4, 0x000180f4}, + {0x0000a79c, 0x00000000, 0x00000000, 0x0001c134, 0x0001c134, 0x0001c134}, + {0x0000a7a0, 0x00000000, 0x00000000, 0x00020174, 0x00020174, 0x00020174}, + {0x0000a7a4, 0x00000000, 0x00000000, 0x0002417c, 0x0002417c, 0x0002417c}, + {0x0000a7a8, 0x00000000, 0x00000000, 0x0002817e, 0x0002817e, 0x0002817e}, + {0x0000a7ac, 0x00000000, 0x00000000, 0x0002c1be, 0x0002c1be, 0x0002c1be}, + {0x0000a7b0, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe}, + {0x0000a7b4, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe}, + {0x0000a7b8, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe}, + {0x0000a7bc, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe}, + {0x0000a7c0, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe}, + {0x0000a7c4, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe}, + {0x0000a7c8, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe}, + {0x0000a7cc, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe}, + {0x0000a7d0, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe}, + {0x0000a7d4, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe}, + {0x0000a274, 0x0a180000, 0x0a180000, 0x0a1aa000, 0x0a1aa000, 0x0a1aa000}, +}; + +static const uint32_t ar9287Modes_rx_gain_9287_1_1[][6] = { + {0x00009a00, 0x00000000, 0x00000000, 0x0000a120, 0x0000a120, 0x0000a120}, + {0x00009a04, 0x00000000, 0x00000000, 0x0000a124, 0x0000a124, 0x0000a124}, + {0x00009a08, 0x00000000, 0x00000000, 0x0000a128, 0x0000a128, 0x0000a128}, + {0x00009a0c, 0x00000000, 0x00000000, 0x0000a12c, 0x0000a12c, 0x0000a12c}, + {0x00009a10, 0x00000000, 0x00000000, 0x0000a130, 0x0000a130, 0x0000a130}, + {0x00009a14, 0x00000000, 0x00000000, 0x0000a194, 0x0000a194, 0x0000a194}, + {0x00009a18, 0x00000000, 0x00000000, 0x0000a198, 0x0000a198, 0x0000a198}, + {0x00009a1c, 0x00000000, 0x00000000, 0x0000a20c, 0x0000a20c, 0x0000a20c}, + {0x00009a20, 0x00000000, 0x00000000, 0x0000a210, 0x0000a210, 0x0000a210}, + {0x00009a24, 0x00000000, 0x00000000, 0x0000a284, 0x0000a284, 0x0000a284}, + {0x00009a28, 0x00000000, 0x00000000, 0x0000a288, 0x0000a288, 0x0000a288}, + {0x00009a2c, 0x00000000, 0x00000000, 0x0000a28c, 0x0000a28c, 0x0000a28c}, + {0x00009a30, 0x00000000, 0x00000000, 0x0000a290, 0x0000a290, 0x0000a290}, + {0x00009a34, 0x00000000, 0x00000000, 0x0000a294, 0x0000a294, 0x0000a294}, + {0x00009a38, 0x00000000, 0x00000000, 0x0000a2a0, 0x0000a2a0, 0x0000a2a0}, + {0x00009a3c, 0x00000000, 0x00000000, 0x0000a2a4, 0x0000a2a4, 0x0000a2a4}, + {0x00009a40, 0x00000000, 0x00000000, 0x0000a2a8, 0x0000a2a8, 0x0000a2a8}, + {0x00009a44, 0x00000000, 0x00000000, 0x0000a2ac, 0x0000a2ac, 0x0000a2ac}, + {0x00009a48, 0x00000000, 0x00000000, 0x0000a2b0, 0x0000a2b0, 0x0000a2b0}, + {0x00009a4c, 0x00000000, 0x00000000, 0x0000a2b4, 0x0000a2b4, 0x0000a2b4}, + {0x00009a50, 0x00000000, 0x00000000, 0x0000a2b8, 0x0000a2b8, 0x0000a2b8}, + {0x00009a54, 0x00000000, 0x00000000, 0x0000a2c4, 0x0000a2c4, 0x0000a2c4}, + {0x00009a58, 0x00000000, 0x00000000, 0x0000a708, 0x0000a708, 0x0000a708}, + {0x00009a5c, 0x00000000, 0x00000000, 0x0000a70c, 0x0000a70c, 0x0000a70c}, + {0x00009a60, 0x00000000, 0x00000000, 0x0000a710, 0x0000a710, 0x0000a710}, + {0x00009a64, 0x00000000, 0x00000000, 0x0000ab04, 0x0000ab04, 0x0000ab04}, + {0x00009a68, 0x00000000, 0x00000000, 0x0000ab08, 0x0000ab08, 0x0000ab08}, + {0x00009a6c, 0x00000000, 0x00000000, 0x0000ab0c, 0x0000ab0c, 0x0000ab0c}, + {0x00009a70, 0x00000000, 0x00000000, 0x0000ab10, 0x0000ab10, 0x0000ab10}, + {0x00009a74, 0x00000000, 0x00000000, 0x0000ab14, 0x0000ab14, 0x0000ab14}, + {0x00009a78, 0x00000000, 0x00000000, 0x0000ab18, 0x0000ab18, 0x0000ab18}, + {0x00009a7c, 0x00000000, 0x00000000, 0x0000ab8c, 0x0000ab8c, 0x0000ab8c}, + {0x00009a80, 0x00000000, 0x00000000, 0x0000ab90, 0x0000ab90, 0x0000ab90}, + {0x00009a84, 0x00000000, 0x00000000, 0x0000ab94, 0x0000ab94, 0x0000ab94}, + {0x00009a88, 0x00000000, 0x00000000, 0x0000ab98, 0x0000ab98, 0x0000ab98}, + {0x00009a8c, 0x00000000, 0x00000000, 0x0000aba4, 0x0000aba4, 0x0000aba4}, + {0x00009a90, 0x00000000, 0x00000000, 0x0000aba8, 0x0000aba8, 0x0000aba8}, + {0x00009a94, 0x00000000, 0x00000000, 0x0000cb04, 0x0000cb04, 0x0000cb04}, + {0x00009a98, 0x00000000, 0x00000000, 0x0000cb08, 0x0000cb08, 0x0000cb08}, + {0x00009a9c, 0x00000000, 0x00000000, 0x0000cb0c, 0x0000cb0c, 0x0000cb0c}, + {0x00009aa0, 0x00000000, 0x00000000, 0x0000cb10, 0x0000cb10, 0x0000cb10}, + {0x00009aa4, 0x00000000, 0x00000000, 0x0000cb14, 0x0000cb14, 0x0000cb14}, + {0x00009aa8, 0x00000000, 0x00000000, 0x0000cb18, 0x0000cb18, 0x0000cb18}, + {0x00009aac, 0x00000000, 0x00000000, 0x0000cb8c, 0x0000cb8c, 0x0000cb8c}, + {0x00009ab0, 0x00000000, 0x00000000, 0x0000cb90, 0x0000cb90, 0x0000cb90}, + {0x00009ab4, 0x00000000, 0x00000000, 0x0000cf18, 0x0000cf18, 0x0000cf18}, + {0x00009ab8, 0x00000000, 0x00000000, 0x0000cf24, 0x0000cf24, 0x0000cf24}, + {0x00009abc, 0x00000000, 0x00000000, 0x0000cf28, 0x0000cf28, 0x0000cf28}, + {0x00009ac0, 0x00000000, 0x00000000, 0x0000d314, 0x0000d314, 0x0000d314}, + {0x00009ac4, 0x00000000, 0x00000000, 0x0000d318, 0x0000d318, 0x0000d318}, + {0x00009ac8, 0x00000000, 0x00000000, 0x0000d38c, 0x0000d38c, 0x0000d38c}, + {0x00009acc, 0x00000000, 0x00000000, 0x0000d390, 0x0000d390, 0x0000d390}, + {0x00009ad0, 0x00000000, 0x00000000, 0x0000d394, 0x0000d394, 0x0000d394}, + {0x00009ad4, 0x00000000, 0x00000000, 0x0000d398, 0x0000d398, 0x0000d398}, + {0x00009ad8, 0x00000000, 0x00000000, 0x0000d3a4, 0x0000d3a4, 0x0000d3a4}, + {0x00009adc, 0x00000000, 0x00000000, 0x0000d3a8, 0x0000d3a8, 0x0000d3a8}, + {0x00009ae0, 0x00000000, 0x00000000, 0x0000d3ac, 0x0000d3ac, 0x0000d3ac}, + {0x00009ae4, 0x00000000, 0x00000000, 0x0000d3b0, 0x0000d3b0, 0x0000d3b0}, + {0x00009ae8, 0x00000000, 0x00000000, 0x0000f380, 0x0000f380, 0x0000f380}, + {0x00009aec, 0x00000000, 0x00000000, 0x0000f384, 0x0000f384, 0x0000f384}, + {0x00009af0, 0x00000000, 0x00000000, 0x0000f388, 0x0000f388, 0x0000f388}, + {0x00009af4, 0x00000000, 0x00000000, 0x0000f710, 0x0000f710, 0x0000f710}, + {0x00009af8, 0x00000000, 0x00000000, 0x0000f714, 0x0000f714, 0x0000f714}, + {0x00009afc, 0x00000000, 0x00000000, 0x0000f718, 0x0000f718, 0x0000f718}, + {0x00009b00, 0x00000000, 0x00000000, 0x0000fb10, 0x0000fb10, 0x0000fb10}, + {0x00009b04, 0x00000000, 0x00000000, 0x0000fb14, 0x0000fb14, 0x0000fb14}, + {0x00009b08, 0x00000000, 0x00000000, 0x0000fb18, 0x0000fb18, 0x0000fb18}, + {0x00009b0c, 0x00000000, 0x00000000, 0x0000fb8c, 0x0000fb8c, 0x0000fb8c}, + {0x00009b10, 0x00000000, 0x00000000, 0x0000fb90, 0x0000fb90, 0x0000fb90}, + {0x00009b14, 0x00000000, 0x00000000, 0x0000fb94, 0x0000fb94, 0x0000fb94}, + {0x00009b18, 0x00000000, 0x00000000, 0x0000ff8c, 0x0000ff8c, 0x0000ff8c}, + {0x00009b1c, 0x00000000, 0x00000000, 0x0000ff90, 0x0000ff90, 0x0000ff90}, + {0x00009b20, 0x00000000, 0x00000000, 0x0000ff94, 0x0000ff94, 0x0000ff94}, + {0x00009b24, 0x00000000, 0x00000000, 0x0000ffa0, 0x0000ffa0, 0x0000ffa0}, + {0x00009b28, 0x00000000, 0x00000000, 0x0000ffa4, 0x0000ffa4, 0x0000ffa4}, + {0x00009b2c, 0x00000000, 0x00000000, 0x0000ffa8, 0x0000ffa8, 0x0000ffa8}, + {0x00009b30, 0x00000000, 0x00000000, 0x0000ffac, 0x0000ffac, 0x0000ffac}, + {0x00009b34, 0x00000000, 0x00000000, 0x0000ffb0, 0x0000ffb0, 0x0000ffb0}, + {0x00009b38, 0x00000000, 0x00000000, 0x0000ffb4, 0x0000ffb4, 0x0000ffb4}, + {0x00009b3c, 0x00000000, 0x00000000, 0x0000ffa1, 0x0000ffa1, 0x0000ffa1}, + {0x00009b40, 0x00000000, 0x00000000, 0x0000ffa5, 0x0000ffa5, 0x0000ffa5}, + {0x00009b44, 0x00000000, 0x00000000, 0x0000ffa9, 0x0000ffa9, 0x0000ffa9}, + {0x00009b48, 0x00000000, 0x00000000, 0x0000ffad, 0x0000ffad, 0x0000ffad}, + {0x00009b4c, 0x00000000, 0x00000000, 0x0000ffb1, 0x0000ffb1, 0x0000ffb1}, + {0x00009b50, 0x00000000, 0x00000000, 0x0000ffb5, 0x0000ffb5, 0x0000ffb5}, + {0x00009b54, 0x00000000, 0x00000000, 0x0000ffb9, 0x0000ffb9, 0x0000ffb9}, + {0x00009b58, 0x00000000, 0x00000000, 0x0000ffc5, 0x0000ffc5, 0x0000ffc5}, + {0x00009b5c, 0x00000000, 0x00000000, 0x0000ffc9, 0x0000ffc9, 0x0000ffc9}, + {0x00009b60, 0x00000000, 0x00000000, 0x0000ffcd, 0x0000ffcd, 0x0000ffcd}, + {0x00009b64, 0x00000000, 0x00000000, 0x0000ffd1, 0x0000ffd1, 0x0000ffd1}, + {0x00009b68, 0x00000000, 0x00000000, 0x0000ffd5, 0x0000ffd5, 0x0000ffd5}, + {0x00009b6c, 0x00000000, 0x00000000, 0x0000ffc2, 0x0000ffc2, 0x0000ffc2}, + {0x00009b70, 0x00000000, 0x00000000, 0x0000ffc6, 0x0000ffc6, 0x0000ffc6}, + {0x00009b74, 0x00000000, 0x00000000, 0x0000ffca, 0x0000ffca, 0x0000ffca}, + {0x00009b78, 0x00000000, 0x00000000, 0x0000ffce, 0x0000ffce, 0x0000ffce}, + {0x00009b7c, 0x00000000, 0x00000000, 0x0000ffd2, 0x0000ffd2, 0x0000ffd2}, + {0x00009b80, 0x00000000, 0x00000000, 0x0000ffd6, 0x0000ffd6, 0x0000ffd6}, + {0x00009b84, 0x00000000, 0x00000000, 0x0000ffda, 0x0000ffda, 0x0000ffda}, + {0x00009b88, 0x00000000, 0x00000000, 0x0000ffc7, 0x0000ffc7, 0x0000ffc7}, + {0x00009b8c, 0x00000000, 0x00000000, 0x0000ffcb, 0x0000ffcb, 0x0000ffcb}, + {0x00009b90, 0x00000000, 0x00000000, 0x0000ffcf, 0x0000ffcf, 0x0000ffcf}, + {0x00009b94, 0x00000000, 0x00000000, 0x0000ffd3, 0x0000ffd3, 0x0000ffd3}, + {0x00009b98, 0x00000000, 0x00000000, 0x0000ffd7, 0x0000ffd7, 0x0000ffd7}, + {0x00009b9c, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009ba0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009ba4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009ba8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009bac, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009bb0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009bb4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009bb8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009bbc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009bc0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009bc4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009bc8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009bcc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009bd0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009bd4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009bd8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009bdc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009be0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009be4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009be8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009bec, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009bf0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009bf4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009bf8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009bfc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000aa00, 0x00000000, 0x00000000, 0x0000a120, 0x0000a120, 0x0000a120}, + {0x0000aa04, 0x00000000, 0x00000000, 0x0000a124, 0x0000a124, 0x0000a124}, + {0x0000aa08, 0x00000000, 0x00000000, 0x0000a128, 0x0000a128, 0x0000a128}, + {0x0000aa0c, 0x00000000, 0x00000000, 0x0000a12c, 0x0000a12c, 0x0000a12c}, + {0x0000aa10, 0x00000000, 0x00000000, 0x0000a130, 0x0000a130, 0x0000a130}, + {0x0000aa14, 0x00000000, 0x00000000, 0x0000a194, 0x0000a194, 0x0000a194}, + {0x0000aa18, 0x00000000, 0x00000000, 0x0000a198, 0x0000a198, 0x0000a198}, + {0x0000aa1c, 0x00000000, 0x00000000, 0x0000a20c, 0x0000a20c, 0x0000a20c}, + {0x0000aa20, 0x00000000, 0x00000000, 0x0000a210, 0x0000a210, 0x0000a210}, + {0x0000aa24, 0x00000000, 0x00000000, 0x0000a284, 0x0000a284, 0x0000a284}, + {0x0000aa28, 0x00000000, 0x00000000, 0x0000a288, 0x0000a288, 0x0000a288}, + {0x0000aa2c, 0x00000000, 0x00000000, 0x0000a28c, 0x0000a28c, 0x0000a28c}, + {0x0000aa30, 0x00000000, 0x00000000, 0x0000a290, 0x0000a290, 0x0000a290}, + {0x0000aa34, 0x00000000, 0x00000000, 0x0000a294, 0x0000a294, 0x0000a294}, + {0x0000aa38, 0x00000000, 0x00000000, 0x0000a2a0, 0x0000a2a0, 0x0000a2a0}, + {0x0000aa3c, 0x00000000, 0x00000000, 0x0000a2a4, 0x0000a2a4, 0x0000a2a4}, + {0x0000aa40, 0x00000000, 0x00000000, 0x0000a2a8, 0x0000a2a8, 0x0000a2a8}, + {0x0000aa44, 0x00000000, 0x00000000, 0x0000a2ac, 0x0000a2ac, 0x0000a2ac}, + {0x0000aa48, 0x00000000, 0x00000000, 0x0000a2b0, 0x0000a2b0, 0x0000a2b0}, + {0x0000aa4c, 0x00000000, 0x00000000, 0x0000a2b4, 0x0000a2b4, 0x0000a2b4}, + {0x0000aa50, 0x00000000, 0x00000000, 0x0000a2b8, 0x0000a2b8, 0x0000a2b8}, + {0x0000aa54, 0x00000000, 0x00000000, 0x0000a2c4, 0x0000a2c4, 0x0000a2c4}, + {0x0000aa58, 0x00000000, 0x00000000, 0x0000a708, 0x0000a708, 0x0000a708}, + {0x0000aa5c, 0x00000000, 0x00000000, 0x0000a70c, 0x0000a70c, 0x0000a70c}, + {0x0000aa60, 0x00000000, 0x00000000, 0x0000a710, 0x0000a710, 0x0000a710}, + {0x0000aa64, 0x00000000, 0x00000000, 0x0000ab04, 0x0000ab04, 0x0000ab04}, + {0x0000aa68, 0x00000000, 0x00000000, 0x0000ab08, 0x0000ab08, 0x0000ab08}, + {0x0000aa6c, 0x00000000, 0x00000000, 0x0000ab0c, 0x0000ab0c, 0x0000ab0c}, + {0x0000aa70, 0x00000000, 0x00000000, 0x0000ab10, 0x0000ab10, 0x0000ab10}, + {0x0000aa74, 0x00000000, 0x00000000, 0x0000ab14, 0x0000ab14, 0x0000ab14}, + {0x0000aa78, 0x00000000, 0x00000000, 0x0000ab18, 0x0000ab18, 0x0000ab18}, + {0x0000aa7c, 0x00000000, 0x00000000, 0x0000ab8c, 0x0000ab8c, 0x0000ab8c}, + {0x0000aa80, 0x00000000, 0x00000000, 0x0000ab90, 0x0000ab90, 0x0000ab90}, + {0x0000aa84, 0x00000000, 0x00000000, 0x0000ab94, 0x0000ab94, 0x0000ab94}, + {0x0000aa88, 0x00000000, 0x00000000, 0x0000ab98, 0x0000ab98, 0x0000ab98}, + {0x0000aa8c, 0x00000000, 0x00000000, 0x0000aba4, 0x0000aba4, 0x0000aba4}, + {0x0000aa90, 0x00000000, 0x00000000, 0x0000aba8, 0x0000aba8, 0x0000aba8}, + {0x0000aa94, 0x00000000, 0x00000000, 0x0000cb04, 0x0000cb04, 0x0000cb04}, + {0x0000aa98, 0x00000000, 0x00000000, 0x0000cb08, 0x0000cb08, 0x0000cb08}, + {0x0000aa9c, 0x00000000, 0x00000000, 0x0000cb0c, 0x0000cb0c, 0x0000cb0c}, + {0x0000aaa0, 0x00000000, 0x00000000, 0x0000cb10, 0x0000cb10, 0x0000cb10}, + {0x0000aaa4, 0x00000000, 0x00000000, 0x0000cb14, 0x0000cb14, 0x0000cb14}, + {0x0000aaa8, 0x00000000, 0x00000000, 0x0000cb18, 0x0000cb18, 0x0000cb18}, + {0x0000aaac, 0x00000000, 0x00000000, 0x0000cb8c, 0x0000cb8c, 0x0000cb8c}, + {0x0000aab0, 0x00000000, 0x00000000, 0x0000cb90, 0x0000cb90, 0x0000cb90}, + {0x0000aab4, 0x00000000, 0x00000000, 0x0000cf18, 0x0000cf18, 0x0000cf18}, + {0x0000aab8, 0x00000000, 0x00000000, 0x0000cf24, 0x0000cf24, 0x0000cf24}, + {0x0000aabc, 0x00000000, 0x00000000, 0x0000cf28, 0x0000cf28, 0x0000cf28}, + {0x0000aac0, 0x00000000, 0x00000000, 0x0000d314, 0x0000d314, 0x0000d314}, + {0x0000aac4, 0x00000000, 0x00000000, 0x0000d318, 0x0000d318, 0x0000d318}, + {0x0000aac8, 0x00000000, 0x00000000, 0x0000d38c, 0x0000d38c, 0x0000d38c}, + {0x0000aacc, 0x00000000, 0x00000000, 0x0000d390, 0x0000d390, 0x0000d390}, + {0x0000aad0, 0x00000000, 0x00000000, 0x0000d394, 0x0000d394, 0x0000d394}, + {0x0000aad4, 0x00000000, 0x00000000, 0x0000d398, 0x0000d398, 0x0000d398}, + {0x0000aad8, 0x00000000, 0x00000000, 0x0000d3a4, 0x0000d3a4, 0x0000d3a4}, + {0x0000aadc, 0x00000000, 0x00000000, 0x0000d3a8, 0x0000d3a8, 0x0000d3a8}, + {0x0000aae0, 0x00000000, 0x00000000, 0x0000d3ac, 0x0000d3ac, 0x0000d3ac}, + {0x0000aae4, 0x00000000, 0x00000000, 0x0000d3b0, 0x0000d3b0, 0x0000d3b0}, + {0x0000aae8, 0x00000000, 0x00000000, 0x0000f380, 0x0000f380, 0x0000f380}, + {0x0000aaec, 0x00000000, 0x00000000, 0x0000f384, 0x0000f384, 0x0000f384}, + {0x0000aaf0, 0x00000000, 0x00000000, 0x0000f388, 0x0000f388, 0x0000f388}, + {0x0000aaf4, 0x00000000, 0x00000000, 0x0000f710, 0x0000f710, 0x0000f710}, + {0x0000aaf8, 0x00000000, 0x00000000, 0x0000f714, 0x0000f714, 0x0000f714}, + {0x0000aafc, 0x00000000, 0x00000000, 0x0000f718, 0x0000f718, 0x0000f718}, + {0x0000ab00, 0x00000000, 0x00000000, 0x0000fb10, 0x0000fb10, 0x0000fb10}, + {0x0000ab04, 0x00000000, 0x00000000, 0x0000fb14, 0x0000fb14, 0x0000fb14}, + {0x0000ab08, 0x00000000, 0x00000000, 0x0000fb18, 0x0000fb18, 0x0000fb18}, + {0x0000ab0c, 0x00000000, 0x00000000, 0x0000fb8c, 0x0000fb8c, 0x0000fb8c}, + {0x0000ab10, 0x00000000, 0x00000000, 0x0000fb90, 0x0000fb90, 0x0000fb90}, + {0x0000ab14, 0x00000000, 0x00000000, 0x0000fb94, 0x0000fb94, 0x0000fb94}, + {0x0000ab18, 0x00000000, 0x00000000, 0x0000ff8c, 0x0000ff8c, 0x0000ff8c}, + {0x0000ab1c, 0x00000000, 0x00000000, 0x0000ff90, 0x0000ff90, 0x0000ff90}, + {0x0000ab20, 0x00000000, 0x00000000, 0x0000ff94, 0x0000ff94, 0x0000ff94}, + {0x0000ab24, 0x00000000, 0x00000000, 0x0000ffa0, 0x0000ffa0, 0x0000ffa0}, + {0x0000ab28, 0x00000000, 0x00000000, 0x0000ffa4, 0x0000ffa4, 0x0000ffa4}, + {0x0000ab2c, 0x00000000, 0x00000000, 0x0000ffa8, 0x0000ffa8, 0x0000ffa8}, + {0x0000ab30, 0x00000000, 0x00000000, 0x0000ffac, 0x0000ffac, 0x0000ffac}, + {0x0000ab34, 0x00000000, 0x00000000, 0x0000ffb0, 0x0000ffb0, 0x0000ffb0}, + {0x0000ab38, 0x00000000, 0x00000000, 0x0000ffb4, 0x0000ffb4, 0x0000ffb4}, + {0x0000ab3c, 0x00000000, 0x00000000, 0x0000ffa1, 0x0000ffa1, 0x0000ffa1}, + {0x0000ab40, 0x00000000, 0x00000000, 0x0000ffa5, 0x0000ffa5, 0x0000ffa5}, + {0x0000ab44, 0x00000000, 0x00000000, 0x0000ffa9, 0x0000ffa9, 0x0000ffa9}, + {0x0000ab48, 0x00000000, 0x00000000, 0x0000ffad, 0x0000ffad, 0x0000ffad}, + {0x0000ab4c, 0x00000000, 0x00000000, 0x0000ffb1, 0x0000ffb1, 0x0000ffb1}, + {0x0000ab50, 0x00000000, 0x00000000, 0x0000ffb5, 0x0000ffb5, 0x0000ffb5}, + {0x0000ab54, 0x00000000, 0x00000000, 0x0000ffb9, 0x0000ffb9, 0x0000ffb9}, + {0x0000ab58, 0x00000000, 0x00000000, 0x0000ffc5, 0x0000ffc5, 0x0000ffc5}, + {0x0000ab5c, 0x00000000, 0x00000000, 0x0000ffc9, 0x0000ffc9, 0x0000ffc9}, + {0x0000ab60, 0x00000000, 0x00000000, 0x0000ffcd, 0x0000ffcd, 0x0000ffcd}, + {0x0000ab64, 0x00000000, 0x00000000, 0x0000ffd1, 0x0000ffd1, 0x0000ffd1}, + {0x0000ab68, 0x00000000, 0x00000000, 0x0000ffd5, 0x0000ffd5, 0x0000ffd5}, + {0x0000ab6c, 0x00000000, 0x00000000, 0x0000ffc2, 0x0000ffc2, 0x0000ffc2}, + {0x0000ab70, 0x00000000, 0x00000000, 0x0000ffc6, 0x0000ffc6, 0x0000ffc6}, + {0x0000ab74, 0x00000000, 0x00000000, 0x0000ffca, 0x0000ffca, 0x0000ffca}, + {0x0000ab78, 0x00000000, 0x00000000, 0x0000ffce, 0x0000ffce, 0x0000ffce}, + {0x0000ab7c, 0x00000000, 0x00000000, 0x0000ffd2, 0x0000ffd2, 0x0000ffd2}, + {0x0000ab80, 0x00000000, 0x00000000, 0x0000ffd6, 0x0000ffd6, 0x0000ffd6}, + {0x0000ab84, 0x00000000, 0x00000000, 0x0000ffda, 0x0000ffda, 0x0000ffda}, + {0x0000ab88, 0x00000000, 0x00000000, 0x0000ffc7, 0x0000ffc7, 0x0000ffc7}, + {0x0000ab8c, 0x00000000, 0x00000000, 0x0000ffcb, 0x0000ffcb, 0x0000ffcb}, + {0x0000ab90, 0x00000000, 0x00000000, 0x0000ffcf, 0x0000ffcf, 0x0000ffcf}, + {0x0000ab94, 0x00000000, 0x00000000, 0x0000ffd3, 0x0000ffd3, 0x0000ffd3}, + {0x0000ab98, 0x00000000, 0x00000000, 0x0000ffd7, 0x0000ffd7, 0x0000ffd7}, + {0x0000ab9c, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000aba0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000aba4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000aba8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abac, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abb0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abb4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abb8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abbc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abc0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abc4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abc8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abcc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abd0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abd4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abd8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abdc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abe0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abe4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abe8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abec, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abf0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abf4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abf8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abfc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009848, 0x00000000, 0x00000000, 0x00001067, 0x00001067, 0x00001067}, + {0x0000a848, 0x00000000, 0x00000000, 0x00001067, 0x00001067, 0x00001067}, +}; + +static const uint32_t ar9287PciePhy_clkreq_always_on_L1_9287_1_1[][2] = { + /* Addr allmodes */ + {0x00004040, 0x9248fd00}, + {0x00004040, 0x24924924}, + {0x00004040, 0xa8000019}, + {0x00004040, 0x13160820}, + {0x00004040, 0xe5980560}, + {0x00004040, 0xc01dcffd}, + {0x00004040, 0x1aaabe41}, + {0x00004040, 0xbe105554}, + {0x00004040, 0x00043007}, + {0x00004044, 0x00000000}, +}; + +static const uint32_t ar9287PciePhy_clkreq_off_L1_9287_1_1[][2] = { + /* Addr allmodes */ + {0x00004040, 0x9248fd00}, + {0x00004040, 0x24924924}, + {0x00004040, 0xa8000019}, + {0x00004040, 0x13160820}, + {0x00004040, 0xe5980560}, + {0x00004040, 0xc01dcffc}, + {0x00004040, 0x1aaabe41}, + {0x00004040, 0xbe105554}, + {0x00004040, 0x00043007}, + {0x00004044, 0x00000000}, +}; diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9287_attach.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9287_attach.c new file mode 100644 index 0000000000..78400f52f9 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9287_attach.c @@ -0,0 +1,479 @@ +/* + * Copyright (c) 2008-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" + +#include "ah_eeprom_v14.h" /* XXX for tx/rx gain */ +#include "ah_eeprom_9287.h" + +#include "ar9002/ar9280.h" +#include "ar9002/ar9287.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" + +#include "ar9002/ar9287_cal.h" +#include "ar9002/ar9287_reset.h" +#include "ar9002/ar9287_olc.h" + +#include "ar9002/ar9287.ini" + +static const HAL_PERCAL_DATA ar9287_iq_cal = { /* single sample */ + .calName = "IQ", .calType = IQ_MISMATCH_CAL, + .calNumSamples = MIN_CAL_SAMPLES, + .calCountMax = PER_MAX_LOG_COUNT, + .calCollect = ar5416IQCalCollect, + .calPostProc = ar5416IQCalibration +}; +static const HAL_PERCAL_DATA ar9287_adc_gain_cal = { /* single sample */ + .calName = "ADC Gain", .calType = ADC_GAIN_CAL, + .calNumSamples = MIN_CAL_SAMPLES, + .calCountMax = PER_MIN_LOG_COUNT, + .calCollect = ar5416AdcGainCalCollect, + .calPostProc = ar5416AdcGainCalibration +}; +static const HAL_PERCAL_DATA ar9287_adc_dc_cal = { /* single sample */ + .calName = "ADC DC", .calType = ADC_DC_CAL, + .calNumSamples = MIN_CAL_SAMPLES, + .calCountMax = PER_MIN_LOG_COUNT, + .calCollect = ar5416AdcDcCalCollect, + .calPostProc = ar5416AdcDcCalibration +}; +static const HAL_PERCAL_DATA ar9287_adc_init_dc_cal = { + .calName = "ADC Init DC", .calType = ADC_DC_INIT_CAL, + .calNumSamples = MIN_CAL_SAMPLES, + .calCountMax = INIT_LOG_COUNT, + .calCollect = ar5416AdcDcCalCollect, + .calPostProc = ar5416AdcDcCalibration +}; + +static void ar9287ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore); +static HAL_BOOL ar9287FillCapabilityInfo(struct ath_hal *ah); +static void ar9287WriteIni(struct ath_hal *ah, + const struct ieee80211_channel *chan); + +static void +ar9287AniSetup(struct ath_hal *ah) +{ + /* + * These are the parameters from the AR5416 ANI code; + * they likely need quite a bit of adjustment for the + * AR9280. + */ + static const struct ar5212AniParams aniparams = { + .maxNoiseImmunityLevel = 4, /* levels 0..4 */ + .totalSizeDesired = { -55, -55, -55, -55, -62 }, + .coarseHigh = { -14, -14, -14, -14, -12 }, + .coarseLow = { -64, -64, -64, -64, -70 }, + .firpwr = { -78, -78, -78, -78, -80 }, + .maxSpurImmunityLevel = 2, + .cycPwrThr1 = { 2, 4, 6 }, + .maxFirstepLevel = 2, /* levels 0..2 */ + .firstep = { 0, 4, 8 }, + .ofdmTrigHigh = 500, + .ofdmTrigLow = 200, + .cckTrigHigh = 200, + .cckTrigLow = 100, + .rssiThrHigh = 40, + .rssiThrLow = 7, + .period = 100, + }; + /* NB: disable ANI noise immmunity for reliable RIFS rx */ + AH5416(ah)->ah_ani_function &= ~ HAL_ANI_NOISE_IMMUNITY_LEVEL; + + /* NB: ANI is not enabled yet */ + ar5416AniAttach(ah, &aniparams, &aniparams, AH_TRUE); +} + +/* + * Attach for an AR9287 part. + */ +static struct ath_hal * +ar9287Attach(uint16_t devid, HAL_SOFTC sc, + HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata, + HAL_STATUS *status) +{ + struct ath_hal_9287 *ahp9287; + struct ath_hal_5212 *ahp; + struct ath_hal *ah; + uint32_t val; + HAL_STATUS ecode; + HAL_BOOL rfStatus; + int8_t pwr_table_offset; + + HALDEBUG_G(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", + __func__, sc, (void*) st, (void*) sh); + + /* NB: memory is returned zero'd */ + ahp9287 = ath_hal_malloc(sizeof (struct ath_hal_9287)); + if (ahp9287 == AH_NULL) { + HALDEBUG_G(AH_NULL, HAL_DEBUG_ANY, + "%s: cannot allocate memory for state block\n", __func__); + *status = HAL_ENOMEM; + return AH_NULL; + } + ahp = AH5212(ahp9287); + ah = &ahp->ah_priv.h; + + ar5416InitState(AH5416(ah), devid, sc, st, sh, status); + + /* XXX override with 9280 specific state */ + /* override 5416 methods for our needs */ + AH5416(ah)->ah_initPLL = ar9280InitPLL; + + ah->ah_setAntennaSwitch = ar9287SetAntennaSwitch; + ah->ah_configPCIE = ar9287ConfigPCIE; + + AH5416(ah)->ah_cal.iqCalData.calData = &ar9287_iq_cal; + AH5416(ah)->ah_cal.adcGainCalData.calData = &ar9287_adc_gain_cal; + AH5416(ah)->ah_cal.adcDcCalData.calData = &ar9287_adc_dc_cal; + AH5416(ah)->ah_cal.adcDcCalInitData.calData = &ar9287_adc_init_dc_cal; + /* Better performance without ADC Gain Calibration */ + AH5416(ah)->ah_cal.suppCals = ADC_DC_CAL | IQ_MISMATCH_CAL; + + AH5416(ah)->ah_spurMitigate = ar9280SpurMitigate; + AH5416(ah)->ah_writeIni = ar9287WriteIni; + + ah->ah_setTxPower = ar9287SetTransmitPower; + ah->ah_setBoardValues = ar9287SetBoardValues; + + AH5416(ah)->ah_olcInit = ar9287olcInit; + AH5416(ah)->ah_olcTempCompensation = ar9287olcTemperatureCompensation; + //AH5416(ah)->ah_setPowerCalTable = ar9287SetPowerCalTable; + AH5416(ah)->ah_cal_initcal = ar9287InitCalHardware; + AH5416(ah)->ah_cal_pacal = ar9287PACal; + + /* XXX NF calibration */ + /* XXX Ini override? (IFS vars - since the kiwi mac clock is faster?) */ + /* XXX what else is kiwi-specific in the radio/calibration pathway? */ + + AH5416(ah)->ah_rx_chainmask = AR9287_DEFAULT_RXCHAINMASK; + AH5416(ah)->ah_tx_chainmask = AR9287_DEFAULT_TXCHAINMASK; + + if (!ar5416SetResetReg(ah, HAL_RESET_POWER_ON)) { + /* reset chip */ + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't reset chip\n", + __func__); + ecode = HAL_EIO; + goto bad; + } + + if (!ar5416SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't wakeup chip\n", + __func__); + ecode = HAL_EIO; + goto bad; + } + /* Read Revisions from Chips before taking out of reset */ + val = OS_REG_READ(ah, AR_SREV); + HALDEBUG(ah, HAL_DEBUG_ATTACH, + "%s: ID 0x%x VERSION 0x%x TYPE 0x%x REVISION 0x%x\n", + __func__, MS(val, AR_XSREV_ID), MS(val, AR_XSREV_VERSION), + MS(val, AR_XSREV_TYPE), MS(val, AR_XSREV_REVISION)); + /* NB: include chip type to differentiate from pre-Sowl versions */ + AH_PRIVATE(ah)->ah_macVersion = + (val & AR_XSREV_VERSION) >> AR_XSREV_TYPE_S; + AH_PRIVATE(ah)->ah_macRev = MS(val, AR_XSREV_REVISION); + AH_PRIVATE(ah)->ah_ispcie = (val & AR_XSREV_TYPE_HOST_MODE) == 0; + + /* Don't support Kiwi < 1.2; those are pre-release chips */ + if (! AR_SREV_KIWI_12_OR_LATER(ah)) { + ath_hal_printf(ah, "[ath]: Kiwi < 1.2 is not supported\n"); + ecode = HAL_EIO; + goto bad; + } + + /* setup common ini data; rf backends handle remainder */ + HAL_INI_INIT(&ahp->ah_ini_modes, ar9287Modes_9287_1_1, 6); + HAL_INI_INIT(&ahp->ah_ini_common, ar9287Common_9287_1_1, 2); + + /* If pcie_clock_req */ + HAL_INI_INIT(&AH5416(ah)->ah_ini_pcieserdes, + ar9287PciePhy_clkreq_always_on_L1_9287_1_1, 2); + + /* XXX WoW ini values */ + + /* Else */ +#if 0 + HAL_INI_INIT(&AH5416(ah)->ah_ini_pcieserdes, + ar9287PciePhy_clkreq_off_L1_9287_1_1, 2); +#endif + + /* Initialise Japan arrays */ + HAL_INI_INIT(&ahp9287->ah_ini_cckFirNormal, + ar9287Common_normal_cck_fir_coeff_9287_1_1, 2); + HAL_INI_INIT(&ahp9287->ah_ini_cckFirJapan2484, + ar9287Common_japan_2484_cck_fir_coeff_9287_1_1, 2); + + ar5416AttachPCIE(ah); + + ecode = ath_hal_9287EepromAttach(ah); + if (ecode != HAL_OK) + goto bad; + + if (!ar5416ChipReset(ah, AH_NULL)) { /* reset chip */ + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__); + ecode = HAL_EIO; + goto bad; + } + + AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIP_ID); + + if (!ar5212ChipTest(ah)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: hardware self-test failed\n", + __func__); + ecode = HAL_ESELFTEST; + goto bad; + } + + /* + * Set correct Baseband to analog shift + * setting to access analog chips. + */ + OS_REG_WRITE(ah, AR_PHY(0), 0x00000007); + + /* Read Radio Chip Rev Extract */ + AH_PRIVATE(ah)->ah_analog5GhzRev = ar5416GetRadioRev(ah); + switch (AH_PRIVATE(ah)->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) { + case AR_RAD2133_SREV_MAJOR: /* Sowl: 2G/3x3 */ + case AR_RAD5133_SREV_MAJOR: /* Sowl: 2+5G/3x3 */ + break; + default: + if (AH_PRIVATE(ah)->ah_analog5GhzRev == 0) { + AH_PRIVATE(ah)->ah_analog5GhzRev = + AR_RAD5133_SREV_MAJOR; + break; + } +#ifdef AH_DEBUG + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: 5G Radio Chip Rev 0x%02X is not supported by " + "this driver\n", __func__, + AH_PRIVATE(ah)->ah_analog5GhzRev); + ecode = HAL_ENOTSUPP; + goto bad; +#endif + } + rfStatus = ar9287RfAttach(ah, &ecode); + if (!rfStatus) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RF setup failed, status %u\n", + __func__, ecode); + goto bad; + } + + /* + * We only implement open-loop TX power control + * for the AR9287 in this codebase. + */ + if (! ath_hal_eepromGetFlag(ah, AR_EEP_OL_PWRCTRL)) { + ath_hal_printf(ah, "[ath] AR9287 w/ closed-loop TX power control" + " isn't supported.\n"); + ecode = HAL_ENOTSUPP; + goto bad; + } + + /* + * Check whether the power table offset isn't the default. + * This can occur with eeprom minor V21 or greater on Merlin. + */ + (void) ath_hal_eepromGet(ah, AR_EEP_PWR_TABLE_OFFSET, &pwr_table_offset); + if (pwr_table_offset != AR5416_PWR_TABLE_OFFSET_DB) + ath_hal_printf(ah, "[ath]: default pwr offset: %d dBm != EEPROM pwr offset: %d dBm; curves will be adjusted.\n", + AR5416_PWR_TABLE_OFFSET_DB, (int) pwr_table_offset); + + /* setup rxgain table */ + HAL_INI_INIT(&ahp9287->ah_ini_rxgain, ar9287Modes_rx_gain_9287_1_1, 6); + + /* setup txgain table */ + HAL_INI_INIT(&ahp9287->ah_ini_txgain, ar9287Modes_tx_gain_9287_1_1, 6); + + /* + * Got everything we need now to setup the capabilities. + */ + if (!ar9287FillCapabilityInfo(ah)) { + ecode = HAL_EEREAD; + goto bad; + } + + ecode = ath_hal_eepromGet(ah, AR_EEP_MACADDR, ahp->ah_macaddr); + if (ecode != HAL_OK) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: error getting mac address from EEPROM\n", __func__); + goto bad; + } + /* XXX How about the serial number ? */ + /* Read Reg Domain */ + AH_PRIVATE(ah)->ah_currentRD = + ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, AH_NULL); + AH_PRIVATE(ah)->ah_currentRDext = AR9287_RDEXT_DEFAULT; + + /* + * ah_miscMode is populated by ar5416FillCapabilityInfo() + * starting from griffin. Set here to make sure that + * AR_MISC_MODE_MIC_NEW_LOC_ENABLE is set before a GTK is + * placed into hardware. + */ + if (ahp->ah_miscMode != 0) + OS_REG_WRITE(ah, AR_MISC_MODE, OS_REG_READ(ah, AR_MISC_MODE) | ahp->ah_miscMode); + + ar9287AniSetup(ah); /* Anti Noise Immunity */ + + /* Setup noise floor min/max/nominal values */ + AH5416(ah)->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9287_2GHZ; + AH5416(ah)->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_9287_2GHZ; + AH5416(ah)->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9287_2GHZ; + AH5416(ah)->nf_5g.max = AR_PHY_CCA_MAX_GOOD_VAL_9287_5GHZ; + AH5416(ah)->nf_5g.min = AR_PHY_CCA_MIN_GOOD_VAL_9287_5GHZ; + AH5416(ah)->nf_5g.nominal = AR_PHY_CCA_NOM_VAL_9287_5GHZ; + + ar5416InitNfHistBuff(AH5416(ah)->ah_cal.nfCalHist); + + HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__); + + return ah; +bad: + if (ah != AH_NULL) + ah->ah_detach(ah); + if (status) + *status = ecode; + return AH_NULL; +} + +static void +ar9287ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore) +{ + if (AH_PRIVATE(ah)->ah_ispcie && !restore) { + ath_hal_ini_write(ah, &AH5416(ah)->ah_ini_pcieserdes, 1, 0); + OS_DELAY(1000); + OS_REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA); + OS_REG_WRITE(ah, AR_WA, AR9285_WA_DEFAULT); /* Yes, Kiwi uses the Kite PCIe PHY WA */ + } +} + +static void +ar9287WriteIni(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + u_int modesIndex, freqIndex; + int regWrites = 0; + + /* Setup the indices for the next set of register array writes */ + /* XXX Ignore 11n dynamic mode on the AR5416 for the moment */ + if (IEEE80211_IS_CHAN_2GHZ(chan)) { + freqIndex = 2; + if (IEEE80211_IS_CHAN_HT40(chan)) + modesIndex = 3; + else if (IEEE80211_IS_CHAN_108G(chan)) + modesIndex = 5; + else + modesIndex = 4; + } else { + freqIndex = 1; + if (IEEE80211_IS_CHAN_HT40(chan) || + IEEE80211_IS_CHAN_TURBO(chan)) + modesIndex = 2; + else + modesIndex = 1; + } + + /* Set correct Baseband to analog shift setting to access analog chips. */ + OS_REG_WRITE(ah, AR_PHY(0), 0x00000007); + OS_REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC); + + regWrites = ath_hal_ini_write(ah, &AH5212(ah)->ah_ini_modes, modesIndex, regWrites); + regWrites = ath_hal_ini_write(ah, &AH9287(ah)->ah_ini_rxgain, modesIndex, regWrites); + regWrites = ath_hal_ini_write(ah, &AH9287(ah)->ah_ini_txgain, modesIndex, regWrites); + regWrites = ath_hal_ini_write(ah, &AH5212(ah)->ah_ini_common, 1, regWrites); +} + +#define AR_BASE_FREQ_2GHZ 2300 +#define AR_BASE_FREQ_5GHZ 4900 +#define AR_SPUR_FEEQ_BOUND_HT40 19 +#define AR_SPUR_FEEQ_BOUND_HT20 10 + + + +/* + * Fill all software cached or static hardware state information. + * Return failure if capabilities are to come from EEPROM and + * cannot be read. + */ +static HAL_BOOL +ar9287FillCapabilityInfo(struct ath_hal *ah) +{ + HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; + + if (!ar5416FillCapabilityInfo(ah)) + return AH_FALSE; + pCap->halNumGpioPins = 10; + pCap->halWowSupport = AH_TRUE; + pCap->halWowMatchPatternExact = AH_TRUE; +#if 0 + pCap->halWowMatchPatternDword = AH_TRUE; +#endif + + pCap->halCSTSupport = AH_TRUE; + pCap->halRifsRxSupport = AH_TRUE; + pCap->halRifsTxSupport = AH_TRUE; + pCap->halRtsAggrLimit = 64*1024; /* 802.11n max */ + pCap->halExtChanDfsSupport = AH_TRUE; + pCap->halUseCombinedRadarRssi = AH_TRUE; +#if 0 + /* XXX bluetooth */ + pCap->halBtCoexSupport = AH_TRUE; +#endif + pCap->halAutoSleepSupport = AH_FALSE; /* XXX? */ + pCap->hal4kbSplitTransSupport = AH_FALSE; + /* Disable this so Block-ACK works correctly */ + pCap->halHasRxSelfLinkedTail = AH_FALSE; + pCap->halPSPollBroken = AH_FALSE; + + /* Hardware supports (at least) single-stream STBC TX/RX */ + pCap->halRxStbcSupport = 1; + pCap->halTxStbcSupport = 1; + + /* Hardware supports short-GI w/ 20MHz */ + pCap->halHTSGI20Support = 1; + + pCap->halEnhancedDfsSupport = AH_TRUE; + + return AH_TRUE; +} + +/* + * This has been disabled - having the HAL flip chainmasks on/off + * when attempting to implement 11n disrupts things. For now, just + * leave this flipped off and worry about implementing TX diversity + * for legacy and MCS0-7 when 11n is fully functioning. + */ +HAL_BOOL +ar9287SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING settings) +{ + return AH_TRUE; +} + +static const char* +ar9287Probe(uint16_t vendorid, uint16_t devid) +{ + if (vendorid == ATHEROS_VENDOR_ID && + (devid == AR9287_DEVID_PCI || devid == AR9287_DEVID_PCIE)) + return "Atheros 9287"; + return AH_NULL; +} +AH_CHIP(AR9287, ar9287Probe, ar9287Attach); diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9287_cal.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9287_cal.c new file mode 100644 index 0000000000..d5024b0623 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9287_cal.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2008-2010 Atheros Communications Inc. + * Copyright (c) 2011 Adrian Chadd, Xenion Pty Ltd. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" +#include "ah.h" +#include "ah_internal.h" + +#include "ah_eeprom_v4k.h" + +#include "ar9002/ar9285.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" +#include "ar9002/ar9002phy.h" +//#include "ar9002/ar9287phy.h" + +#include "ar9002/ar9287_cal.h" + + +void +ar9287PACal(struct ath_hal *ah, HAL_BOOL is_reset) +{ + /* XXX not required */ +} + +/* + * This is like Merlin but without ADC disable + */ +HAL_BOOL +ar9287InitCalHardware(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); + + /* Calibrate the AGC */ + OS_REG_WRITE(ah, AR_PHY_AGC_CONTROL, + OS_REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_CAL); + + /* Poll for offset calibration complete */ + if (!ath_hal_wait(ah, AR_PHY_AGC_CONTROL, + AR_PHY_AGC_CONTROL_CAL, 0)) { + HALDEBUG(ah, HAL_DEBUG_RESET, + "%s: offset calibration failed to complete in 1ms; " + "noisy environment?\n", __func__); + return AH_FALSE; + } + + OS_REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); + + return AH_TRUE; +} diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9287_cal.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9287_cal.h new file mode 100644 index 0000000000..1a7cda2559 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9287_cal.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2008-2010 Atheros Communications Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ +#ifndef __AR9287_CAL_H__ +#define __AR9287_CAL_H__ + +extern void ar9287PACal(struct ath_hal *ah, HAL_BOOL is_reset); +extern HAL_BOOL ar9287InitCalHardware(struct ath_hal *ah, const struct ieee80211_channel *chan); + +#endif /* __AR9287_CAL_H__ */ diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9287_olc.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9287_olc.c new file mode 100644 index 0000000000..cbbe017667 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9287_olc.c @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2011 Adrian Chadd, Xenion Pty Ltd. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ah_eeprom_v14.h" +#include "ah_eeprom_9287.h" + +#include "ar9002/ar9280.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" +#include "ar9002/ar9002phy.h" + +#include "ar9002/ar9287phy.h" +#include "ar9002/ar9287an.h" +#include "ar9002/ar9287_olc.h" + +void +ar9287olcInit(struct ath_hal *ah) +{ + OS_REG_SET_BIT(ah, AR_PHY_TX_PWRCTRL9, + AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL); + OS_A_REG_RMW_FIELD(ah, AR9287_AN_TXPC0, + AR9287_AN_TXPC0_TXPCMODE, + AR9287_AN_TXPC0_TXPCMODE_TEMPSENSE); + OS_DELAY(100); +} + +/* + * Run temperature compensation calibration. + * + * The TX gain table is adjusted depending upon the difference + * between the initial PDADC value and the currently read + * average TX power sample value. This value is only valid if + * frames have been transmitted, so currPDADC will be 0 if + * no frames have yet been transmitted. + */ +void +ar9287olcTemperatureCompensation(struct ath_hal *ah) +{ + uint32_t rddata; + int32_t delta, currPDADC, slope; + + rddata = OS_REG_READ(ah, AR_PHY_TX_PWRCTRL4); + currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT); + + HALDEBUG(ah, HAL_DEBUG_PERCAL, "%s: initPDADC=%d, currPDADC=%d\n", + __func__, AH5416(ah)->initPDADC, currPDADC); + + if (AH5416(ah)->initPDADC == 0 || currPDADC == 0) { + /* + * Zero value indicates that no frames have been transmitted + * yet, can't do temperature compensation until frames are + * transmitted. + */ + return; + } else { + int8_t val; + (void) (ath_hal_eepromGet(ah, AR_EEP_TEMPSENSE_SLOPE, &val)); + slope = val; + + if (slope == 0) { /* to avoid divide by zero case */ + delta = 0; + } else { + delta = ((currPDADC - AH5416(ah)->initPDADC)*4) / slope; + } + OS_REG_RMW_FIELD(ah, AR_PHY_CH0_TX_PWRCTRL11, + AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta); + OS_REG_RMW_FIELD(ah, AR_PHY_CH1_TX_PWRCTRL11, + AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta); + + HALDEBUG(ah, HAL_DEBUG_PERCAL, "%s: delta=%d\n", __func__, delta); + } +} + +void +ar9287olcGetTxGainIndex(struct ath_hal *ah, + const struct ieee80211_channel *chan, + struct cal_data_op_loop_ar9287 *pRawDatasetOpLoop, + uint8_t *pCalChans, uint16_t availPiers, int8_t *pPwr) +{ + uint16_t idxL = 0, idxR = 0, numPiers; + HAL_BOOL match; + CHAN_CENTERS centers; + + ar5416GetChannelCenters(ah, chan, ¢ers); + + for (numPiers = 0; numPiers < availPiers; numPiers++) { + if (pCalChans[numPiers] == AR5416_BCHAN_UNUSED) + break; + } + + match = ath_ee_getLowerUpperIndex( + (uint8_t)FREQ2FBIN(centers.synth_center, IEEE80211_IS_CHAN_2GHZ(chan)), + pCalChans, numPiers, &idxL, &idxR); + + if (match) { + *pPwr = (int8_t) pRawDatasetOpLoop[idxL].pwrPdg[0][0]; + } else { + *pPwr = ((int8_t) pRawDatasetOpLoop[idxL].pwrPdg[0][0] + + (int8_t) pRawDatasetOpLoop[idxR].pwrPdg[0][0])/2; + } +} + +void +ar9287olcSetPDADCs(struct ath_hal *ah, int32_t txPower, + uint16_t chain) +{ + uint32_t tmpVal; + uint32_t a; + + /* Enable OLPC for chain 0 */ + + tmpVal = OS_REG_READ(ah, 0xa270); + tmpVal = tmpVal & 0xFCFFFFFF; + tmpVal = tmpVal | (0x3 << 24); + OS_REG_WRITE(ah, 0xa270, tmpVal); + + /* Enable OLPC for chain 1 */ + + tmpVal = OS_REG_READ(ah, 0xb270); + tmpVal = tmpVal & 0xFCFFFFFF; + tmpVal = tmpVal | (0x3 << 24); + OS_REG_WRITE(ah, 0xb270, tmpVal); + + /* Write the OLPC ref power for chain 0 */ + + if (chain == 0) { + tmpVal = OS_REG_READ(ah, 0xa398); + tmpVal = tmpVal & 0xff00ffff; + a = (txPower)&0xff; + tmpVal = tmpVal | (a << 16); + OS_REG_WRITE(ah, 0xa398, tmpVal); + } + + /* Write the OLPC ref power for chain 1 */ + + if (chain == 1) { + tmpVal = OS_REG_READ(ah, 0xb398); + tmpVal = tmpVal & 0xff00ffff; + a = (txPower)&0xff; + tmpVal = tmpVal | (a << 16); + OS_REG_WRITE(ah, 0xb398, tmpVal); + } +} diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9287_olc.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9287_olc.h new file mode 100644 index 0000000000..ff21ce6da5 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9287_olc.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2010 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ + +#ifndef __AR9287_OLC_H__ +#define __AR9287_OLC_H__ + +extern void ar9287olcInit(struct ath_hal *ah); +extern void ar9287olcTemperatureCompensation(struct ath_hal *ah); +extern void ar9287olcGetTxGainIndex(struct ath_hal *ah, + const struct ieee80211_channel *chan, + struct cal_data_op_loop_ar9287 *pRawDatasetOpLoop, + uint8_t *pCalChans, uint16_t availPiers, int8_t *pPwr); +extern void ar9287olcSetPDADCs(struct ath_hal *ah, + int32_t txPower, uint16_t chain); + +#endif /* __AR9287_OLC_H__ */ diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9287_reset.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9287_reset.c new file mode 100644 index 0000000000..a799ba0da9 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9287_reset.c @@ -0,0 +1,571 @@ +/* + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ + +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" + +#include "ah_eeprom_v14.h" +#include "ah_eeprom_9287.h" + +#include "ar5416/ar5416.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" + +#include "ar9002/ar9287phy.h" +#include "ar9002/ar9287an.h" + +#include "ar9002/ar9287_olc.h" +#include "ar9002/ar9287_reset.h" + +/* + * Set the TX power calibration table per-chain. + * + * This only supports open-loop TX power control for the AR9287. + */ +static void +ar9287SetPowerCalTable(struct ath_hal *ah, + const struct ieee80211_channel *chan, int16_t *pTxPowerIndexOffset) +{ + struct cal_data_op_loop_ar9287 *pRawDatasetOpenLoop; + uint8_t *pCalBChans = NULL; + uint16_t pdGainOverlap_t2; + uint16_t numPiers = 0, i; + uint16_t numXpdGain, xpdMask; + uint16_t xpdGainValues[AR5416_NUM_PD_GAINS] = {0, 0, 0, 0}; + uint32_t regChainOffset; + HAL_EEPROM_9287 *ee = AH_PRIVATE(ah)->ah_eeprom; + struct ar9287_eeprom *pEepData = &ee->ee_base; + + xpdMask = pEepData->modalHeader.xpdGain; + + if ((pEepData->baseEepHeader.version & AR9287_EEP_VER_MINOR_MASK) >= + AR9287_EEP_MINOR_VER_2) + pdGainOverlap_t2 = pEepData->modalHeader.pdGainOverlap; + else + pdGainOverlap_t2 = (uint16_t)(MS(OS_REG_READ(ah, AR_PHY_TPCRG5), + AR_PHY_TPCRG5_PD_GAIN_OVERLAP)); + + /* Note: Kiwi should only be 2ghz.. */ + if (IEEE80211_IS_CHAN_2GHZ(chan)) { + pCalBChans = pEepData->calFreqPier2G; + numPiers = AR9287_NUM_2G_CAL_PIERS; + pRawDatasetOpenLoop = (struct cal_data_op_loop_ar9287 *)pEepData->calPierData2G[0]; + AH5416(ah)->initPDADC = pRawDatasetOpenLoop->vpdPdg[0][0]; + } + numXpdGain = 0; + + /* Calculate the value of xpdgains from the xpdGain Mask */ + for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) { + if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) { + if (numXpdGain >= AR5416_NUM_PD_GAINS) + break; + xpdGainValues[numXpdGain] = + (uint16_t)(AR5416_PD_GAINS_IN_MASK-i); + numXpdGain++; + } + } + + OS_REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN, + (numXpdGain - 1) & 0x3); + OS_REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1, + xpdGainValues[0]); + OS_REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2, + xpdGainValues[1]); + OS_REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3, + xpdGainValues[2]); + + for (i = 0; i < AR9287_MAX_CHAINS; i++) { + regChainOffset = i * 0x1000; + + if (pEepData->baseEepHeader.txMask & (1 << i)) { + int8_t txPower; + pRawDatasetOpenLoop = + (struct cal_data_op_loop_ar9287 *)pEepData->calPierData2G[i]; + ar9287olcGetTxGainIndex(ah, chan, + pRawDatasetOpenLoop, + pCalBChans, numPiers, + &txPower); + ar9287olcSetPDADCs(ah, txPower, i); + } + } + + *pTxPowerIndexOffset = 0; +} + + +/* XXX hard-coded values? */ +#define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 + +/* + * ar9287SetPowerPerRateTable + * + * Sets the transmit power in the baseband for the given + * operating channel and mode. + * + * This is like the v14 EEPROM table except the 5GHz code. + */ +static HAL_BOOL +ar9287SetPowerPerRateTable(struct ath_hal *ah, + struct ar9287_eeprom *pEepData, + const struct ieee80211_channel *chan, + int16_t *ratesArray, uint16_t cfgCtl, + uint16_t AntennaReduction, + uint16_t twiceMaxRegulatoryPower, + uint16_t powerLimit) +{ +#define N(a) (sizeof(a)/sizeof(a[0])) +/* Local defines to distinguish between extension and control CTL's */ +#define EXT_ADDITIVE (0x8000) +#define CTL_11A_EXT (CTL_11A | EXT_ADDITIVE) +#define CTL_11G_EXT (CTL_11G | EXT_ADDITIVE) +#define CTL_11B_EXT (CTL_11B | EXT_ADDITIVE) + + uint16_t twiceMaxEdgePower = AR5416_MAX_RATE_POWER; + int i; + int16_t twiceLargestAntenna; + struct cal_ctl_data_ar9287 *rep; + CAL_TARGET_POWER_LEG targetPowerOfdm; + CAL_TARGET_POWER_LEG targetPowerCck = {0, {0, 0, 0, 0}}; + CAL_TARGET_POWER_LEG targetPowerOfdmExt = {0, {0, 0, 0, 0}}; + CAL_TARGET_POWER_LEG targetPowerCckExt = {0, {0, 0, 0, 0}}; + CAL_TARGET_POWER_HT targetPowerHt20; + CAL_TARGET_POWER_HT targetPowerHt40 = {0, {0, 0, 0, 0}}; + int16_t scaledPower, minCtlPower; + +#define SUB_NUM_CTL_MODES_AT_2G_40 3 /* excluding HT40, EXT-OFDM, EXT-CCK */ + static const uint16_t ctlModesFor11g[] = { + CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40 + }; + const uint16_t *pCtlMode; + uint16_t numCtlModes, ctlMode, freq; + CHAN_CENTERS centers; + + ar5416GetChannelCenters(ah, chan, ¢ers); + + /* Compute TxPower reduction due to Antenna Gain */ + + twiceLargestAntenna = AH_MAX( + pEepData->modalHeader.antennaGainCh[0], + pEepData->modalHeader.antennaGainCh[1]); + + twiceLargestAntenna = (int16_t)AH_MIN((AntennaReduction) - twiceLargestAntenna, 0); + + /* XXX setup for 5212 use (really used?) */ + ath_hal_eepromSet(ah, AR_EEP_ANTGAINMAX_2, twiceLargestAntenna); + + /* + * scaledPower is the minimum of the user input power level and + * the regulatory allowed power level + */ + scaledPower = AH_MIN(powerLimit, twiceMaxRegulatoryPower + twiceLargestAntenna); + + /* Reduce scaled Power by number of chains active to get to per chain tx power level */ + /* TODO: better value than these? */ + switch (owl_get_ntxchains(AH5416(ah)->ah_tx_chainmask)) { + case 1: + break; + case 2: + scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN; + break; + default: + return AH_FALSE; /* Unsupported number of chains */ + } + + scaledPower = AH_MAX(0, scaledPower); + + /* Get target powers from EEPROM - our baseline for TX Power */ + /* XXX assume channel is 2ghz */ + if (1) { + /* Setup for CTL modes */ + numCtlModes = N(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40; /* CTL_11B, CTL_11G, CTL_2GHT20 */ + pCtlMode = ctlModesFor11g; + + ar5416GetTargetPowersLeg(ah, chan, pEepData->calTargetPowerCck, + AR9287_NUM_2G_CCK_TARGET_POWERS, &targetPowerCck, 4, AH_FALSE); + ar5416GetTargetPowersLeg(ah, chan, pEepData->calTargetPower2G, + AR9287_NUM_2G_20_TARGET_POWERS, &targetPowerOfdm, 4, AH_FALSE); + ar5416GetTargetPowers(ah, chan, pEepData->calTargetPower2GHT20, + AR9287_NUM_2G_20_TARGET_POWERS, &targetPowerHt20, 8, AH_FALSE); + + if (IEEE80211_IS_CHAN_HT40(chan)) { + numCtlModes = N(ctlModesFor11g); /* All 2G CTL's */ + + ar5416GetTargetPowers(ah, chan, pEepData->calTargetPower2GHT40, + AR9287_NUM_2G_40_TARGET_POWERS, &targetPowerHt40, 8, AH_TRUE); + /* Get target powers for extension channels */ + ar5416GetTargetPowersLeg(ah, chan, pEepData->calTargetPowerCck, + AR9287_NUM_2G_CCK_TARGET_POWERS, &targetPowerCckExt, 4, AH_TRUE); + ar5416GetTargetPowersLeg(ah, chan, pEepData->calTargetPower2G, + AR9287_NUM_2G_20_TARGET_POWERS, &targetPowerOfdmExt, 4, AH_TRUE); + } + } + + /* + * For MIMO, need to apply regulatory caps individually across dynamically + * running modes: CCK, OFDM, HT20, HT40 + * + * The outer loop walks through each possible applicable runtime mode. + * The inner loop walks through each ctlIndex entry in EEPROM. + * The ctl value is encoded as [7:4] == test group, [3:0] == test mode. + * + */ + for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) { + HAL_BOOL isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) || + (pCtlMode[ctlMode] == CTL_2GHT40); + if (isHt40CtlMode) { + freq = centers.ctl_center; + } else if (pCtlMode[ctlMode] & EXT_ADDITIVE) { + freq = centers.ext_center; + } else { + freq = centers.ctl_center; + } + + /* walk through each CTL index stored in EEPROM */ + for (i = 0; (i < AR9287_NUM_CTLS) && pEepData->ctlIndex[i]; i++) { + uint16_t twiceMinEdgePower; + + /* compare test group from regulatory channel list with test mode from pCtlMode list */ + if ((((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == pEepData->ctlIndex[i]) || + (((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == + ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))) { + rep = &(pEepData->ctlData[i]); + twiceMinEdgePower = ar5416GetMaxEdgePower(freq, + rep->ctlEdges[owl_get_ntxchains(AH5416(ah)->ah_tx_chainmask) - 1], + IEEE80211_IS_CHAN_2GHZ(chan)); + if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) { + /* Find the minimum of all CTL edge powers that apply to this channel */ + twiceMaxEdgePower = AH_MIN(twiceMaxEdgePower, twiceMinEdgePower); + } else { + /* specific */ + twiceMaxEdgePower = twiceMinEdgePower; + break; + } + } + } + minCtlPower = (uint8_t)AH_MIN(twiceMaxEdgePower, scaledPower); + /* Apply ctl mode to correct target power set */ + switch(pCtlMode[ctlMode]) { + case CTL_11B: + for (i = 0; i < N(targetPowerCck.tPow2x); i++) { + targetPowerCck.tPow2x[i] = (uint8_t)AH_MIN(targetPowerCck.tPow2x[i], minCtlPower); + } + break; + case CTL_11A: + case CTL_11G: + for (i = 0; i < N(targetPowerOfdm.tPow2x); i++) { + targetPowerOfdm.tPow2x[i] = (uint8_t)AH_MIN(targetPowerOfdm.tPow2x[i], minCtlPower); + } + break; + case CTL_5GHT20: + case CTL_2GHT20: + for (i = 0; i < N(targetPowerHt20.tPow2x); i++) { + targetPowerHt20.tPow2x[i] = (uint8_t)AH_MIN(targetPowerHt20.tPow2x[i], minCtlPower); + } + break; + case CTL_11B_EXT: + targetPowerCckExt.tPow2x[0] = (uint8_t)AH_MIN(targetPowerCckExt.tPow2x[0], minCtlPower); + break; + case CTL_11A_EXT: + case CTL_11G_EXT: + targetPowerOfdmExt.tPow2x[0] = (uint8_t)AH_MIN(targetPowerOfdmExt.tPow2x[0], minCtlPower); + break; + case CTL_5GHT40: + case CTL_2GHT40: + for (i = 0; i < N(targetPowerHt40.tPow2x); i++) { + targetPowerHt40.tPow2x[i] = (uint8_t)AH_MIN(targetPowerHt40.tPow2x[i], minCtlPower); + } + break; + default: + return AH_FALSE; + break; + } + } /* end ctl mode checking */ + + /* Set rates Array from collected data */ + ar5416SetRatesArrayFromTargetPower(ah, chan, ratesArray, + &targetPowerCck, + &targetPowerCckExt, + &targetPowerOfdm, + &targetPowerOfdmExt, + &targetPowerHt20, + &targetPowerHt40); + return AH_TRUE; +#undef EXT_ADDITIVE +#undef CTL_11A_EXT +#undef CTL_11G_EXT +#undef CTL_11B_EXT +#undef SUB_NUM_CTL_MODES_AT_5G_40 +#undef SUB_NUM_CTL_MODES_AT_2G_40 +#undef N +} + +#undef REDUCE_SCALED_POWER_BY_TWO_CHAIN + +/* + * This is based off of the AR5416/AR9285 code and likely could + * be unified in the future. + */ +HAL_BOOL +ar9287SetTransmitPower(struct ath_hal *ah, + const struct ieee80211_channel *chan, uint16_t *rfXpdGain) +{ +#define POW_SM(_r, _s) (((_r) & 0x3f) << (_s)) +#define N(a) (sizeof (a) / sizeof (a[0])) + + const struct modal_eep_ar9287_header *pModal; + struct ath_hal_5212 *ahp = AH5212(ah); + int16_t ratesArray[Ar5416RateSize]; + int16_t txPowerIndexOffset = 0; + uint8_t ht40PowerIncForPdadc = 2; + int i; + + uint16_t cfgCtl; + uint16_t powerLimit; + uint16_t twiceAntennaReduction; + uint16_t twiceMaxRegulatoryPower; + int16_t maxPower; + HAL_EEPROM_9287 *ee = AH_PRIVATE(ah)->ah_eeprom; + struct ar9287_eeprom *pEepData = &ee->ee_base; + + /* Setup info for the actual eeprom */ + OS_MEMZERO(ratesArray, sizeof(ratesArray)); + cfgCtl = ath_hal_getctl(ah, chan); + powerLimit = chan->ic_maxregpower * 2; + twiceAntennaReduction = chan->ic_maxantgain; + twiceMaxRegulatoryPower = AH_MIN(MAX_RATE_POWER, AH_PRIVATE(ah)->ah_powerLimit); + pModal = &pEepData->modalHeader; + HALDEBUG(ah, HAL_DEBUG_RESET, "%s Channel=%u CfgCtl=%u\n", + __func__,chan->ic_freq, cfgCtl ); + + /* XXX Assume Minor is v2 or later */ + ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc; + + /* Fetch per-rate power table for the given channel */ + if (! ar9287SetPowerPerRateTable(ah, pEepData, chan, + &ratesArray[0],cfgCtl, + twiceAntennaReduction, + twiceMaxRegulatoryPower, powerLimit)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: unable to set tx power per rate table\n", __func__); + return AH_FALSE; + } + + /* Set TX power control calibration curves for each TX chain */ + ar9287SetPowerCalTable(ah, chan, &txPowerIndexOffset); + + /* Calculate maximum power level */ + maxPower = AH_MAX(ratesArray[rate6mb], ratesArray[rateHt20_0]); + maxPower = AH_MAX(maxPower, ratesArray[rate1l]); + + if (IEEE80211_IS_CHAN_HT40(chan)) + maxPower = AH_MAX(maxPower, ratesArray[rateHt40_0]); + + ahp->ah_tx6PowerInHalfDbm = maxPower; + AH_PRIVATE(ah)->ah_maxPowerLevel = maxPower; + ahp->ah_txPowerIndexOffset = txPowerIndexOffset; + + /* + * txPowerIndexOffset is set by the SetPowerTable() call - + * adjust the rate table (0 offset if rates EEPROM not loaded) + */ + /* XXX what about the pwrTableOffset? */ + for (i = 0; i < N(ratesArray); i++) { + ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]); + /* -5 dBm offset for Merlin and later; this includes Kiwi */ + ratesArray[i] -= AR5416_PWR_TABLE_OFFSET_DB * 2; + if (ratesArray[i] > AR5416_MAX_RATE_POWER) + ratesArray[i] = AR5416_MAX_RATE_POWER; + if (ratesArray[i] < 0) + ratesArray[i] = 0; + } + +#ifdef AH_EEPROM_DUMP + ar5416PrintPowerPerRate(ah, ratesArray); +#endif + + /* + * Adjust the HT40 power to meet the correct target TX power + * for 40MHz mode, based on TX power curves that are established + * for 20MHz mode. + * + * XXX handle overflow/too high power level? + */ + if (IEEE80211_IS_CHAN_HT40(chan)) { + ratesArray[rateHt40_0] += ht40PowerIncForPdadc; + ratesArray[rateHt40_1] += ht40PowerIncForPdadc; + ratesArray[rateHt40_2] += ht40PowerIncForPdadc; + ratesArray[rateHt40_3] += ht40PowerIncForPdadc; + ratesArray[rateHt40_4] += ht40PowerIncForPdadc; + ratesArray[rateHt40_5] += ht40PowerIncForPdadc; + ratesArray[rateHt40_6] += ht40PowerIncForPdadc; + ratesArray[rateHt40_7] += ht40PowerIncForPdadc; + } + + /* Write the TX power rate registers */ + ar5416WriteTxPowerRateRegisters(ah, chan, ratesArray); + + return AH_TRUE; +#undef POW_SM +#undef N +} + +/* + * Read EEPROM header info and program the device for correct operation + * given the channel value. + */ +HAL_BOOL +ar9287SetBoardValues(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + const HAL_EEPROM_9287 *ee = AH_PRIVATE(ah)->ah_eeprom; + const struct ar9287_eeprom *eep = &ee->ee_base; + const struct modal_eep_ar9287_header *pModal = &eep->modalHeader; + uint16_t antWrites[AR9287_ANT_16S]; + uint32_t regChainOffset, regval; + uint8_t txRxAttenLocal; + int i, j, offset_num; + + pModal = &eep->modalHeader; + + antWrites[0] = (uint16_t)((pModal->antCtrlCommon >> 28) & 0xF); + antWrites[1] = (uint16_t)((pModal->antCtrlCommon >> 24) & 0xF); + antWrites[2] = (uint16_t)((pModal->antCtrlCommon >> 20) & 0xF); + antWrites[3] = (uint16_t)((pModal->antCtrlCommon >> 16) & 0xF); + antWrites[4] = (uint16_t)((pModal->antCtrlCommon >> 12) & 0xF); + antWrites[5] = (uint16_t)((pModal->antCtrlCommon >> 8) & 0xF); + antWrites[6] = (uint16_t)((pModal->antCtrlCommon >> 4) & 0xF); + antWrites[7] = (uint16_t)(pModal->antCtrlCommon & 0xF); + + offset_num = 8; + + for (i = 0, j = offset_num; i < AR9287_MAX_CHAINS; i++) { + antWrites[j++] = (uint16_t)((pModal->antCtrlChain[i] >> 28) & 0xf); + antWrites[j++] = (uint16_t)((pModal->antCtrlChain[i] >> 10) & 0x3); + antWrites[j++] = (uint16_t)((pModal->antCtrlChain[i] >> 8) & 0x3); + antWrites[j++] = 0; + antWrites[j++] = (uint16_t)((pModal->antCtrlChain[i] >> 6) & 0x3); + antWrites[j++] = (uint16_t)((pModal->antCtrlChain[i] >> 4) & 0x3); + antWrites[j++] = (uint16_t)((pModal->antCtrlChain[i] >> 2) & 0x3); + antWrites[j++] = (uint16_t)(pModal->antCtrlChain[i] & 0x3); + } + + OS_REG_WRITE(ah, AR_PHY_SWITCH_COM, pModal->antCtrlCommon); + + for (i = 0; i < AR9287_MAX_CHAINS; i++) { + regChainOffset = i * 0x1000; + + OS_REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset, + pModal->antCtrlChain[i]); + + OS_REG_WRITE(ah, AR_PHY_TIMING_CTRL4_CHAIN(0) + regChainOffset, + (OS_REG_READ(ah, AR_PHY_TIMING_CTRL4_CHAIN(0) + regChainOffset) + & ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF | + AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) | + SM(pModal->iqCalICh[i], + AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) | + SM(pModal->iqCalQCh[i], + AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF)); + + txRxAttenLocal = pModal->txRxAttenCh[i]; + + OS_REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, + AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, + pModal->bswMargin[i]); + OS_REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, + AR_PHY_GAIN_2GHZ_XATTEN1_DB, + pModal->bswAtten[i]); + OS_REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset, + AR9280_PHY_RXGAIN_TXRX_ATTEN, + txRxAttenLocal); + OS_REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset, + AR9280_PHY_RXGAIN_TXRX_MARGIN, + pModal->rxTxMarginCh[i]); + } + + + if (IEEE80211_IS_CHAN_HT40(chan)) + OS_REG_RMW_FIELD(ah, AR_PHY_SETTLING, + AR_PHY_SETTLING_SWITCH, pModal->swSettleHt40); + else + OS_REG_RMW_FIELD(ah, AR_PHY_SETTLING, + AR_PHY_SETTLING_SWITCH, pModal->switchSettling); + + OS_REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, + AR_PHY_DESIRED_SZ_ADC, pModal->adcDesiredSize); + + OS_REG_WRITE(ah, AR_PHY_RF_CTL4, + SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF) + | SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAB_OFF) + | SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAA_ON) + | SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAB_ON)); + + OS_REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, + AR_PHY_TX_END_TO_A2_RX_ON, pModal->txEndToRxOn); + + OS_REG_RMW_FIELD(ah, AR_PHY_CCA, + AR9280_PHY_CCA_THRESH62, pModal->thresh62); + OS_REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, + AR_PHY_EXT_CCA0_THRESH62, pModal->thresh62); + + regval = OS_REG_READ(ah, AR9287_AN_RF2G3_CH0); + regval &= ~(AR9287_AN_RF2G3_DB1 | + AR9287_AN_RF2G3_DB2 | + AR9287_AN_RF2G3_OB_CCK | + AR9287_AN_RF2G3_OB_PSK | + AR9287_AN_RF2G3_OB_QAM | + AR9287_AN_RF2G3_OB_PAL_OFF); + regval |= (SM(pModal->db1, AR9287_AN_RF2G3_DB1) | + SM(pModal->db2, AR9287_AN_RF2G3_DB2) | + SM(pModal->ob_cck, AR9287_AN_RF2G3_OB_CCK) | + SM(pModal->ob_psk, AR9287_AN_RF2G3_OB_PSK) | + SM(pModal->ob_qam, AR9287_AN_RF2G3_OB_QAM) | + SM(pModal->ob_pal_off, AR9287_AN_RF2G3_OB_PAL_OFF)); + + OS_REG_WRITE(ah, AR9287_AN_RF2G3_CH0, regval); + OS_DELAY(100); /* analog write */ + + regval = OS_REG_READ(ah, AR9287_AN_RF2G3_CH1); + regval &= ~(AR9287_AN_RF2G3_DB1 | + AR9287_AN_RF2G3_DB2 | + AR9287_AN_RF2G3_OB_CCK | + AR9287_AN_RF2G3_OB_PSK | + AR9287_AN_RF2G3_OB_QAM | + AR9287_AN_RF2G3_OB_PAL_OFF); + regval |= (SM(pModal->db1, AR9287_AN_RF2G3_DB1) | + SM(pModal->db2, AR9287_AN_RF2G3_DB2) | + SM(pModal->ob_cck, AR9287_AN_RF2G3_OB_CCK) | + SM(pModal->ob_psk, AR9287_AN_RF2G3_OB_PSK) | + SM(pModal->ob_qam, AR9287_AN_RF2G3_OB_QAM) | + SM(pModal->ob_pal_off, AR9287_AN_RF2G3_OB_PAL_OFF)); + + OS_REG_WRITE(ah, AR9287_AN_RF2G3_CH1, regval); + OS_DELAY(100); /* analog write */ + + OS_REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, + AR_PHY_TX_FRAME_TO_DATA_START, pModal->txFrameToDataStart); + OS_REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, + AR_PHY_TX_FRAME_TO_PA_ON, pModal->txFrameToPaOn); + + OS_A_REG_RMW_FIELD(ah, AR9287_AN_TOP2, + AR9287_AN_TOP2_XPABIAS_LVL, pModal->xpaBiasLvl); + + return AH_TRUE; +} diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9287_reset.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9287_reset.h new file mode 100644 index 0000000000..679fb8cfc8 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9287_reset.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2010 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ + +#ifndef __AR9287_RESET_H__ +#define __AR9287_RESET_H__ + +extern HAL_BOOL ar9287SetTransmitPower(struct ath_hal *ah, + const struct ieee80211_channel *chan, uint16_t *rfXpdGain); +extern HAL_BOOL ar9287SetBoardValues(struct ath_hal *ah, + const struct ieee80211_channel *chan); + +#endif /* __AR9287_RESET_H__ */ diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9287an.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9287an.h new file mode 100644 index 0000000000..ba7a92cbaa --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9287an.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2010 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ + +#ifndef __AR9287AN_H__ +#define __AR9287AN_H__ + +#define AR9287_AN_RF2G3_CH0 0x7808 +#define AR9287_AN_RF2G3_CH1 0x785c +#define AR9287_AN_RF2G3_DB1 0xE0000000 +#define AR9287_AN_RF2G3_DB1_S 29 +#define AR9287_AN_RF2G3_DB2 0x1C000000 +#define AR9287_AN_RF2G3_DB2_S 26 +#define AR9287_AN_RF2G3_OB_CCK 0x03800000 +#define AR9287_AN_RF2G3_OB_CCK_S 23 +#define AR9287_AN_RF2G3_OB_PSK 0x00700000 +#define AR9287_AN_RF2G3_OB_PSK_S 20 +#define AR9287_AN_RF2G3_OB_QAM 0x000E0000 +#define AR9287_AN_RF2G3_OB_QAM_S 17 +#define AR9287_AN_RF2G3_OB_PAL_OFF 0x0001C000 +#define AR9287_AN_RF2G3_OB_PAL_OFF_S 14 + +#define AR9287_AN_TXPC0 0x7898 +#define AR9287_AN_TXPC0_TXPCMODE 0x0000C000 +#define AR9287_AN_TXPC0_TXPCMODE_S 14 +#define AR9287_AN_TXPC0_TXPCMODE_NORMAL 0 +#define AR9287_AN_TXPC0_TXPCMODE_TEST 1 +#define AR9287_AN_TXPC0_TXPCMODE_TEMPSENSE 2 +#define AR9287_AN_TXPC0_TXPCMODE_ATBTEST 3 + +#define AR9287_AN_TOP2 0x78b4 +#define AR9287_AN_TOP2_XPABIAS_LVL 0xC0000000 +#define AR9287_AN_TOP2_XPABIAS_LVL_S 30 + +#endif diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9287phy.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9287phy.h new file mode 100644 index 0000000000..8f28194e44 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_hal/ar9002/ar9287phy.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2010 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ + +#ifndef __AR9287PHY_H__ +#define __AR9287PHY_H__ + +/* AR_PHY_CH0_TX_PWRCTRL11, AR_PHY_CH1_TX_PWRCTRL11 */ +#define AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP 0x0000FC00 +#define AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP_S 10 + +#endif diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_rate/amrr/amrr.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_rate/amrr/amrr.c index 88e71e6c30..5fee76e301 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_rate/amrr/amrr.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_rate/amrr/amrr.c @@ -114,6 +114,30 @@ ath_rate_findrate(struct ath_softc *sc, struct ath_node *an, *txrate = amn->amn_tx_rate0; } +/* + * Get the TX rates. + * + * The short preamble bits aren't set here; the caller should augment + * the returned rate with the relevant preamble rate flag. + */ +void +ath_rate_getxtxrates(struct ath_softc *sc, struct ath_node *an, + uint8_t rix0, uint8_t *rix, uint8_t *try) +{ + struct amrr_node *amn = ATH_NODE_AMRR(an); + +/* rix[0] = amn->amn_tx_rate0; */ + rix[1] = amn->amn_tx_rate1; + rix[2] = amn->amn_tx_rate2; + rix[3] = amn->amn_tx_rate3; + + try[0] = amn->amn_tx_try0; + try[1] = amn->amn_tx_try1; + try[2] = amn->amn_tx_try2; + try[3] = amn->amn_tx_try3; +} + + void ath_rate_setupxtxdesc(struct ath_softc *sc, struct ath_node *an, struct ath_desc *ds, int shortPreamble, u_int8_t rix) diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_rate/onoe/onoe.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_rate/onoe/onoe.c index 22811c4da1..77236adb28 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_rate/onoe/onoe.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_rate/onoe/onoe.c @@ -122,6 +122,29 @@ ath_rate_findrate(struct ath_softc *sc, struct ath_node *an, *txrate = on->on_tx_rate0; } +/* + * Get the TX rates. + * + * The short preamble bits aren't set here; the caller should augment + * the returned rate with the relevant preamble rate flag. + */ +void +ath_rate_getxtxrates(struct ath_softc *sc, struct ath_node *an, + uint8_t rix0, uint8_t *rix, uint8_t *try) +{ + struct onoe_node *on = ATH_NODE_ONOE(an); + +/* rix[0] = on->on_tx_rate0; */ + rix[1] = on->on_tx_rate1; + rix[2] = on->on_tx_rate2; + rix[3] = on->on_tx_rate3; + + try[0] = on->on_tx_try0; + try[1] = 2; + try[2] = 2; + try[3] = 2; +} + void ath_rate_setupxtxdesc(struct ath_softc *sc, struct ath_node *an, struct ath_desc *ds, int shortPreamble, u_int8_t rix) diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_rate/sample/sample.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_rate/sample/sample.c index 714ee9d8d2..27bb98cf87 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_rate/sample/sample.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_rate/sample/sample.c @@ -75,6 +75,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include /* * This file is an implementation of the SampleRate algorithm @@ -142,14 +143,28 @@ ath_rate_node_cleanup(struct ath_softc *sc, struct ath_node *an) { } +static int +dot11rate(const HAL_RATE_TABLE *rt, int rix) +{ + return rt->info[rix].phy == IEEE80211_T_HT ? + rt->info[rix].dot11Rate : (rt->info[rix].dot11Rate & IEEE80211_RATE_VAL) / 2; +} + +static const char * +dot11rate_label(const HAL_RATE_TABLE *rt, int rix) +{ + return rt->info[rix].phy == IEEE80211_T_HT ? "MCS" : "Mb "; +} + /* * Return the rix with the lowest average_tx_time, * or -1 if all the average_tx_times are 0. */ static __inline int -pick_best_rate(struct sample_node *sn, const HAL_RATE_TABLE *rt, +pick_best_rate(struct ath_node *an, const HAL_RATE_TABLE *rt, int size_bin, int require_acked_before) { + struct sample_node *sn = ATH_NODE_SAMPLE(an); int best_rate_rix, best_rate_tt; uint32_t mask; int rix, tt; @@ -160,6 +175,12 @@ pick_best_rate(struct sample_node *sn, const HAL_RATE_TABLE *rt, if ((mask & 1) == 0) /* not a supported rate */ continue; + /* Don't pick a non-HT rate for a HT node */ + if ((an->an_node.ni_flags & IEEE80211_NODE_HT) && + (rt->info[rix].phy != IEEE80211_T_HT)) { + continue; + } + tt = sn->stats[size_bin][rix].average_tx_time; if (tt <= 0 || (require_acked_before && @@ -182,10 +203,12 @@ pick_best_rate(struct sample_node *sn, const HAL_RATE_TABLE *rt, * Pick a good "random" bit-rate to sample other than the current one. */ static __inline int -pick_sample_rate(struct sample_softc *ssc , struct sample_node *sn, +pick_sample_rate(struct sample_softc *ssc , struct ath_node *an, const HAL_RATE_TABLE *rt, int size_bin) { #define DOT11RATE(ix) (rt->info[ix].dot11Rate & IEEE80211_RATE_VAL) +#define MCS(ix) (rt->info[ix].dot11Rate | IEEE80211_RATE_MCS) + struct sample_node *sn = ATH_NODE_SAMPLE(an); int current_rix, rix; unsigned current_tt; uint32_t mask; @@ -193,6 +216,7 @@ pick_sample_rate(struct sample_softc *ssc , struct sample_node *sn, current_rix = sn->current_rix[size_bin]; if (current_rix < 0) { /* no successes yet, send at the lowest bit-rate */ + /* XXX should return MCS0 if HT */ return 0; } @@ -208,6 +232,13 @@ pick_sample_rate(struct sample_softc *ssc , struct sample_node *sn, continue; } + /* if the node is HT and the rate isn't HT, don't bother sample */ + if ((an->an_node.ni_flags & IEEE80211_NODE_HT) && + (rt->info[rix].phy != IEEE80211_T_HT)) { + mask &= ~(1<stats[size_bin][rix].perfect_tx_time > current_tt) { mask &= ~(1< 11M */ - if (DOT11RATE(rix) > 2*11 && rix > current_rix + 2) { - mask &= ~(1< 11M for non-HT rates */ + if (! (an->an_node.ni_flags & IEEE80211_NODE_HT)) { + if (DOT11RATE(rix) > 2*11 && rix > current_rix + 2) { + mask &= ~(1<last_sample_rix[size_bin] = rix; @@ -232,14 +265,65 @@ pick_sample_rate(struct sample_softc *ssc , struct sample_node *sn, } return current_rix; #undef DOT11RATE +#undef MCS } +static int +ath_rate_get_static_rix(struct ath_softc *sc, const struct ieee80211_node *ni) +{ +#define RATE(_ix) (ni->ni_rates.rs_rates[(_ix)] & IEEE80211_RATE_VAL) +#define DOT11RATE(_ix) (rt->info[(_ix)].dot11Rate & IEEE80211_RATE_VAL) +#define MCS(_ix) (ni->ni_htrates.rs_rates[_ix] | IEEE80211_RATE_MCS) + const struct ieee80211_txparam *tp = ni->ni_txparms; + int srate; + + /* Check MCS rates */ + for (srate = ni->ni_htrates.rs_nrates - 1; srate >= 0; srate--) { + if (MCS(srate) == tp->ucastrate) + return sc->sc_rixmap[tp->ucastrate]; + } + + /* Check legacy rates */ + for (srate = ni->ni_rates.rs_nrates - 1; srate >= 0; srate--) { + if (RATE(srate) == tp->ucastrate) + return sc->sc_rixmap[tp->ucastrate]; + } + return -1; +#undef RATE +#undef DOT11RATE +#undef MCS +} + +static void +ath_rate_update_static_rix(struct ath_softc *sc, struct ieee80211_node *ni) +{ + struct ath_node *an = ATH_NODE(ni); + const struct ieee80211_txparam *tp = ni->ni_txparms; + struct sample_node *sn = ATH_NODE_SAMPLE(an); + + if (tp != NULL && tp->ucastrate != IEEE80211_FIXED_RATE_NONE) { + /* + * A fixed rate is to be used; ucastrate is the IEEE code + * for this rate (sans basic bit). Check this against the + * negotiated rate set for the node. Note the fixed rate + * may not be available for various reasons so we only + * setup the static rate index if the lookup is successful. + */ + sn->static_rix = ath_rate_get_static_rix(sc, ni); + } else { + sn->static_rix = -1; + } +} + + + void ath_rate_findrate(struct ath_softc *sc, struct ath_node *an, int shortPreamble, size_t frameLen, u_int8_t *rix0, int *try0, u_int8_t *txrate) { #define DOT11RATE(ix) (rt->info[ix].dot11Rate & IEEE80211_RATE_VAL) +#define MCS(ix) (rt->info[ix].dot11Rate | IEEE80211_RATE_MCS) #define RATE(ix) (DOT11RATE(ix) / 2) struct sample_node *sn = ATH_NODE_SAMPLE(an); struct sample_softc *ssc = ATH_SOFTC_SAMPLE(sc); @@ -250,15 +334,18 @@ ath_rate_findrate(struct ath_softc *sc, struct ath_node *an, int rix, mrr, best_rix, change_rates; unsigned average_tx_time; + ath_rate_update_static_rix(sc, &an->an_node); + if (sn->static_rix != -1) { rix = sn->static_rix; *try0 = ATH_TXMAXTRY; goto done; } + /* XXX TODO: this doesn't know about 11gn vs 11g protection; teach it */ mrr = sc->sc_mrretry && !(ic->ic_flags & IEEE80211_F_USEPROT); - best_rix = pick_best_rate(sn, rt, size_bin, !mrr); + best_rix = pick_best_rate(an, rt, size_bin, !mrr); if (best_rix >= 0) { average_tx_time = sn->stats[size_bin][best_rix].average_tx_time; } else { @@ -269,7 +356,7 @@ ath_rate_findrate(struct ath_softc *sc, struct ath_node *an, * rates to sample_rate% of the total transmission time. */ if (sn->sample_tt[size_bin] < average_tx_time * (sn->packets_since_sample[size_bin]*ssc->sample_rate/100)) { - rix = pick_sample_rate(ssc, sn, rt, size_bin); + rix = pick_sample_rate(ssc, an, rt, size_bin); IEEE80211_NOTE(an->an_node.ni_vap, IEEE80211_MSG_RATECTL, &an->an_node, "size %u sample rate %d current rate %d", bin_to_size(size_bin), RATE(rix), @@ -334,7 +421,7 @@ ath_rate_findrate(struct ath_softc *sc, struct ath_node *an, /* * Set the visible txrate for this node. */ - an->an_node.ni_txrate = DOT11RATE(best_rix); + an->an_node.ni_txrate = (rt->info[best_rix].phy == IEEE80211_T_HT) ? MCS(best_rix) : DOT11RATE(best_rix); } rix = sn->current_rix[size_bin]; sn->packets_since_switch[size_bin]++; @@ -348,80 +435,33 @@ done: | (shortPreamble ? rt->info[rix].shortPreamble : 0); sn->packets_sent[size_bin]++; #undef DOT11RATE +#undef MCS #undef RATE } -#define A(_r) \ - (((_r) == 6) ? 0 : (((_r) == 9) ? 1 : (((_r) == 12) ? 2 : \ - (((_r) == 18) ? 3 : (((_r) == 24) ? 4 : (((_r) == 36) ? 5 : \ - (((_r) == 48) ? 6 : (((_r) == 54) ? 7 : 0)))))))) -static const struct txschedule series_11a[] = { - { 3,A( 6), 3,A( 6), 0,A( 6), 0,A( 6) }, /* 6Mb/s */ - { 4,A( 9), 3,A( 6), 4,A( 6), 0,A( 6) }, /* 9Mb/s */ - { 4,A(12), 3,A( 6), 4,A( 6), 0,A( 6) }, /* 12Mb/s */ - { 4,A(18), 3,A( 12), 4,A( 6), 2,A( 6) }, /* 18Mb/s */ - { 4,A(24), 3,A( 18), 4,A( 12), 2,A( 6) }, /* 24Mb/s */ - { 4,A(36), 3,A( 24), 4,A( 18), 2,A( 6) }, /* 36Mb/s */ - { 4,A(48), 3,A( 36), 4,A( 24), 2,A(12) }, /* 48Mb/s */ - { 4,A(54), 3,A( 48), 4,A( 36), 2,A(24) } /* 54Mb/s */ -}; -#undef A +/* + * Get the TX rates. Don't fiddle with short preamble flags for them; + * the caller can do that. + */ +void +ath_rate_getxtxrates(struct ath_softc *sc, struct ath_node *an, + uint8_t rix0, uint8_t *rix, uint8_t *try) +{ + struct sample_node *sn = ATH_NODE_SAMPLE(an); + const struct txschedule *sched = &sn->sched[rix0]; -#define G(_r) \ - (((_r) == 1) ? 0 : (((_r) == 2) ? 1 : (((_r) == 5.5) ? 2 : \ - (((_r) == 11) ? 3 : (((_r) == 6) ? 4 : (((_r) == 9) ? 5 : \ - (((_r) == 12) ? 6 : (((_r) == 18) ? 7 : (((_r) == 24) ? 8 : \ - (((_r) == 36) ? 9 : (((_r) == 48) ? 10 : (((_r) == 54) ? 11 : 0)))))))))))) -static const struct txschedule series_11g[] = { - { 3,G( 1), 3,G( 1), 0,G( 1), 0,G( 1) }, /* 1Mb/s */ - { 4,G( 2), 3,G( 1), 4,G( 1), 0,G( 1) }, /* 2Mb/s */ - { 4,G(5.5),3,G( 2), 4,G( 1), 2,G( 1) }, /* 5.5Mb/s */ - { 4,G(11), 3,G(5.5), 4,G( 2), 2,G( 1) }, /* 11Mb/s */ - { 4,G( 6), 3,G(5.5), 4,G( 2), 2,G( 1) }, /* 6Mb/s */ - { 4,G( 9), 3,G( 6), 4,G(5.5), 2,G( 1) }, /* 9Mb/s */ - { 4,G(12), 3,G( 11), 4,G(5.5), 2,G( 1) }, /* 12Mb/s */ - { 4,G(18), 3,G( 12), 4,G( 11), 2,G( 1) }, /* 18Mb/s */ - { 4,G(24), 3,G( 18), 4,G( 12), 2,G( 1) }, /* 24Mb/s */ - { 4,G(36), 3,G( 24), 4,G( 18), 2,G( 1) }, /* 36Mb/s */ - { 4,G(48), 3,G( 36), 4,G( 24), 2,G( 1) }, /* 48Mb/s */ - { 4,G(54), 3,G( 48), 4,G( 36), 2,G( 1) } /* 54Mb/s */ -}; -#undef G + KASSERT(rix0 == sched->r0, ("rix0 (%x) != sched->r0 (%x)!\n", rix0, sched->r0)); -#define H(_r) \ - (((_r) == 3) ? 0 : (((_r) == 4.5) ? 1 : (((_r) == 6) ? 2 : \ - (((_r) == 9) ? 3 : (((_r) == 12) ? 4 : (((_r) == 18) ? 5 : \ - (((_r) == 24) ? 6 : (((_r) == 27) ? 7 : 0)))))))) -static const struct txschedule series_half[] = { - { 3,H( 3), 3,H( 3), 0,H( 3), 0,H( 3) }, /* 3Mb/s */ - { 4,H(4.5),3,H( 3), 4,H( 3), 0,H( 3) }, /* 4.5Mb/s */ - { 4,H( 6), 3,H( 3), 4,H( 3), 0,H( 3) }, /* 6Mb/s */ - { 4,H( 9), 3,H( 6), 4,H( 3), 2,H( 3) }, /* 9Mb/s */ - { 4,H(12), 3,H( 9), 4,H( 6), 2,H( 3) }, /* 12Mb/s */ - { 4,H(18), 3,H( 12), 4,H( 9), 2,H( 3) }, /* 18Mb/s */ - { 4,H(24), 3,H( 18), 4,H( 12), 2,H( 6) }, /* 24Mb/s */ - { 4,H(27), 3,H( 24), 4,H( 18), 2,H(12) } /* 27Mb/s */ -}; -#undef H +/* rix[0] = sched->r0; */ + rix[1] = sched->r1; + rix[2] = sched->r2; + rix[3] = sched->r3; -#ifdef Q -#undef Q /* sun4v bogosity */ -#endif -#define Q(_r) \ - (((_r) == 1.5) ? 0 : (((_r) ==2.25) ? 1 : (((_r) == 3) ? 2 : \ - (((_r) == 4.5) ? 3 : (((_r) == 6) ? 4 : (((_r) == 9) ? 5 : \ - (((_r) == 12) ? 6 : (((_r) == 13.5)? 7 : 0)))))))) -static const struct txschedule series_quarter[] = { - { 3,Q( 1.5),3,Q(1.5), 0,Q(1.5), 0,Q(1.5) }, /* 1.5Mb/s */ - { 4,Q(2.25),3,Q(1.5), 4,Q(1.5), 0,Q(1.5) }, /*2.25Mb/s */ - { 4,Q( 3),3,Q(1.5), 4,Q(1.5), 0,Q(1.5) }, /* 3Mb/s */ - { 4,Q( 4.5),3,Q( 3), 4,Q(1.5), 2,Q(1.5) }, /* 4.5Mb/s */ - { 4,Q( 6),3,Q(4.5), 4,Q( 3), 2,Q(1.5) }, /* 6Mb/s */ - { 4,Q( 9),3,Q( 6), 4,Q(4.5), 2,Q(1.5) }, /* 9Mb/s */ - { 4,Q( 12),3,Q( 9), 4,Q( 6), 2,Q( 3) }, /* 12Mb/s */ - { 4,Q(13.5),3,Q( 12), 4,Q( 9), 2,Q( 6) } /*13.5Mb/s */ -}; -#undef Q + try[0] = sched->t0; + try[1] = sched->t1; + try[2] = sched->t2; + try[3] = sched->t3; +} void ath_rate_setupxtxdesc(struct ath_softc *sc, struct ath_node *an, @@ -462,18 +502,19 @@ update_stats(struct ath_softc *sc, struct ath_node *an, const int size_bin = size_to_bin(frame_size); const int size = bin_to_size(size_bin); int tt, tries_so_far; + int is_ht40 = (an->an_node.ni_chw == 40); if (!IS_RATE_DEFINED(sn, rix0)) return; tt = calc_usecs_unicast_packet(sc, size, rix0, short_tries, - MIN(tries0, tries) - 1); + MIN(tries0, tries) - 1, is_ht40); tries_so_far = tries0; if (tries1 && tries_so_far < tries) { if (!IS_RATE_DEFINED(sn, rix1)) return; tt += calc_usecs_unicast_packet(sc, size, rix1, short_tries, - MIN(tries1 + tries_so_far, tries) - tries_so_far - 1); + MIN(tries1 + tries_so_far, tries) - tries_so_far - 1, is_ht40); tries_so_far += tries1; } @@ -481,7 +522,7 @@ update_stats(struct ath_softc *sc, struct ath_node *an, if (!IS_RATE_DEFINED(sn, rix2)) return; tt += calc_usecs_unicast_packet(sc, size, rix2, short_tries, - MIN(tries2 + tries_so_far, tries) - tries_so_far - 1); + MIN(tries2 + tries_so_far, tries) - tries_so_far - 1, is_ht40); tries_so_far += tries2; } @@ -489,7 +530,7 @@ update_stats(struct ath_softc *sc, struct ath_node *an, if (!IS_RATE_DEFINED(sn, rix3)) return; tt += calc_usecs_unicast_packet(sc, size, rix3, short_tries, - MIN(tries3 + tries_so_far, tries) - tries_so_far - 1); + MIN(tries3 + tries_so_far, tries) - tries_so_far - 1, is_ht40); } if (sn->stats[size_bin][rix0].total_packets < ssc->smoothing_minpackets) { @@ -588,11 +629,12 @@ ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an, * Only one rate was used; optimize work. */ IEEE80211_NOTE(an->an_node.ni_vap, IEEE80211_MSG_RATECTL, - &an->an_node, "%s: size %d %s rate/try %d/%d/%d", + &an->an_node, "%s: size %d (%d bytes) %s rate/try %d %s/%d/%d", __func__, bin_to_size(size_to_bin(frame_size)), + frame_size, ts->ts_status ? "FAIL" : "OK", - final_rix, short_tries, long_tries); + dot11rate(rt, final_rix), dot11rate_label(rt, final_rix), short_tries, long_tries); update_stats(sc, an, frame_size, final_rix, long_tries, 0, 0, @@ -600,60 +642,37 @@ ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an, 0, 0, short_tries, long_tries, ts->ts_status); } else { - int hwrate0, rix0, tries0; - int hwrate1, rix1, tries1; - int hwrate2, rix2, tries2; - int hwrate3, rix3, tries3; + int hwrates[4], tries[4], rix[4]; int finalTSIdx = ts->ts_finaltsi; + int i; /* * Process intermediate rates that failed. */ - if (sc->sc_ah->ah_magic != 0x20065416) { - hwrate0 = MS(ds0->ds_ctl3, AR_XmitRate0); - hwrate1 = MS(ds0->ds_ctl3, AR_XmitRate1); - hwrate2 = MS(ds0->ds_ctl3, AR_XmitRate2); - hwrate3 = MS(ds0->ds_ctl3, AR_XmitRate3); - } else { - hwrate0 = MS(ds0->ds_ctl3, AR5416_XmitRate0); - hwrate1 = MS(ds0->ds_ctl3, AR5416_XmitRate1); - hwrate2 = MS(ds0->ds_ctl3, AR5416_XmitRate2); - hwrate3 = MS(ds0->ds_ctl3, AR5416_XmitRate3); + ath_hal_gettxcompletionrates(sc->sc_ah, ds0, hwrates, tries); + + for (i = 0; i < 4; i++) { + rix[i] = rt->rateCodeToIndex[hwrates[i]]; } - rix0 = rt->rateCodeToIndex[hwrate0]; - tries0 = MS(ds0->ds_ctl2, AR_XmitDataTries0); - - rix1 = rt->rateCodeToIndex[hwrate1]; - tries1 = MS(ds0->ds_ctl2, AR_XmitDataTries1); - - rix2 = rt->rateCodeToIndex[hwrate2]; - tries2 = MS(ds0->ds_ctl2, AR_XmitDataTries2); - - rix3 = rt->rateCodeToIndex[hwrate3]; - tries3 = MS(ds0->ds_ctl2, AR_XmitDataTries3); - IEEE80211_NOTE(an->an_node.ni_vap, IEEE80211_MSG_RATECTL, &an->an_node, -"%s: size %d finaltsidx %d tries %d %s rate/try [%d/%d %d/%d %d/%d %d/%d]", +"%s: size %d (%d bytes) finaltsidx %d tries %d %s rate/try [%d %s/%d %d %s/%d %d %s/%d %d %s/%d]", __func__, bin_to_size(size_to_bin(frame_size)), + frame_size, finalTSIdx, long_tries, ts->ts_status ? "FAIL" : "OK", - rix0, tries0, - rix1, tries1, - rix2, tries2, - rix3, tries3); + dot11rate(rt, rix[0]), dot11rate_label(rt, rix[0]), tries[0], + dot11rate(rt, rix[1]), dot11rate_label(rt, rix[1]), tries[1], + dot11rate(rt, rix[2]), dot11rate_label(rt, rix[2]), tries[2], + dot11rate(rt, rix[3]), dot11rate_label(rt, rix[3]), tries[3]); - if (tries0 && !IS_RATE_DEFINED(sn, rix0)) - badrate(ifp, 0, hwrate0, tries0, ts->ts_status); - if (tries1 && !IS_RATE_DEFINED(sn, rix1)) - badrate(ifp, 1, hwrate1, tries1, ts->ts_status); - if (tries2 && !IS_RATE_DEFINED(sn, rix2)) - badrate(ifp, 2, hwrate2, tries2, ts->ts_status); - if (tries3 && !IS_RATE_DEFINED(sn, rix3)) - badrate(ifp, 3, hwrate3, tries3, ts->ts_status); + for (i = 0; i < 4; i++) { + if (tries[i] && !IS_RATE_DEFINED(sn, rix[i])) + badrate(ifp, 0, hwrates[i], tries[i], ts->ts_status); + } /* * NB: series > 0 are not penalized for failure @@ -662,42 +681,42 @@ ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an, * sample higher rates 1 try at a time doing so * may unfairly penalize them. */ - if (tries0) { + if (tries[0]) { update_stats(sc, an, frame_size, - rix0, tries0, - rix1, tries1, - rix2, tries2, - rix3, tries3, + rix[0], tries[0], + rix[1], tries[1], + rix[2], tries[2], + rix[3], tries[3], short_tries, long_tries, - long_tries > tries0); - long_tries -= tries0; + long_tries > tries[0]); + long_tries -= tries[0]; } - if (tries1 && finalTSIdx > 0) { + if (tries[1] && finalTSIdx > 0) { update_stats(sc, an, frame_size, - rix1, tries1, - rix2, tries2, - rix3, tries3, + rix[1], tries[1], + rix[2], tries[2], + rix[3], tries[3], 0, 0, short_tries, long_tries, ts->ts_status); - long_tries -= tries1; + long_tries -= tries[1]; } - if (tries2 && finalTSIdx > 1) { + if (tries[2] && finalTSIdx > 1) { update_stats(sc, an, frame_size, - rix2, tries2, - rix3, tries3, + rix[2], tries[2], + rix[3], tries[3], 0, 0, 0, 0, short_tries, long_tries, ts->ts_status); - long_tries -= tries2; + long_tries -= tries[2]; } - if (tries3 && finalTSIdx > 2) { + if (tries[3] && finalTSIdx > 2) { update_stats(sc, an, frame_size, - rix3, tries3, + rix[3], tries[3], 0, 0, 0, 0, 0, 0, @@ -723,8 +742,8 @@ static const struct txschedule *mrr_schedules[IEEE80211_MODE_MAX+2] = { series_11a, /* IEEE80211_MODE_TURBO_A */ series_11g, /* IEEE80211_MODE_TURBO_G */ series_11a, /* IEEE80211_MODE_STURBO_A */ - series_11a, /* IEEE80211_MODE_11NA */ - series_11g, /* IEEE80211_MODE_11NG */ + series_11na, /* IEEE80211_MODE_11NA */ + series_11ng, /* IEEE80211_MODE_11NG */ series_half, /* IEEE80211_MODE_HALF */ series_quarter, /* IEEE80211_MODE_QUARTER */ }; @@ -737,11 +756,11 @@ ath_rate_ctl_reset(struct ath_softc *sc, struct ieee80211_node *ni) { #define RATE(_ix) (ni->ni_rates.rs_rates[(_ix)] & IEEE80211_RATE_VAL) #define DOT11RATE(_ix) (rt->info[(_ix)].dot11Rate & IEEE80211_RATE_VAL) +#define MCS(_ix) (ni->ni_htrates.rs_rates[_ix] | IEEE80211_RATE_MCS) struct ath_node *an = ATH_NODE(ni); - const struct ieee80211_txparam *tp = ni->ni_txparms; struct sample_node *sn = ATH_NODE_SAMPLE(an); const HAL_RATE_TABLE *rt = sc->sc_currates; - int x, y, srate, rix; + int x, y, rix; KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode)); @@ -752,30 +771,7 @@ ath_rate_ctl_reset(struct ath_softc *sc, struct ieee80211_node *ni) ("no mrr schedule for mode %u", sc->sc_curmode)); sn->static_rix = -1; - if (tp != NULL && tp->ucastrate != IEEE80211_FIXED_RATE_NONE) { - /* - * A fixed rate is to be used; ucastrate is the IEEE code - * for this rate (sans basic bit). Check this against the - * negotiated rate set for the node. Note the fixed rate - * may not be available for various reasons so we only - * setup the static rate index if the lookup is successful. - * XXX handle MCS - */ - for (srate = ni->ni_rates.rs_nrates - 1; srate >= 0; srate--) - if (RATE(srate) == tp->ucastrate) { - sn->static_rix = sc->sc_rixmap[tp->ucastrate]; - break; - } -#ifdef IEEE80211_DEBUG - if (sn->static_rix == -1) { - IEEE80211_NOTE(ni->ni_vap, - IEEE80211_MSG_RATECTL, ni, - "%s: ucastrate %u not found, nrates %u", - __func__, tp->ucastrate, - ni->ni_rates.rs_nrates); - } -#endif - } + ath_rate_update_static_rix(sc, ni); /* * Construct a bitmask of usable rates. This has all @@ -783,6 +779,22 @@ ath_rate_ctl_reset(struct ath_softc *sc, struct ieee80211_node *ni) * to be ignored for doing rate control. */ sn->ratemask = 0; + /* MCS rates */ + if (ni->ni_flags & IEEE80211_NODE_HT) { + for (x = 0; x < ni->ni_htrates.rs_nrates; x++) { + rix = sc->sc_rixmap[MCS(x)]; + if (rix == 0xff) + continue; + /* skip rates marked broken by hal */ + if (!rt->info[rix].valid) + continue; + KASSERT(rix < SAMPLE_MAXRATES, + ("mcs %u has rix %d", MCS(x), rix)); + sn->ratemask |= 1<ni_rates.rs_nrates; x++) { rix = sc->sc_rixmap[RATE(x)]; if (rix == 0xff) @@ -803,8 +815,9 @@ ath_rate_ctl_reset(struct ath_softc *sc, struct ieee80211_node *ni) for (mask = sn->ratemask, rix = 0; mask != 0; mask >>= 1, rix++) { if ((mask & 1) == 0) continue; - printf(" %d/%d", DOT11RATE(rix) / 2, - calc_usecs_unicast_packet(sc, 1600, rix, 0,0)); + printf(" %d %s/%d", dot11rate(rt, rix), dot11rate_label(rt, rix), + calc_usecs_unicast_packet(sc, 1600, rix, 0,0, + (ni->ni_chw == 40))); } printf("\n"); } @@ -833,7 +846,8 @@ ath_rate_ctl_reset(struct ath_softc *sc, struct ieee80211_node *ni) sn->stats[y][rix].last_tx = 0; sn->stats[y][rix].perfect_tx_time = - calc_usecs_unicast_packet(sc, size, rix, 0, 0); + calc_usecs_unicast_packet(sc, size, rix, 0, 0, + (ni->ni_chw == 40)); sn->stats[y][rix].average_tx_time = sn->stats[y][rix].perfect_tx_time; } @@ -871,8 +885,10 @@ sample_stats(void *arg, struct ieee80211_node *ni) ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni), sn->static_rix, sn->ratemask); for (y = 0; y < NUM_PACKET_SIZE_BINS; y++) { - printf("[%4u] cur rix %d since switch: packets %d ticks %u\n", + printf("[%4u] cur rix %d (%d %s) since switch: packets %d ticks %u\n", bin_to_size(y), sn->current_rix[y], + dot11rate(rt, sn->current_rix[y]), + dot11rate_label(rt, sn->current_rix[y]), sn->packets_since_switch[y], sn->ticks_since_switch[y]); printf("[%4u] last sample %d cur sample %d packets sent %d\n", bin_to_size(y), sn->last_sample_rix[y], @@ -887,8 +903,8 @@ sample_stats(void *arg, struct ieee80211_node *ni) for (y = 0; y < NUM_PACKET_SIZE_BINS; y++) { if (sn->stats[y][rix].total_packets == 0) continue; - printf("[%2u:%4u] %8d:%-8d (%3d%%) T %8d F %4d avg %5u last %u\n", - (rt->info[rix].dot11Rate & IEEE80211_RATE_VAL)/2, + printf("[%2u %s:%4u] %8d:%-8d (%3d%%) T %8d F %4d avg %5u last %u\n", + dot11rate(rt, rix), dot11rate_label(rt, rix), bin_to_size(y), sn->stats[y][rix].total_packets, sn->stats[y][rix].packets_acked, diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_rate/sample/sample.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_rate/sample/sample.h index 3baabdf2f7..b39e0be716 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_rate/sample/sample.h +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_rate/sample/sample.h @@ -110,53 +110,14 @@ struct sample_node { #define WIFI_CW_MIN 31 #define WIFI_CW_MAX 1023 -/* - * Definitions for pulling the rate and trie counts from - * a 5212 h/w descriptor. These Don't belong here; the - * driver should record this information so the rate control - * code doesn't go groveling around in the descriptor bits. - */ -#define ds_ctl2 ds_hw[0] -#define ds_ctl3 ds_hw[1] - -/* TX ds_ctl2 */ -#define AR_XmitDataTries0 0x000f0000 /* series 0 max attempts */ -#define AR_XmitDataTries0_S 16 -#define AR_XmitDataTries1 0x00f00000 /* series 1 max attempts */ -#define AR_XmitDataTries1_S 20 -#define AR_XmitDataTries2 0x0f000000 /* series 2 max attempts */ -#define AR_XmitDataTries2_S 24 -#define AR_XmitDataTries3 0xf0000000 /* series 3 max attempts */ -#define AR_XmitDataTries3_S 28 - -/* TX ds_ctl3 */ -#define AR_XmitRate0 0x0000001f /* series 0 tx rate */ -#define AR_XmitRate0_S 0 -#define AR_XmitRate1 0x000003e0 /* series 1 tx rate */ -#define AR_XmitRate1_S 5 -#define AR_XmitRate2 0x00007c00 /* series 2 tx rate */ -#define AR_XmitRate2_S 10 -#define AR_XmitRate3 0x000f8000 /* series 3 tx rate */ -#define AR_XmitRate3_S 15 - -/* TX ds_ctl3 for 5416 */ -#define AR5416_XmitRate0 0x000000ff /* series 0 tx rate */ -#define AR5416_XmitRate0_S 0 -#define AR5416_XmitRate1 0x0000ff00 /* series 1 tx rate */ -#define AR5416_XmitRate1_S 8 -#define AR5416_XmitRate2 0x00ff0000 /* series 2 tx rate */ -#define AR5416_XmitRate2_S 16 -#define AR5416_XmitRate3 0xff000000 /* series 3 tx rate */ -#define AR5416_XmitRate3_S 24 - -#define MS(_v, _f) (((_v) & (_f)) >> _f##_S) - /* * Calculate the transmit duration of a frame. */ static unsigned calc_usecs_unicast_packet(struct ath_softc *sc, - int length, - int rix, int short_retries, int long_retries) { + int length, + int rix, int short_retries, + int long_retries, int is_ht40) +{ const HAL_RATE_TABLE *rt = sc->sc_currates; struct ifnet *ifp = sc->sc_ifp; struct ieee80211com *ic = ifp->if_l2com; @@ -194,6 +155,11 @@ static unsigned calc_usecs_unicast_packet(struct ath_softc *sc, t_sifs = 8; t_difs = 28; break; + case IEEE80211_T_HT: + t_slot = 9; + t_sifs = 8; + t_difs = 28; + break; case IEEE80211_T_DS: /* fall through to default */ default: @@ -213,7 +179,6 @@ static unsigned calc_usecs_unicast_packet(struct ath_softc *sc, cts = 1; cix = rt->info[sc->sc_protrix].controlRate; - } if (0 /*length > ic->ic_rtsthreshold */) { @@ -233,8 +198,9 @@ static unsigned calc_usecs_unicast_packet(struct ath_softc *sc, if (rts) /* SIFS + CTS */ ctsduration += rt->info[cix].spAckDuration; - ctsduration += ath_hal_computetxtime(sc->sc_ah, - rt, length, rix, AH_TRUE); + /* XXX assumes short preamble */ + ctsduration += ath_hal_pkt_txtime(sc->sc_ah, rt, length, rix, + is_ht40, 0); if (cts) /* SIFS + ACK */ ctsduration += rt->info[cix].spAckDuration; @@ -242,9 +208,13 @@ static unsigned calc_usecs_unicast_packet(struct ath_softc *sc, tt += (short_retries + 1) * ctsduration; } tt += t_difs; + + /* XXX assumes short preamble */ + tt += (long_retries+1)*ath_hal_pkt_txtime(sc->sc_ah, rt, length, rix, + is_ht40, 0); + tt += (long_retries+1)*(t_sifs + rt->info[rix].spAckDuration); - tt += (long_retries+1)*ath_hal_computetxtime(sc->sc_ah, rt, length, - rix, AH_TRUE); + for (x = 0; x <= short_retries + long_retries; x++) { cw = MIN(WIFI_CW_MAX, (cw + 1) * 2); tt += (t_slot * cw/2); diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_rate/sample/tx_schedules.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_rate/sample/tx_schedules.h new file mode 100644 index 0000000000..dafca9a396 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/ath_rate/sample/tx_schedules.h @@ -0,0 +1,195 @@ +/*- + * Copyright (c) 2005 John Bicket + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. + * + */ +#ifndef __ATH_RATE_SAMPLE_TXSCHEDULES_H__ +#define __ATH_RATE_SAMPLE_TXSCHEDULES_H__ + +#include +#ifndef __HAIKU__ +__FBSDID("$FreeBSD$"); +#endif + +#define A(_r) \ + (((_r) == 6) ? 0 : (((_r) == 9) ? 1 : (((_r) == 12) ? 2 : \ + (((_r) == 18) ? 3 : (((_r) == 24) ? 4 : (((_r) == 36) ? 5 : \ + (((_r) == 48) ? 6 : (((_r) == 54) ? 7 : 0)))))))) +static const struct txschedule series_11a[] = { + { 3,A( 6), 3,A( 6), 0,A( 6), 0,A( 6) }, /* 6Mb/s */ + { 4,A( 9), 3,A( 6), 4,A( 6), 0,A( 6) }, /* 9Mb/s */ + { 4,A(12), 3,A( 6), 4,A( 6), 0,A( 6) }, /* 12Mb/s */ + { 4,A(18), 3,A( 12), 4,A( 6), 2,A( 6) }, /* 18Mb/s */ + { 4,A(24), 3,A( 18), 4,A( 12), 2,A( 6) }, /* 24Mb/s */ + { 4,A(36), 3,A( 24), 4,A( 18), 2,A( 6) }, /* 36Mb/s */ + { 4,A(48), 3,A( 36), 4,A( 24), 2,A(12) }, /* 48Mb/s */ + { 4,A(54), 3,A( 48), 4,A( 36), 2,A(24) } /* 54Mb/s */ +}; + +#define NA1(_r) \ + (((_r) == 6.5) ? 8 : (((_r) == 13) ? 9 : (((_r) == 19.5)? 10 : \ + (((_r) == 26) ? 11 : (((_r) == 39) ? 12 : (((_r) == 52) ? 13 : \ + (((_r) == 58.5)? 14 : (((_r) == 65) ? 15 : 0)))))))) +#define NA2(_r) \ + (((_r) == 13) ? 16 : (((_r) == 26) ? 17 : (((_r) == 39) ? 18 : \ + (((_r) == 52) ? 19 : (((_r) == 78) ? 20 : (((_r) == 104)? 21 : \ + (((_r) == 117)? 22 : (((_r) == 130)? 23 : 0)))))))) +static const struct txschedule series_11na[] = { + { 3,A( 6), 3,A( 6), 0,A( 6), 0,A( 6) }, /* 6Mb/s */ + { 4,A( 9), 3,A( 6), 4,A( 6), 0,A( 6) }, /* 9Mb/s */ + { 4,A(12), 3,A( 6), 4,A( 6), 0,A( 6) }, /* 12Mb/s */ + { 4,A(18), 3,A( 12), 4,A( 6), 2,A( 6) }, /* 18Mb/s */ + { 4,A(24), 3,A( 18), 4,A( 12), 2,A( 6) }, /* 24Mb/s */ + { 4,A(36), 3,A( 24), 4,A( 18), 2,A( 6) }, /* 36Mb/s */ + { 4,A(48), 3,A( 36), 4,A( 24), 2,A(12) }, /* 48Mb/s */ + { 4,A(54), 3,A( 48), 4,A( 36), 2,A(24) }, /* 54Mb/s */ + { 3,NA1( 6.5), 3,NA1( 6.5), 0,NA1( 6.5), 0,NA1(6.5) }, /* 6.5Mb/s */ + { 4,NA1( 13), 3,NA1( 6.5), 4,NA1( 6.5), 0,NA1(6.5) }, /* 13Mb/s */ + { 4,NA1(19.5), 3,NA1( 6.5), 4,NA1( 6.5), 0,NA1(6.5) }, /*19.5Mb/s */ + { 4,NA1( 26), 3,NA1(19.5), 4,NA1( 6.5), 2,NA1(6.5) }, /* 26Mb/s */ + { 4,NA1( 39), 3,NA1( 26), 4,NA1(19.5), 2,NA1(6.5) }, /* 39Mb/s */ + { 4,NA1( 52), 3,NA1( 39), 4,NA1( 26), 2,NA1(6.5) }, /* 52Mb/s */ + { 4,NA1(58.5), 3,NA1( 52), 4,NA1( 39), 2,NA1( 13) }, /*58.5Mb/s */ + { 4,NA1( 65), 3,NA1(58.5), 4,NA1( 52), 2,NA1( 13) }, /* 65Mb/s */ + { 3,NA2( 13), 3,NA2( 13), 0,NA2( 13), 0,NA2( 13) }, /* 13Mb/s */ + { 4,NA2( 26), 3,NA2( 13), 4,NA2( 13), 0,NA2( 13) }, /* 26Mb/s */ + { 4,NA2( 39), 3,NA2( 26), 4,NA2( 13), 2,NA2( 13) }, /* 39Mb/s */ + { 4,NA2( 52), 3,NA2( 39), 4,NA2( 26), 2,NA2( 13) }, /* 52Mb/s */ + { 4,NA2( 78), 3,NA2( 52), 4,NA2( 39), 2,NA2( 13) }, /* 78Mb/s */ + { 4,NA2( 104), 3,NA2( 78), 4,NA2( 52), 2,NA2( 13) }, /* 104Mb/s */ + { 4,NA2( 117), 3,NA2( 104), 4,NA2( 78), 2,NA2( 26) }, /* 117Mb/s */ + { 4,NA2( 130), 3,NA2( 117), 4,NA2( 104), 2,NA2( 26) } /* 130Mb/s */ +}; +#undef A +#undef NA2 +#undef NA1 + +#define G(_r) \ + (((_r) == 1) ? 0 : (((_r) == 2) ? 1 : (((_r) == 5.5) ? 2 : \ + (((_r) == 11) ? 3 : (((_r) == 6) ? 4 : (((_r) == 9) ? 5 : \ + (((_r) == 12) ? 6 : (((_r) == 18) ? 7 : (((_r) == 24) ? 8 : \ + (((_r) == 36) ? 9 : (((_r) == 48) ? 10 : (((_r) == 54) ? 11 : 0)))))))))))) +static const struct txschedule series_11g[] = { + { 3,G( 1), 3,G( 1), 0,G( 1), 0,G( 1) }, /* 1Mb/s */ + { 4,G( 2), 3,G( 1), 4,G( 1), 0,G( 1) }, /* 2Mb/s */ + { 4,G(5.5),3,G( 2), 4,G( 1), 2,G( 1) }, /* 5.5Mb/s */ + { 4,G(11), 3,G(5.5), 4,G( 2), 2,G( 1) }, /* 11Mb/s */ + { 4,G( 6), 3,G(5.5), 4,G( 2), 2,G( 1) }, /* 6Mb/s */ + { 4,G( 9), 3,G( 6), 4,G(5.5), 2,G( 1) }, /* 9Mb/s */ + { 4,G(12), 3,G( 11), 4,G(5.5), 2,G( 1) }, /* 12Mb/s */ + { 4,G(18), 3,G( 12), 4,G( 11), 2,G( 1) }, /* 18Mb/s */ + { 4,G(24), 3,G( 18), 4,G( 12), 2,G( 1) }, /* 24Mb/s */ + { 4,G(36), 3,G( 24), 4,G( 18), 2,G( 1) }, /* 36Mb/s */ + { 4,G(48), 3,G( 36), 4,G( 24), 2,G( 1) }, /* 48Mb/s */ + { 4,G(54), 3,G( 48), 4,G( 36), 2,G( 1) } /* 54Mb/s */ +}; + +#define NG1(_r) \ + (((_r) == 6.5) ? 12 : (((_r) == 13) ? 13 : (((_r) == 19.5)? 14 : \ + (((_r) == 26) ? 15 : (((_r) == 39) ? 16 : (((_r) == 52) ? 17 : \ + (((_r) == 58.5)? 18 : (((_r) == 65) ? 19 : 0)))))))) +#define NG2(_r) \ + (((_r) == 13) ? 20 : (((_r) == 26) ? 21 : (((_r) == 39) ? 22 : \ + (((_r) == 52) ? 23 : (((_r) == 78) ? 24 : (((_r) == 104) ? 25 : \ + (((_r) == 117) ? 26 : (((_r) == 130)? 27 : 0)))))))) +static const struct txschedule series_11ng[] = { + { 3,G( 1), 3,G( 1), 0,G( 1), 0,G( 1) }, /* 1Mb/s */ + { 4,G( 2), 3,G( 1), 4,G( 1), 0,G( 1) }, /* 2Mb/s */ + { 4,G(5.5),3,G( 2), 4,G( 1), 2,G( 1) }, /* 5.5Mb/s */ + { 4,G(11), 3,G(5.5), 4,G( 2), 2,G( 1) }, /* 11Mb/s */ + { 4,G( 6), 3,G(5.5), 4,G( 2), 2,G( 1) }, /* 6Mb/s */ + { 4,G( 9), 3,G( 6), 4,G(5.5), 2,G( 1) }, /* 9Mb/s */ + { 4,G(12), 3,G( 11), 4,G(5.5), 2,G( 1) }, /* 12Mb/s */ + { 4,G(18), 3,G( 12), 4,G( 11), 2,G( 1) }, /* 18Mb/s */ + { 4,G(24), 3,G( 18), 4,G( 12), 2,G( 1) }, /* 24Mb/s */ + { 4,G(36), 3,G( 24), 4,G( 18), 2,G( 1) }, /* 36Mb/s */ + { 4,G(48), 3,G( 36), 4,G( 24), 2,G( 1) }, /* 48Mb/s */ + { 4,G(54), 3,G( 48), 4,G( 36), 2,G( 1) }, /* 54Mb/s */ + { 3,NG1( 6.5), 3,NG1( 6.5), 0,NG1( 6.5), 0,NG1(6.5) }, /* 6.5Mb/s */ + { 4,NG1( 13), 3,NG1( 6.5), 4,NG1( 6.5), 0,NG1(6.5) }, /* 13Mb/s */ + { 4,NG1(19.5), 3,NG1( 6.5), 4,NG1( 6.5), 0,NG1(6.5) }, /*19.5Mb/s */ + { 4,NG1( 26), 3,NG1(19.5), 4,NG1( 6.5), 2,NG1(6.5) }, /* 26Mb/s */ + { 4,NG1( 39), 3,NG1( 26), 4,NG1(19.5), 2,NG1(6.5) }, /* 39Mb/s */ + { 4,NG1( 52), 3,NG1( 39), 4,NG1( 26), 2,NG1(6.5) }, /* 52Mb/s */ + { 4,NG1(58.5), 3,NG1( 52), 4,NG1( 39), 2,NG1( 13) }, /*58.5Mb/s */ + { 4,NG1( 65), 3,NG1(58.5), 4,NG1( 52), 2,NG1( 13) }, /* 65Mb/s */ + { 3,NG2( 13), 3,NG2( 13), 0,NG2( 13), 0,NG2( 13) }, /* 13Mb/s */ + { 4,NG2( 26), 3,NG2( 13), 4,NG2( 13), 0,NG2( 13) }, /* 26Mb/s */ + { 4,NG2( 39), 3,NG2( 26), 4,NG2( 13), 2,NG2( 13) }, /* 39Mb/s */ + { 4,NG2( 52), 3,NG2( 39), 4,NG2( 26), 2,NG2( 13) }, /* 52Mb/s */ + { 4,NG2( 78), 3,NG2( 52), 4,NG2( 39), 2,NG2( 13) }, /* 78Mb/s */ + { 4,NG2( 104), 3,NG2( 78), 4,NG2( 52), 2,NG2( 13) }, /* 104Mb/s */ + { 4,NG2( 117), 3,NG2( 104), 4,NG2( 78), 2,NG2( 26) }, /* 117Mb/s */ + { 4,NG2( 130), 3,NG2( 117), 4,NG2( 104), 2,NG2( 26) } /* 130Mb/s */ +}; +#undef G +#undef NG2 +#undef NG1 + +#define H(_r) \ + (((_r) == 3) ? 0 : (((_r) == 4.5) ? 1 : (((_r) == 6) ? 2 : \ + (((_r) == 9) ? 3 : (((_r) == 12) ? 4 : (((_r) == 18) ? 5 : \ + (((_r) == 24) ? 6 : (((_r) == 27) ? 7 : 0)))))))) +static const struct txschedule series_half[] = { + { 3,H( 3), 3,H( 3), 0,H( 3), 0,H( 3) }, /* 3Mb/s */ + { 4,H(4.5),3,H( 3), 4,H( 3), 0,H( 3) }, /* 4.5Mb/s */ + { 4,H( 6), 3,H( 3), 4,H( 3), 0,H( 3) }, /* 6Mb/s */ + { 4,H( 9), 3,H( 6), 4,H( 3), 2,H( 3) }, /* 9Mb/s */ + { 4,H(12), 3,H( 9), 4,H( 6), 2,H( 3) }, /* 12Mb/s */ + { 4,H(18), 3,H( 12), 4,H( 9), 2,H( 3) }, /* 18Mb/s */ + { 4,H(24), 3,H( 18), 4,H( 12), 2,H( 6) }, /* 24Mb/s */ + { 4,H(27), 3,H( 24), 4,H( 18), 2,H(12) } /* 27Mb/s */ +}; +#undef H + +#ifdef Q +#undef Q +#endif +#define Q(_r) \ + (((_r) == 1.5) ? 0 : (((_r) ==2.25) ? 1 : (((_r) == 3) ? 2 : \ + (((_r) == 4.5) ? 3 : (((_r) == 6) ? 4 : (((_r) == 9) ? 5 : \ + (((_r) == 12) ? 6 : (((_r) == 13.5)? 7 : 0)))))))) +static const struct txschedule series_quarter[] = { + { 3,Q( 1.5),3,Q(1.5), 0,Q(1.5), 0,Q(1.5) }, /* 1.5Mb/s */ + { 4,Q(2.25),3,Q(1.5), 4,Q(1.5), 0,Q(1.5) }, /*2.25Mb/s */ + { 4,Q( 3),3,Q(1.5), 4,Q(1.5), 0,Q(1.5) }, /* 3Mb/s */ + { 4,Q( 4.5),3,Q( 3), 4,Q(1.5), 2,Q(1.5) }, /* 4.5Mb/s */ + { 4,Q( 6),3,Q(4.5), 4,Q( 3), 2,Q(1.5) }, /* 6Mb/s */ + { 4,Q( 9),3,Q( 6), 4,Q(4.5), 2,Q(1.5) }, /* 9Mb/s */ + { 4,Q( 12),3,Q( 9), 4,Q( 6), 2,Q( 3) }, /* 12Mb/s */ + { 4,Q(13.5),3,Q( 12), 4,Q( 9), 2,Q( 6) } /*13.5Mb/s */ +}; +#undef Q + +#endif diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_ath.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_ath.c index ca048102d1..6ba6b1ae06 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_ath.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_ath.c @@ -58,6 +58,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include @@ -87,11 +88,20 @@ __FBSDID("$FreeBSD$"); #include #include /* XXX for softled */ +#include + +#include +#include +#include +#include +#include +#include #ifdef ATH_TX99_DIAG #include #endif + /* * ATH_BCBUF determines the number of vap's that can transmit * beacons and also (currently) the number of vap's that can @@ -108,15 +118,6 @@ __FBSDID("$FreeBSD$"); */ CTASSERT(ATH_BCBUF <= 8); -/* unaligned little endian access */ -#define LE_READ_2(p) \ - ((u_int16_t) \ - ((((u_int8_t *)(p))[0] ) | (((u_int8_t *)(p))[1] << 8))) -#define LE_READ_4(p) \ - ((u_int32_t) \ - ((((u_int8_t *)(p))[0] ) | (((u_int8_t *)(p))[1] << 8) | \ - (((u_int8_t *)(p))[2] << 16) | (((u_int8_t *)(p))[3] << 24))) - static struct ieee80211vap *ath_vap_create(struct ieee80211com *, const char name[IFNAMSIZ], int unit, int opmode, int flags, const uint8_t bssid[IEEE80211_ADDR_LEN], @@ -126,7 +127,6 @@ static void ath_init(void *); static void ath_stop_locked(struct ifnet *); static void ath_stop(struct ifnet *); static void ath_start(struct ifnet *); -static int ath_reset(struct ifnet *); static int ath_reset_vap(struct ieee80211vap *, u_long); static int ath_media_change(struct ifnet *); static void ath_watchdog(void *); @@ -134,15 +134,6 @@ static int ath_ioctl(struct ifnet *, u_long, caddr_t); static void ath_fatal_proc(void *, int); static void ath_bmiss_vap(struct ieee80211vap *); static void ath_bmiss_proc(void *, int); -static int ath_keyset(struct ath_softc *, const struct ieee80211_key *, - struct ieee80211_node *); -static int ath_key_alloc(struct ieee80211vap *, - struct ieee80211_key *, - ieee80211_keyix *, ieee80211_keyix *); -static int ath_key_delete(struct ieee80211vap *, - const struct ieee80211_key *); -static int ath_key_set(struct ieee80211vap *, const struct ieee80211_key *, - const u_int8_t mac[IEEE80211_ADDR_LEN]); static void ath_key_update_begin(struct ieee80211vap *); static void ath_key_update_end(struct ieee80211vap *); static void ath_update_mcast(struct ifnet *); @@ -181,9 +172,6 @@ static int ath_tx_setup(struct ath_softc *, int, int); static int ath_wme_update(struct ieee80211com *); static void ath_tx_cleanupq(struct ath_softc *, struct ath_txq *); static void ath_tx_cleanup(struct ath_softc *); -static void ath_freetx(struct mbuf *); -static int ath_tx_start(struct ath_softc *, struct ieee80211_node *, - struct ath_buf *, struct mbuf *); static void ath_tx_proc_q0(void *, int); static void ath_tx_proc_q0123(void *, int); static void ath_tx_proc(void *, int); @@ -211,11 +199,10 @@ static void ath_led_event(struct ath_softc *, int); static int ath_rate_setup(struct ath_softc *, u_int mode); static void ath_setcurmode(struct ath_softc *, enum ieee80211_phymode); -static void ath_sysctlattach(struct ath_softc *); -static int ath_raw_xmit(struct ieee80211_node *, - struct mbuf *, const struct ieee80211_bpf_params *); static void ath_announce(struct ath_softc *); +static void ath_dfs_tasklet(void *, int); + #ifdef IEEE80211_SUPPORT_TDMA static void ath_tdma_settimers(struct ath_softc *sc, u_int32_t nexttbtt, u_int32_t bintval); @@ -227,24 +214,6 @@ static void ath_tdma_update(struct ieee80211_node *ni, static void ath_tdma_beacon_send(struct ath_softc *sc, struct ieee80211vap *vap); -static __inline void -ath_hal_setcca(struct ath_hal *ah, int ena) -{ - /* - * NB: fill me in; this is not provided by default because disabling - * CCA in most locales violates regulatory. - */ -} - -static __inline int -ath_hal_getcca(struct ath_hal *ah) -{ - u_int32_t diag; - if (ath_hal_getcapability(ah, HAL_CAP_DIAG, 0, &diag) != HAL_OK) - return 1; - return ((diag & 0x500000) == 0); -} - #define TDMA_EP_MULTIPLIER (1<<10) /* pow2 to optimize out * and / */ #define TDMA_LPF_LEN 6 #define TDMA_DUMMY_MARKER 0x127 @@ -272,6 +241,9 @@ SYSCTL_INT(_hw_ath, OID_AUTO, shortcal, CTLFLAG_RW, &ath_shortcalinterval, static int ath_resetcalinterval = 20*60; /* reset cal state 20 mins */ SYSCTL_INT(_hw_ath, OID_AUTO, resetcal, CTLFLAG_RW, &ath_resetcalinterval, 0, "reset chip calibration results (secs)"); +static int ath_anicalinterval = 100; /* ANI calibration - 100 msec */ +SYSCTL_INT(_hw_ath, OID_AUTO, anical, CTLFLAG_RW, &ath_anicalinterval, + 0, "ANI calibration (msecs)"); static int ath_rxbuf = ATH_RXBUF; /* # rx buffers to allocate */ SYSCTL_INT(_hw_ath, OID_AUTO, rxbuf, CTLFLAG_RW, &ath_rxbuf, @@ -286,69 +258,12 @@ static int ath_bstuck_threshold = 4; /* max missed beacons */ SYSCTL_INT(_hw_ath, OID_AUTO, bstuck, CTLFLAG_RW, &ath_bstuck_threshold, 0, "max missed beacon xmits before chip reset"); -#ifdef ATH_DEBUG -enum { - ATH_DEBUG_XMIT = 0x00000001, /* basic xmit operation */ - ATH_DEBUG_XMIT_DESC = 0x00000002, /* xmit descriptors */ - ATH_DEBUG_RECV = 0x00000004, /* basic recv operation */ - ATH_DEBUG_RECV_DESC = 0x00000008, /* recv descriptors */ - ATH_DEBUG_RATE = 0x00000010, /* rate control */ - ATH_DEBUG_RESET = 0x00000020, /* reset processing */ - ATH_DEBUG_MODE = 0x00000040, /* mode init/setup */ - ATH_DEBUG_BEACON = 0x00000080, /* beacon handling */ - ATH_DEBUG_WATCHDOG = 0x00000100, /* watchdog timeout */ - ATH_DEBUG_INTR = 0x00001000, /* ISR */ - ATH_DEBUG_TX_PROC = 0x00002000, /* tx ISR proc */ - ATH_DEBUG_RX_PROC = 0x00004000, /* rx ISR proc */ - ATH_DEBUG_BEACON_PROC = 0x00008000, /* beacon ISR proc */ - ATH_DEBUG_CALIBRATE = 0x00010000, /* periodic calibration */ - ATH_DEBUG_KEYCACHE = 0x00020000, /* key cache management */ - ATH_DEBUG_STATE = 0x00040000, /* 802.11 state transitions */ - ATH_DEBUG_NODE = 0x00080000, /* node management */ - ATH_DEBUG_LED = 0x00100000, /* led management */ - ATH_DEBUG_FF = 0x00200000, /* fast frames */ - ATH_DEBUG_DFS = 0x00400000, /* DFS processing */ - ATH_DEBUG_TDMA = 0x00800000, /* TDMA processing */ - ATH_DEBUG_TDMA_TIMER = 0x01000000, /* TDMA timer processing */ - ATH_DEBUG_REGDOMAIN = 0x02000000, /* regulatory processing */ - ATH_DEBUG_FATAL = 0x80000000, /* fatal errors */ - ATH_DEBUG_ANY = 0xffffffff -}; -static int ath_debug = ATH_DEBUG_INTR | - ATH_DEBUG_STATE | - ATH_DEBUG_REGDOMAIN; -SYSCTL_INT(_hw_ath, OID_AUTO, debug, CTLFLAG_RW, &ath_debug, - 0, "control debugging printfs"); -TUNABLE_INT("hw.ath.debug", &ath_debug); - -#define IFF_DUMPPKTS(sc, m) \ - ((sc->sc_debug & (m)) || \ - (sc->sc_ifp->if_flags & (IFF_DEBUG|IFF_LINK2)) == (IFF_DEBUG|IFF_LINK2)) -#define DPRINTF(sc, m, fmt, ...) do { \ - if (sc->sc_debug & (m)) \ - printf(fmt, __VA_ARGS__); \ -} while (0) -#define KEYPRINTF(sc, ix, hk, mac) do { \ - if (sc->sc_debug & ATH_DEBUG_KEYCACHE) \ - ath_keyprint(sc, __func__, ix, hk, mac); \ -} while (0) -static void ath_printrxbuf(struct ath_softc *, const struct ath_buf *bf, - u_int ix, int); -static void ath_printtxbuf(struct ath_softc *, const struct ath_buf *bf, - u_int qnum, u_int ix, int done); -#else -#define IFF_DUMPPKTS(sc, m) \ - ((sc->sc_ifp->if_flags & (IFF_DEBUG|IFF_LINK2)) == (IFF_DEBUG|IFF_LINK2)) -#define DPRINTF(sc, m, fmt, ...) do { \ - (void) sc; \ -} while (0) -#define KEYPRINTF(sc, k, ix, mac) do { \ - (void) sc; \ -} while (0) -#endif - MALLOC_DEFINE(M_ATHDEV, "athdev", "ath driver dma buffers"); +#define HAL_MODE_HT20 (HAL_MODE_11NG_HT20 | HAL_MODE_11NA_HT20) +#define HAL_MODE_HT40 \ + (HAL_MODE_11NG_HT40PLUS | HAL_MODE_11NG_HT40MINUS | \ + HAL_MODE_11NA_HT40PLUS | HAL_MODE_11NA_HT40MINUS) int ath_attach(u_int16_t devid, struct ath_softc *sc) { @@ -374,7 +289,7 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) if_initname(ifp, device_get_name(sc->sc_dev), device_get_unit(sc->sc_dev)); - ah = ath_hal_attach(devid, sc, sc->sc_st, sc->sc_sh, &status); + ah = ath_hal_attach(devid, sc, sc->sc_st, sc->sc_sh, sc->sc_eepromdata, &status); if (ah == NULL) { if_printf(ifp, "unable to attach hardware; HAL status %u\n", status); @@ -542,6 +457,16 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) goto bad2; } + /* Attach DFS module */ + if (! ath_dfs_attach(sc)) { + device_printf(sc->sc_dev, "%s: unable to attach DFS\n", __func__); + error = EIO; + goto bad2; + } + + /* Start DFS processing tasklet */ + TASK_INIT(&sc->sc_dfstask, 0, ath_dfs_tasklet, sc); + sc->sc_blinking = 0; sc->sc_ledstate = 1; sc->sc_ledon = 0; /* low true */ @@ -564,8 +489,8 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) ifp->if_start = ath_start; ifp->if_ioctl = ath_ioctl; ifp->if_init = ath_init; - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); - ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); + ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; IFQ_SET_READY(&ifp->if_snd); ic->ic_ifp = ifp; @@ -585,6 +510,9 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) | IEEE80211_C_WPA /* capable of WPA1+WPA2 */ | IEEE80211_C_BGSCAN /* capable of bg scanning */ | IEEE80211_C_TXFRAG /* handle tx frags */ +#ifdef ATH_ENABLE_DFS + | IEEE80211_C_DFS /* Enable DFS radar detection */ +#endif ; /* * Query the hal to figure out h/w crypto support. @@ -666,6 +594,8 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) sc->sc_hasbmask = ath_hal_hasbssidmask(ah); sc->sc_hasbmatch = ath_hal_hasbssidmatch(ah); sc->sc_hastsfadd = ath_hal_hastsfadjust(ah); + sc->sc_rxslink = ath_hal_self_linked_final_rxdesc(ah); + sc->sc_rxtsf32 = ath_hal_has_long_rxdesc_tsf(ah); if (ath_hal_hasfastframes(ah)) ic->ic_caps |= IEEE80211_C_FF; wmodes = ath_hal_getwirelessmodes(ah); @@ -677,6 +607,64 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) ic->ic_tdma_update = ath_tdma_update; } #endif + + /* + * The if_ath 11n support is completely not ready for normal use. + * Enabling this option will likely break everything and everything. + * Don't think of doing that unless you know what you're doing. + */ + +#ifdef ATH_ENABLE_11N + /* + * Query HT capabilities + */ + if (ath_hal_getcapability(ah, HAL_CAP_HT, 0, NULL) == HAL_OK && + (wmodes & (HAL_MODE_HT20 | HAL_MODE_HT40))) { + int rxs, txs; + + device_printf(sc->sc_dev, "[HT] enabling HT modes\n"); + ic->ic_htcaps = IEEE80211_HTC_HT /* HT operation */ + | IEEE80211_HTC_AMPDU /* A-MPDU tx/rx */ + | IEEE80211_HTC_AMSDU /* A-MSDU tx/rx */ + | IEEE80211_HTCAP_MAXAMSDU_3839 /* max A-MSDU length */ + | IEEE80211_HTCAP_SMPS_OFF; /* SM power save off */ + ; + + /* + * Enable short-GI for HT20 only if the hardware + * advertises support. + * Notably, anything earlier than the AR9287 doesn't. + */ + if ((ath_hal_getcapability(ah, + HAL_CAP_HT20_SGI, 0, NULL) == HAL_OK) && + (wmodes & HAL_MODE_HT20)) { + device_printf(sc->sc_dev, + "[HT] enabling short-GI in 20MHz mode\n"); + ic->ic_htcaps |= IEEE80211_HTCAP_SHORTGI20; + } + + if (wmodes & HAL_MODE_HT40) + ic->ic_htcaps |= IEEE80211_HTCAP_CHWIDTH40 + | IEEE80211_HTCAP_SHORTGI40; + + /* + * rx/tx stream is not currently used anywhere; it needs to be taken + * into account when negotiating which MCS rates it'll receive and + * what MCS rates are available for TX. + */ + (void) ath_hal_getcapability(ah, HAL_CAP_STREAMS, 0, &rxs); + (void) ath_hal_getcapability(ah, HAL_CAP_STREAMS, 1, &txs); + + ath_hal_getrxchainmask(ah, &sc->sc_rxchainmask); + ath_hal_gettxchainmask(ah, &sc->sc_txchainmask); + + ic->ic_txstream = txs; + ic->ic_rxstream = rxs; + + device_printf(sc->sc_dev, "[HT] %d RX streams; %d TX streams\n", rxs, txs); + } +#endif + /* * Indicate we need the 802.11 header padded to a * 32-bit boundary for 4-address and QoS frames. @@ -735,6 +723,8 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) * regdomain are available from the hal. */ ath_sysctlattach(sc); + ath_sysctl_stats_attach(sc); + ath_sysctl_hal_attach(sc); if (bootverbose) ieee80211_announce(ic); @@ -782,6 +772,8 @@ ath_detach(struct ath_softc *sc) sc->sc_tx99->detach(sc->sc_tx99); #endif ath_rate_detach(sc->sc_rc); + + ath_dfs_detach(sc); ath_desc_free(sc); ath_tx_cleanup(sc); ath_hal_detach(sc->sc_ah); /* NB: sets chip in full sleep */ @@ -995,6 +987,21 @@ ath_vap_create(struct ieee80211com *ic, avp->av_bmiss = vap->iv_bmiss; vap->iv_bmiss = ath_bmiss_vap; + /* Set default parameters */ + + /* + * Anything earlier than some AR9300 series MACs don't + * support a smaller MPDU density. + */ + vap->iv_ampdu_density = IEEE80211_HTCAP_MPDUDENSITY_8; + /* + * All NICs can handle the maximum size, however + * AR5416 based MACs can only TX aggregates w/ RTS + * protection when the total aggregate size is <= 8k. + * However, for now that's enforced by the TX path. + */ + vap->iv_ampdu_rxmax = IEEE80211_HTCAP_MAXRXAMPDU_64K; + avp->av_bslot = -1; if (needbeacon) { /* @@ -1241,6 +1248,10 @@ ath_resume(struct ath_softc *sc) sc->sc_curchan != NULL ? sc->sc_curchan : ic->ic_curchan, AH_FALSE, &status); ath_reset_keycache(sc); + + /* Let DFS at it in case it's a DFS channel */ + ath_dfs_radar_enable(sc, ic->ic_curchan); + if (sc->sc_resume_up) { if (ic->ic_opmode == IEEE80211_M_STA) { ath_init(sc); @@ -1262,6 +1273,8 @@ ath_resume(struct ath_softc *sc) HAL_GPIO_MUX_MAC_NETWORK_LED); ath_hal_gpioset(ah, sc->sc_ledpin, !sc->sc_ledon); } + + /* XXX beacons ? */ } void @@ -1285,7 +1298,7 @@ ath_intr(void *arg) struct ath_softc *sc = arg; struct ifnet *ifp = sc->sc_ifp; struct ath_hal *ah = sc->sc_ah; - HAL_INT status; + HAL_INT status = 0; #if !defined(__HAIKU__) if (sc->sc_invalid) { @@ -1322,6 +1335,11 @@ ath_intr(void *arg) #endif DPRINTF(sc, ATH_DEBUG_INTR, "%s: status 0x%x\n", __func__, status); status &= sc->sc_imask; /* discard unasked for bits */ + + /* Short-circuit un-handled interrupts */ + if (status == 0x0) + return; + if (status & HAL_INT_FATAL) { sc->sc_stats.ast_hardware++; ath_hal_intrset(ah, 0); /* disable intr's until reset */ @@ -1360,13 +1378,32 @@ ath_intr(void *arg) } } if (status & HAL_INT_RXEOL) { + int imask = sc->sc_imask; /* * NB: the hardware should re-read the link when * RXE bit is written, but it doesn't work at * least on older hardware revs. */ sc->sc_stats.ast_rxeol++; + /* + * Disable RXEOL/RXORN - prevent an interrupt + * storm until the PCU logic can be reset. + * In case the interface is reset some other + * way before "sc_kickpcu" is called, don't + * modify sc_imask - that way if it is reset + * by a call to ath_reset() somehow, the + * interrupt mask will be correctly reprogrammed. + */ + imask &= ~(HAL_INT_RXEOL | HAL_INT_RXORN); + ath_hal_intrset(ah, imask); + /* + * Enqueue an RX proc, to handled whatever + * is in the RX queue. + * This will then kick the PCU. + */ + taskqueue_enqueue(sc->sc_tq, &sc->sc_rxtask); sc->sc_rxlink = NULL; + sc->sc_kickpcu = 1; } if (status & HAL_INT_TXURN) { sc->sc_stats.ast_txurn++; @@ -1381,6 +1418,10 @@ ath_intr(void *arg) sc->sc_stats.ast_bmiss++; taskqueue_enqueue(sc->sc_tq, &sc->sc_bmisstask); } + if (status & HAL_INT_GTT) + sc->sc_stats.ast_tx_timeout++; + if (status & HAL_INT_CST) + sc->sc_stats.ast_tx_cst++; if (status & HAL_INT_MIB) { sc->sc_stats.ast_mib++; /* @@ -1466,7 +1507,7 @@ ath_hal_gethangstate(struct ath_hal *ah, uint32_t mask, uint32_t *hangs) uint32_t rsize; void *sp; - if (!ath_hal_getdiagstate(ah, 32, &mask, sizeof(mask), &sp, &rsize)) + if (!ath_hal_getdiagstate(ah, HAL_DIAG_CHECK_HANGS, &mask, sizeof(mask), &sp, &rsize)) return 0; KASSERT(rsize == sizeof(uint32_t), ("resultsize %u", rsize)); *hangs = *(uint32_t *)sp; @@ -1547,6 +1588,9 @@ ath_init(void *arg) } ath_chan_change(sc, ic->ic_curchan); + /* Let DFS at it in case it's a DFS channel */ + ath_dfs_radar_enable(sc, ic->ic_curchan); + /* * Likewise this is set during reset so update * state cached in the driver. @@ -1555,6 +1599,15 @@ ath_init(void *arg) sc->sc_lastlongcal = 0; sc->sc_resetcal = 1; sc->sc_lastcalreset = 0; + sc->sc_lastani = 0; + sc->sc_lastshortcal = 0; + sc->sc_doresetcal = AH_FALSE; + /* + * Beacon timers were cleared here; give ath_newstate() + * a hint that the beacon timers should be poked when + * things transition to the RUN state. + */ + sc->sc_beacons = 0; /* * Setup the hardware after reset: the key cache @@ -1582,6 +1635,13 @@ ath_init(void *arg) if (sc->sc_needmib && ic->ic_opmode == IEEE80211_M_STA) sc->sc_imask |= HAL_INT_MIB; + /* Enable global TX timeout and carrier sense timeout if available */ + if (ath_hal_gtxto_supported(ah)) + sc->sc_imask |= HAL_INT_GTT; + + DPRINTF(sc, ATH_DEBUG_RESET, "%s: imask=0x%x\n", + __func__, sc->sc_imask); + ifp->if_drv_flags |= IFF_DRV_RUNNING; callout_reset(&sc->sc_wd_ch, hz, ath_watchdog, sc); ath_hal_intrset(ah, sc->sc_imask); @@ -1665,7 +1725,7 @@ ath_stop(struct ifnet *ifp) * operational state. Used to recover from various errors and * to reset or reload hardware state. */ -static int +int ath_reset(struct ifnet *ifp) { struct ath_softc *sc = ifp->if_softc; @@ -1682,6 +1742,10 @@ ath_reset(struct ifnet *ifp) if_printf(ifp, "%s: unable to reset hardware; hal status %u\n", __func__, status); sc->sc_diversity = ath_hal_getdiversity(ah); + + /* Let DFS at it in case it's a DFS channel */ + ath_dfs_radar_enable(sc, ic->ic_curchan); + if (ath_startrecv(sc) != 0) /* restart recv */ if_printf(ifp, "%s: unable to start recv logic\n", __func__); /* @@ -1726,7 +1790,7 @@ ath_reset_vap(struct ieee80211vap *vap, u_long cmd) return ath_reset(ifp); } -static struct ath_buf * +struct ath_buf * _ath_getbuf_locked(struct ath_softc *sc) { struct ath_buf *bf; @@ -1746,7 +1810,7 @@ _ath_getbuf_locked(struct ath_softc *sc) return bf; } -static struct ath_buf * +struct ath_buf * ath_getbuf(struct ath_softc *sc) { struct ath_buf *bf; @@ -1764,54 +1828,6 @@ ath_getbuf(struct ath_softc *sc) return bf; } -/* - * Cleanup driver resources when we run out of buffers - * while processing fragments; return the tx buffers - * allocated and drop node references. - */ -static void -ath_txfrag_cleanup(struct ath_softc *sc, - ath_bufhead *frags, struct ieee80211_node *ni) -{ - struct ath_buf *bf, *next; - - ATH_TXBUF_LOCK_ASSERT(sc); - - STAILQ_FOREACH_SAFE(bf, frags, bf_list, next) { - /* NB: bf assumed clean */ - STAILQ_REMOVE_HEAD(frags, bf_list); - STAILQ_INSERT_HEAD(&sc->sc_txbuf, bf, bf_list); - ieee80211_node_decref(ni); - } -} - -/* - * Setup xmit of a fragmented frame. Allocate a buffer - * for each frag and bump the node reference count to - * reflect the held reference to be setup by ath_tx_start. - */ -static int -ath_txfrag_setup(struct ath_softc *sc, ath_bufhead *frags, - struct mbuf *m0, struct ieee80211_node *ni) -{ - struct mbuf *m; - struct ath_buf *bf; - - ATH_TXBUF_LOCK(sc); - for (m = m0->m_nextpkt; m != NULL; m = m->m_nextpkt) { - bf = _ath_getbuf_locked(sc); - if (bf == NULL) { /* out of buffers, cleanup */ - ath_txfrag_cleanup(sc, frags, ni); - break; - } - ieee80211_node_incref(ni); - STAILQ_INSERT_TAIL(frags, bf, bf_list); - } - ATH_TXBUF_UNLOCK(sc); - - return !STAILQ_EMPTY(frags); -} - static void ath_start(struct ifnet *ifp) { @@ -1916,424 +1932,6 @@ ath_media_change(struct ifnet *ifp) return (error == ENETRESET ? 0 : error); } -#ifdef ATH_DEBUG -static void -ath_keyprint(struct ath_softc *sc, const char *tag, u_int ix, - const HAL_KEYVAL *hk, const u_int8_t mac[IEEE80211_ADDR_LEN]) -{ - static const char *ciphers[] = { - "WEP", - "AES-OCB", - "AES-CCM", - "CKIP", - "TKIP", - "CLR", - }; - int i, n; - - printf("%s: [%02u] %-7s ", tag, ix, ciphers[hk->kv_type]); - for (i = 0, n = hk->kv_len; i < n; i++) - printf("%02x", hk->kv_val[i]); - printf(" mac %s", ether_sprintf(mac)); - if (hk->kv_type == HAL_CIPHER_TKIP) { - printf(" %s ", sc->sc_splitmic ? "mic" : "rxmic"); - for (i = 0; i < sizeof(hk->kv_mic); i++) - printf("%02x", hk->kv_mic[i]); - if (!sc->sc_splitmic) { - printf(" txmic "); - for (i = 0; i < sizeof(hk->kv_txmic); i++) - printf("%02x", hk->kv_txmic[i]); - } - } - printf("\n"); -} -#endif - -/* - * Set a TKIP key into the hardware. This handles the - * potential distribution of key state to multiple key - * cache slots for TKIP. - */ -static int -ath_keyset_tkip(struct ath_softc *sc, const struct ieee80211_key *k, - HAL_KEYVAL *hk, const u_int8_t mac[IEEE80211_ADDR_LEN]) -{ -#define IEEE80211_KEY_XR (IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV) - static const u_int8_t zerobssid[IEEE80211_ADDR_LEN]; - struct ath_hal *ah = sc->sc_ah; - - KASSERT(k->wk_cipher->ic_cipher == IEEE80211_CIPHER_TKIP, - ("got a non-TKIP key, cipher %u", k->wk_cipher->ic_cipher)); - if ((k->wk_flags & IEEE80211_KEY_XR) == IEEE80211_KEY_XR) { - if (sc->sc_splitmic) { - /* - * TX key goes at first index, RX key at the rx index. - * The hal handles the MIC keys at index+64. - */ - memcpy(hk->kv_mic, k->wk_txmic, sizeof(hk->kv_mic)); - KEYPRINTF(sc, k->wk_keyix, hk, zerobssid); - if (!ath_hal_keyset(ah, k->wk_keyix, hk, zerobssid)) - return 0; - - memcpy(hk->kv_mic, k->wk_rxmic, sizeof(hk->kv_mic)); - KEYPRINTF(sc, k->wk_keyix+32, hk, mac); - /* XXX delete tx key on failure? */ - return ath_hal_keyset(ah, k->wk_keyix+32, hk, mac); - } else { - /* - * Room for both TX+RX MIC keys in one key cache - * slot, just set key at the first index; the hal - * will handle the rest. - */ - memcpy(hk->kv_mic, k->wk_rxmic, sizeof(hk->kv_mic)); - memcpy(hk->kv_txmic, k->wk_txmic, sizeof(hk->kv_txmic)); - KEYPRINTF(sc, k->wk_keyix, hk, mac); - return ath_hal_keyset(ah, k->wk_keyix, hk, mac); - } - } else if (k->wk_flags & IEEE80211_KEY_XMIT) { - if (sc->sc_splitmic) { - /* - * NB: must pass MIC key in expected location when - * the keycache only holds one MIC key per entry. - */ - memcpy(hk->kv_mic, k->wk_txmic, sizeof(hk->kv_txmic)); - } else - memcpy(hk->kv_txmic, k->wk_txmic, sizeof(hk->kv_txmic)); - KEYPRINTF(sc, k->wk_keyix, hk, mac); - return ath_hal_keyset(ah, k->wk_keyix, hk, mac); - } else if (k->wk_flags & IEEE80211_KEY_RECV) { - memcpy(hk->kv_mic, k->wk_rxmic, sizeof(hk->kv_mic)); - KEYPRINTF(sc, k->wk_keyix, hk, mac); - return ath_hal_keyset(ah, k->wk_keyix, hk, mac); - } - return 0; -#undef IEEE80211_KEY_XR -} - -/* - * Set a net80211 key into the hardware. This handles the - * potential distribution of key state to multiple key - * cache slots for TKIP with hardware MIC support. - */ -static int -ath_keyset(struct ath_softc *sc, const struct ieee80211_key *k, - struct ieee80211_node *bss) -{ -#define N(a) (sizeof(a)/sizeof(a[0])) - static const u_int8_t ciphermap[] = { - HAL_CIPHER_WEP, /* IEEE80211_CIPHER_WEP */ - HAL_CIPHER_TKIP, /* IEEE80211_CIPHER_TKIP */ - HAL_CIPHER_AES_OCB, /* IEEE80211_CIPHER_AES_OCB */ - HAL_CIPHER_AES_CCM, /* IEEE80211_CIPHER_AES_CCM */ - (u_int8_t) -1, /* 4 is not allocated */ - HAL_CIPHER_CKIP, /* IEEE80211_CIPHER_CKIP */ - HAL_CIPHER_CLR, /* IEEE80211_CIPHER_NONE */ - }; - struct ath_hal *ah = sc->sc_ah; - const struct ieee80211_cipher *cip = k->wk_cipher; - u_int8_t gmac[IEEE80211_ADDR_LEN]; - const u_int8_t *mac; - HAL_KEYVAL hk; - - memset(&hk, 0, sizeof(hk)); - /* - * Software crypto uses a "clear key" so non-crypto - * state kept in the key cache are maintained and - * so that rx frames have an entry to match. - */ - if ((k->wk_flags & IEEE80211_KEY_SWCRYPT) == 0) { - KASSERT(cip->ic_cipher < N(ciphermap), - ("invalid cipher type %u", cip->ic_cipher)); - hk.kv_type = ciphermap[cip->ic_cipher]; - hk.kv_len = k->wk_keylen; - memcpy(hk.kv_val, k->wk_key, k->wk_keylen); - } else - hk.kv_type = HAL_CIPHER_CLR; - - if ((k->wk_flags & IEEE80211_KEY_GROUP) && sc->sc_mcastkey) { - /* - * Group keys on hardware that supports multicast frame - * key search use a MAC that is the sender's address with - * the high bit set instead of the app-specified address. - */ - IEEE80211_ADDR_COPY(gmac, bss->ni_macaddr); - gmac[0] |= 0x80; - mac = gmac; - } else - mac = k->wk_macaddr; - - if (hk.kv_type == HAL_CIPHER_TKIP && - (k->wk_flags & IEEE80211_KEY_SWMIC) == 0) { - return ath_keyset_tkip(sc, k, &hk, mac); - } else { - KEYPRINTF(sc, k->wk_keyix, &hk, mac); - return ath_hal_keyset(ah, k->wk_keyix, &hk, mac); - } -#undef N -} - -/* - * Allocate tx/rx key slots for TKIP. We allocate two slots for - * each key, one for decrypt/encrypt and the other for the MIC. - */ -static u_int16_t -key_alloc_2pair(struct ath_softc *sc, - ieee80211_keyix *txkeyix, ieee80211_keyix *rxkeyix) -{ -#define N(a) (sizeof(a)/sizeof(a[0])) - u_int i, keyix; - - KASSERT(sc->sc_splitmic, ("key cache !split")); - /* XXX could optimize */ - for (i = 0; i < N(sc->sc_keymap)/4; i++) { - u_int8_t b = sc->sc_keymap[i]; - if (b != 0xff) { - /* - * One or more slots in this byte are free. - */ - keyix = i*NBBY; - while (b & 1) { - again: - keyix++; - b >>= 1; - } - /* XXX IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV */ - if (isset(sc->sc_keymap, keyix+32) || - isset(sc->sc_keymap, keyix+64) || - isset(sc->sc_keymap, keyix+32+64)) { - /* full pair unavailable */ - /* XXX statistic */ - if (keyix == (i+1)*NBBY) { - /* no slots were appropriate, advance */ - continue; - } - goto again; - } - setbit(sc->sc_keymap, keyix); - setbit(sc->sc_keymap, keyix+64); - setbit(sc->sc_keymap, keyix+32); - setbit(sc->sc_keymap, keyix+32+64); - DPRINTF(sc, ATH_DEBUG_KEYCACHE, - "%s: key pair %u,%u %u,%u\n", - __func__, keyix, keyix+64, - keyix+32, keyix+32+64); - *txkeyix = keyix; - *rxkeyix = keyix+32; - return 1; - } - } - DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s: out of pair space\n", __func__); - return 0; -#undef N -} - -/* - * Allocate tx/rx key slots for TKIP. We allocate two slots for - * each key, one for decrypt/encrypt and the other for the MIC. - */ -static u_int16_t -key_alloc_pair(struct ath_softc *sc, - ieee80211_keyix *txkeyix, ieee80211_keyix *rxkeyix) -{ -#define N(a) (sizeof(a)/sizeof(a[0])) - u_int i, keyix; - - KASSERT(!sc->sc_splitmic, ("key cache split")); - /* XXX could optimize */ - for (i = 0; i < N(sc->sc_keymap)/4; i++) { - u_int8_t b = sc->sc_keymap[i]; - if (b != 0xff) { - /* - * One or more slots in this byte are free. - */ - keyix = i*NBBY; - while (b & 1) { - again: - keyix++; - b >>= 1; - } - if (isset(sc->sc_keymap, keyix+64)) { - /* full pair unavailable */ - /* XXX statistic */ - if (keyix == (i+1)*NBBY) { - /* no slots were appropriate, advance */ - continue; - } - goto again; - } - setbit(sc->sc_keymap, keyix); - setbit(sc->sc_keymap, keyix+64); - DPRINTF(sc, ATH_DEBUG_KEYCACHE, - "%s: key pair %u,%u\n", - __func__, keyix, keyix+64); - *txkeyix = *rxkeyix = keyix; - return 1; - } - } - DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s: out of pair space\n", __func__); - return 0; -#undef N -} - -/* - * Allocate a single key cache slot. - */ -static int -key_alloc_single(struct ath_softc *sc, - ieee80211_keyix *txkeyix, ieee80211_keyix *rxkeyix) -{ -#define N(a) (sizeof(a)/sizeof(a[0])) - u_int i, keyix; - - /* XXX try i,i+32,i+64,i+32+64 to minimize key pair conflicts */ - for (i = 0; i < N(sc->sc_keymap); i++) { - u_int8_t b = sc->sc_keymap[i]; - if (b != 0xff) { - /* - * One or more slots are free. - */ - keyix = i*NBBY; - while (b & 1) - keyix++, b >>= 1; - setbit(sc->sc_keymap, keyix); - DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s: key %u\n", - __func__, keyix); - *txkeyix = *rxkeyix = keyix; - return 1; - } - } - DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s: out of space\n", __func__); - return 0; -#undef N -} - -/* - * Allocate one or more key cache slots for a uniacst key. The - * key itself is needed only to identify the cipher. For hardware - * TKIP with split cipher+MIC keys we allocate two key cache slot - * pairs so that we can setup separate TX and RX MIC keys. Note - * that the MIC key for a TKIP key at slot i is assumed by the - * hardware to be at slot i+64. This limits TKIP keys to the first - * 64 entries. - */ -static int -ath_key_alloc(struct ieee80211vap *vap, struct ieee80211_key *k, - ieee80211_keyix *keyix, ieee80211_keyix *rxkeyix) -{ - struct ath_softc *sc = vap->iv_ic->ic_ifp->if_softc; - - /* - * Group key allocation must be handled specially for - * parts that do not support multicast key cache search - * functionality. For those parts the key id must match - * the h/w key index so lookups find the right key. On - * parts w/ the key search facility we install the sender's - * mac address (with the high bit set) and let the hardware - * find the key w/o using the key id. This is preferred as - * it permits us to support multiple users for adhoc and/or - * multi-station operation. - */ - if (k->wk_keyix != IEEE80211_KEYIX_NONE) { - /* - * Only global keys should have key index assigned. - */ - if (!(&vap->iv_nw_keys[0] <= k && - k < &vap->iv_nw_keys[IEEE80211_WEP_NKID])) { - /* should not happen */ - DPRINTF(sc, ATH_DEBUG_KEYCACHE, - "%s: bogus group key\n", __func__); - return 0; - } - if (vap->iv_opmode != IEEE80211_M_HOSTAP || - !(k->wk_flags & IEEE80211_KEY_GROUP) || - !sc->sc_mcastkey) { - /* - * XXX we pre-allocate the global keys so - * have no way to check if they've already - * been allocated. - */ - *keyix = *rxkeyix = k - vap->iv_nw_keys; - return 1; - } - /* - * Group key and device supports multicast key search. - */ - k->wk_keyix = IEEE80211_KEYIX_NONE; - } - - /* - * We allocate two pair for TKIP when using the h/w to do - * the MIC. For everything else, including software crypto, - * we allocate a single entry. Note that s/w crypto requires - * a pass-through slot on the 5211 and 5212. The 5210 does - * not support pass-through cache entries and we map all - * those requests to slot 0. - */ - if (k->wk_flags & IEEE80211_KEY_SWCRYPT) { - return key_alloc_single(sc, keyix, rxkeyix); - } else if (k->wk_cipher->ic_cipher == IEEE80211_CIPHER_TKIP && - (k->wk_flags & IEEE80211_KEY_SWMIC) == 0) { - if (sc->sc_splitmic) - return key_alloc_2pair(sc, keyix, rxkeyix); - else - return key_alloc_pair(sc, keyix, rxkeyix); - } else { - return key_alloc_single(sc, keyix, rxkeyix); - } -} - -/* - * Delete an entry in the key cache allocated by ath_key_alloc. - */ -static int -ath_key_delete(struct ieee80211vap *vap, const struct ieee80211_key *k) -{ - struct ath_softc *sc = vap->iv_ic->ic_ifp->if_softc; - struct ath_hal *ah = sc->sc_ah; - const struct ieee80211_cipher *cip = k->wk_cipher; - u_int keyix = k->wk_keyix; - - DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s: delete key %u\n", __func__, keyix); - - ath_hal_keyreset(ah, keyix); - /* - * Handle split tx/rx keying required for TKIP with h/w MIC. - */ - if (cip->ic_cipher == IEEE80211_CIPHER_TKIP && - (k->wk_flags & IEEE80211_KEY_SWMIC) == 0 && sc->sc_splitmic) - ath_hal_keyreset(ah, keyix+32); /* RX key */ - if (keyix >= IEEE80211_WEP_NKID) { - /* - * Don't touch keymap entries for global keys so - * they are never considered for dynamic allocation. - */ - clrbit(sc->sc_keymap, keyix); - if (cip->ic_cipher == IEEE80211_CIPHER_TKIP && - (k->wk_flags & IEEE80211_KEY_SWMIC) == 0) { - clrbit(sc->sc_keymap, keyix+64); /* TX key MIC */ - if (sc->sc_splitmic) { - /* +32 for RX key, +32+64 for RX key MIC */ - clrbit(sc->sc_keymap, keyix+32); - clrbit(sc->sc_keymap, keyix+32+64); - } - } - } - return 1; -} - -/* - * Set the key cache contents for the specified key. Key cache - * slot(s) must already have been allocated by ath_key_alloc. - */ -static int -ath_key_set(struct ieee80211vap *vap, const struct ieee80211_key *k, - const u_int8_t mac[IEEE80211_ADDR_LEN]) -{ - struct ath_softc *sc = vap->iv_ic->ic_ifp->if_softc; - - return ath_keyset(sc, k, vap->iv_bss); -} - /* * Block/unblock tx+rx processing while a key change is done. * We assume the caller serializes key management operations @@ -2389,7 +1987,6 @@ ath_key_update_end(struct ieee80211vap *vap) * - when operating in mesh mode to detect neighbors * o accept control frames: * - when in monitor mode - * XXX BAR frames for 11n * XXX HT protection for 11n */ static u_int32_t @@ -2419,6 +2016,17 @@ ath_calcrxfilter(struct ath_softc *sc) if (ic->ic_opmode == IEEE80211_M_HOSTAP && IEEE80211_IS_CHAN_ANYG(ic->ic_curchan)) rfilt |= HAL_RX_FILTER_BEACON; + + /* + * Enable hardware PS-POLL RX only for hostap mode; + * STA mode sends PS-POLL frames but never + * receives them. + */ + if (ath_hal_getcapability(sc->sc_ah, HAL_CAP_PSPOLL, + 0, NULL) == HAL_OK && + ic->ic_opmode == IEEE80211_M_HOSTAP) + rfilt |= HAL_RX_FILTER_PSPOLL; + if (sc->sc_nmeshvaps) { rfilt |= HAL_RX_FILTER_BEACON; if (sc->sc_hasbmatch) @@ -2428,6 +2036,18 @@ ath_calcrxfilter(struct ath_softc *sc) } if (ic->ic_opmode == IEEE80211_M_MONITOR) rfilt |= HAL_RX_FILTER_CONTROL; + + if (sc->sc_dodfs) { + rfilt |= HAL_RX_FILTER_PHYRADAR; + } + + /* + * Enable RX of compressed BAR frames only when doing + * 802.11n. Required for A-MPDU. + */ + if (IEEE80211_IS_CHAN_HT(ic->ic_curchan)) + rfilt |= HAL_RX_FILTER_COMPBAR; + DPRINTF(sc, ATH_DEBUG_MODE, "%s: RX filter 0x%x, %s if_flags 0x%x\n", __func__, rfilt, ieee80211_opmode_name[ic->ic_opmode], ifp->if_flags); return rfilt; @@ -2832,6 +2452,7 @@ ath_beacon_proc(void *arg, int pending) */ if (ath_hal_numtxpending(ah, sc->sc_bhalq) != 0) { sc->sc_bmisscount++; + sc->sc_stats.ast_be_missed++; DPRINTF(sc, ATH_DEBUG_BEACON, "%s: missed %u consecutive beacons\n", __func__, sc->sc_bmisscount); @@ -3324,16 +2945,31 @@ ath_descdma_setup(struct ath_softc *sc, { #define DS2PHYS(_dd, _ds) \ ((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc)) +#define ATH_DESC_4KB_BOUND_CHECK(_daddr, _len) \ + ((((u_int32_t)(_daddr) & 0xFFF) > (0x1000 - (_len))) ? 1 : 0) struct ifnet *ifp = sc->sc_ifp; - struct ath_desc *ds; + uint8_t *ds; struct ath_buf *bf; int i, bsize, error; + int desc_len; + + desc_len = sizeof(struct ath_desc); DPRINTF(sc, ATH_DEBUG_RESET, "%s: %s DMA: %u buffers %u desc/buf\n", __func__, name, nbuf, ndesc); dd->dd_name = name; - dd->dd_desc_len = sizeof(struct ath_desc) * nbuf * ndesc; + dd->dd_desc_len = desc_len * nbuf * ndesc; + + /* + * Merlin work-around: + * Descriptors that cross the 4KB boundary can't be used. + * Assume one skipped descriptor per 4KB page. + */ + if (! ath_hal_split4ktrans(sc->sc_ah)) { + int numdescpage = 4096 / (desc_len * ndesc); + dd->dd_desc_len = (nbuf / numdescpage + 1) * 4096; + } /* * Setup DMA descriptor area. @@ -3382,7 +3018,7 @@ ath_descdma_setup(struct ath_softc *sc, goto fail2; } - ds = dd->dd_desc; + ds = (uint8_t *) dd->dd_desc; DPRINTF(sc, ATH_DEBUG_RESET, "%s: %s DMA map: %p (%lu) -> %p (%lu)\n", __func__, dd->dd_name, ds, (u_long) dd->dd_desc_len, (caddr_t) dd->dd_desc_paddr, /*XXX*/ (u_long) dd->dd_desc_len); @@ -3398,9 +3034,23 @@ ath_descdma_setup(struct ath_softc *sc, dd->dd_bufptr = bf; STAILQ_INIT(head); - for (i = 0; i < nbuf; i++, bf++, ds += ndesc) { - bf->bf_desc = ds; + for (i = 0; i < nbuf; i++, bf++, ds += (ndesc * desc_len)) { + bf->bf_desc = (struct ath_desc *) ds; bf->bf_daddr = DS2PHYS(dd, ds); + if (! ath_hal_split4ktrans(sc->sc_ah)) { + /* + * Merlin WAR: Skip descriptor addresses which + * cause 4KB boundary crossing along any point + * in the descriptor. + */ + if (ATH_DESC_4KB_BOUND_CHECK(bf->bf_daddr, + desc_len * ndesc)) { + /* Start at the next page */ + ds += 0x1000 - (bf->bf_daddr & 0xFFF); + bf->bf_desc = (struct ath_desc *) ds; + bf->bf_daddr = DS2PHYS(dd, ds); + } + } error = bus_dmamap_create(sc->sc_dmat, BUS_DMA_NOWAIT, &bf->bf_dmamap); if (error != 0) { @@ -3423,6 +3073,7 @@ fail0: memset(dd, 0, sizeof(*dd)); return error; #undef DS2PHYS +#undef ATH_DESC_4KB_BOUND_CHECK } static void @@ -3604,8 +3255,17 @@ ath_rxbuf_init(struct ath_softc *sc, struct ath_buf *bf) * descriptor list. This insures the hardware always has * someplace to write a new frame. */ + /* + * 11N: we can no longer afford to self link the last descriptor. + * MAC acknowledges BA status as long as it copies frames to host + * buffer (or rx fifo). This can incorrectly acknowledge packets + * to a sender if last desc is self-linked. + */ ds = bf->bf_desc; - ds->ds_link = bf->bf_daddr; /* link to self */ + if (sc->sc_rxslink) + ds->ds_link = bf->bf_daddr; /* link to self */ + else + ds->ds_link = 0; /* terminate the list */ ds->ds_data = bf->bf_segs[0].ds_addr; ath_hal_setuprxdesc(ah, ds , m->m_len /* buffer size */ @@ -3623,13 +3283,48 @@ ath_rxbuf_init(struct ath_softc *sc, struct ath_buf *bf) * a full 64-bit TSF using the specified TSF. */ static __inline u_int64_t -ath_extend_tsf(u_int32_t rstamp, u_int64_t tsf) +ath_extend_tsf15(u_int32_t rstamp, u_int64_t tsf) { if ((tsf & 0x7fff) < rstamp) tsf -= 0x8000; + return ((tsf &~ 0x7fff) | rstamp); } +/* + * Extend 32-bit time stamp from rx descriptor to + * a full 64-bit TSF using the specified TSF. + */ +static __inline u_int64_t +ath_extend_tsf32(u_int32_t rstamp, u_int64_t tsf) +{ + u_int32_t tsf_low = tsf & 0xffffffff; + u_int64_t tsf64 = (tsf & ~0xffffffffULL) | rstamp; + + if (rstamp > tsf_low && (rstamp - tsf_low > 0x10000000)) + tsf64 -= 0x100000000ULL; + + if (rstamp < tsf_low && (tsf_low - rstamp > 0x10000000)) + tsf64 += 0x100000000ULL; + + return tsf64; +} + +/* + * Extend the TSF from the RX descriptor to a full 64 bit TSF. + * Earlier hardware versions only wrote the low 15 bits of the + * TSF into the RX descriptor; later versions (AR5416 and up) + * include the 32 bit TSF value. + */ +static __inline u_int64_t +ath_extend_tsf(struct ath_softc *sc, u_int32_t rstamp, u_int64_t tsf) +{ + if (sc->sc_rxtsf32) + return ath_extend_tsf32(rstamp, tsf); + else + return ath_extend_tsf15(rstamp, tsf); +} + /* * Intercept management frames to collect beacon rssi data * and to do ibss merges. @@ -3663,7 +3358,7 @@ ath_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m, if (vap->iv_opmode == IEEE80211_M_IBSS && vap->iv_state == IEEE80211_S_RUN) { uint32_t rstamp = sc->sc_lastrs->rs_tstamp; - u_int64_t tsf = ath_extend_tsf(rstamp, + uint64_t tsf = ath_extend_tsf(sc, rstamp, ath_hal_gettsf64(sc->sc_ah)); /* * Handle ibss merge as needed; check the tsf on the @@ -3735,7 +3430,7 @@ ath_rx_tap(struct ifnet *ifp, struct mbuf *m, sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_SHORTGI; } #endif - sc->sc_rx_th.wr_tsf = htole64(ath_extend_tsf(rs->rs_tstamp, tsf)); + sc->sc_rx_th.wr_tsf = htole64(ath_extend_tsf(sc, rs->rs_tstamp, tsf)); if (rs->rs_status & HAL_RXERR_CRC) sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_BADFCS; /* XXX propagate other error flags from descriptor */ @@ -3779,7 +3474,6 @@ ath_rx_proc(void *arg, int npending) struct mbuf *m; struct ieee80211_node *ni; int len, type, ngood; - u_int phyerr; HAL_STATUS status; int16_t nf; u_int64_t tsf; @@ -3791,9 +3485,16 @@ ath_rx_proc(void *arg, int npending) tsf = ath_hal_gettsf64(ah); do { bf = STAILQ_FIRST(&sc->sc_rxbuf); - if (bf == NULL) { /* NB: shouldn't happen */ + if (sc->sc_rxslink && bf == NULL) { /* NB: shouldn't happen */ if_printf(ifp, "%s: no buffer!\n", __func__); break; + } else if (bf == NULL) { + /* + * End of List: + * this can happen for non-self-linked RX chains + */ + sc->sc_stats.ast_rx_hitqueueend++; + break; } m = bf->bf_m; if (m == NULL) { /* NB: shouldn't happen */ @@ -3809,6 +3510,7 @@ ath_rx_proc(void *arg, int npending) ds = bf->bf_desc; if (ds->ds_link == bf->bf_daddr) { /* NB: never process the self-linked entry at the end */ + sc->sc_stats.ast_rx_hitqueueend++; break; } /* XXX sync descriptor memory */ @@ -3833,6 +3535,21 @@ ath_rx_proc(void *arg, int npending) if (status == HAL_EINPROGRESS) break; STAILQ_REMOVE_HEAD(&sc->sc_rxbuf, bf_list); + + /* These aren't specifically errors */ + if (rs->rs_flags & HAL_RX_GI) + sc->sc_stats.ast_rx_halfgi++; + if (rs->rs_flags & HAL_RX_2040) + sc->sc_stats.ast_rx_2040++; + if (rs->rs_flags & HAL_RX_DELIM_CRC_PRE) + sc->sc_stats.ast_rx_pre_crc_err++; + if (rs->rs_flags & HAL_RX_DELIM_CRC_POST) + sc->sc_stats.ast_rx_post_crc_err++; + if (rs->rs_flags & HAL_RX_DECRYPT_BUSY) + sc->sc_stats.ast_rx_decrypt_busy_err++; + if (rs->rs_flags & HAL_RX_HI_RX_CHAIN) + sc->sc_stats.ast_rx_hi_rx_chain++; + if (rs->rs_status != 0) { if (rs->rs_status & HAL_RXERR_CRC) sc->sc_stats.ast_rx_crcerr++; @@ -3840,8 +3557,20 @@ ath_rx_proc(void *arg, int npending) sc->sc_stats.ast_rx_fifoerr++; if (rs->rs_status & HAL_RXERR_PHY) { sc->sc_stats.ast_rx_phyerr++; - phyerr = rs->rs_phyerr & 0x1f; - sc->sc_stats.ast_rx_phy[phyerr]++; + /* Process DFS radar events */ + if ((rs->rs_phyerr == HAL_PHYERR_RADAR) || + (rs->rs_phyerr == HAL_PHYERR_FALSE_RADAR_EXT)) { + /* Since we're touching the frame data, sync it */ + bus_dmamap_sync(sc->sc_dmat, + bf->bf_dmamap, + BUS_DMASYNC_POSTREAD); + /* Now pass it to the radar processing code */ + ath_dfs_process_phy_err(sc, mtod(m, char *), tsf, rs); + } + + /* Be suitably paranoid about receiving phy errors out of the stats array bounds */ + if (rs->rs_phyerr < 64) + sc->sc_stats.ast_rx_phy[rs->rs_phyerr]++; goto rx_error; /* NB: don't count in ierrors */ } if (rs->rs_status & HAL_RXERR_DECRYPT) { @@ -4004,11 +3733,23 @@ rx_accept: mtod(m, const struct ieee80211_frame_min *), rs->rs_keyix == HAL_RXKEYIX_INVALID ? IEEE80211_KEYIX_NONE : rs->rs_keyix); + sc->sc_lastrs = rs; + + if (rs->rs_isaggr) + sc->sc_stats.ast_rx_agg++; + if (ni != NULL) { + /* + * Only punt packets for ampdu reorder processing for + * 11n nodes; net80211 enforces that M_AMPDU is only + * set for 11n nodes. + */ + if (ni->ni_flags & IEEE80211_NODE_HT) + m->m_flags |= M_AMPDU; + /* * Sending station is known, dispatch directly. */ - sc->sc_lastrs = rs; type = ieee80211_input(ni, m, rs->rs_rssi, nf); ieee80211_free_node(ni); /* @@ -4039,6 +3780,12 @@ rx_accept: } else sc->sc_rxotherant = 0; } + + /* Newer school diversity - kite specific for now */ + /* XXX perhaps migrate the normal diversity code to this? */ + if ((ah)->ah_rxAntCombDiversity) + (*(ah)->ah_rxAntCombDiversity)(ah, rs, ticks, hz); + if (sc->sc_softled) { /* * Blink for any data frame. Otherwise do a @@ -4062,6 +3809,29 @@ rx_next: if (ngood) sc->sc_lastrx = tsf; + /* Queue DFS tasklet if needed */ + if (ath_dfs_tasklet_needed(sc, sc->sc_curchan)) + taskqueue_enqueue(sc->sc_tq, &sc->sc_dfstask); + + /* + * Now that all the RX frames were handled that + * need to be handled, kick the PCU if there's + * been an RXEOL condition. + */ + if (sc->sc_kickpcu) { + sc->sc_kickpcu = 0; + ath_stoprecv(sc); + sc->sc_imask |= (HAL_INT_RXEOL | HAL_INT_RXORN); + if (ath_startrecv(sc) != 0) { + if_printf(ifp, + "%s: couldn't restart RX after RXEOL; resetting\n", + __func__); + ath_reset(ifp); + return; + } + ath_hal_intrset(ah, sc->sc_imask); + } + if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0) { #ifdef IEEE80211_SUPPORT_SUPERG ieee80211_ff_age_all(ic, 100); @@ -4282,7 +4052,7 @@ ath_tx_cleanup(struct ath_softc *sc) * Return h/w rate index for an IEEE rate (w/o basic rate bit) * using the current rates in sc_rixmap. */ -static __inline int +int ath_tx_findrix(const struct ath_softc *sc, uint8_t rate) { int rix = sc->sc_rixmap[rate]; @@ -4290,623 +4060,6 @@ ath_tx_findrix(const struct ath_softc *sc, uint8_t rate) return (rix == 0xff ? 0 : rix); } -/* - * Reclaim mbuf resources. For fragmented frames we - * need to claim each frag chained with m_nextpkt. - */ -static void -ath_freetx(struct mbuf *m) -{ - struct mbuf *next; - - do { - next = m->m_nextpkt; - m->m_nextpkt = NULL; - m_freem(m); - } while ((m = next) != NULL); -} - -static int -ath_tx_dmasetup(struct ath_softc *sc, struct ath_buf *bf, struct mbuf *m0) -{ - struct mbuf *m; - int error; - - /* - * Load the DMA map so any coalescing is done. This - * also calculates the number of descriptors we need. - */ - error = bus_dmamap_load_mbuf_sg(sc->sc_dmat, bf->bf_dmamap, m0, - bf->bf_segs, &bf->bf_nseg, - BUS_DMA_NOWAIT); - if (error == EFBIG) { - /* XXX packet requires too many descriptors */ - bf->bf_nseg = ATH_TXDESC+1; - } else if (error != 0) { - sc->sc_stats.ast_tx_busdma++; - ath_freetx(m0); - return error; - } - /* - * Discard null packets and check for packets that - * require too many TX descriptors. We try to convert - * the latter to a cluster. - */ - if (bf->bf_nseg > ATH_TXDESC) { /* too many desc's, linearize */ - sc->sc_stats.ast_tx_linear++; - m = m_collapse(m0, M_DONTWAIT, ATH_TXDESC); - if (m == NULL) { - ath_freetx(m0); - sc->sc_stats.ast_tx_nombuf++; - return ENOMEM; - } - m0 = m; - error = bus_dmamap_load_mbuf_sg(sc->sc_dmat, bf->bf_dmamap, m0, - bf->bf_segs, &bf->bf_nseg, - BUS_DMA_NOWAIT); - if (error != 0) { - sc->sc_stats.ast_tx_busdma++; - ath_freetx(m0); - return error; - } - KASSERT(bf->bf_nseg <= ATH_TXDESC, - ("too many segments after defrag; nseg %u", bf->bf_nseg)); - } else if (bf->bf_nseg == 0) { /* null packet, discard */ - sc->sc_stats.ast_tx_nodata++; - ath_freetx(m0); - return EIO; - } - DPRINTF(sc, ATH_DEBUG_XMIT, "%s: m %p len %u\n", - __func__, m0, m0->m_pkthdr.len); - bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap, BUS_DMASYNC_PREWRITE); - bf->bf_m = m0; - - return 0; -} - -static void -ath_tx_handoff(struct ath_softc *sc, struct ath_txq *txq, struct ath_buf *bf) -{ - struct ath_hal *ah = sc->sc_ah; - struct ath_desc *ds, *ds0; - int i; - - /* - * Fillin the remainder of the descriptor info. - */ - ds0 = ds = bf->bf_desc; - for (i = 0; i < bf->bf_nseg; i++, ds++) { - ds->ds_data = bf->bf_segs[i].ds_addr; - if (i == bf->bf_nseg - 1) - ds->ds_link = 0; - else - ds->ds_link = bf->bf_daddr + sizeof(*ds) * (i + 1); - ath_hal_filltxdesc(ah, ds - , bf->bf_segs[i].ds_len /* segment length */ - , i == 0 /* first segment */ - , i == bf->bf_nseg - 1 /* last segment */ - , ds0 /* first descriptor */ - ); - DPRINTF(sc, ATH_DEBUG_XMIT, - "%s: %d: %08x %08x %08x %08x %08x %08x\n", - __func__, i, ds->ds_link, ds->ds_data, - ds->ds_ctl0, ds->ds_ctl1, ds->ds_hw[0], ds->ds_hw[1]); - } - /* - * Insert the frame on the outbound list and pass it on - * to the hardware. Multicast frames buffered for power - * save stations and transmit from the CAB queue are stored - * on a s/w only queue and loaded on to the CAB queue in - * the SWBA handler since frames only go out on DTIM and - * to avoid possible races. - */ - ATH_TXQ_LOCK(txq); - KASSERT((bf->bf_flags & ATH_BUF_BUSY) == 0, - ("busy status 0x%x", bf->bf_flags)); - if (txq->axq_qnum != ATH_TXQ_SWQ) { -#ifdef IEEE80211_SUPPORT_TDMA - int qbusy; - - ATH_TXQ_INSERT_TAIL(txq, bf, bf_list); - qbusy = ath_hal_txqenabled(ah, txq->axq_qnum); - if (txq->axq_link == NULL) { - /* - * Be careful writing the address to TXDP. If - * the tx q is enabled then this write will be - * ignored. Normally this is not an issue but - * when tdma is in use and the q is beacon gated - * this race can occur. If the q is busy then - * defer the work to later--either when another - * packet comes along or when we prepare a beacon - * frame at SWBA. - */ - if (!qbusy) { - ath_hal_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr); - txq->axq_flags &= ~ATH_TXQ_PUTPENDING; - DPRINTF(sc, ATH_DEBUG_XMIT, - "%s: TXDP[%u] = %p (%p) depth %d\n", - __func__, txq->axq_qnum, - (caddr_t)bf->bf_daddr, bf->bf_desc, - txq->axq_depth); - } else { - txq->axq_flags |= ATH_TXQ_PUTPENDING; - DPRINTF(sc, ATH_DEBUG_TDMA | ATH_DEBUG_XMIT, - "%s: Q%u busy, defer enable\n", __func__, - txq->axq_qnum); - } - } else { - *txq->axq_link = bf->bf_daddr; - DPRINTF(sc, ATH_DEBUG_XMIT, - "%s: link[%u](%p)=%p (%p) depth %d\n", __func__, - txq->axq_qnum, txq->axq_link, - (caddr_t)bf->bf_daddr, bf->bf_desc, txq->axq_depth); - if ((txq->axq_flags & ATH_TXQ_PUTPENDING) && !qbusy) { - /* - * The q was busy when we previously tried - * to write the address of the first buffer - * in the chain. Since it's not busy now - * handle this chore. We are certain the - * buffer at the front is the right one since - * axq_link is NULL only when the buffer list - * is/was empty. - */ - ath_hal_puttxbuf(ah, txq->axq_qnum, - STAILQ_FIRST(&txq->axq_q)->bf_daddr); - txq->axq_flags &= ~ATH_TXQ_PUTPENDING; - DPRINTF(sc, ATH_DEBUG_TDMA | ATH_DEBUG_XMIT, - "%s: Q%u restarted\n", __func__, - txq->axq_qnum); - } - } -#else - ATH_TXQ_INSERT_TAIL(txq, bf, bf_list); - if (txq->axq_link == NULL) { - ath_hal_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr); - DPRINTF(sc, ATH_DEBUG_XMIT, - "%s: TXDP[%u] = %p (%p) depth %d\n", - __func__, txq->axq_qnum, - (caddr_t)bf->bf_daddr, bf->bf_desc, - txq->axq_depth); - } else { - *txq->axq_link = bf->bf_daddr; - DPRINTF(sc, ATH_DEBUG_XMIT, - "%s: link[%u](%p)=%p (%p) depth %d\n", __func__, - txq->axq_qnum, txq->axq_link, - (caddr_t)bf->bf_daddr, bf->bf_desc, txq->axq_depth); - } -#endif /* IEEE80211_SUPPORT_TDMA */ - txq->axq_link = &bf->bf_desc[bf->bf_nseg - 1].ds_link; - ath_hal_txstart(ah, txq->axq_qnum); - } else { - if (txq->axq_link != NULL) { - struct ath_buf *last = ATH_TXQ_LAST(txq); - struct ieee80211_frame *wh; - - /* mark previous frame */ - wh = mtod(last->bf_m, struct ieee80211_frame *); - wh->i_fc[1] |= IEEE80211_FC1_MORE_DATA; - bus_dmamap_sync(sc->sc_dmat, last->bf_dmamap, - BUS_DMASYNC_PREWRITE); - - /* link descriptor */ - *txq->axq_link = bf->bf_daddr; - } - ATH_TXQ_INSERT_TAIL(txq, bf, bf_list); - txq->axq_link = &bf->bf_desc[bf->bf_nseg - 1].ds_link; - } - ATH_TXQ_UNLOCK(txq); -} - -static int -ath_tx_start(struct ath_softc *sc, struct ieee80211_node *ni, struct ath_buf *bf, - struct mbuf *m0) -{ - struct ieee80211vap *vap = ni->ni_vap; - struct ath_vap *avp = ATH_VAP(vap); - struct ath_hal *ah = sc->sc_ah; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - const struct chanAccParams *cap = &ic->ic_wme.wme_chanParams; - int error, iswep, ismcast, isfrag, ismrr; - int keyix, hdrlen, pktlen, try0; - u_int8_t rix, txrate, ctsrate; - u_int8_t cix = 0xff; /* NB: silence compiler */ - struct ath_desc *ds; - struct ath_txq *txq; - struct ieee80211_frame *wh; - u_int subtype, flags, ctsduration; - HAL_PKT_TYPE atype; - const HAL_RATE_TABLE *rt; - HAL_BOOL shortPreamble; - struct ath_node *an; - u_int pri; - - wh = mtod(m0, struct ieee80211_frame *); - iswep = wh->i_fc[1] & IEEE80211_FC1_WEP; - ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1); - isfrag = m0->m_flags & M_FRAG; - hdrlen = ieee80211_anyhdrsize(wh); - /* - * Packet length must not include any - * pad bytes; deduct them here. - */ - pktlen = m0->m_pkthdr.len - (hdrlen & 3); - - if (iswep) { - const struct ieee80211_cipher *cip; - struct ieee80211_key *k; - - /* - * Construct the 802.11 header+trailer for an encrypted - * frame. The only reason this can fail is because of an - * unknown or unsupported cipher/key type. - */ - k = ieee80211_crypto_encap(ni, m0); - if (k == NULL) { - /* - * This can happen when the key is yanked after the - * frame was queued. Just discard the frame; the - * 802.11 layer counts failures and provides - * debugging/diagnostics. - */ - ath_freetx(m0); - return EIO; - } - /* - * Adjust the packet + header lengths for the crypto - * additions and calculate the h/w key index. When - * a s/w mic is done the frame will have had any mic - * added to it prior to entry so m0->m_pkthdr.len will - * account for it. Otherwise we need to add it to the - * packet length. - */ - cip = k->wk_cipher; - hdrlen += cip->ic_header; - pktlen += cip->ic_header + cip->ic_trailer; - /* NB: frags always have any TKIP MIC done in s/w */ - if ((k->wk_flags & IEEE80211_KEY_SWMIC) == 0 && !isfrag) - pktlen += cip->ic_miclen; - keyix = k->wk_keyix; - - /* packet header may have moved, reset our local pointer */ - wh = mtod(m0, struct ieee80211_frame *); - } else if (ni->ni_ucastkey.wk_cipher == &ieee80211_cipher_none) { - /* - * Use station key cache slot, if assigned. - */ - keyix = ni->ni_ucastkey.wk_keyix; - if (keyix == IEEE80211_KEYIX_NONE) - keyix = HAL_TXKEYIX_INVALID; - } else - keyix = HAL_TXKEYIX_INVALID; - - pktlen += IEEE80211_CRC_LEN; - - /* - * Load the DMA map so any coalescing is done. This - * also calculates the number of descriptors we need. - */ - error = ath_tx_dmasetup(sc, bf, m0); - if (error != 0) - return error; - bf->bf_node = ni; /* NB: held reference */ - m0 = bf->bf_m; /* NB: may have changed */ - wh = mtod(m0, struct ieee80211_frame *); - - /* setup descriptors */ - ds = bf->bf_desc; - rt = sc->sc_currates; - KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode)); - - /* - * NB: the 802.11 layer marks whether or not we should - * use short preamble based on the current mode and - * negotiated parameters. - */ - if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) && - (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE)) { - shortPreamble = AH_TRUE; - sc->sc_stats.ast_tx_shortpre++; - } else { - shortPreamble = AH_FALSE; - } - - an = ATH_NODE(ni); - flags = HAL_TXDESC_CLRDMASK; /* XXX needed for crypto errs */ - ismrr = 0; /* default no multi-rate retry*/ - pri = M_WME_GETAC(m0); /* honor classification */ - /* XXX use txparams instead of fixed values */ - /* - * Calculate Atheros packet type from IEEE80211 packet header, - * setup for rate calculations, and select h/w transmit queue. - */ - switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) { - case IEEE80211_FC0_TYPE_MGT: - subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; - if (subtype == IEEE80211_FC0_SUBTYPE_BEACON) - atype = HAL_PKT_TYPE_BEACON; - else if (subtype == IEEE80211_FC0_SUBTYPE_PROBE_RESP) - atype = HAL_PKT_TYPE_PROBE_RESP; - else if (subtype == IEEE80211_FC0_SUBTYPE_ATIM) - atype = HAL_PKT_TYPE_ATIM; - else - atype = HAL_PKT_TYPE_NORMAL; /* XXX */ - rix = an->an_mgmtrix; - txrate = rt->info[rix].rateCode; - if (shortPreamble) - txrate |= rt->info[rix].shortPreamble; - try0 = ATH_TXMGTTRY; - flags |= HAL_TXDESC_INTREQ; /* force interrupt */ - break; - case IEEE80211_FC0_TYPE_CTL: - atype = HAL_PKT_TYPE_PSPOLL; /* stop setting of duration */ - rix = an->an_mgmtrix; - txrate = rt->info[rix].rateCode; - if (shortPreamble) - txrate |= rt->info[rix].shortPreamble; - try0 = ATH_TXMGTTRY; - flags |= HAL_TXDESC_INTREQ; /* force interrupt */ - break; - case IEEE80211_FC0_TYPE_DATA: - atype = HAL_PKT_TYPE_NORMAL; /* default */ - /* - * Data frames: multicast frames go out at a fixed rate, - * EAPOL frames use the mgmt frame rate; otherwise consult - * the rate control module for the rate to use. - */ - if (ismcast) { - rix = an->an_mcastrix; - txrate = rt->info[rix].rateCode; - if (shortPreamble) - txrate |= rt->info[rix].shortPreamble; - try0 = 1; - } else if (m0->m_flags & M_EAPOL) { - /* XXX? maybe always use long preamble? */ - rix = an->an_mgmtrix; - txrate = rt->info[rix].rateCode; - if (shortPreamble) - txrate |= rt->info[rix].shortPreamble; - try0 = ATH_TXMAXTRY; /* XXX?too many? */ - } else { - ath_rate_findrate(sc, an, shortPreamble, pktlen, - &rix, &try0, &txrate); - sc->sc_txrix = rix; /* for LED blinking */ - sc->sc_lastdatarix = rix; /* for fast frames */ - if (try0 != ATH_TXMAXTRY) - ismrr = 1; - } - if (cap->cap_wmeParams[pri].wmep_noackPolicy) - flags |= HAL_TXDESC_NOACK; - break; - default: - if_printf(ifp, "bogus frame type 0x%x (%s)\n", - wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK, __func__); - /* XXX statistic */ - ath_freetx(m0); - return EIO; - } - txq = sc->sc_ac2q[pri]; - - /* - * When servicing one or more stations in power-save mode - * (or) if there is some mcast data waiting on the mcast - * queue (to prevent out of order delivery) multicast - * frames must be buffered until after the beacon. - */ - if (ismcast && (vap->iv_ps_sta || avp->av_mcastq.axq_depth)) - txq = &avp->av_mcastq; - - /* - * Calculate miscellaneous flags. - */ - if (ismcast) { - flags |= HAL_TXDESC_NOACK; /* no ack on broad/multicast */ - } else if (pktlen > vap->iv_rtsthreshold && - (ni->ni_ath_flags & IEEE80211_NODE_FF) == 0) { - flags |= HAL_TXDESC_RTSENA; /* RTS based on frame length */ - cix = rt->info[rix].controlRate; - sc->sc_stats.ast_tx_rts++; - } - if (flags & HAL_TXDESC_NOACK) /* NB: avoid double counting */ - sc->sc_stats.ast_tx_noack++; -#ifdef IEEE80211_SUPPORT_TDMA - if (sc->sc_tdma && (flags & HAL_TXDESC_NOACK) == 0) { - DPRINTF(sc, ATH_DEBUG_TDMA, - "%s: discard frame, ACK required w/ TDMA\n", __func__); - sc->sc_stats.ast_tdma_ack++; - ath_freetx(m0); - return EIO; - } -#endif - - /* - * If 802.11g protection is enabled, determine whether - * to use RTS/CTS or just CTS. Note that this is only - * done for OFDM unicast frames. - */ - if ((ic->ic_flags & IEEE80211_F_USEPROT) && - rt->info[rix].phy == IEEE80211_T_OFDM && - (flags & HAL_TXDESC_NOACK) == 0) { - /* XXX fragments must use CCK rates w/ protection */ - if (ic->ic_protmode == IEEE80211_PROT_RTSCTS) - flags |= HAL_TXDESC_RTSENA; - else if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) - flags |= HAL_TXDESC_CTSENA; - if (isfrag) { - /* - * For frags it would be desirable to use the - * highest CCK rate for RTS/CTS. But stations - * farther away may detect it at a lower CCK rate - * so use the configured protection rate instead - * (for now). - */ - cix = rt->info[sc->sc_protrix].controlRate; - } else - cix = rt->info[sc->sc_protrix].controlRate; - sc->sc_stats.ast_tx_protect++; - } - - /* - * Calculate duration. This logically belongs in the 802.11 - * layer but it lacks sufficient information to calculate it. - */ - if ((flags & HAL_TXDESC_NOACK) == 0 && - (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_CTL) { - u_int16_t dur; - if (shortPreamble) - dur = rt->info[rix].spAckDuration; - else - dur = rt->info[rix].lpAckDuration; - if (wh->i_fc[1] & IEEE80211_FC1_MORE_FRAG) { - dur += dur; /* additional SIFS+ACK */ - KASSERT(m0->m_nextpkt != NULL, ("no fragment")); - /* - * Include the size of next fragment so NAV is - * updated properly. The last fragment uses only - * the ACK duration - */ - dur += ath_hal_computetxtime(ah, rt, - m0->m_nextpkt->m_pkthdr.len, - rix, shortPreamble); - } - if (isfrag) { - /* - * Force hardware to use computed duration for next - * fragment by disabling multi-rate retry which updates - * duration based on the multi-rate duration table. - */ - ismrr = 0; - try0 = ATH_TXMGTTRY; /* XXX? */ - } - *(u_int16_t *)wh->i_dur = htole16(dur); - } - - /* - * Calculate RTS/CTS rate and duration if needed. - */ - ctsduration = 0; - if (flags & (HAL_TXDESC_RTSENA|HAL_TXDESC_CTSENA)) { - /* - * CTS transmit rate is derived from the transmit rate - * by looking in the h/w rate table. We must also factor - * in whether or not a short preamble is to be used. - */ - /* NB: cix is set above where RTS/CTS is enabled */ - KASSERT(cix != 0xff, ("cix not setup")); - ctsrate = rt->info[cix].rateCode; - /* - * Compute the transmit duration based on the frame - * size and the size of an ACK frame. We call into the - * HAL to do the computation since it depends on the - * characteristics of the actual PHY being used. - * - * NB: CTS is assumed the same size as an ACK so we can - * use the precalculated ACK durations. - */ - if (shortPreamble) { - ctsrate |= rt->info[cix].shortPreamble; - if (flags & HAL_TXDESC_RTSENA) /* SIFS + CTS */ - ctsduration += rt->info[cix].spAckDuration; - ctsduration += ath_hal_computetxtime(ah, - rt, pktlen, rix, AH_TRUE); - if ((flags & HAL_TXDESC_NOACK) == 0) /* SIFS + ACK */ - ctsduration += rt->info[rix].spAckDuration; - } else { - if (flags & HAL_TXDESC_RTSENA) /* SIFS + CTS */ - ctsduration += rt->info[cix].lpAckDuration; - ctsduration += ath_hal_computetxtime(ah, - rt, pktlen, rix, AH_FALSE); - if ((flags & HAL_TXDESC_NOACK) == 0) /* SIFS + ACK */ - ctsduration += rt->info[rix].lpAckDuration; - } - /* - * Must disable multi-rate retry when using RTS/CTS. - */ - ismrr = 0; - try0 = ATH_TXMGTTRY; /* XXX */ - } else - ctsrate = 0; - - /* - * At this point we are committed to sending the frame - * and we don't need to look at m_nextpkt; clear it in - * case this frame is part of frag chain. - */ - m0->m_nextpkt = NULL; - - if (IFF_DUMPPKTS(sc, ATH_DEBUG_XMIT)) - ieee80211_dump_pkt(ic, mtod(m0, const uint8_t *), m0->m_len, - sc->sc_hwmap[rix].ieeerate, -1); - - if (ieee80211_radiotap_active_vap(vap)) { - u_int64_t tsf = ath_hal_gettsf64(ah); - - sc->sc_tx_th.wt_tsf = htole64(tsf); - sc->sc_tx_th.wt_flags = sc->sc_hwmap[rix].txflags; - if (iswep) - sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP; - if (isfrag) - sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_FRAG; - sc->sc_tx_th.wt_rate = sc->sc_hwmap[rix].ieeerate; - sc->sc_tx_th.wt_txpower = ni->ni_txpower; - sc->sc_tx_th.wt_antenna = sc->sc_txantenna; - - ieee80211_radiotap_tx(vap, m0); - } - - /* - * Determine if a tx interrupt should be generated for - * this descriptor. We take a tx interrupt to reap - * descriptors when the h/w hits an EOL condition or - * when the descriptor is specifically marked to generate - * an interrupt. We periodically mark descriptors in this - * way to insure timely replenishing of the supply needed - * for sending frames. Defering interrupts reduces system - * load and potentially allows more concurrent work to be - * done but if done to aggressively can cause senders to - * backup. - * - * NB: use >= to deal with sc_txintrperiod changing - * dynamically through sysctl. - */ - if (flags & HAL_TXDESC_INTREQ) { - txq->axq_intrcnt = 0; - } else if (++txq->axq_intrcnt >= sc->sc_txintrperiod) { - flags |= HAL_TXDESC_INTREQ; - txq->axq_intrcnt = 0; - } - - /* - * Formulate first tx descriptor with tx controls. - */ - /* XXX check return value? */ - ath_hal_setuptxdesc(ah, ds - , pktlen /* packet length */ - , hdrlen /* header length */ - , atype /* Atheros packet type */ - , ni->ni_txpower /* txpower */ - , txrate, try0 /* series 0 rate/tries */ - , keyix /* key cache index */ - , sc->sc_txantenna /* antenna mode */ - , flags /* flags */ - , ctsrate /* rts/cts rate */ - , ctsduration /* rts/cts duration */ - ); - bf->bf_txflags = flags; - /* - * Setup the multi-rate retry state only when we're - * going to use it. This assumes ath_hal_setuptxdesc - * initializes the descriptors (so we don't have to) - * when the hardware supports multi-rate retry and - * we don't use it. - */ - if (ismrr) - ath_rate_setupxtxdesc(sc, an, ds, shortPreamble, rix); - - ath_tx_handoff(sc, txq, bf); - return 0; -} - /* * Process completed xmit descriptors from the specified queue. */ @@ -4987,9 +4140,21 @@ ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) sc->sc_stats.ast_tx_fifoerr++; if (ts->ts_status & HAL_TXERR_FILT) sc->sc_stats.ast_tx_filtered++; + if (ts->ts_status & HAL_TXERR_XTXOP) + sc->sc_stats.ast_tx_xtxop++; + if (ts->ts_status & HAL_TXERR_TIMER_EXPIRED) + sc->sc_stats.ast_tx_timerexpired++; + + /* XXX HAL_TX_DATA_UNDERRUN */ + /* XXX HAL_TX_DELIM_UNDERRUN */ + if (bf->bf_m->m_flags & M_FF) sc->sc_stats.ast_ff_txerr++; } + /* XXX when is this valid? */ + if (ts->ts_status & HAL_TX_DESC_CFG_ERR) + sc->sc_stats.ast_tx_desccfgerr++; + sr = ts->ts_shortretry; lr = ts->ts_longretry; sc->sc_stats.ast_tx_shortretry += sr; @@ -5384,6 +4549,9 @@ ath_chan_set(struct ath_softc *sc, struct ieee80211_channel *chan) } sc->sc_diversity = ath_hal_getdiversity(ah); + /* Let DFS at it in case it's a DFS channel */ + ath_dfs_radar_enable(sc, ic->ic_curchan); + /* * Re-enable rx framework. */ @@ -5399,6 +4567,19 @@ ath_chan_set(struct ath_softc *sc, struct ieee80211_channel *chan) */ ath_chan_change(sc, chan); + /* + * Reset clears the beacon timers; reset them + * here if needed. + */ + if (sc->sc_beacons) { /* restart beacons */ +#ifdef IEEE80211_SUPPORT_TDMA + if (sc->sc_tdma) + ath_tdma_config(sc, NULL); + else +#endif + ath_beacon_config(sc, NULL); + } + /* * Re-enable interrupts. */ @@ -5419,13 +4600,26 @@ ath_calibrate(void *arg) struct ifnet *ifp = sc->sc_ifp; struct ieee80211com *ic = ifp->if_l2com; HAL_BOOL longCal, isCalDone; + HAL_BOOL aniCal, shortCal = AH_FALSE; int nextcal; if (ic->ic_flags & IEEE80211_F_SCAN) /* defer, off channel */ goto restart; longCal = (ticks - sc->sc_lastlongcal >= ath_longcalinterval*hz); + aniCal = (ticks - sc->sc_lastani >= ath_anicalinterval*hz/1000); + if (sc->sc_doresetcal) + shortCal = (ticks - sc->sc_lastshortcal >= ath_shortcalinterval*hz/1000); + + DPRINTF(sc, ATH_DEBUG_CALIBRATE, "%s: shortCal=%d; longCal=%d; aniCal=%d\n", __func__, shortCal, longCal, aniCal); + if (aniCal) { + sc->sc_stats.ast_ani_cal++; + sc->sc_lastani = ticks; + ath_hal_ani_poll(ah, sc->sc_curchan); + } + if (longCal) { sc->sc_stats.ast_per_cal++; + sc->sc_lastlongcal = ticks; if (ath_hal_getrfgain(ah) == HAL_RFGAIN_NEED_CHANGE) { /* * Rfgain is out of bounds, reset the chip @@ -5443,21 +4637,29 @@ ath_calibrate(void *arg) if (sc->sc_resetcal) { (void) ath_hal_calreset(ah, sc->sc_curchan); sc->sc_lastcalreset = ticks; + sc->sc_lastshortcal = ticks; sc->sc_resetcal = 0; + sc->sc_doresetcal = AH_TRUE; } } - if (ath_hal_calibrateN(ah, sc->sc_curchan, longCal, &isCalDone)) { - if (longCal) { - /* - * Calibrate noise floor data again in case of change. - */ - ath_hal_process_noisefloor(ah); + + /* Only call if we're doing a short/long cal, not for ANI calibration */ + if (shortCal || longCal) { + if (ath_hal_calibrateN(ah, sc->sc_curchan, longCal, &isCalDone)) { + if (longCal) { + /* + * Calibrate noise floor data again in case of change. + */ + ath_hal_process_noisefloor(ah); + } + } else { + DPRINTF(sc, ATH_DEBUG_ANY, + "%s: calibration of channel %u failed\n", + __func__, sc->sc_curchan->ic_freq); + sc->sc_stats.ast_per_calfail++; } - } else { - DPRINTF(sc, ATH_DEBUG_ANY, - "%s: calibration of channel %u failed\n", - __func__, sc->sc_curchan->ic_freq); - sc->sc_stats.ast_per_calfail++; + if (shortCal) + sc->sc_lastshortcal = ticks; } if (!isCalDone) { restart: @@ -5469,17 +4671,23 @@ restart: * work when operating as an AP to improve operation right * after startup. */ - nextcal = (1000*ath_shortcalinterval)/hz; + sc->sc_lastshortcal = ticks; + nextcal = ath_shortcalinterval*hz/1000; if (sc->sc_opmode != HAL_M_HOSTAP) nextcal *= 10; + sc->sc_doresetcal = AH_TRUE; } else { + /* nextcal should be the shortest time for next event */ nextcal = ath_longcalinterval*hz; - sc->sc_lastlongcal = ticks; if (sc->sc_lastcalreset == 0) sc->sc_lastcalreset = sc->sc_lastlongcal; else if (ticks - sc->sc_lastcalreset >= ath_resetcalinterval*hz) sc->sc_resetcal = 1; /* setup reset next trip */ + sc->sc_doresetcal = AH_FALSE; } + /* ANI calibration may occur more often than short/long/resetcal */ + if (ath_anicalinterval > 0) + nextcal = MIN(nextcal, ath_anicalinterval*hz/1000); if (nextcal != 0) { DPRINTF(sc, ATH_DEBUG_CALIBRATE, "%s: next +%u (%sisCalDone)\n", @@ -5577,6 +4785,7 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) struct ieee80211_node *ni = NULL; int i, error, stamode; u_int32_t rfilt; + int csa_run_transition = 0; static const HAL_LED_STATE leds[] = { HAL_LED_INIT, /* IEEE80211_S_INIT */ HAL_LED_SCAN, /* IEEE80211_S_SCAN */ @@ -5592,6 +4801,9 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) ieee80211_state_name[vap->iv_state], ieee80211_state_name[nstate]); + if (vap->iv_state == IEEE80211_S_CSA && nstate == IEEE80211_S_RUN) + csa_run_transition = 1; + callout_drain(&sc->sc_cal_ch); ath_hal_setledstate(ah, leds[nstate]); /* set LED */ @@ -5698,8 +4910,14 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) * Defer beacon timer configuration to the next * beacon frame so we have a current TSF to use * (any TSF collected when scanning is likely old). + * However if it's due to a CSA -> RUN transition, + * force a beacon update so we pick up a lack of + * beacons from an AP in CAC and thus force a + * scan. */ sc->sc_syncbeacon = 1; + if (csa_run_transition) + ath_beacon_config(sc, vap); break; case IEEE80211_M_MONITOR: /* @@ -5837,6 +5055,7 @@ ath_setregdomain(struct ieee80211com *ic, struct ieee80211_regdomain *reg, __func__, status); return EINVAL; /* XXX */ } + return 0; } @@ -6060,65 +5279,6 @@ ath_setcurmode(struct ath_softc *sc, enum ieee80211_phymode mode) #undef N } -#ifdef ATH_DEBUG -static void -ath_printrxbuf(struct ath_softc *sc, const struct ath_buf *bf, - u_int ix, int done) -{ - const struct ath_rx_status *rs = &bf->bf_status.ds_rxstat; - struct ath_hal *ah = sc->sc_ah; - const struct ath_desc *ds; - int i; - - for (i = 0, ds = bf->bf_desc; i < bf->bf_nseg; i++, ds++) { - printf("R[%2u] (DS.V:%p DS.P:%p) L:%08x D:%08x%s\n" - " %08x %08x %08x %08x\n", - ix, ds, (const struct ath_desc *)bf->bf_daddr + i, - ds->ds_link, ds->ds_data, - !done ? "" : (rs->rs_status == 0) ? " *" : " !", - ds->ds_ctl0, ds->ds_ctl1, - ds->ds_hw[0], ds->ds_hw[1]); - if (ah->ah_magic == 0x20065416) { - printf(" %08x %08x %08x %08x %08x %08x %08x\n", - ds->ds_hw[2], ds->ds_hw[3], ds->ds_hw[4], - ds->ds_hw[5], ds->ds_hw[6], ds->ds_hw[7], - ds->ds_hw[8]); - } - } -} - -static void -ath_printtxbuf(struct ath_softc *sc, const struct ath_buf *bf, - u_int qnum, u_int ix, int done) -{ - const struct ath_tx_status *ts = &bf->bf_status.ds_txstat; - struct ath_hal *ah = sc->sc_ah; - const struct ath_desc *ds; - int i; - - printf("Q%u[%3u]", qnum, ix); - for (i = 0, ds = bf->bf_desc; i < bf->bf_nseg; i++, ds++) { - printf(" (DS.V:%p DS.P:%p) L:%08x D:%08x F:04%x%s\n" - " %08x %08x %08x %08x %08x %08x\n", - ds, (const struct ath_desc *)bf->bf_daddr + i, - ds->ds_link, ds->ds_data, bf->bf_txflags, - !done ? "" : (ts->ts_status == 0) ? " *" : " !", - ds->ds_ctl0, ds->ds_ctl1, - ds->ds_hw[0], ds->ds_hw[1], ds->ds_hw[2], ds->ds_hw[3]); - if (ah->ah_magic == 0x20065416) { - printf(" %08x %08x %08x %08x %08x %08x %08x %08x\n", - ds->ds_hw[4], ds->ds_hw[5], ds->ds_hw[6], - ds->ds_hw[7], ds->ds_hw[8], ds->ds_hw[9], - ds->ds_hw[10],ds->ds_hw[11]); - printf(" %08x %08x %08x %08x %08x %08x %08x %08x\n", - ds->ds_hw[12],ds->ds_hw[13],ds->ds_hw[14], - ds->ds_hw[15],ds->ds_hw[16],ds->ds_hw[17], - ds->ds_hw[18], ds->ds_hw[19]); - } - } -} -#endif /* ATH_DEBUG */ - static void ath_watchdog(void *arg) { @@ -6262,9 +5422,10 @@ ath_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) sc->sc_stats.ast_tdma_tsfadjm = TDMA_AVG(sc->sc_avgtsfdeltam); #endif rt = sc->sc_currates; - /* XXX HT rates */ sc->sc_stats.ast_tx_rate = rt->info[sc->sc_txrix].dot11Rate &~ IEEE80211_RATE_BASIC; + if (rt->info[sc->sc_txrix].phy & IEEE80211_T_HT) + sc->sc_stats.ast_tx_rate |= IEEE80211_RATE_MCS; return copyout(&sc->sc_stats, ifr->ifr_data, sizeof (sc->sc_stats)); case SIOCZATHSTATS: @@ -6276,6 +5437,9 @@ ath_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) case SIOCGATHDIAG: error = ath_ioctl_diag(sc, (struct ath_diag *) ifr); break; + case SIOCGATHPHYERR: + error = ath_ioctl_phyerr(sc,(struct ath_diag*) ifr); + break; #endif case SIOCGIFADDR: error = ether_ioctl(ifp, cmd, data); @@ -6288,661 +5452,6 @@ ath_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) #undef IS_RUNNING } -static int -ath_sysctl_slottime(SYSCTL_HANDLER_ARGS) -{ - struct ath_softc *sc = arg1; - u_int slottime = ath_hal_getslottime(sc->sc_ah); - int error; - - error = sysctl_handle_int(oidp, &slottime, 0, req); - if (error || !req->newptr) - return error; - return !ath_hal_setslottime(sc->sc_ah, slottime) ? EINVAL : 0; -} - -static int -ath_sysctl_acktimeout(SYSCTL_HANDLER_ARGS) -{ - struct ath_softc *sc = arg1; - u_int acktimeout = ath_hal_getacktimeout(sc->sc_ah); - int error; - - error = sysctl_handle_int(oidp, &acktimeout, 0, req); - if (error || !req->newptr) - return error; - return !ath_hal_setacktimeout(sc->sc_ah, acktimeout) ? EINVAL : 0; -} - -static int -ath_sysctl_ctstimeout(SYSCTL_HANDLER_ARGS) -{ - struct ath_softc *sc = arg1; - u_int ctstimeout = ath_hal_getctstimeout(sc->sc_ah); - int error; - - error = sysctl_handle_int(oidp, &ctstimeout, 0, req); - if (error || !req->newptr) - return error; - return !ath_hal_setctstimeout(sc->sc_ah, ctstimeout) ? EINVAL : 0; -} - -static int -ath_sysctl_softled(SYSCTL_HANDLER_ARGS) -{ - struct ath_softc *sc = arg1; - int softled = sc->sc_softled; - int error; - - error = sysctl_handle_int(oidp, &softled, 0, req); - if (error || !req->newptr) - return error; - softled = (softled != 0); - if (softled != sc->sc_softled) { - if (softled) { - /* NB: handle any sc_ledpin change */ - ath_hal_gpioCfgOutput(sc->sc_ah, sc->sc_ledpin, - HAL_GPIO_MUX_MAC_NETWORK_LED); - ath_hal_gpioset(sc->sc_ah, sc->sc_ledpin, - !sc->sc_ledon); - } - sc->sc_softled = softled; - } - return 0; -} - -static int -ath_sysctl_ledpin(SYSCTL_HANDLER_ARGS) -{ - struct ath_softc *sc = arg1; - int ledpin = sc->sc_ledpin; - int error; - - error = sysctl_handle_int(oidp, &ledpin, 0, req); - if (error || !req->newptr) - return error; - if (ledpin != sc->sc_ledpin) { - sc->sc_ledpin = ledpin; - if (sc->sc_softled) { - ath_hal_gpioCfgOutput(sc->sc_ah, sc->sc_ledpin, - HAL_GPIO_MUX_MAC_NETWORK_LED); - ath_hal_gpioset(sc->sc_ah, sc->sc_ledpin, - !sc->sc_ledon); - } - } - return 0; -} - -static int -ath_sysctl_txantenna(SYSCTL_HANDLER_ARGS) -{ - struct ath_softc *sc = arg1; - u_int txantenna = ath_hal_getantennaswitch(sc->sc_ah); - int error; - - error = sysctl_handle_int(oidp, &txantenna, 0, req); - if (!error && req->newptr) { - /* XXX assumes 2 antenna ports */ - if (txantenna < HAL_ANT_VARIABLE || txantenna > HAL_ANT_FIXED_B) - return EINVAL; - ath_hal_setantennaswitch(sc->sc_ah, txantenna); - /* - * NB: with the switch locked this isn't meaningful, - * but set it anyway so things like radiotap get - * consistent info in their data. - */ - sc->sc_txantenna = txantenna; - } - return error; -} - -static int -ath_sysctl_rxantenna(SYSCTL_HANDLER_ARGS) -{ - struct ath_softc *sc = arg1; - u_int defantenna = ath_hal_getdefantenna(sc->sc_ah); - int error; - - error = sysctl_handle_int(oidp, &defantenna, 0, req); - if (!error && req->newptr) - ath_hal_setdefantenna(sc->sc_ah, defantenna); - return error; -} - -static int -ath_sysctl_diversity(SYSCTL_HANDLER_ARGS) -{ - struct ath_softc *sc = arg1; - u_int diversity = ath_hal_getdiversity(sc->sc_ah); - int error; - - error = sysctl_handle_int(oidp, &diversity, 0, req); - if (error || !req->newptr) - return error; - if (!ath_hal_setdiversity(sc->sc_ah, diversity)) - return EINVAL; - sc->sc_diversity = diversity; - return 0; -} - -static int -ath_sysctl_diag(SYSCTL_HANDLER_ARGS) -{ - struct ath_softc *sc = arg1; - u_int32_t diag; - int error; - - if (!ath_hal_getdiag(sc->sc_ah, &diag)) - return EINVAL; - error = sysctl_handle_int(oidp, &diag, 0, req); - if (error || !req->newptr) - return error; - return !ath_hal_setdiag(sc->sc_ah, diag) ? EINVAL : 0; -} - -static int -ath_sysctl_tpscale(SYSCTL_HANDLER_ARGS) -{ - struct ath_softc *sc = arg1; - struct ifnet *ifp = sc->sc_ifp; - u_int32_t scale; - int error; - - (void) ath_hal_gettpscale(sc->sc_ah, &scale); - error = sysctl_handle_int(oidp, &scale, 0, req); - if (error || !req->newptr) - return error; - return !ath_hal_settpscale(sc->sc_ah, scale) ? EINVAL : - (ifp->if_drv_flags & IFF_DRV_RUNNING) ? ath_reset(ifp) : 0; -} - -static int -ath_sysctl_tpc(SYSCTL_HANDLER_ARGS) -{ - struct ath_softc *sc = arg1; - u_int tpc = ath_hal_gettpc(sc->sc_ah); - int error; - - error = sysctl_handle_int(oidp, &tpc, 0, req); - if (error || !req->newptr) - return error; - return !ath_hal_settpc(sc->sc_ah, tpc) ? EINVAL : 0; -} - -static int -ath_sysctl_rfkill(SYSCTL_HANDLER_ARGS) -{ - struct ath_softc *sc = arg1; - struct ifnet *ifp = sc->sc_ifp; - struct ath_hal *ah = sc->sc_ah; - u_int rfkill = ath_hal_getrfkill(ah); - int error; - - error = sysctl_handle_int(oidp, &rfkill, 0, req); - if (error || !req->newptr) - return error; - if (rfkill == ath_hal_getrfkill(ah)) /* unchanged */ - return 0; - if (!ath_hal_setrfkill(ah, rfkill)) - return EINVAL; - return (ifp->if_drv_flags & IFF_DRV_RUNNING) ? ath_reset(ifp) : 0; -} - -static int -ath_sysctl_rfsilent(SYSCTL_HANDLER_ARGS) -{ - struct ath_softc *sc = arg1; - u_int rfsilent; - int error; - - (void) ath_hal_getrfsilent(sc->sc_ah, &rfsilent); - error = sysctl_handle_int(oidp, &rfsilent, 0, req); - if (error || !req->newptr) - return error; - if (!ath_hal_setrfsilent(sc->sc_ah, rfsilent)) - return EINVAL; - sc->sc_rfsilentpin = rfsilent & 0x1c; - sc->sc_rfsilentpol = (rfsilent & 0x2) != 0; - return 0; -} - -static int -ath_sysctl_tpack(SYSCTL_HANDLER_ARGS) -{ - struct ath_softc *sc = arg1; - u_int32_t tpack; - int error; - - (void) ath_hal_gettpack(sc->sc_ah, &tpack); - error = sysctl_handle_int(oidp, &tpack, 0, req); - if (error || !req->newptr) - return error; - return !ath_hal_settpack(sc->sc_ah, tpack) ? EINVAL : 0; -} - -static int -ath_sysctl_tpcts(SYSCTL_HANDLER_ARGS) -{ - struct ath_softc *sc = arg1; - u_int32_t tpcts; - int error; - - (void) ath_hal_gettpcts(sc->sc_ah, &tpcts); - error = sysctl_handle_int(oidp, &tpcts, 0, req); - if (error || !req->newptr) - return error; - return !ath_hal_settpcts(sc->sc_ah, tpcts) ? EINVAL : 0; -} - -static int -ath_sysctl_intmit(SYSCTL_HANDLER_ARGS) -{ - struct ath_softc *sc = arg1; - int intmit, error; - - intmit = ath_hal_getintmit(sc->sc_ah); - error = sysctl_handle_int(oidp, &intmit, 0, req); - if (error || !req->newptr) - return error; - return !ath_hal_setintmit(sc->sc_ah, intmit) ? EINVAL : 0; -} - -#ifdef IEEE80211_SUPPORT_TDMA -static int -ath_sysctl_setcca(SYSCTL_HANDLER_ARGS) -{ - struct ath_softc *sc = arg1; - int setcca, error; - - setcca = sc->sc_setcca; - error = sysctl_handle_int(oidp, &setcca, 0, req); - if (error || !req->newptr) - return error; - sc->sc_setcca = (setcca != 0); - return 0; -} -#endif /* IEEE80211_SUPPORT_TDMA */ - -static void -ath_sysctlattach(struct ath_softc *sc) -{ - struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->sc_dev); - struct sysctl_oid *tree = device_get_sysctl_tree(sc->sc_dev); - struct ath_hal *ah = sc->sc_ah; - - SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, - "countrycode", CTLFLAG_RD, &sc->sc_eecc, 0, - "EEPROM country code"); - SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, - "regdomain", CTLFLAG_RD, &sc->sc_eerd, 0, - "EEPROM regdomain code"); -#ifdef ATH_DEBUG - SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, - "debug", CTLFLAG_RW, &sc->sc_debug, 0, - "control debugging printfs"); -#endif - SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, - "slottime", CTLTYPE_INT | CTLFLAG_RW, sc, 0, - ath_sysctl_slottime, "I", "802.11 slot time (us)"); - SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, - "acktimeout", CTLTYPE_INT | CTLFLAG_RW, sc, 0, - ath_sysctl_acktimeout, "I", "802.11 ACK timeout (us)"); - SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, - "ctstimeout", CTLTYPE_INT | CTLFLAG_RW, sc, 0, - ath_sysctl_ctstimeout, "I", "802.11 CTS timeout (us)"); - SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, - "softled", CTLTYPE_INT | CTLFLAG_RW, sc, 0, - ath_sysctl_softled, "I", "enable/disable software LED support"); - SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, - "ledpin", CTLTYPE_INT | CTLFLAG_RW, sc, 0, - ath_sysctl_ledpin, "I", "GPIO pin connected to LED"); - SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, - "ledon", CTLFLAG_RW, &sc->sc_ledon, 0, - "setting to turn LED on"); - SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, - "ledidle", CTLFLAG_RW, &sc->sc_ledidle, 0, - "idle time for inactivity LED (ticks)"); - SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, - "txantenna", CTLTYPE_INT | CTLFLAG_RW, sc, 0, - ath_sysctl_txantenna, "I", "antenna switch"); - SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, - "rxantenna", CTLTYPE_INT | CTLFLAG_RW, sc, 0, - ath_sysctl_rxantenna, "I", "default/rx antenna"); - if (ath_hal_hasdiversity(ah)) - SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, - "diversity", CTLTYPE_INT | CTLFLAG_RW, sc, 0, - ath_sysctl_diversity, "I", "antenna diversity"); - sc->sc_txintrperiod = ATH_TXINTR_PERIOD; - SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, - "txintrperiod", CTLFLAG_RW, &sc->sc_txintrperiod, 0, - "tx descriptor batching"); - SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, - "diag", CTLTYPE_INT | CTLFLAG_RW, sc, 0, - ath_sysctl_diag, "I", "h/w diagnostic control"); - SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, - "tpscale", CTLTYPE_INT | CTLFLAG_RW, sc, 0, - ath_sysctl_tpscale, "I", "tx power scaling"); - if (ath_hal_hastpc(ah)) { - SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, - "tpc", CTLTYPE_INT | CTLFLAG_RW, sc, 0, - ath_sysctl_tpc, "I", "enable/disable per-packet TPC"); - SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, - "tpack", CTLTYPE_INT | CTLFLAG_RW, sc, 0, - ath_sysctl_tpack, "I", "tx power for ack frames"); - SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, - "tpcts", CTLTYPE_INT | CTLFLAG_RW, sc, 0, - ath_sysctl_tpcts, "I", "tx power for cts frames"); - } - if (ath_hal_hasrfsilent(ah)) { - SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, - "rfsilent", CTLTYPE_INT | CTLFLAG_RW, sc, 0, - ath_sysctl_rfsilent, "I", "h/w RF silent config"); - SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, - "rfkill", CTLTYPE_INT | CTLFLAG_RW, sc, 0, - ath_sysctl_rfkill, "I", "enable/disable RF kill switch"); - } - if (ath_hal_hasintmit(ah)) { - SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, - "intmit", CTLTYPE_INT | CTLFLAG_RW, sc, 0, - ath_sysctl_intmit, "I", "interference mitigation"); - } - sc->sc_monpass = HAL_RXERR_DECRYPT | HAL_RXERR_MIC; - SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, - "monpass", CTLFLAG_RW, &sc->sc_monpass, 0, - "mask of error frames to pass when monitoring"); -#ifdef IEEE80211_SUPPORT_TDMA - if (ath_hal_macversion(ah) > 0x78) { - sc->sc_tdmadbaprep = 2; - SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, - "dbaprep", CTLFLAG_RW, &sc->sc_tdmadbaprep, 0, - "TDMA DBA preparation time"); - sc->sc_tdmaswbaprep = 10; - SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, - "swbaprep", CTLFLAG_RW, &sc->sc_tdmaswbaprep, 0, - "TDMA SWBA preparation time"); - SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, - "guardtime", CTLFLAG_RW, &sc->sc_tdmaguard, 0, - "TDMA slot guard time"); - SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, - "superframe", CTLFLAG_RD, &sc->sc_tdmabintval, 0, - "TDMA calculated super frame"); - SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, - "setcca", CTLTYPE_INT | CTLFLAG_RW, sc, 0, - ath_sysctl_setcca, "I", "enable CCA control"); - } -#endif -} - -static int -ath_tx_raw_start(struct ath_softc *sc, struct ieee80211_node *ni, - struct ath_buf *bf, struct mbuf *m0, - const struct ieee80211_bpf_params *params) -{ - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - struct ath_hal *ah = sc->sc_ah; - struct ieee80211vap *vap = ni->ni_vap; - int error, ismcast, ismrr; - int keyix, hdrlen, pktlen, try0, txantenna; - u_int8_t rix, cix, txrate, ctsrate, rate1, rate2, rate3; - struct ieee80211_frame *wh; - u_int flags, ctsduration; - HAL_PKT_TYPE atype; - const HAL_RATE_TABLE *rt; - struct ath_desc *ds; - u_int pri; - - wh = mtod(m0, struct ieee80211_frame *); - ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1); - hdrlen = ieee80211_anyhdrsize(wh); - /* - * Packet length must not include any - * pad bytes; deduct them here. - */ - /* XXX honor IEEE80211_BPF_DATAPAD */ - pktlen = m0->m_pkthdr.len - (hdrlen & 3) + IEEE80211_CRC_LEN; - - if (params->ibp_flags & IEEE80211_BPF_CRYPTO) { - const struct ieee80211_cipher *cip; - struct ieee80211_key *k; - - /* - * Construct the 802.11 header+trailer for an encrypted - * frame. The only reason this can fail is because of an - * unknown or unsupported cipher/key type. - */ - k = ieee80211_crypto_encap(ni, m0); - if (k == NULL) { - /* - * This can happen when the key is yanked after the - * frame was queued. Just discard the frame; the - * 802.11 layer counts failures and provides - * debugging/diagnostics. - */ - ath_freetx(m0); - return EIO; - } - /* - * Adjust the packet + header lengths for the crypto - * additions and calculate the h/w key index. When - * a s/w mic is done the frame will have had any mic - * added to it prior to entry so m0->m_pkthdr.len will - * account for it. Otherwise we need to add it to the - * packet length. - */ - cip = k->wk_cipher; - hdrlen += cip->ic_header; - pktlen += cip->ic_header + cip->ic_trailer; - /* NB: frags always have any TKIP MIC done in s/w */ - if ((k->wk_flags & IEEE80211_KEY_SWMIC) == 0) - pktlen += cip->ic_miclen; - keyix = k->wk_keyix; - - /* packet header may have moved, reset our local pointer */ - wh = mtod(m0, struct ieee80211_frame *); - } else if (ni->ni_ucastkey.wk_cipher == &ieee80211_cipher_none) { - /* - * Use station key cache slot, if assigned. - */ - keyix = ni->ni_ucastkey.wk_keyix; - if (keyix == IEEE80211_KEYIX_NONE) - keyix = HAL_TXKEYIX_INVALID; - } else - keyix = HAL_TXKEYIX_INVALID; - - error = ath_tx_dmasetup(sc, bf, m0); - if (error != 0) - return error; - m0 = bf->bf_m; /* NB: may have changed */ - wh = mtod(m0, struct ieee80211_frame *); - bf->bf_node = ni; /* NB: held reference */ - - flags = HAL_TXDESC_CLRDMASK; /* XXX needed for crypto errs */ - flags |= HAL_TXDESC_INTREQ; /* force interrupt */ - if (params->ibp_flags & IEEE80211_BPF_RTS) - flags |= HAL_TXDESC_RTSENA; - else if (params->ibp_flags & IEEE80211_BPF_CTS) - flags |= HAL_TXDESC_CTSENA; - /* XXX leave ismcast to injector? */ - if ((params->ibp_flags & IEEE80211_BPF_NOACK) || ismcast) - flags |= HAL_TXDESC_NOACK; - - rt = sc->sc_currates; - KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode)); - rix = ath_tx_findrix(sc, params->ibp_rate0); - txrate = rt->info[rix].rateCode; - if (params->ibp_flags & IEEE80211_BPF_SHORTPRE) - txrate |= rt->info[rix].shortPreamble; - sc->sc_txrix = rix; - try0 = params->ibp_try0; - ismrr = (params->ibp_try1 != 0); - txantenna = params->ibp_pri >> 2; - if (txantenna == 0) /* XXX? */ - txantenna = sc->sc_txantenna; - ctsduration = 0; - if (flags & (HAL_TXDESC_CTSENA | HAL_TXDESC_RTSENA)) { - cix = ath_tx_findrix(sc, params->ibp_ctsrate); - ctsrate = rt->info[cix].rateCode; - if (params->ibp_flags & IEEE80211_BPF_SHORTPRE) { - ctsrate |= rt->info[cix].shortPreamble; - if (flags & HAL_TXDESC_RTSENA) /* SIFS + CTS */ - ctsduration += rt->info[cix].spAckDuration; - ctsduration += ath_hal_computetxtime(ah, - rt, pktlen, rix, AH_TRUE); - if ((flags & HAL_TXDESC_NOACK) == 0) /* SIFS + ACK */ - ctsduration += rt->info[rix].spAckDuration; - } else { - if (flags & HAL_TXDESC_RTSENA) /* SIFS + CTS */ - ctsduration += rt->info[cix].lpAckDuration; - ctsduration += ath_hal_computetxtime(ah, - rt, pktlen, rix, AH_FALSE); - if ((flags & HAL_TXDESC_NOACK) == 0) /* SIFS + ACK */ - ctsduration += rt->info[rix].lpAckDuration; - } - ismrr = 0; /* XXX */ - } else - ctsrate = 0; - pri = params->ibp_pri & 3; - /* - * NB: we mark all packets as type PSPOLL so the h/w won't - * set the sequence number, duration, etc. - */ - atype = HAL_PKT_TYPE_PSPOLL; - - if (IFF_DUMPPKTS(sc, ATH_DEBUG_XMIT)) - ieee80211_dump_pkt(ic, mtod(m0, caddr_t), m0->m_len, - sc->sc_hwmap[rix].ieeerate, -1); - - if (ieee80211_radiotap_active_vap(vap)) { - u_int64_t tsf = ath_hal_gettsf64(ah); - - sc->sc_tx_th.wt_tsf = htole64(tsf); - sc->sc_tx_th.wt_flags = sc->sc_hwmap[rix].txflags; - if (wh->i_fc[1] & IEEE80211_FC1_WEP) - sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP; - if (m0->m_flags & M_FRAG) - sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_FRAG; - sc->sc_tx_th.wt_rate = sc->sc_hwmap[rix].ieeerate; - sc->sc_tx_th.wt_txpower = ni->ni_txpower; - sc->sc_tx_th.wt_antenna = sc->sc_txantenna; - - ieee80211_radiotap_tx(vap, m0); - } - - /* - * Formulate first tx descriptor with tx controls. - */ - ds = bf->bf_desc; - /* XXX check return value? */ - ath_hal_setuptxdesc(ah, ds - , pktlen /* packet length */ - , hdrlen /* header length */ - , atype /* Atheros packet type */ - , params->ibp_power /* txpower */ - , txrate, try0 /* series 0 rate/tries */ - , keyix /* key cache index */ - , txantenna /* antenna mode */ - , flags /* flags */ - , ctsrate /* rts/cts rate */ - , ctsduration /* rts/cts duration */ - ); - bf->bf_txflags = flags; - - if (ismrr) { - rix = ath_tx_findrix(sc, params->ibp_rate1); - rate1 = rt->info[rix].rateCode; - if (params->ibp_flags & IEEE80211_BPF_SHORTPRE) - rate1 |= rt->info[rix].shortPreamble; - if (params->ibp_try2) { - rix = ath_tx_findrix(sc, params->ibp_rate2); - rate2 = rt->info[rix].rateCode; - if (params->ibp_flags & IEEE80211_BPF_SHORTPRE) - rate2 |= rt->info[rix].shortPreamble; - } else - rate2 = 0; - if (params->ibp_try3) { - rix = ath_tx_findrix(sc, params->ibp_rate3); - rate3 = rt->info[rix].rateCode; - if (params->ibp_flags & IEEE80211_BPF_SHORTPRE) - rate3 |= rt->info[rix].shortPreamble; - } else - rate3 = 0; - ath_hal_setupxtxdesc(ah, ds - , rate1, params->ibp_try1 /* series 1 */ - , rate2, params->ibp_try2 /* series 2 */ - , rate3, params->ibp_try3 /* series 3 */ - ); - } - - /* NB: no buffered multicast in power save support */ - ath_tx_handoff(sc, sc->sc_ac2q[pri], bf); - return 0; -} - -static int -ath_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, - const struct ieee80211_bpf_params *params) -{ - struct ieee80211com *ic = ni->ni_ic; - struct ifnet *ifp = ic->ic_ifp; - struct ath_softc *sc = ifp->if_softc; - struct ath_buf *bf; - int error; - - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || sc->sc_invalid) { - DPRINTF(sc, ATH_DEBUG_XMIT, "%s: discard frame, %s", __func__, - (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ? - "!running" : "invalid"); - m_freem(m); - error = ENETDOWN; - goto bad; - } - /* - * Grab a TX buffer and associated resources. - */ - bf = ath_getbuf(sc); - if (bf == NULL) { - sc->sc_stats.ast_tx_nobuf++; - m_freem(m); - error = ENOBUFS; - goto bad; - } - - if (params == NULL) { - /* - * Legacy path; interpret frame contents to decide - * precisely how to send the frame. - */ - if (ath_tx_start(sc, ni, bf, m)) { - error = EIO; /* XXX */ - goto bad2; - } - } else { - /* - * Caller supplied explicit parameters to use in - * sending the frame. - */ - if (ath_tx_raw_start(sc, ni, bf, m, params)) { - error = EIO; /* XXX */ - goto bad2; - } - } - sc->sc_wd_timer = 5; - ifp->if_opackets++; - sc->sc_stats.ast_tx_raw++; - - return 0; -bad2: - ATH_TXBUF_LOCK(sc); - STAILQ_INSERT_HEAD(&sc->sc_txbuf, bf, bf_list); - ATH_TXBUF_UNLOCK(sc); -bad: - ifp->if_oerrors++; - sc->sc_stats.ast_tx_raw_fail++; - ieee80211_free_node(ni); - return error; -} - /* * Announce various information on device/driver attach. */ @@ -6975,20 +5484,6 @@ ath_announce(struct ath_softc *sc) } #ifdef IEEE80211_SUPPORT_TDMA -static __inline uint32_t -ath_hal_getnexttbtt(struct ath_hal *ah) -{ -#define AR_TIMER0 0x8028 - return OS_REG_READ(ah, AR_TIMER0); -} - -static __inline void -ath_hal_adjusttsf(struct ath_hal *ah, int32_t tsfdelta) -{ - /* XXX handle wrap/overflow */ - OS_REG_WRITE(ah, AR_TSF_L32, OS_REG_READ(ah, AR_TSF_L32) + tsfdelta); -} - static void ath_tdma_settimers(struct ath_softc *sc, u_int32_t nexttbtt, u_int32_t bintval) { @@ -7000,6 +5495,8 @@ ath_tdma_settimers(struct ath_softc *sc, u_int32_t nexttbtt, u_int32_t bintval) bt.bt_nextdba = (nexttbtt<<3) - sc->sc_tdmadbaprep; bt.bt_nextswba = (nexttbtt<<3) - sc->sc_tdmaswbaprep; bt.bt_nextatim = nexttbtt+1; + /* Enables TBTT, DBA, SWBA timers by default */ + bt.bt_flags = 0; ath_hal_beaconsettimers(ah, &bt); } @@ -7142,8 +5639,8 @@ ath_tdma_update(struct ieee80211_node *ni, struct ath_softc *sc = ic->ic_ifp->if_softc; struct ath_hal *ah = sc->sc_ah; const HAL_RATE_TABLE *rt = sc->sc_currates; - u_int64_t tsf, rstamp, nextslot; - u_int32_t txtime, nextslottu, timer0; + u_int64_t tsf, rstamp, nextslot, nexttbtt; + u_int32_t txtime, nextslottu; int32_t tudelta, tsfdelta; const struct ath_rx_status *rs; int rix; @@ -7174,7 +5671,7 @@ ath_tdma_update(struct ieee80211_node *ni, /* extend rx timestamp to 64 bits */ rs = sc->sc_lastrs; tsf = ath_hal_gettsf64(ah); - rstamp = ath_extend_tsf(rs->rs_tstamp, tsf); + rstamp = ath_extend_tsf(sc, rs->rs_tstamp, tsf); /* * The rx timestamp is set by the hardware on completing * reception (at the point where the rx descriptor is DMA'd @@ -7190,15 +5687,15 @@ ath_tdma_update(struct ieee80211_node *ni, nextslottu = TSF_TO_TU(nextslot>>32, nextslot) & HAL_BEACON_PERIOD; /* - * TIMER0 is the h/w's idea of NextTBTT (in TU's). Convert - * to usecs and calculate the difference between what the + * Retrieve the hardware NextTBTT in usecs + * and calculate the difference between what the * other station thinks and what we have programmed. This * lets us figure how to adjust our timers to match. The * adjustments are done by pulling the TSF forward and possibly * rewriting the beacon timers. */ - timer0 = ath_hal_getnexttbtt(ah); - tsfdelta = (int32_t)((nextslot % TU_TO_TSF(HAL_BEACON_PERIOD+1)) - TU_TO_TSF(timer0)); + nexttbtt = ath_hal_getnexttbtt(ah); + tsfdelta = (int32_t)((nextslot % TU_TO_TSF(HAL_BEACON_PERIOD + 1)) - nexttbtt); DPRINTF(sc, ATH_DEBUG_TDMA_TIMER, "tsfdelta %d avg +%d/-%d\n", tsfdelta, @@ -7218,7 +5715,7 @@ ath_tdma_update(struct ieee80211_node *ni, TDMA_SAMPLE(sc->sc_avgtsfdeltap, 0); TDMA_SAMPLE(sc->sc_avgtsfdeltam, 0); } - tudelta = nextslottu - timer0; + tudelta = nextslottu - TSF_TO_TU(nexttbtt >> 32, nexttbtt); /* * Copy sender's timetstamp into tdma ie so they can @@ -7237,10 +5734,9 @@ ath_tdma_update(struct ieee80211_node *ni, &ni->ni_tstamp.data, 8); #if 0 DPRINTF(sc, ATH_DEBUG_TDMA_TIMER, - "tsf %llu nextslot %llu (%d, %d) nextslottu %u timer0 %u (%d)\n", + "tsf %llu nextslot %llu (%d, %d) nextslottu %u nexttbtt %llu (%d)\n", (unsigned long long) tsf, (unsigned long long) nextslot, - (int)(nextslot - tsf), tsfdelta, - nextslottu, timer0, tudelta); + (int)(nextslot - tsf), tsfdelta, nextslottu, nexttbtt, tudelta); #endif /* * Adjust the beacon timers only when pulling them forward @@ -7335,3 +5831,24 @@ ath_tdma_beacon_send(struct ath_softc *sc, struct ieee80211vap *vap) } } #endif /* IEEE80211_SUPPORT_TDMA */ + +static void +ath_dfs_tasklet(void *p, int npending) +{ + struct ath_softc *sc = (struct ath_softc *) p; + struct ifnet *ifp = sc->sc_ifp; + struct ieee80211com *ic = ifp->if_l2com; + + /* + * If previous processing has found a radar event, + * signal this to the net80211 layer to begin DFS + * processing. + */ + if (ath_dfs_process_radar_event(sc, sc->sc_curchan)) { + /* DFS event found, initiate channel change */ + ieee80211_dfs_notify_radar(ic, sc->sc_curchan); + } +} + +MODULE_VERSION(if_ath, 1); +MODULE_DEPEND(if_ath, wlan, 1, 1, 1); /* 802.11 media layer */ diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_ath_ahb.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_ath_ahb.c new file mode 100644 index 0000000000..a2bca05d3c --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_ath_ahb.c @@ -0,0 +1,291 @@ +/*- + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2010-2011 Adrian Chadd, Xenion Pty Ltd + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. + */ + +#include +__FBSDID("$FreeBSD$"); + +/* + * AHB bus front-end for the Atheros Wireless LAN controller driver. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include + +#include + +#include +#include +#include + +/* + * bus glue. + */ + +/* number of 16 bit words */ +#define ATH_EEPROM_DATA_SIZE 2048 + +struct ath_ahb_softc { + struct ath_softc sc_sc; + struct resource *sc_sr; /* memory resource */ + struct resource *sc_irq; /* irq resource */ + struct resource *sc_eeprom; /* eeprom location */ + void *sc_ih; /* interrupt handler */ +}; + +#define VENDOR_ATHEROS 0x168c +#define AR9130_DEVID 0x000b + +static int +ath_ahb_probe(device_t dev) +{ + const char* devname; + + /* Atheros / ar9130 */ + devname = ath_hal_probe(VENDOR_ATHEROS, AR9130_DEVID); + + if (devname != NULL) { + device_set_desc(dev, devname); + return BUS_PROBE_DEFAULT; + } + return ENXIO; +} + +static int +ath_ahb_attach(device_t dev) +{ + struct ath_ahb_softc *psc = device_get_softc(dev); + struct ath_softc *sc = &psc->sc_sc; + int error = ENXIO; + int rid; + long eepromaddr; + uint8_t *p; + + sc->sc_dev = dev; + + rid = 0; + psc->sc_sr = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); + if (psc->sc_sr == NULL) { + device_printf(dev, "cannot map register space\n"); + goto bad; + } + + if (resource_long_value(device_get_name(dev), device_get_unit(dev), + "eepromaddr", &eepromaddr) != 0) { + device_printf(dev, "cannot fetch 'eepromaddr' from hints\n"); + goto bad0; + } + rid = 0; + device_printf(sc->sc_dev, "eeprom @ %p\n", (void *) eepromaddr); + psc->sc_eeprom = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, (uintptr_t) eepromaddr, + (uintptr_t) eepromaddr + (uintptr_t) ((ATH_EEPROM_DATA_SIZE * 2) - 1), 0, RF_ACTIVE); + if (psc->sc_eeprom == NULL) { + device_printf(dev, "cannot map eeprom space\n"); + goto bad0; + } + + /* XXX uintptr_t is a bandaid for ia64; to be fixed */ + sc->sc_st = (HAL_BUS_TAG)(uintptr_t) rman_get_bustag(psc->sc_sr); + sc->sc_sh = (HAL_BUS_HANDLE) rman_get_bushandle(psc->sc_sr); + /* + * Mark device invalid so any interrupts (shared or otherwise) + * that arrive before the HAL is setup are discarded. + */ + sc->sc_invalid = 1; + + /* Copy the EEPROM data out */ + sc->sc_eepromdata = malloc(ATH_EEPROM_DATA_SIZE * 2, M_TEMP, M_NOWAIT | M_ZERO); + if (sc->sc_eepromdata == NULL) { + device_printf(dev, "cannot allocate memory for eeprom data\n"); + goto bad1; + } + device_printf(sc->sc_dev, "eeprom data @ %p\n", (void *) rman_get_bushandle(psc->sc_eeprom)); + /* XXX why doesn't this work? -adrian */ +#if 0 + bus_space_read_multi_1( + rman_get_bustag(psc->sc_eeprom), + rman_get_bushandle(psc->sc_eeprom), + 0, (u_int8_t *) sc->sc_eepromdata, ATH_EEPROM_DATA_SIZE * 2); +#endif + p = (void *) rman_get_bushandle(psc->sc_eeprom); + memcpy(sc->sc_eepromdata, p, ATH_EEPROM_DATA_SIZE * 2); + + /* + * Arrange interrupt line. + */ + rid = 0; + psc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_SHAREABLE|RF_ACTIVE); + if (psc->sc_irq == NULL) { + device_printf(dev, "could not map interrupt\n"); + goto bad1; + } + if (bus_setup_intr(dev, psc->sc_irq, + INTR_TYPE_NET | INTR_MPSAFE, + NULL, ath_intr, sc, &psc->sc_ih)) { + device_printf(dev, "could not establish interrupt\n"); + goto bad2; + } + + /* + * Setup DMA descriptor area. + */ + if (bus_dma_tag_create(bus_get_dma_tag(dev), /* parent */ + 1, 0, /* alignment, bounds */ + BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ + BUS_SPACE_MAXADDR, /* highaddr */ + NULL, NULL, /* filter, filterarg */ + 0x3ffff, /* maxsize XXX */ + ATH_MAX_SCATTER, /* nsegments */ + 0x3ffff, /* maxsegsize XXX */ + BUS_DMA_ALLOCNOW, /* flags */ + NULL, /* lockfunc */ + NULL, /* lockarg */ + &sc->sc_dmat)) { + device_printf(dev, "cannot allocate DMA tag\n"); + goto bad3; + } + + ATH_LOCK_INIT(sc); + + error = ath_attach(AR9130_DEVID, sc); + if (error == 0) /* success */ + return 0; + + ATH_LOCK_DESTROY(sc); + bus_dma_tag_destroy(sc->sc_dmat); +bad3: + bus_teardown_intr(dev, psc->sc_irq, psc->sc_ih); +bad2: + bus_release_resource(dev, SYS_RES_IRQ, 0, psc->sc_irq); +bad1: + bus_release_resource(dev, SYS_RES_MEMORY, 0, psc->sc_eeprom); +bad0: + bus_release_resource(dev, SYS_RES_MEMORY, 0, psc->sc_sr); +bad: + /* XXX?! */ + if (sc->sc_eepromdata) + free(sc->sc_eepromdata, M_TEMP); + return (error); +} + +static int +ath_ahb_detach(device_t dev) +{ + struct ath_ahb_softc *psc = device_get_softc(dev); + struct ath_softc *sc = &psc->sc_sc; + + /* check if device was removed */ + sc->sc_invalid = !bus_child_present(dev); + + ath_detach(sc); + + bus_generic_detach(dev); + bus_teardown_intr(dev, psc->sc_irq, psc->sc_ih); + bus_release_resource(dev, SYS_RES_IRQ, 0, psc->sc_irq); + + bus_dma_tag_destroy(sc->sc_dmat); + bus_release_resource(dev, SYS_RES_MEMORY, 0, psc->sc_sr); + bus_release_resource(dev, SYS_RES_MEMORY, 0, psc->sc_eeprom); + /* XXX?! */ + if (sc->sc_eepromdata) + free(sc->sc_eepromdata, M_TEMP); + + ATH_LOCK_DESTROY(sc); + + return (0); +} + +static int +ath_ahb_shutdown(device_t dev) +{ + struct ath_ahb_softc *psc = device_get_softc(dev); + + ath_shutdown(&psc->sc_sc); + return (0); +} + +static int +ath_ahb_suspend(device_t dev) +{ + struct ath_ahb_softc *psc = device_get_softc(dev); + + ath_suspend(&psc->sc_sc); + + return (0); +} + +static int +ath_ahb_resume(device_t dev) +{ + struct ath_ahb_softc *psc = device_get_softc(dev); + + ath_resume(&psc->sc_sc); + + return (0); +} + +static device_method_t ath_ahb_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, ath_ahb_probe), + DEVMETHOD(device_attach, ath_ahb_attach), + DEVMETHOD(device_detach, ath_ahb_detach), + DEVMETHOD(device_shutdown, ath_ahb_shutdown), + DEVMETHOD(device_suspend, ath_ahb_suspend), + DEVMETHOD(device_resume, ath_ahb_resume), + + { 0,0 } +}; +static driver_t ath_ahb_driver = { + "ath", + ath_ahb_methods, + sizeof (struct ath_ahb_softc) +}; +static devclass_t ath_devclass; +DRIVER_MODULE(ath, nexus, ath_ahb_driver, ath_devclass, 0, 0); +MODULE_VERSION(ath, 1); +MODULE_DEPEND(ath, wlan, 1, 1, 1); /* 802.11 media layer */ +MODULE_DEPEND(ath, if_ath, 1, 1, 1); /* if_ath driver */ diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_ath_debug.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_ath_debug.c new file mode 100644 index 0000000000..b5691acfb6 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_ath_debug.c @@ -0,0 +1,156 @@ +/*- + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include "opt_inet.h" +#include "opt_ath.h" +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#ifdef IEEE80211_SUPPORT_SUPERG +#include +#endif +#ifdef IEEE80211_SUPPORT_TDMA +#include +#endif + +#include + +#ifdef INET +#include +#include +#endif + +#include +#include /* XXX for softled */ +#include + +#ifdef ATH_TX99_DIAG +#include +#endif + +#ifdef ATH_DEBUG +#include + +int ath_debug = 0; + +SYSCTL_DECL(_hw_ath); +SYSCTL_INT(_hw_ath, OID_AUTO, debug, CTLFLAG_RW, &ath_debug, + 0, "control debugging printfs"); +TUNABLE_INT("hw.ath.debug", &ath_debug); + +void +ath_printrxbuf(struct ath_softc *sc, const struct ath_buf *bf, + u_int ix, int done) +{ + const struct ath_rx_status *rs = &bf->bf_status.ds_rxstat; + struct ath_hal *ah = sc->sc_ah; + const struct ath_desc *ds; + int i; + + for (i = 0, ds = bf->bf_desc; i < bf->bf_nseg; i++, ds++) { + printf("R[%2u] (DS.V:%p DS.P:%p) L:%08x D:%08x%s\n" + " %08x %08x %08x %08x\n", + ix, ds, (const struct ath_desc *)bf->bf_daddr + i, + ds->ds_link, ds->ds_data, + !done ? "" : (rs->rs_status == 0) ? " *" : " !", + ds->ds_ctl0, ds->ds_ctl1, + ds->ds_hw[0], ds->ds_hw[1]); + if (ah->ah_magic == 0x20065416) { + printf(" %08x %08x %08x %08x %08x %08x %08x\n", + ds->ds_hw[2], ds->ds_hw[3], ds->ds_hw[4], + ds->ds_hw[5], ds->ds_hw[6], ds->ds_hw[7], + ds->ds_hw[8]); + } + } +} + +void +ath_printtxbuf(struct ath_softc *sc, const struct ath_buf *bf, + u_int qnum, u_int ix, int done) +{ + const struct ath_tx_status *ts = &bf->bf_status.ds_txstat; + struct ath_hal *ah = sc->sc_ah; + const struct ath_desc *ds; + int i; + + printf("Q%u[%3u]", qnum, ix); + for (i = 0, ds = bf->bf_desc; i < bf->bf_nseg; i++, ds++) { + printf(" (DS.V:%p DS.P:%p) L:%08x D:%08x F:04%x%s\n" + " %08x %08x %08x %08x %08x %08x\n", + ds, (const struct ath_desc *)bf->bf_daddr + i, + ds->ds_link, ds->ds_data, bf->bf_txflags, + !done ? "" : (ts->ts_status == 0) ? " *" : " !", + ds->ds_ctl0, ds->ds_ctl1, + ds->ds_hw[0], ds->ds_hw[1], ds->ds_hw[2], ds->ds_hw[3]); + if (ah->ah_magic == 0x20065416) { + printf(" %08x %08x %08x %08x %08x %08x %08x %08x\n", + ds->ds_hw[4], ds->ds_hw[5], ds->ds_hw[6], + ds->ds_hw[7], ds->ds_hw[8], ds->ds_hw[9], + ds->ds_hw[10],ds->ds_hw[11]); + printf(" %08x %08x %08x %08x %08x %08x %08x %08x\n", + ds->ds_hw[12],ds->ds_hw[13],ds->ds_hw[14], + ds->ds_hw[15],ds->ds_hw[16],ds->ds_hw[17], + ds->ds_hw[18], ds->ds_hw[19]); + } + } +} + +#endif /* ATH_DEBUG */ diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_ath_debug.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_ath_debug.h new file mode 100644 index 0000000000..c21914fe8d --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_ath_debug.h @@ -0,0 +1,93 @@ +/*- + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. + * + * $FreeBSD$ + */ +#ifndef __IF_ATH_DEBUG_H__ +#define __IF_ATH_DEBUG_H__ + +#ifdef ATH_DEBUG + +enum { + ATH_DEBUG_XMIT = 0x00000001, /* basic xmit operation */ + ATH_DEBUG_XMIT_DESC = 0x00000002, /* xmit descriptors */ + ATH_DEBUG_RECV = 0x00000004, /* basic recv operation */ + ATH_DEBUG_RECV_DESC = 0x00000008, /* recv descriptors */ + ATH_DEBUG_RATE = 0x00000010, /* rate control */ + ATH_DEBUG_RESET = 0x00000020, /* reset processing */ + ATH_DEBUG_MODE = 0x00000040, /* mode init/setup */ + ATH_DEBUG_BEACON = 0x00000080, /* beacon handling */ + ATH_DEBUG_WATCHDOG = 0x00000100, /* watchdog timeout */ + ATH_DEBUG_INTR = 0x00001000, /* ISR */ + ATH_DEBUG_TX_PROC = 0x00002000, /* tx ISR proc */ + ATH_DEBUG_RX_PROC = 0x00004000, /* rx ISR proc */ + ATH_DEBUG_BEACON_PROC = 0x00008000, /* beacon ISR proc */ + ATH_DEBUG_CALIBRATE = 0x00010000, /* periodic calibration */ + ATH_DEBUG_KEYCACHE = 0x00020000, /* key cache management */ + ATH_DEBUG_STATE = 0x00040000, /* 802.11 state transitions */ + ATH_DEBUG_NODE = 0x00080000, /* node management */ + ATH_DEBUG_LED = 0x00100000, /* led management */ + ATH_DEBUG_FF = 0x00200000, /* fast frames */ + ATH_DEBUG_DFS = 0x00400000, /* DFS processing */ + ATH_DEBUG_TDMA = 0x00800000, /* TDMA processing */ + ATH_DEBUG_TDMA_TIMER = 0x01000000, /* TDMA timer processing */ + ATH_DEBUG_REGDOMAIN = 0x02000000, /* regulatory processing */ + ATH_DEBUG_FATAL = 0x80000000, /* fatal errors */ + ATH_DEBUG_ANY = 0xffffffff +}; + +extern int ath_debug; + +#define IFF_DUMPPKTS(sc, m) \ + ((sc->sc_debug & (m)) || \ + (sc->sc_ifp->if_flags & (IFF_DEBUG|IFF_LINK2)) == (IFF_DEBUG|IFF_LINK2)) +#define DPRINTF(sc, m, fmt, ...) do { \ + if (sc->sc_debug & (m)) \ + device_printf(sc->sc_dev, fmt, __VA_ARGS__); \ +} while (0) +#define KEYPRINTF(sc, ix, hk, mac) do { \ + if (sc->sc_debug & ATH_DEBUG_KEYCACHE) \ + ath_keyprint(sc, __func__, ix, hk, mac); \ +} while (0) + +extern void ath_printrxbuf(struct ath_softc *, const struct ath_buf *bf, + u_int ix, int); +extern void ath_printtxbuf(struct ath_softc *, const struct ath_buf *bf, + u_int qnum, u_int ix, int done); +#else /* ATH_DEBUG */ +#define IFF_DUMPPKTS(sc, m) \ + ((sc->sc_ifp->if_flags & (IFF_DEBUG|IFF_LINK2)) == (IFF_DEBUG|IFF_LINK2)) +#define DPRINTF(sc, m, fmt, ...) do { \ + (void) sc; \ +} while (0) +#define KEYPRINTF(sc, k, ix, mac) do { \ + (void) sc; \ +} while (0) +#endif /* ATH_DEBUG */ + +#endif diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_ath_keycache.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_ath_keycache.c new file mode 100644 index 0000000000..842f76627f --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_ath_keycache.c @@ -0,0 +1,497 @@ +/*- + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. + */ + +#include +__FBSDID("$FreeBSD$"); + +/* + * Driver for the Atheros Wireless LAN controller. + * + * This software is derived from work of Atsushi Onoe; his contribution + * is greatly appreciated. + */ + +#include "opt_inet.h" +#include "opt_ath.h" +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include + +#include +#include + +#ifdef ATH_DEBUG +static void +ath_keyprint(struct ath_softc *sc, const char *tag, u_int ix, + const HAL_KEYVAL *hk, const u_int8_t mac[IEEE80211_ADDR_LEN]) +{ + static const char *ciphers[] = { + "WEP", + "AES-OCB", + "AES-CCM", + "CKIP", + "TKIP", + "CLR", + }; + int i, n; + + printf("%s: [%02u] %-7s ", tag, ix, ciphers[hk->kv_type]); + for (i = 0, n = hk->kv_len; i < n; i++) + printf("%02x", hk->kv_val[i]); + printf(" mac %s", ether_sprintf(mac)); + if (hk->kv_type == HAL_CIPHER_TKIP) { + printf(" %s ", sc->sc_splitmic ? "mic" : "rxmic"); + for (i = 0; i < sizeof(hk->kv_mic); i++) + printf("%02x", hk->kv_mic[i]); + if (!sc->sc_splitmic) { + printf(" txmic "); + for (i = 0; i < sizeof(hk->kv_txmic); i++) + printf("%02x", hk->kv_txmic[i]); + } + } + printf("\n"); +} +#endif + +/* + * Set a TKIP key into the hardware. This handles the + * potential distribution of key state to multiple key + * cache slots for TKIP. + */ +static int +ath_keyset_tkip(struct ath_softc *sc, const struct ieee80211_key *k, + HAL_KEYVAL *hk, const u_int8_t mac[IEEE80211_ADDR_LEN]) +{ +#define IEEE80211_KEY_XR (IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV) + static const u_int8_t zerobssid[IEEE80211_ADDR_LEN]; + struct ath_hal *ah = sc->sc_ah; + + KASSERT(k->wk_cipher->ic_cipher == IEEE80211_CIPHER_TKIP, + ("got a non-TKIP key, cipher %u", k->wk_cipher->ic_cipher)); + if ((k->wk_flags & IEEE80211_KEY_XR) == IEEE80211_KEY_XR) { + if (sc->sc_splitmic) { + /* + * TX key goes at first index, RX key at the rx index. + * The hal handles the MIC keys at index+64. + */ + memcpy(hk->kv_mic, k->wk_txmic, sizeof(hk->kv_mic)); + KEYPRINTF(sc, k->wk_keyix, hk, zerobssid); + if (!ath_hal_keyset(ah, k->wk_keyix, hk, zerobssid)) + return 0; + + memcpy(hk->kv_mic, k->wk_rxmic, sizeof(hk->kv_mic)); + KEYPRINTF(sc, k->wk_keyix+32, hk, mac); + /* XXX delete tx key on failure? */ + return ath_hal_keyset(ah, k->wk_keyix+32, hk, mac); + } else { + /* + * Room for both TX+RX MIC keys in one key cache + * slot, just set key at the first index; the hal + * will handle the rest. + */ + memcpy(hk->kv_mic, k->wk_rxmic, sizeof(hk->kv_mic)); + memcpy(hk->kv_txmic, k->wk_txmic, sizeof(hk->kv_txmic)); + KEYPRINTF(sc, k->wk_keyix, hk, mac); + return ath_hal_keyset(ah, k->wk_keyix, hk, mac); + } + } else if (k->wk_flags & IEEE80211_KEY_XMIT) { + if (sc->sc_splitmic) { + /* + * NB: must pass MIC key in expected location when + * the keycache only holds one MIC key per entry. + */ + memcpy(hk->kv_mic, k->wk_txmic, sizeof(hk->kv_txmic)); + } else + memcpy(hk->kv_txmic, k->wk_txmic, sizeof(hk->kv_txmic)); + KEYPRINTF(sc, k->wk_keyix, hk, mac); + return ath_hal_keyset(ah, k->wk_keyix, hk, mac); + } else if (k->wk_flags & IEEE80211_KEY_RECV) { + memcpy(hk->kv_mic, k->wk_rxmic, sizeof(hk->kv_mic)); + KEYPRINTF(sc, k->wk_keyix, hk, mac); + return ath_hal_keyset(ah, k->wk_keyix, hk, mac); + } + return 0; +#undef IEEE80211_KEY_XR +} + +/* + * Set a net80211 key into the hardware. This handles the + * potential distribution of key state to multiple key + * cache slots for TKIP with hardware MIC support. + */ +int +ath_keyset(struct ath_softc *sc, const struct ieee80211_key *k, + struct ieee80211_node *bss) +{ +#define N(a) (sizeof(a)/sizeof(a[0])) + static const u_int8_t ciphermap[] = { + HAL_CIPHER_WEP, /* IEEE80211_CIPHER_WEP */ + HAL_CIPHER_TKIP, /* IEEE80211_CIPHER_TKIP */ + HAL_CIPHER_AES_OCB, /* IEEE80211_CIPHER_AES_OCB */ + HAL_CIPHER_AES_CCM, /* IEEE80211_CIPHER_AES_CCM */ + (u_int8_t) -1, /* 4 is not allocated */ + HAL_CIPHER_CKIP, /* IEEE80211_CIPHER_CKIP */ + HAL_CIPHER_CLR, /* IEEE80211_CIPHER_NONE */ + }; + struct ath_hal *ah = sc->sc_ah; + const struct ieee80211_cipher *cip = k->wk_cipher; + u_int8_t gmac[IEEE80211_ADDR_LEN]; + const u_int8_t *mac; + HAL_KEYVAL hk; + + memset(&hk, 0, sizeof(hk)); + /* + * Software crypto uses a "clear key" so non-crypto + * state kept in the key cache are maintained and + * so that rx frames have an entry to match. + */ + if ((k->wk_flags & IEEE80211_KEY_SWCRYPT) == 0) { + KASSERT(cip->ic_cipher < N(ciphermap), + ("invalid cipher type %u", cip->ic_cipher)); + hk.kv_type = ciphermap[cip->ic_cipher]; + hk.kv_len = k->wk_keylen; + memcpy(hk.kv_val, k->wk_key, k->wk_keylen); + } else + hk.kv_type = HAL_CIPHER_CLR; + + if ((k->wk_flags & IEEE80211_KEY_GROUP) && sc->sc_mcastkey) { + /* + * Group keys on hardware that supports multicast frame + * key search use a MAC that is the sender's address with + * the multicast bit set instead of the app-specified address. + */ + IEEE80211_ADDR_COPY(gmac, bss->ni_macaddr); + gmac[0] |= 0x01; + mac = gmac; + } else + mac = k->wk_macaddr; + + if (hk.kv_type == HAL_CIPHER_TKIP && + (k->wk_flags & IEEE80211_KEY_SWMIC) == 0) { + return ath_keyset_tkip(sc, k, &hk, mac); + } else { + KEYPRINTF(sc, k->wk_keyix, &hk, mac); + return ath_hal_keyset(ah, k->wk_keyix, &hk, mac); + } +#undef N +} + +/* + * Allocate tx/rx key slots for TKIP. We allocate two slots for + * each key, one for decrypt/encrypt and the other for the MIC. + */ +static u_int16_t +key_alloc_2pair(struct ath_softc *sc, + ieee80211_keyix *txkeyix, ieee80211_keyix *rxkeyix) +{ +#define N(a) (sizeof(a)/sizeof(a[0])) + u_int i, keyix; + + KASSERT(sc->sc_splitmic, ("key cache !split")); + /* XXX could optimize */ + for (i = 0; i < N(sc->sc_keymap)/4; i++) { + u_int8_t b = sc->sc_keymap[i]; + if (b != 0xff) { + /* + * One or more slots in this byte are free. + */ + keyix = i*NBBY; + while (b & 1) { + again: + keyix++; + b >>= 1; + } + /* XXX IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV */ + if (isset(sc->sc_keymap, keyix+32) || + isset(sc->sc_keymap, keyix+64) || + isset(sc->sc_keymap, keyix+32+64)) { + /* full pair unavailable */ + /* XXX statistic */ + if (keyix == (i+1)*NBBY) { + /* no slots were appropriate, advance */ + continue; + } + goto again; + } + setbit(sc->sc_keymap, keyix); + setbit(sc->sc_keymap, keyix+64); + setbit(sc->sc_keymap, keyix+32); + setbit(sc->sc_keymap, keyix+32+64); + DPRINTF(sc, ATH_DEBUG_KEYCACHE, + "%s: key pair %u,%u %u,%u\n", + __func__, keyix, keyix+64, + keyix+32, keyix+32+64); + *txkeyix = keyix; + *rxkeyix = keyix+32; + return 1; + } + } + DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s: out of pair space\n", __func__); + return 0; +#undef N +} + +/* + * Allocate tx/rx key slots for TKIP. We allocate two slots for + * each key, one for decrypt/encrypt and the other for the MIC. + */ +static u_int16_t +key_alloc_pair(struct ath_softc *sc, + ieee80211_keyix *txkeyix, ieee80211_keyix *rxkeyix) +{ +#define N(a) (sizeof(a)/sizeof(a[0])) + u_int i, keyix; + + KASSERT(!sc->sc_splitmic, ("key cache split")); + /* XXX could optimize */ + for (i = 0; i < N(sc->sc_keymap)/4; i++) { + u_int8_t b = sc->sc_keymap[i]; + if (b != 0xff) { + /* + * One or more slots in this byte are free. + */ + keyix = i*NBBY; + while (b & 1) { + again: + keyix++; + b >>= 1; + } + if (isset(sc->sc_keymap, keyix+64)) { + /* full pair unavailable */ + /* XXX statistic */ + if (keyix == (i+1)*NBBY) { + /* no slots were appropriate, advance */ + continue; + } + goto again; + } + setbit(sc->sc_keymap, keyix); + setbit(sc->sc_keymap, keyix+64); + DPRINTF(sc, ATH_DEBUG_KEYCACHE, + "%s: key pair %u,%u\n", + __func__, keyix, keyix+64); + *txkeyix = *rxkeyix = keyix; + return 1; + } + } + DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s: out of pair space\n", __func__); + return 0; +#undef N +} + +/* + * Allocate a single key cache slot. + */ +static int +key_alloc_single(struct ath_softc *sc, + ieee80211_keyix *txkeyix, ieee80211_keyix *rxkeyix) +{ +#define N(a) (sizeof(a)/sizeof(a[0])) + u_int i, keyix; + + /* XXX try i,i+32,i+64,i+32+64 to minimize key pair conflicts */ + for (i = 0; i < N(sc->sc_keymap); i++) { + u_int8_t b = sc->sc_keymap[i]; + if (b != 0xff) { + /* + * One or more slots are free. + */ + keyix = i*NBBY; + while (b & 1) + keyix++, b >>= 1; + setbit(sc->sc_keymap, keyix); + DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s: key %u\n", + __func__, keyix); + *txkeyix = *rxkeyix = keyix; + return 1; + } + } + DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s: out of space\n", __func__); + return 0; +#undef N +} + +/* + * Allocate one or more key cache slots for a uniacst key. The + * key itself is needed only to identify the cipher. For hardware + * TKIP with split cipher+MIC keys we allocate two key cache slot + * pairs so that we can setup separate TX and RX MIC keys. Note + * that the MIC key for a TKIP key at slot i is assumed by the + * hardware to be at slot i+64. This limits TKIP keys to the first + * 64 entries. + */ +int +ath_key_alloc(struct ieee80211vap *vap, struct ieee80211_key *k, + ieee80211_keyix *keyix, ieee80211_keyix *rxkeyix) +{ + struct ath_softc *sc = vap->iv_ic->ic_ifp->if_softc; + + /* + * Group key allocation must be handled specially for + * parts that do not support multicast key cache search + * functionality. For those parts the key id must match + * the h/w key index so lookups find the right key. On + * parts w/ the key search facility we install the sender's + * mac address (with the high bit set) and let the hardware + * find the key w/o using the key id. This is preferred as + * it permits us to support multiple users for adhoc and/or + * multi-station operation. + */ + if (k->wk_keyix != IEEE80211_KEYIX_NONE) { + /* + * Only global keys should have key index assigned. + */ + if (!(&vap->iv_nw_keys[0] <= k && + k < &vap->iv_nw_keys[IEEE80211_WEP_NKID])) { + /* should not happen */ + DPRINTF(sc, ATH_DEBUG_KEYCACHE, + "%s: bogus group key\n", __func__); + return 0; + } + if (vap->iv_opmode != IEEE80211_M_HOSTAP || + !(k->wk_flags & IEEE80211_KEY_GROUP) || + !sc->sc_mcastkey) { + /* + * XXX we pre-allocate the global keys so + * have no way to check if they've already + * been allocated. + */ + *keyix = *rxkeyix = k - vap->iv_nw_keys; + return 1; + } + /* + * Group key and device supports multicast key search. + */ + k->wk_keyix = IEEE80211_KEYIX_NONE; + } + + /* + * We allocate two pair for TKIP when using the h/w to do + * the MIC. For everything else, including software crypto, + * we allocate a single entry. Note that s/w crypto requires + * a pass-through slot on the 5211 and 5212. The 5210 does + * not support pass-through cache entries and we map all + * those requests to slot 0. + */ + if (k->wk_flags & IEEE80211_KEY_SWCRYPT) { + return key_alloc_single(sc, keyix, rxkeyix); + } else if (k->wk_cipher->ic_cipher == IEEE80211_CIPHER_TKIP && + (k->wk_flags & IEEE80211_KEY_SWMIC) == 0) { + if (sc->sc_splitmic) + return key_alloc_2pair(sc, keyix, rxkeyix); + else + return key_alloc_pair(sc, keyix, rxkeyix); + } else { + return key_alloc_single(sc, keyix, rxkeyix); + } +} + +/* + * Delete an entry in the key cache allocated by ath_key_alloc. + */ +int +ath_key_delete(struct ieee80211vap *vap, const struct ieee80211_key *k) +{ + struct ath_softc *sc = vap->iv_ic->ic_ifp->if_softc; + struct ath_hal *ah = sc->sc_ah; + const struct ieee80211_cipher *cip = k->wk_cipher; + u_int keyix = k->wk_keyix; + + DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s: delete key %u\n", __func__, keyix); + + ath_hal_keyreset(ah, keyix); + /* + * Handle split tx/rx keying required for TKIP with h/w MIC. + */ + if (cip->ic_cipher == IEEE80211_CIPHER_TKIP && + (k->wk_flags & IEEE80211_KEY_SWMIC) == 0 && sc->sc_splitmic) + ath_hal_keyreset(ah, keyix+32); /* RX key */ + if (keyix >= IEEE80211_WEP_NKID) { + /* + * Don't touch keymap entries for global keys so + * they are never considered for dynamic allocation. + */ + clrbit(sc->sc_keymap, keyix); + if (cip->ic_cipher == IEEE80211_CIPHER_TKIP && + (k->wk_flags & IEEE80211_KEY_SWMIC) == 0) { + clrbit(sc->sc_keymap, keyix+64); /* TX key MIC */ + if (sc->sc_splitmic) { + /* +32 for RX key, +32+64 for RX key MIC */ + clrbit(sc->sc_keymap, keyix+32); + clrbit(sc->sc_keymap, keyix+32+64); + } + } + } + return 1; +} + +/* + * Set the key cache contents for the specified key. Key cache + * slot(s) must already have been allocated by ath_key_alloc. + */ +int +ath_key_set(struct ieee80211vap *vap, const struct ieee80211_key *k, + const u_int8_t mac[IEEE80211_ADDR_LEN]) +{ + struct ath_softc *sc = vap->iv_ic->ic_ifp->if_softc; + + return ath_keyset(sc, k, vap->iv_bss); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_ath_keycache.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_ath_keycache.h new file mode 100644 index 0000000000..f1696cbd92 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_ath_keycache.h @@ -0,0 +1,43 @@ +/*- + * Copyright (c) 2011 Sam Leffler, Errno Consulting + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. + * + * $FreeBSD$ + */ + +#ifndef __IF_ATH_CRYPTO_H__ +#define __IF_ATH_CRYPTO_H__ + +extern int ath_key_alloc(struct ieee80211vap *, struct ieee80211_key *, + ieee80211_keyix *, ieee80211_keyix *); +extern int ath_key_delete(struct ieee80211vap *, const struct ieee80211_key *); +extern int ath_key_set(struct ieee80211vap *, const struct ieee80211_key *, + const u_int8_t mac[IEEE80211_ADDR_LEN]); +extern int ath_keyset(struct ath_softc *sc, const struct ieee80211_key *k, + struct ieee80211_node *bss); + +#endif diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_ath_misc.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_ath_misc.h new file mode 100644 index 0000000000..35feea212e --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_ath_misc.h @@ -0,0 +1,58 @@ +/*- + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. + * + * $FreeBSD$ + */ +#ifndef __IF_ATH_MISC_H__ +#define __IF_ATH_MISC_H__ + +/* + * This is where definitions for "public things" in if_ath.c + * will go for the time being. + * + * Anything in here should eventually be moved out of if_ath.c + * and into something else. + */ + +/* unaligned little endian access */ +#define LE_READ_2(p) \ + ((u_int16_t) \ + ((((u_int8_t *)(p))[0] ) | (((u_int8_t *)(p))[1] << 8))) +#define LE_READ_4(p) \ + ((u_int32_t) \ + ((((u_int8_t *)(p))[0] ) | (((u_int8_t *)(p))[1] << 8) | \ + (((u_int8_t *)(p))[2] << 16) | (((u_int8_t *)(p))[3] << 24))) + +extern int ath_tx_findrix(const struct ath_softc *sc, uint8_t rate); + +extern struct ath_buf * ath_getbuf(struct ath_softc *sc); +extern struct ath_buf * _ath_getbuf_locked(struct ath_softc *sc); + +extern int ath_reset(struct ifnet *); + +#endif diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_ath_pci.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_ath_pci.c index 44d398db1b..c9b7eecbc1 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_ath_pci.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_ath_pci.c @@ -250,6 +250,7 @@ static driver_t ath_pci_driver = { sizeof (struct ath_pci_softc) }; static devclass_t ath_devclass; -DRIVER_MODULE(ath, pci, ath_pci_driver, ath_devclass, 0, 0); -MODULE_VERSION(ath, 1); -MODULE_DEPEND(ath, wlan, 1, 1, 1); /* 802.11 media layer */ +DRIVER_MODULE(ath_pci, pci, ath_pci_driver, ath_devclass, 0, 0); +MODULE_VERSION(ath_pci, 1); +MODULE_DEPEND(ath_pci, wlan, 1, 1, 1); /* 802.11 media layer */ +MODULE_DEPEND(ath_pci, if_ath, 1, 1, 1); /* if_ath driver */ diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_ath_sysctl.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_ath_sysctl.c new file mode 100644 index 0000000000..ea6f949bdb --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_ath_sysctl.c @@ -0,0 +1,775 @@ +/*- + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. + */ + +#include +__FBSDID("$FreeBSD$"); + +/* + * Driver for the Atheros Wireless LAN controller. + * + * This software is derived from work of Atsushi Onoe; his contribution + * is greatly appreciated. + */ + +#include "opt_inet.h" +#include "opt_ath.h" +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#ifdef IEEE80211_SUPPORT_SUPERG +#include +#endif +#ifdef IEEE80211_SUPPORT_TDMA +#include +#endif + +#include + +#ifdef INET +#include +#include +#endif + +#include +#include /* XXX for softled */ +#include + +#include +#include +#include +#include + +#ifdef ATH_TX99_DIAG +#include +#endif + +static int +ath_sysctl_slottime(SYSCTL_HANDLER_ARGS) +{ + struct ath_softc *sc = arg1; + u_int slottime = ath_hal_getslottime(sc->sc_ah); + int error; + + error = sysctl_handle_int(oidp, &slottime, 0, req); + if (error || !req->newptr) + return error; + return !ath_hal_setslottime(sc->sc_ah, slottime) ? EINVAL : 0; +} + +static int +ath_sysctl_acktimeout(SYSCTL_HANDLER_ARGS) +{ + struct ath_softc *sc = arg1; + u_int acktimeout = ath_hal_getacktimeout(sc->sc_ah); + int error; + + error = sysctl_handle_int(oidp, &acktimeout, 0, req); + if (error || !req->newptr) + return error; + return !ath_hal_setacktimeout(sc->sc_ah, acktimeout) ? EINVAL : 0; +} + +static int +ath_sysctl_ctstimeout(SYSCTL_HANDLER_ARGS) +{ + struct ath_softc *sc = arg1; + u_int ctstimeout = ath_hal_getctstimeout(sc->sc_ah); + int error; + + error = sysctl_handle_int(oidp, &ctstimeout, 0, req); + if (error || !req->newptr) + return error; + return !ath_hal_setctstimeout(sc->sc_ah, ctstimeout) ? EINVAL : 0; +} + +static int +ath_sysctl_softled(SYSCTL_HANDLER_ARGS) +{ + struct ath_softc *sc = arg1; + int softled = sc->sc_softled; + int error; + + error = sysctl_handle_int(oidp, &softled, 0, req); + if (error || !req->newptr) + return error; + softled = (softled != 0); + if (softled != sc->sc_softled) { + if (softled) { + /* NB: handle any sc_ledpin change */ + ath_hal_gpioCfgOutput(sc->sc_ah, sc->sc_ledpin, + HAL_GPIO_MUX_MAC_NETWORK_LED); + ath_hal_gpioset(sc->sc_ah, sc->sc_ledpin, + !sc->sc_ledon); + } + sc->sc_softled = softled; + } + return 0; +} + +static int +ath_sysctl_ledpin(SYSCTL_HANDLER_ARGS) +{ + struct ath_softc *sc = arg1; + int ledpin = sc->sc_ledpin; + int error; + + error = sysctl_handle_int(oidp, &ledpin, 0, req); + if (error || !req->newptr) + return error; + if (ledpin != sc->sc_ledpin) { + sc->sc_ledpin = ledpin; + if (sc->sc_softled) { + ath_hal_gpioCfgOutput(sc->sc_ah, sc->sc_ledpin, + HAL_GPIO_MUX_MAC_NETWORK_LED); + ath_hal_gpioset(sc->sc_ah, sc->sc_ledpin, + !sc->sc_ledon); + } + } + return 0; +} + +static int +ath_sysctl_txantenna(SYSCTL_HANDLER_ARGS) +{ + struct ath_softc *sc = arg1; + u_int txantenna = ath_hal_getantennaswitch(sc->sc_ah); + int error; + + error = sysctl_handle_int(oidp, &txantenna, 0, req); + if (!error && req->newptr) { + /* XXX assumes 2 antenna ports */ + if (txantenna < HAL_ANT_VARIABLE || txantenna > HAL_ANT_FIXED_B) + return EINVAL; + ath_hal_setantennaswitch(sc->sc_ah, txantenna); + /* + * NB: with the switch locked this isn't meaningful, + * but set it anyway so things like radiotap get + * consistent info in their data. + */ + sc->sc_txantenna = txantenna; + } + return error; +} + +static int +ath_sysctl_rxantenna(SYSCTL_HANDLER_ARGS) +{ + struct ath_softc *sc = arg1; + u_int defantenna = ath_hal_getdefantenna(sc->sc_ah); + int error; + + error = sysctl_handle_int(oidp, &defantenna, 0, req); + if (!error && req->newptr) + ath_hal_setdefantenna(sc->sc_ah, defantenna); + return error; +} + +static int +ath_sysctl_diversity(SYSCTL_HANDLER_ARGS) +{ + struct ath_softc *sc = arg1; + u_int diversity = ath_hal_getdiversity(sc->sc_ah); + int error; + + error = sysctl_handle_int(oidp, &diversity, 0, req); + if (error || !req->newptr) + return error; + if (!ath_hal_setdiversity(sc->sc_ah, diversity)) + return EINVAL; + sc->sc_diversity = diversity; + return 0; +} + +static int +ath_sysctl_diag(SYSCTL_HANDLER_ARGS) +{ + struct ath_softc *sc = arg1; + u_int32_t diag; + int error; + + if (!ath_hal_getdiag(sc->sc_ah, &diag)) + return EINVAL; + error = sysctl_handle_int(oidp, &diag, 0, req); + if (error || !req->newptr) + return error; + return !ath_hal_setdiag(sc->sc_ah, diag) ? EINVAL : 0; +} + +static int +ath_sysctl_tpscale(SYSCTL_HANDLER_ARGS) +{ + struct ath_softc *sc = arg1; + struct ifnet *ifp = sc->sc_ifp; + u_int32_t scale; + int error; + + (void) ath_hal_gettpscale(sc->sc_ah, &scale); + error = sysctl_handle_int(oidp, &scale, 0, req); + if (error || !req->newptr) + return error; + return !ath_hal_settpscale(sc->sc_ah, scale) ? EINVAL : + (ifp->if_drv_flags & IFF_DRV_RUNNING) ? ath_reset(ifp) : 0; +} + +static int +ath_sysctl_tpc(SYSCTL_HANDLER_ARGS) +{ + struct ath_softc *sc = arg1; + u_int tpc = ath_hal_gettpc(sc->sc_ah); + int error; + + error = sysctl_handle_int(oidp, &tpc, 0, req); + if (error || !req->newptr) + return error; + return !ath_hal_settpc(sc->sc_ah, tpc) ? EINVAL : 0; +} + +static int +ath_sysctl_rfkill(SYSCTL_HANDLER_ARGS) +{ + struct ath_softc *sc = arg1; + struct ifnet *ifp = sc->sc_ifp; + struct ath_hal *ah = sc->sc_ah; + u_int rfkill = ath_hal_getrfkill(ah); + int error; + + error = sysctl_handle_int(oidp, &rfkill, 0, req); + if (error || !req->newptr) + return error; + if (rfkill == ath_hal_getrfkill(ah)) /* unchanged */ + return 0; + if (!ath_hal_setrfkill(ah, rfkill)) + return EINVAL; + return (ifp->if_drv_flags & IFF_DRV_RUNNING) ? ath_reset(ifp) : 0; +} + +static int +ath_sysctl_rfsilent(SYSCTL_HANDLER_ARGS) +{ + struct ath_softc *sc = arg1; + u_int rfsilent; + int error; + + (void) ath_hal_getrfsilent(sc->sc_ah, &rfsilent); + error = sysctl_handle_int(oidp, &rfsilent, 0, req); + if (error || !req->newptr) + return error; + if (!ath_hal_setrfsilent(sc->sc_ah, rfsilent)) + return EINVAL; + sc->sc_rfsilentpin = rfsilent & 0x1c; + sc->sc_rfsilentpol = (rfsilent & 0x2) != 0; + return 0; +} + +static int +ath_sysctl_tpack(SYSCTL_HANDLER_ARGS) +{ + struct ath_softc *sc = arg1; + u_int32_t tpack; + int error; + + (void) ath_hal_gettpack(sc->sc_ah, &tpack); + error = sysctl_handle_int(oidp, &tpack, 0, req); + if (error || !req->newptr) + return error; + return !ath_hal_settpack(sc->sc_ah, tpack) ? EINVAL : 0; +} + +static int +ath_sysctl_tpcts(SYSCTL_HANDLER_ARGS) +{ + struct ath_softc *sc = arg1; + u_int32_t tpcts; + int error; + + (void) ath_hal_gettpcts(sc->sc_ah, &tpcts); + error = sysctl_handle_int(oidp, &tpcts, 0, req); + if (error || !req->newptr) + return error; + return !ath_hal_settpcts(sc->sc_ah, tpcts) ? EINVAL : 0; +} + +static int +ath_sysctl_intmit(SYSCTL_HANDLER_ARGS) +{ + struct ath_softc *sc = arg1; + int intmit, error; + + intmit = ath_hal_getintmit(sc->sc_ah); + error = sysctl_handle_int(oidp, &intmit, 0, req); + if (error || !req->newptr) + return error; + + /* reusing error; 1 here means "good"; 0 means "fail" */ + error = ath_hal_setintmit(sc->sc_ah, intmit); + if (! error) + return EINVAL; + + /* + * Reset the hardware here - disabling ANI in the HAL + * doesn't reset ANI related registers, so it'll leave + * things in an inconsistent state. + */ + if (sc->sc_ifp->if_drv_flags & IFF_DRV_RUNNING) + ath_reset(sc->sc_ifp); + + return 0; +} + +#ifdef IEEE80211_SUPPORT_TDMA +static int +ath_sysctl_setcca(SYSCTL_HANDLER_ARGS) +{ + struct ath_softc *sc = arg1; + int setcca, error; + + setcca = sc->sc_setcca; + error = sysctl_handle_int(oidp, &setcca, 0, req); + if (error || !req->newptr) + return error; + sc->sc_setcca = (setcca != 0); + return 0; +} +#endif /* IEEE80211_SUPPORT_TDMA */ + +void +ath_sysctlattach(struct ath_softc *sc) +{ + struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->sc_dev); + struct sysctl_oid *tree = device_get_sysctl_tree(sc->sc_dev); + struct ath_hal *ah = sc->sc_ah; + + SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "countrycode", CTLFLAG_RD, &sc->sc_eecc, 0, + "EEPROM country code"); + SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "regdomain", CTLFLAG_RD, &sc->sc_eerd, 0, + "EEPROM regdomain code"); +#ifdef ATH_DEBUG + SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "debug", CTLFLAG_RW, &sc->sc_debug, 0, + "control debugging printfs"); +#endif + SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "slottime", CTLTYPE_INT | CTLFLAG_RW, sc, 0, + ath_sysctl_slottime, "I", "802.11 slot time (us)"); + SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "acktimeout", CTLTYPE_INT | CTLFLAG_RW, sc, 0, + ath_sysctl_acktimeout, "I", "802.11 ACK timeout (us)"); + SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "ctstimeout", CTLTYPE_INT | CTLFLAG_RW, sc, 0, + ath_sysctl_ctstimeout, "I", "802.11 CTS timeout (us)"); + SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "softled", CTLTYPE_INT | CTLFLAG_RW, sc, 0, + ath_sysctl_softled, "I", "enable/disable software LED support"); + SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "ledpin", CTLTYPE_INT | CTLFLAG_RW, sc, 0, + ath_sysctl_ledpin, "I", "GPIO pin connected to LED"); + SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "ledon", CTLFLAG_RW, &sc->sc_ledon, 0, + "setting to turn LED on"); + SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "ledidle", CTLFLAG_RW, &sc->sc_ledidle, 0, + "idle time for inactivity LED (ticks)"); + SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "txantenna", CTLTYPE_INT | CTLFLAG_RW, sc, 0, + ath_sysctl_txantenna, "I", "antenna switch"); + SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "rxantenna", CTLTYPE_INT | CTLFLAG_RW, sc, 0, + ath_sysctl_rxantenna, "I", "default/rx antenna"); + if (ath_hal_hasdiversity(ah)) + SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "diversity", CTLTYPE_INT | CTLFLAG_RW, sc, 0, + ath_sysctl_diversity, "I", "antenna diversity"); + sc->sc_txintrperiod = ATH_TXINTR_PERIOD; + SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "txintrperiod", CTLFLAG_RW, &sc->sc_txintrperiod, 0, + "tx descriptor batching"); + SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "diag", CTLTYPE_INT | CTLFLAG_RW, sc, 0, + ath_sysctl_diag, "I", "h/w diagnostic control"); + SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "tpscale", CTLTYPE_INT | CTLFLAG_RW, sc, 0, + ath_sysctl_tpscale, "I", "tx power scaling"); + if (ath_hal_hastpc(ah)) { + SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "tpc", CTLTYPE_INT | CTLFLAG_RW, sc, 0, + ath_sysctl_tpc, "I", "enable/disable per-packet TPC"); + SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "tpack", CTLTYPE_INT | CTLFLAG_RW, sc, 0, + ath_sysctl_tpack, "I", "tx power for ack frames"); + SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "tpcts", CTLTYPE_INT | CTLFLAG_RW, sc, 0, + ath_sysctl_tpcts, "I", "tx power for cts frames"); + } + if (ath_hal_hasrfsilent(ah)) { + SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "rfsilent", CTLTYPE_INT | CTLFLAG_RW, sc, 0, + ath_sysctl_rfsilent, "I", "h/w RF silent config"); + SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "rfkill", CTLTYPE_INT | CTLFLAG_RW, sc, 0, + ath_sysctl_rfkill, "I", "enable/disable RF kill switch"); + } + if (ath_hal_hasintmit(ah)) { + SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "intmit", CTLTYPE_INT | CTLFLAG_RW, sc, 0, + ath_sysctl_intmit, "I", "interference mitigation"); + } + sc->sc_monpass = HAL_RXERR_DECRYPT | HAL_RXERR_MIC; + SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "monpass", CTLFLAG_RW, &sc->sc_monpass, 0, + "mask of error frames to pass when monitoring"); +#ifdef IEEE80211_SUPPORT_TDMA + if (ath_hal_macversion(ah) > 0x78) { + sc->sc_tdmadbaprep = 2; + SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "dbaprep", CTLFLAG_RW, &sc->sc_tdmadbaprep, 0, + "TDMA DBA preparation time"); + sc->sc_tdmaswbaprep = 10; + SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "swbaprep", CTLFLAG_RW, &sc->sc_tdmaswbaprep, 0, + "TDMA SWBA preparation time"); + SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "guardtime", CTLFLAG_RW, &sc->sc_tdmaguard, 0, + "TDMA slot guard time"); + SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "superframe", CTLFLAG_RD, &sc->sc_tdmabintval, 0, + "TDMA calculated super frame"); + SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "setcca", CTLTYPE_INT | CTLFLAG_RW, sc, 0, + ath_sysctl_setcca, "I", "enable CCA control"); + } +#endif +} + +static int +ath_sysctl_clearstats(SYSCTL_HANDLER_ARGS) +{ + struct ath_softc *sc = arg1; + int val = 0; + int error; + + error = sysctl_handle_int(oidp, &val, 0, req); + if (error || !req->newptr) + return error; + if (val == 0) + return 0; /* Not clearing the stats is still valid */ + memset(&sc->sc_stats, 0, sizeof(sc->sc_stats)); + val = 0; + return 0; +} + +static void +ath_sysctl_stats_attach_rxphyerr(struct ath_softc *sc, struct sysctl_oid_list *parent) +{ + struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->sc_dev); + struct sysctl_oid *tree = device_get_sysctl_tree(sc->sc_dev); + struct sysctl_oid_list *child = SYSCTL_CHILDREN(tree); + int i; + char sn[8]; + + tree = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, "rx_phy_err", CTLFLAG_RD, NULL, "Per-code RX PHY Errors"); + child = SYSCTL_CHILDREN(tree); + for (i = 0; i < 64; i++) { + snprintf(sn, sizeof(sn), "%d", i); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, sn, CTLFLAG_RD, &sc->sc_stats.ast_rx_phy[i], 0, ""); + } +} + +void +ath_sysctl_stats_attach(struct ath_softc *sc) +{ + struct sysctl_oid *tree = device_get_sysctl_tree(sc->sc_dev); + struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->sc_dev); + struct sysctl_oid_list *child = SYSCTL_CHILDREN(tree); + + /* Create "clear" node */ + SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "clear_stats", CTLTYPE_INT | CTLFLAG_RW, sc, 0, + ath_sysctl_clearstats, "I", "clear stats"); + + /* Create stats node */ + tree = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "stats", CTLFLAG_RD, + NULL, "Statistics"); + child = SYSCTL_CHILDREN(tree); + + /* This was generated from if_athioctl.h */ + + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_watchdog", CTLFLAG_RD, + &sc->sc_stats.ast_watchdog, 0, "device reset by watchdog"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_hardware", CTLFLAG_RD, + &sc->sc_stats.ast_hardware, 0, "fatal hardware error interrupts"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_bmiss", CTLFLAG_RD, + &sc->sc_stats.ast_bmiss, 0, "beacon miss interrupts"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_bmiss_phantom", CTLFLAG_RD, + &sc->sc_stats.ast_bmiss_phantom, 0, "beacon miss interrupts"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_bstuck", CTLFLAG_RD, + &sc->sc_stats.ast_bstuck, 0, "beacon stuck interrupts"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rxorn", CTLFLAG_RD, + &sc->sc_stats.ast_rxorn, 0, "rx overrun interrupts"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rxeol", CTLFLAG_RD, + &sc->sc_stats.ast_rxeol, 0, "rx eol interrupts"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_txurn", CTLFLAG_RD, + &sc->sc_stats.ast_txurn, 0, "tx underrun interrupts"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_mib", CTLFLAG_RD, + &sc->sc_stats.ast_mib, 0, "mib interrupts"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_intrcoal", CTLFLAG_RD, + &sc->sc_stats.ast_intrcoal, 0, "interrupts coalesced"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_packets", CTLFLAG_RD, + &sc->sc_stats.ast_tx_packets, 0, "packet sent on the interface"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_mgmt", CTLFLAG_RD, + &sc->sc_stats.ast_tx_mgmt, 0, "management frames transmitted"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_discard", CTLFLAG_RD, + &sc->sc_stats.ast_tx_discard, 0, "frames discarded prior to assoc"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_qstop", CTLFLAG_RD, + &sc->sc_stats.ast_tx_qstop, 0, "output stopped 'cuz no buffer"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_encap", CTLFLAG_RD, + &sc->sc_stats.ast_tx_encap, 0, "tx encapsulation failed"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_nonode", CTLFLAG_RD, + &sc->sc_stats.ast_tx_nonode, 0, "tx failed 'cuz no node"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_nombuf", CTLFLAG_RD, + &sc->sc_stats.ast_tx_nombuf, 0, "tx failed 'cuz no mbuf"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_nomcl", CTLFLAG_RD, + &sc->sc_stats.ast_tx_nomcl, 0, "tx failed 'cuz no cluster"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_linear", CTLFLAG_RD, + &sc->sc_stats.ast_tx_linear, 0, "tx linearized to cluster"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_nodata", CTLFLAG_RD, + &sc->sc_stats.ast_tx_nodata, 0, "tx discarded empty frame"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_busdma", CTLFLAG_RD, + &sc->sc_stats.ast_tx_busdma, 0, "tx failed for dma resrcs"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_xretries", CTLFLAG_RD, + &sc->sc_stats.ast_tx_xretries, 0, "tx failed 'cuz too many retries"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_fifoerr", CTLFLAG_RD, + &sc->sc_stats.ast_tx_fifoerr, 0, "tx failed 'cuz FIFO underrun"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_filtered", CTLFLAG_RD, + &sc->sc_stats.ast_tx_filtered, 0, "tx failed 'cuz xmit filtered"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_shortretry", CTLFLAG_RD, + &sc->sc_stats.ast_tx_shortretry, 0, "tx on-chip retries (short)"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_longretry", CTLFLAG_RD, + &sc->sc_stats.ast_tx_longretry, 0, "tx on-chip retries (long)"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_badrate", CTLFLAG_RD, + &sc->sc_stats.ast_tx_badrate, 0, "tx failed 'cuz bogus xmit rate"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_noack", CTLFLAG_RD, + &sc->sc_stats.ast_tx_noack, 0, "tx frames with no ack marked"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_rts", CTLFLAG_RD, + &sc->sc_stats.ast_tx_rts, 0, "tx frames with rts enabled"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_cts", CTLFLAG_RD, + &sc->sc_stats.ast_tx_cts, 0, "tx frames with cts enabled"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_shortpre", CTLFLAG_RD, + &sc->sc_stats.ast_tx_shortpre, 0, "tx frames with short preamble"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_altrate", CTLFLAG_RD, + &sc->sc_stats.ast_tx_altrate, 0, "tx frames with alternate rate"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_protect", CTLFLAG_RD, + &sc->sc_stats.ast_tx_protect, 0, "tx frames with protection"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_ctsburst", CTLFLAG_RD, + &sc->sc_stats.ast_tx_ctsburst, 0, "tx frames with cts and bursting"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_ctsext", CTLFLAG_RD, + &sc->sc_stats.ast_tx_ctsext, 0, "tx frames with cts extension"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_nombuf", CTLFLAG_RD, + &sc->sc_stats.ast_rx_nombuf, 0, "rx setup failed 'cuz no mbuf"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_busdma", CTLFLAG_RD, + &sc->sc_stats.ast_rx_busdma, 0, "rx setup failed for dma resrcs"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_orn", CTLFLAG_RD, + &sc->sc_stats.ast_rx_orn, 0, "rx failed 'cuz of desc overrun"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_crcerr", CTLFLAG_RD, + &sc->sc_stats.ast_rx_crcerr, 0, "rx failed 'cuz of bad CRC"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_fifoerr", CTLFLAG_RD, + &sc->sc_stats.ast_rx_fifoerr, 0, "rx failed 'cuz of FIFO overrun"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_badcrypt", CTLFLAG_RD, + &sc->sc_stats.ast_rx_badcrypt, 0, "rx failed 'cuz decryption"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_badmic", CTLFLAG_RD, + &sc->sc_stats.ast_rx_badmic, 0, "rx failed 'cuz MIC failure"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_phyerr", CTLFLAG_RD, + &sc->sc_stats.ast_rx_phyerr, 0, "rx failed 'cuz of PHY err"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_tooshort", CTLFLAG_RD, + &sc->sc_stats.ast_rx_tooshort, 0, "rx discarded 'cuz frame too short"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_toobig", CTLFLAG_RD, + &sc->sc_stats.ast_rx_toobig, 0, "rx discarded 'cuz frame too large"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_packets", CTLFLAG_RD, + &sc->sc_stats.ast_rx_packets, 0, "packet recv on the interface"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_mgt", CTLFLAG_RD, + &sc->sc_stats.ast_rx_mgt, 0, "management frames received"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_ctl", CTLFLAG_RD, + &sc->sc_stats.ast_rx_ctl, 0, "rx discarded 'cuz ctl frame"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_be_xmit", CTLFLAG_RD, + &sc->sc_stats.ast_be_xmit, 0, "beacons transmitted"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_be_nombuf", CTLFLAG_RD, + &sc->sc_stats.ast_be_nombuf, 0, "beacon setup failed 'cuz no mbuf"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_per_cal", CTLFLAG_RD, + &sc->sc_stats.ast_per_cal, 0, "periodic calibration calls"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_per_calfail", CTLFLAG_RD, + &sc->sc_stats.ast_per_calfail, 0, "periodic calibration failed"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_per_rfgain", CTLFLAG_RD, + &sc->sc_stats.ast_per_rfgain, 0, "periodic calibration rfgain reset"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rate_calls", CTLFLAG_RD, + &sc->sc_stats.ast_rate_calls, 0, "rate control checks"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rate_raise", CTLFLAG_RD, + &sc->sc_stats.ast_rate_raise, 0, "rate control raised xmit rate"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rate_drop", CTLFLAG_RD, + &sc->sc_stats.ast_rate_drop, 0, "rate control dropped xmit rate"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_ant_defswitch", CTLFLAG_RD, + &sc->sc_stats.ast_ant_defswitch, 0, "rx/default antenna switches"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_ant_txswitch", CTLFLAG_RD, + &sc->sc_stats.ast_ant_txswitch, 0, "tx antenna switches"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_cabq_xmit", CTLFLAG_RD, + &sc->sc_stats.ast_cabq_xmit, 0, "cabq frames transmitted"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_cabq_busy", CTLFLAG_RD, + &sc->sc_stats.ast_cabq_busy, 0, "cabq found busy"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_raw", CTLFLAG_RD, + &sc->sc_stats.ast_tx_raw, 0, "tx frames through raw api"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_ff_txok", CTLFLAG_RD, + &sc->sc_stats.ast_ff_txok, 0, "fast frames tx'd successfully"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_ff_txerr", CTLFLAG_RD, + &sc->sc_stats.ast_ff_txerr, 0, "fast frames tx'd w/ error"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_ff_rx", CTLFLAG_RD, + &sc->sc_stats.ast_ff_rx, 0, "fast frames rx'd"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_ff_flush", CTLFLAG_RD, + &sc->sc_stats.ast_ff_flush, 0, "fast frames flushed from staging q"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_qfull", CTLFLAG_RD, + &sc->sc_stats.ast_tx_qfull, 0, "tx dropped 'cuz of queue limit"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_nobuf", CTLFLAG_RD, + &sc->sc_stats.ast_tx_nobuf, 0, "tx dropped 'cuz no ath buffer"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tdma_update", CTLFLAG_RD, + &sc->sc_stats.ast_tdma_update, 0, "TDMA slot timing updates"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tdma_timers", CTLFLAG_RD, + &sc->sc_stats.ast_tdma_timers, 0, "TDMA slot update set beacon timers"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tdma_tsf", CTLFLAG_RD, + &sc->sc_stats.ast_tdma_tsf, 0, "TDMA slot update set TSF"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tdma_ack", CTLFLAG_RD, + &sc->sc_stats.ast_tdma_ack, 0, "TDMA tx failed 'cuz ACK required"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_raw_fail", CTLFLAG_RD, + &sc->sc_stats.ast_tx_raw_fail, 0, "raw tx failed 'cuz h/w down"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_nofrag", CTLFLAG_RD, + &sc->sc_stats.ast_tx_nofrag, 0, "tx dropped 'cuz no ath frag buffer"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_be_missed", CTLFLAG_RD, + &sc->sc_stats.ast_be_missed, 0, "number of -missed- beacons"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_ani_cal", CTLFLAG_RD, + &sc->sc_stats.ast_ani_cal, 0, "number of ANI polls"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_agg", CTLFLAG_RD, + &sc->sc_stats.ast_rx_agg, 0, "number of aggregate frames received"); + + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_halfgi", CTLFLAG_RD, + &sc->sc_stats.ast_rx_halfgi, 0, "number of frames received with half-GI"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_2040", CTLFLAG_RD, + &sc->sc_stats.ast_rx_2040, 0, "number of HT/40 frames received"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_pre_crc_err", CTLFLAG_RD, + &sc->sc_stats.ast_rx_pre_crc_err, 0, "number of delimeter-CRC errors detected"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_post_crc_err", CTLFLAG_RD, + &sc->sc_stats.ast_rx_post_crc_err, 0, "number of post-delimiter CRC errors detected"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_decrypt_busy_err", CTLFLAG_RD, + &sc->sc_stats.ast_rx_decrypt_busy_err, 0, "number of frames received w/ busy decrypt engine"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_hi_rx_chain", CTLFLAG_RD, + &sc->sc_stats.ast_rx_hi_rx_chain, 0, ""); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_htprotect", CTLFLAG_RD, + &sc->sc_stats.ast_tx_htprotect, 0, "HT tx frames with protection"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_hitqueueend", CTLFLAG_RD, + &sc->sc_stats.ast_rx_hitqueueend, 0, "RX hit queue end"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_timeout", CTLFLAG_RD, + &sc->sc_stats.ast_tx_timeout, 0, "TX Global Timeout"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_cst", CTLFLAG_RD, + &sc->sc_stats.ast_tx_cst, 0, "TX Carrier Sense Timeout"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_xtxop", CTLFLAG_RD, + &sc->sc_stats.ast_tx_xtxop, 0, "TX exceeded TXOP"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_timerexpired", CTLFLAG_RD, + &sc->sc_stats.ast_tx_timerexpired, 0, "TX exceeded TX_TIMER register"); + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_desccfgerr", CTLFLAG_RD, + &sc->sc_stats.ast_tx_desccfgerr, 0, "TX Descriptor Cfg Error"); + + /* Attach the RX phy error array */ + ath_sysctl_stats_attach_rxphyerr(sc, child); +} + +/* + * This doesn't necessarily belong here (because it's HAL related, not + * driver related). + */ +void +ath_sysctl_hal_attach(struct ath_softc *sc) +{ + struct sysctl_oid *tree = device_get_sysctl_tree(sc->sc_dev); + struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->sc_dev); + struct sysctl_oid_list *child = SYSCTL_CHILDREN(tree); + + tree = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "hal", CTLFLAG_RD, + NULL, "Atheros HAL parameters"); + child = SYSCTL_CHILDREN(tree); + + sc->sc_ah->ah_config.ah_debug = 0; + SYSCTL_ADD_INT(ctx, child, OID_AUTO, "debug", CTLFLAG_RW, + &sc->sc_ah->ah_config.ah_debug, 0, "Atheros HAL debugging printfs"); + + sc->sc_ah->ah_config.ah_ar5416_biasadj = 0; + SYSCTL_ADD_INT(ctx, child, OID_AUTO, "ar5416_biasadj", CTLFLAG_RW, + &sc->sc_ah->ah_config.ah_ar5416_biasadj, 0, + "Enable 2ghz AR5416 direction sensitivity bias adjust"); + + sc->sc_ah->ah_config.ah_dma_beacon_response_time = 2; + SYSCTL_ADD_INT(ctx, child, OID_AUTO, "dma_brt", CTLFLAG_RW, + &sc->sc_ah->ah_config.ah_dma_beacon_response_time, 0, + "Atheros HAL DMA beacon response time"); + + sc->sc_ah->ah_config.ah_sw_beacon_response_time = 10; + SYSCTL_ADD_INT(ctx, child, OID_AUTO, "sw_brt", CTLFLAG_RW, + &sc->sc_ah->ah_config.ah_sw_beacon_response_time, 0, + "Atheros HAL software beacon response time"); + + sc->sc_ah->ah_config.ah_additional_swba_backoff = 0; + SYSCTL_ADD_INT(ctx, child, OID_AUTO, "swba_backoff", CTLFLAG_RW, + &sc->sc_ah->ah_config.ah_additional_swba_backoff, 0, + "Atheros HAL additional SWBA backoff time"); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_ath_sysctl.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_ath_sysctl.h new file mode 100644 index 0000000000..1fef2be224 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_ath_sysctl.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2011 Adrian Chadd, Xenion Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. + * + * $FreeBSD$ + */ + +#ifndef __IF_ATH_SYSCTL_H__ +#define __IF_ATH_SYSCTL_H__ + +extern void ath_sysctlattach(struct ath_softc *); +extern void ath_sysctl_stats_attach(struct ath_softc *sc); +extern void ath_sysctl_hal_attach(struct ath_softc *sc); +#endif diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_ath_tx.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_ath_tx.c new file mode 100644 index 0000000000..f4cee6d1de --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_ath_tx.c @@ -0,0 +1,1124 @@ +/*- + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. + */ + +#include +__FBSDID("$FreeBSD$"); + +/* + * Driver for the Atheros Wireless LAN controller. + * + * This software is derived from work of Atsushi Onoe; his contribution + * is greatly appreciated. + */ + +#include "opt_inet.h" +#include "opt_ath.h" +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#ifdef IEEE80211_SUPPORT_SUPERG +#include +#endif +#ifdef IEEE80211_SUPPORT_TDMA +#include +#endif + +#include + +#ifdef INET +#include +#include +#endif + +#include +#include /* XXX for softled */ +#include + +#include + +#ifdef ATH_TX99_DIAG +#include +#endif + +#include +#include +#include + +/* + * Whether to use the 11n rate scenario functions or not + */ +static inline int +ath_tx_is_11n(struct ath_softc *sc) +{ + return (sc->sc_ah->ah_magic == 0x20065416); +} + +void +ath_txfrag_cleanup(struct ath_softc *sc, + ath_bufhead *frags, struct ieee80211_node *ni) +{ + struct ath_buf *bf, *next; + + ATH_TXBUF_LOCK_ASSERT(sc); + + STAILQ_FOREACH_SAFE(bf, frags, bf_list, next) { + /* NB: bf assumed clean */ + STAILQ_REMOVE_HEAD(frags, bf_list); + STAILQ_INSERT_HEAD(&sc->sc_txbuf, bf, bf_list); + ieee80211_node_decref(ni); + } +} + +/* + * Setup xmit of a fragmented frame. Allocate a buffer + * for each frag and bump the node reference count to + * reflect the held reference to be setup by ath_tx_start. + */ +int +ath_txfrag_setup(struct ath_softc *sc, ath_bufhead *frags, + struct mbuf *m0, struct ieee80211_node *ni) +{ + struct mbuf *m; + struct ath_buf *bf; + + ATH_TXBUF_LOCK(sc); + for (m = m0->m_nextpkt; m != NULL; m = m->m_nextpkt) { + bf = _ath_getbuf_locked(sc); + if (bf == NULL) { /* out of buffers, cleanup */ + ath_txfrag_cleanup(sc, frags, ni); + break; + } + ieee80211_node_incref(ni); + STAILQ_INSERT_TAIL(frags, bf, bf_list); + } + ATH_TXBUF_UNLOCK(sc); + + return !STAILQ_EMPTY(frags); +} + +/* + * Reclaim mbuf resources. For fragmented frames we + * need to claim each frag chained with m_nextpkt. + */ +void +ath_freetx(struct mbuf *m) +{ + struct mbuf *next; + + do { + next = m->m_nextpkt; + m->m_nextpkt = NULL; + m_freem(m); + } while ((m = next) != NULL); +} + +static int +ath_tx_dmasetup(struct ath_softc *sc, struct ath_buf *bf, struct mbuf *m0) +{ + struct mbuf *m; + int error; + + /* + * Load the DMA map so any coalescing is done. This + * also calculates the number of descriptors we need. + */ + error = bus_dmamap_load_mbuf_sg(sc->sc_dmat, bf->bf_dmamap, m0, + bf->bf_segs, &bf->bf_nseg, + BUS_DMA_NOWAIT); + if (error == EFBIG) { + /* XXX packet requires too many descriptors */ + bf->bf_nseg = ATH_TXDESC+1; + } else if (error != 0) { + sc->sc_stats.ast_tx_busdma++; + ath_freetx(m0); + return error; + } + /* + * Discard null packets and check for packets that + * require too many TX descriptors. We try to convert + * the latter to a cluster. + */ + if (bf->bf_nseg > ATH_TXDESC) { /* too many desc's, linearize */ + sc->sc_stats.ast_tx_linear++; + m = m_collapse(m0, M_DONTWAIT, ATH_TXDESC); + if (m == NULL) { + ath_freetx(m0); + sc->sc_stats.ast_tx_nombuf++; + return ENOMEM; + } + m0 = m; + error = bus_dmamap_load_mbuf_sg(sc->sc_dmat, bf->bf_dmamap, m0, + bf->bf_segs, &bf->bf_nseg, + BUS_DMA_NOWAIT); + if (error != 0) { + sc->sc_stats.ast_tx_busdma++; + ath_freetx(m0); + return error; + } + KASSERT(bf->bf_nseg <= ATH_TXDESC, + ("too many segments after defrag; nseg %u", bf->bf_nseg)); + } else if (bf->bf_nseg == 0) { /* null packet, discard */ + sc->sc_stats.ast_tx_nodata++; + ath_freetx(m0); + return EIO; + } + DPRINTF(sc, ATH_DEBUG_XMIT, "%s: m %p len %u\n", + __func__, m0, m0->m_pkthdr.len); + bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap, BUS_DMASYNC_PREWRITE); + bf->bf_m = m0; + + return 0; +} + +static void +ath_tx_chaindesclist(struct ath_softc *sc, struct ath_txq *txq, struct ath_buf *bf) +{ + struct ath_hal *ah = sc->sc_ah; + struct ath_desc *ds, *ds0; + int i; + + /* + * Fillin the remainder of the descriptor info. + */ + ds0 = ds = bf->bf_desc; + for (i = 0; i < bf->bf_nseg; i++, ds++) { + ds->ds_data = bf->bf_segs[i].ds_addr; + if (i == bf->bf_nseg - 1) + ds->ds_link = 0; + else + ds->ds_link = bf->bf_daddr + sizeof(*ds) * (i + 1); + ath_hal_filltxdesc(ah, ds + , bf->bf_segs[i].ds_len /* segment length */ + , i == 0 /* first segment */ + , i == bf->bf_nseg - 1 /* last segment */ + , ds0 /* first descriptor */ + ); + DPRINTF(sc, ATH_DEBUG_XMIT, + "%s: %d: %08x %08x %08x %08x %08x %08x\n", + __func__, i, ds->ds_link, ds->ds_data, + ds->ds_ctl0, ds->ds_ctl1, ds->ds_hw[0], ds->ds_hw[1]); + } + +} + +static void +ath_tx_handoff(struct ath_softc *sc, struct ath_txq *txq, struct ath_buf *bf) +{ + struct ath_hal *ah = sc->sc_ah; + + /* Fill in the details in the descriptor list */ + ath_tx_chaindesclist(sc, txq, bf); + + /* + * Insert the frame on the outbound list and pass it on + * to the hardware. Multicast frames buffered for power + * save stations and transmit from the CAB queue are stored + * on a s/w only queue and loaded on to the CAB queue in + * the SWBA handler since frames only go out on DTIM and + * to avoid possible races. + */ + ATH_TXQ_LOCK(txq); + KASSERT((bf->bf_flags & ATH_BUF_BUSY) == 0, + ("busy status 0x%x", bf->bf_flags)); + if (txq->axq_qnum != ATH_TXQ_SWQ) { +#ifdef IEEE80211_SUPPORT_TDMA + int qbusy; + + ATH_TXQ_INSERT_TAIL(txq, bf, bf_list); + qbusy = ath_hal_txqenabled(ah, txq->axq_qnum); + if (txq->axq_link == NULL) { + /* + * Be careful writing the address to TXDP. If + * the tx q is enabled then this write will be + * ignored. Normally this is not an issue but + * when tdma is in use and the q is beacon gated + * this race can occur. If the q is busy then + * defer the work to later--either when another + * packet comes along or when we prepare a beacon + * frame at SWBA. + */ + if (!qbusy) { + ath_hal_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr); + txq->axq_flags &= ~ATH_TXQ_PUTPENDING; + DPRINTF(sc, ATH_DEBUG_XMIT, + "%s: TXDP[%u] = %p (%p) depth %d\n", + __func__, txq->axq_qnum, + (caddr_t)bf->bf_daddr, bf->bf_desc, + txq->axq_depth); + } else { + txq->axq_flags |= ATH_TXQ_PUTPENDING; + DPRINTF(sc, ATH_DEBUG_TDMA | ATH_DEBUG_XMIT, + "%s: Q%u busy, defer enable\n", __func__, + txq->axq_qnum); + } + } else { + *txq->axq_link = bf->bf_daddr; + DPRINTF(sc, ATH_DEBUG_XMIT, + "%s: link[%u](%p)=%p (%p) depth %d\n", __func__, + txq->axq_qnum, txq->axq_link, + (caddr_t)bf->bf_daddr, bf->bf_desc, txq->axq_depth); + if ((txq->axq_flags & ATH_TXQ_PUTPENDING) && !qbusy) { + /* + * The q was busy when we previously tried + * to write the address of the first buffer + * in the chain. Since it's not busy now + * handle this chore. We are certain the + * buffer at the front is the right one since + * axq_link is NULL only when the buffer list + * is/was empty. + */ + ath_hal_puttxbuf(ah, txq->axq_qnum, + STAILQ_FIRST(&txq->axq_q)->bf_daddr); + txq->axq_flags &= ~ATH_TXQ_PUTPENDING; + DPRINTF(sc, ATH_DEBUG_TDMA | ATH_DEBUG_XMIT, + "%s: Q%u restarted\n", __func__, + txq->axq_qnum); + } + } +#else + ATH_TXQ_INSERT_TAIL(txq, bf, bf_list); + if (txq->axq_link == NULL) { + ath_hal_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr); + DPRINTF(sc, ATH_DEBUG_XMIT, + "%s: TXDP[%u] = %p (%p) depth %d\n", + __func__, txq->axq_qnum, + (caddr_t)bf->bf_daddr, bf->bf_desc, + txq->axq_depth); + } else { + *txq->axq_link = bf->bf_daddr; + DPRINTF(sc, ATH_DEBUG_XMIT, + "%s: link[%u](%p)=%p (%p) depth %d\n", __func__, + txq->axq_qnum, txq->axq_link, + (caddr_t)bf->bf_daddr, bf->bf_desc, txq->axq_depth); + } +#endif /* IEEE80211_SUPPORT_TDMA */ + txq->axq_link = &bf->bf_desc[bf->bf_nseg - 1].ds_link; + ath_hal_txstart(ah, txq->axq_qnum); + } else { + if (txq->axq_link != NULL) { + struct ath_buf *last = ATH_TXQ_LAST(txq); + struct ieee80211_frame *wh; + + /* mark previous frame */ + wh = mtod(last->bf_m, struct ieee80211_frame *); + wh->i_fc[1] |= IEEE80211_FC1_MORE_DATA; + bus_dmamap_sync(sc->sc_dmat, last->bf_dmamap, + BUS_DMASYNC_PREWRITE); + + /* link descriptor */ + *txq->axq_link = bf->bf_daddr; + } + ATH_TXQ_INSERT_TAIL(txq, bf, bf_list); + txq->axq_link = &bf->bf_desc[bf->bf_nseg - 1].ds_link; + } + ATH_TXQ_UNLOCK(txq); +} + +static int +ath_tx_tag_crypto(struct ath_softc *sc, struct ieee80211_node *ni, + struct mbuf *m0, int iswep, int isfrag, int *hdrlen, int *pktlen, int *keyix) +{ + if (iswep) { + const struct ieee80211_cipher *cip; + struct ieee80211_key *k; + + /* + * Construct the 802.11 header+trailer for an encrypted + * frame. The only reason this can fail is because of an + * unknown or unsupported cipher/key type. + */ + k = ieee80211_crypto_encap(ni, m0); + if (k == NULL) { + /* + * This can happen when the key is yanked after the + * frame was queued. Just discard the frame; the + * 802.11 layer counts failures and provides + * debugging/diagnostics. + */ + return 0; + } + /* + * Adjust the packet + header lengths for the crypto + * additions and calculate the h/w key index. When + * a s/w mic is done the frame will have had any mic + * added to it prior to entry so m0->m_pkthdr.len will + * account for it. Otherwise we need to add it to the + * packet length. + */ + cip = k->wk_cipher; + (*hdrlen) += cip->ic_header; + (*pktlen) += cip->ic_header + cip->ic_trailer; + /* NB: frags always have any TKIP MIC done in s/w */ + if ((k->wk_flags & IEEE80211_KEY_SWMIC) == 0 && !isfrag) + (*pktlen) += cip->ic_miclen; + (*keyix) = k->wk_keyix; + } else if (ni->ni_ucastkey.wk_cipher == &ieee80211_cipher_none) { + /* + * Use station key cache slot, if assigned. + */ + (*keyix) = ni->ni_ucastkey.wk_keyix; + if ((*keyix) == IEEE80211_KEYIX_NONE) + (*keyix) = HAL_TXKEYIX_INVALID; + } else + (*keyix) = HAL_TXKEYIX_INVALID; + + return 1; +} + +static uint8_t +ath_tx_get_rtscts_rate(struct ath_hal *ah, const HAL_RATE_TABLE *rt, + int rix, int cix, int shortPreamble) +{ + uint8_t ctsrate; + + /* + * CTS transmit rate is derived from the transmit rate + * by looking in the h/w rate table. We must also factor + * in whether or not a short preamble is to be used. + */ + /* NB: cix is set above where RTS/CTS is enabled */ + KASSERT(cix != 0xff, ("cix not setup")); + ctsrate = rt->info[cix].rateCode; + + /* XXX this should only matter for legacy rates */ + if (shortPreamble) + ctsrate |= rt->info[cix].shortPreamble; + + return ctsrate; +} + + +/* + * Calculate the RTS/CTS duration for legacy frames. + */ +static int +ath_tx_calc_ctsduration(struct ath_hal *ah, int rix, int cix, + int shortPreamble, int pktlen, const HAL_RATE_TABLE *rt, + int flags) +{ + int ctsduration = 0; + + /* This mustn't be called for HT modes */ + if (rt->info[cix].phy == IEEE80211_T_HT) { + printf("%s: HT rate where it shouldn't be (0x%x)\n", + __func__, rt->info[cix].rateCode); + return -1; + } + + /* + * Compute the transmit duration based on the frame + * size and the size of an ACK frame. We call into the + * HAL to do the computation since it depends on the + * characteristics of the actual PHY being used. + * + * NB: CTS is assumed the same size as an ACK so we can + * use the precalculated ACK durations. + */ + if (shortPreamble) { + if (flags & HAL_TXDESC_RTSENA) /* SIFS + CTS */ + ctsduration += rt->info[cix].spAckDuration; + ctsduration += ath_hal_computetxtime(ah, + rt, pktlen, rix, AH_TRUE); + if ((flags & HAL_TXDESC_NOACK) == 0) /* SIFS + ACK */ + ctsduration += rt->info[rix].spAckDuration; + } else { + if (flags & HAL_TXDESC_RTSENA) /* SIFS + CTS */ + ctsduration += rt->info[cix].lpAckDuration; + ctsduration += ath_hal_computetxtime(ah, + rt, pktlen, rix, AH_FALSE); + if ((flags & HAL_TXDESC_NOACK) == 0) /* SIFS + ACK */ + ctsduration += rt->info[rix].lpAckDuration; + } + + return ctsduration; +} + +int +ath_tx_start(struct ath_softc *sc, struct ieee80211_node *ni, struct ath_buf *bf, + struct mbuf *m0) +{ + struct ieee80211vap *vap = ni->ni_vap; + struct ath_vap *avp = ATH_VAP(vap); + struct ath_hal *ah = sc->sc_ah; + struct ifnet *ifp = sc->sc_ifp; + struct ieee80211com *ic = ifp->if_l2com; + const struct chanAccParams *cap = &ic->ic_wme.wme_chanParams; + int error, iswep, ismcast, isfrag, ismrr; + int keyix, hdrlen, pktlen, try0; + u_int8_t rix, txrate, ctsrate; + u_int8_t cix = 0xff; /* NB: silence compiler */ + struct ath_desc *ds; + struct ath_txq *txq; + struct ieee80211_frame *wh; + u_int subtype, flags, ctsduration; + HAL_PKT_TYPE atype; + const HAL_RATE_TABLE *rt; + HAL_BOOL shortPreamble; + struct ath_node *an; + u_int pri; + uint8_t try[4], rate[4]; + + bzero(try, sizeof(try)); + bzero(rate, sizeof(rate)); + + wh = mtod(m0, struct ieee80211_frame *); + iswep = wh->i_fc[1] & IEEE80211_FC1_WEP; + ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1); + isfrag = m0->m_flags & M_FRAG; + hdrlen = ieee80211_anyhdrsize(wh); + /* + * Packet length must not include any + * pad bytes; deduct them here. + */ + pktlen = m0->m_pkthdr.len - (hdrlen & 3); + + /* Handle encryption twiddling if needed */ + if (! ath_tx_tag_crypto(sc, ni, m0, iswep, isfrag, &hdrlen, &pktlen, &keyix)) { + ath_freetx(m0); + return EIO; + } + + /* packet header may have moved, reset our local pointer */ + wh = mtod(m0, struct ieee80211_frame *); + + pktlen += IEEE80211_CRC_LEN; + + /* + * Load the DMA map so any coalescing is done. This + * also calculates the number of descriptors we need. + */ + error = ath_tx_dmasetup(sc, bf, m0); + if (error != 0) + return error; + bf->bf_node = ni; /* NB: held reference */ + m0 = bf->bf_m; /* NB: may have changed */ + wh = mtod(m0, struct ieee80211_frame *); + + /* setup descriptors */ + ds = bf->bf_desc; + rt = sc->sc_currates; + KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode)); + + /* + * NB: the 802.11 layer marks whether or not we should + * use short preamble based on the current mode and + * negotiated parameters. + */ + if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) && + (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE)) { + shortPreamble = AH_TRUE; + sc->sc_stats.ast_tx_shortpre++; + } else { + shortPreamble = AH_FALSE; + } + + an = ATH_NODE(ni); + flags = HAL_TXDESC_CLRDMASK; /* XXX needed for crypto errs */ + ismrr = 0; /* default no multi-rate retry*/ + pri = M_WME_GETAC(m0); /* honor classification */ + /* XXX use txparams instead of fixed values */ + /* + * Calculate Atheros packet type from IEEE80211 packet header, + * setup for rate calculations, and select h/w transmit queue. + */ + switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) { + case IEEE80211_FC0_TYPE_MGT: + subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; + if (subtype == IEEE80211_FC0_SUBTYPE_BEACON) + atype = HAL_PKT_TYPE_BEACON; + else if (subtype == IEEE80211_FC0_SUBTYPE_PROBE_RESP) + atype = HAL_PKT_TYPE_PROBE_RESP; + else if (subtype == IEEE80211_FC0_SUBTYPE_ATIM) + atype = HAL_PKT_TYPE_ATIM; + else + atype = HAL_PKT_TYPE_NORMAL; /* XXX */ + rix = an->an_mgmtrix; + txrate = rt->info[rix].rateCode; + if (shortPreamble) + txrate |= rt->info[rix].shortPreamble; + try0 = ATH_TXMGTTRY; + flags |= HAL_TXDESC_INTREQ; /* force interrupt */ + break; + case IEEE80211_FC0_TYPE_CTL: + atype = HAL_PKT_TYPE_PSPOLL; /* stop setting of duration */ + rix = an->an_mgmtrix; + txrate = rt->info[rix].rateCode; + if (shortPreamble) + txrate |= rt->info[rix].shortPreamble; + try0 = ATH_TXMGTTRY; + flags |= HAL_TXDESC_INTREQ; /* force interrupt */ + break; + case IEEE80211_FC0_TYPE_DATA: + atype = HAL_PKT_TYPE_NORMAL; /* default */ + /* + * Data frames: multicast frames go out at a fixed rate, + * EAPOL frames use the mgmt frame rate; otherwise consult + * the rate control module for the rate to use. + */ + if (ismcast) { + rix = an->an_mcastrix; + txrate = rt->info[rix].rateCode; + if (shortPreamble) + txrate |= rt->info[rix].shortPreamble; + try0 = 1; + } else if (m0->m_flags & M_EAPOL) { + /* XXX? maybe always use long preamble? */ + rix = an->an_mgmtrix; + txrate = rt->info[rix].rateCode; + if (shortPreamble) + txrate |= rt->info[rix].shortPreamble; + try0 = ATH_TXMAXTRY; /* XXX?too many? */ + } else { + ath_rate_findrate(sc, an, shortPreamble, pktlen, + &rix, &try0, &txrate); + sc->sc_txrix = rix; /* for LED blinking */ + sc->sc_lastdatarix = rix; /* for fast frames */ + if (try0 != ATH_TXMAXTRY) + ismrr = 1; + } + if (cap->cap_wmeParams[pri].wmep_noackPolicy) + flags |= HAL_TXDESC_NOACK; + break; + default: + if_printf(ifp, "bogus frame type 0x%x (%s)\n", + wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK, __func__); + /* XXX statistic */ + ath_freetx(m0); + return EIO; + } + txq = sc->sc_ac2q[pri]; + + /* + * When servicing one or more stations in power-save mode + * (or) if there is some mcast data waiting on the mcast + * queue (to prevent out of order delivery) multicast + * frames must be buffered until after the beacon. + */ + if (ismcast && (vap->iv_ps_sta || avp->av_mcastq.axq_depth)) + txq = &avp->av_mcastq; + + /* + * Calculate miscellaneous flags. + */ + if (ismcast) { + flags |= HAL_TXDESC_NOACK; /* no ack on broad/multicast */ + } else if (pktlen > vap->iv_rtsthreshold && + (ni->ni_ath_flags & IEEE80211_NODE_FF) == 0) { + flags |= HAL_TXDESC_RTSENA; /* RTS based on frame length */ + cix = rt->info[rix].controlRate; + sc->sc_stats.ast_tx_rts++; + } + if (flags & HAL_TXDESC_NOACK) /* NB: avoid double counting */ + sc->sc_stats.ast_tx_noack++; +#ifdef IEEE80211_SUPPORT_TDMA + if (sc->sc_tdma && (flags & HAL_TXDESC_NOACK) == 0) { + DPRINTF(sc, ATH_DEBUG_TDMA, + "%s: discard frame, ACK required w/ TDMA\n", __func__); + sc->sc_stats.ast_tdma_ack++; + ath_freetx(m0); + return EIO; + } +#endif + + /* + * If 802.11g protection is enabled, determine whether + * to use RTS/CTS or just CTS. Note that this is only + * done for OFDM unicast frames. + */ + if ((ic->ic_flags & IEEE80211_F_USEPROT) && + rt->info[rix].phy == IEEE80211_T_OFDM && + (flags & HAL_TXDESC_NOACK) == 0) { + /* XXX fragments must use CCK rates w/ protection */ + if (ic->ic_protmode == IEEE80211_PROT_RTSCTS) + flags |= HAL_TXDESC_RTSENA; + else if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) + flags |= HAL_TXDESC_CTSENA; + if (isfrag) { + /* + * For frags it would be desirable to use the + * highest CCK rate for RTS/CTS. But stations + * farther away may detect it at a lower CCK rate + * so use the configured protection rate instead + * (for now). + */ + cix = rt->info[sc->sc_protrix].controlRate; + } else + cix = rt->info[sc->sc_protrix].controlRate; + sc->sc_stats.ast_tx_protect++; + } + +#if 0 + /* + * If 11n protection is enabled and it's a HT frame, + * enable RTS. + * + * XXX ic_htprotmode or ic_curhtprotmode? + * XXX should it_htprotmode only matter if ic_curhtprotmode + * XXX indicates it's not a HT pure environment? + */ + if ((ic->ic_htprotmode == IEEE80211_PROT_RTSCTS) && + rt->info[rix].phy == IEEE80211_T_HT && + (flags & HAL_TXDESC_NOACK) == 0) { + cix = rt->info[sc->sc_protrix].controlRate; + flags |= HAL_TXDESC_RTSENA; + sc->sc_stats.ast_tx_htprotect++; + } +#endif + + /* + * Calculate duration. This logically belongs in the 802.11 + * layer but it lacks sufficient information to calculate it. + */ + if ((flags & HAL_TXDESC_NOACK) == 0 && + (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_CTL) { + u_int16_t dur; + if (shortPreamble) + dur = rt->info[rix].spAckDuration; + else + dur = rt->info[rix].lpAckDuration; + if (wh->i_fc[1] & IEEE80211_FC1_MORE_FRAG) { + dur += dur; /* additional SIFS+ACK */ + KASSERT(m0->m_nextpkt != NULL, ("no fragment")); + /* + * Include the size of next fragment so NAV is + * updated properly. The last fragment uses only + * the ACK duration + */ + dur += ath_hal_computetxtime(ah, rt, + m0->m_nextpkt->m_pkthdr.len, + rix, shortPreamble); + } + if (isfrag) { + /* + * Force hardware to use computed duration for next + * fragment by disabling multi-rate retry which updates + * duration based on the multi-rate duration table. + */ + ismrr = 0; + try0 = ATH_TXMGTTRY; /* XXX? */ + } + *(u_int16_t *)wh->i_dur = htole16(dur); + } + + /* + * Calculate RTS/CTS rate and duration if needed. + */ + ctsduration = 0; + if (flags & (HAL_TXDESC_RTSENA|HAL_TXDESC_CTSENA)) { + ctsrate = ath_tx_get_rtscts_rate(ah, rt, rix, cix, shortPreamble); + + /* The 11n chipsets do ctsduration calculations for you */ + if (! ath_tx_is_11n(sc)) + ctsduration = ath_tx_calc_ctsduration(ah, rix, cix, shortPreamble, + pktlen, rt, flags); + /* + * Must disable multi-rate retry when using RTS/CTS. + */ + ismrr = 0; + try0 = ATH_TXMGTTRY; /* XXX */ + } else + ctsrate = 0; + + /* + * At this point we are committed to sending the frame + * and we don't need to look at m_nextpkt; clear it in + * case this frame is part of frag chain. + */ + m0->m_nextpkt = NULL; + + if (IFF_DUMPPKTS(sc, ATH_DEBUG_XMIT)) + ieee80211_dump_pkt(ic, mtod(m0, const uint8_t *), m0->m_len, + sc->sc_hwmap[rix].ieeerate, -1); + + if (ieee80211_radiotap_active_vap(vap)) { + u_int64_t tsf = ath_hal_gettsf64(ah); + + sc->sc_tx_th.wt_tsf = htole64(tsf); + sc->sc_tx_th.wt_flags = sc->sc_hwmap[rix].txflags; + if (iswep) + sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP; + if (isfrag) + sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_FRAG; + sc->sc_tx_th.wt_rate = sc->sc_hwmap[rix].ieeerate; + sc->sc_tx_th.wt_txpower = ni->ni_txpower; + sc->sc_tx_th.wt_antenna = sc->sc_txantenna; + + ieee80211_radiotap_tx(vap, m0); + } + + /* + * Determine if a tx interrupt should be generated for + * this descriptor. We take a tx interrupt to reap + * descriptors when the h/w hits an EOL condition or + * when the descriptor is specifically marked to generate + * an interrupt. We periodically mark descriptors in this + * way to insure timely replenishing of the supply needed + * for sending frames. Defering interrupts reduces system + * load and potentially allows more concurrent work to be + * done but if done to aggressively can cause senders to + * backup. + * + * NB: use >= to deal with sc_txintrperiod changing + * dynamically through sysctl. + */ + if (flags & HAL_TXDESC_INTREQ) { + txq->axq_intrcnt = 0; + } else if (++txq->axq_intrcnt >= sc->sc_txintrperiod) { + flags |= HAL_TXDESC_INTREQ; + txq->axq_intrcnt = 0; + } + + if (ath_tx_is_11n(sc)) { + rate[0] = rix; + try[0] = try0; + } + + /* + * Formulate first tx descriptor with tx controls. + */ + /* XXX check return value? */ + /* XXX is this ok to call for 11n descriptors? */ + /* XXX or should it go through the first, next, last 11n calls? */ + ath_hal_setuptxdesc(ah, ds + , pktlen /* packet length */ + , hdrlen /* header length */ + , atype /* Atheros packet type */ + , ni->ni_txpower /* txpower */ + , txrate, try0 /* series 0 rate/tries */ + , keyix /* key cache index */ + , sc->sc_txantenna /* antenna mode */ + , flags /* flags */ + , ctsrate /* rts/cts rate */ + , ctsduration /* rts/cts duration */ + ); + bf->bf_txflags = flags; + /* + * Setup the multi-rate retry state only when we're + * going to use it. This assumes ath_hal_setuptxdesc + * initializes the descriptors (so we don't have to) + * when the hardware supports multi-rate retry and + * we don't use it. + */ + if (ismrr) { + if (ath_tx_is_11n(sc)) + ath_rate_getxtxrates(sc, an, rix, rate, try); + else + ath_rate_setupxtxdesc(sc, an, ds, shortPreamble, rix); + } + + if (ath_tx_is_11n(sc)) { + ath_buf_set_rate(sc, ni, bf, pktlen, flags, ctsrate, (atype == HAL_PKT_TYPE_PSPOLL), rate, try); + } + + ath_tx_handoff(sc, txq, bf); + return 0; +} + +static int +ath_tx_raw_start(struct ath_softc *sc, struct ieee80211_node *ni, + struct ath_buf *bf, struct mbuf *m0, + const struct ieee80211_bpf_params *params) +{ + struct ifnet *ifp = sc->sc_ifp; + struct ieee80211com *ic = ifp->if_l2com; + struct ath_hal *ah = sc->sc_ah; + struct ieee80211vap *vap = ni->ni_vap; + int error, ismcast, ismrr; + int keyix, hdrlen, pktlen, try0, txantenna; + u_int8_t rix, cix, txrate, ctsrate, rate1, rate2, rate3; + struct ieee80211_frame *wh; + u_int flags, ctsduration; + HAL_PKT_TYPE atype; + const HAL_RATE_TABLE *rt; + struct ath_desc *ds; + u_int pri; + uint8_t try[4], rate[4]; + + bzero(try, sizeof(try)); + bzero(rate, sizeof(rate)); + + wh = mtod(m0, struct ieee80211_frame *); + ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1); + hdrlen = ieee80211_anyhdrsize(wh); + /* + * Packet length must not include any + * pad bytes; deduct them here. + */ + /* XXX honor IEEE80211_BPF_DATAPAD */ + pktlen = m0->m_pkthdr.len - (hdrlen & 3) + IEEE80211_CRC_LEN; + + /* Handle encryption twiddling if needed */ + if (! ath_tx_tag_crypto(sc, ni, m0, params->ibp_flags & IEEE80211_BPF_CRYPTO, 0, &hdrlen, &pktlen, &keyix)) { + ath_freetx(m0); + return EIO; + } + /* packet header may have moved, reset our local pointer */ + wh = mtod(m0, struct ieee80211_frame *); + + error = ath_tx_dmasetup(sc, bf, m0); + if (error != 0) + return error; + m0 = bf->bf_m; /* NB: may have changed */ + wh = mtod(m0, struct ieee80211_frame *); + bf->bf_node = ni; /* NB: held reference */ + + flags = HAL_TXDESC_CLRDMASK; /* XXX needed for crypto errs */ + flags |= HAL_TXDESC_INTREQ; /* force interrupt */ + if (params->ibp_flags & IEEE80211_BPF_RTS) + flags |= HAL_TXDESC_RTSENA; + else if (params->ibp_flags & IEEE80211_BPF_CTS) + flags |= HAL_TXDESC_CTSENA; + /* XXX leave ismcast to injector? */ + if ((params->ibp_flags & IEEE80211_BPF_NOACK) || ismcast) + flags |= HAL_TXDESC_NOACK; + + rt = sc->sc_currates; + KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode)); + rix = ath_tx_findrix(sc, params->ibp_rate0); + txrate = rt->info[rix].rateCode; + if (params->ibp_flags & IEEE80211_BPF_SHORTPRE) + txrate |= rt->info[rix].shortPreamble; + sc->sc_txrix = rix; + try0 = params->ibp_try0; + ismrr = (params->ibp_try1 != 0); + txantenna = params->ibp_pri >> 2; + if (txantenna == 0) /* XXX? */ + txantenna = sc->sc_txantenna; + + ctsduration = 0; + if (flags & (HAL_TXDESC_RTSENA|HAL_TXDESC_CTSENA)) { + cix = ath_tx_findrix(sc, params->ibp_ctsrate); + ctsrate = ath_tx_get_rtscts_rate(ah, rt, rix, cix, params->ibp_flags & IEEE80211_BPF_SHORTPRE); + /* The 11n chipsets do ctsduration calculations for you */ + if (! ath_tx_is_11n(sc)) + ctsduration = ath_tx_calc_ctsduration(ah, rix, cix, + params->ibp_flags & IEEE80211_BPF_SHORTPRE, pktlen, + rt, flags); + /* + * Must disable multi-rate retry when using RTS/CTS. + */ + ismrr = 0; /* XXX */ + } else + ctsrate = 0; + + pri = params->ibp_pri & 3; + /* + * NB: we mark all packets as type PSPOLL so the h/w won't + * set the sequence number, duration, etc. + */ + atype = HAL_PKT_TYPE_PSPOLL; + + if (IFF_DUMPPKTS(sc, ATH_DEBUG_XMIT)) + ieee80211_dump_pkt(ic, mtod(m0, caddr_t), m0->m_len, + sc->sc_hwmap[rix].ieeerate, -1); + + if (ieee80211_radiotap_active_vap(vap)) { + u_int64_t tsf = ath_hal_gettsf64(ah); + + sc->sc_tx_th.wt_tsf = htole64(tsf); + sc->sc_tx_th.wt_flags = sc->sc_hwmap[rix].txflags; + if (wh->i_fc[1] & IEEE80211_FC1_WEP) + sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP; + if (m0->m_flags & M_FRAG) + sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_FRAG; + sc->sc_tx_th.wt_rate = sc->sc_hwmap[rix].ieeerate; + sc->sc_tx_th.wt_txpower = ni->ni_txpower; + sc->sc_tx_th.wt_antenna = sc->sc_txantenna; + + ieee80211_radiotap_tx(vap, m0); + } + + /* + * Formulate first tx descriptor with tx controls. + */ + ds = bf->bf_desc; + /* XXX check return value? */ + ath_hal_setuptxdesc(ah, ds + , pktlen /* packet length */ + , hdrlen /* header length */ + , atype /* Atheros packet type */ + , params->ibp_power /* txpower */ + , txrate, try0 /* series 0 rate/tries */ + , keyix /* key cache index */ + , txantenna /* antenna mode */ + , flags /* flags */ + , ctsrate /* rts/cts rate */ + , ctsduration /* rts/cts duration */ + ); + bf->bf_txflags = flags; + + if (ath_tx_is_11n(sc)) { + rate[0] = ath_tx_findrix(sc, params->ibp_rate0); + try[0] = params->ibp_try0; + + if (ismrr) { + /* Remember, rate[] is actually an array of rix's -adrian */ + rate[0] = ath_tx_findrix(sc, params->ibp_rate0); + rate[1] = ath_tx_findrix(sc, params->ibp_rate1); + rate[2] = ath_tx_findrix(sc, params->ibp_rate2); + rate[3] = ath_tx_findrix(sc, params->ibp_rate3); + + try[0] = params->ibp_try0; + try[1] = params->ibp_try1; + try[2] = params->ibp_try2; + try[3] = params->ibp_try3; + } + } else { + if (ismrr) { + rix = ath_tx_findrix(sc, params->ibp_rate1); + rate1 = rt->info[rix].rateCode; + if (params->ibp_flags & IEEE80211_BPF_SHORTPRE) + rate1 |= rt->info[rix].shortPreamble; + if (params->ibp_try2) { + rix = ath_tx_findrix(sc, params->ibp_rate2); + rate2 = rt->info[rix].rateCode; + if (params->ibp_flags & IEEE80211_BPF_SHORTPRE) + rate2 |= rt->info[rix].shortPreamble; + } else + rate2 = 0; + if (params->ibp_try3) { + rix = ath_tx_findrix(sc, params->ibp_rate3); + rate3 = rt->info[rix].rateCode; + if (params->ibp_flags & IEEE80211_BPF_SHORTPRE) + rate3 |= rt->info[rix].shortPreamble; + } else + rate3 = 0; + ath_hal_setupxtxdesc(ah, ds + , rate1, params->ibp_try1 /* series 1 */ + , rate2, params->ibp_try2 /* series 2 */ + , rate3, params->ibp_try3 /* series 3 */ + ); + } + } + + if (ath_tx_is_11n(sc)) { + /* + * notice that rix doesn't include any of the "magic" flags txrate + * does for communicating "other stuff" to the HAL. + */ + ath_buf_set_rate(sc, ni, bf, pktlen, flags, ctsrate, (atype == HAL_PKT_TYPE_PSPOLL), rate, try); + } + + /* NB: no buffered multicast in power save support */ + ath_tx_handoff(sc, sc->sc_ac2q[pri], bf); + return 0; +} + +int +ath_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, + const struct ieee80211_bpf_params *params) +{ + struct ieee80211com *ic = ni->ni_ic; + struct ifnet *ifp = ic->ic_ifp; + struct ath_softc *sc = ifp->if_softc; + struct ath_buf *bf; + int error; + + if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || sc->sc_invalid) { + DPRINTF(sc, ATH_DEBUG_XMIT, "%s: discard frame, %s", __func__, + (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ? + "!running" : "invalid"); + m_freem(m); + error = ENETDOWN; + goto bad; + } + /* + * Grab a TX buffer and associated resources. + */ + bf = ath_getbuf(sc); + if (bf == NULL) { + sc->sc_stats.ast_tx_nobuf++; + m_freem(m); + error = ENOBUFS; + goto bad; + } + + if (params == NULL) { + /* + * Legacy path; interpret frame contents to decide + * precisely how to send the frame. + */ + if (ath_tx_start(sc, ni, bf, m)) { + error = EIO; /* XXX */ + goto bad2; + } + } else { + /* + * Caller supplied explicit parameters to use in + * sending the frame. + */ + if (ath_tx_raw_start(sc, ni, bf, m, params)) { + error = EIO; /* XXX */ + goto bad2; + } + } + sc->sc_wd_timer = 5; + ifp->if_opackets++; + sc->sc_stats.ast_tx_raw++; + + return 0; +bad2: + ATH_TXBUF_LOCK(sc); + STAILQ_INSERT_HEAD(&sc->sc_txbuf, bf, bf_list); + ATH_TXBUF_UNLOCK(sc); +bad: + ifp->if_oerrors++; + sc->sc_stats.ast_tx_raw_fail++; + ieee80211_free_node(ni); + return error; +} diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_ath_tx.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_ath_tx.h new file mode 100644 index 0000000000..e181f7a48d --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_ath_tx.h @@ -0,0 +1,44 @@ +/*- + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. + * + * $FreeBSD$ + */ +#ifndef __IF_ATH_TX_H__ +#define __IF_ATH_TX_H__ + +extern void ath_freetx(struct mbuf *m); +extern void ath_txfrag_cleanup(struct ath_softc *sc, ath_bufhead *frags, + struct ieee80211_node *ni); +extern int ath_txfrag_setup(struct ath_softc *sc, ath_bufhead *frags, + struct mbuf *m0, struct ieee80211_node *ni); +extern int ath_tx_start(struct ath_softc *sc, struct ieee80211_node *ni, + struct ath_buf *bf, struct mbuf *m0); +extern int ath_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, + const struct ieee80211_bpf_params *params); + +#endif diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_ath_tx_ht.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_ath_tx_ht.c new file mode 100644 index 0000000000..348a1499bb --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_ath_tx_ht.c @@ -0,0 +1,243 @@ +/*- + * Copyright (c) 2011 Adrian Chadd, Xenion Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include "opt_inet.h" +#include "opt_ath.h" +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#ifdef IEEE80211_SUPPORT_SUPERG +#include +#endif +#ifdef IEEE80211_SUPPORT_TDMA +#include +#endif + +#include + +#ifdef INET +#include +#include +#endif + +#include +#include /* XXX for softled */ +#include + +#ifdef ATH_TX99_DIAG +#include +#endif + +#include + +/* + * Setup a 11n rate series structure + * + * This should be called for both legacy and MCS rates. + */ +static void +ath_rateseries_setup(struct ath_softc *sc, struct ieee80211_node *ni, + HAL_11N_RATE_SERIES *series, unsigned int pktlen, uint8_t *rix, + uint8_t *try, int flags) +{ +#define HT_RC_2_STREAMS(_rc) ((((_rc) & 0x78) >> 3) + 1) + struct ieee80211com *ic = ni->ni_ic; + struct ath_hal *ah = sc->sc_ah; + HAL_BOOL shortPreamble = AH_FALSE; + const HAL_RATE_TABLE *rt = sc->sc_currates; + int i; + + if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) && + (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE)) + shortPreamble = AH_TRUE; + + memset(series, 0, sizeof(HAL_11N_RATE_SERIES) * 4); + for (i = 0; i < 4; i++) { + /* Only set flags for actual TX attempts */ + if (try[i] == 0) + continue; + + series[i].Tries = try[i]; + + /* + * XXX this isn't strictly correct - sc_txchainmask + * XXX isn't the currently active chainmask; + * XXX it's the interface chainmask at startup. + * XXX It's overridden in the HAL rate scenario function + * XXX for now. + */ + series[i].ChSel = sc->sc_txchainmask; + + if (flags & (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA)) + series[i].RateFlags |= HAL_RATESERIES_RTS_CTS; + + /* + * Transmit 40MHz frames only if the node has negotiated + * it rather than whether the node is capable of it or not. + * It's subtly different in the hostap case. + */ + if (ni->ni_chw == 40) + series[i].RateFlags |= HAL_RATESERIES_2040; + + /* + * Set short-GI only if the node has advertised it + * the channel width is suitable, and we support it. + * We don't currently have a "negotiated" set of bits - + * ni_htcap is what the remote end sends, not what this + * node is capable of. + */ + if (ni->ni_chw == 40 && + ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI40 && + ni->ni_htcap & IEEE80211_HTCAP_SHORTGI40) + series[i].RateFlags |= HAL_RATESERIES_HALFGI; + + if (ni->ni_chw == 20 && + ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI20 && + ni->ni_htcap & IEEE80211_HTCAP_SHORTGI20) + series[i].RateFlags |= HAL_RATESERIES_HALFGI; + + series[i].Rate = rt->info[rix[i]].rateCode; + + /* PktDuration doesn't include slot, ACK, RTS, etc timing - it's just the packet duration */ + if (series[i].Rate & IEEE80211_RATE_MCS) { + series[i].PktDuration = + ath_computedur_ht(pktlen + , series[i].Rate + , HT_RC_2_STREAMS(series[i].Rate) + , series[i].RateFlags & HAL_RATESERIES_2040 + , series[i].RateFlags & HAL_RATESERIES_HALFGI); + } else { + if (shortPreamble) + series[i].Rate |= rt->info[rix[i]].shortPreamble; + series[i].PktDuration = ath_hal_computetxtime(ah, + rt, pktlen, rix[i], shortPreamble); + } + } +#undef HT_RC_2_STREAMS +} + +#if 0 +static void +ath_rateseries_print(HAL_11N_RATE_SERIES *series) +{ + int i; + for (i = 0; i < 4; i++) { + printf("series %d: rate %x; tries %d; pktDuration %d; chSel %d; rateFlags %x\n", + i, + series[i].Rate, + series[i].Tries, + series[i].PktDuration, + series[i].ChSel, + series[i].RateFlags); + } +} +#endif + +/* + * Setup the 11n rate scenario and burst duration for the given TX descriptor + * list. + * + * This isn't useful for sending beacon frames, which has different needs + * wrt what's passed into the rate scenario function. + */ + +void +ath_buf_set_rate(struct ath_softc *sc, struct ieee80211_node *ni, struct ath_buf *bf, + int pktlen, int flags, uint8_t ctsrate, int is_pspoll, uint8_t *rix, uint8_t *try) +{ + HAL_11N_RATE_SERIES series[4]; + struct ath_desc *ds = bf->bf_desc; + struct ath_desc *lastds = NULL; + struct ath_hal *ah = sc->sc_ah; + + /* Setup rate scenario */ + memset(&series, 0, sizeof(series)); + + ath_rateseries_setup(sc, ni, series, pktlen, rix, try, flags); + + /* Enforce AR5416 aggregate limit - can't do RTS w/ an agg frame > 8k */ + + /* Enforce RTS and CTS are mutually exclusive */ + + /* Get a pointer to the last tx descriptor in the list */ + lastds = &bf->bf_desc[bf->bf_nseg - 1]; + +#if 0 + printf("pktlen: %d; flags 0x%x\n", pktlen, flags); + ath_rateseries_print(series); +#endif + + /* Set rate scenario */ + ath_hal_set11nratescenario(ah, ds, + !is_pspoll, /* whether to override the duration or not */ + /* don't allow hardware to override the duration on ps-poll packets */ + ctsrate, /* rts/cts rate */ + series, /* 11n rate series */ + 4, /* number of series */ + flags); + + /* Setup the last descriptor in the chain */ + ath_hal_setuplasttxdesc(ah, lastds, ds); + + /* Set burst duration */ + /* This should only be done if aggregate protection is enabled */ + //ath_hal_set11nburstduration(ah, ds, 8192); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_ath_tx_ht.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_ath_tx_ht.h new file mode 100644 index 0000000000..cf16c46d81 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_ath_tx_ht.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2011 Adrian Chadd, Xenion Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. + * + * $FreeBSD$ + */ +#ifndef __IF_ATH_TX_HT_H__ +#define __IF_ATH_TX_HT_H__ + +extern void ath_buf_set_rate(struct ath_softc *sc, + struct ieee80211_node *ni, struct ath_buf *bf, + int pktlen, int flags, uint8_t ctsrate, int is_pspoll, + uint8_t *rix, uint8_t *try); + +#endif diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_athdfs.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_athdfs.h new file mode 100644 index 0000000000..a3f27f90e9 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_athdfs.h @@ -0,0 +1,48 @@ +/*- + * Copyright (c) 2011 Adrian Chadd, Xenion Pty Ltd + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. + * + * $FreeBSD$ + */ +#ifndef __IF_ATHDFS_H__ +#define __IF_ATHDFS_H__ + +extern int ath_dfs_attach(struct ath_softc *sc); +extern int ath_dfs_detach(struct ath_softc *sc); +extern void ath_dfs_radar_enable(struct ath_softc *, + struct ieee80211_channel *chan); +extern void ath_dfs_process_phy_err(struct ath_softc *sc, const char *buf, + uint64_t tsf, struct ath_rx_status *rxstat); +extern int ath_dfs_process_radar_event(struct ath_softc *sc, + struct ieee80211_channel *chan); +extern int ath_dfs_tasklet_needed(struct ath_softc *sc, + struct ieee80211_channel *chan); +extern int ath_ioctl_phyerr(struct ath_softc *sc, struct ath_diag *ad); +extern int ath_dfs_get_thresholds(struct ath_softc *sc, + HAL_PHYERR_PARAM *param); + +#endif /* __IF_ATHDFS_H__ */ diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_athioctl.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_athioctl.h index 35947a098d..4b50d0d826 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_athioctl.h +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_athioctl.h @@ -79,7 +79,7 @@ struct ath_stats { u_int32_t ast_rx_badcrypt;/* rx failed 'cuz decryption */ u_int32_t ast_rx_badmic; /* rx failed 'cuz MIC failure */ u_int32_t ast_rx_phyerr; /* rx failed 'cuz of PHY err */ - u_int32_t ast_rx_phy[32]; /* rx PHY error per-code counts */ + u_int32_t ast_rx_phy[64]; /* rx PHY error per-code counts */ u_int32_t ast_rx_tooshort;/* rx discarded 'cuz frame too short */ u_int32_t ast_rx_toobig; /* rx discarded 'cuz frame too large */ u_int32_t ast_rx_packets; /* packet recv on the interface */ @@ -118,7 +118,23 @@ struct ath_stats { u_int32_t ast_tdma_ack; /* TDMA tx failed 'cuz ACK required */ u_int32_t ast_tx_raw_fail;/* raw tx failed 'cuz h/w down */ u_int32_t ast_tx_nofrag; /* tx dropped 'cuz no ath frag buffer */ - u_int32_t ast_pad[14]; + u_int32_t ast_be_missed; /* missed beacons */ + u_int32_t ast_ani_cal; /* ANI calibrations performed */ + u_int32_t ast_rx_agg; /* number of aggregate frames RX'ed */ + u_int32_t ast_rx_halfgi; /* RX half-GI */ + u_int32_t ast_rx_2040; /* RX 40mhz frame */ + u_int32_t ast_rx_pre_crc_err; /* RX pre-delimiter CRC error */ + u_int32_t ast_rx_post_crc_err; /* RX post-delimiter CRC error */ + u_int32_t ast_rx_decrypt_busy_err; /* RX decrypt engine busy error */ + u_int32_t ast_rx_hi_rx_chain; + u_int32_t ast_tx_htprotect; /* HT tx frames with protection */ + u_int32_t ast_rx_hitqueueend; /* RX hit descr queue end */ + u_int32_t ast_tx_timeout; /* Global TX timeout */ + u_int32_t ast_tx_cst; /* Carrier sense timeout */ + u_int32_t ast_tx_xtxop; /* tx exceeded TXOP */ + u_int32_t ast_tx_timerexpired; /* tx exceeded TX_TIMER */ + u_int32_t ast_tx_desccfgerr; /* tx desc cfg error */ + u_int32_t ast_pad[13]; }; #define SIOCGATHSTATS _IOWR('i', 137, struct ifreq) @@ -138,6 +154,7 @@ struct ath_diag { }; #define SIOCGATHDIAG _IOWR('i', 138, struct ath_diag) +#define SIOCGATHPHYERR _IOWR('i', 140, struct ath_diag) /* * Radio capture format. @@ -189,4 +206,34 @@ struct ath_tx_radiotap_header { int8_t wt_chan_maxpow; } __packed; +/* + * DFS ioctl commands + */ + +#define DFS_SET_THRESH 2 +#define DFS_GET_THRESH 3 +#define DFS_RADARDETECTS 6 + +/* + * DFS ioctl parameter types + */ +#define DFS_PARAM_FIRPWR 1 +#define DFS_PARAM_RRSSI 2 +#define DFS_PARAM_HEIGHT 3 +#define DFS_PARAM_PRSSI 4 +#define DFS_PARAM_INBAND 5 +#define DFS_PARAM_NOL 6 /* XXX not used in FreeBSD */ +#define DFS_PARAM_RELSTEP_EN 7 +#define DFS_PARAM_RELSTEP 8 +#define DFS_PARAM_RELPWR_EN 9 +#define DFS_PARAM_RELPWR 10 +#define DFS_PARAM_MAXLEN 11 +#define DFS_PARAM_USEFIR128 12 +#define DFS_PARAM_BLOCKRADAR 13 +#define DFS_PARAM_MAXRSSI_EN 14 + +/* FreeBSD-specific start at 32 */ +#define DFS_PARAM_ENABLE 32 +#define DFS_PARAM_EN_EXTCH 33 + #endif /* _DEV_ATH_ATHIOCTL_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_athrate.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_athrate.h index 189db10d85..55b99a2d9a 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_athrate.h +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_athrate.h @@ -101,6 +101,12 @@ void ath_rate_newassoc(struct ath_softc *, struct ath_node *, /* * Transmit handling. */ +/* + * Return the four TX rate index and try counts for the current data packet. + */ +void ath_rate_getxtxrates(struct ath_softc *sc, struct ath_node *an, + uint8_t rix0, uint8_t *rix, uint8_t *try); + /* * Return the transmit info for a data packet. If multi-rate state * is to be setup then try0 should contain a value other than ATH_TXMATRY diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_athvar.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_athvar.h index 171b6b7a46..b8153ef05f 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_athvar.h +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_athvar.h @@ -43,6 +43,14 @@ #define ATH_TIMEOUT 1000 +/* + * 802.11n requires more TX and RX buffers to do AMPDU. + */ +#ifdef ATH_ENABLE_11N +#define ATH_TXBUF 512 +#define ATH_RXBUF 512 +#endif + #ifndef ATH_RXBUF #define ATH_RXBUF 40 /* number of RX buffers */ #endif @@ -245,7 +253,10 @@ struct ath_softc { sc_resume_up: 1,/* on resume, start all vaps */ sc_tdma : 1,/* TDMA in use */ sc_setcca : 1,/* set/clr CCA with TDMA */ - sc_resetcal : 1;/* reset cal state next trip */ + sc_resetcal : 1,/* reset cal state next trip */ + sc_rxslink : 1,/* do self-linked final descriptor */ + sc_kickpcu : 1,/* kick PCU RX on next RX proc */ + sc_rxtsf32 : 1;/* RX dec TSF is 32 bits */ uint32_t sc_eerd; /* regdomain from EEPROM */ uint32_t sc_eecc; /* country code from EEPROM */ /* rate tables */ @@ -306,7 +317,7 @@ struct ath_softc { u_int sc_txqsetup; /* h/w queues setup */ u_int sc_txintrperiod;/* tx interrupt batching */ struct ath_txq sc_txq[HAL_NUM_TX_QUEUES]; - struct ath_txq *sc_ac2q[5]; /* WME AC -> h/w q map */ + struct ath_txq *sc_ac2q[5]; /* WME AC -> h/w q map */ struct task sc_txtask; /* tx int processing */ int sc_wd_timer; /* count down for wd timer */ struct callout sc_wd_ch; /* tx watchdog timer */ @@ -333,6 +344,9 @@ struct ath_softc { struct callout sc_cal_ch; /* callout handle for cals */ int sc_lastlongcal; /* last long cal completed */ int sc_lastcalreset;/* last cal reset done */ + int sc_lastani; /* last ANI poll */ + int sc_lastshortcal; /* last short calibration */ + HAL_BOOL sc_doresetcal; /* Yes, we're doing a reset cal atm */ HAL_NODE_STATS sc_halstats; /* station-mode rssi stats */ u_int sc_tdmadbaprep; /* TDMA DBA prep time */ u_int sc_tdmaswbaprep;/* TDMA SWBA prep time */ @@ -342,6 +356,14 @@ struct ath_softc { u_int sc_tdmaslotlen; /* TDMA slot length (usec) */ u_int32_t sc_avgtsfdeltap;/* TDMA slot adjust (+) */ u_int32_t sc_avgtsfdeltam;/* TDMA slot adjust (-) */ + uint16_t *sc_eepromdata; /* Local eeprom data, if AR9100 */ + int sc_txchainmask; /* currently configured TX chainmask */ + int sc_rxchainmask; /* currently configured RX chainmask */ + + /* DFS related state */ + void *sc_dfs; /* Used by an optional DFS module */ + int sc_dodfs; /* Whether to enable DFS rx filter bits */ + struct task sc_dfstask; /* DFS processing task */ #if defined(__HAIKU__) HAL_INT sc_intr_status; @@ -465,6 +487,8 @@ void ath_intr(void *); ((*(_ah)->ah_setBeaconTimers)((_ah), (_bt))) #define ath_hal_beacontimers(_ah, _bs) \ ((*(_ah)->ah_setStationBeaconTimers)((_ah), (_bs))) +#define ath_hal_getnexttbtt(_ah) \ + ((*(_ah)->ah_getNextTBTT)((_ah))) #define ath_hal_setassocid(_ah, _bss, _associd) \ ((*(_ah)->ah_writeAssocid)((_ah), (_bss), (_associd))) #define ath_hal_phydisable(_ah) \ @@ -506,6 +530,8 @@ void ath_intr(void *); ((*(_ah)->ah_setDefAntenna)((_ah), (_ant))) #define ath_hal_rxmonitor(_ah, _arg, _chan) \ ((*(_ah)->ah_rxMonitor)((_ah), (_arg), (_chan))) +#define ath_hal_ani_poll(_ah, _chan) \ + ((*(_ah)->ah_aniPoll)((_ah), (_chan))) #define ath_hal_mibevent(_ah, _stats) \ ((*(_ah)->ah_procMibEvent)((_ah), (_stats))) #define ath_hal_setslottime(_ah, _us) \ @@ -621,13 +647,25 @@ void ath_intr(void *); #define ath_hal_settpcts(_ah, _tpcts) \ ath_hal_setcapability(_ah, HAL_CAP_TPC_CTS, 0, _tpcts, NULL) #define ath_hal_hasintmit(_ah) \ - (ath_hal_getcapability(_ah, HAL_CAP_INTMIT, 0, NULL) == HAL_OK) + (ath_hal_getcapability(_ah, HAL_CAP_INTMIT, HAL_CAP_INTMIT_PRESENT, NULL) == HAL_OK) #define ath_hal_getintmit(_ah) \ - (ath_hal_getcapability(_ah, HAL_CAP_INTMIT, 1, NULL) == HAL_OK) + (ath_hal_getcapability(_ah, HAL_CAP_INTMIT, HAL_CAP_INTMIT_ENABLE, NULL) == HAL_OK) #define ath_hal_setintmit(_ah, _v) \ - ath_hal_setcapability(_ah, HAL_CAP_INTMIT, 1, _v, NULL) + ath_hal_setcapability(_ah, HAL_CAP_INTMIT, HAL_CAP_INTMIT_ENABLE, _v, NULL) #define ath_hal_getchannoise(_ah, _c) \ ((*(_ah)->ah_getChanNoise)((_ah), (_c))) +#define ath_hal_getrxchainmask(_ah, _prxchainmask) \ + (ath_hal_getcapability(_ah, HAL_CAP_RX_CHAINMASK, 0, _prxchainmask)) +#define ath_hal_gettxchainmask(_ah, _ptxchainmask) \ + (ath_hal_getcapability(_ah, HAL_CAP_TX_CHAINMASK, 0, _ptxchainmask)) +#define ath_hal_split4ktrans(_ah) \ + (ath_hal_getcapability(_ah, HAL_CAP_SPLIT_4KB_TRANS, 0, NULL) == HAL_OK) +#define ath_hal_self_linked_final_rxdesc(_ah) \ + (ath_hal_getcapability(_ah, HAL_CAP_RXDESC_SELFLINK, 0, NULL) == HAL_OK) +#define ath_hal_gtxto_supported(_ah) \ + (ath_hal_getcapability(_ah, HAL_CAP_GTXTO, 0, NULL) == HAL_OK) +#define ath_hal_has_long_rxdesc_tsf(_ah) \ + (ath_hal_getcapability(_ah, HAL_CAP_LONG_RXDESC_TSF, 0, NULL) == HAL_OK) #define ath_hal_setuprxdesc(_ah, _ds, _size, _intreq) \ ((*(_ah)->ah_setupRxDesc)((_ah), (_ds), (_size), (_intreq))) @@ -649,6 +687,42 @@ void ath_intr(void *); ((*(_ah)->ah_procTxDesc)((_ah), (_ds), (_ts))) #define ath_hal_gettxintrtxqs(_ah, _txqs) \ ((*(_ah)->ah_getTxIntrQueue)((_ah), (_txqs))) +#define ath_hal_gettxcompletionrates(_ah, _ds, _rates, _tries) \ + ((*(_ah)->ah_getTxCompletionRates)((_ah), (_ds), (_rates), (_tries))) + +#define ath_hal_chaintxdesc(_ah, _ds, _pktlen, _hdrlen, _type, _keyix, \ + _cipher, _delims, _seglen, _first, _last) \ + ((*(_ah)->ah_chainTxDesc((_ah), (_ds), (_pktlen), (_hdrlen), \ + (_type), (_keyix), (_cipher), (_delims), (_seglen), \ + (_first), (_last)))) +#define ath_hal_setupfirsttxdesc(_ah, _ds, _aggrlen, _flags, _txpower, \ + _txr0, _txtr0, _antm, _rcr, _rcd) \ + ((*(_ah)->ah_setupFirstTxDesc)((_ah), (_ds), (_aggrlen), (_flags), \ + (_txpower), (_txr0), (_txtr0), (_antm), (_rcr), (_rcd))) +#define ath_hal_setuplasttxdesc(_ah, _ds, _ds0) \ + ((*(_ah)->ah_setupLastTxDesc)((_ah), (_ds), (_ds0))) +#define ath_hal_set11nratescenario(_ah, _ds, _dur, _rt, _series, _ns, _flags) \ + ((*(_ah)->ah_set11nRateScenario)((_ah), (_ds), (_dur), (_rt), \ + (_series), (_ns), (_flags))) +#define ath_hal_set11naggrmiddle(_ah, _ds, _num) \ + ((*(_ah)->ah_set11nAggrMiddle((_ah), (_ds), (_num)))) +#define ath_hal_set11nburstduration(_ah, _ds, _dur) \ + ((*(_ah)->ah_set11nBurstDuration)((_ah), (_ds), (_dur))) + +/* + * This is badly-named; you need to set the correct parameters + * to begin to receive useful radar events; and even then + * it doesn't "enable" DFS. See the ath_dfs/null/ module for + * more information. + */ +#define ath_hal_enabledfs(_ah, _param) \ + ((*(_ah)->ah_enableDfs)((_ah), (_param))) +#define ath_hal_getdfsthresh(_ah, _param) \ + ((*(_ah)->ah_getDfsThresh)((_ah), (_param))) +#define ath_hal_procradarevent(_ah, _rxs, _fulltsf, _buf, _event) \ + ((*(_ah)->ah_procRadarEvent)((_ah), (_rxs), (_fulltsf), (_buf), (_event))) +#define ath_hal_is_fast_clock_enabled(_ah) \ + ((*(_ah)->ah_isFastClockEnabled)((_ah))) #define ath_hal_gpioCfgOutput(_ah, _gpio, _type) \ ((*(_ah)->ah_gpioCfgOutput)((_ah), (_gpio), (_type))) diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/glue.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/glue.c index e7496b957f..0b1eaf75e7 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/glue.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/glue.c @@ -15,7 +15,7 @@ #include -HAIKU_FBSD_WLAN_DRIVER_GLUE(atheroswifi, ath, pci) +HAIKU_FBSD_WLAN_DRIVER_GLUE(atheroswifi, ath_pci, pci) NO_HAIKU_FBSD_MII_DRIVER(); HAIKU_DRIVER_REQUIREMENTS(FBSD_TASKQUEUES | FBSD_WLAN);